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-loss-of-precision": "warn",
|
||||
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||
"no-case-declarations": "warn",
|
||||
"no-case-declarations": "error",
|
||||
"prettier/prettier": "error",
|
||||
"@typescript-eslint/semi": "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",
|
||||
"express": "^5",
|
||||
"mongoose": "^8.9.4",
|
||||
"warframe-public-export-plus": "^0.5.35",
|
||||
"warframe-public-export-plus": "^0.5.36",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
@ -4093,9 +4093,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.35",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.35.tgz",
|
||||
"integrity": "sha512-YLQP1n5sOV+PS5hfC4Kuoapa9gsqOy5Qy/E4EYfRV/xJBruFl3tPhbdbgFn3HhL2OBrgRJ8yzT5bjIvaHKhOCw=="
|
||||
"version": "0.5.36",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.36.tgz",
|
||||
"integrity": "sha512-FYZECqBSnynl6lQvcQyEqpnGW9l84wzusekhtwKjvg3280CYdn7g5x0Q9tOMhj1jpc/1tuY+akHtHa94sPtqKw=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
@ -17,7 +17,7 @@
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5",
|
||||
"mongoose": "^8.9.4",
|
||||
"warframe-public-export-plus": "^0.5.35",
|
||||
"warframe-public-export-plus": "^0.5.36",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
|
@ -1,77 +1,31 @@
|
||||
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 { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||
import { getRandomWeightedReward2 } from "@/src/services/rngService";
|
||||
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IVoidTearParticipantInfo } from "@/src/types/requestTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
|
||||
|
||||
export const getVoidProjectionRewardsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
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 = {
|
||||
CurrentWave: data.CurrentWave,
|
||||
ParticipantInfo: data.ParticipantInfo,
|
||||
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);
|
||||
};
|
||||
|
||||
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 {
|
||||
CurrentWave: number;
|
||||
ParticipantInfo: IParticipantInfo;
|
||||
ParticipantInfo: IVoidTearParticipantInfo;
|
||||
VoidTier: string;
|
||||
DifficultyTier: number;
|
||||
VoidProjectionRemovalHash: string;
|
||||
@ -79,20 +33,6 @@ interface IVoidProjectionRewardRequest {
|
||||
|
||||
interface IVoidProjectionRewardResponse {
|
||||
CurrentWave: number;
|
||||
ParticipantInfo: IParticipantInfo;
|
||||
ParticipantInfo: IVoidTearParticipantInfo;
|
||||
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 (
|
||||
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
||||
startingGear: TPartialStartingGear | undefined = undefined
|
||||
) => {
|
||||
): Promise<IInventoryChanges> => {
|
||||
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
|
||||
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
|
||||
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)!;
|
||||
inventory.Suits.pull(suit);
|
||||
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;
|
||||
}
|
||||
if ((inventory.InfestedFoundry!.XP ?? 0) < 73125_00) {
|
||||
|
@ -2,7 +2,14 @@ import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
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> = {
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": "LongGuns",
|
||||
@ -36,8 +43,11 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
||||
const category = modularWeaponTypes[data.WeaponType];
|
||||
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
|
||||
const weapon = addEquipment(inventory, category, data.WeaponType, data.Parts);
|
||||
const inventoryChanges = addEquipment(inventory, category, data.WeaponType, data.Parts, {}, { Configs: configs });
|
||||
|
||||
// Remove credits & parts
|
||||
const miscItemChanges = [];
|
||||
@ -58,8 +68,8 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
||||
// Tell client what we did
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
...inventoryChanges,
|
||||
...currencyChanges,
|
||||
[category]: [weapon],
|
||||
MiscItems: miscItemChanges
|
||||
}
|
||||
});
|
||||
|
@ -50,6 +50,7 @@ const qualityKeywordToNumber: Record<VoidProjectionQuality, number> = {
|
||||
// e.g. "/Lotus/Types/Game/Projections/T2VoidProjectionProteaPrimeDBronze" -> ["Lith", "W5", "VPQ_BRONZE"]
|
||||
const parseProjection = (typeName: string): [string, string, VoidProjectionQuality] => {
|
||||
const relic: IRelic | undefined = ExportRelics[typeName];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!relic) {
|
||||
throw new Error(`Unknown projection ${typeName}`);
|
||||
}
|
||||
|
@ -39,18 +39,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
res.miscitems = [];
|
||||
res.Syndicates = [];
|
||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||
if (
|
||||
item.productCategory == "Suits" ||
|
||||
item.productCategory == "SpaceSuits" ||
|
||||
item.productCategory == "MechSuits"
|
||||
) {
|
||||
res[item.productCategory].push({
|
||||
uniqueName,
|
||||
name: getString(item.name, lang),
|
||||
exalted: item.exalted
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
|
||||
if (item.productCategory == "Sentinels") {
|
||||
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")
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
http.createServer(app).listen(httpPort, () => {
|
||||
logger.info("HTTP server started on port " + httpPort);
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
https.createServer(options, app).listen(httpsPort, () => {
|
||||
logger.info("HTTPS server started on port " + httpsPort);
|
||||
|
||||
|
@ -808,7 +808,7 @@ detailsSchema.set("toJSON", {
|
||||
const EquipmentSchema = new Schema<IEquipmentDatabase>(
|
||||
{
|
||||
ItemType: String,
|
||||
Configs: [ItemConfigSchema],
|
||||
Configs: { type: [ItemConfigSchema], default: [] },
|
||||
UpgradeVer: { type: Number, default: 101 },
|
||||
XP: { type: Number, default: 0 },
|
||||
Features: Number,
|
||||
@ -1303,7 +1303,7 @@ inventorySchema.set("toJSON", {
|
||||
if (inventoryDatabase.GuildId) {
|
||||
inventoryResponse.GuildId = toOid(inventoryDatabase.GuildId);
|
||||
}
|
||||
if (inventoryResponse.BlessingCooldown) {
|
||||
if (inventoryDatabase.BlessingCooldown) {
|
||||
inventoryResponse.BlessingCooldown = toMongoDate(inventoryDatabase.BlessingCooldown);
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ const convertEquipment = (client: IEquipmentClient): IEquipmentDatabase => {
|
||||
UpgradesExpiry: convertOptionalDate(client.UpgradesExpiry),
|
||||
CrewMembers: client.CrewMembers ? convertCrewShipMembers(client.CrewMembers) : undefined,
|
||||
Details: client.Details ? convertKubrowDetails(client.Details) : undefined,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
Configs: client.Configs
|
||||
? client.Configs.map(obj =>
|
||||
Object.fromEntries(
|
||||
|
@ -27,7 +27,7 @@ export const deleteAllMessagesRead = async (accountId: string): Promise<void> =>
|
||||
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 latestEventMessageDate = account.LatestEventMessageDate;
|
||||
|
||||
|
@ -38,27 +38,30 @@ import { getExalted, getKeyChainItems } from "@/src/services/itemDataService";
|
||||
import { IEquipmentClient, IEquipmentDatabase, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
|
||||
import {
|
||||
ExportArcanes,
|
||||
ExportBundles,
|
||||
ExportCustoms,
|
||||
ExportDrones,
|
||||
ExportFlavour,
|
||||
ExportFusionBundles,
|
||||
ExportGear,
|
||||
ExportKeys,
|
||||
ExportMisc,
|
||||
ExportRecipes,
|
||||
ExportResources,
|
||||
ExportSentinels,
|
||||
ExportSyndicates,
|
||||
ExportUpgrades,
|
||||
ExportWeapons,
|
||||
IDefaultUpgrade,
|
||||
TStandingLimitBin
|
||||
} from "warframe-public-export-plus";
|
||||
import { createShip } from "./shipService";
|
||||
import { creditBundles } from "@/src/services/missionInventoryUpdateService";
|
||||
import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||
import { toOid } from "../helpers/inventoryHelpers";
|
||||
import { generateRewardSeed } from "@/src/controllers/api/getNewRewardSeedController";
|
||||
import { addStartingGear } from "@/src/controllers/api/giveStartingGearController";
|
||||
import { addQuestKey, completeQuest } from "@/src/services/questService";
|
||||
import { handleBundleAcqusition } from "./purchaseService";
|
||||
|
||||
export const createInventory = async (
|
||||
accountOwnerId: Types.ObjectId,
|
||||
@ -157,6 +160,11 @@ export const addItem = async (
|
||||
typeName: string,
|
||||
quantity: number = 1
|
||||
): 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
|
||||
if (typeName in ExportRecipes) {
|
||||
const recipeChanges = [
|
||||
@ -203,6 +211,7 @@ export const addItem = async (
|
||||
const inventoryChanges = {
|
||||
...addCrewShip(inventory, typeName),
|
||||
// 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
|
||||
? addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness")
|
||||
: {})
|
||||
@ -284,6 +293,11 @@ export const addItem = async (
|
||||
const weapon = ExportWeapons[typeName];
|
||||
if (weapon.totalDamage != 0) {
|
||||
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);
|
||||
return {
|
||||
InventoryChanges: {
|
||||
@ -307,8 +321,8 @@ export const addItem = async (
|
||||
};
|
||||
}
|
||||
}
|
||||
if (typeName in creditBundles) {
|
||||
const creditsTotal = creditBundles[typeName] * quantity;
|
||||
if (typeName in ExportMisc.creditBundles) {
|
||||
const creditsTotal = ExportMisc.creditBundles[typeName] * quantity;
|
||||
inventory.RegularCredits += creditsTotal;
|
||||
return {
|
||||
InventoryChanges: {
|
||||
@ -331,9 +345,8 @@ export const addItem = async (
|
||||
|
||||
if (key.chainStages) {
|
||||
const key = addQuestKey(inventory, { ItemType: typeName });
|
||||
if (key) {
|
||||
if (!key) return { InventoryChanges: {} };
|
||||
return { InventoryChanges: { QuestKeys: [key] } };
|
||||
}
|
||||
} else {
|
||||
const key = { ItemType: typeName, ItemCount: quantity };
|
||||
|
||||
@ -405,6 +418,7 @@ export const addItem = async (
|
||||
switch (typeName.substr(1).split("/")[2]) {
|
||||
case "Mods": // Legendary Core
|
||||
case "CosmeticEnhancers": // Traumatic Peculiar
|
||||
{
|
||||
const changes = [
|
||||
{
|
||||
ItemType: typeName,
|
||||
@ -420,6 +434,8 @@ export const addItem = async (
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Types":
|
||||
switch (typeName.substr(1).split("/")[2]) {
|
||||
case "Sentinels": {
|
||||
@ -517,21 +533,15 @@ export const addItems = async (
|
||||
return inventoryChanges;
|
||||
};
|
||||
|
||||
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
||||
export const addSentinel = (
|
||||
export const applyDefaultUpgrades = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
sentinelName: string,
|
||||
inventoryChanges: IInventoryChanges = {}
|
||||
): IInventoryChanges => {
|
||||
if (ExportSentinels[sentinelName]?.defaultWeapon) {
|
||||
addSentinelWeapon(inventory, ExportSentinels[sentinelName].defaultWeapon, inventoryChanges);
|
||||
}
|
||||
|
||||
defaultUpgrades: IDefaultUpgrade[] | undefined
|
||||
): IItemConfig[] => {
|
||||
const modsToGive: IRawUpgrade[] = [];
|
||||
const configs: IItemConfig[] = [];
|
||||
if (ExportSentinels[sentinelName]?.defaultUpgrades) {
|
||||
if (defaultUpgrades) {
|
||||
const upgrades = [];
|
||||
for (const defaultUpgrade of ExportSentinels[sentinelName].defaultUpgrades) {
|
||||
for (const defaultUpgrade of defaultUpgrades) {
|
||||
modsToGive.push({ ItemType: defaultUpgrade.ItemType, ItemCount: 1 });
|
||||
if (defaultUpgrade.Slot != -1) {
|
||||
upgrades[defaultUpgrade.Slot] = defaultUpgrade.ItemType;
|
||||
@ -541,8 +551,24 @@ export const addSentinel = (
|
||||
configs.push({ Upgrades: upgrades });
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
inventoryChanges.Sentinels ??= [];
|
||||
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 { handleStoreItemAcquisition } from "./purchaseService";
|
||||
import { IMissionReward } from "../types/missionTypes";
|
||||
import { crackRelic } from "@/src/helpers/relicHelper";
|
||||
|
||||
const getRotations = (rotationCount: number): number[] => {
|
||||
if (rotationCount === 0) return [0];
|
||||
@ -51,27 +52,6 @@ const getRandomRewardByChance = (pool: IReward[]): IRngResult | undefined => {
|
||||
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;
|
||||
//const ignoredInventoryUpdateKeys = ["FpsAvg", "FpsMax", "FpsMin", "FpsSamples"] satisfies TMissionInventoryUpdateKeys[]; // for keys with no meaning for this server
|
||||
//type TignoredInventoryUpdateKeys = (typeof ignoredInventoryUpdateKeys)[number];
|
||||
@ -80,7 +60,7 @@ export const creditBundles: Record<string, number> = {
|
||||
export const addMissionInventoryUpdates = (
|
||||
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
|
||||
inventoryUpdates: IMissionInventoryUpdateRequest
|
||||
) => {
|
||||
): Partial<IInventoryDatabase> | undefined => {
|
||||
//TODO: type this properly
|
||||
const inventoryChanges: Partial<IInventoryDatabase> = {};
|
||||
if (inventoryUpdates.MissionFailed === true) {
|
||||
@ -208,14 +188,14 @@ export const addMissionInventoryUpdates = (
|
||||
inventory.CompletedSorties.push(value);
|
||||
break;
|
||||
}
|
||||
case "SeasonChallengeCompletions":
|
||||
case "SeasonChallengeCompletions": {
|
||||
const processedCompletions = value.map(({ challenge, id }) => ({
|
||||
challenge: challenge.substring(challenge.lastIndexOf("/") + 1),
|
||||
id
|
||||
}));
|
||||
|
||||
inventory.SeasonChallengeHistory.push(...processedCompletions);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Equipment XP updates
|
||||
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
||||
@ -242,7 +222,8 @@ export const addMissionRewards = async (
|
||||
RewardInfo: rewardInfo,
|
||||
LevelKeyName: levelKeyName,
|
||||
Missions: missions,
|
||||
RegularCredits: creditDrops
|
||||
RegularCredits: creditDrops,
|
||||
VoidTearParticipantsCurrWave: voidTearWave
|
||||
}: IMissionInventoryUpdateRequest
|
||||
) => {
|
||||
if (!rewardInfo) {
|
||||
@ -252,9 +233,7 @@ export const addMissionRewards = async (
|
||||
}
|
||||
|
||||
//TODO: check double reward merging
|
||||
const MissionRewards = getRandomMissionDrops(rewardInfo).map(drop => {
|
||||
return { StoreItem: drop.type, ItemCount: drop.itemCount };
|
||||
});
|
||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo);
|
||||
logger.debug("random mission drops:", MissionRewards);
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
|
||||
@ -282,12 +261,15 @@ export const addMissionRewards = async (
|
||||
}
|
||||
}
|
||||
|
||||
if (missions) {
|
||||
if (
|
||||
missions &&
|
||||
missions.Tag != "" // #1013
|
||||
) {
|
||||
const node = getNode(missions.Tag);
|
||||
|
||||
//node based credit rewards for mission completion
|
||||
if (node.missionIndex !== 28) {
|
||||
const levelCreditReward = getLevelCreditRewards(missions?.Tag);
|
||||
const levelCreditReward = getLevelCreditRewards(missions.Tag);
|
||||
missionCompletionCredits += levelCreditReward;
|
||||
inventory.RegularCredits += levelCreditReward;
|
||||
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
||||
@ -312,6 +294,15 @@ export const addMissionRewards = async (
|
||||
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 };
|
||||
};
|
||||
|
||||
@ -360,7 +351,7 @@ export const addFixedLevelRewards = (
|
||||
if (rewards.items) {
|
||||
for (const item of rewards.items) {
|
||||
MissionRewards.push({
|
||||
StoreItem: `/Lotus/StoreItems${item.substring("Lotus/".length)}`,
|
||||
StoreItem: item.includes(`/StoreItems/`) ? item : `/Lotus/StoreItems${item.substring("Lotus/".length)}`,
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
@ -368,7 +359,9 @@ export const addFixedLevelRewards = (
|
||||
if (rewards.countedItems) {
|
||||
for (const item of rewards.countedItems) {
|
||||
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
|
||||
});
|
||||
}
|
||||
@ -389,11 +382,14 @@ function getLevelCreditRewards(nodeName: string): number {
|
||||
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
||||
}
|
||||
|
||||
function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
||||
const drops: IRngResult[] = [];
|
||||
function getRandomMissionDrops(RewardInfo: IRewardInfo): IMissionReward[] {
|
||||
const drops: IMissionReward[] = [];
|
||||
if (RewardInfo.node in ExportRegions) {
|
||||
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[] = [];
|
||||
if (RewardInfo.VaultsCracked) {
|
||||
@ -412,7 +408,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
||||
const rotationRewards = table[rotation];
|
||||
const drop = getRandomRewardByChance(rotationRewards);
|
||||
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) {
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
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]);
|
||||
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 {
|
||||
ExportBoosterPacks,
|
||||
ExportBoosters,
|
||||
ExportBundles,
|
||||
ExportGear,
|
||||
ExportMisc,
|
||||
ExportResources,
|
||||
ExportSyndicates,
|
||||
ExportVendors,
|
||||
@ -25,7 +27,6 @@ import {
|
||||
} from "warframe-public-export-plus";
|
||||
import { config } from "./configService";
|
||||
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
||||
import { creditBundles } from "./missionInventoryUpdateService";
|
||||
|
||||
export const getStoreItemCategory = (storeItem: string): string => {
|
||||
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 (
|
||||
storeItemName: string,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
@ -211,22 +237,7 @@ export const handleStoreItemAcquisition = async (
|
||||
};
|
||||
logger.debug(`handling acquision of ${storeItemName}`);
|
||||
if (storeItemName in ExportBundles) {
|
||||
const bundle = ExportBundles[storeItemName];
|
||||
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
|
||||
);
|
||||
}
|
||||
await handleBundleAcqusition(storeItemName, inventory, quantity, purchaseResponse.InventoryChanges);
|
||||
} else {
|
||||
const storeCategory = getStoreItemCategory(storeItemName);
|
||||
const internalName = storeItemName.replace("/StoreItems", "");
|
||||
@ -247,7 +258,7 @@ export const handleStoreItemAcquisition = async (
|
||||
purchaseResponse = await handleTypesPurchase(internalName, inventory, quantity);
|
||||
break;
|
||||
case "Boosters":
|
||||
purchaseResponse = handleBoostersPurchase(internalName, inventory, durability);
|
||||
purchaseResponse = handleBoostersPurchase(storeItemName, inventory, durability);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -335,8 +346,8 @@ const handleCreditBundlePurchase = async (
|
||||
typeName: string,
|
||||
inventory: TInventoryDatabaseDocument
|
||||
): Promise<IPurchaseResponse> => {
|
||||
if (typeName && typeName in creditBundles) {
|
||||
const creditsAmount = creditBundles[typeName];
|
||||
if (typeName && typeName in ExportMisc.creditBundles) {
|
||||
const creditsAmount = ExportMisc.creditBundles[typeName];
|
||||
|
||||
inventory.RegularCredits += creditsAmount;
|
||||
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 = (
|
||||
boosterStoreName: string,
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
durability: TRarity
|
||||
): { InventoryChanges: IInventoryChanges } => {
|
||||
const ItemType = boosterStoreName.replace("StoreItem", "");
|
||||
if (!boosterCollection.find(x => x == ItemType)) {
|
||||
logger.error(`unknown booster type: ${ItemType}`);
|
||||
if (!(boosterStoreName in ExportBoosters)) {
|
||||
logger.error(`unknown booster type: ${boosterStoreName}`);
|
||||
return { InventoryChanges: {} };
|
||||
}
|
||||
|
||||
const ExpiryDate = boosterDuration[durability];
|
||||
const ItemType = ExportBoosters[boosterStoreName].typeName;
|
||||
const ExpiryDate = ExportMisc.boosterDurations[durability];
|
||||
|
||||
addBooster(ItemType, ExpiryDate, inventory);
|
||||
|
||||
|
@ -15,6 +15,7 @@ import { logger } from "@/src/utils/logger";
|
||||
import { HydratedDocument } from "mongoose";
|
||||
import { ExportKeys } from "warframe-public-export-plus";
|
||||
import { addFixedLevelRewards } from "./missionInventoryUpdateService";
|
||||
import { IInventoryChanges } from "../types/purchaseTypes";
|
||||
|
||||
export interface IUpdateQuestRequest {
|
||||
QuestKeys: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
||||
@ -64,6 +65,7 @@ export const updateQuestStage = (
|
||||
|
||||
const questStage = quest.Progress[ChainStage];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!questStage) {
|
||||
const questStageIndex = quest.Progress.push(questStageUpdate) - 1;
|
||||
if (questStageIndex !== ChainStage) {
|
||||
@ -77,7 +79,7 @@ export const updateQuestStage = (
|
||||
|
||||
export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQuestKeyDatabase) => {
|
||||
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;
|
||||
}
|
||||
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) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
const chainStages = ExportKeys[questKey]?.chainStages;
|
||||
|
||||
if (!chainStages) {
|
||||
@ -164,7 +167,10 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
|
||||
//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);
|
||||
|
||||
if (isEmptyObject(inventoryChanges)) {
|
||||
@ -189,7 +195,7 @@ export const giveKeyChainMessage = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
accountId: string,
|
||||
keyChainInfo: IKeyChainRequest
|
||||
) => {
|
||||
): Promise<void> => {
|
||||
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
||||
|
||||
const message = {
|
||||
|
@ -148,7 +148,7 @@ export const handleInventoryItemConfigChange = async (
|
||||
|
||||
const itemEntries = equipment as IItemEntry;
|
||||
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) {
|
||||
throw new Error(`inventory item ${equipmentName} not found with id ${itemId}`);
|
||||
|
@ -58,6 +58,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
||||
break;
|
||||
default:
|
||||
if (!ignoredCategories.includes(category)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!unknownCategories[action]) {
|
||||
unknownCategories[action] = [];
|
||||
}
|
||||
@ -105,7 +106,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
||||
case "FIRE_WEAPON":
|
||||
case "HIT_ENTITY_ITEM":
|
||||
case "HEADSHOT_ITEM":
|
||||
case "KILL_ENEMY_ITEM":
|
||||
case "KILL_ENEMY_ITEM": {
|
||||
playerStats.Weapons ??= [];
|
||||
const statKey = {
|
||||
FIRE_WEAPON: "fired",
|
||||
@ -126,10 +127,11 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "KILL_ENEMY":
|
||||
case "EXECUTE_ENEMY":
|
||||
case "HEADSHOT":
|
||||
case "HEADSHOT": {
|
||||
playerStats.Enemies ??= [];
|
||||
const enemyStatKey = {
|
||||
KILL_ENEMY: "kills",
|
||||
@ -149,6 +151,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "DIE":
|
||||
playerStats.Enemies ??= [];
|
||||
@ -229,6 +232,7 @@ export const updateStats = async (playerStats: TStatsDatabaseDocument, payload:
|
||||
|
||||
default:
|
||||
if (!ignoredCategories.includes(category)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!unknownCategories[action]) {
|
||||
unknownCategories[action] = [];
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ export interface IInventoryDatabase
|
||||
GuildId?: Types.ObjectId;
|
||||
PendingRecipes: IPendingRecipe[];
|
||||
QuestKeys: IQuestKeyDatabase[];
|
||||
BlessingCooldown: Date;
|
||||
BlessingCooldown?: Date;
|
||||
Ships: Types.ObjectId[];
|
||||
WeaponSkins: IWeaponSkinDatabase[];
|
||||
Upgrades: IUpgradeDatabase[];
|
||||
@ -300,7 +300,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
PlayedParkourTutorial: boolean;
|
||||
SubscribedToEmailsPersonalized: number;
|
||||
InfestedFoundry?: IInfestedFoundryClient;
|
||||
BlessingCooldown: IMongoDate;
|
||||
BlessingCooldown?: IMongoDate;
|
||||
CrewShipRawSalvage: IConsumable[];
|
||||
CrewMembers: ICrewMember[];
|
||||
LotusCustomization: ILotusCustomization;
|
||||
@ -309,7 +309,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
LastInventorySync: IOid;
|
||||
NextRefill: IMongoDate; // Next time argon crystals will have a decay tick
|
||||
FoundToday?: IMiscItem[]; // for Argon Crystals
|
||||
CustomMarkers: ICustomMarkers[];
|
||||
CustomMarkers?: ICustomMarkers[];
|
||||
ActiveLandscapeTraps: any[];
|
||||
EvolutionProgress?: IEvolutionProgress[];
|
||||
RepVotes: any[];
|
||||
|
@ -8,4 +8,6 @@ export interface IMissionReward {
|
||||
ItemCount: number;
|
||||
TweetText?: string;
|
||||
ProductCategory?: string;
|
||||
FromEnemyCache?: boolean;
|
||||
IsStrippedItem?: boolean;
|
||||
}
|
||||
|
@ -87,6 +87,11 @@ export type IMissionInventoryUpdateRequest = {
|
||||
PlayerSkillGains: IPlayerSkills;
|
||||
CustomMarkers?: ICustomMarkers[];
|
||||
LoreFragmentScans?: ILoreFragmentScan[];
|
||||
VoidTearParticipantsCurrWave?: {
|
||||
Wave: number;
|
||||
IsFinalWave: boolean;
|
||||
Participants: IVoidTearParticipantInfo[];
|
||||
};
|
||||
} & {
|
||||
[K in TEquipmentKey]?: IEquipmentClient[];
|
||||
};
|
||||
@ -136,3 +141,17 @@ export interface IUnlockShipFeatureRequest {
|
||||
KeyChain: string;
|
||||
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
|
||||
});
|
||||
|
||||
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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user