From 1c9acbbc2e4459be8f49850996cc444f7a6e0660 Mon Sep 17 00:00:00 2001 From: Dev Date: Fri, 19 Jan 2024 19:21:51 +0000 Subject: [PATCH] improve bot generation time --- project/src/controllers/BotController.ts | 143 +++++++++++++----- .../generators/BotEquipmentModGenerator.ts | 2 +- project/src/generators/BotGenerator.ts | 45 +++--- project/src/generators/BotLootGenerator.ts | 2 +- 4 files changed, 125 insertions(+), 67 deletions(-) diff --git a/project/src/controllers/BotController.ts b/project/src/controllers/BotController.ts index 593ac00c..d24a654f 100644 --- a/project/src/controllers/BotController.ts +++ b/project/src/controllers/BotController.ts @@ -7,6 +7,7 @@ import { BotDifficultyHelper } from "@spt-aki/helpers/BotDifficultyHelper"; import { BotHelper } from "@spt-aki/helpers/BotHelper"; import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper"; import { IGenerateBotsRequestData } from "@spt-aki/models/eft/bot/IGenerateBotsRequestData"; +import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { IBotBase } from "@spt-aki/models/eft/common/tables/IBotBase"; import { IBotCore } from "@spt-aki/models/eft/common/tables/IBotCore"; import { Difficulty } from "@spt-aki/models/eft/common/tables/IBotType"; @@ -145,8 +146,25 @@ export class BotController { const pmcProfile = this.profileHelper.getPmcProfile(sessionId); - const botsToReturn: IBotBase[] = []; - for (const condition of info.conditions) + const isFirstGen = info.conditions.length > 1; + if (isFirstGen) + { + return this.generateBotsFirstTime(info, pmcProfile, sessionId); + } + + return this.returnSingleBotFromCache(sessionId, info); + } + + /** + * On first bot generation bots are generated and stored inside a cache, ready to be used later + * @param request Bot generation request object + * @param pmcProfile Player profile + * @param sessionId Session id + * @returns + */ + protected generateBotsFirstTime(request: IGenerateBotsRequestData, pmcProfile: IPmcData, sessionId: string): IBotBase[] + { + for (const condition of request.conditions) { const botGenerationDetails: BotGenerationDetails = { isPmc: false, @@ -167,7 +185,7 @@ 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.eventRole ); } @@ -179,53 +197,104 @@ export class BotController botGenerationDetails.side = this.botHelper.getPmcSideByRole(condition.Role); } - // Loop over and make x bots for this condition + // Loop over and make x bots for this bot wave let cacheKey = ""; for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) { const details = this.jsonUtil.clone(botGenerationDetails); - 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()]; - if (botConvertRateMinMax) - { - // Should bot become PMC - const convertToPmc = this.botHelper.rollChanceToBePmc(details.role, botConvertRateMinMax); - if (convertToPmc) - { - details.isPmc = true; - details.role = this.botHelper.getRandomizedPmcRole(); - details.side = this.botHelper.getPmcSideByRole(details.role); - details.botDifficulty = this.getPMCDifficulty(details.botDifficulty); - } - } cacheKey = `${details.role}${details.botDifficulty}`; - // Check for bot in cache, add if not - if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) - { - // Generate and add x bots to cache - const botsToAddToCache = this.botGenerator.prepareAndGenerateBots(sessionId, details); - this.botGenerationCacheService.storeBots(cacheKey, botsToAddToCache); - } + // Generate and add bot to cache + const botToCache = this.botGenerator.prepareAndGenerateBot(sessionId, details); + this.botGenerationCacheService.storeBots(cacheKey, [botToCache]); } + this.logger.debug( + `Generated ${botGenerationDetails.botCountToGenerate} ${botGenerationDetails.role} (${ + botGenerationDetails.eventRole ?? "" + }) ${botGenerationDetails.botDifficulty} bots`, + ); + // Get bot from cache, add to return array const botToReturn = this.botGenerationCacheService.getBot(cacheKey); - - if (info.conditions.length === 1) - { - // Cache bot when we're returning 1 bot, this indicated the bot is being requested to be spawned - // Used by PMC response text system - this.matchBotDetailsCacheService.cacheBot(botToReturn); - } - - botsToReturn.push(botToReturn); } - return botsToReturn; + return []; + } + + /** + * Pull a single bot out of cache and return, if cache is empty add bots to it and then return + * @param sessionId Session id + * @param request Bot generation request object + * @returns Single IBotBase object + */ + protected returnSingleBotFromCache(sessionId: string, request: IGenerateBotsRequestData): IBotBase[] + { + const pmcProfile = this.profileHelper.getPmcProfile(sessionId); + const requestedBot = request.conditions[0]; + + // Create gen request for when cache is empty + const botGenerationDetails: BotGenerationDetails = { + isPmc: false, + side: "Savage", + role: requestedBot.Role, + playerLevel: pmcProfile.Info.Level, + botRelativeLevelDeltaMax: this.pmcConfig.botRelativeLevelDeltaMax, + botRelativeLevelDeltaMin: this.pmcConfig.botRelativeLevelDeltaMin, + botCountToGenerate: this.botConfig.presetBatch[requestedBot.Role], + botDifficulty: requestedBot.Difficulty, + isPlayerScav: false, + }; + + // Event bots need special actions to occur, set data up for them + const isEventBot = requestedBot.Role.toLowerCase().includes("event"); + if (isEventBot) + { + // Add eventRole data + reassign role property + botGenerationDetails.eventRole = requestedBot.Role; + botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot( + botGenerationDetails.eventRole, + ); + } + + // Roll chance to be pmc if type is allowed to be one + const botConvertRateMinMax = this.pmcConfig.convertIntoPmcChance[requestedBot.Role.toLowerCase()]; + if (botConvertRateMinMax) + { + // Should bot become PMC + const convertToPmc = this.botHelper.rollChanceToBePmc(requestedBot.Role, botConvertRateMinMax); + if (convertToPmc) + { + botGenerationDetails.isPmc = true; + botGenerationDetails.role = this.botHelper.getRandomizedPmcRole(); + botGenerationDetails.side = this.botHelper.getPmcSideByRole(requestedBot.Role); + botGenerationDetails.botDifficulty = this.getPMCDifficulty(requestedBot.Difficulty); + botGenerationDetails.botCountToGenerate = this.botConfig.presetBatch[requestedBot.Role]; + } + } + + // Construct cache key + const cacheKey = `${requestedBot.Role}${requestedBot.Difficulty}`; + + // Check cache for bot using above key + if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) + { + // No bot in cache, generate new and return one + for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) + { + const botToCache = this.botGenerator.prepareAndGenerateBot(sessionId, botGenerationDetails); + this.botGenerationCacheService.storeBots(cacheKey, [botToCache]); + } + + this.logger.debug( + `Generated ${botGenerationDetails.botCountToGenerate} ${botGenerationDetails.role} (${ + botGenerationDetails.eventRole ?? "" + }) ${botGenerationDetails.botDifficulty} bots`, + ); + } + + return [this.botGenerationCacheService.getBot(cacheKey)]; } /** diff --git a/project/src/generators/BotEquipmentModGenerator.ts b/project/src/generators/BotEquipmentModGenerator.ts index b5ae1007..3962bdbc 100644 --- a/project/src/generators/BotEquipmentModGenerator.ts +++ b/project/src/generators/BotEquipmentModGenerator.ts @@ -115,7 +115,7 @@ export class BotEquipmentModGenerator const outcome = this.filterPlateModsForSlotByLevel(settings, modSlot.toLowerCase(), compatibleModsPool[modSlot], parentTemplate); if ([Result.UNKNOWN_FAILURE, Result.NO_DEFAULT_FILTER].includes(outcome.result)) { - this.logger.warning(`Plate slot: ${modSlot} selection for armor: ${parentTemplate._id} failed: ${Result[outcome.result]}, skipping`); + this.logger.debug(`Plate slot: ${modSlot} selection for armor: ${parentTemplate._id} failed: ${Result[outcome.result]}, skipping`); continue; } diff --git a/project/src/generators/BotGenerator.ts b/project/src/generators/BotGenerator.ts index 7c9c9bc2..b45fe1de 100644 --- a/project/src/generators/BotGenerator.ts +++ b/project/src/generators/BotGenerator.ts @@ -95,41 +95,30 @@ export class BotGenerator } /** - * Create x number of bots of the type/side/difficulty defined in botGenerationDetails + * Create 1 bots of the type/side/difficulty defined in botGenerationDetails * @param sessionId Session id * @param botGenerationDetails details on how to generate bots - * @returns array of bots + * @returns constructed bot */ - public prepareAndGenerateBots(sessionId: string, botGenerationDetails: BotGenerationDetails): IBotBase[] + public prepareAndGenerateBot(sessionId: string, botGenerationDetails: BotGenerationDetails): IBotBase { - const output: IBotBase[] = []; - for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) - { - let bot = this.getCloneOfBotBase(); + let bot = this.getCloneOfBotBase(); + bot.Info.Settings.Role = botGenerationDetails.eventRole + ? botGenerationDetails.eventRole + : botGenerationDetails.role; + bot.Info.Side = botGenerationDetails.side; + bot.Info.Settings.BotDifficulty = botGenerationDetails.botDifficulty; - bot.Info.Settings.Role = botGenerationDetails.role; - bot.Info.Side = botGenerationDetails.side; - bot.Info.Settings.BotDifficulty = botGenerationDetails.botDifficulty; - - // Get raw json data for bot (Cloned) - const botJsonTemplate = this.jsonUtil.clone( - this.botHelper.getBotTemplate((botGenerationDetails.isPmc) - ? bot.Info.Side - : botGenerationDetails.role), - ); - - bot = this.generateBot(sessionId, bot, botJsonTemplate, botGenerationDetails); - - output.push(bot); - } - - this.logger.debug( - `Generated ${botGenerationDetails.botCountToGenerate} ${output[0].Info.Settings.Role} (${ - botGenerationDetails.eventRole ?? "" - }) bots`, + // Get raw json data for bot (Cloned) + const botJsonTemplate = this.jsonUtil.clone( + this.botHelper.getBotTemplate((botGenerationDetails.isPmc) + ? bot.Info.Side + : botGenerationDetails.role), ); - return output; + bot = this.generateBot(sessionId, bot, botJsonTemplate, botGenerationDetails); + + return bot; } /** diff --git a/project/src/generators/BotLootGenerator.ts b/project/src/generators/BotLootGenerator.ts index a2b0efe4..b722485d 100644 --- a/project/src/generators/BotLootGenerator.ts +++ b/project/src/generators/BotLootGenerator.ts @@ -210,7 +210,7 @@ export class BotLootGenerator this.addLootFromPool( this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate), [EquipmentSlots.SECURED_CONTAINER], - 100, + 50, botInventory, botRole, false,