From ee1eb7d690c5ebd3d1aa4229d3a15d1050f84b5a Mon Sep 17 00:00:00 2001 From: DrakiaXYZ Date: Tue, 30 Jul 2024 07:24:29 +0000 Subject: [PATCH] Fix issue in BotLevelGenerator when high level (!388) Previously `highestValue` could be lower than `lowestValue`, resulting in an exception. These values are now generated in the same method and clamped Add a catch to the botgen promise await so we get more useful errors if botgen fails Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com> Reviewed-on: https://dev.sp-tarkov.com/SPT/Server/pulls/388 Co-authored-by: DrakiaXYZ Co-committed-by: DrakiaXYZ --- project/src/controllers/BotController.ts | 5 +- project/src/generators/BotLevelGenerator.ts | 68 ++++++++------------- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/project/src/controllers/BotController.ts b/project/src/controllers/BotController.ts index 92b8574b..6752adae 100644 --- a/project/src/controllers/BotController.ts +++ b/project/src/controllers/BotController.ts @@ -226,8 +226,9 @@ export class BotController { conditionPromises.push(this.generateWithBotDetails(condition, botGenerationDetails, sessionId)); } - await Promise.all(conditionPromises).then((p) => Promise.all(p)); - + await Promise.all(conditionPromises).then((p) => Promise.all(p)).catch((ex) => { + this.logger.error(ex); + }); return []; } diff --git a/project/src/generators/BotLevelGenerator.ts b/project/src/generators/BotLevelGenerator.ts index dcd33b62..2c2186fc 100644 --- a/project/src/generators/BotLevelGenerator.ts +++ b/project/src/generators/BotLevelGenerator.ts @@ -30,12 +30,11 @@ export class BotLevelGenerator { bot: IBotBase, ): IRandomisedBotLevelResult { const expTable = this.databaseService.getGlobals().config.exp.level.exp_table; - const highestLevel = this.getHighestRelativeBotLevel(botGenerationDetails, levelDetails, expTable.length); - const lowestLevel = this.getLowestRelativeBotLevel(botGenerationDetails, levelDetails, expTable.length); + const botLevelRange = this.getRelativeBotLevelRange(botGenerationDetails, levelDetails, expTable.length); // Get random level based on the exp table. let exp = 0; - const level = this.chooseBotLevel(lowestLevel, highestLevel, 1, 1.15); + const level = this.chooseBotLevel(botLevelRange.min, botLevelRange.max, 1, 1.15); for (let i = 0; i < level; i++) { exp += expTable[i].exp; } @@ -53,55 +52,40 @@ export class BotLevelGenerator { } /** - * Get the highest level a bot can be relative to the players level, but no further than the max size from globals.exp_table - * @param botGenerationDetails Details to help generate a bot - * @param levelDetails - * @param maxLevel Max possible level - * @returns Highest level possible for bot - */ - protected getHighestRelativeBotLevel( - botGenerationDetails: BotGenerationDetails, - levelDetails: MinMax, - maxLevel: number, - ): number { - const maxPossibleLevel = - botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride - ? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxLevel) // Was a PMC and they have a level override - : Math.min(levelDetails.max, maxLevel); // Not pmc with override or non-pmc - - let level = botGenerationDetails.playerLevel + botGenerationDetails.botRelativeLevelDeltaMax; - if (level > maxPossibleLevel) { - level = maxPossibleLevel; - } - - return level; - } - - /** - * Get the lowest level a bot can be relative to the players level, but no lower than 1 + * Return the min and max bot level based on a relative delta from the PMC level * @param botGenerationDetails Details to help generate a bot * @param levelDetails * @param maxlevel Max level allowed - * @returns Lowest level possible for bot + * @returns A MinMax of the lowest and highest level to generate the bots */ - protected getLowestRelativeBotLevel( + protected getRelativeBotLevelRange( botGenerationDetails: BotGenerationDetails, levelDetails: MinMax, - maxlevel: number, - ): number { + maxAvailableLevel: number, + ): MinMax { const minPossibleLevel = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride ? Math.min( - Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min - maxlevel, // Fallback if value above is crazy (default is 79) - ) - : Math.min(levelDetails.min, maxlevel); // Not pmc with override or non-pmc + Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min + maxAvailableLevel, // Fallback if value above is crazy (default is 79) + ) + : Math.min(levelDetails.min, maxAvailableLevel); // Not pmc with override or non-pmc - let level = botGenerationDetails.playerLevel - botGenerationDetails.botRelativeLevelDeltaMin; - if (level < minPossibleLevel) { - level = minPossibleLevel; + const maxPossibleLevel = + botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride + ? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxAvailableLevel) // Was a PMC and they have a level override + : Math.min(levelDetails.max, maxAvailableLevel); // Not pmc with override or non-pmc + + let minLevel = botGenerationDetails.playerLevel - botGenerationDetails.botRelativeLevelDeltaMin; + let maxLevel = botGenerationDetails.playerLevel + botGenerationDetails.botRelativeLevelDeltaMax; + + // Bound the level to the min/max possible + maxLevel = Math.min(Math.max(maxLevel, minPossibleLevel), maxPossibleLevel); + minLevel = Math.min(Math.max(minLevel, minPossibleLevel), maxPossibleLevel); + + return { + min: minLevel, + max: maxLevel, } - - return level; } }