diff --git a/project/Server.code-workspace b/project/Server.code-workspace index 38ce6f32..2c833b46 100644 --- a/project/Server.code-workspace +++ b/project/Server.code-workspace @@ -21,12 +21,63 @@ "source.fixAll.eslint", "source.organizeImports.biome" ], + "cSpell.language": "en-GB", "cSpell.words": [ + "armor", + "asonline", + "behaviour", + "biomejs", + "botreload", + "currexp", + "currlvl", + "dbaeumer", "deathmatch", + "dprint", + "edgeofdarkness", + "fulfill", "gethideout", + "gifter", + "hpresource", + "inraid", + "isvalid", + "leftbehind", + "leveled", + "loadout", + "maxlvl", + "medkit", + "MEDSTATION", + "nextlvl", + "offraid", + "peacefullzryachiyevent", + "preparetoescape", + "prevexp", "profileid", + "Protobuf", + "pscav", + "Ragfair", + "Regen", "requestid", - "scavcase" + "sanitise", + "Sanitised", + "scav", + "scavcase", + "scavs", + "Spawnpoint", + "spawnpoints", + "sptbear", + "sptdeveloper", + "spteasystart", + "sptusec", + "sptzerotohero", + "stackcount", + "statustimer", + "Tarkov", + "toggleable", + "tooshort", + "unrestartable", + "usec", + "userbuilds", + "Wishlist" ] } } diff --git a/project/src/controllers/BotController.ts b/project/src/controllers/BotController.ts index d13136a2..c10640b4 100644 --- a/project/src/controllers/BotController.ts +++ b/project/src/controllers/BotController.ts @@ -43,7 +43,7 @@ export class BotController @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("ConfigServer") protected configServer: ConfigServer, @inject("ApplicationContext") protected applicationContext: ApplicationContext, - @inject("JsonUtil") protected jsonUtil: JsonUtil + @inject("JsonUtil") protected jsonUtil: JsonUtil, ) { this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); @@ -51,29 +51,29 @@ export class BotController } /** - * Return the number of bot loadout varieties to be generated - * @param type bot Type we want the loadout gen count for + * Return the number of bot load-out varieties to be generated + * @param type bot Type we want the load-out gen count for * @returns number of bots to generate */ public getBotPresetGenerationLimit(type: string): number { - const value = this.botConfig.presetBatch[(type === "assaultGroup") - ? "assault" - : type]; + const value = this.botConfig.presetBatch[ + (type === "assaultGroup") ? + "assault" : + type + ]; if (!value) { this.logger.warning(`No value found for bot type ${type}, defaulting to 30`); - return value; } - return value; } /** * Handle singleplayer/settings/bot/difficulty - * Get the core.json difficulty settings from database\bots + * Get the core.json difficulty settings from database/bots * @returns IBotCore */ public getBotCoreDifficulty(): IBotCore @@ -90,10 +90,14 @@ export class BotController */ public getBotDifficulty(type: string, difficulty: string): Difficulty { - const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue(); + const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue< + IGetRaidConfigurationRequestData + >(); if (!raidConfig) { - this.logger.error(this.localisationService.getText("bot-missing_application_context", "RAID_CONFIGURATION")); + this.logger.error( + this.localisationService.getText("bot-missing_application_context", "RAID_CONFIGURATION"), + ); } // Check value chosen in pre-raid difficulty dropdown @@ -101,7 +105,9 @@ export class BotController const botDifficultyDropDownValue = raidConfig.wavesSettings.botDifficulty.toLowerCase(); if (botDifficultyDropDownValue !== "asonline") { - difficulty = this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue); + difficulty = this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty( + botDifficultyDropDownValue, + ); } let difficultySettings: Difficulty; @@ -109,19 +115,31 @@ export class BotController switch (lowercasedBotType) { case this.pmcConfig.bearType.toLowerCase(): - difficultySettings = this.botDifficultyHelper.getPmcDifficultySettings("bear", difficulty, this.pmcConfig.usecType, this.pmcConfig.bearType); + difficultySettings = this.botDifficultyHelper.getPmcDifficultySettings( + "bear", + difficulty, + this.pmcConfig.usecType, + this.pmcConfig.bearType, + ); break; case this.pmcConfig.usecType.toLowerCase(): - difficultySettings = this.botDifficultyHelper.getPmcDifficultySettings("usec", difficulty, this.pmcConfig.usecType, this.pmcConfig.bearType); + difficultySettings = this.botDifficultyHelper.getPmcDifficultySettings( + "usec", + difficulty, + this.pmcConfig.usecType, + this.pmcConfig.bearType, + ); break; default: difficultySettings = this.botDifficultyHelper.getBotDifficultySettings(type, difficulty); - // Don't add pmcs to event enemies (e.g. gifter/peacefullzryachiyevent) + // Don't add PMCs to event enemies (e.g. gifter/peacefullzryachiyevent) if (!this.botConfig.botsToNotAddPMCsAsEnemiesTo.includes(type.toLowerCase())) { - this.botHelper.addBotToEnemyList(difficultySettings, [this.pmcConfig.bearType, this.pmcConfig.usecType], lowercasedBotType); + this.botHelper.addBotToEnemyList(difficultySettings, [ + this.pmcConfig.bearType, + this.pmcConfig.usecType, + ], lowercasedBotType); } - break; } @@ -149,7 +167,7 @@ export class BotController botRelativeLevelDeltaMax: this.pmcConfig.botRelativeLevelDeltaMax, botCountToGenerate: this.botConfig.presetBatch[condition.Role], botDifficulty: condition.Difficulty, - isPlayerScav: false + isPlayerScav: false, }; // Event bots need special actions to occur, set data up for them @@ -158,7 +176,9 @@ export class BotController { // Add eventRole data + reassign role property to be base type botGenerationDetails.eventRole = condition.Role; - botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot(botGenerationDetails.eventRole); + botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot( + botGenerationDetails.eventRole, + ); } // Custom map waves can have spt roles in them @@ -171,10 +191,10 @@ export class BotController // Loop over and make x bots for this condition let cacheKey = ""; - for (let i = 0; i < botGenerationDetails.botCountToGenerate; i ++) + for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) { const details = this.jsonUtil.clone(botGenerationDetails); - const botRole = (isEventBot) ? details.eventRole : details.role; + const botRole = isEventBot ? details.eventRole : details.role; // Roll chance to be pmc if type is allowed to be one const botConvertRateMinMax = this.pmcConfig.convertIntoPmcChance[botRole.toLowerCase()]; @@ -192,6 +212,7 @@ export class BotController } cacheKey = `${botRole}${details.botDifficulty}`; + // Check for bot in cache, add if not if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) { @@ -200,6 +221,7 @@ export class BotController this.botGenerationCacheService.storeBots(cacheKey, botsToAddToCache); } } + // Get bot from cache, add to return array const botToReturn = this.botGenerationCacheService.getBot(cacheKey); @@ -217,13 +239,13 @@ export class BotController } /** - * Get the difficulty passed in, if its not "asoline", get selected difficulty from config - * @param requestedDifficulty - * @returns + * Get the difficulty passed in, if its not "asonline", get selected difficulty from config + * @param requestedDifficulty + * @returns */ public getPMCDifficulty(requestedDifficulty: string): string { - // maybe retrun a random difficulty... + // Maybe return a random difficulty... if (this.pmcConfig.difficulty.toLowerCase() === "asonline") { return requestedDifficulty; @@ -245,20 +267,27 @@ export class BotController public getBotCap(): number { const defaultMapCapId = "default"; - const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue(); + const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue< + IGetRaidConfigurationRequestData + >(); if (!raidConfig) { this.logger.warning(this.localisationService.getText("bot-missing_saved_match_info")); } - const mapName = (raidConfig) - ? raidConfig.location - : defaultMapCapId; + const mapName = raidConfig ? + raidConfig.location : + defaultMapCapId; let botCap = this.botConfig.maxBotCap[mapName.toLowerCase()]; if (!botCap) { - this.logger.warning(this.localisationService.getText("bot-no_bot_cap_found_for_location", raidConfig.location.toLowerCase())); + this.logger.warning( + this.localisationService.getText( + "bot-no_bot_cap_found_for_location", + raidConfig.location.toLowerCase(), + ), + ); botCap = this.botConfig.maxBotCap[defaultMapCapId]; } @@ -269,7 +298,7 @@ export class BotController { return { pmc: this.pmcConfig.pmcType, - assault: this.botConfig.assaultBrainType + assault: this.botConfig.assaultBrainType, }; } } diff --git a/project/src/controllers/ClientLogController.ts b/project/src/controllers/ClientLogController.ts index f8c0b6dc..0db5d170 100644 --- a/project/src/controllers/ClientLogController.ts +++ b/project/src/controllers/ClientLogController.ts @@ -9,9 +9,9 @@ import { inject, injectable } from "tsyringe"; export class ClientLogController { constructor( - @inject("WinstonLogger") protected logger: ILogger + @inject("WinstonLogger") protected logger: ILogger, ) - { } + {} /** * Handle /singleplayer/log @@ -54,4 +54,4 @@ export class ClientLogController this.logger.info(message); } } -} \ No newline at end of file +} diff --git a/project/src/controllers/CustomizationController.ts b/project/src/controllers/CustomizationController.ts index 4cf18ea9..62fafde6 100644 --- a/project/src/controllers/CustomizationController.ts +++ b/project/src/controllers/CustomizationController.ts @@ -17,7 +17,7 @@ export class CustomizationController { protected readonly clothingIds = { lowerParentId: "5cd944d01388ce000a659df9", - upperParentId: "5cd944ca1388ce03a44dc2a4" + upperParentId: "5cd944ca1388ce03a44dc2a4", }; constructor( @@ -26,7 +26,7 @@ export class CustomizationController @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("SaveServer") protected saveServer: SaveServer, @inject("LocalisationService") protected localisationService: LocalisationService, - @inject("ProfileHelper") protected profileHelper: ProfileHelper + @inject("ProfileHelper") protected profileHelper: ProfileHelper, ) {} @@ -42,18 +42,22 @@ export class CustomizationController const templates = this.databaseServer.getTables().templates.customization; const suits = this.databaseServer.getTables().traders[traderID].suits; - // Get an inner join of clothing from templates.customization and ragmans suits array - const matchingSuits = suits.filter(x => x.suiteId in templates); + // Get an inner join of clothing from templates.customization and Ragman's suits array + const matchingSuits = suits.filter((x) => x.suiteId in templates); // Return all suits that have a side array containing the players side (usec/bear) - return matchingSuits.filter(x => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side)); + return matchingSuits.filter((x) => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side)); } /** * Handle CustomizationWear event * Equip one to many clothing items to player */ - public wearClothing(pmcData: IPmcData, wearClothingRequest: IWearClothingRequestData, sessionID: string): IItemEventRouterResponse + public wearClothing( + pmcData: IPmcData, + wearClothingRequest: IWearClothingRequestData, + sessionID: string, + ): IItemEventRouterResponse { for (const suitId of wearClothingRequest.suites) { @@ -85,7 +89,11 @@ export class CustomizationController * @param sessionId Session id * @returns IItemEventRouterResponse */ - public buyClothing(pmcData: IPmcData, buyClothingRequest: IBuyClothingRequestData, sessionId: string): IItemEventRouterResponse + public buyClothing( + pmcData: IPmcData, + buyClothingRequest: IBuyClothingRequestData, + sessionId: string, + ): IItemEventRouterResponse { const db = this.databaseServer.getTables(); const output = this.eventOutputHolder.getOutput(sessionId); @@ -93,7 +101,9 @@ export class CustomizationController const traderOffer = this.getTraderClothingOffer(sessionId, buyClothingRequest.offer); if (!traderOffer) { - this.logger.error(this.localisationService.getText("customisation-unable_to_find_suit_by_id", buyClothingRequest.offer)); + this.logger.error( + this.localisationService.getText("customisation-unable_to_find_suit_by_id", buyClothingRequest.offer), + ); return output; } @@ -102,7 +112,12 @@ export class CustomizationController if (this.outfitAlreadyPurchased(suitId, sessionId)) { const suitDetails = db.templates.customization[suitId]; - this.logger.error(this.localisationService.getText("customisation-item_already_purchased", {itemId: suitDetails._id, itemName: suitDetails._name})); + this.logger.error( + this.localisationService.getText("customisation-item_already_purchased", { + itemId: suitDetails._id, + itemName: suitDetails._name, + }), + ); return output; } @@ -118,7 +133,7 @@ export class CustomizationController protected getTraderClothingOffer(sessionId: string, offerId: string): ISuit { - return this.getAllTraderSuits(sessionId).find(x => x._id === offerId); + return this.getAllTraderSuits(sessionId).find((x) => x._id === offerId); } /** @@ -139,7 +154,12 @@ export class CustomizationController * @param clothingItems Clothing purchased * @param output Client response */ - protected payForClothingItems(sessionId: string, pmcData: IPmcData, clothingItems: ClothingItem[], output: IItemEventRouterResponse): void + protected payForClothingItems( + sessionId: string, + pmcData: IPmcData, + clothingItems: ClothingItem[], + output: IItemEventRouterResponse, + ): void { for (const sellItem of clothingItems) { @@ -154,12 +174,22 @@ export class CustomizationController * @param clothingItem Clothing item purchased * @param output Client response */ - protected payForClothingItem(sessionId: string, pmcData: IPmcData, clothingItem: ClothingItem, output: IItemEventRouterResponse): void + protected payForClothingItem( + sessionId: string, + pmcData: IPmcData, + clothingItem: ClothingItem, + output: IItemEventRouterResponse, + ): void { - const relatedItem = pmcData.Inventory.items.find(x => x._id === clothingItem.id); + const relatedItem = pmcData.Inventory.items.find((x) => x._id === clothingItem.id); if (!relatedItem) { - this.logger.error(this.localisationService.getText("customisation-unable_to_find_clothing_item_in_inventory", clothingItem.id)); + this.logger.error( + this.localisationService.getText( + "customisation-unable_to_find_clothing_item_in_inventory", + clothingItem.id, + ), + ); return; } @@ -179,7 +209,7 @@ export class CustomizationController parentId: relatedItem.parentId, slotId: relatedItem.slotId, location: relatedItem.location, - upd: { StackObjectsCount: relatedItem.upd.StackObjectsCount } + upd: {StackObjectsCount: relatedItem.upd.StackObjectsCount}, }); } } @@ -199,4 +229,4 @@ export class CustomizationController return result; } -} \ No newline at end of file +} diff --git a/project/src/controllers/DialogueController.ts b/project/src/controllers/DialogueController.ts index d50471a2..76bc8c09 100644 --- a/project/src/controllers/DialogueController.ts +++ b/project/src/controllers/DialogueController.ts @@ -37,7 +37,7 @@ export class DialogueController @inject("MailSendService") protected mailSendService: MailSendService, @inject("GiftService") protected giftService: GiftService, @inject("HashUtil") protected hashUtil: HashUtil, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); @@ -57,14 +57,13 @@ export class DialogueController * Handle client/friend/list * @returns IGetFriendListDataResponse */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getFriendList(sessionID: string): IGetFriendListDataResponse { // Force a fake friend called SPT into friend list return { Friends: [this.getSptFriendData()], Ignore: [], - InIgnoreList: [] + InIgnoreList: [], }; } @@ -104,7 +103,7 @@ export class DialogueController new: dialogue.new, attachmentsNew: dialogue.attachmentsNew, pinned: dialogue.pinned, - Users: this.getDialogueUsers(dialogue, dialogue.type, sessionID) + Users: this.getDialogueUsers(dialogue, dialogue.type, sessionID), }; return result; @@ -121,7 +120,9 @@ export class DialogueController const profile = this.saveServer.getProfile(sessionID); // User to user messages are special in that they need the player to exist in them, add if they don't - if (messageType === MessageType.USER_MESSAGE && !dialog.Users?.find(x => x._id === profile.characters.pmc._id)) + if ( + messageType === MessageType.USER_MESSAGE && !dialog.Users?.find((x) => x._id === profile.characters.pmc._id) + ) { if (!dialog.Users) { @@ -134,8 +135,8 @@ export class DialogueController Level: profile.characters.pmc.Info.Level, Nickname: profile.characters.pmc.Info.Nickname, Side: profile.characters.pmc.Info.Side, - MemberCategory: profile.characters.pmc.Info.MemberCategory - } + MemberCategory: profile.characters.pmc.Info.MemberCategory, + }, }); } @@ -144,14 +145,17 @@ export class DialogueController /** * Handle client/mail/dialog/view - * Handle player clicking 'messenger' and seeing all the messages they've recieved + * Handle player clicking 'messenger' and seeing all the messages they've received * Set the content of the dialogue on the details panel, showing all the messages * for the specified dialogue. * @param request Get dialog request * @param sessionId Session id * @returns IGetMailDialogViewResponseData object */ - public generateDialogueView(request: IGetMailDialogViewRequestData, sessionId: string): IGetMailDialogViewResponseData + public generateDialogueView( + request: IGetMailDialogViewRequestData, + sessionId: string, + ): IGetMailDialogViewResponseData { const dialogueId = request.dialogId; const fullProfile = this.saveServer.getProfile(sessionId); @@ -163,17 +167,17 @@ export class DialogueController // Set number of new attachments, but ignore those that have expired. dialogue.attachmentsNew = this.getUnreadMessagesWithAttachmentsCount(sessionId, dialogueId); - return { + return { messages: dialogue.messages, profiles: this.getProfilesForMail(fullProfile, dialogue.Users), - hasMessagesWithRewards: this.messagesHaveUncollectedRewards(dialogue.messages) + hasMessagesWithRewards: this.messagesHaveUncollectedRewards(dialogue.messages), }; } /** * Get dialog from player profile, create if doesn't exist * @param profile Player profile - * @param request get dialog request (params used when dialog doesnt exist in profile) + * @param request get dialog request (params used when dialog doesn't exist in profile) * @returns Dialogue */ protected getDialogByIdFromProfile(profile: IAkiProfile, request: IGetMailDialogViewRequestData): Dialogue @@ -186,7 +190,7 @@ export class DialogueController pinned: false, messages: [], new: 0, - type: request.type + type: request.type, }; if (request.type === MessageType.USER_MESSAGE) @@ -211,8 +215,8 @@ export class DialogueController { result.push(...dialogUsers); - // Player doesnt exist, add them in before returning - if (!result.find(x => x._id === fullProfile.info.id)) + // Player doesn't exist, add them in before returning + if (!result.find((x) => x._id === fullProfile.info.id)) { const pmcProfile = fullProfile.characters.pmc; result.push({ @@ -221,8 +225,8 @@ export class DialogueController Nickname: pmcProfile.Info.Nickname, Side: pmcProfile.Info.Side, Level: pmcProfile.Info.Level, - MemberCategory: pmcProfile.Info.MemberCategory - } + MemberCategory: pmcProfile.Info.MemberCategory, + }, }); } } @@ -258,7 +262,7 @@ export class DialogueController */ protected messagesHaveUncollectedRewards(messages: Message[]): boolean { - return messages.some(x => x.items?.data?.length > 0); + return messages.some((x) => x.items?.data?.length > 0); } /** @@ -274,7 +278,6 @@ export class DialogueController if (!dialog) { this.logger.error(`No dialog in profile: ${sessionId} found with id: ${dialogueId}`); - return; } @@ -288,7 +291,6 @@ export class DialogueController if (!dialog) { this.logger.error(`No dialog in profile: ${sessionId} found with id: ${dialogueId}`); - return; } @@ -307,7 +309,6 @@ export class DialogueController if (!dialogs) { this.logger.error(`No dialog object in profile: ${sessionId}`); - return; } @@ -323,7 +324,7 @@ export class DialogueController * Get all uncollected items attached to mail in a particular dialog * @param dialogueId Dialog to get mail attachments from * @param sessionId Session id - * @returns + * @returns */ public getAllAttachments(dialogueId: string, sessionId: string): IGetAllAttachmentsResponse { @@ -332,25 +333,23 @@ export class DialogueController if (!dialog) { this.logger.error(`No dialog in profile: ${sessionId} found with id: ${dialogueId}`); - return; } // Removes corner 'new messages' tag dialog.attachmentsNew = 0; - + const activeMessages = this.getActiveMessagesFromDialog(sessionId, dialogueId); const messagesWithAttachments = this.getMessagesWithAttachments(activeMessages); - return { + return { messages: messagesWithAttachments, profiles: [], - hasMessagesWithRewards: this.messagesHaveUncollectedRewards(messagesWithAttachments) + hasMessagesWithRewards: this.messagesHaveUncollectedRewards(messagesWithAttachments), }; } /** client/mail/msg/send */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public sendMessage(sessionId: string, request: ISendMessageRequest): string { this.mailSendService.sendPlayerMessageToNpc(sessionId, request.dialogId, request.text); @@ -372,48 +371,97 @@ export class DialogueController protected handleChatWithSPTFriend(sessionId: string, request: ISendMessageRequest): void { const sender = this.profileHelper.getPmcProfile(sessionId); - const sptFriendUser = this.getSptFriendData(); - const giftSent = this.giftService.sendGiftToPlayer(sessionId, request.text); - if (giftSent === GiftSentResult.SUCCESS) + if (giftSent === GiftSentResult.SUCCESS) { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["Hey! you got the right code!", "A secret code, how exciting!", "You found a gift code!"])); - + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue([ + "Hey! you got the right code!", + "A secret code, how exciting!", + "You found a gift code!", + ]), + ); return; } - if (giftSent === GiftSentResult.FAILED_GIFT_ALREADY_RECEIVED) + if (giftSent === GiftSentResult.FAILED_GIFT_ALREADY_RECEIVED) { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["Looks like you already used that code", "You already have that!!"])); - + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue(["Looks like you already used that code", "You already have that!!"]), + ); return; } - if (request.text.toLowerCase().includes("love you")) + if (request.text.toLowerCase().includes("love you")) { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["That's quite forward but i love you too in a purely chatbot-human way", "I love you too buddy :3!", "uwu", `love you too ${sender?.Info?.Nickname}`])); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue([ + "That's quite forward but i love you too in a purely chatbot-human way", + "I love you too buddy :3!", + "uwu", + `love you too ${sender?.Info?.Nickname}`, + ]), + ); } - if (request.text.toLowerCase() === "spt") + if (request.text.toLowerCase() === "spt") { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["Its me!!", "spt? i've heard of that project"])); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue(["Its me!!", "spt? i've heard of that project"]), + ); } - if (["hello", "hi", "sup", "yo", "hey"].includes(request.text.toLowerCase())) + if (["hello", "hi", "sup", "yo", "hey"].includes(request.text.toLowerCase())) { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["Howdy", "Hi", "Greetings", "Hello", "bonjor", "Yo", "Sup", "Heyyyyy", "Hey there", `Hello ${sender?.Info?.Nickname}`])); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue([ + "Howdy", + "Hi", + "Greetings", + "Hello", + "Bonjour", + "Yo", + "Sup", + "Heyyyyy", + "Hey there", + `Hello ${sender?.Info?.Nickname}`, + ]), + ); } - if (request.text.toLowerCase() === "nikita") + if (request.text.toLowerCase() === "nikita") { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["I know that guy!", "Cool guy, he made EFT!", "Legend", "Remember when he said webel-webel-webel-webel, classic nikita moment"])); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue([ + "I know that guy!", + "Cool guy, he made EFT!", + "Legend", + "Remember when he said webel-webel-webel-webel, classic nikita moment", + ]), + ); } - if (request.text.toLowerCase() === "are you a bot") + if (request.text.toLowerCase() === "are you a bot") { - this.mailSendService.sendUserMessageToPlayer(sessionId, sptFriendUser, this.randomUtil.getArrayValue(["beep boop", "**sad boop**", "probably", "sometimes", "yeah lol"])); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + sptFriendUser, + this.randomUtil.getArrayValue(["beep boop", "**sad boop**", "probably", "sometimes", "yeah lol"]), + ); } } @@ -425,8 +473,8 @@ export class DialogueController Level: 1, MemberCategory: MemberCategory.DEVELOPER, Nickname: this.coreConfig.sptFriendNickname, - Side: "Usec" - } + Side: "Usec", + }, }; } @@ -440,7 +488,7 @@ export class DialogueController { const timeNow = this.timeUtil.getTimestamp(); const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); - return dialogs[dialogueId].messages.filter(x => timeNow < (x.dt + x.maxStorageTime)); + return dialogs[dialogueId].messages.filter((x) => timeNow < (x.dt + x.maxStorageTime)); } /** @@ -450,7 +498,7 @@ export class DialogueController */ protected getMessagesWithAttachments(messages: Message[]): Message[] { - return messages.filter(x => x.items?.data?.length > 0); + return messages.filter((x) => x.items?.data?.length > 0); } /** @@ -497,4 +545,4 @@ export class DialogueController { return (this.timeUtil.getTimestamp()) > (message.dt + message.maxStorageTime); } -} \ No newline at end of file +} diff --git a/project/src/controllers/GameController.ts b/project/src/controllers/GameController.ts index 27f13b7a..cef02021 100644 --- a/project/src/controllers/GameController.ts +++ b/project/src/controllers/GameController.ts @@ -69,7 +69,7 @@ export class GameController @inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService, @inject("GiftService") protected giftService: GiftService, @inject("ApplicationContext") protected applicationContext: ApplicationContext, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.httpConfig = this.configServer.getConfig(ConfigTypes.HTTP); @@ -82,10 +82,10 @@ export class GameController public load(): void { - // Regenerate basecache now mods are loaded and game is starting - // Mods that add items and use the baseclass service generate the cache including their items, the next mod that add items gets left out,causing warnings + // Regenerate base cache now mods are loaded and game is starting + // Mods that add items and use the baseClass service generate the cache including their items, the next mod that + // add items gets left out,causing warnings this.itemBaseClassService.hydrateItemBaseClassCache(); - this.addCustomLooseLootPositions(); } @@ -121,9 +121,9 @@ export class GameController this.checkTraderRepairValuesExist(); - // repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in offraidData) - // Since we don't want to clutter the Quests list, we need to remove all completed (failed / successful) repeatable quests. - // We also have to remove the Counters from the repeatableQuests + // repeatableQuests are stored by in profile.Quests due to the responses of the client (e.g. Quests in + // offraidData). Since we don't want to clutter the Quests list, we need to remove all completed (failed or + // successful) repeatable quests. We also have to remove the Counters from the repeatableQuests if (sessionID) { const fullProfile = this.profileHelper.getFullProfile(sessionID); @@ -166,7 +166,7 @@ export class GameController this.profileFixerService.fixIncorrectAidValue(fullProfile); this.profileFixerService.migrateStatsToNewStructure(fullProfile); - + this.sendPraporGiftsToNewProfiles(pmcProfile); this.profileFixerService.checkForOrphanedModdedItems(sessionID, fullProfile); @@ -184,7 +184,7 @@ export class GameController this.hideoutHelper.unlockHideoutWallInProfile(pmcProfile); this.profileFixerService.addMissingIdsToBonuses(pmcProfile); } - + this.logProfileDetails(fullProfile); this.adjustLabsRaiderSpawnRate(); @@ -240,7 +240,9 @@ export class GameController const trader = this.databaseServer.getTables().traders[traderKey]; if (!trader?.base?.repair) { - this.logger.warning(`Trader ${trader.base._id} ${trader.base.name} is missing a repair object, adding in default values`); + this.logger.warning( + `Trader ${trader.base._id} ${trader.base.name} is missing a repair object, adding in default values`, + ); trader.base.repair = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair); return; @@ -248,8 +250,12 @@ export class GameController if (trader?.base?.repair?.quality) { - this.logger.warning(`Trader ${trader.base._id} ${trader.base.name} is missing a repair quality value, adding in default value`); - trader.base.repair.quality = this.jsonUtil.clone(this.databaseServer.getTables().traders.ragfair.base.repair.quality); + this.logger.warning( + `Trader ${trader.base._id} ${trader.base.name} is missing a repair quality value, adding in default value`, + ); + trader.base.repair.quality = this.jsonUtil.clone( + this.databaseServer.getTables().traders.ragfair.base.repair.quality, + ); } } } @@ -274,7 +280,9 @@ export class GameController for (const positionToAdd of positionsToAdd) { // Exists already, add new items to existing positions pool - const existingLootPosition = mapLooseLoot.spawnpoints.find(x => x.template.Id === positionToAdd.template.Id); + const existingLootPosition = mapLooseLoot.spawnpoints.find((x) => + x.template.Id === positionToAdd.template.Id + ); if (existingLootPosition) { existingLootPosition.template.Items.push(...positionToAdd.template.Items); @@ -283,7 +291,7 @@ export class GameController continue; } - // new postion, add entire object + // New position, add entire object mapLooseLoot.spawnpoints.push(positionToAdd); } } @@ -303,7 +311,7 @@ export class GameController const mapLootAdjustmentsDict = adjustments[mapId]; for (const lootKey in mapLootAdjustmentsDict) { - const lootPostionToAdjust = mapLooseLootData.spawnpoints.find(x => x.template.Id === lootKey); + const lootPostionToAdjust = mapLooseLootData.spawnpoints.find((x) => x.template.Id === lootKey); if (!lootPostionToAdjust) { this.logger.warning(`Unable to adjust loot position: ${lootKey} on map: ${mapId}`); @@ -314,24 +322,24 @@ export class GameController } } } - + protected setHideoutAreasAndCraftsTo40Secs(): void { - for (const hideoutProd of this.databaseServer.getTables().hideout.production) + for (const hideoutProd of this.databaseServer.getTables().hideout.production) { - if (hideoutProd.productionTime > 40) + if (hideoutProd.productionTime > 40) { hideoutProd.productionTime = 40; } } this.logger.warning("DEVELOPER: SETTING ALL HIDEOUT PRODUCTIONS TO 40 SECONDS"); - for (const hideoutArea of this.databaseServer.getTables().hideout.areas) + for (const hideoutArea of this.databaseServer.getTables().hideout.areas) { - for (const stageKey in hideoutArea.stages) + for (const stageKey in hideoutArea.stages) { const stage = hideoutArea.stages[stageKey]; - if (stage.constructionTime > 40) + if (stage.constructionTime > 40) { stage.constructionTime = 40; } @@ -339,9 +347,9 @@ export class GameController } this.logger.warning("DEVELOPER: SETTING ALL HIDEOUT AREAS TO 40 SECOND UPGRADES"); - for (const scavCaseCraft of this.databaseServer.getTables().hideout.scavcase) + for (const scavCaseCraft of this.databaseServer.getTables().hideout.scavcase) { - if (scavCaseCraft.ProductionTime > 40) + if (scavCaseCraft.ProductionTime > 40) { scavCaseCraft.ProductionTime = 40; } @@ -363,12 +371,14 @@ export class GameController const map: ILocationData = mapsDb[mapId]; if (!map) { - this.logger.warning(this.localisationService.getText("bot-unable_to_edit_limits_of_unknown_map", mapId)); + this.logger.warning( + this.localisationService.getText("bot-unable_to_edit_limits_of_unknown_map", mapId), + ); } for (const botToLimit of this.locationConfig.botTypeLimits[mapId]) { - const index = map.base.MinMaxBots.findIndex(x => x.WildSpawnType === botToLimit.type); + const index = map.base.MinMaxBots.findIndex((x) => x.WildSpawnType === botToLimit.type); if (index !== -1) { // Existing bot type found in MinMaxBots array, edit @@ -378,14 +388,12 @@ export class GameController } else { - map.base.MinMaxBots.push( - { - // Bot type not found, add new object - WildSpawnType: botToLimit.type, - min: botToLimit.min, - max: botToLimit.max - } - ); + // Bot type not found, add new object + map.base.MinMaxBots.push({ + WildSpawnType: botToLimit.type, + min: botToLimit.min, + max: botToLimit.max, + }); } } } @@ -412,12 +420,11 @@ export class GameController Trading: this.httpServerHelper.getBackendUrl(), Messaging: this.httpServerHelper.getBackendUrl(), Main: this.httpServerHelper.getBackendUrl(), - RagFair: this.httpServerHelper.getBackendUrl() + RagFair: this.httpServerHelper.getBackendUrl(), }, useProtobuf: false, - // eslint-disable-next-line @typescript-eslint/naming-convention utc_time: new Date().getTime() / 1000, - totalInGame: profile.Stats?.Eft?.TotalInGameTime ?? 0 + totalInGame: profile.Stats?.Eft?.TotalInGameTime ?? 0, }; return config; @@ -426,50 +433,43 @@ export class GameController /** * Handle client/server/list */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getServer(sessionId: string): IServerDetails[] { - return [ - { - ip: this.httpConfig.ip, - port: this.httpConfig.port - } - ]; + return [{ + ip: this.httpConfig.ip, + port: this.httpConfig.port, + }]; } /** * Handle client/match/group/current */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getCurrentGroup(sessionId: string): ICurrentGroupResponse { return { - squad: [] + squad: [], }; } /** * Handle client/checkVersion */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getValidGameVersion(sessionId: string): ICheckVersionResponse { return { isvalid: true, - latestVersion: this.coreConfig.compatibleTarkovVersion + latestVersion: this.coreConfig.compatibleTarkovVersion, }; } /** * Handle client/game/keepalive */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getKeepAlive(sessionId: string): IGameKeepAliveResponse { return { msg: "OK", - // eslint-disable-next-line @typescript-eslint/naming-convention - utc_time: new Date().getTime() / 1000 + utc_time: new Date().getTime() / 1000, }; } @@ -520,8 +520,8 @@ export class GameController /** * When player logs in, iterate over all active effects and reduce timer - * TODO - add body part HP regen - * @param pmcProfile + * // TODO: Add body part HP regeneration + * @param pmcProfile */ protected updateProfileHealthValues(pmcProfile: IPmcData): void { @@ -538,14 +538,23 @@ export class GameController let hpRegenPerHour = 456.6; // Set new values, whatever is smallest - energyRegenPerHour += pmcProfile.Bonuses.filter(x => x.type === "EnergyRegeneration").reduce((sum, curr) => sum + curr.value, 0); - hydrationRegenPerHour += pmcProfile.Bonuses.filter(x => x.type === "HydrationRegeneration").reduce((sum, curr) => sum + curr.value, 0); - hpRegenPerHour += pmcProfile.Bonuses.filter(x => x.type === "HealthRegeneration").reduce((sum, curr) => sum + curr.value, 0); + energyRegenPerHour += pmcProfile.Bonuses.filter((x) => x.type === "EnergyRegeneration").reduce( + (sum, curr) => sum + curr.value, + 0, + ); + hydrationRegenPerHour += pmcProfile.Bonuses.filter((x) => x.type === "HydrationRegeneration").reduce( + (sum, curr) => sum + curr.value, + 0, + ); + hpRegenPerHour += pmcProfile.Bonuses.filter((x) => x.type === "HealthRegeneration").reduce( + (sum, curr) => sum + curr.value, + 0, + ); if (pmcProfile.Health.Energy.Current !== pmcProfile.Health.Energy.Maximum) { // Set new value, whatever is smallest - pmcProfile.Health.Energy.Current += Math.round((energyRegenPerHour * (diffSeconds / 3600))); + pmcProfile.Health.Energy.Current += Math.round(energyRegenPerHour * (diffSeconds / 3600)); if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum) { pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum; @@ -554,7 +563,7 @@ export class GameController if (pmcProfile.Health.Hydration.Current !== pmcProfile.Health.Hydration.Maximum) { - pmcProfile.Health.Hydration.Current += Math.round((hydrationRegenPerHour * (diffSeconds / 3600))); + pmcProfile.Health.Hydration.Current += Math.round(hydrationRegenPerHour * (diffSeconds / 3600)); if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum) { pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum; @@ -565,17 +574,17 @@ export class GameController for (const bodyPartKey in pmcProfile.Health.BodyParts) { const bodyPart = pmcProfile.Health.BodyParts[bodyPartKey] as BodyPartHealth; - + // Check part hp if (bodyPart.Health.Current < bodyPart.Health.Maximum) { - bodyPart.Health.Current += Math.round((hpRegenPerHour * (diffSeconds / 3600))); + bodyPart.Health.Current += Math.round(hpRegenPerHour * (diffSeconds / 3600)); } if (bodyPart.Health.Current > bodyPart.Health.Maximum) { bodyPart.Health.Current = bodyPart.Health.Maximum; } - + // Look for effects if (Object.keys(bodyPart.Effects ?? {}).length > 0) { @@ -618,7 +627,9 @@ export class GameController const location: ILocationData = this.databaseServer.getTables().locations[locationKey]; if (!location.base) { - this.logger.warning(this.localisationService.getText("location-unable_to_fix_broken_waves_missing_base", locationKey)); + this.logger.warning( + this.localisationService.getText("location-unable_to_fix_broken_waves_missing_base", locationKey), + ); continue; } @@ -626,7 +637,9 @@ export class GameController { if ((wave.slots_max - wave.slots_min === 0)) { - this.logger.debug(`Fixed ${wave.WildSpawnType} Spawn: ${locationKey} wave: ${wave.number} of type: ${wave.WildSpawnType} in zone: ${wave.SpawnPoints} with Max Slots of ${wave.slots_max}`); + this.logger.debug( + `Fixed ${wave.WildSpawnType} Spawn: ${locationKey} wave: ${wave.number} of type: ${wave.WildSpawnType} in zone: ${wave.SpawnPoints} with Max Slots of ${wave.slots_max}`, + ); wave.slots_max++; } } @@ -673,7 +686,8 @@ export class GameController } /** - * Find and split waves with large numbers of bots into smaller waves - BSG appears to reduce the size of these waves to one bot when they're waiting to spawn for too long + * Find and split waves with large numbers of bots into smaller waves - BSG appears to reduce the size of these + * waves to one bot when they're waiting to spawn for too long */ protected splitBotWavesIntoSingleWaves(): void { @@ -689,18 +703,23 @@ export class GameController for (const wave of location.base.waves) { // Wave has size that makes it candidate for splitting - if (wave.slots_max - wave.slots_min >= this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold) + if ( + wave.slots_max - wave.slots_min >= + this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold + ) { // Get count of bots to be spawned in wave const waveSize = wave.slots_max - wave.slots_min; - + // Update wave to spawn single bot wave.slots_min = 1; wave.slots_max = 2; - + // Get index of wave const indexOfWaveToSplit = location.base.waves.indexOf(wave); - this.logger.debug(`Splitting map: ${location.base.Id} wave: ${indexOfWaveToSplit} with ${waveSize} bots`); + this.logger.debug( + `Splitting map: ${location.base.Id} wave: ${indexOfWaveToSplit} with ${waveSize} bots`, + ); // Add new waves to fill gap from bots we removed in above wave let wavesAddedCount = 0; @@ -716,20 +735,23 @@ export class GameController waveToAdd.number = index; } - // Place wave into array in just-edited postion + 1 + // Place wave into array in just-edited position + 1 location.base.waves.splice(index, 0, waveToAdd); wavesAddedCount++; } - // Update subsequent wave number property to accomodate the new waves - for (let index = indexOfWaveToSplit + wavesAddedCount + 1; index < location.base.waves.length; index++) + // Update subsequent wave number property to accommodate the new waves + for ( + let index = indexOfWaveToSplit + wavesAddedCount + 1; + index < location.base.waves.length; + index++ + ) { // Some waves have value of 0, leave them as-is if (location.base.waves[index].number !== 0) { location.base.waves[index].number += wavesAddedCount; } - } } } @@ -753,9 +775,13 @@ export class GameController for (const modKey in activeMods) { const modDetails = activeMods[modKey]; - if (fullProfile.aki.mods.some(x => x.author === modDetails.author - && x.name === modDetails.name - && x.version === modDetails.version)) + if ( + fullProfile.aki.mods.some((x) => + x.author === modDetails.author && + x.name === modDetails.name && + x.version === modDetails.version + ) + ) { // Exists already, skip continue; @@ -765,13 +791,13 @@ export class GameController author: modDetails.author, dateAdded: Date.now(), name: modDetails.name, - version: modDetails.version + version: modDetails.version, }); } } /** - * Check for any missing assorts inside each traders assort.json data, checking against traders qeustassort.json + * Check for any missing assorts inside each traders assort.json data, checking against traders questassort.json */ protected validateQuestAssortUnlocksExist(): void { @@ -788,19 +814,26 @@ export class GameController } // Merge started/success/fail quest assorts into one dictionary - const mergedQuestAssorts = { ...traderData.questassort["started"], ...traderData.questassort["success"], ...traderData.questassort["fail"]}; + const mergedQuestAssorts = { + ...traderData.questassort["started"], + ...traderData.questassort["success"], + ...traderData.questassort["fail"], + }; - // loop over all assorts for trader + // Loop over all assorts for trader for (const [assortKey, questKey] of Object.entries(mergedQuestAssorts)) { // Does assort key exist in trader assort file if (!traderAssorts.loyal_level_items[assortKey]) { - // reverse lookup of enum key by value + // Reverse lookup of enum key by value const messageValues = { traderName: Object.keys(Traders)[Object.values(Traders).indexOf(traderId)], - questName: quests[questKey]?.QuestName ?? "UNKNOWN"}; - this.logger.debug(this.localisationService.getText("assort-missing_quest_assort_unlock", messageValues)); + questName: quests[questKey]?.QuestName ?? "UNKNOWN", + }; + this.logger.debug( + this.localisationService.getText("assort-missing_quest_assort_unlock", messageValues), + ); } } } @@ -821,11 +854,11 @@ export class GameController { bots["bear"].firstName.push(playerName); } - + if (bots["usec"]) { bots["usec"].firstName.push(playerName); - } + } } } @@ -847,7 +880,7 @@ export class GameController */ protected removePraporTestMessage(): void { - // Iterate over all langauges (e.g. "en", "fr") + // Iterate over all languages (e.g. "en", "fr") for (const localeKey in this.databaseServer.getTables().locales.global) { this.databaseServer.getTables().locales.global[localeKey]["61687e2c3e526901fa76baf9"] = ""; @@ -860,7 +893,9 @@ export class GameController protected adjustLabsRaiderSpawnRate(): void { const labsBase = this.databaseServer.getTables().locations.laboratory.base; - const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter(x => x.TriggerId === "" && x.TriggerName === ""); + const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter((x) => + x.TriggerId === "" && x.TriggerName === "" + ); if (nonTriggerLabsBossSpawns) { for (const boss of nonTriggerLabsBossSpawns) @@ -878,4 +913,4 @@ export class GameController this.logger.debug(`Debug enabled: ${globalThis.G_DEBUG_CONFIGURATION}`); this.logger.debug(`Mods enabled: ${globalThis.G_MODS_ENABLED}`); } -} \ No newline at end of file +} diff --git a/project/src/controllers/HandbookController.ts b/project/src/controllers/HandbookController.ts index 96fdcdb2..d9a957da 100644 --- a/project/src/controllers/HandbookController.ts +++ b/project/src/controllers/HandbookController.ts @@ -8,12 +8,12 @@ export class HandbookController { constructor( @inject("DatabaseServer") protected databaseServer: DatabaseServer, - @inject("HandbookHelper") protected handbookHelper: HandbookHelper + @inject("HandbookHelper") protected handbookHelper: HandbookHelper, ) - { } + {} public load(): void { return; } -} \ No newline at end of file +} diff --git a/project/src/controllers/HealthController.ts b/project/src/controllers/HealthController.ts index 3060f102..5090b36f 100644 --- a/project/src/controllers/HealthController.ts +++ b/project/src/controllers/HealthController.ts @@ -31,7 +31,7 @@ export class HealthController @inject("InventoryHelper") protected inventoryHelper: InventoryHelper, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, - @inject("HealthHelper") protected healthHelper: HealthHelper + @inject("HealthHelper") protected healthHelper: HealthHelper, ) {} @@ -43,7 +43,13 @@ export class HealthController * @param addEffects Should effects found be added or removed from profile * @param deleteExistingEffects Should all prior effects be removed before apply new ones */ - public saveVitality(pmcData: IPmcData, info: ISyncHealthRequestData, sessionID: string, addEffects = true, deleteExistingEffects = true): void + public saveVitality( + pmcData: IPmcData, + info: ISyncHealthRequestData, + sessionID: string, + addEffects = true, + deleteExistingEffects = true, + ): void { this.healthHelper.saveVitality(pmcData, info, sessionID, addEffects, deleteExistingEffects); } @@ -60,10 +66,13 @@ export class HealthController const output = this.eventOutputHolder.getOutput(sessionID); // Update medkit used (hpresource) - const healingItemToUse = pmcData.Inventory.items.find(item => item._id === request.item); + const healingItemToUse = pmcData.Inventory.items.find((item) => item._id === request.item); if (!healingItemToUse) { - const errorMessage = this.localisationService.getText("health-healing_item_not_found", healingItemToUse._id); + const errorMessage = this.localisationService.getText( + "health-healing_item_not_found", + healingItemToUse._id, + ); this.logger.error(errorMessage); return this.httpResponse.appendErrorToOutput(output, errorMessage); @@ -82,8 +91,8 @@ export class HealthController else { // Get max healing from db - const maxhp = this.itemHelper.getItem(healingItemToUse._tpl)[1]._props.MaxHpResource; - healingItemToUse.upd.MedKit = { HpResource: maxhp - request.count }; // Subtract amout used from max + const maxHp = this.itemHelper.getItem(healingItemToUse._tpl)[1]._props.MaxHpResource; + healingItemToUse.upd.MedKit = {HpResource: maxHp - request.count}; // Subtract amount used from max } // Resource in medkit is spent, delete it @@ -108,11 +117,14 @@ export class HealthController let output = this.eventOutputHolder.getOutput(sessionID); let resourceLeft = 0; - const itemToConsume = pmcData.Inventory.items.find(x => x._id === request.item); + const itemToConsume = pmcData.Inventory.items.find((x) => x._id === request.item); if (!itemToConsume) { // Item not found, very bad - return this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("health-unable_to_find_item_to_consume", request.item)); + return this.httpResponse.appendErrorToOutput( + output, + this.localisationService.getText("health-unable_to_find_item_to_consume", request.item), + ); } const consumedItemMaxResource = this.itemHelper.getItem(itemToConsume._tpl)[1]._props.MaxResource; @@ -120,7 +132,7 @@ export class HealthController { if (itemToConsume.upd.FoodDrink === undefined) { - itemToConsume.upd.FoodDrink = { HpPercent: consumedItemMaxResource - request.count }; + itemToConsume.upd.FoodDrink = {HpPercent: consumedItemMaxResource - request.count}; } else { @@ -138,7 +150,7 @@ export class HealthController return output; } - + /** * Handle RestoreHealth event * Occurs on post-raid healing page @@ -147,20 +159,21 @@ export class HealthController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public healthTreatment(pmcData: IPmcData, healthTreatmentRequest: IHealthTreatmentRequestData, sessionID: string): IItemEventRouterResponse + public healthTreatment( + pmcData: IPmcData, + healthTreatmentRequest: IHealthTreatmentRequestData, + sessionID: string, + ): IItemEventRouterResponse { let output = this.eventOutputHolder.getOutput(sessionID); const payMoneyRequest: IProcessBuyTradeRequestData = { Action: healthTreatmentRequest.Action, tid: Traders.THERAPIST, - // eslint-disable-next-line @typescript-eslint/naming-convention scheme_items: healthTreatmentRequest.items, type: "", - // eslint-disable-next-line @typescript-eslint/naming-convention item_id: "", count: 0, - // eslint-disable-next-line @typescript-eslint/naming-convention - scheme_id: 0 + scheme_id: 0, }; output = this.paymentService.payMoney(pmcData, payMoneyRequest, sessionID, output); @@ -175,7 +188,7 @@ export class HealthController const partRequest: BodyPart = healthTreatmentRequest.difference.BodyParts[bodyPartKey]; const profilePart = pmcData.Health.BodyParts[bodyPartKey]; - // Set profile bodypart to max + // Set profile body part to max profilePart.Health.Current = profilePart.Health.Maximum; // Check for effects to remove @@ -205,9 +218,8 @@ export class HealthController * applies skills from hideout workout. * @param pmcData Player profile * @param info Request data - * @param sessionID + * @param sessionID */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public applyWorkoutChanges(pmcData: IPmcData, info: IWorkoutData, sessionId: string): void { // https://dev.sp-tarkov.com/SPT-AKI/Server/issues/2674 @@ -215,4 +227,4 @@ export class HealthController // Health effects (fractures etc) are handled in /player/health/sync. pmcData.Skills.Common = info.skills.Common; } -} \ No newline at end of file +} diff --git a/project/src/controllers/HideoutController.ts b/project/src/controllers/HideoutController.ts index c7f58e1b..af7c6b62 100644 --- a/project/src/controllers/HideoutController.ts +++ b/project/src/controllers/HideoutController.ts @@ -69,7 +69,7 @@ export class HideoutController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("JsonUtil") protected jsonUtil: JsonUtil, - @inject("FenceService") protected fenceService: FenceService + @inject("FenceService") protected fenceService: FenceService, ) { this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT); @@ -83,15 +83,19 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public startUpgrade(pmcData: IPmcData, request: IHideoutUpgradeRequestData, sessionID: string): IItemEventRouterResponse + public startUpgrade( + pmcData: IPmcData, + request: IHideoutUpgradeRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - const items = request.items.map(reqItem => + const items = request.items.map((reqItem) => { - const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id); + const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id); return { inventoryItem: item, - requestedItem: reqItem + requestedItem: reqItem, }; }); @@ -100,14 +104,18 @@ export class HideoutController { if (!item.inventoryItem) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id), + ); return this.httpResponse.appendErrorToOutput(output); } - if (this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) - && item.inventoryItem.upd - && item.inventoryItem.upd.StackObjectsCount - && item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count) + if ( + this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) && + item.inventoryItem.upd && + item.inventoryItem.upd.StackObjectsCount && + item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count + ) { item.inventoryItem.upd.StackObjectsCount -= item.requestedItem.count; } @@ -118,17 +126,21 @@ export class HideoutController } // Construction time management - const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType); + const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); if (!hideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); return this.httpResponse.appendErrorToOutput(output); } - const hideoutData = this.databaseServer.getTables().hideout.areas.find(area => area.type === request.areaType); + const hideoutData = this.databaseServer.getTables().hideout.areas.find((area) => + area.type === request.areaType + ); if (!hideoutData) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -152,12 +164,16 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public upgradeComplete(pmcData: IPmcData, request: HideoutUpgradeCompleteRequestData, sessionID: string): IItemEventRouterResponse + public upgradeComplete( + pmcData: IPmcData, + request: HideoutUpgradeCompleteRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const db = this.databaseServer.getTables(); - const profileHideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType); + const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); if (!profileHideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); @@ -169,10 +185,12 @@ export class HideoutController profileHideoutArea.completeTime = 0; profileHideoutArea.constructing = false; - const hideoutData = db.hideout.areas.find(area => area.type === profileHideoutArea.type); + const hideoutData = db.hideout.areas.find((area) => area.type === profileHideoutArea.type); if (!hideoutData) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -190,18 +208,32 @@ export class HideoutController // Upgrade includes a container improvement/addition if (hideoutStage?.container) { - this.addContainerImprovementToProfile(output, sessionID, pmcData, profileHideoutArea, hideoutData, hideoutStage); + this.addContainerImprovementToProfile( + output, + sessionID, + pmcData, + profileHideoutArea, + hideoutData, + hideoutStage, + ); } // Upgrading water collector / med station - if (profileHideoutArea.type === HideoutAreas.WATER_COLLECTOR || profileHideoutArea.type === HideoutAreas.MEDSTATION) + if ( + profileHideoutArea.type === HideoutAreas.WATER_COLLECTOR || + profileHideoutArea.type === HideoutAreas.MEDSTATION + ) { this.checkAndUpgradeWall(pmcData); } // Add Skill Points Per Area Upgrade - this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, db.globals.config.SkillsSettings.HideoutManagement.SkillPointsPerAreaUpgrade); - + this.profileHelper.addSkillPointsToPlayer( + pmcData, + SkillTypes.HIDEOUT_MANAGEMENT, + db.globals.config.SkillsSettings.HideoutManagement.SkillPointsPerAreaUpgrade, + ); + return output; } @@ -211,11 +243,11 @@ export class HideoutController */ protected checkAndUpgradeWall(pmcData: IPmcData): void { - const medStation = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.MEDSTATION); - const waterCollector = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.WATER_COLLECTOR); + const medStation = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.MEDSTATION); + const waterCollector = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.WATER_COLLECTOR); if (medStation?.level >= 1 && waterCollector?.level >= 1) { - const wall = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.EMERGENCY_WALL); + const wall = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.EMERGENCY_WALL); if (wall?.level === 0) { wall.level = 3; @@ -224,7 +256,6 @@ export class HideoutController } /** - * * @param pmcData Profile to edit * @param output Object to send back to client * @param sessionID Session/player id @@ -232,7 +263,14 @@ export class HideoutController * @param dbHideoutArea Hideout area being upgraded * @param hideoutStage Stage hideout area is being upgraded to */ - protected addContainerImprovementToProfile(output: IItemEventRouterResponse, sessionID: string, pmcData: IPmcData, profileParentHideoutArea: HideoutArea, dbHideoutArea: IHideoutArea, hideoutStage: Stage): void + protected addContainerImprovementToProfile( + output: IItemEventRouterResponse, + sessionID: string, + pmcData: IPmcData, + profileParentHideoutArea: HideoutArea, + dbHideoutArea: IHideoutArea, + hideoutStage: Stage, + ): void { // Add key/value to `hideoutAreaStashes` dictionary - used to link hideout area to inventory stash by its id if (!pmcData.Inventory.hideoutAreaStashes[dbHideoutArea.type]) @@ -247,7 +285,9 @@ export class HideoutController this.addContainerUpgradeToClientOutput(output, sessionID, dbHideoutArea.type, dbHideoutArea, hideoutStage); // Some areas like gun stand have a child area linked to it, it needs to do the same as above - const childDbArea = this.databaseServer.getTables().hideout.areas.find(x => x.parentArea === dbHideoutArea._id); + const childDbArea = this.databaseServer.getTables().hideout.areas.find((x) => + x.parentArea === dbHideoutArea._id + ); if (childDbArea) { // Add key/value to `hideoutAreaStashes` dictionary - used to link hideout area to inventory stash by its id @@ -257,7 +297,9 @@ export class HideoutController } // Set child area level to same as parent area - pmcData.Hideout.Areas.find(x => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find(x => x.type === profileParentHideoutArea.type).level; + pmcData.Hideout.Areas.find((x) => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find((x) => + x.type === profileParentHideoutArea.type + ).level; // Add/upgrade stash item in player inventory const childDbAreaStage = childDbArea.stages[profileParentHideoutArea.level]; @@ -276,38 +318,41 @@ export class HideoutController */ protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void { - const existingInventoryItem = pmcData.Inventory.items.find(x => x._id === dbHideoutData._id); - if (existingInventoryItem) + const existingInventoryItem = pmcData.Inventory.items.find((x) => x._id === dbHideoutData._id); + if (existingInventoryItem) { // Update existing items container tpl to point to new id (tpl) existingInventoryItem._tpl = hideoutStage.container; - return; } // Add new item as none exists - pmcData.Inventory.items.push({ _id: dbHideoutData._id, _tpl: hideoutStage.container }); + pmcData.Inventory.items.push({_id: dbHideoutData._id, _tpl: hideoutStage.container}); } /** - * * @param output Objet to send to client * @param sessionID Session/player id * @param areaType Hideout area that had stash added * @param hideoutDbData Hideout area that caused addition of stash * @param hideoutStage Hideout area upgraded to this */ - protected addContainerUpgradeToClientOutput(output: IItemEventRouterResponse, sessionID: string, areaType: HideoutAreas, hideoutDbData: IHideoutArea, hideoutStage: Stage): void + protected addContainerUpgradeToClientOutput( + output: IItemEventRouterResponse, + sessionID: string, + areaType: HideoutAreas, + hideoutDbData: IHideoutArea, + hideoutStage: Stage, + ): void { if (!output.profileChanges[sessionID].changedHideoutStashes) { output.profileChanges[sessionID].changedHideoutStashes = {}; } - output.profileChanges[sessionID].changedHideoutStashes[areaType] = - { + output.profileChanges[sessionID].changedHideoutStashes[areaType] = { Id: hideoutDbData._id, - Tpl: hideoutStage.container + Tpl: hideoutStage.container, }; } @@ -315,28 +360,37 @@ export class HideoutController * Handle HideoutPutItemsInAreaSlots * Create item in hideout slot item array, remove item from player inventory * @param pmcData Profile data - * @param addItemToHideoutRequest reqeust from client to place item in area slot + * @param addItemToHideoutRequest request from client to place item in area slot * @param sessionID Session id * @returns IItemEventRouterResponse object */ - public putItemsInAreaSlots(pmcData: IPmcData, addItemToHideoutRequest: IHideoutPutItemInRequestData, sessionID: string): IItemEventRouterResponse + public putItemsInAreaSlots( + pmcData: IPmcData, + addItemToHideoutRequest: IHideoutPutItemInRequestData, + sessionID: string, + ): IItemEventRouterResponse { let output = this.eventOutputHolder.getOutput(sessionID); - const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map(kvp => + const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map((kvp) => { - const item = pmcData.Inventory.items.find(invItem => invItem._id === kvp[1]["id"]); + const item = pmcData.Inventory.items.find((invItem) => invItem._id === kvp[1]["id"]); return { inventoryItem: item, requestedItem: kvp[1], - slot: kvp[0] + slot: kvp[0], }; }); - const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === addItemToHideoutRequest.areaType); + const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === addItemToHideoutRequest.areaType); if (!hideoutArea) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_area_in_database", addItemToHideoutRequest.areaType)); + this.logger.error( + this.localisationService.getText( + "hideout-unable_to_find_area_in_database", + addItemToHideoutRequest.areaType, + ), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -344,21 +398,26 @@ export class HideoutController { if (!item.inventoryItem) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_item_in_inventory", {itemId: item.requestedItem["id"], area: hideoutArea.type})); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_item_in_inventory", { + itemId: item.requestedItem["id"], + area: hideoutArea.type, + }), + ); return this.httpResponse.appendErrorToOutput(output); } // Add item to area.slots const destinationLocationIndex = Number(item.slot); - const hideoutSlotIndex = hideoutArea.slots.findIndex(x => x.locationIndex === destinationLocationIndex); + const hideoutSlotIndex = hideoutArea.slots.findIndex((x) => x.locationIndex === destinationLocationIndex); hideoutArea.slots[hideoutSlotIndex].item = [{ _id: item.inventoryItem._id, _tpl: item.inventoryItem._tpl, - upd: item.inventoryItem.upd + upd: item.inventoryItem.upd, }]; output = this.inventoryHelper.removeItem(pmcData, item.inventoryItem._id, sessionID, output); - } + } // Trigger a forced update this.hideoutHelper.updatePlayerHideout(sessionID); @@ -374,11 +433,15 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public takeItemsFromAreaSlots(pmcData: IPmcData, request: IHideoutTakeItemOutRequestData, sessionID: string): IItemEventRouterResponse + public takeItemsFromAreaSlots( + pmcData: IPmcData, + request: IHideoutTakeItemOutRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType); + const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); if (!hideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); @@ -387,19 +450,30 @@ export class HideoutController if (!hideoutArea.slots || hideoutArea.slots.length === 0) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_item_to_remove_from_area", hideoutArea.type)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_item_to_remove_from_area", hideoutArea.type), + ); return this.httpResponse.appendErrorToOutput(output); } // Handle areas that have resources that can be placed in/taken out of slots from the area - if ([HideoutAreas.AIR_FILTERING, HideoutAreas.WATER_COLLECTOR, HideoutAreas.GENERATOR, HideoutAreas.BITCOIN_FARM].includes(hideoutArea.type)) + if ( + [ + HideoutAreas.AIR_FILTERING, + HideoutAreas.WATER_COLLECTOR, + HideoutAreas.GENERATOR, + HideoutAreas.BITCOIN_FARM, + ].includes(hideoutArea.type) + ) { const response = this.removeResourceFromArea(sessionID, pmcData, request, output, hideoutArea); this.update(); return response; } - throw new Error(this.localisationService.getText("hideout-unhandled_remove_item_from_area_request", hideoutArea.type)); + throw new Error( + this.localisationService.getText("hideout-unhandled_remove_item_from_area_request", hideoutArea.type), + ); } /** @@ -411,22 +485,36 @@ export class HideoutController * @param hideoutArea Area fuel is being removed from * @returns IItemEventRouterResponse response */ - protected removeResourceFromArea(sessionID: string, pmcData: IPmcData, removeResourceRequest: IHideoutTakeItemOutRequestData, output: IItemEventRouterResponse, hideoutArea: HideoutArea): IItemEventRouterResponse + protected removeResourceFromArea( + sessionID: string, + pmcData: IPmcData, + removeResourceRequest: IHideoutTakeItemOutRequestData, + output: IItemEventRouterResponse, + hideoutArea: HideoutArea, + ): IItemEventRouterResponse { const slotIndexToRemove = removeResourceRequest.slots[0]; - const itemToReturn = hideoutArea.slots.find(x => x.locationIndex === slotIndexToRemove).item[0]; - + const itemToReturn = hideoutArea.slots.find((x) => x.locationIndex === slotIndexToRemove).item[0]; + const newReq = { items: [{ // eslint-disable-next-line @typescript-eslint/naming-convention item_id: itemToReturn._tpl, - count: 1 + count: 1, }], - tid: "ragfair" + tid: "ragfair", }; - output = this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, null, !!itemToReturn.upd.SpawnedInSession, itemToReturn.upd); + output = this.inventoryHelper.addItem( + pmcData, + newReq, + output, + sessionID, + null, + !!itemToReturn.upd.SpawnedInSession, + itemToReturn.upd, + ); // If addItem returned with errors, drop out if (output.warnings && output.warnings.length > 0) @@ -435,7 +523,7 @@ export class HideoutController } // Remove items from slot, locationIndex remains - const hideoutSlotIndex = hideoutArea.slots.findIndex(x => x.locationIndex === slotIndexToRemove); + const hideoutSlotIndex = hideoutArea.slots.findIndex((x) => x.locationIndex === slotIndexToRemove); hideoutArea.slots[hideoutSlotIndex].item = undefined; return output; @@ -449,14 +537,18 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public toggleArea(pmcData: IPmcData, request: IHideoutToggleAreaRequestData, sessionID: string): IItemEventRouterResponse + public toggleArea( + pmcData: IPmcData, + request: IHideoutToggleAreaRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); // Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress) this.hideoutHelper.updatePlayerHideout(sessionID); - const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType); + const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType); if (!hideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); @@ -472,27 +564,31 @@ export class HideoutController * Handle HideoutSingleProductionStart event * Start production for an item from hideout area * @param pmcData Player profile - * @param body Start prodution of single item request + * @param body Start production of single item request * @param sessionID Session id * @returns IItemEventRouterResponse */ - public singleProductionStart(pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData, sessionID: string): IItemEventRouterResponse + public singleProductionStart( + pmcData: IPmcData, + body: IHideoutSingleProductionStartRequestData, + sessionID: string, + ): IItemEventRouterResponse { // Start production this.registerProduction(pmcData, body, sessionID); // Find the recipe of the production - const recipe = this.databaseServer.getTables().hideout.production.find(p => p._id === body.recipeId); + const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId); // Find the actual amount of items we need to remove because body can send weird data - const requirements = this.jsonUtil.clone(recipe.requirements.filter(i => i.type === "Item")); + const requirements = this.jsonUtil.clone(recipe.requirements.filter((i) => i.type === "Item")); const output = this.eventOutputHolder.getOutput(sessionID); for (const itemToDelete of body.items) { - const itemToCheck = pmcData.Inventory.items.find(i => i._id === itemToDelete.id); - const requirement = requirements.find(requirement => requirement.templateId === itemToCheck._tpl); + const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id); + const requirement = requirements.find((requirement) => requirement.templateId === itemToCheck._tpl); if (requirement.count <= 0) { continue; @@ -513,21 +609,32 @@ export class HideoutController * @param sessionID session id * @returns item event router response */ - public scavCaseProductionStart(pmcData: IPmcData, body: IHideoutScavCaseStartRequestData, sessionID: string): IItemEventRouterResponse + public scavCaseProductionStart( + pmcData: IPmcData, + body: IHideoutScavCaseStartRequestData, + sessionID: string, + ): IItemEventRouterResponse { let output = this.eventOutputHolder.getOutput(sessionID); for (const requestedItem of body.items) { - const inventoryItem = pmcData.Inventory.items.find(item => item._id === requestedItem.id); + const inventoryItem = pmcData.Inventory.items.find((item) => item._id === requestedItem.id); if (!inventoryItem) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_scavcase_requested_item_in_profile_inventory", requestedItem.id)); + this.logger.error( + this.localisationService.getText( + "hideout-unable_to_find_scavcase_requested_item_in_profile_inventory", + requestedItem.id, + ), + ); return this.httpResponse.appendErrorToOutput(output); } - if (inventoryItem.upd?.StackObjectsCount - && inventoryItem.upd.StackObjectsCount > requestedItem.count) + if ( + inventoryItem.upd?.StackObjectsCount && + inventoryItem.upd.StackObjectsCount > requestedItem.count + ) { inventoryItem.upd.StackObjectsCount -= requestedItem.count; } @@ -537,19 +644,25 @@ export class HideoutController } } - const recipe = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === body.recipeId); + const recipe = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === body.recipeId); if (!recipe) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_scav_case_recipie_in_database", body.recipeId)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_scav_case_recipie_in_database", body.recipeId), + ); return this.httpResponse.appendErrorToOutput(output); } - + // @Important: Here we need to be very exact: // - normal recipe: Production time value is stored in attribute "productionType" with small "p" // - scav case recipe: Production time value is stored in attribute "ProductionType" with capital "P" const modifiedScavCaseTime = this.getScavCaseTime(pmcData, recipe.ProductionTime); - pmcData.Hideout.Production[body.recipeId] = this.hideoutHelper.initProduction(body.recipeId, modifiedScavCaseTime, false); + pmcData.Hideout.Production[body.recipeId] = this.hideoutHelper.initProduction( + body.recipeId, + modifiedScavCaseTime, + false, + ); pmcData.Hideout.Production[body.recipeId].sptIsScavCase = true; return output; @@ -557,7 +670,7 @@ export class HideoutController /** * Adjust scav case time based on fence standing - * + * * @param pmcData Player profile * @param productionTime Time to complete scav case in seconds * @returns Adjusted scav case time in seconds @@ -569,7 +682,6 @@ export class HideoutController { return productionTime; } - return productionTime * fenceLevel.ScavCaseTimeModifier; } @@ -582,21 +694,24 @@ export class HideoutController protected addScavCaseRewardsToProfile(pmcData: IPmcData, rewards: Product[], recipeId: string): void { pmcData.Hideout.Production[`ScavCase${recipeId}`] = { - Products: rewards + Products: rewards, }; } /** * Start production of continuously created item * @param pmcData Player profile - * @param request Continious production request + * @param request Continuous production request * @param sessionID Session id * @returns IItemEventRouterResponse */ - public continuousProductionStart(pmcData: IPmcData, request: IHideoutContinuousProductionStartRequestData, sessionID: string): IItemEventRouterResponse + public continuousProductionStart( + pmcData: IPmcData, + request: IHideoutContinuousProductionStartRequestData, + sessionID: string, + ): IItemEventRouterResponse { this.registerProduction(pmcData, request, sessionID); - return this.eventOutputHolder.getOutput(sessionID); } @@ -608,7 +723,11 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public takeProduction(pmcData: IPmcData, request: IHideoutTakeProductionRequestData, sessionID: string): IItemEventRouterResponse + public takeProduction( + pmcData: IPmcData, + request: IHideoutTakeProductionRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); @@ -617,19 +736,24 @@ export class HideoutController return this.hideoutHelper.getBTC(pmcData, request, sessionID); } - const recipe = this.databaseServer.getTables().hideout.production.find(r => r._id === request.recipeId); + const recipe = this.databaseServer.getTables().hideout.production.find((r) => r._id === request.recipeId); if (recipe) { return this.handleRecipe(sessionID, recipe, pmcData, request, output); } - const scavCase = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === request.recipeId); + const scavCase = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === request.recipeId); if (scavCase) { return this.handleScavCase(sessionID, pmcData, request, output); } - this.logger.error(this.localisationService.getText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.recipeId)); + this.logger.error( + this.localisationService.getText( + "hideout-unable_to_find_production_in_profile_by_recipie_id", + request.recipeId, + ), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -643,9 +767,15 @@ export class HideoutController * @param output Output object to update * @returns IItemEventRouterResponse */ - protected handleRecipe(sessionID: string, recipe: IHideoutProduction, pmcData: IPmcData, request: IHideoutTakeProductionRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse + protected handleRecipe( + sessionID: string, + recipe: IHideoutProduction, + pmcData: IPmcData, + request: IHideoutTakeProductionRequestData, + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { - // Variables for managemnet of skill + // Variables for management of skill let craftingExpAmount = 0; // ? move the logic of BackendCounters in new method? @@ -654,12 +784,11 @@ export class HideoutController { pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting] = { id: HideoutController.nameBackendCountersCrafting, - value: 0 + value: 0, }; counterHoursCrafting = pmcData.BackendCounters[HideoutController.nameBackendCountersCrafting]; } let hoursCrafting = counterHoursCrafting.value; - // create item and throw it into profile let id = recipe.endProduct; @@ -672,18 +801,18 @@ export class HideoutController const newReq = { items: [{ - // eslint-disable-next-line @typescript-eslint/naming-convention item_id: id, - count: recipe.count + count: recipe.count, }], - tid: "ragfair" + tid: "ragfair", }; const entries = Object.entries(pmcData.Hideout.Production); let prodId: string; for (const x of entries) { - if (this.hideoutHelper.isProductionType(x[1])) // Production or ScavCase + // Production or ScavCase + if (this.hideoutHelper.isProductionType(x[1])) { if ((x[1] as Production).RecipeId === request.recipeId) { @@ -695,7 +824,12 @@ export class HideoutController if (prodId === undefined) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.recipeId)); + this.logger.error( + this.localisationService.getText( + "hideout-unable_to_find_production_in_profile_by_recipie_id", + request.recipeId, + ), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -712,9 +846,9 @@ export class HideoutController hoursCrafting += recipe.productionTime; if ((hoursCrafting / this.hideoutConfig.hoursForSkillCrafting) >= 1) { - const multiplierCrafting = Math.floor((hoursCrafting / this.hideoutConfig.hoursForSkillCrafting)); - craftingExpAmount += (1 * multiplierCrafting); - hoursCrafting -= (this.hideoutConfig.hoursForSkillCrafting * multiplierCrafting); + const multiplierCrafting = Math.floor(hoursCrafting / this.hideoutConfig.hoursForSkillCrafting); + craftingExpAmount += 1 * multiplierCrafting; + hoursCrafting -= this.hideoutConfig.hoursForSkillCrafting * multiplierCrafting; } // increment @@ -726,12 +860,21 @@ export class HideoutController // manager Hideout skill // ? use a configuration variable for the value? const globals = this.databaseServer.getTables().globals; - this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, globals.config.SkillsSettings.HideoutManagement.SkillPointsPerCraft, true); - //manager Crafting skill + this.profileHelper.addSkillPointsToPlayer( + pmcData, + SkillTypes.HIDEOUT_MANAGEMENT, + globals.config.SkillsSettings.HideoutManagement.SkillPointsPerCraft, + true, + ); + // manager Crafting skill if (craftingExpAmount > 0) { this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.CRAFTING, craftingExpAmount); - this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, 0.5 * (Math.round(craftingExpAmount / 15))); + this.profileHelper.addSkillPointsToPlayer( + pmcData, + SkillTypes.INTELLECT, + 0.5 * (Math.round(craftingExpAmount / 15)), + ); } area.lastRecipe = request.recipeId; counterHoursCrafting.value = hoursCrafting; @@ -747,7 +890,7 @@ export class HideoutController if (recipe.isEncoded) { const upd: Upd = { - RecodableComponent: { IsEncoded: true} + RecodableComponent: {IsEncoded: true}, }; return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, true, upd); @@ -764,13 +907,19 @@ export class HideoutController * @param output Output object to update * @returns IItemEventRouterResponse */ - protected handleScavCase(sessionID: string, pmcData: IPmcData, request: IHideoutTakeProductionRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse + protected handleScavCase( + sessionID: string, + pmcData: IPmcData, + request: IHideoutTakeProductionRequestData, + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { const ongoingProductions = Object.entries(pmcData.Hideout.Production); let prodId: string; for (const production of ongoingProductions) { - if (this.hideoutHelper.isProductionType(production[1])) // Production or ScavCase + // Production or ScavCase + if (this.hideoutHelper.isProductionType(production[1])) { if ((production[1] as ScavCase).RecipeId === request.recipeId) { @@ -782,7 +931,12 @@ export class HideoutController if (prodId === undefined) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.recipeId)); + this.logger.error( + this.localisationService.getText( + "hideout-unable_to_find_production_in_profile_by_recipie_id", + request.recipeId, + ), + ); return this.httpResponse.appendErrorToOutput(output); } @@ -795,28 +949,29 @@ export class HideoutController // Remove the old production from output object before its sent to client delete output.profileChanges[sessionID].production[request.recipeId]; - const itemsToAdd = pmcData.Hideout.Production[prodId].Products.map((x: { _tpl: string; upd?: { StackObjectsCount?: number; }; }) => - { - let id = x._tpl; - if (this.presetHelper.hasPreset(id)) + const itemsToAdd = pmcData.Hideout.Production[prodId].Products.map( + (x: {_tpl: string; upd?: {StackObjectsCount?: number;};}) => { - id = this.presetHelper.getDefaultPreset(id)._id; - } - const numOfItems = !x.upd?.StackObjectsCount - ? 1 - : x.upd.StackObjectsCount; - // eslint-disable-next-line @typescript-eslint/naming-convention - return { item_id: id, count: numOfItems }; - }); + let id = x._tpl; + if (this.presetHelper.hasPreset(id)) + { + id = this.presetHelper.getDefaultPreset(id)._id; + } + const numOfItems = !x.upd?.StackObjectsCount ? + 1 : + x.upd.StackObjectsCount; + + return {item_id: id, count: numOfItems}; + }, + ); const newReq = { items: itemsToAdd, - tid: "ragfair" + tid: "ragfair", }; const callback = () => { - // Null production data now it's complete - will be cleaned up later by update() process pmcData.Hideout.Production[prodId] = null; }; @@ -831,18 +986,21 @@ export class HideoutController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public registerProduction(pmcData: IPmcData, request: IHideoutSingleProductionStartRequestData | IHideoutContinuousProductionStartRequestData, sessionID: string): IItemEventRouterResponse + public registerProduction( + pmcData: IPmcData, + request: IHideoutSingleProductionStartRequestData | IHideoutContinuousProductionStartRequestData, + sessionID: string, + ): IItemEventRouterResponse { return this.hideoutHelper.registerProduction(pmcData, request, sessionID); } /** * Get quick time event list for hideout - * // TODO - implement this + * // TODO: Implement this * @param sessionId Session id * @returns IQteData array - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + */ public getQteList(sessionId: string): IQteData[] { return this.databaseServer.getTables().hideout.qte; @@ -855,8 +1013,11 @@ export class HideoutController * @param pmcData Profile to adjust * @param request QTE result object */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public handleQTEEventOutcome(sessionId: string, pmcData: IPmcData, request: IHandleQTEEventRequestData): IItemEventRouterResponse + public handleQTEEventOutcome( + sessionId: string, + pmcData: IPmcData, + request: IHandleQTEEventRequestData, + ): IItemEventRouterResponse { // { // Action: "HideoutQuickTimeEvent", @@ -865,7 +1026,7 @@ export class HideoutController // timestamp: 1672585349 // } - // Skill changes are done in + // Skill changes are done in // /client/hideout/workout (applyWorkoutChanges). pmcData.Health.Energy.Current -= 50; @@ -890,22 +1051,28 @@ export class HideoutController * @param request shooting range score request * @returns IItemEventRouterResponse */ - public recordShootingRangePoints(sessionId: string, pmcData: IPmcData, request: IRecordShootingRangePoints): IItemEventRouterResponse + public recordShootingRangePoints( + sessionId: string, + pmcData: IPmcData, + request: IRecordShootingRangePoints, + ): IItemEventRouterResponse { - // Check if counter exists, add placeholder if it doesnt - if (!pmcData.Stats.Eft.OverallCounters.Items.find(x => x.Key.includes("ShootingRangePoints"))) + // Check if counter exists, add placeholder if it doesn't + if (!pmcData.Stats.Eft.OverallCounters.Items.find((x) => x.Key.includes("ShootingRangePoints"))) { pmcData.Stats.Eft.OverallCounters.Items.push({ Key: ["ShootingRangePoints"], - Value: 0 + Value: 0, }); } // Find counter by key and update value - const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find(x => x.Key.includes("ShootingRangePoints")); + const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find((x) => + x.Key.includes("ShootingRangePoints") + ); shootingRangeHighScore.Value = request.points; - // Check against live, maybe a response isnt necessary + // Check against live, maybe a response isn't necessary return this.eventOutputHolder.getOutput(sessionId); } @@ -915,17 +1082,21 @@ export class HideoutController * @param pmcData Profile to improve area in * @param request Improve area request data */ - public improveArea(sessionId: string, pmcData: IPmcData, request: IHideoutImproveAreaRequestData): IItemEventRouterResponse + public improveArea( + sessionId: string, + pmcData: IPmcData, + request: IHideoutImproveAreaRequestData, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); - // Create mapping of required item with corrisponding item from player inventory - const items = request.items.map(reqItem => + // Create mapping of required item with corresponding item from player inventory + const items = request.items.map((reqItem) => { - const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id); + const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id); return { inventoryItem: item, - requestedItem: reqItem + requestedItem: reqItem, }; }); @@ -934,14 +1105,18 @@ export class HideoutController { if (!item.inventoryItem) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_item_in_inventory", item.requestedItem.id), + ); return this.httpResponse.appendErrorToOutput(output); } - if (this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) - && item.inventoryItem.upd - && item.inventoryItem.upd.StackObjectsCount - && item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count) + if ( + this.paymentHelper.isMoneyTpl(item.inventoryItem._tpl) && + item.inventoryItem.upd && + item.inventoryItem.upd.StackObjectsCount && + item.inventoryItem.upd.StackObjectsCount > item.requestedItem.count + ) { item.inventoryItem.upd.StackObjectsCount -= item.requestedItem.count; } @@ -951,21 +1126,23 @@ export class HideoutController } } - const profileHideoutArea = pmcData.Hideout.Areas.find(x => x.type === request.areaType); + const profileHideoutArea = pmcData.Hideout.Areas.find((x) => x.type === request.areaType); if (!profileHideoutArea) { this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType)); return this.httpResponse.appendErrorToOutput(output); } - const hideoutDbData = this.databaseServer.getTables().hideout.areas.find(x => x.type === request.areaType); + const hideoutDbData = this.databaseServer.getTables().hideout.areas.find((x) => x.type === request.areaType); if (!hideoutDbData) { - this.logger.error(this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType)); + this.logger.error( + this.localisationService.getText("hideout-unable_to_find_area_in_database", request.areaType), + ); return this.httpResponse.appendErrorToOutput(output); } - // Add all improvemets to output object + // Add all improvements to output object const improvements = hideoutDbData.stages[profileHideoutArea.level].improvements; const timestamp = this.timeUtil.getTimestamp(); for (const improvement of improvements) @@ -975,10 +1152,13 @@ export class HideoutController output.profileChanges[sessionId].improvements = {}; } - const improvementDetails = {completed: false, improveCompleteTimestamp: timestamp + improvement.improvementTime}; + const improvementDetails = { + completed: false, + improveCompleteTimestamp: timestamp + improvement.improvementTime, + }; output.profileChanges[sessionId].improvements[improvement.id] = improvementDetails; pmcData.Hideout.Improvement[improvement.id] = improvementDetails; - } + } return output; } @@ -990,7 +1170,11 @@ export class HideoutController * @param request Cancel production request data * @returns IItemEventRouterResponse */ - public cancelProduction(sessionId: string, pmcData: IPmcData, request: IHideoutCancelProductionRequestData): IItemEventRouterResponse + public cancelProduction( + sessionId: string, + pmcData: IPmcData, + request: IHideoutCancelProductionRequestData, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionId); @@ -1006,7 +1190,7 @@ export class HideoutController // Null out production data so client gets informed when response send back pmcData.Hideout.Production[request.recipeId] = null; - // TODO - handle timestamp somehow? + // TODO: handle timestamp somehow? return output; } diff --git a/project/src/controllers/InraidController.ts b/project/src/controllers/InraidController.ts index beda6701..682134e3 100644 --- a/project/src/controllers/InraidController.ts +++ b/project/src/controllers/InraidController.ts @@ -56,7 +56,7 @@ export class InraidController @inject("InsuranceService") protected insuranceService: InsuranceService, @inject("InRaidHelper") protected inRaidHelper: InRaidHelper, @inject("ApplicationContext") protected applicationContext: ApplicationContext, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP); @@ -124,7 +124,12 @@ export class InraidController // Check for exit status this.markOrRemoveFoundInRaidItems(postRaidRequest); - postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs(postRaidRequest.profile, postRaidRequest.profile.Inventory.items, serverPmcData.InsuredItems, postRaidRequest.profile.Inventory.fastPanel); + postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs( + postRaidRequest.profile, + postRaidRequest.profile.Inventory.items, + serverPmcData.InsuredItems, + postRaidRequest.profile.Inventory.fastPanel, + ); this.inRaidHelper.addUpdToMoneyFromRaid(postRaidRequest.profile.Inventory.items); // Purge profile of equipment/container items @@ -146,22 +151,30 @@ export class InraidController if (locationName === "lighthouse" && postRaidRequest.profile.Info.Side.toLowerCase() === "usec") { // Decrement counter if it exists, don't go below 0 - const remainingCounter = serverPmcData?.Stats.Eft.OverallCounters.Items.find(x => x.Key.includes("UsecRaidRemainKills")); + const remainingCounter = serverPmcData?.Stats.Eft.OverallCounters.Items.find((x) => + x.Key.includes("UsecRaidRemainKills") + ); if (remainingCounter?.Value > 0) { - remainingCounter.Value --; + remainingCounter.Value--; } } if (isDead) { - this.pmcChatResponseService.sendKillerResponse(sessionID, serverPmcData, postRaidRequest.profile.Stats.Eft.Aggressor); + this.pmcChatResponseService.sendKillerResponse( + sessionID, + serverPmcData, + postRaidRequest.profile.Stats.Eft.Aggressor, + ); this.matchBotDetailsCacheService.clearCache(); serverPmcData = this.performPostRaidActionsWhenDead(postRaidRequest, serverPmcData, sessionID); } - const victims = postRaidRequest.profile.Stats.Eft.Victims.filter(x => ["sptbear", "sptusec"].includes(x.Role.toLowerCase())); + const victims = postRaidRequest.profile.Stats.Eft.Victims.filter((x) => + ["sptbear", "sptusec"].includes(x.Role.toLowerCase()) + ); if (victims?.length > 0) { this.pmcChatResponseService.sendVictimResponse(sessionID, victims, serverPmcData); @@ -175,26 +188,37 @@ export class InraidController /** * Make changes to pmc profile after they've died in raid, - * Alter bodypart hp, handle insurance, delete inventory items, remove carried quest items - * @param postRaidSaveRequest Post-raid save request + * Alter body part hp, handle insurance, delete inventory items, remove carried quest items + * @param postRaidSaveRequest Post-raid save request * @param pmcData Pmc profile * @param sessionID Session id * @returns Updated profile object */ - protected performPostRaidActionsWhenDead(postRaidSaveRequest: ISaveProgressRequestData, pmcData: IPmcData, sessionID: string): IPmcData + protected performPostRaidActionsWhenDead( + postRaidSaveRequest: ISaveProgressRequestData, + pmcData: IPmcData, + sessionID: string, + ): IPmcData { this.updatePmcHealthPostRaid(postRaidSaveRequest, pmcData); this.inRaidHelper.deleteInventory(pmcData, sessionID); if (this.inRaidHelper.removeQuestItemsOnDeath()) { - // Find and remove the completed condition from profile if player died, otherwise quest is stuck in limbo and quest items cannot be picked up again + // Find and remove the completed condition from profile if player died, otherwise quest is stuck in limbo + // and quest items cannot be picked up again const allQuests = this.questHelper.getQuestsFromDb(); - const activeQuestIdsInProfile = pmcData.Quests.filter(x => ![QuestStatus.AvailableForStart, QuestStatus.Success, QuestStatus.Expired].includes(x.status)).map(x => x.qid); + const activeQuestIdsInProfile = pmcData.Quests.filter((x) => + ![QuestStatus.AvailableForStart, QuestStatus.Success, QuestStatus.Expired].includes(x.status) + ).map((x) => x.qid); for (const questItem of postRaidSaveRequest.profile.Stats.Eft.CarriedQuestItems) { // Get quest/find condition for carried quest item - const questAndFindItemConditionId = this.questHelper.getFindItemConditionByQuestItem(questItem, activeQuestIdsInProfile, allQuests); + const questAndFindItemConditionId = this.questHelper.getFindItemConditionByQuestItem( + questItem, + activeQuestIdsInProfile, + allQuests, + ); if (questAndFindItemConditionId) { this.profileHelper.removeCompletedQuestConditionFromProfile(pmcData, questAndFindItemConditionId); @@ -209,7 +233,7 @@ export class InraidController } /** - * Adjust player characters bodypart hp post-raid + * Adjust player characters body part hp post-raid * @param postRaidSaveRequest post raid data * @param pmcData player profile */ @@ -234,13 +258,13 @@ export class InraidController /** * Reduce body part hp to % of max * @param pmcData profile to edit - * @param multipler multipler to apply to max health + * @param multiplier multiplier to apply to max health */ - protected reducePmcHealthToPercent(pmcData: IPmcData, multipler: number): void + protected reducePmcHealthToPercent(pmcData: IPmcData, multiplier: number): void { for (const bodyPart of Object.values(pmcData.Health.BodyParts)) { - (bodyPart).Health.Current = (bodyPart).Health.Maximum * multipler; + (bodyPart).Health.Current = (bodyPart).Health.Maximum * multiplier; } } @@ -269,7 +293,12 @@ export class InraidController // Check for exit status this.markOrRemoveFoundInRaidItems(postRaidRequest); - postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs(postRaidRequest.profile, postRaidRequest.profile.Inventory.items, pmcData.InsuredItems, postRaidRequest.profile.Inventory.fastPanel); + postRaidRequest.profile.Inventory.items = this.itemHelper.replaceIDs( + postRaidRequest.profile, + postRaidRequest.profile.Inventory.items, + pmcData.InsuredItems, + postRaidRequest.profile.Inventory.fastPanel, + ); this.inRaidHelper.addUpdToMoneyFromRaid(postRaidRequest.profile.Inventory.items); this.handlePostRaidPlayerScavProcess(scavData, sessionID, postRaidRequest, pmcData, isDead); @@ -278,7 +307,7 @@ export class InraidController /** * Does provided profile contain any condition counters * @param profile Profile to check for condition counters - * @returns + * @returns */ protected profileHasConditionCounters(profile: IPmcData): boolean { @@ -286,7 +315,6 @@ export class InraidController { return false; } - return profile.ConditionCounters.Counters.length > 0; } @@ -294,7 +322,7 @@ export class InraidController { for (const quest of scavProfile.Quests) { - const pmcQuest = pmcProfile.Quests.find(x => x.qid === quest.qid); + const pmcQuest = pmcProfile.Quests.find((x) => x.qid === quest.qid); if (!pmcQuest) { this.logger.warning(`No PMC quest found for ID: ${quest.qid}`); @@ -303,9 +331,14 @@ export class InraidController // Post-raid status is enum word e.g. `Started` but pmc quest status is number e.g. 2 // Status values mismatch or statusTimers counts mismatch - if (quest.status !== QuestStatus[pmcQuest.status] || quest.statusTimers.length !== pmcQuest.statusTimers.length) + if ( + quest.status !== QuestStatus[pmcQuest.status] || + quest.statusTimers.length !== pmcQuest.statusTimers.length + ) { - this.logger.warning(`Quest: ${quest.qid} found in PMC profile has different status/statustimer. Scav: ${quest.status} vs PMC: ${pmcQuest.status}`); + this.logger.warning( + `Quest: ${quest.qid} found in PMC profile has different status/statustimer. Scav: ${quest.status} vs PMC: ${pmcQuest.status}`, + ); pmcQuest.status = QuestStatus[quest.status]; // Copy status timers over + fix bad enum key for each @@ -324,17 +357,20 @@ export class InraidController // Loop over all scav counters and add into pmc profile for (const scavCounter of scavProfile.ConditionCounters.Counters) { - this.logger.warning(`Processing counter: ${scavCounter.id} value:${scavCounter.value} quest:${scavCounter.qid}`); - const counterInPmcProfile = pmcProfile.ConditionCounters.Counters.find(x => x.id === scavCounter.id); + this.logger.warning( + `Processing counter: ${scavCounter.id} value:${scavCounter.value} quest:${scavCounter.qid}`, + ); + const counterInPmcProfile = pmcProfile.ConditionCounters.Counters.find((x) => x.id === scavCounter.id); if (!counterInPmcProfile) { // Doesn't exist yet, push it straight in pmcProfile.ConditionCounters.Counters.push(scavCounter); - continue; } - this.logger.warning(`Counter id: ${scavCounter.id} already exists in pmc profile! with value: ${counterInPmcProfile.value} for quest: ${counterInPmcProfile.qid}`); + this.logger.warning( + `Counter id: ${scavCounter.id} already exists in pmc profile! with value: ${counterInPmcProfile.value} for quest: ${counterInPmcProfile.qid}`, + ); // Only adjust counter value if its changed if (counterInPmcProfile.value !== scavCounter.value) @@ -363,7 +399,7 @@ export class InraidController { if (offraidData.exit !== PlayerRaidEndState.SURVIVED) { - // Remove FIR status if the player havn't survived + // Remove FIR status if the player hasn't survived offraidData.profile = this.inRaidHelper.removeSpawnedInSessionPropertyFromItems(offraidData.profile); } } @@ -376,7 +412,13 @@ export class InraidController * @param pmcData Pmc profile * @param isDead Is player dead */ - protected handlePostRaidPlayerScavProcess(scavData: IPmcData, sessionID: string, offraidData: ISaveProgressRequestData, pmcData: IPmcData, isDead: boolean): void + protected handlePostRaidPlayerScavProcess( + scavData: IPmcData, + sessionID: string, + offraidData: ISaveProgressRequestData, + pmcData: IPmcData, + isDead: boolean, + ): void { // Update scav profile inventory scavData = this.inRaidHelper.setInventory(sessionID, scavData, offraidData.profile); @@ -411,14 +453,17 @@ export class InraidController let fenceStanding = Number(pmcData.TradersInfo[fenceId].standing); this.logger.debug(`Old fence standing: ${fenceStanding}`); - fenceStanding = this.inRaidHelper.calculateFenceStandingChangeFromKills(fenceStanding, offraidData.profile.Stats.Eft.Victims); + fenceStanding = this.inRaidHelper.calculateFenceStandingChangeFromKills( + fenceStanding, + offraidData.profile.Stats.Eft.Victims, + ); // Successful extract with scav adds 0.01 standing if (offraidData.exit === PlayerRaidEndState.SURVIVED) { fenceStanding += this.inraidConfig.scavExtractGain; } - + // Make standing changes to pmc profile pmcData.TradersInfo[fenceId].standing = Math.min(Math.max(fenceStanding, -7), 15); // Ensure it stays between -7 and 15 this.logger.debug(`New fence standing: ${pmcData.TradersInfo[fenceId].standing}`); @@ -443,4 +488,4 @@ export class InraidController { return this.airdropConfig; } -} \ No newline at end of file +} diff --git a/project/src/controllers/InsuranceController.ts b/project/src/controllers/InsuranceController.ts index 6393f9db..271ad0bd 100644 --- a/project/src/controllers/InsuranceController.ts +++ b/project/src/controllers/InsuranceController.ts @@ -10,7 +10,7 @@ import { IGetInsuranceCostRequestData } from "@spt-aki/models/eft/insurance/IGet import { IGetInsuranceCostResponseData } from "@spt-aki/models/eft/insurance/IGetInsuranceCostResponseData"; import { IInsureRequestData } from "@spt-aki/models/eft/insurance/IInsureRequestData"; import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse"; -import { ISystemData, Insurance } from "@spt-aki/models/eft/profile/IAkiProfile"; +import { Insurance, ISystemData } from "@spt-aki/models/eft/profile/IAkiProfile"; import { IProcessBuyTradeRequestData } from "@spt-aki/models/eft/trade/IProcessBuyTradeRequestData"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { MessageType } from "@spt-aki/models/enums/MessageType"; @@ -24,9 +24,9 @@ import { SaveServer } from "@spt-aki/servers/SaveServer"; import { InsuranceService } from "@spt-aki/services/InsuranceService"; import { MailSendService } from "@spt-aki/services/MailSendService"; import { PaymentService } from "@spt-aki/services/PaymentService"; +import { MathUtil } from "@spt-aki/utils/MathUtil"; import { RandomUtil } from "@spt-aki/utils/RandomUtil"; import { TimeUtil } from "@spt-aki/utils/TimeUtil"; -import { MathUtil } from "@spt-aki/utils/MathUtil"; @injectable() export class InsuranceController @@ -48,7 +48,7 @@ export class InsuranceController @inject("PaymentService") protected paymentService: PaymentService, @inject("InsuranceService") protected insuranceService: InsuranceService, @inject("MailSendService") protected mailSendService: MailSendService, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); @@ -58,7 +58,7 @@ export class InsuranceController * Process insurance items of all profiles prior to being given back to the player through the mail service. * * @returns void - */ + */ public processReturn(): void { // Process each installed profile. @@ -72,7 +72,7 @@ export class InsuranceController * Process insurance items of a single profile prior to being given back to the player through the mail service. * * @returns void - */ + */ public processReturnByProfile(sessionID: string): void { // Filter out items that don't need to be processed yet. @@ -117,7 +117,11 @@ export class InsuranceController */ protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void { - this.logger.debug(`Processing ${insuranceDetails.length} insurance packages, which includes a total of ${this.countAllInsuranceItems(insuranceDetails)} items, in profile ${sessionID}`); + this.logger.debug( + `Processing ${insuranceDetails.length} insurance packages, which includes a total of ${ + this.countAllInsuranceItems(insuranceDetails) + } items, in profile ${sessionID}`, + ); // Iterate over each of the insurance packages. for (const insured of insuranceDetails) @@ -146,7 +150,7 @@ export class InsuranceController */ protected countAllInsuranceItems(insurance: Insurance[]): number { - return this.mathUtil.arraySum(insurance.map(ins => ins.items.length)); + return this.mathUtil.arraySum(insurance.map((ins) => ins.items.length)); } /** @@ -159,13 +163,15 @@ export class InsuranceController protected removeInsurancePackageFromProfile(sessionID: string, packageInfo: ISystemData): void { const profile = this.saveServer.getProfile(sessionID); - profile.insurance = profile.insurance.filter(insurance => + profile.insurance = profile.insurance.filter((insurance) => insurance.messageContent.systemData.date !== packageInfo.date || insurance.messageContent.systemData.time !== packageInfo.time || insurance.messageContent.systemData.location !== packageInfo.location ); - this.logger.debug(`Removed insurance package with date: ${packageInfo.date}, time: ${packageInfo.time}, and location: ${packageInfo.location} from profile ${sessionID}. Remaining packages: ${profile.insurance.length}`); + this.logger.debug( + `Removed insurance package with date: ${packageInfo.date}, time: ${packageInfo.time}, and location: ${packageInfo.location} from profile ${sessionID}. Remaining packages: ${profile.insurance.length}`, + ); } /** @@ -184,7 +190,9 @@ export class InsuranceController const parentAttachmentsMap = this.populateParentAttachmentsMap(insured, itemsMap); // Check to see if any regular items are present. - const hasRegularItems = Array.from(itemsMap.values()).some(item => !this.itemHelper.isAttachmentAttached(item)); + const hasRegularItems = Array.from(itemsMap.values()).some((item) => + !this.itemHelper.isAttachmentAttached(item) + ); // Process all items that are not attached, attachments. Those are handled separately, by value. if (hasRegularItems) @@ -238,12 +246,14 @@ export class InsuranceController for (const insuredItem of insured.items) { // Use the parent ID from the item to get the parent item. - const parentItem = insured.items.find(item => item._id === insuredItem.parentId); + const parentItem = insured.items.find((item) => item._id === insuredItem.parentId); // The parent (not the hideout) could not be found. Skip and warn. if (!parentItem && insuredItem.parentId !== this.fetchHideoutItemParent(insured.items)) { - this.logger.warning(`Could not find parent for insured item - ID: ${insuredItem._id}, Template: ${insuredItem._tpl}, Parent ID: ${insuredItem.parentId}`); + this.logger.warning( + `Could not find parent for insured item - ID: ${insuredItem._id}, Template: ${insuredItem._tpl}, Parent ID: ${insuredItem.parentId}`, + ); continue; } @@ -261,7 +271,9 @@ export class InsuranceController if (!mainParent) { // Odd. The parent couldn't be found. Skip this attachment and warn. - this.logger.warning(`Could not find main-parent for insured attachment - ID: ${insuredItem._id}, Template: ${insuredItem._tpl}, Parent ID: ${insuredItem.parentId}`); + this.logger.warning( + `Could not find main-parent for insured attachment - ID: ${insuredItem._id}, Template: ${insuredItem._tpl}, Parent ID: ${insuredItem.parentId}`, + ); continue; } @@ -310,8 +322,10 @@ export class InsuranceController // Check if the item has any children and mark those for deletion as well, but only if those // children are currently attached attachments. - const directChildren = insured.items.filter(item => item.parentId === insuredItem._id); - const allChildrenAreAttachments = directChildren.every(child => this.itemHelper.isAttachmentAttached(child)); + const directChildren = insured.items.filter((item) => item.parentId === insuredItem._id); + const allChildrenAreAttachments = directChildren.every((child) => + this.itemHelper.isAttachmentAttached(child) + ); if (allChildrenAreAttachments) { for (const item of itemAndChildren) @@ -331,9 +345,14 @@ export class InsuranceController * @param traderId The trader ID from the Insurance object. * @param toDelete A Set object to keep track of items marked for deletion. */ - protected processAttachments(mainParentToAttachmentsMap: Map, itemsMap: Map, traderId: string, toDelete: Set): void + protected processAttachments( + mainParentToAttachmentsMap: Map, + itemsMap: Map, + traderId: string, + toDelete: Set, + ): void { - for (const [ parentId, attachmentItems ] of mainParentToAttachmentsMap) + for (const [parentId, attachmentItems] of mainParentToAttachmentsMap) { // Log the parent item's name. const parentItem = itemsMap.get(parentId); @@ -375,10 +394,10 @@ export class InsuranceController */ protected sortAttachmentsByPrice(attachments: Item[]): EnrichedItem[] { - return attachments.map(item => ({ + return attachments.map((item) => ({ ...item, name: this.itemHelper.getItemName(item._tpl), - maxPrice: this.itemHelper.getItemMaxPrice(item._tpl) + maxPrice: this.itemHelper.getItemMaxPrice(item._tpl), })).sort((a, b) => b.maxPrice - a.maxPrice); } @@ -389,7 +408,7 @@ export class InsuranceController */ protected logAttachmentsDetails(attachments: EnrichedItem[]): void { - for ( const attachment of attachments) + for (const attachment of attachments) { this.logger.debug(`Child Item - Name: ${attachment.name}, Max Price: ${attachment.maxPrice}`); } @@ -404,7 +423,7 @@ export class InsuranceController */ protected countSuccessfulRolls(attachments: Item[], traderId: string): number { - const rolls = Array.from({ length: attachments.length }, () => this.rollForDelete(traderId)); + const rolls = Array.from({length: attachments.length}, () => this.rollForDelete(traderId)); return rolls.filter(Boolean).length; } @@ -415,16 +434,20 @@ export class InsuranceController * @param successfulRolls The number of successful rolls. * @param toDelete The array that accumulates the IDs of the items to be deleted. */ - protected attachmentDeletionByValue(attachments: EnrichedItem[], successfulRolls: number, toDelete: Set): void + protected attachmentDeletionByValue( + attachments: EnrichedItem[], + successfulRolls: number, + toDelete: Set, + ): void { - const valuableToDelete = attachments.slice(0, successfulRolls).map(({ _id }) => _id); + const valuableToDelete = attachments.slice(0, successfulRolls).map(({_id}) => _id); for (const attachmentsId of valuableToDelete) { - const valuableChild = attachments.find(({ _id }) => _id === attachmentsId); + const valuableChild = attachments.find(({_id}) => _id === attachmentsId); if (valuableChild) { - const { name, maxPrice } = valuableChild; + const {name, maxPrice} = valuableChild; this.logger.debug(`Marked for removal - Child Item: ${name}, Max Price: ${maxPrice}`); toDelete.add(attachmentsId); } @@ -440,7 +463,7 @@ export class InsuranceController */ protected removeItemsFromInsurance(insured: Insurance, toDelete: Set): void { - insured.items = insured.items.filter(item => !toDelete.has(item._id)); + insured.items = insured.items.filter((item) => !toDelete.has(item._id)); } /** @@ -457,7 +480,7 @@ export class InsuranceController for (const item of insured.items) { // Check if the item's parent exists in the insured items list. - const parentExists = insured.items.some(parentItem => parentItem._id === item.parentId); + const parentExists = insured.items.some((parentItem) => parentItem._id === item.parentId); // If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item. if (!parentExists && item.parentId !== hideoutParentId && item.slotId !== "hideout") @@ -478,7 +501,7 @@ export class InsuranceController */ protected fetchHideoutItemParent(items: Item[]): string { - const hideoutItem = items.find(item => item.slotId === "hideout"); + const hideoutItem = items.find((item) => item.slotId === "hideout"); const hideoutParentId = hideoutItem ? hideoutItem?.parentId : ""; if (hideoutParentId === "") @@ -502,7 +525,8 @@ export class InsuranceController // successfully "failed" to return anything and an appropriate message should be sent to the player. if (insurance.items.length === 0) { - const insuranceFailedTemplates = this.databaseServer.getTables().traders[insurance.traderId].dialogue.insuranceFailed; + const insuranceFailedTemplates = + this.databaseServer.getTables().traders[insurance.traderId].dialogue.insuranceFailed; insurance.messageContent.templateId = this.randomUtil.getArrayValue(insuranceFailedTemplates); } @@ -514,7 +538,7 @@ export class InsuranceController insurance.messageContent.templateId, insurance.items, insurance.messageContent.maxStorageTime, - insurance.messageContent.systemData + insurance.messageContent.systemData, ); } @@ -544,7 +568,9 @@ export class InsuranceController // Log the roll with as much detail as possible. const itemName = insuredItem ? ` for "${this.itemHelper.getItemName(insuredItem._tpl)}"` : ""; const status = roll ? "Delete" : "Keep"; - this.logger.debug(`Rolling deletion${itemName} with ${trader} - Return ${traderReturnChance}% - Roll: ${returnChance} - Status: ${status}`); + this.logger.debug( + `Rolling deletion${itemName} with ${trader} - Return ${traderReturnChance}% - Roll: ${returnChance} - Status: ${status}`, + ); return roll; } @@ -575,21 +601,18 @@ export class InsuranceController { itemsToPay.push({ id: inventoryItemsHash[key]._id, - count: Math.round(this.insuranceService.getPremium(pmcData, inventoryItemsHash[key], body.tid)) + count: Math.round(this.insuranceService.getPremium(pmcData, inventoryItemsHash[key], body.tid)), }); } const options: IProcessBuyTradeRequestData = { - // eslint-disable-next-line @typescript-eslint/naming-convention scheme_items: itemsToPay, tid: body.tid, Action: "", type: "", - // eslint-disable-next-line @typescript-eslint/naming-convention item_id: "", count: 0, - // eslint-disable-next-line @typescript-eslint/naming-convention - scheme_id: 0 + scheme_id: 0, }; // pay for the item insurance @@ -604,7 +627,7 @@ export class InsuranceController { pmcData.InsuredItems.push({ tid: body.tid, - itemId: inventoryItemsHash[key]._id + itemId: inventoryItemsHash[key]._id, }); } @@ -645,7 +668,9 @@ export class InsuranceController this.logger.debug(`Item with id: ${itemId} missing from player inventory, skipping`); continue; } - items[inventoryItemsHash[itemId]._tpl] = Math.round(this.insuranceService.getPremium(pmcData, inventoryItemsHash[itemId], trader)); + items[inventoryItemsHash[itemId]._tpl] = Math.round( + this.insuranceService.getPremium(pmcData, inventoryItemsHash[itemId], trader), + ); } output[trader] = items; diff --git a/project/src/controllers/InventoryController.ts b/project/src/controllers/InventoryController.ts index 23f5a5b4..084787b1 100644 --- a/project/src/controllers/InventoryController.ts +++ b/project/src/controllers/InventoryController.ts @@ -62,21 +62,25 @@ export class InventoryController @inject("LocalisationService") protected localisationService: LocalisationService, @inject("LootGenerator") protected lootGenerator: LootGenerator, @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, - @inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil + @inject("HttpResponseUtil") protected httpResponseUtil: HttpResponseUtil, ) {} /** - * Move Item - * change location of item with parentId and slotId - * transfers items from one profile to another if fromOwner/toOwner is set in the body. - * otherwise, move is contained within the same profile_f. + * Move Item + * change location of item with parentId and slotId + * transfers items from one profile to another if fromOwner/toOwner is set in the body. + * otherwise, move is contained within the same profile_f. * @param pmcData Profile * @param moveRequest Move request data * @param sessionID Session id * @returns IItemEventRouterResponse */ - public moveItem(pmcData: IPmcData, moveRequest: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse + public moveItem( + pmcData: IPmcData, + moveRequest: IInventoryMoveRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); @@ -89,14 +93,14 @@ export class InventoryController const ownerInventoryItems = this.inventoryHelper.getOwnerInventoryItems(moveRequest, sessionID); if (ownerInventoryItems.sameInventory) { - // Dont move items from trader to profile, this can happen when editing a traders preset weapons + // Don't move items from trader to profile, this can happen when editing a traders preset weapons if (moveRequest.fromOwner?.type === "Trader" && !ownerInventoryItems.isMail) { return this.getTraderExploitErrorResponse(output); } // Check for item in inventory before allowing internal transfer - const originalItemLocation = ownerInventoryItems.from.find(x => x._id === moveRequest.item); + const originalItemLocation = ownerInventoryItems.from.find((x) => x._id === moveRequest.item); if (!originalItemLocation) { // Internal item move but item never existed, possible dupe glitch @@ -123,14 +127,23 @@ export class InventoryController */ protected getTraderExploitErrorResponse(output: IItemEventRouterResponse): IItemEventRouterResponse { - return this.httpResponseUtil.appendErrorToOutput(output, this.localisationService.getText("inventory-edit_trader_item"), 228); + return this.httpResponseUtil.appendErrorToOutput( + output, + this.localisationService.getText("inventory-edit_trader_item"), + 228, + ); } /** - * Remove Item from Profile - * Deep tree item deletion, also removes items from insurance list - */ - public removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output: IItemEventRouterResponse = undefined): IItemEventRouterResponse + * Remove Item from Profile + * Deep tree item deletion, also removes items from insurance list + */ + public removeItem( + pmcData: IPmcData, + itemId: string, + sessionID: string, + output: IItemEventRouterResponse = undefined, + ): IItemEventRouterResponse { return this.inventoryHelper.removeItem(pmcData, itemId, sessionID, output); } @@ -140,29 +153,46 @@ export class InventoryController * Implements functionality "Discard" from Main menu (Stash etc.) * Removes item from PMC Profile */ - public discardItem(pmcData: IPmcData, body: IInventoryRemoveRequestData, sessionID: string): IItemEventRouterResponse + public discardItem( + pmcData: IPmcData, + body: IInventoryRemoveRequestData, + sessionID: string, + ): IItemEventRouterResponse { if (body.fromOwner?.type === "Mail") { - return this.inventoryHelper.removeItemAndChildrenFromMailRewards(sessionID, body, this.eventOutputHolder.getOutput(sessionID)); + return this.inventoryHelper.removeItemAndChildrenFromMailRewards( + sessionID, + body, + this.eventOutputHolder.getOutput(sessionID), + ); } - - const profileToRemoveItemFrom = (!body.fromOwner || body.fromOwner.id === pmcData._id) - ? pmcData - : this.profileHelper.getFullProfile(sessionID).characters.scav; - return this.inventoryHelper.removeItem(profileToRemoveItemFrom, body.item, sessionID, this.eventOutputHolder.getOutput(sessionID)); + const profileToRemoveItemFrom = (!body.fromOwner || body.fromOwner.id === pmcData._id) ? + pmcData : + this.profileHelper.getFullProfile(sessionID).characters.scav; + + return this.inventoryHelper.removeItem( + profileToRemoveItemFrom, + body.item, + sessionID, + this.eventOutputHolder.getOutput(sessionID), + ); } /** * Split Item - * spliting 1 stack into 2 + * splitting 1 stack into 2 * @param pmcData Player profile (unused, getOwnerInventoryItems() gets profile) * @param request Split request * @param sessionID Session/player id * @returns IItemEventRouterResponse */ - public splitItem(pmcData: IPmcData, request: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse + public splitItem( + pmcData: IPmcData, + request: IInventorySplitRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); @@ -172,15 +202,16 @@ export class InventoryController // Handle cartridge edge-case if (!request.container.location && request.container.container === "cartridges") { - const matchingItems = inventoryItems.to.filter(x => x.parentId === request.container.id); + const matchingItems = inventoryItems.to.filter((x) => x.parentId === request.container.id); request.container.location = matchingItems.length; // Wrong location for first cartridge } - // The item being merged has three possible sources: pmc, scav or mail, getOwnerInventoryItems() handles getting correct one - const itemToSplit = inventoryItems.from.find(x => x._id === request.splitItem); + // The item being merged has three possible sources: pmc, scav or mail, getOwnerInventoryItems() handles getting + // correct one. + const itemToSplit = inventoryItems.from.find((x) => x._id === request.splitItem); if (!itemToSplit) { - const errorMessage = (`Unable to split stack as source item: ${request.splitItem} cannot be found`); + const errorMessage = `Unable to split stack as source item: ${request.splitItem} cannot be found`; this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); @@ -197,7 +228,7 @@ export class InventoryController output.profileChanges[sessionID].items.new.push({ _id: request.newItem, _tpl: itemToSplit._tpl, - upd: updatedUpd + upd: updatedUpd, }); // Update player inventory @@ -207,7 +238,7 @@ export class InventoryController parentId: request.container.id, slotId: request.container.container, location: request.container.location, - upd: updatedUpd + upd: updatedUpd, }); return output; @@ -229,20 +260,20 @@ export class InventoryController const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID); // Get source item (can be from player or trader or mail) - const sourceItem = inventoryItems.from.find(x => x._id === body.item); + const sourceItem = inventoryItems.from.find((x) => x._id === body.item); if (!sourceItem) { - const errorMessage = (`Unable to merge stacks as source item: ${body.with} cannot be found`); + const errorMessage = `Unable to merge stacks as source item: ${body.with} cannot be found`; this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); } // Get item being merged into - const destinationItem = inventoryItems.to.find(x => x._id === body.with); + const destinationItem = inventoryItems.to.find((x) => x._id === body.with); if (!destinationItem) { - const errorMessage = (`Unable to merge stacks as destination item: ${body.with} cannot be found`); + const errorMessage = `Unable to merge stacks as destination item: ${body.with} cannot be found`; this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); @@ -250,29 +281,29 @@ export class InventoryController if (!(destinationItem.upd?.StackObjectsCount)) { - // No stackcount on destination, add one - destinationItem.upd = { StackObjectsCount: 1 }; + // No stack count on destination, add one + destinationItem.upd = {StackObjectsCount: 1}; } if (!sourceItem.upd) { sourceItem.upd = { - StackObjectsCount: 1 + StackObjectsCount: 1, }; } else if (!sourceItem.upd.StackObjectsCount) { - // Items pulled out of raid can have no stackcount if the stack should be 1 + // Items pulled out of raid can have no stack count if the stack should be 1 sourceItem.upd.StackObjectsCount = 1; } - destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stackcount to destination - output.profileChanges[sessionID].items.del.push({ _id: sourceItem._id }); // Inform client source item being deleted + destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stack count to destination + output.profileChanges[sessionID].items.del.push({_id: sourceItem._id}); // Inform client source item being deleted - const indexOfItemToRemove = inventoryItems.from.findIndex(x => x._id === sourceItem._id); + const indexOfItemToRemove = inventoryItems.from.findIndex((x) => x._id === sourceItem._id); if (indexOfItemToRemove === -1) { - const errorMessage = (`Unable to find item: ${sourceItem._id} to remove from sender inventory`); + const errorMessage = `Unable to find item: ${sourceItem._id} to remove from sender inventory`; this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); @@ -283,8 +314,8 @@ export class InventoryController } /** - * TODO: Adds no data to output to send to client, is this by design? - * TODO: should make use of getOwnerInventoryItems(), stack being transferred may not always be on pmc + * // TODO: Adds no data to output to send to client, is this by design? + * // TODO: should make use of getOwnerInventoryItems(), stack being transferred may not always be on pmc * Transfer items from one stack into another while keeping original stack * Used to take items from scav inventory into stash or to insert ammo into mags (shotgun ones) and reloading weapon by clicking "Reload" * @param pmcData Player profile @@ -292,7 +323,11 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public transferItem(pmcData: IPmcData, body: IInventoryTransferRequestData, sessionID: string): IItemEventRouterResponse + public transferItem( + pmcData: IPmcData, + body: IInventoryTransferRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); @@ -314,7 +349,7 @@ export class InventoryController if (sourceItem !== null && destinationItem !== null) { // Both items found, exit loop - break; + break; } } @@ -359,7 +394,7 @@ export class InventoryController } else { - Object.assign(destinationItem, { upd: { StackObjectsCount: 1 } }); + Object.assign(destinationItem, {upd: {StackObjectsCount: 1}}); } destinationItem.upd.StackObjectsCount = destinationStackCount + body.count; @@ -368,28 +403,28 @@ export class InventoryController } /** - * Swap Item - * its used for "reload" if you have weapon in hands and magazine is somewhere else in rig or backpack in equipment - * Also used to swap items using quick selection on character screen - */ + * Swap Item + * its used for "reload" if you have weapon in hands and magazine is somewhere else in rig or backpack in equipment + * Also used to swap items using quick selection on character screen + */ public swapItem(pmcData: IPmcData, request: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse { - const itemOne = pmcData.Inventory.items.find(x => x._id === request.item); + const itemOne = pmcData.Inventory.items.find((x) => x._id === request.item); if (!itemOne) { this.logger.error(`Unable to find item: ${request.item} to swap positions with: ${request.item2}`); } - const itemTwo = pmcData.Inventory.items.find(x => x._id === request.item2); + const itemTwo = pmcData.Inventory.items.find((x) => x._id === request.item2); if (!itemTwo) { this.logger.error(`Unable to find item: ${request.item2} to swap positions with: ${request.item}`); } - // to.id is the parentid + // to.id is the parentId itemOne.parentId = request.to.id; - - // to.container is the slotid + + // to.container is the slotId itemOne.slotId = request.to.container; // Request object has location data, add it in, otherwise remove existing location from object @@ -423,9 +458,11 @@ export class InventoryController public foldItem(pmcData: IPmcData, body: IInventoryFoldRequestData, sessionID: string): IItemEventRouterResponse { // Fix for folding weapons while on they're in the Scav inventory - if (body.fromOwner - && body.fromOwner.type === "Profile" - && body.fromOwner.id !== pmcData._id) + if ( + body.fromOwner && + body.fromOwner.type === "Profile" && + body.fromOwner.id !== pmcData._id + ) { pmcData = this.profileHelper.getScavProfile(sessionID); } @@ -434,19 +471,19 @@ export class InventoryController { if (item._id && item._id === body.item) { - item.upd.Foldable = { Folded: body.value }; + item.upd.Foldable = {Folded: body.value}; return this.eventOutputHolder.getOutput(sessionID); } } return { warnings: [], - profileChanges: {} + profileChanges: {}, }; } /** - * Toggles "Toggleable" items like night vision goggles and face shields. + * Toggles "toggleable" items like night vision goggles and face shields. * @param pmcData player profile * @param body Toggle request * @param sessionID Session id @@ -460,27 +497,31 @@ export class InventoryController pmcData = this.profileHelper.getScavProfile(sessionID); } - const itemToToggle = pmcData.Inventory.items.find(x => x._id === body.item); + const itemToToggle = pmcData.Inventory.items.find((x) => x._id === body.item); if (itemToToggle) { if (!itemToToggle.upd) { - this.logger.warning(this.localisationService.getText("inventory-item_to_toggle_missing_upd", itemToToggle._id)); + this.logger.warning( + this.localisationService.getText("inventory-item_to_toggle_missing_upd", itemToToggle._id), + ); itemToToggle.upd = {}; } - itemToToggle.upd.Togglable = { On: body.value }; + itemToToggle.upd.Togglable = {On: body.value}; return this.eventOutputHolder.getOutput(sessionID); } else { - this.logger.warning(this.localisationService.getText("inventory-unable_to_toggle_item_not_found", body.item)); + this.logger.warning( + this.localisationService.getText("inventory-unable_to_toggle_item_not_found", body.item), + ); } return { warnings: [], - profileChanges: {} + profileChanges: {}, }; } @@ -499,11 +540,11 @@ export class InventoryController { if ("upd" in item) { - item.upd.Tag = { Color: body.TagColor, Name: body.TagName }; + item.upd.Tag = {Color: body.TagColor, Name: body.TagName}; } else { - item.upd = { Tag: { Color: body.TagColor, Name: body.TagName } }; + item.upd = {Tag: {Color: body.TagColor, Name: body.TagName}}; } return this.eventOutputHolder.getOutput(sessionID); @@ -512,18 +553,22 @@ export class InventoryController return { warnings: [], - profileChanges: {} + profileChanges: {}, }; } /** * Bind an inventory item to the quick access menu at bottom of player screen * @param pmcData Player profile - * @param bindRequest Reqeust object + * @param bindRequest Request object * @param sessionID Session id * @returns IItemEventRouterResponse */ - public bindItem(pmcData: IPmcData, bindRequest: IInventoryBindRequestData, sessionID: string): IItemEventRouterResponse + public bindItem( + pmcData: IPmcData, + bindRequest: IInventoryBindRequestData, + sessionID: string, + ): IItemEventRouterResponse { for (const index in pmcData.Inventory.fastPanel) { @@ -538,7 +583,6 @@ export class InventoryController return this.eventOutputHolder.getOutput(sessionID); } - /** * Handles examining an item * @param pmcData player profile @@ -546,7 +590,11 @@ export class InventoryController * @param sessionID session id * @returns response */ - public examineItem(pmcData: IPmcData, body: IInventoryExamineRequestData, sessionID: string): IItemEventRouterResponse + public examineItem( + pmcData: IPmcData, + body: IInventoryExamineRequestData, + sessionID: string, + ): IItemEventRouterResponse { let itemId = ""; if ("fromOwner" in body) @@ -559,7 +607,7 @@ export class InventoryController { this.logger.error(this.localisationService.getText("inventory-examine_item_does_not_exist", body.item)); } - + // get hideout item if (body.fromOwner.type === "HideoutProduction") { @@ -606,9 +654,9 @@ export class InventoryController } /** - * Get the tplid of an item from the examine request object + * Get the tplId of an item from the examine request object * @param body response request - * @returns tplid + * @returns string */ protected getExaminedItemTpl(body: IInventoryExamineRequestData): string { @@ -618,49 +666,55 @@ export class InventoryController } else if (body.fromOwner.id === Traders.FENCE) { - // get tpl from fence assorts - return this.fenceService.getRawFenceAssorts().items.find(x => x._id === body.item)._tpl; + // Get tpl from fence assorts + return this.fenceService.getRawFenceAssorts().items.find((x) => x._id === body.item)._tpl; } - else if (body.fromOwner.type === "Trader") // not fence + else if (body.fromOwner.type === "Trader") { - // get tpl from trader assort - return this.databaseServer.getTables().traders[body.fromOwner.id].assort.items.find(item => item._id === body.item)._tpl; + // Not fence + // Get tpl from trader assort + return this.databaseServer.getTables().traders[body.fromOwner.id].assort.items.find((item) => + item._id === body.item + )._tpl; } else if (body.fromOwner.type === "RagFair") { - // try to get tplid from items.json first + // try to get tplId from items.json first const item = this.databaseServer.getTables().templates.items[body.item]; if (item) { return item._id; } - // try alternate way of getting offer if first approach fails + // Try alternate way of getting offer if first approach fails let offer = this.ragfairOfferService.getOfferByOfferId(body.item); if (!offer) { offer = this.ragfairOfferService.getOfferByOfferId(body.fromOwner.id); } - // try find examine item inside offer items array - const matchingItem = offer.items.find(x => x._id === body.item); + // Try find examine item inside offer items array + const matchingItem = offer.items.find((x) => x._id === body.item); if (matchingItem) { return matchingItem._tpl; - } + } - // unable to find item in database or ragfair + // Unable to find item in database or ragfair throw new Error(this.localisationService.getText("inventory-unable_to_find_item", body.item)); } } - public readEncyclopedia(pmcData: IPmcData, body: IInventoryReadEncyclopediaRequestData, sessionID: string): IItemEventRouterResponse + public readEncyclopedia( + pmcData: IPmcData, + body: IInventoryReadEncyclopediaRequestData, + sessionID: string, + ): IItemEventRouterResponse { for (const id of body.ids) { pmcData.Encyclopedia[id] = true; } - return this.eventOutputHolder.getOutput(sessionID); } @@ -672,15 +726,20 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public sortInventory(pmcData: IPmcData, request: IInventorySortRequestData, sessionID: string): IItemEventRouterResponse + public sortInventory( + pmcData: IPmcData, + request: IInventorySortRequestData, + sessionID: string, + ): IItemEventRouterResponse { - for (const change of request.changedItems) { - const inventoryItem = pmcData.Inventory.items.find(x => x._id === change._id); + const inventoryItem = pmcData.Inventory.items.find((x) => x._id === change._id); if (!inventoryItem) { - this.logger.error(`Unable to find inventory item: ${change._id} to auto-sort, YOU MUST RELOAD YOUR GAME`); + this.logger.error( + `Unable to find inventory item: ${change._id} to auto-sort, YOU MUST RELOAD YOUR GAME`, + ); continue; } @@ -707,13 +766,17 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public createMapMarker(pmcData: IPmcData, request: IInventoryCreateMarkerRequestData, sessionID: string): IItemEventRouterResponse + public createMapMarker( + pmcData: IPmcData, + request: IInventoryCreateMarkerRequestData, + sessionID: string, + ): IItemEventRouterResponse { // Get map from inventory - const mapItem = pmcData.Inventory.items.find(i => i._id === request.item); + const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item); // add marker - mapItem.upd.Map = mapItem.upd.Map || { Markers: [] }; + mapItem.upd.Map = mapItem.upd.Map || {Markers: []}; request.mapMarker.Note = this.sanitiseMapMarkerText(request.mapMarker.Note); mapItem.upd.Map.Markers.push(request.mapMarker); @@ -731,10 +794,14 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public deleteMapMarker(pmcData: IPmcData, request: IInventoryDeleteMarkerRequestData, sessionID: string): IItemEventRouterResponse + public deleteMapMarker( + pmcData: IPmcData, + request: IInventoryDeleteMarkerRequestData, + sessionID: string, + ): IItemEventRouterResponse { // Get map from inventory - const mapItem = pmcData.Inventory.items.find(i => i._id === request.item); + const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item); // remove marker const markers = mapItem.upd.Map.Markers.filter((marker) => @@ -756,13 +823,17 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public editMapMarker(pmcData: IPmcData, request: IInventoryEditMarkerRequestData, sessionID: string): IItemEventRouterResponse + public editMapMarker( + pmcData: IPmcData, + request: IInventoryEditMarkerRequestData, + sessionID: string, + ): IItemEventRouterResponse { // Get map from inventory - const mapItem = pmcData.Inventory.items.find(i => i._id === request.item); + const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item); // edit marker - const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex(m => m.X === request.X && m.Y === request.Y); + const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex((m) => m.X === request.X && m.Y === request.Y); request.mapMarker.Note = this.sanitiseMapMarkerText(request.mapMarker.Note); mapItem.upd.Map.Markers[indexOfExistingNote] = request.mapMarker; @@ -791,15 +862,19 @@ export class InventoryController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public openRandomLootContainer(pmcData: IPmcData, body: IOpenRandomLootContainerRequestData, sessionID: string): IItemEventRouterResponse + public openRandomLootContainer( + pmcData: IPmcData, + body: IOpenRandomLootContainerRequestData, + sessionID: string, + ): IItemEventRouterResponse { - const openedItem = pmcData.Inventory.items.find(x => x._id === body.item); + const openedItem = pmcData.Inventory.items.find((x) => x._id === body.item); const containerDetails = this.itemHelper.getItem(openedItem._tpl); const isSealedWeaponBox = containerDetails[1]._name.includes("event_container_airdrop"); const newItemRequest: IAddItemRequestData = { tid: "RandomLootContainer", - items: [] + items: [], }; let foundInRaid = false; @@ -829,4 +904,4 @@ export class InventoryController return output; } -} \ No newline at end of file +} diff --git a/project/src/controllers/LauncherController.ts b/project/src/controllers/LauncherController.ts index 6ead15e3..748135ab 100644 --- a/project/src/controllers/LauncherController.ts +++ b/project/src/controllers/LauncherController.ts @@ -30,7 +30,7 @@ export class LauncherController @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("PreAkiModLoader") protected preAkiModLoader: PreAkiModLoader, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.coreConfig = this.configServer.getConfig(ConfigTypes.CORE); @@ -42,30 +42,26 @@ export class LauncherController backendUrl: this.httpServerHelper.getBackendUrl(), name: this.coreConfig.serverName, editions: Object.keys(this.databaseServer.getTables().templates.profiles), - profileDescriptions: this.getProfileDescriptions() + profileDescriptions: this.getProfileDescriptions(), }; } /** - * Get descriptive text for each of the profile edtions a player can choose - * @returns + * Get descriptive text for each of the profile editions a player can choose + * @returns */ protected getProfileDescriptions(): Record { return { + /* eslint-disable @typescript-eslint/naming-convention */ Standard: this.localisationService.getText("launcher-profile_standard"), - // eslint-disable-next-line @typescript-eslint/naming-convention "Left Behind": this.localisationService.getText("launcher-profile_leftbehind"), - // eslint-disable-next-line @typescript-eslint/naming-convention "Prepare To Escape": this.localisationService.getText("launcher-profile_preparetoescape"), - // eslint-disable-next-line @typescript-eslint/naming-convention "Edge Of Darkness": this.localisationService.getText("launcher-edgeofdarkness"), - // eslint-disable-next-line @typescript-eslint/naming-convention "SPT Easy start": this.localisationService.getText("launcher-profile_spteasystart"), - // eslint-disable-next-line @typescript-eslint/naming-convention "SPT Zero to hero": this.localisationService.getText("launcher-profile_sptzerotohero"), - // eslint-disable-next-line @typescript-eslint/naming-convention - "SPT Developer": this.localisationService.getText("launcher-profile_sptdeveloper") + "SPT Developer": this.localisationService.getText("launcher-profile_sptdeveloper"), + /* eslint-enable @typescript-eslint/naming-convention */ }; } @@ -115,12 +111,13 @@ export class LauncherController username: info.username, password: info.password, wipe: true, - edition: info.edition + edition: info.edition, }; this.saveServer.createProfile(newProfileDetails); this.saveServer.loadProfile(sessionID); this.saveServer.saveProfile(sessionID); + return sessionID; } diff --git a/project/src/controllers/LocationController.ts b/project/src/controllers/LocationController.ts index c46e6a43..df0c5671 100644 --- a/project/src/controllers/LocationController.ts +++ b/project/src/controllers/LocationController.ts @@ -41,7 +41,7 @@ export class LocationController @inject("LootGenerator") protected lootGenerator: LootGenerator, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("TimeUtil") protected timeUtil: TimeUtil, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP); @@ -88,17 +88,23 @@ export class LocationController // Create containers and add loot to them const staticLoot = this.locationGenerator.generateStaticContainers(location.base, staticAmmoDist); output.Loot.push(...staticLoot); - - // Add dyanmic loot to output loot + + // Add dynamic loot to output loot const dynamicLootDist: ILooseLoot = this.jsonUtil.clone(location.looseLoot); - const dynamicSpawnPoints: SpawnpointTemplate[] = this.locationGenerator.generateDynamicLoot(dynamicLootDist, staticAmmoDist, name); + const dynamicSpawnPoints: SpawnpointTemplate[] = this.locationGenerator.generateDynamicLoot( + dynamicLootDist, + staticAmmoDist, + name, + ); for (const spawnPoint of dynamicSpawnPoints) { output.Loot.push(spawnPoint); } // Done generating, log results - this.logger.success(this.localisationService.getText("location-dynamic_items_spawned_success", dynamicSpawnPoints.length)); + this.logger.success( + this.localisationService.getText("location-dynamic_items_spawned_success", dynamicSpawnPoints.length), + ); this.logger.success(this.localisationService.getText("location-generated_success", name)); return output; @@ -110,7 +116,6 @@ export class LocationController * @param sessionId Players Id * @returns ILocationsGenerateAllResponse */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public generateAll(sessionId: string): ILocationsGenerateAllResponse { const locationsFromDb = this.databaseServer.getTables().locations; @@ -130,15 +135,15 @@ export class LocationController locations[mapBase._Id] = mapBase; } - return { + return { locations: locations, - paths: locationsFromDb.base.paths + paths: locationsFromDb.base.paths, }; } /** * Handle client/location/getAirdropLoot - * Get loot for an airdop container + * Get loot for an airdrop container * Generates it randomly based on config/airdrop.json values * @returns Array of LootItem objects */ @@ -174,7 +179,9 @@ export class LocationController let lootSettingsByType = this.airdropConfig.loot[airdropType]; if (!lootSettingsByType) { - this.logger.error(this.localisationService.getText("location-unable_to_find_airdrop_drop_config_of_type", airdropType)); + this.logger.error( + this.localisationService.getText("location-unable_to_find_airdrop_drop_config_of_type", airdropType), + ); lootSettingsByType = this.airdropConfig.loot[AirdropTypeEnum.MIXED]; } @@ -187,7 +194,7 @@ export class LocationController itemLimits: lootSettingsByType.itemLimits, itemStackLimits: lootSettingsByType.itemStackLimits, armorLevelWhitelist: lootSettingsByType.armorLevelWhitelist, - allowBossItems: lootSettingsByType.allowBossItems + allowBossItems: lootSettingsByType.allowBossItems, }; } -} \ No newline at end of file +} diff --git a/project/src/controllers/MatchController.ts b/project/src/controllers/MatchController.ts index b0135193..0baefa00 100644 --- a/project/src/controllers/MatchController.ts +++ b/project/src/controllers/MatchController.ts @@ -56,7 +56,7 @@ export class MatchController @inject("BotGenerationCacheService") protected botGenerationCacheService: BotGenerationCacheService, @inject("MailSendService") protected mailSendService: MailSendService, @inject("LootGenerator") protected lootGenerator: LootGenerator, - @inject("ApplicationContext") protected applicationContext: ApplicationContext + @inject("ApplicationContext") protected applicationContext: ApplicationContext, ) { this.matchConfig = this.configServer.getConfig(ConfigTypes.MATCH); @@ -99,12 +99,11 @@ export class MatchController } /** Handle match/group/start_game */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public joinMatch(info: IJoinMatchRequestData, sessionId: string): IJoinMatchResult { const output: IJoinMatchResult = { maxPveCountExceeded: false, - profiles: [] + profiles: [], }; // get list of players joining into the match @@ -120,20 +119,18 @@ export class MatchController raidMode: "Online", mode: "deathmatch", shortid: null, - // eslint-disable-next-line @typescript-eslint/naming-convention - additional_info: null + additional_info: null, }); return output; } /** Handle client/match/group/status */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getGroupStatus(info: IGetGroupStatusRequestData): any { return { players: [], - maxPveCountExceeded: false + maxPveCountExceeded: false, }; } @@ -147,15 +144,17 @@ export class MatchController // Store request data for access during bot generation this.applicationContext.addValue(ContextVariableType.RAID_CONFIGURATION, request); - //TODO: add code to strip PMC of equipment now they've started the raid + // TODO: add code to strip PMC of equipment now they've started the raid - // Set pmcs to difficulty set in pre-raid screen if override in bot config isnt enabled + // Set PMCs to difficulty set in pre-raid screen if override in bot config isn't enabled if (!this.pmcConfig.useDifficultyOverride) { - this.pmcConfig.difficulty = this.convertDifficultyDropdownIntoBotDifficulty(request.wavesSettings.botDifficulty); + this.pmcConfig.difficulty = this.convertDifficultyDropdownIntoBotDifficulty( + request.wavesSettings.botDifficulty, + ); } - // Store the profile as-is for later use on the post-raid exp screen + // Store the profile as-is for later use on the post-raid exp screen const currentProfile = this.saveServer.getProfile(sessionID); this.profileSnapshotService.storeProfileSnapshot(sessionID, currentProfile); } @@ -178,7 +177,7 @@ export class MatchController /** Handle client/match/offline/end */ public endOfflineRaid(info: IEndOfflineRaidRequestData, sessionId: string): void - { + { const pmcData: IPmcData = this.profileHelper.getPmcProfile(sessionId); const extractName = info.exitName; @@ -223,7 +222,7 @@ export class MatchController // Generate reward for taking coop extract const loot = this.lootGenerator.createRandomLoot(this.traderConfig.fence.coopExtractGift); const mailableLoot: Item[] = []; - + const parentId = this.hashUtil.generate(); for (const item of loot) { @@ -235,9 +234,9 @@ export class MatchController parentId: parentId, upd: { StackObjectsCount: item.stackCount, - SpawnedInSession: true - } - } + SpawnedInSession: true, + }, + }, ); } @@ -248,7 +247,7 @@ export class MatchController MessageType.MESSAGE_WITH_ITEMS, this.randomUtil.getArrayValue(this.traderConfig.fence.coopExtractGift.messageLocaleIds), mailableLoot, - this.timeUtil.getHoursAsSeconds(this.traderConfig.fence.coopExtractGift.giftExpiryHours) + this.timeUtil.getHoursAsSeconds(this.traderConfig.fence.coopExtractGift.giftExpiryHours), ); } @@ -292,25 +291,27 @@ export class MatchController const fenceId: string = Traders.FENCE; this.updateFenceStandingInProfile(pmcData, fenceId, extractName); - + this.traderHelper.lvlUp(fenceId, pmcData); pmcData.TradersInfo[fenceId].loyaltyLevel = Math.max(pmcData.TradersInfo[fenceId].loyaltyLevel, 1); - this.logger.debug(`Car extract: ${extractName} used, total times taken: ${pmcData.CarExtractCounts[extractName]}`); + this.logger.debug( + `Car extract: ${extractName} used, total times taken: ${pmcData.CarExtractCounts[extractName]}`, + ); } /** * Update players fence trader standing value in profile * @param pmcData Player profile * @param fenceId Id of fence trader - * @param extractName Name of extract used + * @param extractName Name of extract used */ protected updateFenceStandingInProfile(pmcData: IPmcData, fenceId: string, extractName: string): void { let fenceStanding = Number(pmcData.TradersInfo[fenceId].standing); - // Not exact replica of Live behaviour - // Simplified for now, no real reason to do the whole (unconfirmed) extra 0.01 standing per day regeneration mechanic + // Not exact replica of Live behaviour... Simplified for now. No real reason to do the whole (unconfirmed) + // extra 0.01 standing per day regeneration mechanic. const baseGain: number = this.inraidConfig.carExtractBaseStandingGain; const extractCount: number = pmcData.CarExtractCounts[extractName]; @@ -321,4 +322,4 @@ export class MatchController this.logger.debug(`Old vs new fence standing: ${pmcData.TradersInfo[fenceId].standing}, ${newFenceStanding}`); pmcData.TradersInfo[fenceId].standing = newFenceStanding; } -} \ No newline at end of file +} diff --git a/project/src/controllers/NoteController.ts b/project/src/controllers/NoteController.ts index 8b0c37b1..4f6fcc16 100644 --- a/project/src/controllers/NoteController.ts +++ b/project/src/controllers/NoteController.ts @@ -10,15 +10,15 @@ import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder"; export class NoteController { constructor( - @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder + @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, ) - { } + {} public addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse { const newNote: Note = { Time: body.note.Time, - Text: body.note.Text + Text: body.note.Text, }; pmcData.Notes.Notes.push(newNote); @@ -39,4 +39,4 @@ export class NoteController pmcData.Notes.Notes.splice(body.index, 1); return this.eventOutputHolder.getOutput(sessionID); } -} \ No newline at end of file +} diff --git a/project/src/controllers/NotifierController.ts b/project/src/controllers/NotifierController.ts index ab4d9bdd..60ad5e83 100644 --- a/project/src/controllers/NotifierController.ts +++ b/project/src/controllers/NotifierController.ts @@ -14,7 +14,7 @@ export class NotifierController constructor( @inject("NotifierHelper") protected notifierHelper: NotifierHelper, @inject("HttpServerHelper") protected httpServerHelper: HttpServerHelper, - @inject("NotificationService") protected notificationService: NotificationService + @inject("NotificationService") protected notificationService: NotificationService, ) {} @@ -82,11 +82,10 @@ export class NotifierController { return { server: this.httpServerHelper.buildUrl(), - // eslint-disable-next-line @typescript-eslint/naming-convention channel_id: sessionID, url: "", notifierServer: this.getServer(sessionID), - ws: this.notifierHelper.getWebSocketServer(sessionID) + ws: this.notifierHelper.getWebSocketServer(sessionID), }; } } diff --git a/project/src/controllers/PresetBuildController.ts b/project/src/controllers/PresetBuildController.ts index e3f4ca9d..9a42b95f 100644 --- a/project/src/controllers/PresetBuildController.ts +++ b/project/src/controllers/PresetBuildController.ts @@ -23,9 +23,9 @@ export class PresetBuildController @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("DatabaseServer") protected databaseServer: DatabaseServer, @inject("ItemHelper") protected itemHelper: ItemHelper, - @inject("SaveServer") protected saveServer: SaveServer + @inject("SaveServer") protected saveServer: SaveServer, ) - { } + {} /** Handle client/handbook/builds/my/list */ public getUserBuilds(sessionID: string): IUserBuilds @@ -35,21 +35,27 @@ export class PresetBuildController { profile.userbuilds = { equipmentBuilds: [], - weaponBuilds: [] + weaponBuilds: [], }; } // Ensure the secure container in the default presets match what the player has equipped - const defaultEquipmentPresets = this.jsonUtil.clone(this.databaseServer.getTables().templates.defaultEquipmentPresets); - const playerSecureContainer = profile.characters.pmc.Inventory.items?.find(x => x.slotId === "SecuredContainer"); - const firstDefaultItemsSecureContainer = defaultEquipmentPresets[0]?.items?.find(x => x.slotId === "SecuredContainer"); + const defaultEquipmentPresets = this.jsonUtil.clone( + this.databaseServer.getTables().templates.defaultEquipmentPresets, + ); + const playerSecureContainer = profile.characters.pmc.Inventory.items?.find((x) => + x.slotId === "SecuredContainer" + ); + const firstDefaultItemsSecureContainer = defaultEquipmentPresets[0]?.items?.find((x) => + x.slotId === "SecuredContainer" + ); if (playerSecureContainer && playerSecureContainer?._tpl !== firstDefaultItemsSecureContainer?._tpl) { - // Default equipment presets' secure container tpl doesnt match players secure container tpl + // Default equipment presets' secure container tpl doesn't match players secure container tpl for (const defaultPreset of defaultEquipmentPresets) { // Find presets secure container - const secureContainer = defaultPreset.items.find(x => x.slotId === "SecuredContainer"); + const secureContainer = defaultPreset.items.find((x) => x.slotId === "SecuredContainer"); if (secureContainer) { secureContainer._tpl = playerSecureContainer._tpl; @@ -65,9 +71,13 @@ export class PresetBuildController } /** Handle SaveWeaponBuild event */ - public saveWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionId: string): IItemEventRouterResponse + public saveWeaponBuild( + pmcData: IPmcData, + body: IPresetBuildActionRequestData, + sessionId: string, + ): IItemEventRouterResponse { - // TODO - could be merged into saveBuild, maybe + // TODO: Could be merged into saveBuild, maybe const output = this.eventOutputHolder.getOutput(sessionId); // Replace duplicate Id's. The first item is the base item. @@ -82,15 +92,19 @@ export class PresetBuildController name: body.name, root: body.root, items: body.items, - type: "weapon" + type: "weapon", }; const savedWeaponBuilds = this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds; - const existingBuild = savedWeaponBuilds.find(x => x.id === body.id); + const existingBuild = savedWeaponBuilds.find((x) => x.id === body.id); if (existingBuild) { // exists, replace - this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds.splice(savedWeaponBuilds.indexOf(existingBuild), 1, newBuild); + this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds.splice( + savedWeaponBuilds.indexOf(existingBuild), + 1, + newBuild, + ); } else { @@ -105,12 +119,21 @@ export class PresetBuildController } /** Handle SaveEquipmentBuild event */ - public saveEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse + public saveEquipmentBuild( + pmcData: IPmcData, + body: IPresetBuildActionRequestData, + sessionID: string, + ): IItemEventRouterResponse { return this.saveBuild(pmcData, body, sessionID, "equipmentBuilds"); } - protected saveBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, buildType: string): IItemEventRouterResponse + protected saveBuild( + pmcData: IPmcData, + body: IPresetBuildActionRequestData, + sessionID: string, + buildType: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); const existingSavedBuilds: any[] = this.saveServer.getProfile(sessionID).userbuilds[buildType]; @@ -125,14 +148,18 @@ export class PresetBuildController buildType: "Custom", root: body.root, fastPanel: [], - items: body.items + items: body.items, }; - const existingBuild = existingSavedBuilds.find(x => x.name === body.name); + const existingBuild = existingSavedBuilds.find((x) => x.name === body.name); if (existingBuild) { // Already exists, replace - this.saveServer.getProfile(sessionID).userbuilds[buildType].splice(existingSavedBuilds.indexOf(existingBuild), 1, newBuild); + this.saveServer.getProfile(sessionID).userbuilds[buildType].splice( + existingSavedBuilds.indexOf(existingBuild), + 1, + newBuild, + ); } else { @@ -152,26 +179,34 @@ export class PresetBuildController } /** Handle RemoveWeaponBuild event*/ - public removeWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse + public removeWeaponBuild( + pmcData: IPmcData, + body: IPresetBuildActionRequestData, + sessionID: string, + ): IItemEventRouterResponse { - // todo - does this get called? + // TODO: Does this get called? return this.removePlayerBuild(pmcData, body.id, sessionID); } /** Handle RemoveEquipmentBuild event*/ - public removeEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse + public removeEquipmentBuild( + pmcData: IPmcData, + body: IPresetBuildActionRequestData, + sessionID: string, + ): IItemEventRouterResponse { - // todo - does this get called? + // TODO: Does this get called? return this.removePlayerBuild(pmcData, body.id, sessionID); } - + protected removePlayerBuild(pmcData: IPmcData, id: string, sessionID: string): IItemEventRouterResponse { const weaponBuilds = this.saveServer.getProfile(sessionID).userbuilds.weaponBuilds; const equipmentBuilds = this.saveServer.getProfile(sessionID).userbuilds.equipmentBuilds; // Check for id in weapon array first - const matchingWeaponBuild = weaponBuilds.find(x => x.id === id); + const matchingWeaponBuild = weaponBuilds.find((x) => x.id === id); if (matchingWeaponBuild) { weaponBuilds.splice(weaponBuilds.indexOf(matchingWeaponBuild), 1); @@ -180,7 +215,7 @@ export class PresetBuildController } // Id not found in weapons, try equipment - const matchingEquipmentBuild = equipmentBuilds.find(x => x.id === id); + const matchingEquipmentBuild = equipmentBuilds.find((x) => x.id === id); if (matchingEquipmentBuild) { equipmentBuilds.splice(equipmentBuilds.indexOf(matchingEquipmentBuild), 1); @@ -191,8 +226,7 @@ export class PresetBuildController { this.logger.error(`Unable to delete preset, cannot find ${id} in weapon or equipment presets`); } - return this.eventOutputHolder.getOutput(sessionID); } -} \ No newline at end of file +} diff --git a/project/src/controllers/PresetController.ts b/project/src/controllers/PresetController.ts index 0ab8f8ed..ceaa0b12 100644 --- a/project/src/controllers/PresetController.ts +++ b/project/src/controllers/PresetController.ts @@ -9,9 +9,9 @@ export class PresetController { constructor( @inject("PresetHelper") protected presetHelper: PresetHelper, - @inject("DatabaseServer") protected databaseServer: DatabaseServer + @inject("DatabaseServer") protected databaseServer: DatabaseServer, ) - { } + {} public initialize(): void { diff --git a/project/src/controllers/ProfileController.ts b/project/src/controllers/ProfileController.ts index b8ba3455..521e5f0c 100644 --- a/project/src/controllers/ProfileController.ts +++ b/project/src/controllers/ProfileController.ts @@ -47,9 +47,9 @@ export class ProfileController @inject("TraderHelper") protected traderHelper: TraderHelper, @inject("DialogueHelper") protected dialogueHelper: DialogueHelper, @inject("QuestHelper") protected questHelper: QuestHelper, - @inject("ProfileHelper") protected profileHelper: ProfileHelper + @inject("ProfileHelper") protected profileHelper: ProfileHelper, ) - { } + {} /** * Handle /launcher/profiles @@ -76,7 +76,7 @@ export class ProfileController const pmc = profile.characters.pmc; // make sure character completed creation - if (!((pmc?.Info?.Level))) + if (!(pmc?.Info?.Level)) { return { username: profile.info.username, @@ -87,7 +87,7 @@ export class ProfileController prevexp: 0, nextlvl: 0, maxlvl: maxlvl, - akiData: this.profileHelper.getDefaultAkiDataObject() + akiData: this.profileHelper.getDefaultAkiDataObject(), }; } @@ -102,7 +102,7 @@ export class ProfileController prevexp: (currlvl === 0) ? 0 : this.profileHelper.getExperience(currlvl), nextlvl: nextlvl, maxlvl: maxlvl, - akiData: profile.aki + akiData: profile.aki, }; return result; @@ -122,7 +122,8 @@ export class ProfileController public createProfile(info: IProfileCreateRequestData, sessionID: string): void { const account = this.saveServer.getProfile(sessionID).info; - const profile: TemplateSide = this.databaseServer.getTables().templates.profiles[account.edition][info.side.toLowerCase()]; + const profile: TemplateSide = + this.databaseServer.getTables().templates.profiles[account.edition][info.side.toLowerCase()]; const pmcData = profile.character; // Delete existing profile @@ -148,11 +149,16 @@ export class ProfileController if (!pmcData.UnlockedInfo) { - pmcData.UnlockedInfo = { unlockedProductionRecipe: [] }; + pmcData.UnlockedInfo = {unlockedProductionRecipe: []}; } // Change item id's to be unique - pmcData.Inventory.items = this.itemHelper.replaceIDs(pmcData, pmcData.Inventory.items, null, pmcData.Inventory.fastPanel); + pmcData.Inventory.items = this.itemHelper.replaceIDs( + pmcData, + pmcData.Inventory.items, + null, + pmcData.Inventory.fastPanel, + ); pmcData.Inventory.hideoutAreaStashes = {}; // Create profile @@ -160,7 +166,7 @@ export class ProfileController info: account, characters: { pmc: pmcData, - scav: {} as IPmcData + scav: {} as IPmcData, }, suits: profile.suits, userbuilds: profile.userbuilds, @@ -169,7 +175,7 @@ export class ProfileController vitality: {} as Vitality, inraid: {} as Inraid, insurance: [], - traderPurchases: {} + traderPurchases: {}, }; this.profileFixerService.checkForAndFixPmcProfileIssues(profileDetails.characters.pmc); @@ -185,7 +191,11 @@ export class ProfileController // Profile is flagged as wanting quests set to ready to hand in and collect rewards if (profile.trader.setQuestsAvailableForFinish) { - this.questHelper.addAllQuestsToProfile(profileDetails.characters.pmc, [QuestStatus.AvailableForStart, QuestStatus.Started, QuestStatus.AvailableForFinish]); + this.questHelper.addAllQuestsToProfile(profileDetails.characters.pmc, [ + QuestStatus.AvailableForStart, + QuestStatus.Started, + QuestStatus.AvailableForFinish, + ]); // Make unused response so applyQuestReward works const response = this.eventOutputHolder.getOutput(sessionID); @@ -219,7 +229,9 @@ export class ProfileController } else { - this.logger.warning(this.localisationService.getText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID)); + this.logger.warning( + this.localisationService.getText("profile-unable_to_find_profile_by_id_cannot_delete", sessionID), + ); } } @@ -230,16 +242,29 @@ export class ProfileController * @param sessionID Session id * @param response Event router response */ - protected givePlayerStartingQuestRewards(profileDetails: IAkiProfile, sessionID: string, response: IItemEventRouterResponse): void + protected givePlayerStartingQuestRewards( + profileDetails: IAkiProfile, + sessionID: string, + response: IItemEventRouterResponse, + ): void { - for (const quest of profileDetails.characters.pmc.Quests) + for (const quest of profileDetails.characters.pmc.Quests) { const questFromDb = this.questHelper.getQuestFromDb(quest.qid, profileDetails.characters.pmc); // Get messageId of text to send to player as text message in game // Copy of code from QuestController.acceptQuest() - const messageId = this.questHelper.getMessageIdForQuestStart(questFromDb.startedMessageText, questFromDb.description); - const itemRewards = this.questHelper.applyQuestReward(profileDetails.characters.pmc, quest.qid, QuestStatus.Started, sessionID, response); + const messageId = this.questHelper.getMessageIdForQuestStart( + questFromDb.startedMessageText, + questFromDb.description, + ); + const itemRewards = this.questHelper.applyQuestReward( + profileDetails.characters.pmc, + quest.qid, + QuestStatus.Started, + sessionID, + response, + ); this.mailSendService.sendLocalisedNpcMessageToPlayer( sessionID, @@ -247,7 +272,8 @@ export class ProfileController MessageType.QUEST_START, messageId, itemRewards, - this.timeUtil.getHoursAsSeconds(100)); + this.timeUtil.getHoursAsSeconds(100), + ); } } @@ -266,7 +292,7 @@ export class ProfileController /** * Generate a player scav object * PMC profile MUST exist first before pscav can be generated - * @param sessionID + * @param sessionID * @returns IPmcData object */ public generatePlayerScav(sessionID: string): IPmcData @@ -323,18 +349,15 @@ export class ProfileController /** * Handle client/game/profile/search */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars public getFriends(info: ISearchFriendRequestData, sessionID: string): ISearchFriendResponse[] { - return [ - { - _id: this.hashUtil.generate(), - Info: { - Level: 1, - Side: "Bear", - Nickname: info.nickname - } - } - ]; + return [{ + _id: this.hashUtil.generate(), + Info: { + Level: 1, + Side: "Bear", + Nickname: info.nickname, + }, + }]; } -} \ No newline at end of file +} diff --git a/project/src/controllers/QuestController.ts b/project/src/controllers/QuestController.ts index dd402187..3ce39b96 100644 --- a/project/src/controllers/QuestController.ts +++ b/project/src/controllers/QuestController.ts @@ -57,7 +57,7 @@ export class QuestController @inject("LocaleService") protected localeService: LocaleService, @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("LocalisationService") protected localisationService: LocalisationService, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); @@ -79,7 +79,7 @@ export class QuestController for (const quest of allQuests) { // Player already accepted the quest, show it regardless of status - const questInProfile = profile.Quests.find(x => x.qid === quest._id); + const questInProfile = profile.Quests.find((x) => x.qid === quest._id); if (questInProfile) { quest.sptStatus = questInProfile.status; @@ -105,8 +105,12 @@ export class QuestController } const questRequirements = this.questConditionHelper.getQuestConditions(quest.conditions.AvailableForStart); - const loyaltyRequirements = this.questConditionHelper.getLoyaltyConditions(quest.conditions.AvailableForStart); - const standingRequirements = this.questConditionHelper.getStandingConditions(quest.conditions.AvailableForStart); + const loyaltyRequirements = this.questConditionHelper.getLoyaltyConditions( + quest.conditions.AvailableForStart, + ); + const standingRequirements = this.questConditionHelper.getStandingConditions( + quest.conditions.AvailableForStart, + ); // Quest has no conditions, standing or loyalty conditions, add to visible quest list if (questRequirements.length === 0 && loyaltyRequirements.length === 0 && standingRequirements.length === 0) @@ -122,14 +126,14 @@ export class QuestController for (const conditionToFulfil of questRequirements) { // If the previous quest isn't in the user profile, it hasn't been completed or started - const prerequisiteQuest = profile.Quests.find(pq => pq.qid === conditionToFulfil._props.target); + const prerequisiteQuest = profile.Quests.find((pq) => pq.qid === conditionToFulfil._props.target); if (!prerequisiteQuest) { haveCompletedPreviousQuest = false; break; } - // Prereq does not have its status requirement fulfilled + // Prerequisite does not have its status requirement fulfilled if (!conditionToFulfil._props.status.includes(prerequisiteQuest.status)) { haveCompletedPreviousQuest = false; @@ -144,7 +148,11 @@ export class QuestController const unlockTime = previousQuestCompleteTime + conditionToFulfil._props.availableAfter; if (unlockTime > this.timeUtil.getTimestamp()) { - this.logger.debug(`Quest ${quest.QuestName} is locked for another ${unlockTime - this.timeUtil.getTimestamp()} seconds`); + this.logger.debug( + `Quest ${quest.QuestName} is locked for another ${ + unlockTime - this.timeUtil.getTimestamp() + } seconds`, + ); } } } @@ -207,7 +215,7 @@ export class QuestController } // All conditions passed / has no level requirement, valid - return true; + return true; } /** @@ -221,19 +229,28 @@ export class QuestController const isHalloweenEventActive = this.seasonalEventService.halloweenEventEnabled(); // Not christmas + quest is for christmas - if (!isChristmasEventActive && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.CHRISTMAS)) + if ( + !isChristmasEventActive && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.CHRISTMAS) + ) { return false; } // Not halloween + quest is for halloween - if (!isHalloweenEventActive && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.HALLOWEEN)) + if ( + !isHalloweenEventActive && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.HALLOWEEN) + ) { return false; } // Should non-season event quests be shown to player - if (!this.questConfig.showNonSeasonalEventQuests && this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.NONE)) + if ( + !this.questConfig.showNonSeasonalEventQuests && + this.seasonalEventService.isQuestRelatedToEvent(questId, SeasonalEventType.NONE) + ) { return false; } @@ -274,7 +291,11 @@ export class QuestController * @param sessionID Session id * @returns client response */ - public acceptQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse + public acceptQuest( + pmcData: IPmcData, + acceptedQuest: IAcceptQuestRequestData, + sessionID: string, + ): IItemEventRouterResponse { const acceptQuestResponse = this.eventOutputHolder.getOutput(sessionID); @@ -282,7 +303,7 @@ export class QuestController const newQuest = this.questHelper.getQuestReadyForProfile(pmcData, startedState, acceptedQuest); // Does quest exist in profile - if (pmcData.Quests.find(x => x.qid === acceptedQuest.qid)) + if (pmcData.Quests.find((x) => x.qid === acceptedQuest.qid)) { // Update existing this.questHelper.updateQuestState(pmcData, QuestStatus.Started, acceptedQuest.qid); @@ -297,8 +318,17 @@ export class QuestController // Note that for starting quests, the correct locale field is "description", not "startedMessageText". const questFromDb = this.questHelper.getQuestFromDb(acceptedQuest.qid, pmcData); // Get messageId of text to send to player as text message in game - const messageId = this.questHelper.getMessageIdForQuestStart(questFromDb.startedMessageText, questFromDb.description); - const startedQuestRewards = this.questHelper.applyQuestReward(pmcData, acceptedQuest.qid, QuestStatus.Started, sessionID, acceptQuestResponse); + const messageId = this.questHelper.getMessageIdForQuestStart( + questFromDb.startedMessageText, + questFromDb.description, + ); + const startedQuestRewards = this.questHelper.applyQuestReward( + pmcData, + acceptedQuest.qid, + QuestStatus.Started, + sessionID, + acceptQuestResponse, + ); this.mailSendService.sendLocalisedNpcMessageToPlayer( sessionID, @@ -306,9 +336,11 @@ export class QuestController MessageType.QUEST_START, messageId, startedQuestRewards, - this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime)); + this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime), + ); - acceptQuestResponse.profileChanges[sessionID].quests = this.questHelper.getNewlyAccessibleQuestsWhenStartingQuest(acceptedQuest.qid, sessionID); + acceptQuestResponse.profileChanges[sessionID].quests = this.questHelper + .getNewlyAccessibleQuestsWhenStartingQuest(acceptedQuest.qid, sessionID); return acceptQuestResponse; } @@ -322,24 +354,36 @@ export class QuestController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public acceptRepeatableQuest(pmcData: IPmcData, acceptedQuest: IAcceptQuestRequestData, sessionID: string): IItemEventRouterResponse + public acceptRepeatableQuest( + pmcData: IPmcData, + acceptedQuest: IAcceptQuestRequestData, + sessionID: string, + ): IItemEventRouterResponse { const acceptQuestResponse = this.eventOutputHolder.getOutput(sessionID); const desiredQuestState = QuestStatus.Started; const newQuest = this.questHelper.getQuestReadyForProfile(pmcData, desiredQuestState, acceptedQuest); pmcData.Quests.push(newQuest); - + const repeatableQuestProfile = this.getRepeatableQuestFromProfile(pmcData, acceptedQuest); if (!repeatableQuestProfile) { - this.logger.error(this.localisationService.getText("repeatable-accepted_repeatable_quest_not_found_in_active_quests", acceptedQuest.qid)); + this.logger.error( + this.localisationService.getText( + "repeatable-accepted_repeatable_quest_not_found_in_active_quests", + acceptedQuest.qid, + ), + ); throw new Error(this.localisationService.getText("repeatable-unable_to_accept_quest_see_log")); } // Some scav quests need to be added to scav profile for them to show up in-raid - if (repeatableQuestProfile.side === "Scav" && ["PickUp", "Exploration", "Elimination"].includes(repeatableQuestProfile.type)) + if ( + repeatableQuestProfile.side === "Scav" && + ["PickUp", "Exploration", "Elimination"].includes(repeatableQuestProfile.type) + ) { const fullProfile = this.profileHelper.getFullProfile(sessionID); if (!fullProfile.characters.scav.Quests) @@ -351,46 +395,67 @@ export class QuestController } const locale = this.localeService.getLocaleDb(); - const questStartedMessageKey = this.questHelper.getMessageIdForQuestStart(repeatableQuestProfile.startedMessageText, repeatableQuestProfile.description); + const questStartedMessageKey = this.questHelper.getMessageIdForQuestStart( + repeatableQuestProfile.startedMessageText, + repeatableQuestProfile.description, + ); // Can be started text or description text based on above function result let questStartedMessageText = locale[questStartedMessageKey]; - // TODO: remove this whole if statement, possibly not required? + // TODO: Remove this whole if statement, possibly not required? if (!questStartedMessageText) { - this.logger.debug(`Unable to accept quest ${acceptedQuest.qid}, cannot find the quest started message text with id ${questStartedMessageKey}. attempting to find it in en locale instead`); + this.logger.debug( + `Unable to accept quest ${acceptedQuest.qid}, cannot find the quest started message text with id ${questStartedMessageKey}. attempting to find it in en locale instead`, + ); - // For some reason non-en locales dont have repeatable quest ids, fall back to en and grab it if possible + // For some reason non-en locales don't have repeatable quest ids, fall back to en and grab it if possible const enLocale = this.databaseServer.getTables().locales.global["en"]; questStartedMessageText = enLocale[repeatableQuestProfile.startedMessageText]; if (!questStartedMessageText) { - this.logger.error(this.localisationService.getText("repeatable-unable_to_accept_quest_starting_message_not_found", {questId: acceptedQuest.qid, messageId: questStartedMessageKey})); + this.logger.error( + this.localisationService.getText("repeatable-unable_to_accept_quest_starting_message_not_found", { + questId: acceptedQuest.qid, + messageId: questStartedMessageKey, + }), + ); - return this.httpResponseUtil.appendErrorToOutput(acceptQuestResponse, this.localisationService.getText("repeatable-unable_to_accept_quest_see_log")); + return this.httpResponseUtil.appendErrorToOutput( + acceptQuestResponse, + this.localisationService.getText("repeatable-unable_to_accept_quest_see_log"), + ); } } - const questRewards = this.questHelper.getQuestRewardItems(repeatableQuestProfile, desiredQuestState); + const questRewards = this.questHelper.getQuestRewardItems( + repeatableQuestProfile, + desiredQuestState, + ); this.mailSendService.sendLocalisedNpcMessageToPlayer( sessionID, this.traderHelper.getTraderById(repeatableQuestProfile.traderId), MessageType.QUEST_START, questStartedMessageKey, questRewards, - this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime)); + this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime), + ); - const repeatableSettings = pmcData.RepeatableQuests.find(x => x.name === repeatableQuestProfile.sptRepatableGroupName); + const repeatableSettings = pmcData.RepeatableQuests.find((x) => + x.name === repeatableQuestProfile.sptRepatableGroupName + ); const change = {}; change[repeatableQuestProfile._id] = repeatableSettings.changeRequirement[repeatableQuestProfile._id]; const responseData: IPmcDataRepeatableQuest = { - id: repeatableSettings.id ?? this.questConfig.repeatableQuests.find(x => x.name === repeatableQuestProfile.sptRepatableGroupName).id, + id: repeatableSettings.id ?? + this.questConfig.repeatableQuests.find((x) => x.name === repeatableQuestProfile.sptRepatableGroupName) + .id, name: repeatableSettings.name, endTime: repeatableSettings.endTime, changeRequirement: change, activeQuests: [repeatableQuestProfile], - inactiveQuests: [] + inactiveQuests: [], }; acceptQuestResponse.profileChanges[sessionID].repeatableQuests = [responseData]; @@ -407,12 +472,12 @@ export class QuestController { for (const repeatableQuest of pmcData.RepeatableQuests) { - const matchingQuest = repeatableQuest.activeQuests.find(x => x._id === acceptedQuest.qid); + const matchingQuest = repeatableQuest.activeQuests.find((x) => x._id === acceptedQuest.qid); if (matchingQuest) { this.logger.debug(`Accepted repeatable quest ${acceptedQuest.qid} from ${repeatableQuest.name}`); matchingQuest.sptRepatableGroupName = repeatableQuest.name; - + return matchingQuest; } } @@ -430,7 +495,11 @@ export class QuestController * @param sessionID Session id * @returns ItemEvent client response */ - public completeQuest(pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string): IItemEventRouterResponse + public completeQuest( + pmcData: IPmcData, + body: ICompleteQuestRequestData, + sessionID: string, + ): IItemEventRouterResponse { const completeQuestResponse = this.eventOutputHolder.getOutput(sessionID); @@ -442,7 +511,13 @@ export class QuestController const newQuestState = QuestStatus.Success; this.questHelper.updateQuestState(pmcData, newQuestState, completedQuestId); - const questRewards = this.questHelper.applyQuestReward(pmcData, body.qid, newQuestState, sessionID, completeQuestResponse); + const questRewards = this.questHelper.applyQuestReward( + pmcData, + body.qid, + newQuestState, + sessionID, + completeQuestResponse, + ); // Check for linked failed + unrestartable quests const questsToFail = this.getQuestsFailedByCompletingQuest(completedQuestId); @@ -456,8 +531,8 @@ export class QuestController // Add diff of quests before completion vs after for client response const questDelta = this.questHelper.getDeltaQuests(beforeQuests, this.getClientQuests(sessionID)); - - // Check newly available + failed quests for timegates and add them to profile + + // Check newly available + failed quests for time gates and add them to profile this.addTimeLockedQuestsToProfile(pmcData, [...questDelta, ...questsToFail], body.qid); // Inform client of quest changes @@ -466,10 +541,12 @@ export class QuestController // Check if it's a repeatable quest. If so, remove from Quests and repeatable.activeQuests list + move to repeatable.inactiveQuests for (const currentRepeatable of pmcData.RepeatableQuests) { - const repeatableQuest = currentRepeatable.activeQuests.find(x => x._id === completedQuestId); + const repeatableQuest = currentRepeatable.activeQuests.find((x) => x._id === completedQuestId); if (repeatableQuest) { - currentRepeatable.activeQuests = currentRepeatable.activeQuests.filter(x => x._id !== completedQuestId); + currentRepeatable.activeQuests = currentRepeatable.activeQuests.filter((x) => + x._id !== completedQuestId + ); currentRepeatable.inactiveQuests.push(repeatableQuest); // Need to remove redundant scav quest object as its no longer necessary, is tracked in pmc profile @@ -498,31 +575,39 @@ export class QuestController protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void { const fullProfile = this.profileHelper.getFullProfile(sessionId); - const repeatableInScavProfile = fullProfile.characters.scav.Quests.find(x => x.qid === questIdToRemove); + const repeatableInScavProfile = fullProfile.characters.scav.Quests.find((x) => x.qid === questIdToRemove); if (!repeatableInScavProfile) { - this.logger.warning(`Unable to remove quest: ${questIdToRemove} from profile as scav profile cannot be found`); + this.logger.warning( + `Unable to remove quest: ${questIdToRemove} from profile as scav profile cannot be found`, + ); return; } - fullProfile.characters.scav.Quests.splice(fullProfile.characters.scav.Quests.indexOf(repeatableInScavProfile), 1); + fullProfile.characters.scav.Quests.splice( + fullProfile.characters.scav.Quests.indexOf(repeatableInScavProfile), + 1, + ); } /** * Return quests that have different statuses - * @param preQuestStatusus Quests before + * @param preQuestStatuses Quests before * @param postQuestStatuses Quests after * @returns QuestStatusChange array */ - protected getQuestsWithDifferentStatuses(preQuestStatusus: IQuestStatus[], postQuestStatuses: IQuestStatus[]): IQuestStatus[] + protected getQuestsWithDifferentStatuses( + preQuestStatuses: IQuestStatus[], + postQuestStatuses: IQuestStatus[], + ): IQuestStatus[] { const result: IQuestStatus[] = []; for (const quest of postQuestStatuses) { // Add quest if status differs or quest not found - const preQuest = preQuestStatusus.find(x => x.qid === quest.qid); + const preQuest = preQuestStatuses.find((x) => x.qid === quest.qid); if (!preQuest || preQuest.status !== quest.status) { result.push(quest); @@ -544,7 +629,12 @@ export class QuestController * @param completedQuestId Completed quest id * @param questRewards Rewards given to player */ - protected sendSuccessDialogMessageOnQuestComplete(sessionID: string, pmcData: IPmcData, completedQuestId: string, questRewards: Reward[]): void + protected sendSuccessDialogMessageOnQuestComplete( + sessionID: string, + pmcData: IPmcData, + completedQuestId: string, + questRewards: Reward[], + ): void { const quest = this.questHelper.getQuestFromDb(completedQuestId, pmcData); @@ -554,7 +644,8 @@ export class QuestController MessageType.QUEST_SUCCESS, quest.successMessageText, questRewards, - this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime)); + this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime), + ); } /** @@ -568,15 +659,18 @@ export class QuestController // Iterate over quests, look for quests with right criteria for (const quest of quests) { - // If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time) - const nextQuestWaitCondition = quest.conditions.AvailableForStart.find(x => x._props.target === completedQuestId && x._props.availableAfter > 0); + // If quest has prerequisite of completed quest + availableAfter value > 0 (quest has wait time) + const nextQuestWaitCondition = quest.conditions.AvailableForStart.find((x) => + x._props.target === completedQuestId && x._props.availableAfter > 0 + ); if (nextQuestWaitCondition) { // Now + wait time - const availableAfterTimestamp = this.timeUtil.getTimestamp() + nextQuestWaitCondition._props.availableAfter; + const availableAfterTimestamp = this.timeUtil.getTimestamp() + + nextQuestWaitCondition._props.availableAfter; // Update quest in profile with status of AvailableAfter - const existingQuestInProfile = pmcData.Quests.find(x => x.qid === quest._id); + const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id); if (existingQuestInProfile) { existingQuestInProfile.availableAfter = availableAfterTimestamp; @@ -592,10 +686,9 @@ export class QuestController startTime: 0, status: QuestStatus.AvailableAfter, statusTimers: { - // eslint-disable-next-line @typescript-eslint/naming-convention - "9": this.timeUtil.getTimestamp() + "9": this.timeUtil.getTimestamp(), // eslint-disable-line @typescript-eslint/naming-convention }, - availableAfter: availableAfterTimestamp + availableAfter: availableAfterTimestamp, }); } } @@ -617,7 +710,7 @@ export class QuestController return false; } - return x.conditions.Fail.some(y => y._props.target === completedQuestId); + return x.conditions.Fail.some((y) => y._props.target === completedQuestId); }); } @@ -629,23 +722,28 @@ export class QuestController * @param questsToFail quests to fail * @param output Client output */ - protected failQuests(sessionID: string, pmcData: IPmcData, questsToFail: IQuest[], output: IItemEventRouterResponse): void + protected failQuests( + sessionID: string, + pmcData: IPmcData, + questsToFail: IQuest[], + output: IItemEventRouterResponse, + ): void { for (const questToFail of questsToFail) { // Skip failing a quest that has a fail status of something other than success - if (questToFail.conditions.Fail?.some(x => x._props.status?.some(y => y !== QuestStatus.Success))) + if (questToFail.conditions.Fail?.some((x) => x._props.status?.some((y) => y !== QuestStatus.Success))) { continue; } - const isActiveQuestInPlayerProfile = pmcData.Quests.find(y => y.qid === questToFail._id); + const isActiveQuestInPlayerProfile = pmcData.Quests.find((y) => y.qid === questToFail._id); if (isActiveQuestInPlayerProfile) { const failBody: IFailQuestRequestData = { Action: "QuestComplete", qid: questToFail._id, - removeExcessItems: true + removeExcessItems: true, }; this.questHelper.failQuest(pmcData, failBody, sessionID, output); } @@ -657,7 +755,7 @@ export class QuestController qid: questToFail._id, startTime: this.timeUtil.getTimestamp(), statusTimers: statusTimers, - status: QuestStatus.Fail + status: QuestStatus.Fail, }; pmcData.Quests.push(questData); } @@ -671,7 +769,11 @@ export class QuestController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public handoverQuest(pmcData: IPmcData, handoverQuestRequest: IHandoverQuestRequestData, sessionID: string): IItemEventRouterResponse + public handoverQuest( + pmcData: IPmcData, + handoverQuestRequest: IHandoverQuestRequestData, + sessionID: string, + ): IItemEventRouterResponse { const quest = this.questHelper.getQuestFromDb(handoverQuestRequest.qid, pmcData); const handoverQuestTypes = ["HandoverItem", "WeaponAssembly"]; @@ -684,20 +786,33 @@ export class QuestController let handoverRequirements: AvailableForConditions; for (const condition of quest.conditions.AvailableForFinish) { - if (condition._props.id === handoverQuestRequest.conditionId && handoverQuestTypes.includes(condition._parent)) + if ( + condition._props.id === handoverQuestRequest.conditionId && + handoverQuestTypes.includes(condition._parent) + ) { handedInCount = Number.parseInt(condition._props.value); isItemHandoverQuest = condition._parent === handoverQuestTypes[0]; handoverRequirements = condition; - const profileCounter = (handoverQuestRequest.conditionId in pmcData.BackendCounters) - ? pmcData.BackendCounters[handoverQuestRequest.conditionId].value - : 0; + const profileCounter = (handoverQuestRequest.conditionId in pmcData.BackendCounters) ? + pmcData.BackendCounters[handoverQuestRequest.conditionId].value : + 0; handedInCount -= profileCounter; if (handedInCount <= 0) { - this.logger.error(this.localisationService.getText("repeatable-quest_handover_failed_condition_already_satisfied", {questId: handoverQuestRequest.qid, conditionId: handoverQuestRequest.conditionId, profileCounter: profileCounter, value: handedInCount})); + this.logger.error( + this.localisationService.getText( + "repeatable-quest_handover_failed_condition_already_satisfied", + { + questId: handoverQuestRequest.qid, + conditionId: handoverQuestRequest.conditionId, + profileCounter: profileCounter, + value: handedInCount, + }, + ), + ); return output; } @@ -710,15 +825,20 @@ export class QuestController { return this.showRepeatableQuestInvalidConditionError(handoverQuestRequest, output); } - + let totalItemCountToRemove = 0; for (const itemHandover of handoverQuestRequest.items) { - const matchingItemInProfile = pmcData.Inventory.items.find(x => x._id === itemHandover.id); + const matchingItemInProfile = pmcData.Inventory.items.find((x) => x._id === itemHandover.id); if (!handoverRequirements._props.target.includes(matchingItemInProfile._tpl)) { - // Item handed in by player doesnt match what was requested - return this.showQuestItemHandoverMatchError(handoverQuestRequest, matchingItemInProfile, handoverRequirements, output); + // Item handed in by player doesn't match what was requested + return this.showQuestItemHandoverMatchError( + handoverQuestRequest, + matchingItemInProfile, + handoverRequirements, + output, + ); } // Remove the right quantity of given items @@ -727,7 +847,13 @@ export class QuestController if (itemHandover.count - itemCountToRemove > 0) { // Remove single item with no children - this.questHelper.changeItemStack(pmcData, itemHandover.id, itemHandover.count - itemCountToRemove, sessionID, output); + this.questHelper.changeItemStack( + pmcData, + itemHandover.id, + itemHandover.count - itemCountToRemove, + sessionID, + output, + ); if (totalItemCountToRemove === handedInCount) { break; @@ -740,7 +866,7 @@ export class QuestController let index = pmcData.Inventory.items.length; // Important: don't tell the client to remove the attachments, it will handle it - output.profileChanges[sessionID].items.del.push({ _id: itemHandover.id }); + output.profileChanges[sessionID].items.del.push({_id: itemHandover.id}); // Important: loop backward when removing items from the array we're looping on while (index-- > 0) @@ -753,7 +879,12 @@ export class QuestController } } - this.updateProfileBackendCounterValue(pmcData, handoverQuestRequest.conditionId, handoverQuestRequest.qid, totalItemCountToRemove); + this.updateProfileBackendCounterValue( + pmcData, + handoverQuestRequest.conditionId, + handoverQuestRequest.qid, + totalItemCountToRemove, + ); return output; } @@ -764,9 +895,15 @@ export class QuestController * @param output Response to send to user * @returns IItemEventRouterResponse */ - protected showRepeatableQuestInvalidConditionError(handoverQuestRequest: IHandoverQuestRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse + protected showRepeatableQuestInvalidConditionError( + handoverQuestRequest: IHandoverQuestRequestData, + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { - const errorMessage = this.localisationService.getText("repeatable-quest_handover_failed_condition_invalid", { questId: handoverQuestRequest.qid, conditionId: handoverQuestRequest.conditionId }); + const errorMessage = this.localisationService.getText("repeatable-quest_handover_failed_condition_invalid", { + questId: handoverQuestRequest.qid, + conditionId: handoverQuestRequest.conditionId, + }); this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); @@ -780,9 +917,18 @@ export class QuestController * @param output Response to send to user * @returns IItemEventRouterResponse */ - protected showQuestItemHandoverMatchError(handoverQuestRequest: IHandoverQuestRequestData, itemHandedOver: Item, handoverRequirements: AvailableForConditions, output: IItemEventRouterResponse): IItemEventRouterResponse + protected showQuestItemHandoverMatchError( + handoverQuestRequest: IHandoverQuestRequestData, + itemHandedOver: Item, + handoverRequirements: AvailableForConditions, + output: IItemEventRouterResponse, + ): IItemEventRouterResponse { - const errorMessage = this.localisationService.getText("quest-handover_wrong_item", { questId: handoverQuestRequest.qid, handedInTpl: itemHandedOver._tpl, requiredTpl: handoverRequirements._props.target[0] }); + const errorMessage = this.localisationService.getText("quest-handover_wrong_item", { + questId: handoverQuestRequest.qid, + handedInTpl: itemHandedOver._tpl, + requiredTpl: handoverRequirements._props.target[0], + }); this.logger.error(errorMessage); return this.httpResponseUtil.appendErrorToOutput(output, errorMessage); @@ -796,7 +942,12 @@ export class QuestController * @param questId quest id counter is associated with * @param counterValue value to increment the backend counter with */ - protected updateProfileBackendCounterValue(pmcData: IPmcData, conditionId: string, questId: string, counterValue: number): void + protected updateProfileBackendCounterValue( + pmcData: IPmcData, + conditionId: string, + questId: string, + counterValue: number, + ): void { if (pmcData.BackendCounters[conditionId] !== undefined) { @@ -804,10 +955,10 @@ export class QuestController return; } - pmcData.BackendCounters[conditionId] = { + pmcData.BackendCounters[conditionId] = { id: conditionId, qid: questId, - value: counterValue + value: counterValue, }; } -} \ No newline at end of file +} diff --git a/project/src/controllers/RagfairController.ts b/project/src/controllers/RagfairController.ts index 0fd7c298..313c30bb 100644 --- a/project/src/controllers/RagfairController.ts +++ b/project/src/controllers/RagfairController.ts @@ -76,7 +76,7 @@ export class RagfairController @inject("RagfairRequiredItemsService") protected ragfairRequiredItemsService: RagfairRequiredItemsService, @inject("RagfairOfferGenerator") protected ragfairOfferGenerator: RagfairOfferGenerator, @inject("LocalisationService") protected localisationService: LocalisationService, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); @@ -89,7 +89,7 @@ export class RagfairController const result: IGetOffersResult = { offers: [], offersCount: searchRequest.limit, - selectedCategory: searchRequest.handbookId + selectedCategory: searchRequest.handbookId, }; const pmcProfile = this.profileHelper.getPmcProfile(sessionID); @@ -106,7 +106,11 @@ export class RagfairController this.addIndexValueToOffers(result.offers); // Sort offers - result.offers = this.ragfairSortHelper.sortOffers(result.offers, searchRequest.sortType, searchRequest.sortDirection); + result.offers = this.ragfairSortHelper.sortOffers( + result.offers, + searchRequest.sortType, + searchRequest.sortDirection, + ); // Match offers with quests and lock unfinished quests const profile = this.profileHelper.getFullProfile(sessionID); @@ -114,13 +118,13 @@ export class RagfairController { if (offer.user.memberType === MemberCategory.TRADER) { - // for the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked to true if the quest - // is not completed yet + // for the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked + // to true if the quest is not completed yet if (this.ragfairOfferHelper.traderOfferItemQuestLocked(offer, traderAssorts)) { offer.locked = true; } - + // Update offers BuyRestrictionCurrent/BuyRestrictionMax values this.setTraderOfferPurchaseLimits(offer, profile); this.setTraderOfferStackSize(offer); @@ -132,10 +136,10 @@ export class RagfairController result.offersCount = result.offers.length; // Handle paging before returning results only if searching for general items, not preset items - if (searchRequest.buildCount === 0) + if (searchRequest.buildCount === 0) { const start = searchRequest.page * searchRequest.limit; - const end = Math.min(((searchRequest.page + 1) * searchRequest.limit), result.offers.length); + const end = Math.min((searchRequest.page + 1) * searchRequest.limit, result.offers.length); result.offers = result.offers.slice(start, end); } return result; @@ -149,7 +153,12 @@ export class RagfairController * @param pmcProfile Player profile * @returns array of offers */ - protected getOffersForSearchType(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record, pmcProfile: IPmcData): IRagfairOffer[] + protected getOffersForSearchType( + searchRequest: ISearchRequestData, + itemsToAdd: string[], + traderAssorts: Record, + pmcProfile: IPmcData, + ): IRagfairOffer[] { // Searching for items in preset menu if (searchRequest.buildCount) @@ -165,14 +174,14 @@ export class RagfairController * Get categories for the type of search being performed, linked/required/all * @param searchRequest Client search request data * @param offers ragfair offers to get categories for - * @returns record with tpls + counts + * @returns record with templates + counts */ protected getSpecificCategories(searchRequest: ISearchRequestData, offers: IRagfairOffer[]): Record { // Linked/required search categories if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest)) { - return this.ragfairServer.getBespokeCategories(offers); + return this.ragfairServer.getBespokeCategories(offers); } // Get all categories @@ -187,11 +196,16 @@ export class RagfairController /** * Add Required offers to offers result * @param searchRequest Client search request data - * @param assorts + * @param assorts * @param pmcProfile Player profile * @param result Result object being sent back to client */ - protected addRequiredOffersToResult(searchRequest: ISearchRequestData, assorts: Record, pmcProfile: IPmcData, result: IGetOffersResult): void + protected addRequiredOffersToResult( + searchRequest: ISearchRequestData, + assorts: Record, + pmcProfile: IPmcData, + result: IGetOffersResult, + ): void { const requiredOffers = this.ragfairRequiredItemsService.getRequiredItemsById(searchRequest.neededSearchId); for (const requiredOffer of requiredOffers) @@ -214,7 +228,7 @@ export class RagfairController for (const offer of offers) { offer.intId = ++counter; - offer.items[0].parentId = ""; //without this it causes error: "Item deserialization error: No parent with id hideout found for item x" + offer.items[0].parentId = ""; // Without this it causes error: "Item deserialization error: No parent with id hideout found for item x" } } @@ -239,12 +253,12 @@ export class RagfairController const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items; const assortId = offer.items[0]._id; - const assortData = traderAssorts.find(x => x._id === assortId); + const assortData = traderAssorts.find((x) => x._id === assortId); // Use value stored in profile, otherwise use value directly from in-memory trader assort data - offer.buyRestrictionCurrent = profile.traderPurchases[offer.user.id][assortId] - ? profile.traderPurchases[offer.user.id][assortId].count - : assortData.upd.BuyRestrictionCurrent; + offer.buyRestrictionCurrent = profile.traderPurchases[offer.user.id][assortId] ? + profile.traderPurchases[offer.user.id][assortId].count : + assortData.upd.BuyRestrictionCurrent; offer.buyRestrictionMax = assortData.upd.BuyRestrictionMax; } @@ -258,10 +272,15 @@ export class RagfairController const firstItem = offer.items[0]; const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items; - const assortPurchased = traderAssorts.find(x => x._id === offer.items[0]._id); + const assortPurchased = traderAssorts.find((x) => x._id === offer.items[0]._id); if (!assortPurchased) { - this.logger.warning(this.localisationService.getText("ragfair-unable_to_adjust_stack_count_assort_not_found", {offerId: offer.items[0]._id, traderId: offer.user.id})); + this.logger.warning( + this.localisationService.getText("ragfair-unable_to_adjust_stack_count_assort_not_found", { + offerId: offer.items[0]._id, + traderId: offer.user.id, + }), + ); return; } @@ -292,7 +311,7 @@ export class RagfairController /** * Called when creating an offer on flea, fills values in top right corner - * @param getPriceRequest + * @param getPriceRequest * @returns min/avg/max values for an item based on flea offers available */ public getItemMinAvgMaxFleaPriceValues(getPriceRequest: IGetMarketPriceRequestData): IGetItemPriceResult @@ -301,7 +320,7 @@ export class RagfairController let offers = this.ragfairOfferService.getOffersOfType(getPriceRequest.templateId); // Offers exist for item, get averages of what's listed - if (typeof(offers) === "object" && offers.length > 0) + if (typeof offers === "object" && offers.length > 0) { offers = this.ragfairSortHelper.sortOffers(offers, RagfairSort.PRICE); const min = offers[0].requirementsCost; // Get first item from array as its pre-sorted @@ -310,10 +329,11 @@ export class RagfairController return { avg: (min + max) / 2, min: min, - max: max + max: max, }; } - else // No offers listed, get price from live ragfair price list prices.json + // No offers listed, get price from live ragfair price list prices.json + else { const templatesDb = this.databaseServer.getTables().templates; @@ -327,7 +347,7 @@ export class RagfairController return { avg: tplPrice, min: tplPrice, - max: tplPrice + max: tplPrice, }; } } @@ -339,7 +359,11 @@ export class RagfairController * @param sessionID Session id * @returns IItemEventRouterResponse */ - public addPlayerOffer(pmcData: IPmcData, offerRequest: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse + public addPlayerOffer( + pmcData: IPmcData, + offerRequest: IAddOfferRequestData, + sessionID: string, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); @@ -351,7 +375,11 @@ export class RagfairController // Get an array of items from player inventory to list on flea const getItemsFromInventoryErrorMessage = ""; - const itemsInInventoryToList = this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items, getItemsFromInventoryErrorMessage); + const itemsInInventoryToList = this.getItemsToListOnFleaFromInventory( + pmcData, + offerRequest.items, + getItemsFromInventoryErrorMessage, + ); if (!itemsInInventoryToList) { this.httpResponse.appendErrorToOutput(output, getItemsFromInventoryErrorMessage); @@ -360,32 +388,52 @@ export class RagfairController // Checks are done, create the offer const playerListedPriceInRub = this.calculateRequirementsPriceInRub(offerRequest.requirements); const fullProfile = this.saveServer.getProfile(sessionID); - const offer = this.createPlayerOffer(fullProfile, offerRequest.requirements, this.ragfairHelper.mergeStackable(itemsInInventoryToList), offerRequest.sellInOnePiece, playerListedPriceInRub); + const offer = this.createPlayerOffer( + fullProfile, + offerRequest.requirements, + this.ragfairHelper.mergeStackable(itemsInInventoryToList), + offerRequest.sellInOnePiece, + playerListedPriceInRub, + ); const rootItem = offer.items[0]; const qualityMultiplier = this.itemHelper.getItemQualityModifier(rootItem); - const averageOfferPrice = this.ragfairPriceService.getFleaPriceForItem(rootItem._tpl) * rootItem.upd.StackObjectsCount * qualityMultiplier; - const itemStackCount = (offerRequest.sellInOnePiece) - ? 1 - : rootItem.upd.StackObjectsCount; + const averageOfferPrice = this.ragfairPriceService.getFleaPriceForItem(rootItem._tpl) * + rootItem.upd.StackObjectsCount * qualityMultiplier; + const itemStackCount = (offerRequest.sellInOnePiece) ? + 1 : + rootItem.upd.StackObjectsCount; // Get averaged price of a single item being listed - const averageSingleItemPrice = (offerRequest.sellInOnePiece) - ? averageOfferPrice / rootItem.upd.StackObjectsCount // Packs are a single offer made of many items - : averageOfferPrice / itemStackCount; - + const averageSingleItemPrice = (offerRequest.sellInOnePiece) ? + averageOfferPrice / rootItem.upd.StackObjectsCount // Packs are a single offer made of many items + : + averageOfferPrice / itemStackCount; + // Get averaged price of listing - const averagePlayerListedPriceInRub = (offerRequest.sellInOnePiece) - ? playerListedPriceInRub / rootItem.upd.StackObjectsCount - : playerListedPriceInRub; + const averagePlayerListedPriceInRub = (offerRequest.sellInOnePiece) ? + playerListedPriceInRub / rootItem.upd.StackObjectsCount : + playerListedPriceInRub; // Packs are reduced to the average price of a single item in the pack vs the averaged single price of an item - const sellChancePercent = this.ragfairSellHelper.calculateSellChance(averageSingleItemPrice, averagePlayerListedPriceInRub, qualityMultiplier); + const sellChancePercent = this.ragfairSellHelper.calculateSellChance( + averageSingleItemPrice, + averagePlayerListedPriceInRub, + qualityMultiplier, + ); offer.sellResult = this.ragfairSellHelper.rollForSale(sellChancePercent, itemStackCount); // Subtract flea market fee from stash if (this.ragfairConfig.sell.fees) { - const taxFeeChargeFailed = this.chargePlayerTaxFee(sessionID, rootItem, pmcData, playerListedPriceInRub, itemStackCount, offerRequest, output); + const taxFeeChargeFailed = this.chargePlayerTaxFee( + sessionID, + rootItem, + pmcData, + playerListedPriceInRub, + itemStackCount, + offerRequest, + output, + ); if (taxFeeChargeFailed) { return output; @@ -415,24 +463,41 @@ export class RagfairController * @param output IItemEventRouterResponse * @returns True if charging tax to player failed */ - protected chargePlayerTaxFee(sessionID: string, rootItem: Item, pmcData: IPmcData, requirementsPriceInRub: number, itemStackCount: number, offerRequest: IAddOfferRequestData, output: IItemEventRouterResponse): boolean + protected chargePlayerTaxFee( + sessionID: string, + rootItem: Item, + pmcData: IPmcData, + requirementsPriceInRub: number, + itemStackCount: number, + offerRequest: IAddOfferRequestData, + output: IItemEventRouterResponse, + ): boolean { // Get tax from cache hydrated earlier by client, if that's missing fall back to server calculation (inaccurate) const storedClientTaxValue = this.ragfairTaxService.getStoredClientOfferTaxValueById(offerRequest.items[0]); - const tax = storedClientTaxValue - ? storedClientTaxValue.fee - : this.ragfairTaxService.calculateTax(rootItem, pmcData, requirementsPriceInRub, itemStackCount, offerRequest.sellInOnePiece); + const tax = storedClientTaxValue ? + storedClientTaxValue.fee : + this.ragfairTaxService.calculateTax( + rootItem, + pmcData, + requirementsPriceInRub, + itemStackCount, + offerRequest.sellInOnePiece, + ); this.logger.debug(`Offer tax to charge: ${tax}, pulled from client: ${(!!storedClientTaxValue)}`); - //cleanup of cache now we've used the tax value from it + // cleanup of cache now we've used the tax value from it this.ragfairTaxService.clearStoredOfferTaxById(offerRequest.items[0]); const buyTradeRequest = this.createBuyTradeRequestObject("RUB", tax); output = this.paymentService.payMoney(pmcData, buyTradeRequest, sessionID, output); if (output.warnings.length > 0) { - output = this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("ragfair-unable_to_pay_commission_fee", tax)); + output = this.httpResponse.appendErrorToOutput( + output, + this.localisationService.getText("ragfair-unable_to_pay_commission_fee", tax), + ); return true; } @@ -454,7 +519,7 @@ export class RagfairController return false; } - + if (!offerRequest.requirements) { errorMessage = this.localisationService.getText("ragfair-unable_to_place_offer_with_no_requirements"); @@ -462,13 +527,13 @@ export class RagfairController return false; } - + return true; } /** * Get the handbook price in roubles for the items being listed - * @param requirements + * @param requirements * @returns Rouble price */ protected calculateRequirementsPriceInRub(requirements: Requirement[]): number @@ -477,37 +542,44 @@ export class RagfairController for (const item of requirements) { const requestedItemTpl = item._tpl; - + if (this.paymentHelper.isMoneyTpl(requestedItemTpl)) { requirementsPriceInRub += this.handbookHelper.inRUB(item.count, requestedItemTpl); } else { - requirementsPriceInRub += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count; + requirementsPriceInRub += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * + item.count; } } - + return requirementsPriceInRub; } /** - * Using item ids from flea offer request, find corrispnding items from player inventory and return as array + * Using item ids from flea offer request, find corresponding items from player inventory and return as array * @param pmcData Player profile * @param itemIdsFromFleaOfferRequest Ids from request * @param errorMessage if item is not found, add error message to this parameter * @returns Array of items from player inventory */ - protected getItemsToListOnFleaFromInventory(pmcData: IPmcData, itemIdsFromFleaOfferRequest: string[], errorMessage: string): Item[] + protected getItemsToListOnFleaFromInventory( + pmcData: IPmcData, + itemIdsFromFleaOfferRequest: string[], + errorMessage: string, + ): Item[] { const itemsToReturn = []; // Count how many items are being sold and multiply the requested amount accordingly for (const itemId of itemIdsFromFleaOfferRequest) { - let item = pmcData.Inventory.items.find(i => i._id === itemId); + let item = pmcData.Inventory.items.find((i) => i._id === itemId); if (!item) { - errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", {id: itemId}); + errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", { + id: itemId, + }); this.logger.error(errorMessage); return null; @@ -528,28 +600,34 @@ export class RagfairController return itemsToReturn; } - public createPlayerOffer(profile: IAkiProfile, requirements: Requirement[], items: Item[], sellInOnePiece: boolean, amountToSend: number): IRagfairOffer + public createPlayerOffer( + profile: IAkiProfile, + requirements: Requirement[], + items: Item[], + sellInOnePiece: boolean, + amountToSend: number, + ): IRagfairOffer { const loyalLevel = 1; - const formattedItems: Item[] = items.map(item => + const formattedItems: Item[] = items.map((item) => { - const isChild = items.find(it => it._id === item.parentId); + const isChild = items.find((it) => it._id === item.parentId); return { _id: item._id, _tpl: item._tpl, - parentId: (isChild) ? item.parentId : "hideout", - slotId: (isChild) ? item.slotId : "hideout", - upd: item.upd + parentId: isChild ? item.parentId : "hideout", + slotId: isChild ? item.slotId : "hideout", + upd: item.upd, }; }); - const formattedRequirements: IBarterScheme[] = requirements.map(item => + const formattedRequirements: IBarterScheme[] = requirements.map((item) => { return { _tpl: item._tpl, count: item.count, - onlyFunctional: item.onlyFunctional + onlyFunctional: item.onlyFunctional, }; }); @@ -559,7 +637,7 @@ export class RagfairController formattedItems, formattedRequirements, loyalLevel, - sellInOnePiece + sellInOnePiece, ); } @@ -586,21 +664,32 @@ export class RagfairController const offers = pmcData.RagfairInfo.offers; if (!offers) { - this.logger.warning(this.localisationService.getText("ragfair-unable_to_remove_offer_not_found_in_profile", {profileId: sessionID, offerId: offerId})); + this.logger.warning( + this.localisationService.getText("ragfair-unable_to_remove_offer_not_found_in_profile", { + profileId: sessionID, + offerId: offerId, + }), + ); pmcData.RagfairInfo.offers = []; } - const index = offers.findIndex(offer => offer._id === offerId); + const index = offers.findIndex((offer) => offer._id === offerId); if (index === -1) { - this.logger.error(this.localisationService.getText("ragfair-offer_not_found_in_profile", {offerId: offerId})); - return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionID), this.localisationService.getText("ragfair-offer_not_found_in_profile_short")); + this.logger.error( + this.localisationService.getText("ragfair-offer_not_found_in_profile", {offerId: offerId}), + ); + return this.httpResponse.appendErrorToOutput( + this.eventOutputHolder.getOutput(sessionID), + this.localisationService.getText("ragfair-offer_not_found_in_profile_short"), + ); } - const differenceInSeconds = (offers[index].endTime - this.timeUtil.getTimestamp()); - if (differenceInSeconds > this.ragfairConfig.sell.expireSeconds)// expireSeconds Default is 71 seconds + const differenceInSeconds = offers[index].endTime - this.timeUtil.getTimestamp(); + if (differenceInSeconds > this.ragfairConfig.sell.expireSeconds) { + // expireSeconds Default is 71 seconds const newEndTime = this.ragfairConfig.sell.expireSeconds + this.timeUtil.getTimestamp(); offers[index].endTime = Math.round(newEndTime); } @@ -613,26 +702,42 @@ export class RagfairController let output = this.eventOutputHolder.getOutput(sessionID); const pmcData = this.saveServer.getProfile(sessionID).characters.pmc; const offers = pmcData.RagfairInfo.offers; - const index = offers.findIndex(offer => offer._id === info.offerId); + const index = offers.findIndex((offer) => offer._id === info.offerId); const secondsToAdd = info.renewalTime * TimeUtil.oneHourAsSeconds; if (index === -1) { - this.logger.warning(this.localisationService.getText("ragfair-offer_not_found_in_profile", {offerId: info.offerId})); - return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionID), this.localisationService.getText("ragfair-offer_not_found_in_profile_short")); + this.logger.warning( + this.localisationService.getText("ragfair-offer_not_found_in_profile", {offerId: info.offerId}), + ); + return this.httpResponse.appendErrorToOutput( + this.eventOutputHolder.getOutput(sessionID), + this.localisationService.getText("ragfair-offer_not_found_in_profile_short"), + ); } // MOD: Pay flea market fee if (this.ragfairConfig.sell.fees) { - const count = offers[index].sellInOnePiece ? 1 : offers[index].items.reduce((sum, item) => sum += item.upd.StackObjectsCount, 0); - const tax = this.ragfairTaxService.calculateTax(offers[index].items[0], this.profileHelper.getPmcProfile(sessionID), offers[index].requirementsCost, count, offers[index].sellInOnePiece); + const count = offers[index].sellInOnePiece ? + 1 : + offers[index].items.reduce((sum, item) => sum += item.upd.StackObjectsCount, 0); + const tax = this.ragfairTaxService.calculateTax( + offers[index].items[0], + this.profileHelper.getPmcProfile(sessionID), + offers[index].requirementsCost, + count, + offers[index].sellInOnePiece, + ); const request = this.createBuyTradeRequestObject("RUB", tax); output = this.paymentService.payMoney(pmcData, request, sessionID, output); if (output.warnings.length > 0) { - return this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("ragfair-unable_to_pay_commission_fee")); + return this.httpResponse.appendErrorToOutput( + output, + this.localisationService.getText("ragfair-unable_to_pay_commission_fee"), + ); } } @@ -652,19 +757,16 @@ export class RagfairController return { tid: "ragfair", Action: "TradingConfirm", - // eslint-disable-next-line @typescript-eslint/naming-convention scheme_items: [ { id: this.paymentHelper.getCurrency(currency), - count: Math.round(value) - } + count: Math.round(value), + }, ], type: "", - // eslint-disable-next-line @typescript-eslint/naming-convention item_id: "", count: 0, - // eslint-disable-next-line @typescript-eslint/naming-convention - scheme_id: 0 + scheme_id: 0, }; } -} \ No newline at end of file +} diff --git a/project/src/controllers/RepairController.ts b/project/src/controllers/RepairController.ts index 37fc25a6..0c5607f0 100644 --- a/project/src/controllers/RepairController.ts +++ b/project/src/controllers/RepairController.ts @@ -27,9 +27,9 @@ export class RepairController @inject("TraderHelper") protected traderHelper: TraderHelper, @inject("PaymentService") protected paymentService: PaymentService, @inject("RepairHelper") protected repairHelper: RepairHelper, - @inject("RepairService") protected repairService: RepairService + @inject("RepairService") protected repairService: RepairService, ) - { } + {} /** * Handle TraderRepair event @@ -39,16 +39,27 @@ export class RepairController * @param pmcData player profile * @returns item event router action */ - public traderRepair(sessionID: string, body: ITraderRepairActionDataRequest, pmcData: IPmcData): IItemEventRouterResponse + public traderRepair( + sessionID: string, + body: ITraderRepairActionDataRequest, + pmcData: IPmcData, + ): IItemEventRouterResponse { const output = this.eventOutputHolder.getOutput(sessionID); - + // find the item to repair for (const repairItem of body.repairItems) { const repairDetails = this.repairService.repairItemByTrader(sessionID, pmcData, repairItem, body.tid); - this.repairService.payForRepair(sessionID, pmcData, repairItem._id, repairDetails.repairCost, body.tid, output); + this.repairService.payForRepair( + sessionID, + pmcData, + repairItem._id, + repairDetails.repairCost, + body.tid, + output, + ); if (output.warnings.length > 0) { @@ -78,7 +89,13 @@ export class RepairController const output = this.eventOutputHolder.getOutput(sessionID); // repair item - const repairDetails = this.repairService.repairItemByKit(sessionID, pmcData, body.repairKitsInfo, body.target, output); + const repairDetails = this.repairService.repairItemByKit( + sessionID, + pmcData, + body.repairKitsInfo, + body.target, + output, + ); this.repairService.addBuffToItem(repairDetails, pmcData); @@ -90,4 +107,4 @@ export class RepairController return output; } -} \ No newline at end of file +} diff --git a/project/src/controllers/RepeatableQuestController.ts b/project/src/controllers/RepeatableQuestController.ts index e9337c0a..531fae50 100644 --- a/project/src/controllers/RepeatableQuestController.ts +++ b/project/src/controllers/RepeatableQuestController.ts @@ -7,7 +7,11 @@ import { RagfairServerHelper } from "@spt-aki/helpers/RagfairServerHelper"; import { RepeatableQuestHelper } from "@spt-aki/helpers/RepeatableQuestHelper"; import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; -import { IChangeRequirement, IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests"; +import { + IChangeRequirement, + IPmcDataRepeatableQuest, + IRepeatableQuest, +} from "@spt-aki/models/eft/common/tables/IRepeatableQuests"; import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse"; import { IRepeatableQuestChangeRequest } from "@spt-aki/models/eft/quests/IRepeatableQuestChangeRequest"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; @@ -50,13 +54,12 @@ export class RepeatableQuestController @inject("RepeatableQuestGenerator") protected repeatableQuestGenerator: RepeatableQuestGenerator, @inject("RepeatableQuestHelper") protected repeatableQuestHelper: RepeatableQuestHelper, @inject("QuestHelper") protected questHelper: QuestHelper, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.questConfig = this.configServer.getConfig(ConfigTypes.QUEST); } - /** * Handle client/repeatalbeQuests/activityPeriods * Returns an array of objects in the format of repeatable quests to the client. @@ -69,8 +72,8 @@ export class RepeatableQuestController * } * * The method checks if the player level requirement for repeatable quests (e.g. daily lvl5, weekly lvl15) is met and if the previously active quests - * are still valid. This ischecked by endTime persisted in profile accordning to the resetTime configured for each repeatable kind (daily, weekly) - * in QuestCondig.js + * are still valid. This is checked by endTime persisted in profile according to the resetTime configured for each repeatable kind (daily, weekly) + * in QuestConfig.js * * If the condition is met, new repeatableQuests are created, old quests (which are persisted in the profile.RepeatableQuests[i].activeQuests) are * moved to profile.RepeatableQuests[i].inactiveQuests. This memory is required to get rid of old repeatable quest data in the profile, otherwise @@ -78,26 +81,28 @@ export class RepeatableQuestController * (if the are on "Succeed" but not "Completed" we keep them, to allow the player to complete them and get the rewards) * The new quests generated are again persisted in profile.RepeatableQuests * - * * @param {string} sessionId Player's session id - * @returns {array} array of "repeatableQuestObjects" as descibed above + * @returns {array} array of "repeatableQuestObjects" as described above */ public getClientRepeatableQuests(_info: IEmptyRequestData, sessionID: string): IPmcDataRepeatableQuest[] { const returnData: Array = []; const pmcData = this.profileHelper.getPmcProfile(sessionID); const time = this.timeUtil.getTimestamp(); - const scavQuestUnlocked = pmcData?.Hideout?.Areas?.find(hideoutArea => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1; - + const scavQuestUnlocked = + pmcData?.Hideout?.Areas?.find((hideoutArea) => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1; + // Daily / weekly / Daily_Savage for (const repeatableConfig of this.questConfig.repeatableQuests) { // get daily/weekly data from profile, add empty object if missing const currentRepeatableQuestType = this.getRepeatableQuestSubTypeFromProfile(repeatableConfig, pmcData); - - if (repeatableConfig.side === "Pmc" - && pmcData.Info.Level >= repeatableConfig.minPlayerLevel - || repeatableConfig.side === "Scav" && scavQuestUnlocked) + + if ( + repeatableConfig.side === "Pmc" && + pmcData.Info.Level >= repeatableConfig.minPlayerLevel || + repeatableConfig.side === "Scav" && scavQuestUnlocked + ) { if (time > currentRepeatableQuestType.endTime - 1) { @@ -110,22 +115,24 @@ export class RepeatableQuestController // after a raid (the client seems to keep quests internally and we want to get rid of old repeatable quests) // and remove them from the PMC's Quests and RepeatableQuests[i].activeQuests const questsToKeep = []; - //for (let i = 0; i < currentRepeatable.activeQuests.length; i++) + // for (let i = 0; i < currentRepeatable.activeQuests.length; i++) for (const activeQuest of currentRepeatableQuestType.activeQuests) { // check if the quest is ready to be completed, if so, don't remove it - const quest = pmcData.Quests.filter(q => q.qid === activeQuest._id); + const quest = pmcData.Quests.filter((q) => q.qid === activeQuest._id); if (quest.length > 0) { if (quest[0].status === QuestStatus.AvailableForFinish) { questsToKeep.push(activeQuest); - this.logger.debug(`Keeping repeatable quest ${activeQuest._id} in activeQuests since it is available to AvailableForFinish`); + this.logger.debug( + `Keeping repeatable quest ${activeQuest._id} in activeQuests since it is available to AvailableForFinish`, + ); continue; } } this.profileFixerService.removeDanglingConditionCounters(pmcData); - pmcData.Quests = pmcData.Quests.filter(q => q.qid !== activeQuest._id); + pmcData.Quests = pmcData.Quests.filter((q) => q.qid !== activeQuest._id); currentRepeatableQuestType.inactiveQuests.push(activeQuest); } currentRepeatableQuestType.activeQuests = questsToKeep; @@ -144,12 +151,14 @@ export class RepeatableQuestController pmcData.Info.Level, pmcData.TradersInfo, questTypePool, - repeatableConfig + repeatableConfig, ); lifeline++; if (lifeline > 10) { - this.logger.debug("We were stuck in repeatable quest generation. This should never happen. Please report"); + this.logger.debug( + "We were stuck in repeatable quest generation. This should never happen. Please report", + ); break; } } @@ -174,7 +183,7 @@ export class RepeatableQuestController { currentRepeatableQuestType.changeRequirement[quest._id] = { changeCost: quest.changeCost, - changeStandingCost: this.randomUtil.getArrayValue([0, 0.01]) + changeStandingCost: this.randomUtil.getArrayValue([0, 0.01]), }; } @@ -184,7 +193,7 @@ export class RepeatableQuestController endTime: currentRepeatableQuestType.endTime, activeQuests: currentRepeatableQuestType.activeQuests, inactiveQuests: currentRepeatableQuestType.inactiveQuests, - changeRequirement: currentRepeatableQuestType.changeRequirement + changeRequirement: currentRepeatableQuestType.changeRequirement, }); } @@ -199,10 +208,15 @@ export class RepeatableQuestController */ protected getQuestCount(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): number { - if (repeatableConfig.name.toLowerCase() === "daily" && this.profileHelper.hasEliteSkillLevel(SkillTypes.CHARISMA, pmcData)) + if ( + repeatableConfig.name.toLowerCase() === "daily" && + this.profileHelper.hasEliteSkillLevel(SkillTypes.CHARISMA, pmcData) + ) { // Elite charisma skill gives extra daily quest(s) - return repeatableConfig.numQuests + this.databaseServer.getTables().globals.config.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings.RepeatableQuestExtraCount; + return repeatableConfig.numQuests + + this.databaseServer.getTables().globals.config.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings + .RepeatableQuestExtraCount; } return repeatableConfig.numQuests; @@ -214,10 +228,13 @@ export class RepeatableQuestController * @param pmcData Profile to search * @returns IPmcDataRepeatableQuest */ - protected getRepeatableQuestSubTypeFromProfile(repeatableConfig: IRepeatableQuestConfig, pmcData: IPmcData): IPmcDataRepeatableQuest + protected getRepeatableQuestSubTypeFromProfile( + repeatableConfig: IRepeatableQuestConfig, + pmcData: IPmcData, + ): IPmcDataRepeatableQuest { // Get from profile, add if missing - let repeatableQuestDetails = pmcData.RepeatableQuests.find(x => x.name === repeatableConfig.name); + let repeatableQuestDetails = pmcData.RepeatableQuests.find((x) => x.name === repeatableConfig.name); if (!repeatableQuestDetails) { repeatableQuestDetails = { @@ -226,7 +243,7 @@ export class RepeatableQuestController activeQuests: [], inactiveQuests: [], endTime: 0, - changeRequirement: {} + changeRequirement: {}, }; // Add base object that holds repeatable data to profile @@ -297,16 +314,16 @@ export class RepeatableQuestController // Target is boss if (probabilityObject.data.isBoss) { - questPool.pool.Elimination.targets[probabilityObject.key] = { locations: ["any"] }; + questPool.pool.Elimination.targets[probabilityObject.key] = {locations: ["any"]}; } else { const possibleLocations = Object.keys(repeatableConfig.locations); - // Set possible locations for elimination task, ift arget is savage, exclude labs from locations - questPool.pool.Elimination.targets[probabilityObject.key] = (probabilityObject.key === "Savage") - ? { locations: possibleLocations.filter(x => x !== "laboratory")} - : { locations: possibleLocations }; + // Set possible locations for elimination task, if target is savage, exclude labs from locations + questPool.pool.Elimination.targets[probabilityObject.key] = (probabilityObject.key === "Savage") ? + {locations: possibleLocations.filter((x) => x !== "laboratory")} : + {locations: possibleLocations}; } } @@ -319,15 +336,15 @@ export class RepeatableQuestController types: repeatableConfig.types.slice(), pool: { Exploration: { - locations: {} + locations: {}, }, Elimination: { - targets: {} + targets: {}, }, Pickup: { - locations: {} - } - } + locations: {}, + }, + }, }; } @@ -355,7 +372,11 @@ export class RepeatableQuestController /** * Handle RepeatableQuestChange event */ - public changeRepeatableQuest(pmcData: IPmcData, changeRequest: IRepeatableQuestChangeRequest, sessionID: string): IItemEventRouterResponse + public changeRepeatableQuest( + pmcData: IPmcData, + changeRequest: IRepeatableQuestChangeRequest, + sessionID: string, + ): IItemEventRouterResponse { let repeatableToChange: IPmcDataRepeatableQuest; let changeRequirement: IChangeRequirement; @@ -367,24 +388,29 @@ export class RepeatableQuestController for (const currentRepeatablePool of pmcData.RepeatableQuests) { // Check for existing quest in (daily/weekly/scav arrays) - const questToReplace = currentRepeatablePool.activeQuests.find(x => x._id === changeRequest.qid); + const questToReplace = currentRepeatablePool.activeQuests.find((x) => x._id === changeRequest.qid); if (!questToReplace) { continue; } - + // Save for later standing loss calculation replacedQuestTraderId = questToReplace.traderId; // Update active quests to exclude the quest we're replacing - currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter(x => x._id !== changeRequest.qid); + currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter((x) => + x._id !== changeRequest.qid + ); // Get cost to replace existing quest changeRequirement = this.jsonUtil.clone(currentRepeatablePool.changeRequirement[changeRequest.qid]); delete currentRepeatablePool.changeRequirement[changeRequest.qid]; - // TODO: somehow we need to reduce the questPool by the currently active quests (for all repeatables) - - const repeatableConfig = this.questConfig.repeatableQuests.find(x => x.name === currentRepeatablePool.name); + + // TODO: somehow we need to reduce the questPool by the currently active quests (for all repeatable) + + const repeatableConfig = this.questConfig.repeatableQuests.find((x) => + x.name === currentRepeatablePool.name + ); const questTypePool = this.generateQuestPool(repeatableConfig, pmcData.Info.Level); const newRepeatableQuest = this.attemptToGenerateRepeatableQuest(pmcData, questTypePool, repeatableConfig); if (newRepeatableQuest) @@ -394,16 +420,19 @@ export class RepeatableQuestController currentRepeatablePool.activeQuests.push(newRepeatableQuest); currentRepeatablePool.changeRequirement[newRepeatableQuest._id] = { changeCost: newRepeatableQuest.changeCost, - changeStandingCost: this.randomUtil.getArrayValue([0, 0.01]) + changeStandingCost: this.randomUtil.getArrayValue([0, 0.01]), }; const fullProfile = this.profileHelper.getFullProfile(sessionID); // Find quest we're replacing in pmc profile quests array and remove it this.questHelper.findAndRemoveQuestFromArrayIfExists(questToReplace._id, pmcData.Quests); - + // Find quest we're replacing in scav profile quests array and remove it - this.questHelper.findAndRemoveQuestFromArrayIfExists(questToReplace._id, fullProfile.characters.scav?.Quests ?? []); + this.questHelper.findAndRemoveQuestFromArrayIfExists( + questToReplace._id, + fullProfile.characters.scav?.Quests ?? [], + ); } // Found and replaced the quest in current repeatable @@ -442,7 +471,11 @@ export class RepeatableQuestController return output; } - protected attemptToGenerateRepeatableQuest(pmcData: IPmcData, questTypePool: IQuestTypePool, repeatableConfig: IRepeatableQuestConfig): IRepeatableQuest + protected attemptToGenerateRepeatableQuest( + pmcData: IPmcData, + questTypePool: IQuestTypePool, + repeatableConfig: IRepeatableQuestConfig, + ): IRepeatableQuest { let newRepeatableQuest: IRepeatableQuest = null; let attemptsToGenerateQuest = 0; @@ -452,16 +485,17 @@ export class RepeatableQuestController pmcData.Info.Level, pmcData.TradersInfo, questTypePool, - repeatableConfig + repeatableConfig, ); attemptsToGenerateQuest++; if (attemptsToGenerateQuest > 10) { - this.logger.debug("We were stuck in repeatable quest generation. This should never happen. Please report"); + this.logger.debug( + "We were stuck in repeatable quest generation. This should never happen. Please report", + ); break; } } - return newRepeatableQuest; } } diff --git a/project/src/controllers/TradeController.ts b/project/src/controllers/TradeController.ts index c891fd97..db399e4b 100644 --- a/project/src/controllers/TradeController.ts +++ b/project/src/controllers/TradeController.ts @@ -29,7 +29,7 @@ import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil"; import { JsonUtil } from "@spt-aki/utils/JsonUtil"; @injectable() -class TradeController +export class TradeController { protected ragfairConfig: IRagfairConfig; protected traderConfig: ITraderConfig; @@ -46,7 +46,7 @@ class TradeController @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); @@ -54,34 +54,56 @@ class TradeController } /** Handle TradingConfirm event */ - public confirmTrading(pmcData: IPmcData, request: IProcessBaseTradeRequestData, sessionID: string): IItemEventRouterResponse + public confirmTrading( + pmcData: IPmcData, + request: IProcessBaseTradeRequestData, + sessionID: string, + ): IItemEventRouterResponse { return this.confirmTradingInternal(pmcData, request, sessionID, this.traderConfig.purchasesAreFoundInRaid); } /** Handle RagFairBuyOffer event */ - public confirmRagfairTrading(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse + public confirmRagfairTrading( + pmcData: IPmcData, + body: IProcessRagfairTradeRequestData, + sessionID: string, + ): IItemEventRouterResponse { let output = this.eventOutputHolder.getOutput(sessionID); for (const offer of body.offers) { const fleaOffer = this.ragfairServer.getOffer(offer.id); - if (!fleaOffer) + if (!fleaOffer) { - return this.httpResponse.appendErrorToOutput(output, `Offer with ID ${offer.id} not found`, BackendErrorCodes.OFFERNOTFOUND); + return this.httpResponse.appendErrorToOutput( + output, + `Offer with ID ${offer.id} not found`, + BackendErrorCodes.OFFERNOTFOUND, + ); } if (offer.count === 0) { - const errorMessage = this.localisationService.getText("ragfair-unable_to_purchase_0_count_item", this.itemHelper.getItem(fleaOffer.items[0]._tpl)[1]._name); + const errorMessage = this.localisationService.getText( + "ragfair-unable_to_purchase_0_count_item", + this.itemHelper.getItem(fleaOffer.items[0]._tpl)[1]._name, + ); return this.httpResponse.appendErrorToOutput(output, errorMessage, BackendErrorCodes.OFFEROUTOFSTOCK); } // Skip buying items when player doesn't have necessary loyalty - if (fleaOffer.user.memberType === MemberCategory.TRADER && fleaOffer.loyaltyLevel > pmcData.TradersInfo[fleaOffer.user.id].loyaltyLevel) + if ( + fleaOffer.user.memberType === MemberCategory.TRADER && + fleaOffer.loyaltyLevel > pmcData.TradersInfo[fleaOffer.user.id].loyaltyLevel + ) { - this.logger.debug(`Unable to buy item: ${fleaOffer.items[0]._tpl} from trader: ${fleaOffer.user.id} as loyalty level too low, skipping`); + this.logger.debug( + `Unable to buy item: ${ + fleaOffer.items[0]._tpl + } from trader: ${fleaOffer.user.id} as loyalty level too low, skipping`, + ); continue; } @@ -91,17 +113,21 @@ class TradeController Action: "TradingConfirm", type: "buy_from_trader", tid: (fleaOffer.user.memberType !== MemberCategory.TRADER) ? "ragfair" : fleaOffer.user.id, - // eslint-disable-next-line @typescript-eslint/naming-convention item_id: fleaOffer.root, count: offer.count, - // eslint-disable-next-line @typescript-eslint/naming-convention scheme_id: 0, - // eslint-disable-next-line @typescript-eslint/naming-convention - scheme_items: offer.items + scheme_items: offer.items, }; - // confirmTrading() must occur prior to removing the offer stack, otherwise item inside offer doesn't exist for confirmTrading() to use - output = this.confirmTradingInternal(pmcData, buyData, sessionID, this.ragfairConfig.dynamic.purchasesAreFoundInRaid, fleaOffer.items[0].upd); + // confirmTrading() must occur prior to removing the offer stack, otherwise item inside offer doesn't exist + // for confirmTrading() to use + output = this.confirmTradingInternal( + pmcData, + buyData, + sessionID, + this.ragfairConfig.dynamic.purchasesAreFoundInRaid, + fleaOffer.items[0].upd, + ); if (fleaOffer.user.memberType !== MemberCategory.TRADER) { // remove player item offer stack @@ -113,30 +139,42 @@ class TradeController } /** Handle SellAllFromSavage event */ - public sellScavItemsToFence(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse + public sellScavItemsToFence( + pmcData: IPmcData, + body: ISellScavItemsToFenceRequestData, + sessionId: string, + ): IItemEventRouterResponse { const scavProfile = this.profileHelper.getFullProfile(sessionId)?.characters?.scav; if (!scavProfile) { - return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionId), `Profile ${body.fromOwner.id} has no scav account`); + return this.httpResponse.appendErrorToOutput( + this.eventOutputHolder.getOutput(sessionId), + `Profile ${body.fromOwner.id} has no scav account`, + ); } return this.sellInventoryToTrader(sessionId, scavProfile, pmcData, Traders.FENCE); } /** - * Sell all sellable items to a trader from inventory + * Sell all items (that can be sold) to a trader from inventory * WILL DELETE ITEMS FROM INVENTORY + CHILDREN OF ITEMS SOLD * @param sessionId Session id - * @param profileWithItemsToSell Profile with items to be sold to trader + * @param profileWithItemsToSell Profile with items to be sold to trader * @param profileThatGetsMoney Profile that gets the money after selling items * @param trader Trader to sell items to * @returns IItemEventRouterResponse */ - protected sellInventoryToTrader(sessionId: string, profileWithItemsToSell: IPmcData, profileThatGetsMoney: IPmcData, trader: Traders): IItemEventRouterResponse + protected sellInventoryToTrader( + sessionId: string, + profileWithItemsToSell: IPmcData, + profileThatGetsMoney: IPmcData, + trader: Traders, + ): IItemEventRouterResponse { const handbookPrices = this.ragfairPriceService.getAllStaticPrices(); - // TODO, apply trader sell bonuses? + // TODO: apply trader sell bonuses? const traderDetails = this.traderHelper.getTrader(trader, sessionId); // Prep request object @@ -145,16 +183,23 @@ class TradeController type: "sell_to_trader", tid: trader, price: 0, - items: [] + items: [], }; // Get all base items that scav has (primaryweapon/backpack/pockets etc) // Add items that trader will buy (only sell items that have the container as parent) to request object - const containerAndEquipmentItems = profileWithItemsToSell.Inventory.items.filter(x => x.parentId === profileWithItemsToSell.Inventory.equipment); + const containerAndEquipmentItems = profileWithItemsToSell.Inventory.items.filter((x) => + x.parentId === profileWithItemsToSell.Inventory.equipment + ); for (const itemToSell of containerAndEquipmentItems) { // Increment sell price in request - sellRequest.price += this.getPriceOfItemAndChildren(itemToSell._id, profileWithItemsToSell.Inventory.items, handbookPrices, traderDetails); + sellRequest.price += this.getPriceOfItemAndChildren( + itemToSell._id, + profileWithItemsToSell.Inventory.items, + handbookPrices, + traderDetails, + ); // Add item details to request // eslint-disable-next-line @typescript-eslint/naming-convention @@ -172,7 +217,12 @@ class TradeController * @param traderDetails Trader being sold to to perform buy category check against * @returns Rouble price */ - protected getPriceOfItemAndChildren(parentItemId: string, items: Item[], handbookPrices: Record, traderDetails: ITraderBase): number + protected getPriceOfItemAndChildren( + parentItemId: string, + items: Item[], + handbookPrices: Record, + traderDetails: ITraderBase, + ): number { const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(items, parentItemId); @@ -180,9 +230,12 @@ class TradeController for (const itemToSell of itemWithChildren) { const itemDetails = this.itemHelper.getItem(itemToSell._tpl); - if (!(itemDetails[0] && this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category))) + if ( + !(itemDetails[0] && + this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category)) + ) { - // Skip if tpl isnt item OR item doesn't fulfill match traders buy categories + // Skip if tpl isn't item OR item doesn't fulfill match traders buy categories continue; } @@ -193,7 +246,13 @@ class TradeController return totalPrice; } - protected confirmTradingInternal(pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string, foundInRaid = false, upd: Upd = null): IItemEventRouterResponse + protected confirmTradingInternal( + pmcData: IPmcData, + body: IProcessBaseTradeRequestData, + sessionID: string, + foundInRaid = false, + upd: Upd = null, + ): IItemEventRouterResponse { // buying if (body.type === "buy_from_trader") @@ -212,6 +271,3 @@ class TradeController return null; } } - -export { TradeController }; - diff --git a/project/src/controllers/TraderController.ts b/project/src/controllers/TraderController.ts index de7fc77d..29301929 100644 --- a/project/src/controllers/TraderController.ts +++ b/project/src/controllers/TraderController.ts @@ -23,12 +23,13 @@ export class TraderController @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("TraderHelper") protected traderHelper: TraderHelper, @inject("TraderAssortService") protected traderAssortService: TraderAssortService, - @inject("TraderPurchasePersisterService") protected traderPurchasePersisterService: TraderPurchasePersisterService, + @inject("TraderPurchasePersisterService") protected traderPurchasePersisterService: + TraderPurchasePersisterService, @inject("FenceService") protected fenceService: FenceService, @inject("FenceBaseAssortGenerator") protected fenceBaseAssortGenerator: FenceBaseAssortGenerator, - @inject("JsonUtil") protected jsonUtil: JsonUtil + @inject("JsonUtil") protected jsonUtil: JsonUtil, ) - { } + {} /** * Runs when onLoad event is fired @@ -93,7 +94,7 @@ export class TraderController } const trader = this.databaseServer.getTables().traders[traderId]; - + // trader needs to be refreshed if (this.traderAssortHelper.traderAssortsHaveExpired(traderId)) { @@ -132,7 +133,7 @@ export class TraderController } } - return traders.sort((a, b) => this.sortByTraderId(a,b)); + return traders.sort((a, b) => this.sortByTraderId(a, b)); } /** @@ -167,4 +168,4 @@ export class TraderController { return this.traderAssortHelper.getAssort(sessionId, traderId); } -} \ No newline at end of file +} diff --git a/project/src/controllers/WeatherController.ts b/project/src/controllers/WeatherController.ts index 216424f6..eca193db 100644 --- a/project/src/controllers/WeatherController.ts +++ b/project/src/controllers/WeatherController.ts @@ -15,7 +15,7 @@ export class WeatherController constructor( @inject("WeatherGenerator") protected weatherGenerator: WeatherGenerator, @inject("WinstonLogger") protected logger: ILogger, - @inject("ConfigServer") protected configServer: ConfigServer + @inject("ConfigServer") protected configServer: ConfigServer, ) { this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER); @@ -28,7 +28,7 @@ export class WeatherController acceleration: 0, time: "", date: "", - weather: null + weather: null, }; result = this.weatherGenerator.calculateGameTime(result); @@ -45,4 +45,4 @@ export class WeatherController { return this.weatherGenerator.getInRaidTime(new Date()); } -} \ No newline at end of file +} diff --git a/project/src/controllers/WishlistController.ts b/project/src/controllers/WishlistController.ts index eaa7d8e4..aae3f9e5 100644 --- a/project/src/controllers/WishlistController.ts +++ b/project/src/controllers/WishlistController.ts @@ -9,16 +9,16 @@ import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder"; export class WishlistController { constructor( - @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder + @inject("EventOutputHolder") protected eventOutputHolder: EventOutputHolder, ) - { } + {} /** Handle AddToWishList */ public addToWishList(pmcData: IPmcData, body: IWishlistActionData, sessionID: string): IItemEventRouterResponse { for (const item in pmcData.WishList) { - // don't add the item + // Don't add the item if (pmcData.WishList[item] === body.templateId) { return this.eventOutputHolder.getOutput(sessionID); @@ -43,4 +43,4 @@ export class WishlistController return this.eventOutputHolder.getOutput(sessionID); } -} \ No newline at end of file +}