import { config } from "@/src/services/configService"; import { toOid } from "@/src/helpers/inventoryHelpers"; import { IOid } from "@/src/types/commonTypes"; import { Types } from "mongoose"; import { RequestHandler } from "express"; import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes"; import { IDailyAffiliations, IInventoryClient, IPlayerSkills, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes"; import { addConsumables, addKeyChainItems, addMods, getInventory } from "@/src/services/inventoryService"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { getAccountIdForRequest } from "@/src/services/loginService"; export const giveStartingGearController: RequestHandler = async (req, res) => { const accountId = await getAccountIdForRequest(req); const inventory = await getInventory(accountId); const dataJSON = getJSONfromString(String(req.body)); for (const key of Object.keys(dataJSON) as Array) { switch (key) { // This is the only gear we receive as the rest will come from future quests case "LongGuns": case "Pistols": case "Melee": case "Suits": // Filter out already owned items (shouldnt happen but this was mostly for testing) const existingItems = new Set(inventory[key].map(item => item.ItemType)); // Adding items to inventory inventory[key].push( ...dataJSON[key] .filter(item => !existingItems.has(item.ItemType)) .map(x => ({ _id: new Types.ObjectId(), ItemType: x.ItemType, XP: x.XP, Configs: [{}, {}, {}] })) ); } } await addKeyChainItems(inventory, { KeyChain: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain", ChainStage: 0 }); addConsumables(inventory, [{ ItemCount: 1, ItemType: "/Lotus/Types/Restoratives/LisetAutoHack" }]); if (!config.unlockAllFlavourItems) { inventory.FlavourItems.push([ { ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1" }, { ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2" }, { ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3" }, { ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4" } ]); } addMods(inventory, [ { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarShieldMaxMod", LastAdded: toOid(new Types.ObjectId()) } ]); inventory.DrifterMelee.push({ ItemType: "/Lotus/Types/Friendly/PlayerControllable/Weapons/DuviriDualSwords", _id: new Types.ObjectId() }); inventory.PlayedParkourTutorial = true; inventory.ReceivedStartingGear = true; inventory.TrainingDate = new Date(); inventory.QuestKeys.push({ Progress: [{ i: true }], unlock: false, ItemType: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain" }); await inventory.save(); res.json({}); }; // Alot of stuff is not received in the request, instead of being redundant I will just omit an already created type (pain) interface IStartingGearClient extends Omit< IInventoryClient, | keyof IDailyAffiliations | "Missions" | "RandomUpgradesIdentified" | "LastRegionPlayed" | "TradesRemaining" | "DailyFocus" | "GiftsRemaining" | "HasOwnedVoidProjectionsPreviously" | "ChallengesFixVersion" | "ChallengeProgress" | "ReceivedStartingGear" | "PendingRecipes" | "PendingTrades" | "DeathMarks" | "WebFlags" | "CompletedAlerts" | "TauntHistory" | "StoryModeChoice" | "PeriodicMissionCompletions" | "ActiveDojoColorResearch" | "SentientSpawnChanceBoosters" | "SupportedSyndicate" | "Affiliations" | "QualifyingInvasions" | "FactionScores" | "ArchwingEnabled" | "PendingSpectreLoadouts" | "SpectreLoadouts" | "CompletedSyndicates" | "FocusXP" | "Alignment" | "CompletedSorties" | "LastSortieReward" | "ActiveAvatarImageType" | "DiscoveredMarkers" | "CompletedJobs" | "FocusAbility" | "HasContributedToDojo" | "HWIDProtectEnabled" | "AlignmentReplay" | "PersonalGoalProgress" | "ThemeStyle" | "ThemeBackground" | "ThemeSounds" | "BountyScore" | "ChallengeInstanceStates" | "LoginMilestoneRewards" | "NodeIntrosCompleted" | "GuildId" | "CompletedJobChains" | "SeasonChallengeHistory" | "EquippedInstrument" | "InvasionChainProgress" | "NemesisHistory" | "LastNemesisAllySpawnTime" | "Settings" | "PersonalTechProjects" | "PlayerSkills" | "TradeBannedUntil" | "PlayedParkourTutorial" | "SubscribedToEmailsPersonalized" | "BlessingCooldown" | "NemesisAbandonedRewards" | "LastInventorySync" | "NextRefill" | "CustomMarkers" | "ActiveLandscapeTraps" | "EvolutionProgress" | "RepVotes" | "UsedDailyDeals" | "LibraryPersonalTarget" | "LibraryPersonalProgress" | "CollectibleSeries" | "LibraryAvailableDailyTaskInfo" | "HasResetAccount" | "PendingCoupon" | "Harvestable" | "DeathSquadable" | "EndlessXP" | "DialogueHistory" > { LongGuns: IStartingGearItem[]; Melee: IStartingGearItem[]; Pistols: IStartingGearItem[]; Suits: IStartingGearItem[]; XPLost?: unknown[]; CrewShipFusionPoints?: number; PlayerSkillGains?: IPlayerSkills[]; // Lot's of unknown but these never receive data (at least not in this request) StrippedItems?: unknown[]; BonusMiscItems?: unknown[]; EmailItems: ITypeCount[]; OneTimePurchases?: unknown[]; Rating?: number; WishlistChanges?: unknown[]; RecentVendorPurchases: (string | number)[]; RemovedIdItems?: { ItemId: number }[]; SongChallenges?: unknown[]; } interface IStartingGearItem extends Omit< IEquipmentClient, | "_id" | "InfestationDate" | "InfestationDays" | "InfestationType" | "UnlockLevel" | "Weapon" | "Customization" | "RailjackImage" | "CrewMembers" | "Details" > { // Warframe sends an ItemId instead _id, it will be converted to _id before being pushed to the inventory ItemId: IOid; Favorite?: boolean; }