From 3896d8be09ab5a2114b23ff1b09c1186a612f251 Mon Sep 17 00:00:00 2001 From: Dustin Hendrickson Date: Mon, 17 Feb 2025 08:42:43 -0800 Subject: [PATCH] Adding DeathKnight handling and new Brackets --- README.md | 50 ++++++--- conf/mod_player_bot_level_brackets.conf.dist | 53 +++++---- src/mod-player-bot-level-brackets.cpp | 110 +++++++++++++------ 3 files changed, 136 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 524d3d4..43f6a5c 100644 --- a/README.md +++ b/README.md @@ -7,25 +7,37 @@ The Bot Level Brackets module for AzerothCore ensures an even spread of player b Features -------- -• **Configurable Level Brackets:** - Define eight distinct level brackets with customizable lower and upper bounds. +• **Configurable Level Brackets:** + Define nine distinct level brackets with customizable lower and upper bounds: + - 1-9 + - 10-19 + - 20-29 + - 30-39 + - 40-49 + - 50-59 + - 60-69 + - 70-79 + - 80 -• **Desired Percentage Distribution:** +• **Desired Percentage Distribution:** Set target percentages for the number of bots within each level bracket. -• **Dynamic Bot Adjustment:** +• **Dynamic Bot Adjustment:** Automatically reassign bots from brackets with a surplus to those with a deficit. -• **Auto Maintenance Execution:** +• **Death Knight Level Safeguard:** + Ensures that bots of the Death Knight class are never assigned a level below 55, guaranteeing they only appear in higher brackets. + +• **Auto Maintenance Execution:** Executes the AutoMaintenanceOnLevelupAction after adjusting a bot’s level to ensure proper reinitialization. -• **Equipment and Pet Reset:** +• **Equipment and Pet Reset:** Destroys all equipped items and removes any pet during a level adjustment. -• **Support for Random Bots:** +• **Support for Random Bots:** Applies exclusively to bots managed by RandomPlayerbotMgr. -• **Debug Mode:** +• **Debug Mode:** Provides detailed logging to aid in monitoring and troubleshooting module operations. Installation @@ -60,16 +72,17 @@ Customize the module’s behavior by editing the `mod-bot-level-brackets.conf` f Setting | Description | Default | Valid Values -------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------- | -------------------- -BotLevelBrackets.DebugMode | Enables detailed debug logging for module operations. | 0 | 0 (off) / 1 (on) -BotLevelBrackets.CheckFrequency | Frequency (in seconds) for performing the bot bracket distribution check. | 300 | Positive Integer -BotLevelBrackets.Range1Pct | Desired percentage of bots in level bracket 1-10. | 14 | 0-100 -BotLevelBrackets.Range2Pct | Desired percentage of bots in level bracket 11-20. | 12 | 0-100 -BotLevelBrackets.Range3Pct | Desired percentage of bots in level bracket 21-30. | 12 | 0-100 -BotLevelBrackets.Range4Pct | Desired percentage of bots in level bracket 31-40. | 12 | 0-100 -BotLevelBrackets.Range5Pct | Desired percentage of bots in level bracket 41-50. | 12 | 0-100 -BotLevelBrackets.Range6Pct | Desired percentage of bots in level bracket 51-60. | 12 | 0-100 -BotLevelBrackets.Range7Pct | Desired percentage of bots in level bracket 61-70. | 12 | 0-100 -BotLevelBrackets.Range8Pct | Desired percentage of bots in level bracket 71-80. | 14 | 0-100 +BotLevelBrackets.DebugMode | Enables detailed debug logging for module operations. | 0 | 0 (off) / 1 (on) +BotLevelBrackets.CheckFrequency | Frequency (in seconds) for performing the bot bracket distribution check. | 300 | Positive Integer +BotLevelBrackets.Range1Pct | Desired percentage of bots in level bracket 1-9. | 11 | 0-100 +BotLevelBrackets.Range2Pct | Desired percentage of bots in level bracket 10-19. | 11 | 0-100 +BotLevelBrackets.Range3Pct | Desired percentage of bots in level bracket 20-29. | 11 | 0-100 +BotLevelBrackets.Range4Pct | Desired percentage of bots in level bracket 30-39. | 11 | 0-100 +BotLevelBrackets.Range5Pct | Desired percentage of bots in level bracket 40-49. | 11 | 0-100 +BotLevelBrackets.Range6Pct | Desired percentage of bots in level bracket 50-59. | 11 | 0-100 +BotLevelBrackets.Range7Pct | Desired percentage of bots in level bracket 60-69. | 11 | 0-100 +BotLevelBrackets.Range8Pct | Desired percentage of bots in level bracket 70-79. | 11 | 0-100 +BotLevelBrackets.Range9Pct | Desired percentage of bots in level bracket 80. | 12 | 0-100 *Note: The sum of all bracket percentages must equal 100.* @@ -88,4 +101,5 @@ This module is released under the GNU GPL v2 license, consistent with AzerothCor Contribution ------------ Created by Dustin Hendrickson. + Pull requests and issues are welcome. Please ensure that contributions adhere to AzerothCore's coding standards. diff --git a/conf/mod_player_bot_level_brackets.conf.dist b/conf/mod_player_bot_level_brackets.conf.dist index a89fa2f..c27b565 100644 --- a/conf/mod_player_bot_level_brackets.conf.dist +++ b/conf/mod_player_bot_level_brackets.conf.dist @@ -16,41 +16,46 @@ BotLevelBrackets.DebugMode = 0 BotLevelBrackets.CheckFrequency = 300 # BotLevelBrackets.Range1Pct -# Description: Desired percentage of bots within level range 1-10. -# Default: 14 -BotLevelBrackets.Range1Pct = 14 +# Description: Desired percentage of bots within level range 1-9. +# Default: 11 +BotLevelBrackets.Range1Pct = 11 # BotLevelBrackets.Range2Pct -# Description: Desired percentage of bots within level range 11-20. -# Default: 12 -BotLevelBrackets.Range2Pct = 12 +# Description: Desired percentage of bots within level range 10-19. +# Default: 11 +BotLevelBrackets.Range2Pct = 11 # BotLevelBrackets.Range3Pct -# Description: Desired percentage of bots within level range 21-30. -# Default: 12 -BotLevelBrackets.Range3Pct = 12 +# Description: Desired percentage of bots within level range 20-29. +# Default: 11 +BotLevelBrackets.Range3Pct = 11 # BotLevelBrackets.Range4Pct -# Description: Desired percentage of bots within level range 31-40. -# Default: 12 -BotLevelBrackets.Range4Pct = 12 +# Description: Desired percentage of bots within level range 30-39. +# Default: 11 +BotLevelBrackets.Range4Pct = 11 # BotLevelBrackets.Range5Pct -# Description: Desired percentage of bots within level range 41-50. -# Default: 12 -BotLevelBrackets.Range5Pct = 12 +# Description: Desired percentage of bots within level range 40-49. +# Default: 11 +BotLevelBrackets.Range5Pct = 11 # BotLevelBrackets.Range6Pct -# Description: Desired percentage of bots within level range 51-60. -# Default: 12 -BotLevelBrackets.Range6Pct = 12 +# Description: Desired percentage of bots within level range 50-59. +# Default: 11 +BotLevelBrackets.Range6Pct = 11 # BotLevelBrackets.Range7Pct -# Description: Desired percentage of bots within level range 61-70. -# Default: 12 -BotLevelBrackets.Range7Pct = 12 +# Description: Desired percentage of bots within level range 60-69. +# Default: 11 +BotLevelBrackets.Range7Pct = 11 # BotLevelBrackets.Range8Pct -# Description: Desired percentage of bots within level range 71-80. -# Default: 14 -BotLevelBrackets.Range8Pct = 14 +# Description: Desired percentage of bots within level range 70-79. +# Default: 11 +BotLevelBrackets.Range8Pct = 11 + +# BotLevelBrackets.Range9Pct +# Description: Desired percentage of bots within level range 80. +# Default: 12 +BotLevelBrackets.Range9Pct = 12 diff --git a/src/mod-player-bot-level-brackets.cpp b/src/mod-player-bot-level-brackets.cpp index 7653c00..8366328 100644 --- a/src/mod-player-bot-level-brackets.cpp +++ b/src/mod-player-bot-level-brackets.cpp @@ -22,7 +22,7 @@ struct LevelRangeConfig uint8 desiredPercent;///< Desired percentage of bots in this range }; -static const uint8 NUM_RANGES = 8; +static const uint8 NUM_RANGES = 9; static LevelRangeConfig g_LevelRanges[NUM_RANGES]; static uint32 g_BotDistCheckFrequency = 300; // in seconds @@ -30,14 +30,15 @@ static bool g_BotDistDebugMode = false; // Loads the configuration from the config file. // Expected keys (with example default percentages): -// BotLevelBrackets.Range1Pct = 14 -// BotLevelBrackets.Range2Pct = 12 -// BotLevelBrackets.Range3Pct = 12 -// BotLevelBrackets.Range4Pct = 12 -// BotLevelBrackets.Range5Pct = 12 -// BotLevelBrackets.Range6Pct = 12 -// BotLevelBrackets.Range7Pct = 12 -// BotLevelBrackets.Range8Pct = 14 +// BotLevelBrackets.Range1Pct = 11 +// BotLevelBrackets.Range2Pct = 11 +// BotLevelBrackets.Range3Pct = 11 +// BotLevelBrackets.Range4Pct = 11 +// BotLevelBrackets.Range5Pct = 11 +// BotLevelBrackets.Range6Pct = 11 +// BotLevelBrackets.Range7Pct = 11 +// BotLevelBrackets.Range8Pct = 11 +// BotLevelBrackets.Range9Pct = 12 // Additionally: // BotLevelBrackets.CheckFrequency (in seconds) // BotLevelBrackets.DebugMode (true/false) @@ -46,14 +47,15 @@ static void LoadBotLevelBracketsConfig() g_BotDistDebugMode = sConfigMgr->GetOption("BotLevelBrackets.DebugMode", false); g_BotDistCheckFrequency = sConfigMgr->GetOption("BotLevelBrackets.CheckFrequency", 60); - g_LevelRanges[0] = { 1, 10, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range1Pct", 14)) }; - g_LevelRanges[1] = { 11, 20, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range2Pct", 12)) }; - g_LevelRanges[2] = { 21, 30, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range3Pct", 12)) }; - g_LevelRanges[3] = { 31, 40, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range4Pct", 12)) }; - g_LevelRanges[4] = { 41, 50, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range5Pct", 12)) }; - g_LevelRanges[5] = { 51, 60, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range6Pct", 12)) }; - g_LevelRanges[6] = { 61, 70, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range7Pct", 12)) }; - g_LevelRanges[7] = { 71, 80, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range8Pct", 14)) }; + g_LevelRanges[0] = { 1, 9, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range1Pct", 11)) }; + g_LevelRanges[1] = { 10, 19, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range2Pct", 11)) }; + g_LevelRanges[2] = { 20, 29, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range3Pct", 11)) }; + g_LevelRanges[3] = { 30, 39, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range4Pct", 11)) }; + g_LevelRanges[4] = { 40, 49, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range5Pct", 11)) }; + g_LevelRanges[5] = { 50, 59, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range6Pct", 11)) }; + g_LevelRanges[6] = { 60, 69, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range7Pct", 11)) }; + g_LevelRanges[7] = { 70, 79, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range8Pct", 11)) }; + g_LevelRanges[8] = { 80, 80, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Range9Pct", 12)) }; uint32 totalPercent = 0; for (uint8 i = 0; i < NUM_RANGES; ++i) @@ -81,6 +83,7 @@ static uint8 GetRandomLevelInRange(const LevelRangeConfig& range) } // Adjusts a bot's level by selecting a random level within the target range. +// For Death Knight bots, the new level will not be set below 55. // In addition to setting the new level and resetting XP, this function: // - Sends a system message indicating the reset. // - Destroys all equipped items. @@ -91,11 +94,36 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex) if (!bot || targetRangeIndex < 0 || targetRangeIndex >= NUM_RANGES) return; - uint8 newLevel = GetRandomLevelInRange(g_LevelRanges[targetRangeIndex]); + uint8 newLevel = 0; + // If the bot is a Death Knight, ensure level is not set below 55. + if (bot->getClass() == CLASS_DEATH_KNIGHT) + { + uint8 lowerBound = g_LevelRanges[targetRangeIndex].lower; + uint8 upperBound = g_LevelRanges[targetRangeIndex].upper; + if (upperBound < 55) + { + // This target range is invalid for Death Knights. + if (g_BotDistDebugMode) + { + LOG_INFO("server.loading", "[BotLevelBrackets] AdjustBotToRange: Cannot assign Death Knight '{}' to range {}-{} (below level 55).", + bot->GetName(), lowerBound, upperBound); + } + return; + } + // Adjust lower bound to 55 if necessary. + if (lowerBound < 55) + lowerBound = 55; + newLevel = urand(lowerBound, upperBound); + } + else + { + newLevel = GetRandomLevelInRange(g_LevelRanges[targetRangeIndex]); + } + bot->SetLevel(newLevel); bot->SetUInt32Value(PLAYER_XP, 0); - // Inform the bot (or player) about the level reset. + // Inform the bot about the level reset. ChatHandler(bot->GetSession()).SendSysMessage("[mod-bot-level-brackets] Your level has been reset."); // Destroy equipped items. @@ -236,26 +264,38 @@ public: { while (actualCounts[i] > desiredCounts[i] && !botsByRange[i].empty()) { - // Locate a target range with a deficit. - int targetRange = -1; - for (int j = 0; j < NUM_RANGES; ++j) - { - if (actualCounts[j] < desiredCounts[j]) - { - targetRange = j; - break; - } - } - if (targetRange == -1) - break; // No underpopulated range found. - - // Retrieve one bot from the current (overpopulated) range. Player* bot = botsByRange[i].back(); botsByRange[i].pop_back(); - // Adjust its level to a random level within the target range and perform cleanup. - AdjustBotToRange(bot, targetRange); + int targetRange = -1; + // For Death Knights, only consider target ranges where the upper bound is at least 55. + if (bot->getClass() == CLASS_DEATH_KNIGHT) + { + for (int j = 0; j < NUM_RANGES; ++j) + { + if (actualCounts[j] < desiredCounts[j] && g_LevelRanges[j].upper >= 55) + { + targetRange = j; + break; + } + } + } + else + { + for (int j = 0; j < NUM_RANGES; ++j) + { + if (actualCounts[j] < desiredCounts[j]) + { + targetRange = j; + break; + } + } + } + if (targetRange == -1) + break; // No appropriate underpopulated range found. + + AdjustBotToRange(bot, targetRange); actualCounts[i]--; actualCounts[targetRange]++; }