Adding DeathKnight handling and new Brackets

This commit is contained in:
Dustin Hendrickson
2025-02-17 08:42:43 -08:00
parent c84178e79c
commit 3896d8be09
3 changed files with 136 additions and 77 deletions

View File

@@ -7,25 +7,37 @@ The Bot Level Brackets module for AzerothCore ensures an even spread of player b
Features Features
-------- --------
**Configurable Level Brackets:** **Configurable Level Brackets:**
Define eight distinct level brackets with customizable lower and upper bounds. 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. 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. 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 bots level to ensure proper reinitialization. Executes the AutoMaintenanceOnLevelupAction after adjusting a bots 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. 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. Applies exclusively to bots managed by RandomPlayerbotMgr.
**Debug Mode:** **Debug Mode:**
Provides detailed logging to aid in monitoring and troubleshooting module operations. Provides detailed logging to aid in monitoring and troubleshooting module operations.
Installation Installation
@@ -60,16 +72,17 @@ Customize the modules behavior by editing the `mod-bot-level-brackets.conf` f
Setting | Description | Default | Valid Values Setting | Description | Default | Valid Values
-------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------- | -------------------- -------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------- | --------------------
BotLevelBrackets.DebugMode | Enables detailed debug logging for module operations. | 0 | 0 (off) / 1 (on) 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.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.Range1Pct | Desired percentage of bots in level bracket 1-9. | 11 | 0-100
BotLevelBrackets.Range2Pct | Desired percentage of bots in level bracket 11-20. | 12 | 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 21-30. | 12 | 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 31-40. | 12 | 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 41-50. | 12 | 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 51-60. | 12 | 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 61-70. | 12 | 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 71-80. | 14 | 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.* *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 Contribution
------------ ------------
Created by Dustin Hendrickson. Created by Dustin Hendrickson.
Pull requests and issues are welcome. Please ensure that contributions adhere to AzerothCore's coding standards. Pull requests and issues are welcome. Please ensure that contributions adhere to AzerothCore's coding standards.

View File

@@ -16,41 +16,46 @@ BotLevelBrackets.DebugMode = 0
BotLevelBrackets.CheckFrequency = 300 BotLevelBrackets.CheckFrequency = 300
# BotLevelBrackets.Range1Pct # BotLevelBrackets.Range1Pct
# Description: Desired percentage of bots within level range 1-10. # Description: Desired percentage of bots within level range 1-9.
# Default: 14 # Default: 11
BotLevelBrackets.Range1Pct = 14 BotLevelBrackets.Range1Pct = 11
# BotLevelBrackets.Range2Pct # BotLevelBrackets.Range2Pct
# Description: Desired percentage of bots within level range 11-20. # Description: Desired percentage of bots within level range 10-19.
# Default: 12 # Default: 11
BotLevelBrackets.Range2Pct = 12 BotLevelBrackets.Range2Pct = 11
# BotLevelBrackets.Range3Pct # BotLevelBrackets.Range3Pct
# Description: Desired percentage of bots within level range 21-30. # Description: Desired percentage of bots within level range 20-29.
# Default: 12 # Default: 11
BotLevelBrackets.Range3Pct = 12 BotLevelBrackets.Range3Pct = 11
# BotLevelBrackets.Range4Pct # BotLevelBrackets.Range4Pct
# Description: Desired percentage of bots within level range 31-40. # Description: Desired percentage of bots within level range 30-39.
# Default: 12 # Default: 11
BotLevelBrackets.Range4Pct = 12 BotLevelBrackets.Range4Pct = 11
# BotLevelBrackets.Range5Pct # BotLevelBrackets.Range5Pct
# Description: Desired percentage of bots within level range 41-50. # Description: Desired percentage of bots within level range 40-49.
# Default: 12 # Default: 11
BotLevelBrackets.Range5Pct = 12 BotLevelBrackets.Range5Pct = 11
# BotLevelBrackets.Range6Pct # BotLevelBrackets.Range6Pct
# Description: Desired percentage of bots within level range 51-60. # Description: Desired percentage of bots within level range 50-59.
# Default: 12 # Default: 11
BotLevelBrackets.Range6Pct = 12 BotLevelBrackets.Range6Pct = 11
# BotLevelBrackets.Range7Pct # BotLevelBrackets.Range7Pct
# Description: Desired percentage of bots within level range 61-70. # Description: Desired percentage of bots within level range 60-69.
# Default: 12 # Default: 11
BotLevelBrackets.Range7Pct = 12 BotLevelBrackets.Range7Pct = 11
# BotLevelBrackets.Range8Pct # BotLevelBrackets.Range8Pct
# Description: Desired percentage of bots within level range 71-80. # Description: Desired percentage of bots within level range 70-79.
# Default: 14 # Default: 11
BotLevelBrackets.Range8Pct = 14 BotLevelBrackets.Range8Pct = 11
# BotLevelBrackets.Range9Pct
# Description: Desired percentage of bots within level range 80.
# Default: 12
BotLevelBrackets.Range9Pct = 12

View File

@@ -22,7 +22,7 @@ struct LevelRangeConfig
uint8 desiredPercent;///< Desired percentage of bots in this range 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 LevelRangeConfig g_LevelRanges[NUM_RANGES];
static uint32 g_BotDistCheckFrequency = 300; // in seconds static uint32 g_BotDistCheckFrequency = 300; // in seconds
@@ -30,14 +30,15 @@ static bool g_BotDistDebugMode = false;
// Loads the configuration from the config file. // Loads the configuration from the config file.
// Expected keys (with example default percentages): // Expected keys (with example default percentages):
// BotLevelBrackets.Range1Pct = 14 // BotLevelBrackets.Range1Pct = 11
// BotLevelBrackets.Range2Pct = 12 // BotLevelBrackets.Range2Pct = 11
// BotLevelBrackets.Range3Pct = 12 // BotLevelBrackets.Range3Pct = 11
// BotLevelBrackets.Range4Pct = 12 // BotLevelBrackets.Range4Pct = 11
// BotLevelBrackets.Range5Pct = 12 // BotLevelBrackets.Range5Pct = 11
// BotLevelBrackets.Range6Pct = 12 // BotLevelBrackets.Range6Pct = 11
// BotLevelBrackets.Range7Pct = 12 // BotLevelBrackets.Range7Pct = 11
// BotLevelBrackets.Range8Pct = 14 // BotLevelBrackets.Range8Pct = 11
// BotLevelBrackets.Range9Pct = 12
// Additionally: // Additionally:
// BotLevelBrackets.CheckFrequency (in seconds) // BotLevelBrackets.CheckFrequency (in seconds)
// BotLevelBrackets.DebugMode (true/false) // BotLevelBrackets.DebugMode (true/false)
@@ -46,14 +47,15 @@ static void LoadBotLevelBracketsConfig()
g_BotDistDebugMode = sConfigMgr->GetOption<bool>("BotLevelBrackets.DebugMode", false); g_BotDistDebugMode = sConfigMgr->GetOption<bool>("BotLevelBrackets.DebugMode", false);
g_BotDistCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFrequency", 60); g_BotDistCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFrequency", 60);
g_LevelRanges[0] = { 1, 10, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range1Pct", 14)) }; g_LevelRanges[0] = { 1, 9, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range1Pct", 11)) };
g_LevelRanges[1] = { 11, 20, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range2Pct", 12)) }; g_LevelRanges[1] = { 10, 19, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range2Pct", 11)) };
g_LevelRanges[2] = { 21, 30, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range3Pct", 12)) }; g_LevelRanges[2] = { 20, 29, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range3Pct", 11)) };
g_LevelRanges[3] = { 31, 40, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range4Pct", 12)) }; g_LevelRanges[3] = { 30, 39, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range4Pct", 11)) };
g_LevelRanges[4] = { 41, 50, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range5Pct", 12)) }; g_LevelRanges[4] = { 40, 49, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range5Pct", 11)) };
g_LevelRanges[5] = { 51, 60, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range6Pct", 12)) }; g_LevelRanges[5] = { 50, 59, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range6Pct", 11)) };
g_LevelRanges[6] = { 61, 70, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range7Pct", 12)) }; g_LevelRanges[6] = { 60, 69, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range7Pct", 11)) };
g_LevelRanges[7] = { 71, 80, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range8Pct", 14)) }; g_LevelRanges[7] = { 70, 79, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range8Pct", 11)) };
g_LevelRanges[8] = { 80, 80, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Range9Pct", 12)) };
uint32 totalPercent = 0; uint32 totalPercent = 0;
for (uint8 i = 0; i < NUM_RANGES; ++i) 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. // 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: // In addition to setting the new level and resetting XP, this function:
// - Sends a system message indicating the reset. // - Sends a system message indicating the reset.
// - Destroys all equipped items. // - Destroys all equipped items.
@@ -91,11 +94,36 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex)
if (!bot || targetRangeIndex < 0 || targetRangeIndex >= NUM_RANGES) if (!bot || targetRangeIndex < 0 || targetRangeIndex >= NUM_RANGES)
return; 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->SetLevel(newLevel);
bot->SetUInt32Value(PLAYER_XP, 0); 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."); ChatHandler(bot->GetSession()).SendSysMessage("[mod-bot-level-brackets] Your level has been reset.");
// Destroy equipped items. // Destroy equipped items.
@@ -236,26 +264,38 @@ public:
{ {
while (actualCounts[i] > desiredCounts[i] && !botsByRange[i].empty()) 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(); Player* bot = botsByRange[i].back();
botsByRange[i].pop_back(); botsByRange[i].pop_back();
// Adjust its level to a random level within the target range and perform cleanup. int targetRange = -1;
AdjustBotToRange(bot, targetRange); // 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[i]--;
actualCounts[targetRange]++; actualCounts[targetRange]++;
} }