mirror of
https://github.com/kadeshar/mod-player-bot-level-brackets.git
synced 2026-01-13 01:08:36 +00:00
Adding new Dynamic brackets feature
This commit is contained in:
38
README.md
38
README.md
@@ -5,7 +5,6 @@ Overview
|
||||
--------
|
||||
The Bot Level Brackets module for AzerothCore ensures an even spread of player bots across configurable level ranges (brackets). It periodically monitors bot levels and automatically adjusts them by transferring bots from overpopulated brackets to those with a deficit. During adjustments, bot levels are reset, equipped items are destroyed, trade skills are removed, quests are cleared, active auras are removed, pets are dismissed, and auto-maintenance actions are executed. Bots that are not immediately safe for level reset (for example, those in combat or engaged in other activities) are flagged for pending adjustment and processed later when they become safe. Additionally, Death Knight bots are safeguarded to never be assigned a level below 55.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
- **Configurable Level Brackets:**
|
||||
@@ -38,9 +37,23 @@ Features
|
||||
- **Support for Random Bots:**
|
||||
The module applies exclusively to bots managed by RandomPlayerbotMgr.
|
||||
|
||||
- **Dynamic Real Player Weighting with Inverse Scaling:**
|
||||
When dynamic distribution is enabled, the module uses a configurable weight multiplier (set via `BotLevelBrackets.RealPlayerWeight`) to boost each real player's contribution to the desired distribution. This weight is further scaled inversely by the total number of real players online, ensuring that when few players are active, each player's impact on the bot distribution is significantly increased.
|
||||
**Note:** The `RealPlayerWeight` option only takes effect when `BotLevelBrackets.UseDynamicDistribution` is enabled.
|
||||
|
||||
- **Dynamic Distribution Toggle:**
|
||||
Enable or disable the dynamic recalculation of bot distribution percentages based on the number of non-bot players in each level bracket via the `BotLevelBrackets.UseDynamicDistribution` option.
|
||||
|
||||
- **Debug Mode:**
|
||||
An optional debug mode provides detailed logging for monitoring bot adjustments and troubleshooting module operations.
|
||||
|
||||
### Dynamic Real Player Weighting and Scaling
|
||||
|
||||
When dynamic distribution is enabled (`BotLevelBrackets.UseDynamicDistribution`), the module recalculates the desired bot percentages for each level bracket based on the number of non-bot players present.
|
||||
|
||||
The total weight across all brackets is computed, and each bracket’s desired percentage is derived from its share of that total. This ensures that while more players in a bracket increase its weight, each additional player contributes progressively less.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
1. **Clone the Module**
|
||||
@@ -74,17 +87,18 @@ Customize the module’s behavior by editing the `mod_player_bot_level_brackets.
|
||||
### Global Settings
|
||||
|
||||
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.CheckFlaggedFrequency | Frequency (in seconds) at which the bot level reset is performed for flagged bots that failed safety checks initially. | 15 | Positive Integer
|
||||
|
||||
BotLevelBrackets.RealPlayerWeight | Multiplier applied to each real player's contribution in their level bracket. This value is further scaled inversely by the total number of real players online. **Only active if dynamic distribution is enabled.** | 1.0 | Floating point number
|
||||
BotLevelBrackets.UseDynamicDistribution | Enables dynamic recalculation of bot distribution percentages based on the number of non-bot players in each bracket. | 0 | 0 (off) / 1 (on)
|
||||
|
||||
### Alliance Level Brackets Configuration
|
||||
*The percentages below must sum to 100.*
|
||||
|
||||
Setting | Description | Default | Valid Values
|
||||
-------------------------------------------|--------------------------------------------------------------|---------|--------------------
|
||||
-------------------------------------------|---------------------------------------------------------------|---------|--------------------
|
||||
BotLevelBrackets.Alliance.Range1Pct | Desired percentage of Alliance bots within level range 1-9. | 12 | 0-100
|
||||
BotLevelBrackets.Alliance.Range2Pct | Desired percentage of Alliance bots within level range 10-19. | 11 | 0-100
|
||||
BotLevelBrackets.Alliance.Range3Pct | Desired percentage of Alliance bots within level range 20-29. | 11 | 0-100
|
||||
@@ -99,15 +113,15 @@ BotLevelBrackets.Alliance.Range9Pct | Desired percentage of Alliance bot
|
||||
*The percentages below must sum to 100.*
|
||||
|
||||
Setting | Description | Default | Valid Values
|
||||
---------------------------------------|-----------------------------------------------------------|---------|--------------------
|
||||
-------------------------------------------|---------------------------------------------------------------|---------|--------------------
|
||||
BotLevelBrackets.Horde.Range1Pct | Desired percentage of Horde bots within level range 1-9. | 12 | 0-100
|
||||
BotLevelBrackets.Horde.Range2Pct | Desired percentage of Horde bots within level range 10-19.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range3Pct | Desired percentage of Horde bots within level range 20-29.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range4Pct | Desired percentage of Horde bots within level range 30-39.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range5Pct | Desired percentage of Horde bots within level range 40-49.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range6Pct | Desired percentage of Horde bots within level range 50-59.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range7Pct | Desired percentage of Horde bots within level range 60-69.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range8Pct | Desired percentage of Horde bots within level range 70-79.| 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range2Pct | Desired percentage of Horde bots within level range 10-19. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range3Pct | Desired percentage of Horde bots within level range 20-29. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range4Pct | Desired percentage of Horde bots within level range 30-39. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range5Pct | Desired percentage of Horde bots within level range 40-49. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range6Pct | Desired percentage of Horde bots within level range 50-59. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range7Pct | Desired percentage of Horde bots within level range 60-69. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range8Pct | Desired percentage of Horde bots within level range 70-79. | 11 | 0-100
|
||||
BotLevelBrackets.Horde.Range9Pct | Desired percentage of Horde bots at level 80. | 11 | 0-100
|
||||
|
||||
Debugging
|
||||
|
||||
@@ -20,6 +20,20 @@ BotLevelBrackets.CheckFrequency = 300
|
||||
# Default: 15
|
||||
BotLevelBrackets.CheckFlaggedFrequency = 15
|
||||
|
||||
# BotLevelBrackets.UseDynamicDistribution
|
||||
# Description: Enables dynamic recalculation of bot distribution percentages based on the number of non-bot players present in each level bracket.
|
||||
# Default: 0 (disabled)
|
||||
# Valid values: 0 (off) / 1 (on)
|
||||
BotLevelBrackets.UseDynamicDistribution = 0
|
||||
|
||||
#
|
||||
# BotLevelBrackets.RealPlayerWeight
|
||||
# Description: A multiplier applied to each real player's contribution in their level bracket.
|
||||
# When combined with inverse scaling by total player count, a higher value significantly boosts the effective weight
|
||||
# of a real player when few are online.
|
||||
# Default: 1.0
|
||||
BotLevelBrackets.RealPlayerWeight = 1.0
|
||||
|
||||
#
|
||||
# Alliance Level Brackets Configuration
|
||||
# The percentages below must sum to 100.
|
||||
|
||||
@@ -37,6 +37,10 @@ static LevelRangeConfig g_HordeLevelRanges[NUM_RANGES];
|
||||
static uint32 g_BotDistCheckFrequency = 300; // in seconds
|
||||
static uint32 g_BotDistFlaggedCheckFrequency = 15; // in seconds
|
||||
static bool g_BotDistDebugMode = false;
|
||||
static bool g_UseDynamicDistribution = false;
|
||||
|
||||
// New configuration: real player weight to boost bracket contributions.
|
||||
static float g_RealPlayerWeight = 1.0f;
|
||||
|
||||
// Loads the configuration from the config file.
|
||||
static void LoadBotLevelBracketsConfig()
|
||||
@@ -44,6 +48,8 @@ static void LoadBotLevelBracketsConfig()
|
||||
g_BotDistDebugMode = sConfigMgr->GetOption<bool>("BotLevelBrackets.DebugMode", false);
|
||||
g_BotDistCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFrequency", 300);
|
||||
g_BotDistFlaggedCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFlaggedFrequency", 15);
|
||||
g_UseDynamicDistribution = sConfigMgr->GetOption<bool>("BotLevelBrackets.UseDynamicDistribution", false);
|
||||
g_RealPlayerWeight = sConfigMgr->GetOption<float>("BotLevelBrackets.RealPlayerWeight", 1.0f);
|
||||
|
||||
// Alliance configuration.
|
||||
g_AllianceLevelRanges[0] = { 1, 9, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range1Pct", 12)) };
|
||||
@@ -156,7 +162,6 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRange
|
||||
}
|
||||
|
||||
ChatHandler(bot->GetSession()).SendSysMessage("[mod-bot-level-brackets] Your level has been reset.");
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -274,18 +279,84 @@ public:
|
||||
m_timer += diff;
|
||||
m_flaggedTimer += diff;
|
||||
|
||||
// Check if it's time to process pending level resets
|
||||
// Process pending level resets.
|
||||
if (m_flaggedTimer >= g_BotDistFlaggedCheckFrequency * 1000)
|
||||
{
|
||||
ProcessPendingLevelResets();
|
||||
m_flaggedTimer = 0;
|
||||
}
|
||||
|
||||
// Continue with distribution adjustments once its timer expires
|
||||
// Continue with distribution adjustments once the timer expires.
|
||||
if (m_timer < g_BotDistCheckFrequency * 1000)
|
||||
return;
|
||||
m_timer = 0;
|
||||
|
||||
// Dynamic distribution: recalc desired percentages based on non-bot players.
|
||||
if (g_UseDynamicDistribution)
|
||||
{
|
||||
int allianceRealCounts[NUM_RANGES] = {0};
|
||||
int hordeRealCounts[NUM_RANGES] = {0};
|
||||
uint32 totalAllianceReal = 0;
|
||||
uint32 totalHordeReal = 0;
|
||||
// Iterate over all players and count non-bot players.
|
||||
for (auto const& itr : ObjectAccessor::GetPlayers())
|
||||
{
|
||||
Player* player = itr.second;
|
||||
if (!player || !player->IsInWorld())
|
||||
continue;
|
||||
if (IsPlayerBot(player))
|
||||
continue; // Skip bots.
|
||||
int rangeIndex = GetLevelRangeIndex(player->GetLevel());
|
||||
if (rangeIndex < 0)
|
||||
continue;
|
||||
if (player->GetTeamId() == TEAM_ALLIANCE)
|
||||
{
|
||||
allianceRealCounts[rangeIndex]++;
|
||||
totalAllianceReal++;
|
||||
}
|
||||
else if (player->GetTeamId() == TEAM_HORDE)
|
||||
{
|
||||
hordeRealCounts[rangeIndex]++;
|
||||
totalHordeReal++;
|
||||
}
|
||||
}
|
||||
// Use a baseline weight to ensure an equal share when no real players are present.
|
||||
const float baseline = 1.0f;
|
||||
float allianceTotalWeight = 0.0f;
|
||||
float hordeTotalWeight = 0.0f;
|
||||
float allianceWeights[NUM_RANGES] = {0};
|
||||
float hordeWeights[NUM_RANGES] = {0};
|
||||
for (int i = 0; i < NUM_RANGES; ++i)
|
||||
{
|
||||
allianceWeights[i] = baseline + g_RealPlayerWeight * log(1 + allianceRealCounts[i]);
|
||||
|
||||
hordeWeights[i] = baseline + g_RealPlayerWeight * log(1 + hordeRealCounts[i]);
|
||||
|
||||
allianceTotalWeight += allianceWeights[i];
|
||||
hordeTotalWeight += hordeWeights[i];
|
||||
}
|
||||
// Recalculate desired percentages for each range.
|
||||
for (int i = 0; i < NUM_RANGES; ++i)
|
||||
{
|
||||
g_AllianceLevelRanges[i].desiredPercent = static_cast<uint8>(round((allianceWeights[i] / allianceTotalWeight) * 100));
|
||||
if (g_BotDistDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Dynamic Distribution - Alliance Range {}: {}-{}, Real Players: {} (weight: {:.2f}), New Desired: {}%",
|
||||
i + 1, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper, allianceRealCounts[i], allianceWeights[i], g_AllianceLevelRanges[i].desiredPercent);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_RANGES; ++i)
|
||||
{
|
||||
g_HordeLevelRanges[i].desiredPercent = static_cast<uint8>(round((hordeWeights[i] / hordeTotalWeight) * 100));
|
||||
if (g_BotDistDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Dynamic Distribution - Horde Range {}: {}-{}, Real Players: {} (weight: {:.2f}), New Desired: {}%",
|
||||
i + 1, g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper, hordeRealCounts[i], hordeWeights[i], g_HordeLevelRanges[i].desiredPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Containers for Alliance bots.
|
||||
uint32 totalAllianceBots = 0;
|
||||
int allianceActualCounts[NUM_RANGES] = {0};
|
||||
|
||||
Reference in New Issue
Block a user