From f34341ad794837b9f5a7dd87eedb2df0c1515c0c Mon Sep 17 00:00:00 2001 From: Dustin Hendrickson Date: Thu, 6 Mar 2025 17:09:29 -0800 Subject: [PATCH] Adding support to change bracket ranges/number of brackets in the conf --- conf/mod_player_bot_level_brackets.conf.dist | 232 ++++++----- src/mod-player-bot-level-brackets.cpp | 407 ++++++++++--------- 2 files changed, 360 insertions(+), 279 deletions(-) diff --git a/conf/mod_player_bot_level_brackets.conf.dist b/conf/mod_player_bot_level_brackets.conf.dist index 9c81f37..411b770 100644 --- a/conf/mod_player_bot_level_brackets.conf.dist +++ b/conf/mod_player_bot_level_brackets.conf.dist @@ -10,36 +10,44 @@ # Valid values: 0 (off) / 1 (on) BotLevelBrackets.Enabled = 1 +# # BotLevelBrackets.FullDebugMode # Description: Enables full debug logging for the Bot Level Brackets module. # Default: 0 (disabled) # Valid values: 0 (off) / 1 (on) BotLevelBrackets.FullDebugMode = 0 +# # BotLevelBrackets.LiteDebugMode # Description: Enables lite debug logging for the Bot Level Brackets module. # Default: 0 (disabled) # Valid values: 0 (off) / 1 (on) BotLevelBrackets.LiteDebugMode = 0 +# # BotLevelBrackets.CheckFrequency # Description: The frequency (in seconds) at which the bot level distribution check is performed. # Default: 300 BotLevelBrackets.CheckFrequency = 300 +# # BotLevelBrackets.CheckFlaggedFrequency # Description: The frequency (in seconds) at which the bot level reset is performed for flagged bots that failed safety checks initially. # Default: 15 BotLevelBrackets.CheckFlaggedFrequency = 15 +# # BotLevelBrackets.IgnoreGuildBotsWithRealPlayers -# Description: When enabled, bots that are in a guild with at least one real (non-bot) player online are excluded from bot bracket calculations and will not be level changed or flagged. +# Description: When enabled, bots that are in a guild with at least one real (non-bot) player online are excluded +# from bot bracket calculations and will not be level changed or flagged. # Default: 1 (enabled) # Valid values: 0 (disabled) / 1 (enabled) BotLevelBrackets.IgnoreGuildBotsWithRealPlayers = 1 +# # BotLevelBrackets.UseDynamicDistribution -# Description: Enables dynamic recalculation of bot distribution percentages based on the number of non-bot players present in each level bracket. +# 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 @@ -53,106 +61,148 @@ BotLevelBrackets.UseDynamicDistribution = 0 BotLevelBrackets.RealPlayerWeight = 1.0 # -# BotLevelBrackets.IgnoreFriendListed -# Description: Ignore bots that are on real players friend's lists from any brackets -# Default: 1 (enabled) -# Valid values: 0 (off) / 1 (on) -BotLevelBrackets.IgnoreFriendListed = 1 +# BotLevelBrackets.IgnoreFriendListed +# Description: Ignore bots that are on real players friend's lists from any brackets. +# Default: 1 (enabled) +# Valid values: 0 (off) / 1 (on) +BotLevelBrackets.IgnoreFriendListed = 1 # -# Alliance Level Brackets Configuration -# The percentages below must sum to 100. +# BotLevelBrackets.NumRanges +# Description: The number of level brackets used for bot distribution. +# Both Alliance and Horde should have the same number of brackets defined below. +# Default: 9 # -# BotLevelBrackets.Alliance.Range1Pct -# Description: Desired percentage of Alliance bots within level range 1-9. -# Default: 12 -BotLevelBrackets.Alliance.Range1Pct = 12 - -# BotLevelBrackets.Alliance.Range2Pct -# Description: Desired percentage of Alliance bots within level range 10-19. -# Default: 11 -BotLevelBrackets.Alliance.Range2Pct = 11 - -# BotLevelBrackets.Alliance.Range3Pct -# Description: Desired percentage of Alliance bots within level range 20-29. -# Default: 11 -BotLevelBrackets.Alliance.Range3Pct = 11 - -# BotLevelBrackets.Alliance.Range4Pct -# Description: Desired percentage of Alliance bots within level range 30-39. -# Default: 11 -BotLevelBrackets.Alliance.Range4Pct = 11 - -# BotLevelBrackets.Alliance.Range5Pct -# Description: Desired percentage of Alliance bots within level range 40-49. -# Default: 11 -BotLevelBrackets.Alliance.Range5Pct = 11 - -# BotLevelBrackets.Alliance.Range6Pct -# Description: Desired percentage of Alliance bots within level range 50-59. -# Default: 11 -BotLevelBrackets.Alliance.Range6Pct = 11 - -# BotLevelBrackets.Alliance.Range7Pct -# Description: Desired percentage of Alliance bots within level range 60-69. -# Default: 11 -BotLevelBrackets.Alliance.Range7Pct = 11 - -# BotLevelBrackets.Alliance.Range8Pct -# Description: Desired percentage of Alliance bots within level range 70-79. -# Default: 11 -BotLevelBrackets.Alliance.Range8Pct = 11 - -# BotLevelBrackets.Alliance.Range9Pct -# Description: Desired percentage of Alliance bots within level range 80. -# Default: 11 -BotLevelBrackets.Alliance.Range9Pct = 11 +# IMPORTANT: If you are extending the number of brackets beyond 9, you must update your +# mod_player_bot_level_brackets.conf file AND the corresponding mod_player_bot_level_brackets.conf.dist file to include configuration +# lines for the additional bracket lines added below (e.g. Range10, Range11, etc.). Ensure that the +# sum of the Pct values for each faction remains 100. +BotLevelBrackets.NumRanges = 9 +############################################## +# Alliance Level Brackets Configuration +############################################## +# The following settings define the level brackets for Alliance bots. +# For each bracket, you must specify three parameters: # -# Horde Level Brackets Configuration -# The percentages below must sum to 100. +# BotLevelBrackets.Alliance.RangeX.Lower +# Description: The lower bound (inclusive) of bracket X. # -# BotLevelBrackets.Horde.Range1Pct -# Description: Desired percentage of Horde bots within level range 1-9. -# Default: 12 -BotLevelBrackets.Horde.Range1Pct = 12 +# BotLevelBrackets.Alliance.RangeX.Upper +# Description: The upper bound (inclusive) of bracket X. +# +# BotLevelBrackets.Alliance.RangeX.Pct +# Description: The desired percentage of Alliance bots that should fall into bracket X. +# +# EXAMPLE: +# The default configuration below defines 9 brackets: +# +# Range1 covers levels 1-9, Range2 covers levels 10-19, Range3 covers levels 20-29, and so on. +# +# To customize or add a new bracket (for example, to isolate level 60 in its own bracket), you can: +# - Set Range7.Lower = 60 and Range7.Upper = 60, then adjust the Pct values for Range6 and Range8 accordingly. +# +# Also, if you want to add an extra bracket beyond the default 9, you must: +# 1. Increase BotLevelBrackets.NumRanges to the desired number. +# 2. Add configuration lines for the new RangeX.Lower, RangeX.Upper, and RangeX.Pct. +# +# NOTE: +# The sum of all Pct values for the Alliance brackets must equal 100. +# +BotLevelBrackets.Alliance.Range1.Lower = 1 +BotLevelBrackets.Alliance.Range1.Upper = 9 +BotLevelBrackets.Alliance.Range1.Pct = 12 -# BotLevelBrackets.Horde.Range2Pct -# Description: Desired percentage of Horde bots within level range 10-19. -# Default: 11 -BotLevelBrackets.Horde.Range2Pct = 11 +BotLevelBrackets.Alliance.Range2.Lower = 10 +BotLevelBrackets.Alliance.Range2.Upper = 19 +BotLevelBrackets.Alliance.Range2.Pct = 11 -# BotLevelBrackets.Horde.Range3Pct -# Description: Desired percentage of Horde bots within level range 20-29. -# Default: 11 -BotLevelBrackets.Horde.Range3Pct = 11 +BotLevelBrackets.Alliance.Range3.Lower = 20 +BotLevelBrackets.Alliance.Range3.Upper = 29 +BotLevelBrackets.Alliance.Range3.Pct = 11 -# BotLevelBrackets.Horde.Range4Pct -# Description: Desired percentage of Horde bots within level range 30-39. -# Default: 11 -BotLevelBrackets.Horde.Range4Pct = 11 +BotLevelBrackets.Alliance.Range4.Lower = 30 +BotLevelBrackets.Alliance.Range4.Upper = 39 +BotLevelBrackets.Alliance.Range4.Pct = 11 -# BotLevelBrackets.Horde.Range5Pct -# Description: Desired percentage of Horde bots within level range 40-49. -# Default: 11 -BotLevelBrackets.Horde.Range5Pct = 11 +BotLevelBrackets.Alliance.Range5.Lower = 40 +BotLevelBrackets.Alliance.Range5.Upper = 49 +BotLevelBrackets.Alliance.Range5.Pct = 11 -# BotLevelBrackets.Horde.Range6Pct -# Description: Desired percentage of Horde bots within level range 50-59. -# Default: 11 -BotLevelBrackets.Horde.Range6Pct = 11 +BotLevelBrackets.Alliance.Range6.Lower = 50 +BotLevelBrackets.Alliance.Range6.Upper = 59 +BotLevelBrackets.Alliance.Range6.Pct = 11 -# BotLevelBrackets.Horde.Range7Pct -# Description: Desired percentage of Horde bots within level range 60-69. -# Default: 11 -BotLevelBrackets.Horde.Range7Pct = 11 +BotLevelBrackets.Alliance.Range7.Lower = 60 +BotLevelBrackets.Alliance.Range7.Upper = 69 +BotLevelBrackets.Alliance.Range7.Pct = 11 -# BotLevelBrackets.Horde.Range8Pct -# Description: Desired percentage of Horde bots within level range 70-79. -# Default: 11 -BotLevelBrackets.Horde.Range8Pct = 11 +BotLevelBrackets.Alliance.Range8.Lower = 70 +BotLevelBrackets.Alliance.Range8.Upper = 79 +BotLevelBrackets.Alliance.Range8.Pct = 11 -# BotLevelBrackets.Horde.Range9Pct -# Description: Desired percentage of Horde bots within level range 80. -# Default: 11 -BotLevelBrackets.Horde.Range9Pct = 11 +BotLevelBrackets.Alliance.Range9.Lower = 80 +BotLevelBrackets.Alliance.Range9.Upper = 80 +BotLevelBrackets.Alliance.Range9.Pct = 11 + +############################################## +# Horde Level Brackets Configuration +############################################## +# The following settings define the level brackets for Horde bots. +# For each bracket, you must specify: +# +# BotLevelBrackets.Horde.RangeX.Lower +# Description: The lower bound (inclusive) of bracket X. +# +# BotLevelBrackets.Horde.RangeX.Upper +# Description: The upper bound (inclusive) of bracket X. +# +# BotLevelBrackets.Horde.RangeX.Pct +# Description: The desired percentage of Horde bots that should fall into bracket X. +# +# EXAMPLE: +# The default configuration below defines 9 brackets: +# +# Range1 covers levels 1-9, Range2 covers levels 10-19, Range3 covers levels 20-29, and so on. +# +# To customize or add a new bracket (for example, to isolate level 70 in its own bracket), you can: +# - Set Range8.Lower = 70 and Range8.Upper = 70, then adjust the Pct values for the adjacent ranges. +# +# NOTE: +# The sum of all Pct values for the Horde brackets must equal 100. +# +BotLevelBrackets.Horde.Range1.Lower = 1 +BotLevelBrackets.Horde.Range1.Upper = 9 +BotLevelBrackets.Horde.Range1.Pct = 12 + +BotLevelBrackets.Horde.Range2.Lower = 10 +BotLevelBrackets.Horde.Range2.Upper = 19 +BotLevelBrackets.Horde.Range2.Pct = 11 + +BotLevelBrackets.Horde.Range3.Lower = 20 +BotLevelBrackets.Horde.Range3.Upper = 29 +BotLevelBrackets.Horde.Range3.Pct = 11 + +BotLevelBrackets.Horde.Range4.Lower = 30 +BotLevelBrackets.Horde.Range4.Upper = 39 +BotLevelBrackets.Horde.Range4.Pct = 11 + +BotLevelBrackets.Horde.Range5.Lower = 40 +BotLevelBrackets.Horde.Range5.Upper = 49 +BotLevelBrackets.Horde.Range5.Pct = 11 + +BotLevelBrackets.Horde.Range6.Lower = 50 +BotLevelBrackets.Horde.Range6.Upper = 59 +BotLevelBrackets.Horde.Range6.Pct = 11 + +BotLevelBrackets.Horde.Range7.Lower = 60 +BotLevelBrackets.Horde.Range7.Upper = 69 +BotLevelBrackets.Horde.Range7.Pct = 11 + +BotLevelBrackets.Horde.Range8.Lower = 70 +BotLevelBrackets.Horde.Range8.Upper = 79 +BotLevelBrackets.Horde.Range8.Pct = 11 + +BotLevelBrackets.Horde.Range9.Lower = 80 +BotLevelBrackets.Horde.Range9.Upper = 80 +BotLevelBrackets.Horde.Range9.Pct = 11 diff --git a/src/mod-player-bot-level-brackets.cpp b/src/mod-player-bot-level-brackets.cpp index b618b77..dfe2a0c 100644 --- a/src/mod-player-bot-level-brackets.cpp +++ b/src/mod-player-bot-level-brackets.cpp @@ -17,8 +17,9 @@ #include "PlayerbotFactory.h" #include "DatabaseEnv.h" #include "QueryResult.h" +#include - +// Forward declarations. static bool IsAlliancePlayerBot(Player* bot); static bool IsHordePlayerBot(Player* bot); static void ClampAndBalanceBrackets(); @@ -34,7 +35,8 @@ struct LevelRangeConfig uint8 desiredPercent;///< Desired percentage of bots in this range }; -static const uint8 NUM_RANGES = 9; +// Instead of a fixed constant, load the number of brackets from configuration. +static uint8 g_NumRanges = 9; // Global variables to restrict bot levels. static uint8 g_RandomBotMinLevel = 1; @@ -45,10 +47,9 @@ static bool g_BotLevelBracketsEnabled = true; // New configuration option to ignore bots in guilds with a real player online. Default is true. static bool g_IgnoreGuildBotsWithRealPlayers = true; -// Separate arrays for Alliance and Horde. -static LevelRangeConfig g_BaseLevelRanges[NUM_RANGES]; -static LevelRangeConfig g_AllianceLevelRanges[NUM_RANGES]; -static LevelRangeConfig g_HordeLevelRanges[NUM_RANGES]; +// Use vectors to store the level ranges. +static std::vector g_AllianceLevelRanges; +static std::vector g_HordeLevelRanges; static uint32 g_BotDistCheckFrequency = 300; // in seconds static uint32 g_BotDistFlaggedCheckFrequency = 15; // in seconds @@ -69,7 +70,6 @@ std::vector SocialFriendsList; static void LoadBotLevelBracketsConfig() { g_BotLevelBracketsEnabled = sConfigMgr->GetOption("BotLevelBrackets.Enabled", true); - // Load the new option to ignore guild bots with a real player online. g_IgnoreGuildBotsWithRealPlayers = sConfigMgr->GetOption("BotLevelBrackets.IgnoreGuildBotsWithRealPlayers", true); g_BotDistFullDebugMode = sConfigMgr->GetOption("BotLevelBrackets.FullDebugMode", false); @@ -84,45 +84,48 @@ static void LoadBotLevelBracketsConfig() g_RandomBotMinLevel = static_cast(sConfigMgr->GetOption("AiPlayerbot.RandomBotMinLevel", 1)); g_RandomBotMaxLevel = static_cast(sConfigMgr->GetOption("AiPlayerbot.RandomBotMaxLevel", 80)); - // Alliance configuration. - g_AllianceLevelRanges[0] = { 1, 9, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range1Pct", 12)) }; - g_AllianceLevelRanges[1] = { 10, 19, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range2Pct", 11)) }; - g_AllianceLevelRanges[2] = { 20, 29, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range3Pct", 11)) }; - g_AllianceLevelRanges[3] = { 30, 39, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range4Pct", 11)) }; - g_AllianceLevelRanges[4] = { 40, 49, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range5Pct", 11)) }; - g_AllianceLevelRanges[5] = { 50, 59, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range6Pct", 11)) }; - g_AllianceLevelRanges[6] = { 60, 69, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range7Pct", 11)) }; - g_AllianceLevelRanges[7] = { 70, 79, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range8Pct", 11)) }; - g_AllianceLevelRanges[8] = { 80, 80, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range9Pct", 11)) }; + // Load the custom number of brackets. + g_NumRanges = static_cast(sConfigMgr->GetOption("BotLevelBrackets.NumRanges", 9)); + g_AllianceLevelRanges.resize(g_NumRanges); + g_HordeLevelRanges.resize(g_NumRanges); - // Horde configuration. - g_HordeLevelRanges[0] = { 1, 9, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range1Pct", 12)) }; - g_HordeLevelRanges[1] = { 10, 19, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range2Pct", 11)) }; - g_HordeLevelRanges[2] = { 20, 29, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range3Pct", 11)) }; - g_HordeLevelRanges[3] = { 30, 39, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range4Pct", 11)) }; - g_HordeLevelRanges[4] = { 40, 49, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range5Pct", 11)) }; - g_HordeLevelRanges[5] = { 50, 59, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range6Pct", 11)) }; - g_HordeLevelRanges[6] = { 60, 69, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range7Pct", 11)) }; - g_HordeLevelRanges[7] = { 70, 79, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range8Pct", 11)) }; - g_HordeLevelRanges[8] = { 80, 80, static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range9Pct", 11)) }; + // Load Alliance configuration. + for (uint8 i = 0; i < g_NumRanges; ++i) + { + std::string idx = std::to_string(i + 1); + g_AllianceLevelRanges[i].lower = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range" + idx + ".Lower", (i == 0 ? 1 : i * 10))); + g_AllianceLevelRanges[i].upper = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range" + idx + ".Upper", (i < g_NumRanges - 1 ? i * 10 + 9 : g_RandomBotMaxLevel))); + g_AllianceLevelRanges[i].desiredPercent = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Alliance.Range" + idx + ".Pct", 11)); + } + + // Load Horde configuration. + for (uint8 i = 0; i < g_NumRanges; ++i) + { + std::string idx = std::to_string(i + 1); + g_HordeLevelRanges[i].lower = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range" + idx + ".Lower", (i == 0 ? 1 : i * 10))); + g_HordeLevelRanges[i].upper = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range" + idx + ".Upper", (i < g_NumRanges - 1 ? i * 10 + 9 : g_RandomBotMaxLevel))); + g_HordeLevelRanges[i].desiredPercent = static_cast(sConfigMgr->GetOption("BotLevelBrackets.Horde.Range" + idx + ".Pct", 11)); + } ClampAndBalanceBrackets(); } // ----------------------------------------------------------------------------- // Loads the friend guid(s) from character_social into array -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- static void LoadSocialFriendList() { SocialFriendsList.clear(); QueryResult result = CharacterDatabase.Query("SELECT friend FROM character_social WHERE flags = 1"); if (!result) + { return; - + } if (result->GetRowCount() == 0) + { return; - + } if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Fetching Social Friend List GUIDs into array"); @@ -137,32 +140,35 @@ static void LoadSocialFriendList() LOG_INFO("server.load", "[BotLevelBrackets] Adding GUID {} to Social Friend List", socialFriendGUID); } } while (result->NextRow()); - } -// Returns the index of the level range bracket that the given level belongs to. +// Returns the index of the level bracket that the given level belongs to. // If the bot is out of range, it returns -1 static int GetLevelRangeIndex(uint8 level, uint8 teamID) { - // If the bot's level is outside the allowed global bounds, signal an invalid bracket. if (level < g_RandomBotMinLevel || level > g_RandomBotMaxLevel) - return -1; - - if(teamID == TEAM_ALLIANCE) { - for (int i = 0; i < NUM_RANGES; ++i) - { - if (level >= g_AllianceLevelRanges[i].lower && level <= g_AllianceLevelRanges[i].upper) - return i; - } + return -1; } - if(teamID == TEAM_HORDE) + if (teamID == TEAM_ALLIANCE) { - for (int i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) + { + if (level >= g_AllianceLevelRanges[i].lower && level <= g_AllianceLevelRanges[i].upper) + { + return i; + } + } + } + else if (teamID == TEAM_HORDE) + { + for (uint8 i = 0; i < g_NumRanges; ++i) { if (level >= g_HordeLevelRanges[i].lower && level <= g_HordeLevelRanges[i].upper) + { return i; + } } } @@ -178,8 +184,10 @@ static uint8 GetRandomLevelInRange(const LevelRangeConfig& range) // Adjusts a bot's level by selecting a random level within the target range. static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRangeConfig* factionRanges) { - if (!bot || targetRangeIndex < 0 || targetRangeIndex >= NUM_RANGES) + if (!bot || targetRangeIndex < 0 || targetRangeIndex >= g_NumRanges) + { return; + } if (bot->IsMounted()) { @@ -206,7 +214,9 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRange return; } if (lowerBound < 55) + { lowerBound = 55; + } newLevel = urand(lowerBound, upperBound); } else @@ -215,7 +225,6 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRange } PlayerbotFactory newFactory(bot, newLevel); - newFactory.Randomize(false); if (g_BotDistFullDebugMode) @@ -238,7 +247,9 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRange static bool IsPlayerBot(Player* player) { if (!player) + { return false; + } PlayerbotAI* botAI = sPlayerbotsMgr->GetPlayerbotAI(player); return botAI && botAI->IsBotAI(); } @@ -246,20 +257,19 @@ static bool IsPlayerBot(Player* player) static bool IsPlayerRandomBot(Player* player) { if (!player) + { return false; + } return sRandomPlayerbotMgr->IsRandomBot(player); } -// Helper functions to determine faction. static bool IsAlliancePlayerBot(Player* bot) { - // Assumes GetTeam() returns TEAM_ALLIANCE for Alliance bots. return bot && (bot->GetTeamId() == TEAM_ALLIANCE); } static bool IsHordePlayerBot(Player* bot) { - // Assumes GetTeam() returns TEAM_HORDE for Horde bots. return bot && (bot->GetTeamId() == TEAM_HORDE); } @@ -272,11 +282,14 @@ static void LogAllBotLevels() { Player* player = itr.second; if (!player || !player->IsInWorld()) + { continue; + } if (!IsPlayerBot(player)) + { continue; - uint8 level = player->GetLevel(); - botLevelCount[level]++; + } + botLevelCount[player->GetLevel()]++; } for (const auto& entry : botLevelCount) { @@ -291,20 +304,26 @@ static void LogAllBotLevels() static bool BotInGuildWithRealPlayer(Player* bot) { if (!bot) + { return false; - // If the bot is not in a guild, nothing to do. + } uint32 guildId = bot->GetGuildId(); if (guildId == 0) + { return false; + } - // Iterate over all players and check for an online, non-bot member in the same guild. for (auto const& itr : ObjectAccessor::GetPlayers()) { Player* member = itr.second; if (!member || !member->IsInWorld()) + { continue; + } if (!IsPlayerBot(member) && member->GetGuildId() == guildId) + { return true; + } } return false; } @@ -312,7 +331,9 @@ static bool BotInGuildWithRealPlayer(Player* bot) static bool BotInFriendList(Player* bot) { if (!bot) + { return false; + } for (size_t i = 0; i < SocialFriendsList.size(); ++i) { @@ -334,51 +355,55 @@ static bool BotInFriendList(Player* bot) static void ClampAndBalanceBrackets() { - // First, adjust Alliance brackets. - for (uint8 i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) { if (g_AllianceLevelRanges[i].lower < g_RandomBotMinLevel) + { g_AllianceLevelRanges[i].lower = g_RandomBotMinLevel; + } if (g_AllianceLevelRanges[i].upper > g_RandomBotMaxLevel) + { g_AllianceLevelRanges[i].upper = g_RandomBotMaxLevel; - // If the adjusted bracket is invalid, mark it to not be used. + } if (g_AllianceLevelRanges[i].lower > g_AllianceLevelRanges[i].upper) + { g_AllianceLevelRanges[i].desiredPercent = 0; + } } - // Then, adjust Horde brackets similarly. - for (uint8 i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) { if (g_HordeLevelRanges[i].lower < g_RandomBotMinLevel) + { g_HordeLevelRanges[i].lower = g_RandomBotMinLevel; + } if (g_HordeLevelRanges[i].upper > g_RandomBotMaxLevel) + { g_HordeLevelRanges[i].upper = g_RandomBotMaxLevel; + } if (g_HordeLevelRanges[i].lower > g_HordeLevelRanges[i].upper) + { g_HordeLevelRanges[i].desiredPercent = 0; + } } - // Balance desired percentages so the sum is 100. uint32 totalAlliance = 0; uint32 totalHorde = 0; - for (uint8 i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) { totalAlliance += g_AllianceLevelRanges[i].desiredPercent; totalHorde += g_HordeLevelRanges[i].desiredPercent; } - // If totals are not 100, then distribute the missing percent among valid brackets. - if(totalAlliance != 100 && totalAlliance > 0) + if (totalAlliance != 100 && totalAlliance > 0) { - if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance: Sum of percentages is {} (expected 100). Auto adjusting.", totalAlliance); } - int missing = 100 - totalAlliance; - while(missing > 0) + while (missing > 0) { - for (uint8 i = 0; i < NUM_RANGES && missing > 0; ++i) + for (uint8 i = 0; i < g_NumRanges && missing > 0; ++i) { - if(g_AllianceLevelRanges[i].lower <= g_AllianceLevelRanges[i].upper && - g_AllianceLevelRanges[i].desiredPercent > 0) + if (g_AllianceLevelRanges[i].lower <= g_AllianceLevelRanges[i].upper && g_AllianceLevelRanges[i].desiredPercent > 0) { g_AllianceLevelRanges[i].desiredPercent++; missing--; @@ -386,20 +411,18 @@ static void ClampAndBalanceBrackets() } } } - if(totalHorde != 100 && totalHorde > 0) + if (totalHorde != 100 && totalHorde > 0) { if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Horde: Sum of percentages is {} (expected 100). Auto adjusting.", totalHorde); } - int missing = 100 - totalHorde; - while(missing > 0) + while (missing > 0) { - for (uint8 i = 0; i < NUM_RANGES && missing > 0; ++i) + for (uint8 i = 0; i < g_NumRanges && missing > 0; ++i) { - if(g_HordeLevelRanges[i].lower <= g_HordeLevelRanges[i].upper && - g_HordeLevelRanges[i].desiredPercent > 0) + if (g_HordeLevelRanges[i].lower <= g_HordeLevelRanges[i].upper && g_HordeLevelRanges[i].desiredPercent > 0) { g_HordeLevelRanges[i].desiredPercent++; missing--; @@ -477,11 +500,9 @@ static bool IsBotSafeForLevelReset(Player* bot) } } } - return true; } - // Global container to hold bots flagged for pending level reset. // Each entry is a pair: the bot and the target level range index along with a pointer to the faction config. struct PendingResetEntry @@ -498,15 +519,15 @@ static void ProcessPendingLevelResets() { LOG_INFO("server.loading", "[BotLevelBrackets] Processing {} pending resets...", g_PendingLevelResets.size()); } - if (g_PendingLevelResets.empty()) + { return; + } for (auto it = g_PendingLevelResets.begin(); it != g_PendingLevelResets.end(); ) { Player* bot = it->bot; int targetRange = it->targetRange; - // If the bot is in a guild with a real player online and the option is enabled, remove it from pending resets. if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(bot)) { it = g_PendingLevelResets.erase(it); @@ -541,29 +562,41 @@ static int GetOrFlagPlayerBracket(Player* player) { int rangeIndex = GetLevelRangeIndex(player->GetLevel(), player->GetTeamId()); if (rangeIndex >= 0) + { return rangeIndex; + } LevelRangeConfig* factionRanges = nullptr; if (IsAlliancePlayerBot(player)) - factionRanges = g_AllianceLevelRanges; + { + factionRanges = g_AllianceLevelRanges.data(); + } else if (IsHordePlayerBot(player)) - factionRanges = g_HordeLevelRanges; + { + factionRanges = g_HordeLevelRanges.data(); + } else + { return -1; // Unknown faction + } - // Player's level did not fall into any base range; compute the closest valid bracket. int targetRange = -1; int smallestDiff = std::numeric_limits::max(); - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { - // Only consider valid brackets (those not disabled by ClampAndBalanceBrackets) if (factionRanges[i].lower > factionRanges[i].upper) + { continue; + } int diff = 0; if (player->GetLevel() < factionRanges[i].lower) + { diff = factionRanges[i].lower - player->GetLevel(); + } else if (player->GetLevel() > factionRanges[i].upper) + { diff = player->GetLevel() - factionRanges[i].upper; + } if (diff < smallestDiff) { smallestDiff = diff; @@ -573,7 +606,6 @@ static int GetOrFlagPlayerBracket(Player* player) if (targetRange >= 0) { - // Add the player to the pending reset list if not already flagged. bool alreadyFlagged = false; for (const auto &entry : g_PendingLevelResets) { @@ -612,12 +644,12 @@ public: if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Module loaded. Check frequency: {} seconds, Check flagged frequency: {}.", g_BotDistCheckFrequency, g_BotDistFlaggedCheckFrequency); - for (uint8 i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance Range {}: {}-{}, Desired Percentage: {}%", i + 1, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper, g_AllianceLevelRanges[i].desiredPercent); } - for (uint8 i = 0; i < NUM_RANGES; ++i) + for (uint8 i = 0; i < g_NumRanges; ++i) { LOG_INFO("server.loading", "[BotLevelBrackets] Horde Range {}: {}-{}, Desired Percentage: {}%", i + 1, g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper, g_HordeLevelRanges[i].desiredPercent); @@ -628,48 +660,53 @@ public: void OnUpdate(uint32 diff) override { if (!g_BotLevelBracketsEnabled) + { return; + } m_timer += diff; m_flaggedTimer += diff; - // Process pending level resets. if (m_flaggedTimer >= g_BotDistFlaggedCheckFrequency * 1000) { if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Pending Level Resets Triggering."); - } + } ProcessPendingLevelResets(); m_flaggedTimer = 0; } - // Continue with distribution adjustments once the timer expires. if (m_timer < g_BotDistCheckFrequency * 1000) + { return; + } m_timer = 0; - // Refresh Social Friends List Array LoadSocialFriendList(); - // Dynamic distribution: recalc desired percentages based on non-bot players. if (g_UseDynamicDistribution) { - int allianceRealCounts[NUM_RANGES] = {0}; - int hordeRealCounts[NUM_RANGES] = {0}; + std::vector allianceRealCounts(g_NumRanges, 0); + std::vector hordeRealCounts(g_NumRanges, 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 = GetOrFlagPlayerBracket(player); if (rangeIndex < 0) + { continue; + } if (player->GetTeamId() == TEAM_ALLIANCE) { allianceRealCounts[rangeIndex]++; @@ -681,34 +718,39 @@ public: totalHordeReal++; } } - // Use a baseline weight to ensure an equal share when no real players are present. const float baseline = 1.0f; + std::vector allianceWeights(g_NumRanges, 0.0f); + std::vector hordeWeights(g_NumRanges, 0.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) + for (int i = 0; i < g_NumRanges; ++i) { - // Only count valid brackets. if (g_AllianceLevelRanges[i].lower > g_AllianceLevelRanges[i].upper) + { allianceWeights[i] = 0.0f; + } else + { allianceWeights[i] = baseline + g_RealPlayerWeight * (totalAllianceReal > 0 ? (1.0f / totalAllianceReal) : 1.0f) * log(1 + allianceRealCounts[i]); + } if (g_HordeLevelRanges[i].lower > g_HordeLevelRanges[i].upper) + { hordeWeights[i] = 0.0f; + } else + { hordeWeights[i] = baseline + g_RealPlayerWeight * (totalHordeReal > 0 ? (1.0f / totalHordeReal) : 1.0f) * log(1 + hordeRealCounts[i]); + } allianceTotalWeight += allianceWeights[i]; hordeTotalWeight += hordeWeights[i]; } - // Recalculate desired percentages for each range. - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { g_AllianceLevelRanges[i].desiredPercent = static_cast(round((allianceWeights[i] / allianceTotalWeight) * 100)); if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) @@ -719,8 +761,10 @@ public: } uint8 sumAlliance = 0; - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) + { sumAlliance += g_AllianceLevelRanges[i].desiredPercent; + } if (sumAlliance < 100 && allianceTotalWeight > 0) { uint8 missing = 100 - sumAlliance; @@ -730,10 +774,9 @@ public: } while (missing > 0) { - for (int i = 0; i < NUM_RANGES && missing > 0; ++i) + for (int i = 0; i < g_NumRanges && missing > 0; ++i) { - if (g_AllianceLevelRanges[i].lower <= g_AllianceLevelRanges[i].upper && - allianceWeights[i] > 0) + if (g_AllianceLevelRanges[i].lower <= g_AllianceLevelRanges[i].upper && allianceWeights[i] > 0) { g_AllianceLevelRanges[i].desiredPercent++; missing--; @@ -743,18 +786,15 @@ public: if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance normalized percentages:"); - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { - LOG_INFO("server.loading", " Range {}: {}% ({}-{})", i + 1, - g_AllianceLevelRanges[i].desiredPercent, - g_AllianceLevelRanges[i].lower, - g_AllianceLevelRanges[i].upper); + LOG_INFO("server.loading", " Range {}: {}% ({}-{})", i + 1, g_AllianceLevelRanges[i].desiredPercent, + g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper); } } } - - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { g_HordeLevelRanges[i].desiredPercent = static_cast(round((hordeWeights[i] / hordeTotalWeight) * 100)); if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) @@ -765,8 +805,10 @@ public: } uint8 sumHorde = 0; - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) + { sumHorde += g_HordeLevelRanges[i].desiredPercent; + } if (sumHorde < 100 && hordeTotalWeight > 0) { uint8 missing = 100 - sumHorde; @@ -776,10 +818,9 @@ public: } while (missing > 0) { - for (int i = 0; i < NUM_RANGES && missing > 0; ++i) + for (int i = 0; i < g_NumRanges && missing > 0; ++i) { - if (g_HordeLevelRanges[i].lower <= g_HordeLevelRanges[i].upper && - hordeWeights[i] > 0) + if (g_HordeLevelRanges[i].lower <= g_HordeLevelRanges[i].upper && hordeWeights[i] > 0) { g_HordeLevelRanges[i].desiredPercent++; missing--; @@ -789,32 +830,28 @@ public: if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Horde normalized percentages:"); - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { - LOG_INFO("server.loading", " Range {}: {}% ({}-{})", i + 1, - g_HordeLevelRanges[i].desiredPercent, - g_HordeLevelRanges[i].lower, - g_HordeLevelRanges[i].upper); + LOG_INFO("server.loading", " Range {}: {}% ({}-{})", i + 1, g_HordeLevelRanges[i].desiredPercent, + g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper); } } } - } - // Containers for Alliance bots. uint32 totalAllianceBots = 0; - int allianceActualCounts[NUM_RANGES] = {0}; - std::vector allianceBotsByRange[NUM_RANGES]; + std::vector allianceActualCounts(g_NumRanges, 0); + std::vector< std::vector > allianceBotsByRange(g_NumRanges); - // Containers for Horde bots. uint32 totalHordeBots = 0; - int hordeActualCounts[NUM_RANGES] = {0}; - std::vector hordeBotsByRange[NUM_RANGES]; + std::vector hordeActualCounts(g_NumRanges, 0); + std::vector< std::vector > hordeBotsByRange(g_NumRanges); - // Iterate only over player bots. auto const& allPlayers = ObjectAccessor::GetPlayers(); if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Starting processing of {} players.", allPlayers.size()); + } for (auto const& itr : allPlayers) { @@ -822,29 +859,35 @@ public: if (!player) { if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Skipping null player."); + } continue; } if (!player->IsInWorld()) { if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Skipping player '{}' as they are not in world.", player->GetName()); + } continue; } if (!IsPlayerBot(player) || !IsPlayerRandomBot(player)) { if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Skipping player '{}' as they are not a random bot.", player->GetName()); + } continue; } - // If the bot is in a guild with a real player online and the option is enabled, skip it. if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(player)) + { continue; - - // If the bot is a friend with a real player and the option is enabled, skip it. + } if (g_IgnoreFriendListed && BotInFriendList(player)) + { continue; - + } if (IsAlliancePlayerBot(player)) { totalAllianceBots++; @@ -854,13 +897,14 @@ public: allianceActualCounts[rangeIndex]++; allianceBotsByRange[rangeIndex].push_back(player); if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' with level {} added to range {}.", player->GetName(), player->GetLevel(), rangeIndex + 1); + } } else if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' with level {} does not fall into any defined range.", - player->GetName(), player->GetLevel()); + LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' with level {} does not fall into any defined range.", player->GetName(), player->GetLevel()); } } else if (IsHordePlayerBot(player)) @@ -872,13 +916,14 @@ public: hordeActualCounts[rangeIndex]++; hordeBotsByRange[rangeIndex].push_back(player); if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' with level {} added to range {}.", player->GetName(), player->GetLevel(), rangeIndex + 1); + } } else if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' with level {} does not fall into any defined range.", - player->GetName(), player->GetLevel()); + LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' with level {} does not fall into any defined range.", player->GetName(), player->GetLevel()); } } } @@ -898,8 +943,8 @@ public: { LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); } - int allianceDesiredCounts[NUM_RANGES] = {0}; - for (int i = 0; i < NUM_RANGES; ++i) + std::vector allianceDesiredCounts(g_NumRanges, 0); + for (int i = 0; i < g_NumRanges; ++i) { allianceDesiredCounts[i] = static_cast(round((g_AllianceLevelRanges[i].desiredPercent / 100.0) * totalAllianceBots)); if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) @@ -909,16 +954,12 @@ public: allianceDesiredCounts[i], allianceActualCounts[i]); } } - if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); - } - // Adjust overpopulated ranges. - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] >>> Processing Alliance bots in range {}.", i + 1); - + } std::vector safeBots; std::vector flaggedBots; for (Player* bot : allianceBotsByRange[i]) @@ -926,17 +967,15 @@ public: if (IsBotSafeForLevelReset(bot)) { safeBots.push_back(bot); - if (g_BotDistFullDebugMode) - { - //LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' is safe for level reset in range {}.", bot->GetName(), i + 1); - } } else { flaggedBots.push_back(bot); if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' is NOT safe for level reset in range {}.", bot->GetName(), i + 1); + } } } while (allianceActualCounts[i] > allianceDesiredCounts[i] && !safeBots.empty()) @@ -950,7 +989,7 @@ public: int targetRange = -1; if (bot->getClass() == CLASS_DEATH_KNIGHT) { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (allianceActualCounts[j] < allianceDesiredCounts[j] && g_AllianceLevelRanges[j].upper >= 55) { @@ -961,7 +1000,7 @@ public: } else { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (allianceActualCounts[j] < allianceDesiredCounts[j]) { @@ -980,9 +1019,10 @@ public: } if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting alliance bot '{}' from range {} to range {} ({}-{}).", bot->GetName(), i + 1, targetRange + 1, g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); + LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting alliance bot '{}' from range {} to range {} ({}-{}).", + bot->GetName(), i + 1, targetRange + 1, g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); } - AdjustBotToRange(bot, targetRange, g_AllianceLevelRanges); + AdjustBotToRange(bot, targetRange, g_AllianceLevelRanges.data()); allianceActualCounts[i]--; allianceActualCounts[targetRange]++; } @@ -990,7 +1030,6 @@ public: { Player* bot = flaggedBots.back(); flaggedBots.pop_back(); - if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance flagged bot '{}' from range {} will be processed for pending reset.", bot->GetName(), i + 1); @@ -998,7 +1037,7 @@ public: int targetRange = -1; if (bot->getClass() == CLASS_DEATH_KNIGHT) { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (allianceActualCounts[j] < allianceDesiredCounts[j] && g_AllianceLevelRanges[j].upper >= 55) { @@ -1009,7 +1048,7 @@ public: } else { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (allianceActualCounts[j] < allianceDesiredCounts[j]) { @@ -1037,10 +1076,11 @@ public: } if (!alreadyFlagged) { - g_PendingLevelResets.push_back({bot, targetRange, g_AllianceLevelRanges}); + g_PendingLevelResets.push_back({bot, targetRange, g_AllianceLevelRanges.data()}); if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' flagged for pending level reset to range {}-{}.", bot->GetName(), g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); + LOG_INFO("server.loading", "[BotLevelBrackets] Alliance bot '{}' flagged for pending level reset to range {}-{}.", + bot->GetName(), g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); } } } @@ -1054,8 +1094,8 @@ public: { LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); } - int hordeDesiredCounts[NUM_RANGES] = {0}; - for (int i = 0; i < NUM_RANGES; ++i) + std::vector hordeDesiredCounts(g_NumRanges, 0); + for (int i = 0; i < g_NumRanges; ++i) { hordeDesiredCounts[i] = static_cast(round((g_HordeLevelRanges[i].desiredPercent / 100.0) * totalHordeBots)); if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) @@ -1065,15 +1105,12 @@ public: hordeDesiredCounts[i], hordeActualCounts[i]); } } - if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); - } - for (int i = 0; i < NUM_RANGES; ++i) + for (int i = 0; i < g_NumRanges; ++i) { if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Processing Horde bots in range {}.", i + 1); - + } std::vector safeBots; std::vector flaggedBots; for (Player* bot : hordeBotsByRange[i]) @@ -1081,33 +1118,29 @@ public: if (IsBotSafeForLevelReset(bot)) { safeBots.push_back(bot); - if (g_BotDistFullDebugMode) - { - //LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' is safe for level reset in range {}.", bot->GetName(), i + 1); - } } else { flaggedBots.push_back(bot); if (g_BotDistFullDebugMode) + { LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' is NOT safe for level reset in range {}.", bot->GetName(), i + 1); + } } } while (hordeActualCounts[i] > hordeDesiredCounts[i] && !safeBots.empty()) { Player* bot = safeBots.back(); safeBots.pop_back(); - if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Horde safe bot '{}' from range {} will be moved.", bot->GetName(), i + 1); } - int targetRange = -1; if (bot->getClass() == CLASS_DEATH_KNIGHT) { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (hordeActualCounts[j] < hordeDesiredCounts[j] && g_HordeLevelRanges[j].upper >= 55) { @@ -1118,7 +1151,7 @@ public: } else { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (hordeActualCounts[j] < hordeDesiredCounts[j]) { @@ -1137,9 +1170,10 @@ public: } if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting horde bot '{}' from range {} to range {} ({}-{}).", bot->GetName(), i + 1, targetRange + 1, g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); + LOG_INFO("server.loading", "[BotLevelBrackets] !!!! Adjusting horde bot '{}' from range {} to range {} ({}-{}).", + bot->GetName(), i + 1, targetRange + 1, g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); } - AdjustBotToRange(bot, targetRange, g_HordeLevelRanges); + AdjustBotToRange(bot, targetRange, g_HordeLevelRanges.data()); hordeActualCounts[i]--; hordeActualCounts[targetRange]++; } @@ -1154,7 +1188,7 @@ public: int targetRange = -1; if (bot->getClass() == CLASS_DEATH_KNIGHT) { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (hordeActualCounts[j] < hordeDesiredCounts[j] && g_HordeLevelRanges[j].upper >= 55) { @@ -1165,7 +1199,7 @@ public: } else { - for (int j = 0; j < NUM_RANGES; ++j) + for (int j = 0; j < g_NumRanges; ++j) { if (hordeActualCounts[j] < hordeDesiredCounts[j]) { @@ -1193,27 +1227,25 @@ public: } if (!alreadyFlagged) { - g_PendingLevelResets.push_back({bot, targetRange, g_HordeLevelRanges}); + g_PendingLevelResets.push_back({bot, targetRange, g_HordeLevelRanges.data()}); if (g_BotDistFullDebugMode) { - LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' flagged for pending level reset to range {}-{}.", bot->GetName(), g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); + LOG_INFO("server.loading", "[BotLevelBrackets] Horde bot '{}' flagged for pending level reset to range {}-{}.", + bot->GetName(), g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); } } } } } - if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] ========================================= COMPLETE"); LOG_INFO("server.loading", "[BotLevelBrackets] Distribution adjustment complete. Alliance bots: {}, Horde bots: {}.", totalAllianceBots, totalHordeBots); LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); - LogAllBotLevels(); - LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); - int allianceDesiredCounts[NUM_RANGES] = {0}; - for (int i = 0; i < NUM_RANGES; ++i) + std::vector allianceDesiredCounts(g_NumRanges, 0); + for (int i = 0; i < g_NumRanges; ++i) { allianceDesiredCounts[i] = static_cast(round((g_AllianceLevelRanges[i].desiredPercent / 100.0) * totalAllianceBots)); LOG_INFO("server.loading", "[BotLevelBrackets] Alliance Range {} ({}-{}): Desired = {}, Actual = {}.", @@ -1221,8 +1253,8 @@ public: allianceDesiredCounts[i], allianceActualCounts[i]); } LOG_INFO("server.loading", "[BotLevelBrackets] ----------------------------------------"); - int hordeDesiredCounts[NUM_RANGES] = {0}; - for (int i = 0; i < NUM_RANGES; ++i) + std::vector hordeDesiredCounts(g_NumRanges, 0); + for (int i = 0; i < g_NumRanges; ++i) { hordeDesiredCounts[i] = static_cast(round((g_HordeLevelRanges[i].desiredPercent / 100.0) * totalHordeBots)); LOG_INFO("server.loading", "[BotLevelBrackets] Horde Range {} ({}-{}): Desired = {}, Actual = {}.", @@ -1230,7 +1262,6 @@ public: hordeDesiredCounts[i], hordeActualCounts[i]); } LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); - } }