From a2a159f26106e8b732d7cd63c25a89383517de8a Mon Sep 17 00:00:00 2001 From: Sainan Date: Sun, 5 Jan 2025 10:13:55 +0100 Subject: [PATCH] feat: spectre loadouts --- .../api/claimCompletedRecipeController.ts | 24 +++++++++ src/controllers/api/startRecipeController.ts | 54 +++++++++++++++++++ src/models/inventoryModels/inventoryModel.ts | 21 ++++---- src/types/inventoryTypes/inventoryTypes.ts | 17 +++--- 4 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/controllers/api/claimCompletedRecipeController.ts b/src/controllers/api/claimCompletedRecipeController.ts index 5b8e048e..179327da 100644 --- a/src/controllers/api/claimCompletedRecipeController.ts +++ b/src/controllers/api/claimCompletedRecipeController.ts @@ -59,6 +59,30 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) = }); } else { logger.debug("Claiming Recipe", { recipe, pendingRecipe }); + + if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") { + const inventory = await getInventory(accountId); + inventory.PendingSpectreLoadouts ??= []; + inventory.SpectreLoadouts ??= []; + + const pendingLoadoutIndex = inventory.PendingSpectreLoadouts.findIndex( + x => x.ItemType == recipe.resultType + ); + if (pendingLoadoutIndex != -1) { + const loadoutIndex = inventory.SpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType); + if (loadoutIndex != -1) { + inventory.SpectreLoadouts.splice(loadoutIndex, 1); + } + logger.debug( + "moving spectre loadout from pending to active", + inventory.toJSON().PendingSpectreLoadouts![pendingLoadoutIndex] + ); + inventory.SpectreLoadouts.push(inventory.PendingSpectreLoadouts[pendingLoadoutIndex]); + inventory.PendingSpectreLoadouts.splice(pendingLoadoutIndex, 1); + await inventory.save(); + } + } + let InventoryChanges = {}; if (recipe.consumeOnUse) { const recipeChanges = [ diff --git a/src/controllers/api/startRecipeController.ts b/src/controllers/api/startRecipeController.ts index 83501874..4a511315 100644 --- a/src/controllers/api/startRecipeController.ts +++ b/src/controllers/api/startRecipeController.ts @@ -6,6 +6,7 @@ import { getRecipe } from "@/src/services/itemDataService"; import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService"; import { unixTimesInMs } from "@/src/constants/timeConstants"; import { Types } from "mongoose"; +import { ISpectreLoadout } from "@/src/types/inventoryTypes/inventoryTypes"; interface IStartRecipeRequest { RecipeName: string; @@ -43,6 +44,59 @@ export const startRecipeController: RequestHandler = async (req, res) => { _id: new Types.ObjectId() }); + if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") { + const spectreLoadout: ISpectreLoadout = { + ItemType: recipe.resultType, + Suits: "", + LongGuns: "", + Pistols: "", + Melee: "" + }; + for ( + let secretIngredientsIndex = 0; + secretIngredientsIndex != recipe.secretIngredients!.length; + ++secretIngredientsIndex + ) { + const type = recipe.secretIngredients![secretIngredientsIndex].ItemType; + const oid = startRecipeRequest.Ids[recipe.ingredients.length + secretIngredientsIndex]; + if (oid == "ffffffffffffffffffffffff") { + // user chose to preserve the active loadout + break; + } + if (type == "/Lotus/Types/Game/PowerSuits/PlayerPowerSuit") { + const item = inventory.Suits.find(x => x._id.toString() == oid)!; + spectreLoadout.Suits = item.ItemType; + } else if (type == "/Lotus/Weapons/Tenno/Pistol/LotusPistol") { + const item = inventory.Pistols.find(x => x._id.toString() == oid)!; + spectreLoadout.Pistols = item.ItemType; + spectreLoadout.PistolsModularParts = item.ModularParts; + } else if (type == "/Lotus/Weapons/Tenno/LotusLongGun") { + const item = inventory.LongGuns.find(x => x._id.toString() == oid)!; + spectreLoadout.LongGuns = item.ItemType; + spectreLoadout.LongGunsModularParts = item.ModularParts; + } else { + console.assert(type == "/Lotus/Types/Game/LotusMeleeWeapon"); + const item = inventory.Melee.find(x => x._id.toString() == oid)!; + spectreLoadout.Melee = item.ItemType; + spectreLoadout.MeleeModularParts = item.ModularParts; + } + } + if ( + spectreLoadout.Suits != "" && + spectreLoadout.LongGuns != "" && + spectreLoadout.Pistols != "" && + spectreLoadout.Melee != "" + ) { + inventory.PendingSpectreLoadouts ??= []; + const existingIndex = inventory.PendingSpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType); + if (existingIndex != -1) { + inventory.PendingSpectreLoadouts.splice(existingIndex, 1); + } + inventory.PendingSpectreLoadouts.push(spectreLoadout); + logger.debug("pending spectre loadout", spectreLoadout); + } + } + const newInventory = await inventory.save(); res.json({ diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 7c8d5b75..2ab583c1 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -532,13 +532,14 @@ const fusionTreasuresSchema = new Schema().add(typeCountSchema) const spectreLoadoutsSchema = new Schema( { - LongGuns: String, - Melee: String, - Pistols: String, - PistolsFeatures: Number, - PistolsModularParts: [String], + ItemType: String, Suits: String, - ItemType: String + LongGuns: String, + LongGunsModularParts: { type: [String], default: undefined }, + Pistols: String, + PistolsModularParts: { type: [String], default: undefined }, + Melee: String, + MeleeModularParts: { type: [String], default: undefined } }, { _id: false } ); @@ -920,11 +921,9 @@ const inventorySchema = new Schema( QualifyingInvasions: [Schema.Types.Mixed], FactionScores: [Number], - //Have only Suit+Pistols+LongGuns+Melee+ItemType(BronzeSpectre,GoldSpectre,PlatinumSpectreArmy,SilverSpectreArmy) - //"/Lotus/Types/Game/SpectreArmies/BronzeSpectreArmy": "Vapor Specter Regiment", - SpectreLoadouts: [spectreLoadoutsSchema], - //If you want change Spectre Gear id - PendingSpectreLoadouts: [Schema.Types.Mixed], + // https://warframe.fandom.com/wiki/Specter_(Tenno) + PendingSpectreLoadouts: { type: [spectreLoadoutsSchema], default: undefined }, + SpectreLoadouts: { type: [spectreLoadoutsSchema], default: undefined }, //New Quest Email EmailItems: [TypeXPItemSchema], diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index 6d6dd9bc..90ab9d5c 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -203,8 +203,8 @@ export interface IInventoryResponse { SpaceMelee: IEquipmentDatabase[]; SpaceGuns: IEquipmentDatabase[]; ArchwingEnabled: boolean; - PendingSpectreLoadouts: any[]; - SpectreLoadouts: ISpectreLoadout[]; + PendingSpectreLoadouts?: ISpectreLoadout[]; + SpectreLoadouts?: ISpectreLoadout[]; SentinelWeapons: IEquipmentDatabase[]; Sentinels: IEquipmentDatabase[]; EmailItems: ITypeCount[]; @@ -869,13 +869,14 @@ export interface IShipInventory { } export interface ISpectreLoadout { - LongGuns: string; - Melee: string; - Pistols: string; - PistolsFeatures: number; - PistolsModularParts: string[]; - Suits: string; ItemType: string; + Suits: string; + LongGuns: string; + LongGunsModularParts?: string[]; + Pistols: string; + PistolsModularParts?: string[]; + Melee: string; + MeleeModularParts?: string[]; } export interface IStepSequencer {