improve bot generation time

This commit is contained in:
Dev 2024-01-19 19:21:51 +00:00
parent cdb5baac4b
commit 1c9acbbc2e
4 changed files with 125 additions and 67 deletions

View File

@ -7,6 +7,7 @@ import { BotDifficultyHelper } from "@spt-aki/helpers/BotDifficultyHelper";
import { BotHelper } from "@spt-aki/helpers/BotHelper"; import { BotHelper } from "@spt-aki/helpers/BotHelper";
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper"; import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
import { IGenerateBotsRequestData } from "@spt-aki/models/eft/bot/IGenerateBotsRequestData"; 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 { IBotBase } from "@spt-aki/models/eft/common/tables/IBotBase";
import { IBotCore } from "@spt-aki/models/eft/common/tables/IBotCore"; import { IBotCore } from "@spt-aki/models/eft/common/tables/IBotCore";
import { Difficulty } from "@spt-aki/models/eft/common/tables/IBotType"; import { Difficulty } from "@spt-aki/models/eft/common/tables/IBotType";
@ -145,8 +146,25 @@ export class BotController
{ {
const pmcProfile = this.profileHelper.getPmcProfile(sessionId); const pmcProfile = this.profileHelper.getPmcProfile(sessionId);
const botsToReturn: IBotBase[] = []; const isFirstGen = info.conditions.length > 1;
for (const condition of info.conditions) 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 = { const botGenerationDetails: BotGenerationDetails = {
isPmc: false, isPmc: false,
@ -167,7 +185,7 @@ export class BotController
// Add eventRole data + reassign role property to be base type // Add eventRole data + reassign role property to be base type
botGenerationDetails.eventRole = condition.Role; botGenerationDetails.eventRole = condition.Role;
botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot( botGenerationDetails.role = this.seasonalEventService.getBaseRoleForEventBot(
botGenerationDetails.eventRole, botGenerationDetails.eventRole
); );
} }
@ -179,53 +197,104 @@ export class BotController
botGenerationDetails.side = this.botHelper.getPmcSideByRole(condition.Role); 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 = ""; 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 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}`; cacheKey = `${details.role}${details.botDifficulty}`;
// Check for bot in cache, add if not // Generate and add bot to cache
if (!this.botGenerationCacheService.cacheHasBotOfRole(cacheKey)) const botToCache = this.botGenerator.prepareAndGenerateBot(sessionId, details);
{ this.botGenerationCacheService.storeBots(cacheKey, [botToCache]);
// Generate and add x bots to cache
const botsToAddToCache = this.botGenerator.prepareAndGenerateBots(sessionId, details);
this.botGenerationCacheService.storeBots(cacheKey, botsToAddToCache);
}
} }
this.logger.debug(
`Generated ${botGenerationDetails.botCountToGenerate} ${botGenerationDetails.role} (${
botGenerationDetails.eventRole ?? ""
}) ${botGenerationDetails.botDifficulty} bots`,
);
// Get bot from cache, add to return array // Get bot from cache, add to return array
const botToReturn = this.botGenerationCacheService.getBot(cacheKey); 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)];
} }
/** /**

View File

@ -115,7 +115,7 @@ export class BotEquipmentModGenerator
const outcome = this.filterPlateModsForSlotByLevel(settings, modSlot.toLowerCase(), compatibleModsPool[modSlot], parentTemplate); const outcome = this.filterPlateModsForSlotByLevel(settings, modSlot.toLowerCase(), compatibleModsPool[modSlot], parentTemplate);
if ([Result.UNKNOWN_FAILURE, Result.NO_DEFAULT_FILTER].includes(outcome.result)) 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; continue;
} }

View File

@ -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 sessionId Session id
* @param botGenerationDetails details on how to generate bots * @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[] = []; let bot = this.getCloneOfBotBase();
for (let i = 0; i < botGenerationDetails.botCountToGenerate; i++) bot.Info.Settings.Role = botGenerationDetails.eventRole
{ ? botGenerationDetails.eventRole
let bot = this.getCloneOfBotBase(); : botGenerationDetails.role;
bot.Info.Side = botGenerationDetails.side;
bot.Info.Settings.BotDifficulty = botGenerationDetails.botDifficulty;
bot.Info.Settings.Role = botGenerationDetails.role; // Get raw json data for bot (Cloned)
bot.Info.Side = botGenerationDetails.side; const botJsonTemplate = this.jsonUtil.clone(
bot.Info.Settings.BotDifficulty = botGenerationDetails.botDifficulty; this.botHelper.getBotTemplate((botGenerationDetails.isPmc)
? bot.Info.Side
// Get raw json data for bot (Cloned) : botGenerationDetails.role),
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`,
); );
return output; bot = this.generateBot(sessionId, bot, botJsonTemplate, botGenerationDetails);
return bot;
} }
/** /**

View File

@ -210,7 +210,7 @@ export class BotLootGenerator
this.addLootFromPool( this.addLootFromPool(
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate), this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate),
[EquipmentSlots.SECURED_CONTAINER], [EquipmentSlots.SECURED_CONTAINER],
100, 50,
botInventory, botInventory,
botRole, botRole,
false, false,