2025-01-03 22:17:34 +01:00
|
|
|
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
2024-12-29 21:11:10 +01:00
|
|
|
import postTutorialInventory from "@/static/fixed_responses/postTutorialInventory.json";
|
2024-05-15 21:55:59 +02:00
|
|
|
import { config } from "@/src/services/configService";
|
2023-06-04 03:06:22 +02:00
|
|
|
import { Types } from "mongoose";
|
2024-12-31 01:41:29 +01:00
|
|
|
import { SlotNames, IInventoryChanges, IBinChanges, ICurrencyChanges } from "@/src/types/purchaseTypes";
|
2023-08-31 14:29:09 +04:00
|
|
|
import {
|
2023-09-05 07:37:30 -05:00
|
|
|
IChallengeProgress,
|
2023-09-06 14:02:54 +04:00
|
|
|
IConsumable,
|
2023-09-05 07:37:30 -05:00
|
|
|
IFlavourItem,
|
2023-09-06 14:02:54 +04:00
|
|
|
IMiscItem,
|
2023-09-10 00:10:21 +04:00
|
|
|
IMission,
|
2024-05-09 16:04:31 +02:00
|
|
|
IRawUpgrade,
|
2024-06-16 17:51:20 +02:00
|
|
|
ISeasonChallenge,
|
2024-06-15 02:50:43 +02:00
|
|
|
ITypeCount,
|
2024-06-22 23:19:07 +02:00
|
|
|
InventorySlot,
|
2024-06-29 13:55:15 +02:00
|
|
|
IWeaponSkinClient,
|
|
|
|
TEquipmentKey,
|
2024-07-03 23:01:35 +02:00
|
|
|
equipmentKeys,
|
2025-01-16 18:05:17 +01:00
|
|
|
IFusionTreasure,
|
|
|
|
IInventoryDatabase
|
2023-09-05 07:37:30 -05:00
|
|
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
|
|
|
import { IGenericUpdate } from "../types/genericUpdate";
|
2024-06-02 18:35:06 +03:00
|
|
|
import {
|
|
|
|
IArtifactsRequest,
|
|
|
|
IMissionInventoryUpdateRequest,
|
|
|
|
IThemeUpdateRequest,
|
|
|
|
IUpdateChallengeProgressRequest
|
|
|
|
} from "../types/requestTypes";
|
2024-01-06 16:26:58 +01:00
|
|
|
import { logger } from "@/src/utils/logger";
|
2024-06-29 15:11:12 +02:00
|
|
|
import { getWeaponType, getExalted } from "@/src/services/itemDataService";
|
2024-12-23 22:44:24 +01:00
|
|
|
import { IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
|
2024-07-03 12:30:32 +02:00
|
|
|
import {
|
2024-12-22 16:15:05 +01:00
|
|
|
ExportArcanes,
|
2024-07-03 12:30:32 +02:00
|
|
|
ExportCustoms,
|
|
|
|
ExportFlavour,
|
2024-12-22 05:38:46 +01:00
|
|
|
ExportGear,
|
2024-07-03 12:30:32 +02:00
|
|
|
ExportRecipes,
|
2024-12-22 05:32:30 +01:00
|
|
|
ExportResources,
|
2024-12-23 22:44:24 +01:00
|
|
|
ExportSentinels,
|
2025-01-16 18:05:17 +01:00
|
|
|
ExportUpgrades,
|
|
|
|
TStandingLimitBin
|
2024-07-03 12:30:32 +02:00
|
|
|
} from "warframe-public-export-plus";
|
2024-12-23 09:15:41 +01:00
|
|
|
import { createShip } from "./shipService";
|
2023-06-04 03:06:22 +02:00
|
|
|
|
2024-02-18 13:58:43 +01:00
|
|
|
export const createInventory = async (
|
|
|
|
accountOwnerId: Types.ObjectId,
|
|
|
|
defaultItemReferences: { loadOutPresetId: Types.ObjectId; ship: Types.ObjectId }
|
2024-12-29 21:47:18 +01:00
|
|
|
): Promise<void> => {
|
2023-06-04 03:06:22 +02:00
|
|
|
try {
|
2024-12-29 21:11:10 +01:00
|
|
|
const inventory = config.skipTutorial
|
|
|
|
? new Inventory({
|
|
|
|
accountOwnerId: accountOwnerId,
|
|
|
|
LoadOutPresets: defaultItemReferences.loadOutPresetId,
|
|
|
|
Ships: [defaultItemReferences.ship],
|
|
|
|
...postTutorialInventory
|
|
|
|
})
|
|
|
|
: new Inventory({
|
|
|
|
accountOwnerId: accountOwnerId,
|
|
|
|
LoadOutPresets: defaultItemReferences.loadOutPresetId,
|
|
|
|
Ships: [defaultItemReferences.ship],
|
|
|
|
TrainingDate: 0
|
|
|
|
});
|
2023-06-04 03:06:22 +02:00
|
|
|
await inventory.save();
|
|
|
|
} catch (error) {
|
|
|
|
if (error instanceof Error) {
|
|
|
|
throw new Error(`error creating inventory" ${error.message}`);
|
|
|
|
}
|
|
|
|
throw new Error("error creating inventory that is not of instance Error");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-07-03 12:30:32 +02:00
|
|
|
export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, delta: IInventoryChanges): void => {
|
|
|
|
for (const key in delta) {
|
|
|
|
if (!(key in InventoryChanges)) {
|
|
|
|
InventoryChanges[key] = delta[key];
|
|
|
|
} else if (Array.isArray(delta[key])) {
|
|
|
|
const left = InventoryChanges[key] as object[];
|
2024-07-03 13:00:31 +02:00
|
|
|
const right: object[] = delta[key];
|
2024-07-03 12:30:32 +02:00
|
|
|
for (const item of right) {
|
|
|
|
left.push(item);
|
|
|
|
}
|
2024-12-29 21:40:54 +01:00
|
|
|
} else if (typeof delta[key] == "object") {
|
2024-07-03 12:30:32 +02:00
|
|
|
console.assert(key.substring(-3) == "Bin");
|
2025-01-05 07:16:48 +01:00
|
|
|
console.assert(key != "InfestedFoundry");
|
2024-07-03 12:30:32 +02:00
|
|
|
const left = InventoryChanges[key] as IBinChanges;
|
2025-01-05 07:16:48 +01:00
|
|
|
const right = delta[key] as IBinChanges;
|
2024-07-03 12:30:32 +02:00
|
|
|
left.count += right.count;
|
|
|
|
left.platinum += right.platinum;
|
|
|
|
left.Slots += right.Slots;
|
|
|
|
if (right.Extra) {
|
|
|
|
left.Extra ??= 0;
|
|
|
|
left.Extra += right.Extra;
|
|
|
|
}
|
2024-12-29 21:40:54 +01:00
|
|
|
} else {
|
|
|
|
logger.warn(`inventory change not merged: ${key}`);
|
2024-07-03 12:30:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
export const getInventory = async (accountOwnerId: string): Promise<TInventoryDatabaseDocument> => {
|
2023-06-14 02:26:19 +02:00
|
|
|
const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId });
|
|
|
|
|
|
|
|
if (!inventory) {
|
|
|
|
throw new Error(`Didn't find an inventory for ${accountOwnerId}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
return inventory;
|
|
|
|
};
|
|
|
|
|
2024-06-15 02:50:43 +02:00
|
|
|
export const addItem = async (
|
2025-01-04 00:25:09 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-06-15 02:50:43 +02:00
|
|
|
typeName: string,
|
|
|
|
quantity: number = 1
|
2024-06-20 16:35:24 +02:00
|
|
|
): Promise<{ InventoryChanges: IInventoryChanges }> => {
|
2024-06-17 16:41:02 +02:00
|
|
|
// Strict typing
|
|
|
|
if (typeName in ExportRecipes) {
|
|
|
|
const recipeChanges = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies ITypeCount
|
|
|
|
];
|
|
|
|
addRecipes(inventory, recipeChanges);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
Recipes: recipeChanges
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-06-20 16:35:24 +02:00
|
|
|
if (typeName in ExportResources) {
|
2024-12-23 09:15:41 +01:00
|
|
|
if (ExportResources[typeName].productCategory == "Ships") {
|
2025-01-04 00:25:09 +01:00
|
|
|
const oid = await createShip(inventory.accountOwnerId, typeName);
|
2024-12-23 09:15:41 +01:00
|
|
|
inventory.Ships.push(oid);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
Ships: [
|
|
|
|
{
|
|
|
|
ItemId: { $oid: oid },
|
|
|
|
ItemType: typeName
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
};
|
2024-12-23 22:47:58 +01:00
|
|
|
} else if (ExportResources[typeName].productCategory == "CrewShips") {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addCrewShip(inventory, typeName);
|
|
|
|
return { InventoryChanges: inventoryChanges };
|
2025-01-11 12:54:11 +01:00
|
|
|
} else if (ExportResources[typeName].productCategory == "ShipDecorations") {
|
|
|
|
const changes = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies IMiscItem
|
|
|
|
];
|
|
|
|
addShipDecorations(inventory, changes);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
ShipDecorations: changes
|
|
|
|
}
|
|
|
|
};
|
2024-12-23 09:15:41 +01:00
|
|
|
} else {
|
|
|
|
const miscItemChanges = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies IMiscItem
|
|
|
|
];
|
|
|
|
addMiscItems(inventory, miscItemChanges);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
MiscItems: miscItemChanges
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-06-20 16:35:24 +02:00
|
|
|
}
|
2024-06-22 23:19:07 +02:00
|
|
|
if (typeName in ExportCustoms) {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addSkin(inventory, typeName);
|
|
|
|
return { InventoryChanges: inventoryChanges };
|
2024-06-22 23:19:07 +02:00
|
|
|
}
|
2024-06-24 12:30:32 +02:00
|
|
|
if (typeName in ExportFlavour) {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addCustomization(inventory, typeName);
|
|
|
|
return { InventoryChanges: inventoryChanges };
|
2024-06-24 12:30:32 +02:00
|
|
|
}
|
2024-12-22 16:15:05 +01:00
|
|
|
if (typeName in ExportUpgrades || typeName in ExportArcanes) {
|
2024-12-22 05:32:30 +01:00
|
|
|
const changes = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
}
|
|
|
|
];
|
|
|
|
addMods(inventory, changes);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
RawUpgrades: changes
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-12-22 05:38:46 +01:00
|
|
|
if (typeName in ExportGear) {
|
|
|
|
const consumablesChanges = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies IConsumable
|
|
|
|
];
|
|
|
|
addConsumables(inventory, consumablesChanges);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
Consumables: consumablesChanges
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2024-06-17 16:41:02 +02:00
|
|
|
|
|
|
|
// Path-based duck typing
|
2024-06-15 02:50:43 +02:00
|
|
|
switch (typeName.substr(1).split("/")[1]) {
|
|
|
|
case "Powersuits":
|
2024-06-19 17:46:12 +02:00
|
|
|
switch (typeName.substr(1).split("/")[2]) {
|
|
|
|
default: {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addPowerSuit(inventory, typeName);
|
|
|
|
updateSlots(inventory, InventorySlot.SUITS, 0, 1);
|
2024-06-19 17:46:12 +02:00
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
2024-12-29 03:42:22 +01:00
|
|
|
...inventoryChanges,
|
2024-06-19 17:46:12 +02:00
|
|
|
SuitBin: {
|
|
|
|
count: 1,
|
|
|
|
platinum: 0,
|
|
|
|
Slots: -1
|
2024-12-29 03:42:22 +01:00
|
|
|
}
|
2024-06-19 17:46:12 +02:00
|
|
|
}
|
|
|
|
};
|
2024-06-15 02:50:43 +02:00
|
|
|
}
|
2024-06-19 17:46:12 +02:00
|
|
|
case "Archwing": {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addSpaceSuit(inventory, typeName);
|
|
|
|
updateSlots(inventory, InventorySlot.SPACESUITS, 0, 1);
|
2024-06-19 17:46:12 +02:00
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
2025-01-04 00:25:09 +01:00
|
|
|
...inventoryChanges,
|
2024-06-19 17:46:12 +02:00
|
|
|
SpaceSuitBin: {
|
|
|
|
count: 1,
|
|
|
|
platinum: 0,
|
|
|
|
Slots: -1
|
2025-01-04 00:25:09 +01:00
|
|
|
}
|
2024-06-19 17:46:12 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
case "EntratiMech": {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addMechSuit(inventory, typeName);
|
|
|
|
updateSlots(inventory, InventorySlot.MECHSUITS, 0, 1);
|
2024-06-19 17:46:12 +02:00
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
2024-12-29 03:42:22 +01:00
|
|
|
...inventoryChanges,
|
2024-06-19 17:46:12 +02:00
|
|
|
MechBin: {
|
|
|
|
count: 1,
|
|
|
|
platinum: 0,
|
|
|
|
Slots: -1
|
2024-12-29 03:42:22 +01:00
|
|
|
}
|
2024-06-19 17:46:12 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2024-12-29 05:37:48 +01:00
|
|
|
case "Weapons": {
|
2024-06-15 02:50:43 +02:00
|
|
|
const weaponType = getWeaponType(typeName);
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addEquipment(inventory, weaponType, typeName);
|
|
|
|
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
2024-06-15 02:50:43 +02:00
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
2025-01-04 00:25:09 +01:00
|
|
|
...inventoryChanges,
|
|
|
|
WeaponBin: { count: 1, platinum: 0, Slots: -1 }
|
2024-06-15 02:50:43 +02:00
|
|
|
}
|
|
|
|
};
|
2024-12-29 05:37:48 +01:00
|
|
|
}
|
2024-06-15 02:50:43 +02:00
|
|
|
case "Types":
|
|
|
|
switch (typeName.substr(1).split("/")[2]) {
|
2024-12-23 22:44:24 +01:00
|
|
|
case "Sentinels": {
|
2025-01-04 00:25:09 +01:00
|
|
|
const inventoryChanges = addSentinel(inventory, typeName);
|
|
|
|
updateSlots(inventory, InventorySlot.SENTINELS, 0, 1);
|
2024-06-15 02:50:43 +02:00
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
2024-12-23 22:44:24 +01:00
|
|
|
...inventoryChanges,
|
|
|
|
SentinelBin: { count: 1, platinum: 0, Slots: -1 }
|
2024-06-15 02:50:43 +02:00
|
|
|
}
|
|
|
|
};
|
2024-12-23 22:44:24 +01:00
|
|
|
}
|
2024-06-15 02:50:43 +02:00
|
|
|
case "Items": {
|
2024-06-15 15:12:08 +02:00
|
|
|
switch (typeName.substr(1).split("/")[3]) {
|
|
|
|
default: {
|
|
|
|
const miscItemChanges = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies IMiscItem
|
|
|
|
];
|
|
|
|
addMiscItems(inventory, miscItemChanges);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
MiscItems: miscItemChanges
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2024-06-15 02:50:43 +02:00
|
|
|
}
|
2024-07-03 12:30:32 +02:00
|
|
|
case "Game":
|
|
|
|
if (typeName.substr(1).split("/")[3] == "Projections") {
|
|
|
|
// Void Relics, e.g. /Lotus/Types/Game/Projections/T2VoidProjectionGaussPrimeDBronze
|
|
|
|
const miscItemChanges = [
|
|
|
|
{
|
|
|
|
ItemType: typeName,
|
|
|
|
ItemCount: quantity
|
|
|
|
} satisfies IMiscItem
|
|
|
|
];
|
|
|
|
addMiscItems(inventory, miscItemChanges);
|
|
|
|
return {
|
|
|
|
InventoryChanges: {
|
|
|
|
MiscItems: miscItemChanges
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
break;
|
2024-06-15 02:50:43 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
const errorMessage = `unable to add item: ${typeName}`;
|
|
|
|
logger.error(errorMessage);
|
|
|
|
throw new Error(errorMessage);
|
|
|
|
};
|
|
|
|
|
2023-12-28 16:24:52 +01:00
|
|
|
//TODO: maybe genericMethod for all the add methods, they share a lot of logic
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addSentinel = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
sentinelName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
2024-12-23 22:44:24 +01:00
|
|
|
if (ExportSentinels[sentinelName]?.defaultWeapon) {
|
2025-01-04 00:25:09 +01:00
|
|
|
addSentinelWeapon(inventory, ExportSentinels[sentinelName].defaultWeapon, inventoryChanges);
|
2024-12-23 22:44:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const modsToGive: IRawUpgrade[] = [];
|
|
|
|
const configs: IItemConfig[] = [];
|
|
|
|
if (ExportSentinels[sentinelName]?.defaultUpgrades) {
|
|
|
|
const upgrades = [];
|
|
|
|
for (const defaultUpgrade of ExportSentinels[sentinelName].defaultUpgrades) {
|
|
|
|
modsToGive.push({ ItemType: defaultUpgrade.ItemType, ItemCount: 1 });
|
|
|
|
if (defaultUpgrade.Slot != -1) {
|
|
|
|
upgrades[defaultUpgrade.Slot] = defaultUpgrade.ItemType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (upgrades.length != 0) {
|
|
|
|
configs.push({ Upgrades: upgrades });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addMods(inventory, modsToGive);
|
2025-01-04 00:25:09 +01:00
|
|
|
const sentinelIndex = inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0 }) - 1;
|
|
|
|
inventoryChanges.Sentinels ??= [];
|
|
|
|
(inventoryChanges.Sentinels as IEquipmentClient[]).push(
|
|
|
|
inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>()
|
|
|
|
);
|
2024-12-23 22:44:24 +01:00
|
|
|
|
|
|
|
return inventoryChanges;
|
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addSentinelWeapon = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
typeName: string,
|
|
|
|
inventoryChanges: IInventoryChanges
|
|
|
|
): void => {
|
|
|
|
const index = inventory.SentinelWeapons.push({ ItemType: typeName }) - 1;
|
|
|
|
inventoryChanges.SentinelWeapons ??= [];
|
|
|
|
(inventoryChanges.SentinelWeapons as IEquipmentClient[]).push(
|
|
|
|
inventory.SentinelWeapons[index].toJSON<IEquipmentClient>()
|
|
|
|
);
|
2023-12-14 17:34:15 +01:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addPowerSuit = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
powersuitName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
2024-06-07 15:58:20 +02:00
|
|
|
const specialItems = getExalted(powersuitName);
|
2024-10-17 22:12:28 +02:00
|
|
|
if (specialItems) {
|
2025-01-04 00:25:09 +01:00
|
|
|
for (const specialItem of specialItems) {
|
|
|
|
addSpecialItem(inventory, specialItem, inventoryChanges);
|
2024-06-07 15:58:20 +02:00
|
|
|
}
|
|
|
|
}
|
2025-01-04 00:25:09 +01:00
|
|
|
const suitIndex = inventory.Suits.push({ ItemType: powersuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
|
|
|
inventoryChanges.Suits ??= [];
|
|
|
|
(inventoryChanges.Suits as IEquipmentClient[]).push(inventory.Suits[suitIndex].toJSON<IEquipmentClient>());
|
2024-12-29 03:42:22 +01:00
|
|
|
return inventoryChanges;
|
2023-06-14 02:26:19 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addMechSuit = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
mechsuitName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
2024-06-07 15:58:20 +02:00
|
|
|
const specialItems = getExalted(mechsuitName);
|
2024-10-17 22:12:28 +02:00
|
|
|
if (specialItems) {
|
2025-01-04 00:25:09 +01:00
|
|
|
for (const specialItem of specialItems) {
|
|
|
|
addSpecialItem(inventory, specialItem, inventoryChanges);
|
2024-06-07 15:58:20 +02:00
|
|
|
}
|
|
|
|
}
|
2025-01-04 00:25:09 +01:00
|
|
|
const suitIndex = inventory.MechSuits.push({ ItemType: mechsuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
|
|
|
inventoryChanges.MechSuits ??= [];
|
|
|
|
(inventoryChanges.MechSuits as IEquipmentClient[]).push(inventory.MechSuits[suitIndex].toJSON<IEquipmentClient>());
|
2024-12-29 03:42:22 +01:00
|
|
|
return inventoryChanges;
|
2023-12-14 17:34:15 +01:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addSpecialItem = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-12-29 03:42:22 +01:00
|
|
|
itemName: string,
|
|
|
|
inventoryChanges: IInventoryChanges
|
2025-01-04 00:25:09 +01:00
|
|
|
): void => {
|
2024-12-29 02:46:57 +01:00
|
|
|
if (inventory.SpecialItems.find(x => x.ItemType == itemName)) {
|
|
|
|
return;
|
|
|
|
}
|
2025-01-04 00:25:09 +01:00
|
|
|
const specialItemIndex =
|
|
|
|
inventory.SpecialItems.push({
|
|
|
|
ItemType: itemName,
|
|
|
|
Configs: [],
|
|
|
|
Features: 1,
|
|
|
|
UpgradeVer: 101,
|
|
|
|
XP: 0
|
|
|
|
}) - 1;
|
2024-12-29 03:42:22 +01:00
|
|
|
inventoryChanges.SpecialItems ??= [];
|
2025-01-04 00:25:09 +01:00
|
|
|
(inventoryChanges.SpecialItems as IEquipmentClient[]).push(
|
|
|
|
inventory.SpecialItems[specialItemIndex].toJSON<IEquipmentClient>()
|
|
|
|
);
|
2024-06-07 15:58:20 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addSpaceSuit = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
spacesuitName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
|
|
|
const suitIndex = inventory.SpaceSuits.push({ ItemType: spacesuitName, Configs: [], UpgradeVer: 101, XP: 0 }) - 1;
|
|
|
|
inventoryChanges.SpaceSuits ??= [];
|
|
|
|
(inventoryChanges.SpaceSuits as IEquipmentClient[]).push(
|
|
|
|
inventory.SpaceSuits[suitIndex].toJSON<IEquipmentClient>()
|
|
|
|
);
|
|
|
|
return inventoryChanges;
|
2024-06-19 17:46:12 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const updateSlots = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-12-29 21:47:18 +01:00
|
|
|
slotName: SlotNames,
|
|
|
|
slotAmount: number,
|
|
|
|
extraAmount: number
|
2025-01-04 00:25:09 +01:00
|
|
|
): void => {
|
2023-12-28 16:24:52 +01:00
|
|
|
inventory[slotName].Slots += slotAmount;
|
|
|
|
if (inventory[slotName].Extra === undefined) {
|
|
|
|
inventory[slotName].Extra = extraAmount;
|
|
|
|
} else {
|
|
|
|
inventory[slotName].Extra += extraAmount;
|
2023-06-14 02:26:19 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-12-31 01:41:29 +01:00
|
|
|
const isCurrencyTracked = (usePremium: boolean): boolean => {
|
|
|
|
return usePremium ? !config.infinitePlatinum : !config.infiniteCredits;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const updateCurrency = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-12-31 01:41:29 +01:00
|
|
|
price: number,
|
|
|
|
usePremium: boolean
|
|
|
|
): ICurrencyChanges => {
|
|
|
|
const currencyChanges: ICurrencyChanges = {};
|
|
|
|
if (price != 0 && isCurrencyTracked(usePremium)) {
|
|
|
|
if (usePremium) {
|
|
|
|
if (inventory.PremiumCreditsFree > 0) {
|
|
|
|
currencyChanges.PremiumCreditsFree = Math.min(price, inventory.PremiumCreditsFree) * -1;
|
|
|
|
inventory.PremiumCreditsFree += currencyChanges.PremiumCreditsFree;
|
|
|
|
}
|
|
|
|
currencyChanges.PremiumCredits = -price;
|
|
|
|
inventory.PremiumCredits += currencyChanges.PremiumCredits;
|
|
|
|
} else {
|
|
|
|
currencyChanges.RegularCredits = -price;
|
|
|
|
inventory.RegularCredits += currencyChanges.RegularCredits;
|
|
|
|
}
|
|
|
|
logger.debug(`currency changes `, currencyChanges);
|
|
|
|
}
|
|
|
|
return currencyChanges;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const updateCurrencyByAccountId = async (
|
2024-12-29 21:40:54 +01:00
|
|
|
price: number,
|
|
|
|
usePremium: boolean,
|
|
|
|
accountId: string
|
2024-12-31 01:41:29 +01:00
|
|
|
): Promise<ICurrencyChanges> => {
|
|
|
|
if (!isCurrencyTracked(usePremium)) {
|
2024-05-09 01:27:32 +02:00
|
|
|
return {};
|
|
|
|
}
|
2023-06-14 02:26:19 +02:00
|
|
|
const inventory = await getInventory(accountId);
|
2024-12-31 01:41:29 +01:00
|
|
|
const currencyChanges = updateCurrency(inventory, price, usePremium);
|
2023-06-14 02:26:19 +02:00
|
|
|
await inventory.save();
|
2023-12-28 16:24:52 +01:00
|
|
|
return currencyChanges;
|
2023-06-14 02:26:19 +02:00
|
|
|
};
|
|
|
|
|
2025-01-16 18:05:17 +01:00
|
|
|
const standingLimitBinToInventoryKey: Record<
|
|
|
|
Exclude<TStandingLimitBin, "STANDING_LIMIT_BIN_NONE">,
|
|
|
|
keyof IInventoryDatabase
|
|
|
|
> = {
|
|
|
|
STANDING_LIMIT_BIN_NORMAL: "DailyAffiliation",
|
|
|
|
STANDING_LIMIT_BIN_PVP: "DailyAffiliationPvp",
|
|
|
|
STANDING_LIMIT_BIN_LIBRARY: "DailyAffiliationLibrary",
|
|
|
|
STANDING_LIMIT_BIN_CETUS: "DailyAffiliationCetus",
|
|
|
|
STANDING_LIMIT_BIN_QUILLS: "DailyAffiliationQuills",
|
|
|
|
STANDING_LIMIT_BIN_SOLARIS: "DailyAffiliationSolaris",
|
|
|
|
STANDING_LIMIT_BIN_VENTKIDS: "DailyAffiliationVentkids",
|
|
|
|
STANDING_LIMIT_BIN_VOX: "DailyAffiliationVox",
|
|
|
|
STANDING_LIMIT_BIN_ENTRATI: "DailyAffiliationEntrati",
|
|
|
|
STANDING_LIMIT_BIN_NECRALOID: "DailyAffiliationNecraloid",
|
|
|
|
STANDING_LIMIT_BIN_ZARIMAN: "DailyAffiliationZariman",
|
|
|
|
STANDING_LIMIT_BIN_KAHL: "DailyAffiliationKahl",
|
|
|
|
STANDING_LIMIT_BIN_CAVIA: "DailyAffiliationCavia",
|
|
|
|
STANDING_LIMIT_BIN_HEX: "DailyAffiliationHex"
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getStandingLimit = (inventory: TInventoryDatabaseDocument, bin: TStandingLimitBin): number => {
|
|
|
|
if (bin == "STANDING_LIMIT_BIN_NONE") {
|
|
|
|
return Number.MAX_SAFE_INTEGER;
|
|
|
|
}
|
|
|
|
return inventory[standingLimitBinToInventoryKey[bin]] as number;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const updateStandingLimit = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
bin: TStandingLimitBin,
|
|
|
|
subtrahend: number
|
|
|
|
): void => {
|
|
|
|
if (bin != "STANDING_LIMIT_BIN_NONE") {
|
|
|
|
(inventory[standingLimitBinToInventoryKey[bin]] as number) -= subtrahend;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-09-05 07:37:30 -05:00
|
|
|
// TODO: AffiliationMods support (Nightwave).
|
2024-10-17 22:24:24 +02:00
|
|
|
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<void> => {
|
2023-09-05 07:37:30 -05:00
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
|
|
|
|
// Make it an array for easier parsing.
|
|
|
|
if (typeof data.NodeIntrosCompleted === "string") {
|
|
|
|
data.NodeIntrosCompleted = [data.NodeIntrosCompleted];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Combine the two arrays into one.
|
|
|
|
data.NodeIntrosCompleted = inventory.NodeIntrosCompleted.concat(data.NodeIntrosCompleted);
|
|
|
|
|
|
|
|
// Remove duplicate entries.
|
|
|
|
const nodes = [...new Set(data.NodeIntrosCompleted)];
|
|
|
|
|
|
|
|
inventory.NodeIntrosCompleted = nodes;
|
|
|
|
await inventory.save();
|
|
|
|
};
|
|
|
|
|
2024-12-29 21:47:18 +01:00
|
|
|
export const updateTheme = async (data: IThemeUpdateRequest, accountId: string): Promise<void> => {
|
2024-04-04 01:55:51 +03:00
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
if (data.Style) inventory.ThemeStyle = data.Style;
|
|
|
|
if (data.Background) inventory.ThemeBackground = data.Background;
|
|
|
|
if (data.Sounds) inventory.ThemeSounds = data.Sounds;
|
|
|
|
|
|
|
|
await inventory.save();
|
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addEquipment = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-06-29 15:11:12 +02:00
|
|
|
category: TEquipmentKey,
|
|
|
|
type: string,
|
2025-01-04 00:25:09 +01:00
|
|
|
modularParts: string[] | undefined = undefined,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
|
|
|
const index =
|
|
|
|
inventory[category].push({
|
|
|
|
ItemType: type,
|
|
|
|
Configs: [],
|
|
|
|
XP: 0,
|
|
|
|
ModularParts: modularParts
|
|
|
|
}) - 1;
|
|
|
|
|
|
|
|
inventoryChanges[category] ??= [];
|
|
|
|
(inventoryChanges[category] as IEquipmentClient[]).push(inventory[category][index].toJSON<IEquipmentClient>());
|
|
|
|
return inventoryChanges;
|
2023-06-14 02:26:19 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addCustomization = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
customizationName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
|
|
|
const flavourItemIndex = inventory.FlavourItems.push({ ItemType: customizationName }) - 1;
|
|
|
|
inventoryChanges.FlavourItems ??= [];
|
|
|
|
(inventoryChanges.FlavourItems as IFlavourItem[]).push(
|
|
|
|
inventory.FlavourItems[flavourItemIndex].toJSON<IFlavourItem>()
|
|
|
|
);
|
|
|
|
return inventoryChanges;
|
2023-06-14 02:26:19 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
export const addSkin = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
typeName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
2024-06-22 23:19:07 +02:00
|
|
|
const index = inventory.WeaponSkins.push({ ItemType: typeName }) - 1;
|
2025-01-04 00:25:09 +01:00
|
|
|
inventoryChanges.WeaponSkins ??= [];
|
|
|
|
(inventoryChanges.WeaponSkins as IWeaponSkinClient[]).push(
|
|
|
|
inventory.WeaponSkins[index].toJSON<IWeaponSkinClient>()
|
|
|
|
);
|
|
|
|
return inventoryChanges;
|
2024-06-22 23:19:07 +02:00
|
|
|
};
|
|
|
|
|
2025-01-04 00:25:09 +01:00
|
|
|
const addCrewShip = (
|
|
|
|
inventory: TInventoryDatabaseDocument,
|
|
|
|
typeName: string,
|
|
|
|
inventoryChanges: IInventoryChanges = {}
|
|
|
|
): IInventoryChanges => {
|
2024-12-23 22:47:58 +01:00
|
|
|
const index = inventory.CrewShips.push({ ItemType: typeName }) - 1;
|
2025-01-04 00:25:09 +01:00
|
|
|
inventoryChanges.CrewShips ??= [];
|
|
|
|
(inventoryChanges.CrewShips as object[]).push(inventory.CrewShips[index].toJSON());
|
|
|
|
return inventoryChanges;
|
2024-12-23 22:47:58 +01:00
|
|
|
};
|
|
|
|
|
2023-08-31 14:29:09 +04:00
|
|
|
const addGearExpByCategory = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-06-16 17:51:20 +02:00
|
|
|
gearArray: IEquipmentClient[] | undefined,
|
2024-06-29 13:55:15 +02:00
|
|
|
categoryName: TEquipmentKey
|
2024-12-29 21:47:18 +01:00
|
|
|
): void => {
|
2023-08-31 14:29:09 +04:00
|
|
|
const category = inventory[categoryName];
|
|
|
|
|
|
|
|
gearArray?.forEach(({ ItemId, XP }) => {
|
2024-05-08 22:53:06 +02:00
|
|
|
if (!XP) {
|
|
|
|
return;
|
|
|
|
}
|
2023-08-31 14:29:09 +04:00
|
|
|
|
2024-05-08 22:53:06 +02:00
|
|
|
const itemIndex = ItemId ? category.findIndex(item => item._id?.equals(ItemId.$oid)) : -1;
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
const item = category[itemIndex];
|
|
|
|
item.XP ??= 0;
|
|
|
|
item.XP += XP;
|
2023-08-31 14:29:09 +04:00
|
|
|
inventory.markModified(`${categoryName}.${itemIndex}.XP`);
|
2024-05-08 22:53:06 +02:00
|
|
|
|
|
|
|
const xpinfoIndex = inventory.XPInfo.findIndex(x => x.ItemType == item.ItemType);
|
|
|
|
if (xpinfoIndex !== -1) {
|
|
|
|
const xpinfo = inventory.XPInfo[xpinfoIndex];
|
|
|
|
xpinfo.XP += XP;
|
|
|
|
} else {
|
|
|
|
inventory.XPInfo.push({
|
|
|
|
ItemType: item.ItemType,
|
|
|
|
XP: XP
|
|
|
|
});
|
|
|
|
}
|
2023-08-31 14:29:09 +04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
export const addMiscItems = (inventory: TInventoryDatabaseDocument, itemsArray: IMiscItem[] | undefined): void => {
|
2023-09-06 14:02:54 +04:00
|
|
|
const { MiscItems } = inventory;
|
|
|
|
|
|
|
|
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
|
|
|
const itemIndex = MiscItems.findIndex(miscItem => miscItem.ItemType === ItemType);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
MiscItems[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`MiscItems.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
MiscItems.push({ ItemCount, ItemType });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-12-29 21:47:18 +01:00
|
|
|
export const addShipDecorations = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-12-29 21:47:18 +01:00
|
|
|
itemsArray: IConsumable[] | undefined
|
|
|
|
): void => {
|
2024-06-15 15:12:08 +02:00
|
|
|
const { ShipDecorations } = inventory;
|
|
|
|
|
|
|
|
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
|
|
|
const itemIndex = ShipDecorations.findIndex(miscItem => miscItem.ItemType === ItemType);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
ShipDecorations[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`ShipDecorations.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
ShipDecorations.push({ ItemCount, ItemType });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
export const addConsumables = (inventory: TInventoryDatabaseDocument, itemsArray: IConsumable[] | undefined): void => {
|
2023-09-06 14:02:54 +04:00
|
|
|
const { Consumables } = inventory;
|
2023-08-31 14:29:09 +04:00
|
|
|
|
|
|
|
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
2023-09-06 14:02:54 +04:00
|
|
|
const itemIndex = Consumables.findIndex(i => i.ItemType === ItemType);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
Consumables[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`Consumables.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
Consumables.push({ ItemCount, ItemType });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
export const addRecipes = (inventory: TInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
2023-09-06 14:02:54 +04:00
|
|
|
const { Recipes } = inventory;
|
|
|
|
|
|
|
|
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
|
|
|
const itemIndex = Recipes.findIndex(i => i.ItemType === ItemType);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
Recipes[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`Recipes.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
Recipes.push({ ItemCount, ItemType });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
export const addMods = (inventory: TInventoryDatabaseDocument, itemsArray: IRawUpgrade[] | undefined): void => {
|
2023-09-06 14:02:54 +04:00
|
|
|
const { RawUpgrades } = inventory;
|
|
|
|
itemsArray?.forEach(({ ItemType, ItemCount }) => {
|
|
|
|
const itemIndex = RawUpgrades.findIndex(i => i.ItemType === ItemType);
|
2023-08-31 14:29:09 +04:00
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
2023-09-06 14:02:54 +04:00
|
|
|
RawUpgrades[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`RawUpgrades.${itemIndex}.ItemCount`);
|
2023-08-31 14:29:09 +04:00
|
|
|
} else {
|
2023-09-06 14:02:54 +04:00
|
|
|
RawUpgrades.push({ ItemCount, ItemType });
|
2023-08-31 14:29:09 +04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-07-03 23:01:35 +02:00
|
|
|
export const addFusionTreasures = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-07-03 23:01:35 +02:00
|
|
|
itemsArray: IFusionTreasure[] | undefined
|
2024-12-29 21:47:18 +01:00
|
|
|
): void => {
|
2024-07-03 23:01:35 +02:00
|
|
|
const { FusionTreasures } = inventory;
|
|
|
|
itemsArray?.forEach(({ ItemType, ItemCount, Sockets }) => {
|
2024-10-12 23:51:45 +02:00
|
|
|
const itemIndex = FusionTreasures.findIndex(i => i.ItemType == ItemType && (i.Sockets || 0) == (Sockets || 0));
|
2024-07-03 23:01:35 +02:00
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
FusionTreasures[itemIndex].ItemCount += ItemCount;
|
|
|
|
inventory.markModified(`FusionTreasures.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
FusionTreasures.push({ ItemCount, ItemType, Sockets });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-12-29 21:47:18 +01:00
|
|
|
export const updateChallengeProgress = async (
|
|
|
|
challenges: IUpdateChallengeProgressRequest,
|
|
|
|
accountId: string
|
|
|
|
): Promise<void> => {
|
2024-06-02 18:35:06 +03:00
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
|
|
|
|
addChallenges(inventory, challenges.ChallengeProgress);
|
|
|
|
addSeasonalChallengeHistory(inventory, challenges.SeasonChallengeHistory);
|
|
|
|
|
|
|
|
await inventory.save();
|
|
|
|
};
|
|
|
|
|
|
|
|
export const addSeasonalChallengeHistory = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-06-16 17:51:20 +02:00
|
|
|
itemsArray: ISeasonChallenge[] | undefined
|
2024-12-29 21:47:18 +01:00
|
|
|
): void => {
|
2024-06-02 18:35:06 +03:00
|
|
|
const category = inventory.SeasonChallengeHistory;
|
|
|
|
|
|
|
|
itemsArray?.forEach(({ challenge, id }) => {
|
|
|
|
const itemIndex = category.findIndex(i => i.challenge === challenge);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
category[itemIndex].id = id;
|
|
|
|
} else {
|
|
|
|
category.push({ challenge, id });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-12-29 21:47:18 +01:00
|
|
|
export const addChallenges = (
|
2025-01-03 22:17:34 +01:00
|
|
|
inventory: TInventoryDatabaseDocument,
|
2024-12-29 21:47:18 +01:00
|
|
|
itemsArray: IChallengeProgress[] | undefined
|
|
|
|
): void => {
|
2023-08-31 14:29:09 +04:00
|
|
|
const category = inventory.ChallengeProgress;
|
|
|
|
|
|
|
|
itemsArray?.forEach(({ Name, Progress }) => {
|
|
|
|
const itemIndex = category.findIndex(i => i.Name === Name);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
category[itemIndex].Progress += Progress;
|
|
|
|
inventory.markModified(`ChallengeProgress.${itemIndex}.ItemCount`);
|
|
|
|
} else {
|
|
|
|
category.push({ Name, Progress });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2025-01-03 22:17:34 +01:00
|
|
|
const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes }: IMission): void => {
|
2023-09-10 00:10:21 +04:00
|
|
|
const { Missions } = inventory;
|
|
|
|
const itemIndex = Missions.findIndex(item => item.Tag === Tag);
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
Missions[itemIndex].Completes += Completes;
|
|
|
|
inventory.markModified(`Missions.${itemIndex}.Completes`);
|
|
|
|
} else {
|
|
|
|
Missions.push({ Tag, Completes });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const missionInventoryUpdate = async (data: IMissionInventoryUpdateRequest, accountId: string) => {
|
2024-07-03 23:01:35 +02:00
|
|
|
const {
|
|
|
|
RawUpgrades,
|
|
|
|
MiscItems,
|
|
|
|
RegularCredits,
|
|
|
|
ChallengeProgress,
|
|
|
|
FusionPoints,
|
|
|
|
Consumables,
|
|
|
|
Recipes,
|
|
|
|
Missions,
|
|
|
|
FusionTreasures
|
|
|
|
} = data;
|
2023-08-31 14:29:09 +04:00
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
|
2023-09-06 14:02:54 +04:00
|
|
|
// credits
|
|
|
|
inventory.RegularCredits += RegularCredits || 0;
|
|
|
|
|
|
|
|
// endo
|
|
|
|
inventory.FusionPoints += FusionPoints || 0;
|
|
|
|
|
2024-06-02 18:35:06 +03:00
|
|
|
// syndicate
|
|
|
|
data.AffiliationChanges?.forEach(affiliation => {
|
|
|
|
const syndicate = inventory.Affiliations.find(x => x.Tag == affiliation.Tag);
|
|
|
|
if (syndicate !== undefined) {
|
|
|
|
syndicate.Standing =
|
|
|
|
syndicate.Standing === undefined ? affiliation.Standing : syndicate.Standing + affiliation.Standing;
|
|
|
|
syndicate.Title = syndicate.Title === undefined ? affiliation.Title : syndicate.Title + affiliation.Title;
|
|
|
|
} else {
|
|
|
|
inventory.Affiliations.push({
|
|
|
|
Standing: affiliation.Standing,
|
|
|
|
Title: affiliation.Title,
|
|
|
|
Tag: affiliation.Tag,
|
|
|
|
FreeFavorsEarned: [],
|
|
|
|
FreeFavorsUsed: []
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-09-05 07:37:30 -05:00
|
|
|
// Gear XP
|
2024-06-29 13:55:15 +02:00
|
|
|
equipmentKeys.forEach(key => addGearExpByCategory(inventory, data[key], key));
|
2023-08-31 14:29:09 +04:00
|
|
|
|
2024-06-20 13:05:07 +02:00
|
|
|
// Incarnon Challenges
|
|
|
|
if (data.EvolutionProgress) {
|
|
|
|
for (const evoProgress of data.EvolutionProgress) {
|
|
|
|
const entry = inventory.EvolutionProgress
|
|
|
|
? inventory.EvolutionProgress.find(entry => entry.ItemType == evoProgress.ItemType)
|
|
|
|
: undefined;
|
|
|
|
if (entry) {
|
|
|
|
entry.Progress = evoProgress.Progress;
|
|
|
|
entry.Rank = evoProgress.Rank;
|
|
|
|
} else {
|
|
|
|
inventory.EvolutionProgress ??= [];
|
|
|
|
inventory.EvolutionProgress.push(evoProgress);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-29 13:50:32 +02:00
|
|
|
// LastRegionPlayed
|
|
|
|
if (data.LastRegionPlayed) {
|
|
|
|
inventory.LastRegionPlayed = data.LastRegionPlayed;
|
|
|
|
}
|
|
|
|
|
2023-09-06 14:02:54 +04:00
|
|
|
// other
|
|
|
|
addMods(inventory, RawUpgrades);
|
|
|
|
addMiscItems(inventory, MiscItems);
|
|
|
|
addConsumables(inventory, Consumables);
|
|
|
|
addRecipes(inventory, Recipes);
|
2023-08-31 14:29:09 +04:00
|
|
|
addChallenges(inventory, ChallengeProgress);
|
2024-07-03 23:01:35 +02:00
|
|
|
addFusionTreasures(inventory, FusionTreasures);
|
2024-05-06 15:07:36 +02:00
|
|
|
if (Missions) {
|
|
|
|
addMissionComplete(inventory, Missions);
|
|
|
|
}
|
2023-08-31 14:29:09 +04:00
|
|
|
|
2023-09-06 14:02:54 +04:00
|
|
|
const changedInventory = await inventory.save();
|
|
|
|
return changedInventory.toJSON();
|
2023-08-31 14:29:09 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
export const addBooster = async (ItemType: string, time: number, accountId: string): Promise<void> => {
|
2023-09-05 07:37:30 -05:00
|
|
|
const currentTime = Math.floor(Date.now() / 1000) - 129600; // Value is wrong without 129600. Figure out why, please. :)
|
2023-08-31 14:29:09 +04:00
|
|
|
|
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
const { Boosters } = inventory;
|
|
|
|
|
2023-09-06 14:02:54 +04:00
|
|
|
const itemIndex = Boosters.findIndex(booster => booster.ItemType === ItemType);
|
2023-08-31 14:29:09 +04:00
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
const existingBooster = Boosters[itemIndex];
|
|
|
|
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time;
|
|
|
|
inventory.markModified(`Boosters.${itemIndex}.ExpiryDate`);
|
|
|
|
} else {
|
2025-01-04 00:25:09 +01:00
|
|
|
Boosters.push({ ItemType, ExpiryDate: currentTime + time });
|
2023-08-31 14:29:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
await inventory.save();
|
|
|
|
};
|
|
|
|
|
2023-09-10 00:10:21 +04:00
|
|
|
export const upgradeMod = async (artifactsData: IArtifactsRequest, accountId: string): Promise<string | undefined> => {
|
|
|
|
const { Upgrade, LevelDiff, Cost, FusionPointCost } = artifactsData;
|
2023-09-06 14:02:54 +04:00
|
|
|
try {
|
|
|
|
const inventory = await getInventory(accountId);
|
|
|
|
const { Upgrades, RawUpgrades } = inventory;
|
|
|
|
const { ItemType, UpgradeFingerprint, ItemId } = Upgrade;
|
|
|
|
|
|
|
|
const safeUpgradeFingerprint = UpgradeFingerprint || '{"lvl":0}';
|
2024-12-29 21:40:38 +01:00
|
|
|
const parsedUpgradeFingerprint = JSON.parse(safeUpgradeFingerprint) as { lvl: number };
|
2023-09-06 14:02:54 +04:00
|
|
|
parsedUpgradeFingerprint.lvl += LevelDiff;
|
|
|
|
const stringifiedUpgradeFingerprint = JSON.stringify(parsedUpgradeFingerprint);
|
|
|
|
|
|
|
|
let itemIndex = Upgrades.findIndex(upgrade => upgrade._id?.equals(ItemId!.$oid));
|
|
|
|
|
|
|
|
if (itemIndex !== -1) {
|
|
|
|
Upgrades[itemIndex].UpgradeFingerprint = stringifiedUpgradeFingerprint;
|
|
|
|
inventory.markModified(`Upgrades.${itemIndex}.UpgradeFingerprint`);
|
|
|
|
} else {
|
|
|
|
itemIndex =
|
|
|
|
Upgrades.push({
|
|
|
|
UpgradeFingerprint: stringifiedUpgradeFingerprint,
|
|
|
|
ItemType
|
|
|
|
}) - 1;
|
|
|
|
|
|
|
|
const rawItemIndex = RawUpgrades.findIndex(rawUpgrade => rawUpgrade.ItemType === ItemType);
|
|
|
|
RawUpgrades[rawItemIndex].ItemCount--;
|
|
|
|
if (RawUpgrades[rawItemIndex].ItemCount > 0) {
|
|
|
|
inventory.markModified(`RawUpgrades.${rawItemIndex}.UpgradeFingerprint`);
|
|
|
|
} else {
|
|
|
|
RawUpgrades.splice(rawItemIndex, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-06 05:36:39 +01:00
|
|
|
if (!config.infiniteCredits) {
|
|
|
|
inventory.RegularCredits -= Cost;
|
|
|
|
}
|
|
|
|
if (!config.infiniteEndo) {
|
|
|
|
inventory.FusionPoints -= FusionPointCost;
|
|
|
|
}
|
2023-09-06 14:02:54 +04:00
|
|
|
|
|
|
|
const changedInventory = await inventory.save();
|
|
|
|
const itemId = changedInventory.toJSON().Upgrades[itemIndex]?.ItemId?.$oid;
|
|
|
|
|
|
|
|
if (!itemId) {
|
|
|
|
throw new Error("Item Id not found in upgradeMod");
|
|
|
|
}
|
|
|
|
|
|
|
|
return itemId;
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error in upgradeMod:", error);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
};
|