forked from OpenWF/SpaceNinjaServer
Compare commits
13 Commits
045d933458
...
a27f1c5e01
Author | SHA1 | Date | |
---|---|---|---|
a27f1c5e01 | |||
93afc2645c | |||
b5b088249c | |||
e6ec144f1f | |||
3d82fee99e | |||
39f0f7de9a | |||
f672f05db9 | |||
4d9e6a35ab | |||
c29bf6aab5 | |||
bc07978846 | |||
2efe0df2f2 | |||
38b255d41a | |||
421164986a |
@ -23,7 +23,7 @@
|
|||||||
"@typescript-eslint/no-explicit-any": "warn",
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
"@typescript-eslint/no-loss-of-precision": "warn",
|
"@typescript-eslint/no-loss-of-precision": "warn",
|
||||||
"@typescript-eslint/no-unnecessary-condition": "warn",
|
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||||
"no-case-declarations": "warn",
|
"no-case-declarations": "error",
|
||||||
"prettier/prettier": "error",
|
"prettier/prettier": "error",
|
||||||
"@typescript-eslint/semi": "error",
|
"@typescript-eslint/semi": "error",
|
||||||
"no-mixed-spaces-and-tabs": "error",
|
"no-mixed-spaces-and-tabs": "error",
|
||||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.4",
|
"mongoose": "^8.9.4",
|
||||||
"warframe-public-export-plus": "^0.5.35",
|
"warframe-public-export-plus": "^0.5.36",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
@ -4093,9 +4093,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.35",
|
"version": "0.5.36",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.35.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.36.tgz",
|
||||||
"integrity": "sha512-YLQP1n5sOV+PS5hfC4Kuoapa9gsqOy5Qy/E4EYfRV/xJBruFl3tPhbdbgFn3HhL2OBrgRJ8yzT5bjIvaHKhOCw=="
|
"integrity": "sha512-FYZECqBSnynl6lQvcQyEqpnGW9l84wzusekhtwKjvg3280CYdn7g5x0Q9tOMhj1jpc/1tuY+akHtHa94sPtqKw=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.4",
|
"mongoose": "^8.9.4",
|
||||||
"warframe-public-export-plus": "^0.5.35",
|
"warframe-public-export-plus": "^0.5.36",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
@ -1,77 +1,31 @@
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
import { crackRelic } from "@/src/helpers/relicHelper";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
import { IVoidTearParticipantInfo } from "@/src/types/requestTypes";
|
||||||
import { getRandomWeightedReward2 } from "@/src/services/rngService";
|
|
||||||
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
|
||||||
import { logger } from "@/src/utils/logger";
|
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
|
|
||||||
|
|
||||||
export const getVoidProjectionRewardsController: RequestHandler = async (req, res) => {
|
export const getVoidProjectionRewardsController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const data = getJSONfromString<IVoidProjectionRewardRequest>(String(req.body));
|
const data = getJSONfromString<IVoidProjectionRewardRequest>(String(req.body));
|
||||||
|
|
||||||
|
if (data.ParticipantInfo.QualifiesForReward && !data.ParticipantInfo.HaveRewardResponse) {
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
await crackRelic(inventory, data.ParticipantInfo);
|
||||||
|
await inventory.save();
|
||||||
|
}
|
||||||
|
|
||||||
const response: IVoidProjectionRewardResponse = {
|
const response: IVoidProjectionRewardResponse = {
|
||||||
CurrentWave: data.CurrentWave,
|
CurrentWave: data.CurrentWave,
|
||||||
ParticipantInfo: data.ParticipantInfo,
|
ParticipantInfo: data.ParticipantInfo,
|
||||||
DifficultyTier: data.DifficultyTier
|
DifficultyTier: data.DifficultyTier
|
||||||
};
|
};
|
||||||
if (data.ParticipantInfo.QualifiesForReward) {
|
|
||||||
const relic = ExportRelics[data.ParticipantInfo.VoidProjection];
|
|
||||||
const weights = refinementToWeights[relic.quality];
|
|
||||||
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
|
|
||||||
const reward = getRandomWeightedReward2(
|
|
||||||
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
|
|
||||||
weights
|
|
||||||
)!;
|
|
||||||
logger.debug(`relic rolled`, reward);
|
|
||||||
response.ParticipantInfo.Reward = reward.type;
|
|
||||||
|
|
||||||
const inventory = await getInventory(accountId);
|
|
||||||
// Remove relic
|
|
||||||
addMiscItems(inventory, [
|
|
||||||
{
|
|
||||||
ItemType: data.ParticipantInfo.VoidProjection,
|
|
||||||
ItemCount: -1
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
// Give reward
|
|
||||||
await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount);
|
|
||||||
await inventory.save();
|
|
||||||
}
|
|
||||||
res.json(response);
|
res.json(response);
|
||||||
};
|
};
|
||||||
|
|
||||||
const refinementToWeights = {
|
|
||||||
VPQ_BRONZE: {
|
|
||||||
COMMON: 0.76,
|
|
||||||
UNCOMMON: 0.22,
|
|
||||||
RARE: 0.02,
|
|
||||||
LEGENDARY: 0
|
|
||||||
},
|
|
||||||
VPQ_SILVER: {
|
|
||||||
COMMON: 0.7,
|
|
||||||
UNCOMMON: 0.26,
|
|
||||||
RARE: 0.04,
|
|
||||||
LEGENDARY: 0
|
|
||||||
},
|
|
||||||
VPQ_GOLD: {
|
|
||||||
COMMON: 0.6,
|
|
||||||
UNCOMMON: 0.34,
|
|
||||||
RARE: 0.06,
|
|
||||||
LEGENDARY: 0
|
|
||||||
},
|
|
||||||
VPQ_PLATINUM: {
|
|
||||||
COMMON: 0.5,
|
|
||||||
UNCOMMON: 0.4,
|
|
||||||
RARE: 0.1,
|
|
||||||
LEGENDARY: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interface IVoidProjectionRewardRequest {
|
interface IVoidProjectionRewardRequest {
|
||||||
CurrentWave: number;
|
CurrentWave: number;
|
||||||
ParticipantInfo: IParticipantInfo;
|
ParticipantInfo: IVoidTearParticipantInfo;
|
||||||
VoidTier: string;
|
VoidTier: string;
|
||||||
DifficultyTier: number;
|
DifficultyTier: number;
|
||||||
VoidProjectionRemovalHash: string;
|
VoidProjectionRemovalHash: string;
|
||||||
@ -79,20 +33,6 @@ interface IVoidProjectionRewardRequest {
|
|||||||
|
|
||||||
interface IVoidProjectionRewardResponse {
|
interface IVoidProjectionRewardResponse {
|
||||||
CurrentWave: number;
|
CurrentWave: number;
|
||||||
ParticipantInfo: IParticipantInfo;
|
ParticipantInfo: IVoidTearParticipantInfo;
|
||||||
DifficultyTier: number;
|
DifficultyTier: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IParticipantInfo {
|
|
||||||
AccountId: string;
|
|
||||||
Name: string;
|
|
||||||
ChosenRewardOwner: string;
|
|
||||||
MissionHash: string;
|
|
||||||
VoidProjection: string;
|
|
||||||
Reward: string;
|
|
||||||
QualifiesForReward: boolean;
|
|
||||||
HaveRewardResponse: boolean;
|
|
||||||
RewardsMultiplier: number;
|
|
||||||
RewardProjection: string;
|
|
||||||
HardModeReward: ITypeCount;
|
|
||||||
}
|
|
||||||
|
@ -39,7 +39,7 @@ const awakeningRewards = [
|
|||||||
export const addStartingGear = async (
|
export const addStartingGear = async (
|
||||||
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
||||||
startingGear: TPartialStartingGear | undefined = undefined
|
startingGear: TPartialStartingGear | undefined = undefined
|
||||||
) => {
|
): Promise<IInventoryChanges> => {
|
||||||
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
|
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
|
||||||
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
|
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
|
||||||
Pistols: [{ ItemType: "/Lotus/Weapons/Tenno/Pistol/Pistol" }],
|
Pistols: [{ ItemType: "/Lotus/Weapons/Tenno/Pistol/Pistol" }],
|
||||||
|
@ -249,7 +249,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
|||||||
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
||||||
inventory.Suits.pull(suit);
|
inventory.Suits.pull(suit);
|
||||||
const consumedSuit: IConsumedSuit = { s: suit.ItemType };
|
const consumedSuit: IConsumedSuit = { s: suit.ItemType };
|
||||||
if (suit.Configs && suit.Configs[0] && suit.Configs[0].pricol) {
|
if (suit.Configs[0] && suit.Configs[0].pricol) {
|
||||||
consumedSuit.c = suit.Configs[0].pricol;
|
consumedSuit.c = suit.Configs[0].pricol;
|
||||||
}
|
}
|
||||||
if ((inventory.InfestedFoundry!.XP ?? 0) < 73125_00) {
|
if ((inventory.InfestedFoundry!.XP ?? 0) < 73125_00) {
|
||||||
|
@ -2,7 +2,14 @@ import { RequestHandler } from "express";
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { getInventory, updateCurrency, addEquipment, addMiscItems } from "@/src/services/inventoryService";
|
import {
|
||||||
|
getInventory,
|
||||||
|
updateCurrency,
|
||||||
|
addEquipment,
|
||||||
|
addMiscItems,
|
||||||
|
applyDefaultUpgrades
|
||||||
|
} from "@/src/services/inventoryService";
|
||||||
|
import { ExportWeapons } from "warframe-public-export-plus";
|
||||||
|
|
||||||
const modularWeaponTypes: Record<string, TEquipmentKey> = {
|
const modularWeaponTypes: Record<string, TEquipmentKey> = {
|
||||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": "LongGuns",
|
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": "LongGuns",
|
||||||
@ -36,8 +43,11 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
|||||||
const category = modularWeaponTypes[data.WeaponType];
|
const category = modularWeaponTypes[data.WeaponType];
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
const configs = applyDefaultUpgrades(inventory, ExportWeapons[data.Parts[0]]?.defaultUpgrades);
|
||||||
|
|
||||||
// Give weapon
|
// Give weapon
|
||||||
const weapon = addEquipment(inventory, category, data.WeaponType, data.Parts);
|
const inventoryChanges = addEquipment(inventory, category, data.WeaponType, data.Parts, {}, { Configs: configs });
|
||||||
|
|
||||||
// Remove credits & parts
|
// Remove credits & parts
|
||||||
const miscItemChanges = [];
|
const miscItemChanges = [];
|
||||||
@ -58,8 +68,8 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
|||||||
// Tell client what we did
|
// Tell client what we did
|
||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: {
|
InventoryChanges: {
|
||||||
|
...inventoryChanges,
|
||||||
...currencyChanges,
|
...currencyChanges,
|
||||||
[category]: [weapon],
|
|
||||||
MiscItems: miscItemChanges
|
MiscItems: miscItemChanges
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -50,6 +50,7 @@ const qualityKeywordToNumber: Record<VoidProjectionQuality, number> = {
|
|||||||
// e.g. "/Lotus/Types/Game/Projections/T2VoidProjectionProteaPrimeDBronze" -> ["Lith", "W5", "VPQ_BRONZE"]
|
// e.g. "/Lotus/Types/Game/Projections/T2VoidProjectionProteaPrimeDBronze" -> ["Lith", "W5", "VPQ_BRONZE"]
|
||||||
const parseProjection = (typeName: string): [string, string, VoidProjectionQuality] => {
|
const parseProjection = (typeName: string): [string, string, VoidProjectionQuality] => {
|
||||||
const relic: IRelic | undefined = ExportRelics[typeName];
|
const relic: IRelic | undefined = ExportRelics[typeName];
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!relic) {
|
if (!relic) {
|
||||||
throw new Error(`Unknown projection ${typeName}`);
|
throw new Error(`Unknown projection ${typeName}`);
|
||||||
}
|
}
|
||||||
|
@ -39,18 +39,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
res.miscitems = [];
|
res.miscitems = [];
|
||||||
res.Syndicates = [];
|
res.Syndicates = [];
|
||||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||||
if (
|
|
||||||
item.productCategory == "Suits" ||
|
|
||||||
item.productCategory == "SpaceSuits" ||
|
|
||||||
item.productCategory == "MechSuits"
|
|
||||||
) {
|
|
||||||
res[item.productCategory].push({
|
res[item.productCategory].push({
|
||||||
uniqueName,
|
uniqueName,
|
||||||
name: getString(item.name, lang),
|
name: getString(item.name, lang),
|
||||||
exalted: item.exalted
|
exalted: item.exalted
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
|
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
|
||||||
if (item.productCategory == "Sentinels") {
|
if (item.productCategory == "Sentinels") {
|
||||||
res[item.productCategory].push({
|
res[item.productCategory].push({
|
||||||
|
60
src/helpers/relicHelper.ts
Normal file
60
src/helpers/relicHelper.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
|
import { IVoidTearParticipantInfo } from "@/src/types/requestTypes";
|
||||||
|
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
|
||||||
|
import { getRandomWeightedReward2 } from "@/src/services/rngService";
|
||||||
|
import { logger } from "@/src/utils/logger";
|
||||||
|
import { addMiscItems } from "@/src/services/inventoryService";
|
||||||
|
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||||
|
|
||||||
|
export const crackRelic = async (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
participant: IVoidTearParticipantInfo
|
||||||
|
): Promise<void> => {
|
||||||
|
const relic = ExportRelics[participant.VoidProjection];
|
||||||
|
const weights = refinementToWeights[relic.quality];
|
||||||
|
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
|
||||||
|
const reward = getRandomWeightedReward2(
|
||||||
|
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
|
||||||
|
weights
|
||||||
|
)!;
|
||||||
|
logger.debug(`relic rolled`, reward);
|
||||||
|
participant.Reward = reward.type;
|
||||||
|
|
||||||
|
// Remove relic
|
||||||
|
addMiscItems(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: participant.VoidProjection,
|
||||||
|
ItemCount: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Give reward
|
||||||
|
await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refinementToWeights = {
|
||||||
|
VPQ_BRONZE: {
|
||||||
|
COMMON: 0.76,
|
||||||
|
UNCOMMON: 0.22,
|
||||||
|
RARE: 0.02,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_SILVER: {
|
||||||
|
COMMON: 0.7,
|
||||||
|
UNCOMMON: 0.26,
|
||||||
|
RARE: 0.04,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_GOLD: {
|
||||||
|
COMMON: 0.6,
|
||||||
|
UNCOMMON: 0.34,
|
||||||
|
RARE: 0.06,
|
||||||
|
LEGENDARY: 0
|
||||||
|
},
|
||||||
|
VPQ_PLATINUM: {
|
||||||
|
COMMON: 0.5,
|
||||||
|
UNCOMMON: 0.4,
|
||||||
|
RARE: 0.1,
|
||||||
|
LEGENDARY: 0
|
||||||
|
}
|
||||||
|
};
|
@ -25,8 +25,10 @@ mongoose
|
|||||||
cert: fs.readFileSync("static/certs/cert.pem")
|
cert: fs.readFileSync("static/certs/cert.pem")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
http.createServer(app).listen(httpPort, () => {
|
http.createServer(app).listen(httpPort, () => {
|
||||||
logger.info("HTTP server started on port " + httpPort);
|
logger.info("HTTP server started on port " + httpPort);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
https.createServer(options, app).listen(httpsPort, () => {
|
https.createServer(options, app).listen(httpsPort, () => {
|
||||||
logger.info("HTTPS server started on port " + httpsPort);
|
logger.info("HTTPS server started on port " + httpsPort);
|
||||||
|
|
||||||
|
@ -808,7 +808,7 @@ detailsSchema.set("toJSON", {
|
|||||||
const EquipmentSchema = new Schema<IEquipmentDatabase>(
|
const EquipmentSchema = new Schema<IEquipmentDatabase>(
|
||||||
{
|
{
|
||||||
ItemType: String,
|
ItemType: String,
|
||||||
Configs: [ItemConfigSchema],
|
Configs: { type: [ItemConfigSchema], default: [] },
|
||||||
UpgradeVer: { type: Number, default: 101 },
|
UpgradeVer: { type: Number, default: 101 },
|
||||||
XP: { type: Number, default: 0 },
|
XP: { type: Number, default: 0 },
|
||||||
Features: Number,
|
Features: Number,
|
||||||
@ -1303,7 +1303,7 @@ inventorySchema.set("toJSON", {
|
|||||||
if (inventoryDatabase.GuildId) {
|
if (inventoryDatabase.GuildId) {
|
||||||
inventoryResponse.GuildId = toOid(inventoryDatabase.GuildId);
|
inventoryResponse.GuildId = toOid(inventoryDatabase.GuildId);
|
||||||
}
|
}
|
||||||
if (inventoryResponse.BlessingCooldown) {
|
if (inventoryDatabase.BlessingCooldown) {
|
||||||
inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown);
|
inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ const convertEquipment = (client: IEquipmentClient): IEquipmentDatabase => {
|
|||||||
UpgradesExpiry: convertOptionalDate(client.UpgradesExpiry),
|
UpgradesExpiry: convertOptionalDate(client.UpgradesExpiry),
|
||||||
CrewMembers: client.CrewMembers ? convertCrewShipMembers(client.CrewMembers) : undefined,
|
CrewMembers: client.CrewMembers ? convertCrewShipMembers(client.CrewMembers) : undefined,
|
||||||
Details: client.Details ? convertKubrowDetails(client.Details) : undefined,
|
Details: client.Details ? convertKubrowDetails(client.Details) : undefined,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
Configs: client.Configs
|
Configs: client.Configs
|
||||||
? client.Configs.map(obj =>
|
? client.Configs.map(obj =>
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
|
@ -27,7 +27,7 @@ export const deleteAllMessagesRead = async (accountId: string): Promise<void> =>
|
|||||||
await Inbox.deleteMany({ ownerId: accountId, r: true });
|
await Inbox.deleteMany({ ownerId: accountId, r: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createNewEventMessages = async (req: Request) => {
|
export const createNewEventMessages = async (req: Request): Promise<void> => {
|
||||||
const account = await getAccountForRequest(req);
|
const account = await getAccountForRequest(req);
|
||||||
const latestEventMessageDate = account.LatestEventMessageDate;
|
const latestEventMessageDate = account.LatestEventMessageDate;
|
||||||
|
|
||||||
|
@ -38,27 +38,30 @@ import { getExalted, getKeyChainItems } from "@/src/services/itemDataService";
|
|||||||
import { IEquipmentClient, IEquipmentDatabase, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
|
import { IEquipmentClient, IEquipmentDatabase, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
|
||||||
import {
|
import {
|
||||||
ExportArcanes,
|
ExportArcanes,
|
||||||
|
ExportBundles,
|
||||||
ExportCustoms,
|
ExportCustoms,
|
||||||
ExportDrones,
|
ExportDrones,
|
||||||
ExportFlavour,
|
ExportFlavour,
|
||||||
ExportFusionBundles,
|
ExportFusionBundles,
|
||||||
ExportGear,
|
ExportGear,
|
||||||
ExportKeys,
|
ExportKeys,
|
||||||
|
ExportMisc,
|
||||||
ExportRecipes,
|
ExportRecipes,
|
||||||
ExportResources,
|
ExportResources,
|
||||||
ExportSentinels,
|
ExportSentinels,
|
||||||
ExportSyndicates,
|
ExportSyndicates,
|
||||||
ExportUpgrades,
|
ExportUpgrades,
|
||||||
ExportWeapons,
|
ExportWeapons,
|
||||||
|
IDefaultUpgrade,
|
||||||
TStandingLimitBin
|
TStandingLimitBin
|
||||||
} from "warframe-public-export-plus";
|
} from "warframe-public-export-plus";
|
||||||
import { createShip } from "./shipService";
|
import { createShip } from "./shipService";
|
||||||
import { creditBundles } from "@/src/services/missionInventoryUpdateService";
|
|
||||||
import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||||
import { toOid } from "../helpers/inventoryHelpers";
|
import { toOid } from "../helpers/inventoryHelpers";
|
||||||
import { generateRewardSeed } from "@/src/controllers/api/getNewRewardSeedController";
|
import { generateRewardSeed } from "@/src/controllers/api/getNewRewardSeedController";
|
||||||
import { addStartingGear } from "@/src/controllers/api/giveStartingGearController";
|
import { addStartingGear } from "@/src/controllers/api/giveStartingGearController";
|
||||||
import { addQuestKey, completeQuest } from "@/src/services/questService";
|
import { addQuestKey, completeQuest } from "@/src/services/questService";
|
||||||
|
import { handleBundleAcqusition } from "./purchaseService";
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -157,6 +160,11 @@ export const addItem = async (
|
|||||||
typeName: string,
|
typeName: string,
|
||||||
quantity: number = 1
|
quantity: number = 1
|
||||||
): Promise<{ InventoryChanges: IInventoryChanges }> => {
|
): Promise<{ InventoryChanges: IInventoryChanges }> => {
|
||||||
|
// Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments.
|
||||||
|
if (typeName in ExportBundles) {
|
||||||
|
return { InventoryChanges: await handleBundleAcqusition(typeName, inventory, quantity) };
|
||||||
|
}
|
||||||
|
|
||||||
// Strict typing
|
// Strict typing
|
||||||
if (typeName in ExportRecipes) {
|
if (typeName in ExportRecipes) {
|
||||||
const recipeChanges = [
|
const recipeChanges = [
|
||||||
@ -203,6 +211,7 @@ export const addItem = async (
|
|||||||
const inventoryChanges = {
|
const inventoryChanges = {
|
||||||
...addCrewShip(inventory, typeName),
|
...addCrewShip(inventory, typeName),
|
||||||
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
|
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
...(!inventory.CrewShipHarnesses?.length
|
...(!inventory.CrewShipHarnesses?.length
|
||||||
? addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness")
|
? addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness")
|
||||||
: {})
|
: {})
|
||||||
@ -284,6 +293,11 @@ export const addItem = async (
|
|||||||
const weapon = ExportWeapons[typeName];
|
const weapon = ExportWeapons[typeName];
|
||||||
if (weapon.totalDamage != 0) {
|
if (weapon.totalDamage != 0) {
|
||||||
const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName);
|
const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName);
|
||||||
|
if (weapon.additionalItems) {
|
||||||
|
for (const item of weapon.additionalItems) {
|
||||||
|
combineInventoryChanges(inventoryChanges, await addItem(inventory, item, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
||||||
return {
|
return {
|
||||||
InventoryChanges: {
|
InventoryChanges: {
|
||||||
@ -307,8 +321,8 @@ export const addItem = async (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeName in creditBundles) {
|
if (typeName in ExportMisc.creditBundles) {
|
||||||
const creditsTotal = creditBundles[typeName] * quantity;
|
const creditsTotal = ExportMisc.creditBundles[typeName] * quantity;
|
||||||
inventory.RegularCredits += creditsTotal;
|
inventory.RegularCredits += creditsTotal;
|
||||||
return {
|
return {
|
||||||
InventoryChanges: {
|
InventoryChanges: {
|
||||||
@ -331,9 +345,8 @@ export const addItem = async (
|
|||||||
|
|
||||||
if (key.chainStages) {
|
if (key.chainStages) {
|
||||||
const key = addQuestKey(inventory, { ItemType: typeName });
|
const key = addQuestKey(inventory, { ItemType: typeName });
|
||||||
if (key) {
|
if (!key) return { InventoryChanges: {} };
|
||||||
return { InventoryChanges: { QuestKeys: [key] } };
|
return { InventoryChanges: { QuestKeys: [key] } };
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const key = { ItemType: typeName, ItemCount: quantity };
|
const key = { ItemType: typeName, ItemCount: quantity };
|
||||||
|
|
||||||
@ -405,6 +418,7 @@ export const addItem = async (
|
|||||||
switch (typeName.substr(1).split("/")[2]) {
|
switch (typeName.substr(1).split("/")[2]) {
|
||||||
case "Mods": // Legendary Core
|
case "Mods": // Legendary Core
|
||||||
case "CosmeticEnhancers": // Traumatic Peculiar
|
case "CosmeticEnhancers": // Traumatic Peculiar
|
||||||
|
{
|
||||||
const changes = [
|
const changes = [
|
||||||
{
|
{
|
||||||
ItemType: typeName,
|
ItemType: typeName,
|
||||||
@ -420,6 +434,8 @@ export const addItem = async (
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "Types":
|
case "Types":
|
||||||
switch (typeName.substr(1).split("/")[2]) {
|
switch (typeName.substr(1).split("/")[2]) {
|
||||||
case "Sentinels": {
|
case "Sentinels": {
|
||||||
@ -517,21 +533,15 @@ export const addItems = async (
|
|||||||
return inventoryChanges;
|
return inventoryChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
export const applyDefaultUpgrades = (
|
||||||
export const addSentinel = (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
sentinelName: string,
|
defaultUpgrades: IDefaultUpgrade[] | undefined
|
||||||
inventoryChanges: IInventoryChanges = {}
|
): IItemConfig[] => {
|
||||||
): IInventoryChanges => {
|
|
||||||
if (ExportSentinels[sentinelName]?.defaultWeapon) {
|
|
||||||
addSentinelWeapon(inventory, ExportSentinels[sentinelName].defaultWeapon, inventoryChanges);
|
|
||||||
}
|
|
||||||
|
|
||||||
const modsToGive: IRawUpgrade[] = [];
|
const modsToGive: IRawUpgrade[] = [];
|
||||||
const configs: IItemConfig[] = [];
|
const configs: IItemConfig[] = [];
|
||||||
if (ExportSentinels[sentinelName]?.defaultUpgrades) {
|
if (defaultUpgrades) {
|
||||||
const upgrades = [];
|
const upgrades = [];
|
||||||
for (const defaultUpgrade of ExportSentinels[sentinelName].defaultUpgrades) {
|
for (const defaultUpgrade of defaultUpgrades) {
|
||||||
modsToGive.push({ ItemType: defaultUpgrade.ItemType, ItemCount: 1 });
|
modsToGive.push({ ItemType: defaultUpgrade.ItemType, ItemCount: 1 });
|
||||||
if (defaultUpgrade.Slot != -1) {
|
if (defaultUpgrade.Slot != -1) {
|
||||||
upgrades[defaultUpgrade.Slot] = defaultUpgrade.ItemType;
|
upgrades[defaultUpgrade.Slot] = defaultUpgrade.ItemType;
|
||||||
@ -541,8 +551,24 @@ export const addSentinel = (
|
|||||||
configs.push({ Upgrades: upgrades });
|
configs.push({ Upgrades: upgrades });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addMods(inventory, modsToGive);
|
addMods(inventory, modsToGive);
|
||||||
|
return configs;
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
||||||
|
export const addSentinel = (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
sentinelName: string,
|
||||||
|
inventoryChanges: IInventoryChanges = {}
|
||||||
|
): IInventoryChanges => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
if (ExportSentinels[sentinelName]?.defaultWeapon) {
|
||||||
|
addSentinelWeapon(inventory, ExportSentinels[sentinelName].defaultWeapon, inventoryChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
const configs: IItemConfig[] = applyDefaultUpgrades(inventory, ExportSentinels[sentinelName]?.defaultUpgrades);
|
||||||
|
|
||||||
const sentinelIndex = inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0 }) - 1;
|
const sentinelIndex = inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0 }) - 1;
|
||||||
inventoryChanges.Sentinels ??= [];
|
inventoryChanges.Sentinels ??= [];
|
||||||
inventoryChanges.Sentinels.push(inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>());
|
inventoryChanges.Sentinels.push(inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>());
|
||||||
|
@ -33,6 +33,7 @@ import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
|||||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import { handleStoreItemAcquisition } from "./purchaseService";
|
import { handleStoreItemAcquisition } from "./purchaseService";
|
||||||
import { IMissionReward } from "../types/missionTypes";
|
import { IMissionReward } from "../types/missionTypes";
|
||||||
|
import { crackRelic } from "@/src/helpers/relicHelper";
|
||||||
|
|
||||||
const getRotations = (rotationCount: number): number[] => {
|
const getRotations = (rotationCount: number): number[] => {
|
||||||
if (rotationCount === 0) return [0];
|
if (rotationCount === 0) return [0];
|
||||||
@ -51,27 +52,6 @@ const getRandomRewardByChance = (pool: IReward[]): IRngResult | undefined => {
|
|||||||
return getRandomReward(pool as IRngResult[]);
|
return getRandomReward(pool as IRngResult[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const creditBundles: Record<string, number> = {
|
|
||||||
"/Lotus/Types/PickUps/Credits/1500Credits": 1500,
|
|
||||||
"/Lotus/Types/PickUps/Credits/2000Credits": 2000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/2500Credits": 2500,
|
|
||||||
"/Lotus/Types/PickUps/Credits/3000Credits": 3000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/4000Credits": 4000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/5000Credits": 5000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/7500Credits": 7500,
|
|
||||||
"/Lotus/Types/PickUps/Credits/10000Credits": 10000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/5000Hollars": 5000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/7500Hollars": 7500,
|
|
||||||
"/Lotus/Types/PickUps/Credits/10000Hollars": 10000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardOneHard": 105000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardTwoHard": 175000,
|
|
||||||
"/Lotus/Types/PickUps/Credits/CorpusArenaCreditRewards/CorpusArenaRewardThreeHard": 250000,
|
|
||||||
"/Lotus/Types/StoreItems/CreditBundles/Zariman/TableACreditsCommon": 15000,
|
|
||||||
"/Lotus/Types/StoreItems/CreditBundles/Zariman/TableACreditsUncommon": 30000,
|
|
||||||
"/Lotus/Types/StoreItems/CreditBundles/CreditBundleA": 50000,
|
|
||||||
"/Lotus/Types/StoreItems/CreditBundles/CreditBundleC": 175000
|
|
||||||
};
|
|
||||||
|
|
||||||
//type TMissionInventoryUpdateKeys = keyof IMissionInventoryUpdateRequest;
|
//type TMissionInventoryUpdateKeys = keyof IMissionInventoryUpdateRequest;
|
||||||
//const ignoredInventoryUpdateKeys = ["FpsAvg", "FpsMax", "FpsMin", "FpsSamples"] satisfies TMissionInventoryUpdateKeys[]; // for keys with no meaning for this server
|
//const ignoredInventoryUpdateKeys = ["FpsAvg", "FpsMax", "FpsMin", "FpsSamples"] satisfies TMissionInventoryUpdateKeys[]; // for keys with no meaning for this server
|
||||||
//type TignoredInventoryUpdateKeys = (typeof ignoredInventoryUpdateKeys)[number];
|
//type TignoredInventoryUpdateKeys = (typeof ignoredInventoryUpdateKeys)[number];
|
||||||
@ -80,7 +60,7 @@ export const creditBundles: Record<string, number> = {
|
|||||||
export const addMissionInventoryUpdates = (
|
export const addMissionInventoryUpdates = (
|
||||||
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
||||||
inventoryUpdates: IMissionInventoryUpdateRequest
|
inventoryUpdates: IMissionInventoryUpdateRequest
|
||||||
) => {
|
): Partial<IInventoryDatabase> | undefined => {
|
||||||
//TODO: type this properly
|
//TODO: type this properly
|
||||||
const inventoryChanges: Partial<IInventoryDatabase> = {};
|
const inventoryChanges: Partial<IInventoryDatabase> = {};
|
||||||
if (inventoryUpdates.MissionFailed === true) {
|
if (inventoryUpdates.MissionFailed === true) {
|
||||||
@ -208,14 +188,14 @@ export const addMissionInventoryUpdates = (
|
|||||||
inventory.CompletedSorties.push(value);
|
inventory.CompletedSorties.push(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SeasonChallengeCompletions":
|
case "SeasonChallengeCompletions": {
|
||||||
const processedCompletions = value.map(({ challenge, id }) => ({
|
const processedCompletions = value.map(({ challenge, id }) => ({
|
||||||
challenge: challenge.substring(challenge.lastIndexOf("/") + 1),
|
challenge: challenge.substring(challenge.lastIndexOf("/") + 1),
|
||||||
id
|
id
|
||||||
}));
|
}));
|
||||||
|
|
||||||
inventory.SeasonChallengeHistory.push(...processedCompletions);
|
inventory.SeasonChallengeHistory.push(...processedCompletions);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// Equipment XP updates
|
// Equipment XP updates
|
||||||
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
||||||
@ -242,7 +222,8 @@ export const addMissionRewards = async (
|
|||||||
RewardInfo: rewardInfo,
|
RewardInfo: rewardInfo,
|
||||||
LevelKeyName: levelKeyName,
|
LevelKeyName: levelKeyName,
|
||||||
Missions: missions,
|
Missions: missions,
|
||||||
RegularCredits: creditDrops
|
RegularCredits: creditDrops,
|
||||||
|
VoidTearParticipantsCurrWave: voidTearWave
|
||||||
}: IMissionInventoryUpdateRequest
|
}: IMissionInventoryUpdateRequest
|
||||||
) => {
|
) => {
|
||||||
if (!rewardInfo) {
|
if (!rewardInfo) {
|
||||||
@ -252,9 +233,7 @@ export const addMissionRewards = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check double reward merging
|
//TODO: check double reward merging
|
||||||
const MissionRewards = getRandomMissionDrops(rewardInfo).map(drop => {
|
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo);
|
||||||
return { StoreItem: drop.type, ItemCount: drop.itemCount };
|
|
||||||
});
|
|
||||||
logger.debug("random mission drops:", MissionRewards);
|
logger.debug("random mission drops:", MissionRewards);
|
||||||
const inventoryChanges: IInventoryChanges = {};
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
|
|
||||||
@ -282,12 +261,15 @@ export const addMissionRewards = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missions) {
|
if (
|
||||||
|
missions &&
|
||||||
|
missions.Tag != "" // #1013
|
||||||
|
) {
|
||||||
const node = getNode(missions.Tag);
|
const node = getNode(missions.Tag);
|
||||||
|
|
||||||
//node based credit rewards for mission completion
|
//node based credit rewards for mission completion
|
||||||
if (node.missionIndex !== 28) {
|
if (node.missionIndex !== 28) {
|
||||||
const levelCreditReward = getLevelCreditRewards(missions?.Tag);
|
const levelCreditReward = getLevelCreditRewards(missions.Tag);
|
||||||
missionCompletionCredits += levelCreditReward;
|
missionCompletionCredits += levelCreditReward;
|
||||||
inventory.RegularCredits += levelCreditReward;
|
inventory.RegularCredits += levelCreditReward;
|
||||||
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
||||||
@ -312,6 +294,15 @@ export const addMissionRewards = async (
|
|||||||
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
voidTearWave &&
|
||||||
|
voidTearWave.Participants[0].QualifiesForReward &&
|
||||||
|
!voidTearWave.Participants[0].HaveRewardResponse
|
||||||
|
) {
|
||||||
|
await crackRelic(inventory, voidTearWave.Participants[0]);
|
||||||
|
MissionRewards.push({ StoreItem: voidTearWave.Participants[0].Reward, ItemCount: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
return { inventoryChanges, MissionRewards, credits };
|
return { inventoryChanges, MissionRewards, credits };
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,7 +351,7 @@ export const addFixedLevelRewards = (
|
|||||||
if (rewards.items) {
|
if (rewards.items) {
|
||||||
for (const item of rewards.items) {
|
for (const item of rewards.items) {
|
||||||
MissionRewards.push({
|
MissionRewards.push({
|
||||||
StoreItem: `/Lotus/StoreItems${item.substring("Lotus/".length)}`,
|
StoreItem: item.includes(`/StoreItems/`) ? item : `/Lotus/StoreItems${item.substring("Lotus/".length)}`,
|
||||||
ItemCount: 1
|
ItemCount: 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -368,7 +359,9 @@ export const addFixedLevelRewards = (
|
|||||||
if (rewards.countedItems) {
|
if (rewards.countedItems) {
|
||||||
for (const item of rewards.countedItems) {
|
for (const item of rewards.countedItems) {
|
||||||
MissionRewards.push({
|
MissionRewards.push({
|
||||||
StoreItem: `/Lotus/StoreItems${item.ItemType.substring("Lotus/".length)}`,
|
StoreItem: item.ItemType.includes(`/StoreItems/`)
|
||||||
|
? item.ItemType
|
||||||
|
: `/Lotus/StoreItems${item.ItemType.substring("Lotus/".length)}`,
|
||||||
ItemCount: item.ItemCount
|
ItemCount: item.ItemCount
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -389,11 +382,14 @@ function getLevelCreditRewards(nodeName: string): number {
|
|||||||
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
function getRandomMissionDrops(RewardInfo: IRewardInfo): IMissionReward[] {
|
||||||
const drops: IRngResult[] = [];
|
const drops: IMissionReward[] = [];
|
||||||
if (RewardInfo.node in ExportRegions) {
|
if (RewardInfo.node in ExportRegions) {
|
||||||
const region = ExportRegions[RewardInfo.node];
|
const region = ExportRegions[RewardInfo.node];
|
||||||
const rewardManifests = region.rewardManifests ?? [];
|
const rewardManifests: string[] =
|
||||||
|
RewardInfo.periodicMissionTag == "EliteAlert" || RewardInfo.periodicMissionTag == "EliteAlertB"
|
||||||
|
? ["/Lotus/Types/Game/MissionDecks/EliteAlertMissionRewards/EliteAlertMissionRewards"]
|
||||||
|
: region.rewardManifests;
|
||||||
|
|
||||||
let rotations: number[] = [];
|
let rotations: number[] = [];
|
||||||
if (RewardInfo.VaultsCracked) {
|
if (RewardInfo.VaultsCracked) {
|
||||||
@ -412,7 +408,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
|||||||
const rotationRewards = table[rotation];
|
const rotationRewards = table[rotation];
|
||||||
const drop = getRandomRewardByChance(rotationRewards);
|
const drop = getRandomRewardByChance(rotationRewards);
|
||||||
if (drop) {
|
if (drop) {
|
||||||
drops.push(drop);
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -422,7 +418,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
|||||||
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
for (let rotation = 0; rotation != RewardInfo.EnemyCachesFound; ++rotation) {
|
||||||
const drop = getRandomRewardByChance(deck[rotation]);
|
const drop = getRandomRewardByChance(deck[rotation]);
|
||||||
if (drop) {
|
if (drop) {
|
||||||
drops.push(drop);
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount, FromEnemyCache: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,7 +437,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
|||||||
|
|
||||||
const drop = getRandomRewardByChance(deck[rotation]);
|
const drop = getRandomRewardByChance(deck[rotation]);
|
||||||
if (drop) {
|
if (drop) {
|
||||||
drops.push(drop);
|
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@ import { logger } from "@/src/utils/logger";
|
|||||||
import worldState from "@/static/fixed_responses/worldState/worldState.json";
|
import worldState from "@/static/fixed_responses/worldState/worldState.json";
|
||||||
import {
|
import {
|
||||||
ExportBoosterPacks,
|
ExportBoosterPacks,
|
||||||
|
ExportBoosters,
|
||||||
ExportBundles,
|
ExportBundles,
|
||||||
ExportGear,
|
ExportGear,
|
||||||
|
ExportMisc,
|
||||||
ExportResources,
|
ExportResources,
|
||||||
ExportSyndicates,
|
ExportSyndicates,
|
||||||
ExportVendors,
|
ExportVendors,
|
||||||
@ -25,7 +27,6 @@ import {
|
|||||||
} from "warframe-public-export-plus";
|
} from "warframe-public-export-plus";
|
||||||
import { config } from "./configService";
|
import { config } from "./configService";
|
||||||
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
||||||
import { creditBundles } from "./missionInventoryUpdateService";
|
|
||||||
|
|
||||||
export const getStoreItemCategory = (storeItem: string): string => {
|
export const getStoreItemCategory = (storeItem: string): string => {
|
||||||
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
|
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
|
||||||
@ -199,6 +200,31 @@ const handleItemPrices = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const handleBundleAcqusition = async (
|
||||||
|
storeItemName: string,
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
quantity: number = 1,
|
||||||
|
inventoryChanges: IInventoryChanges = {}
|
||||||
|
): Promise<IInventoryChanges> => {
|
||||||
|
const bundle = ExportBundles[storeItemName];
|
||||||
|
logger.debug("acquiring bundle", bundle);
|
||||||
|
for (const component of bundle.components) {
|
||||||
|
combineInventoryChanges(
|
||||||
|
inventoryChanges,
|
||||||
|
(
|
||||||
|
await handleStoreItemAcquisition(
|
||||||
|
component.typeName,
|
||||||
|
inventory,
|
||||||
|
component.purchaseQuantity * quantity,
|
||||||
|
component.durability,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
).InventoryChanges
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return inventoryChanges;
|
||||||
|
};
|
||||||
|
|
||||||
export const handleStoreItemAcquisition = async (
|
export const handleStoreItemAcquisition = async (
|
||||||
storeItemName: string,
|
storeItemName: string,
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
@ -211,22 +237,7 @@ export const handleStoreItemAcquisition = async (
|
|||||||
};
|
};
|
||||||
logger.debug(`handling acquision of ${storeItemName}`);
|
logger.debug(`handling acquision of ${storeItemName}`);
|
||||||
if (storeItemName in ExportBundles) {
|
if (storeItemName in ExportBundles) {
|
||||||
const bundle = ExportBundles[storeItemName];
|
await handleBundleAcqusition(storeItemName, inventory, quantity, purchaseResponse.InventoryChanges);
|
||||||
logger.debug("acquiring bundle", bundle);
|
|
||||||
for (const component of bundle.components) {
|
|
||||||
combineInventoryChanges(
|
|
||||||
purchaseResponse.InventoryChanges,
|
|
||||||
(
|
|
||||||
await handleStoreItemAcquisition(
|
|
||||||
component.typeName,
|
|
||||||
inventory,
|
|
||||||
component.purchaseQuantity * quantity,
|
|
||||||
component.durability,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
).InventoryChanges
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
const storeCategory = getStoreItemCategory(storeItemName);
|
const storeCategory = getStoreItemCategory(storeItemName);
|
||||||
const internalName = storeItemName.replace("/StoreItems", "");
|
const internalName = storeItemName.replace("/StoreItems", "");
|
||||||
@ -247,7 +258,7 @@ export const handleStoreItemAcquisition = async (
|
|||||||
purchaseResponse = await handleTypesPurchase(internalName, inventory, quantity);
|
purchaseResponse = await handleTypesPurchase(internalName, inventory, quantity);
|
||||||
break;
|
break;
|
||||||
case "Boosters":
|
case "Boosters":
|
||||||
purchaseResponse = handleBoostersPurchase(internalName, inventory, durability);
|
purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durability);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,8 +346,8 @@ const handleCreditBundlePurchase = async (
|
|||||||
typeName: string,
|
typeName: string,
|
||||||
inventory: TInventoryDatabaseDocument
|
inventory: TInventoryDatabaseDocument
|
||||||
): Promise<IPurchaseResponse> => {
|
): Promise<IPurchaseResponse> => {
|
||||||
if (typeName && typeName in creditBundles) {
|
if (typeName && typeName in ExportMisc.creditBundles) {
|
||||||
const creditsAmount = creditBundles[typeName];
|
const creditsAmount = ExportMisc.creditBundles[typeName];
|
||||||
|
|
||||||
inventory.RegularCredits += creditsAmount;
|
inventory.RegularCredits += creditsAmount;
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
@ -367,32 +378,18 @@ const handleTypesPurchase = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const boosterCollection = [
|
|
||||||
"/Lotus/Types/Boosters/ResourceAmountBooster",
|
|
||||||
"/Lotus/Types/Boosters/AffinityBooster",
|
|
||||||
"/Lotus/Types/Boosters/ResourceDropChanceBooster",
|
|
||||||
"/Lotus/Types/Boosters/CreditBooster"
|
|
||||||
];
|
|
||||||
|
|
||||||
const boosterDuration: Record<TRarity, number> = {
|
|
||||||
COMMON: 3 * 86400,
|
|
||||||
UNCOMMON: 7 * 86400,
|
|
||||||
RARE: 30 * 86400,
|
|
||||||
LEGENDARY: 90 * 86400
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBoostersPurchase = (
|
const handleBoostersPurchase = (
|
||||||
boosterStoreName: string,
|
boosterStoreName: string,
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
durability: TRarity
|
durability: TRarity
|
||||||
): { InventoryChanges: IInventoryChanges } => {
|
): { InventoryChanges: IInventoryChanges } => {
|
||||||
const ItemType = boosterStoreName.replace("StoreItem", "");
|
if (!(boosterStoreName in ExportBoosters)) {
|
||||||
if (!boosterCollection.find(x => x == ItemType)) {
|
logger.error(`unknown booster type: ${boosterStoreName}`);
|
||||||
logger.error(`unknown booster type: ${ItemType}`);
|
|
||||||
return { InventoryChanges: {} };
|
return { InventoryChanges: {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExpiryDate = boosterDuration[durability];
|
const ItemType = ExportBoosters[boosterStoreName].typeName;
|
||||||
|
const ExpiryDate = ExportMisc.boosterDurations[durability];
|
||||||
|
|
||||||
addBooster(ItemType, ExpiryDate, inventory);
|
addBooster(ItemType, ExpiryDate, inventory);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import { logger } from "@/src/utils/logger";
|
|||||||
import { HydratedDocument } from "mongoose";
|
import { HydratedDocument } from "mongoose";
|
||||||
import { ExportKeys } from "warframe-public-export-plus";
|
import { ExportKeys } from "warframe-public-export-plus";
|
||||||
import { addFixedLevelRewards } from "./missionInventoryUpdateService";
|
import { addFixedLevelRewards } from "./missionInventoryUpdateService";
|
||||||
|
import { IInventoryChanges } from "../types/purchaseTypes";
|
||||||
|
|
||||||
export interface IUpdateQuestRequest {
|
export interface IUpdateQuestRequest {
|
||||||
QuestKeys: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
QuestKeys: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
||||||
@ -64,6 +65,7 @@ export const updateQuestStage = (
|
|||||||
|
|
||||||
const questStage = quest.Progress[ChainStage];
|
const questStage = quest.Progress[ChainStage];
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!questStage) {
|
if (!questStage) {
|
||||||
const questStageIndex = quest.Progress.push(questStageUpdate) - 1;
|
const questStageIndex = quest.Progress.push(questStageUpdate) - 1;
|
||||||
if (questStageIndex !== ChainStage) {
|
if (questStageIndex !== ChainStage) {
|
||||||
@ -77,7 +79,7 @@ export const updateQuestStage = (
|
|||||||
|
|
||||||
export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQuestKeyDatabase) => {
|
export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQuestKeyDatabase) => {
|
||||||
if (inventory.QuestKeys.some(q => q.ItemType === questKey.ItemType)) {
|
if (inventory.QuestKeys.some(q => q.ItemType === questKey.ItemType)) {
|
||||||
logger.error(`quest key ${questKey.ItemType} already exists`);
|
logger.warn(`Quest key ${questKey.ItemType} already exists. It will not be added`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const index = inventory.QuestKeys.push(questKey);
|
const index = inventory.QuestKeys.push(questKey);
|
||||||
@ -86,6 +88,7 @@ export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQu
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const completeQuest = async (inventory: TInventoryDatabaseDocument, questKey: string) => {
|
export const completeQuest = async (inventory: TInventoryDatabaseDocument, questKey: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
const chainStages = ExportKeys[questKey]?.chainStages;
|
const chainStages = ExportKeys[questKey]?.chainStages;
|
||||||
|
|
||||||
if (!chainStages) {
|
if (!chainStages) {
|
||||||
@ -164,7 +167,10 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
|
|||||||
//TODO: handle quest completion items
|
//TODO: handle quest completion items
|
||||||
};
|
};
|
||||||
|
|
||||||
export const giveKeyChainItem = async (inventory: TInventoryDatabaseDocument, keyChainInfo: IKeyChainRequest) => {
|
export const giveKeyChainItem = async (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
keyChainInfo: IKeyChainRequest
|
||||||
|
): Promise<IInventoryChanges> => {
|
||||||
const inventoryChanges = await addKeyChainItems(inventory, keyChainInfo);
|
const inventoryChanges = await addKeyChainItems(inventory, keyChainInfo);
|
||||||
|
|
||||||
if (isEmptyObject(inventoryChanges)) {
|
if (isEmptyObject(inventoryChanges)) {
|
||||||
@ -189,7 +195,7 @@ export const giveKeyChainMessage = async (
|
|||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
accountId: string,
|
accountId: string,
|
||||||
keyChainInfo: IKeyChainRequest
|
keyChainInfo: IKeyChainRequest
|
||||||
) => {
|
): Promise<void> => {
|
||||||
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
|
@ -148,7 +148,7 @@ export const handleInventoryItemConfigChange = async (
|
|||||||
|
|
||||||
const itemEntries = equipment as IItemEntry;
|
const itemEntries = equipment as IItemEntry;
|
||||||
for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) {
|
for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) {
|
||||||
const inventoryItem = inventory[equipmentName].find(item => item._id?.toString() === itemId);
|
const inventoryItem = inventory[equipmentName].id(itemId);
|
||||||
|
|
||||||
if (!inventoryItem) {
|
if (!inventoryItem) {
|
||||||
throw new Error(`inventory item ${equipmentName} not found with id ${itemId}`);
|
throw new Error(`inventory item ${equipmentName} not found with id ${itemId}`);
|
||||||
|
@ -58,6 +58,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!ignoredCategories.includes(category)) {
|
if (!ignoredCategories.includes(category)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!unknownCategories[action]) {
|
if (!unknownCategories[action]) {
|
||||||
unknownCategories[action] = [];
|
unknownCategories[action] = [];
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
|||||||
case "FIRE_WEAPON":
|
case "FIRE_WEAPON":
|
||||||
case "HIT_ENTITY_ITEM":
|
case "HIT_ENTITY_ITEM":
|
||||||
case "HEADSHOT_ITEM":
|
case "HEADSHOT_ITEM":
|
||||||
case "KILL_ENEMY_ITEM":
|
case "KILL_ENEMY_ITEM": {
|
||||||
playerStats.Weapons ??= [];
|
playerStats.Weapons ??= [];
|
||||||
const statKey = {
|
const statKey = {
|
||||||
FIRE_WEAPON: "fired",
|
FIRE_WEAPON: "fired",
|
||||||
@ -126,10 +127,11 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "KILL_ENEMY":
|
case "KILL_ENEMY":
|
||||||
case "EXECUTE_ENEMY":
|
case "EXECUTE_ENEMY":
|
||||||
case "HEADSHOT":
|
case "HEADSHOT": {
|
||||||
playerStats.Enemies ??= [];
|
playerStats.Enemies ??= [];
|
||||||
const enemyStatKey = {
|
const enemyStatKey = {
|
||||||
KILL_ENEMY: "kills",
|
KILL_ENEMY: "kills",
|
||||||
@ -149,6 +151,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "DIE":
|
case "DIE":
|
||||||
playerStats.Enemies ??= [];
|
playerStats.Enemies ??= [];
|
||||||
@ -229,6 +232,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
if (!ignoredCategories.includes(category)) {
|
if (!ignoredCategories.includes(category)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
if (!unknownCategories[action]) {
|
if (!unknownCategories[action]) {
|
||||||
unknownCategories[action] = [];
|
unknownCategories[action] = [];
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ export interface IInventoryDatabase
|
|||||||
GuildId?: Types.ObjectId;
|
GuildId?: Types.ObjectId;
|
||||||
PendingRecipes: IPendingRecipe[];
|
PendingRecipes: IPendingRecipe[];
|
||||||
QuestKeys: IQuestKeyDatabase[];
|
QuestKeys: IQuestKeyDatabase[];
|
||||||
BlessingCooldown: Date;
|
BlessingCooldown?: Date;
|
||||||
Ships: Types.ObjectId[];
|
Ships: Types.ObjectId[];
|
||||||
WeaponSkins: IWeaponSkinDatabase[];
|
WeaponSkins: IWeaponSkinDatabase[];
|
||||||
Upgrades: IUpgradeDatabase[];
|
Upgrades: IUpgradeDatabase[];
|
||||||
@ -300,7 +300,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
PlayedParkourTutorial: boolean;
|
PlayedParkourTutorial: boolean;
|
||||||
SubscribedToEmailsPersonalized: number;
|
SubscribedToEmailsPersonalized: number;
|
||||||
InfestedFoundry?: IInfestedFoundryClient;
|
InfestedFoundry?: IInfestedFoundryClient;
|
||||||
BlessingCooldown: IMongoDate;
|
BlessingCooldown?: IMongoDate;
|
||||||
CrewShipRawSalvage: IConsumable[];
|
CrewShipRawSalvage: IConsumable[];
|
||||||
CrewMembers: ICrewMember[];
|
CrewMembers: ICrewMember[];
|
||||||
LotusCustomization: ILotusCustomization;
|
LotusCustomization: ILotusCustomization;
|
||||||
@ -309,7 +309,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
|||||||
LastInventorySync: IOid;
|
LastInventorySync: IOid;
|
||||||
NextRefill: IMongoDate; // Next time argon crystals will have a decay tick
|
NextRefill: IMongoDate; // Next time argon crystals will have a decay tick
|
||||||
FoundToday?: IMiscItem[]; // for Argon Crystals
|
FoundToday?: IMiscItem[]; // for Argon Crystals
|
||||||
CustomMarkers: ICustomMarkers[];
|
CustomMarkers?: ICustomMarkers[];
|
||||||
ActiveLandscapeTraps: any[];
|
ActiveLandscapeTraps: any[];
|
||||||
EvolutionProgress?: IEvolutionProgress[];
|
EvolutionProgress?: IEvolutionProgress[];
|
||||||
RepVotes: any[];
|
RepVotes: any[];
|
||||||
|
@ -8,4 +8,6 @@ export interface IMissionReward {
|
|||||||
ItemCount: number;
|
ItemCount: number;
|
||||||
TweetText?: string;
|
TweetText?: string;
|
||||||
ProductCategory?: string;
|
ProductCategory?: string;
|
||||||
|
FromEnemyCache?: boolean;
|
||||||
|
IsStrippedItem?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,11 @@ export type IMissionInventoryUpdateRequest = {
|
|||||||
PlayerSkillGains: IPlayerSkills;
|
PlayerSkillGains: IPlayerSkills;
|
||||||
CustomMarkers?: ICustomMarkers[];
|
CustomMarkers?: ICustomMarkers[];
|
||||||
LoreFragmentScans?: ILoreFragmentScan[];
|
LoreFragmentScans?: ILoreFragmentScan[];
|
||||||
|
VoidTearParticipantsCurrWave?: {
|
||||||
|
Wave: number;
|
||||||
|
IsFinalWave: boolean;
|
||||||
|
Participants: IVoidTearParticipantInfo[];
|
||||||
|
};
|
||||||
} & {
|
} & {
|
||||||
[K in TEquipmentKey]?: IEquipmentClient[];
|
[K in TEquipmentKey]?: IEquipmentClient[];
|
||||||
};
|
};
|
||||||
@ -136,3 +141,17 @@ export interface IUnlockShipFeatureRequest {
|
|||||||
KeyChain: string;
|
KeyChain: string;
|
||||||
ChainStage: number;
|
ChainStage: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IVoidTearParticipantInfo {
|
||||||
|
AccountId: string;
|
||||||
|
Name: string;
|
||||||
|
ChosenRewardOwner: string;
|
||||||
|
MissionHash: string;
|
||||||
|
VoidProjection: string;
|
||||||
|
Reward: string;
|
||||||
|
QualifiesForReward: boolean;
|
||||||
|
HaveRewardResponse: boolean;
|
||||||
|
RewardsMultiplier: number;
|
||||||
|
RewardProjection: string;
|
||||||
|
HardModeReward: ITypeCount;
|
||||||
|
}
|
||||||
|
@ -33,9 +33,9 @@ const consolelogFormat = format.printf(info => {
|
|||||||
colors: true
|
colors: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${info.timestamp} [${info.version}] ${info.level}: ${info.message} ${metadataString}`;
|
return `${info.timestamp as string} [${info.version as string}] ${info.level}: ${info.message as string} ${metadataString}`;
|
||||||
}
|
}
|
||||||
return `${info.timestamp} [${info.version}] ${info.level}: ${info.message}`;
|
return `${info.timestamp as string} [${info.version as string}] ${info.level}: ${info.message as string}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const fileFormat = format.combine(
|
const fileFormat = format.combine(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user