From 41ba216d48ee1528bf6f5cd771cdb4e4e673d703 Mon Sep 17 00:00:00 2001 From: Dustin Hendrickson Date: Tue, 27 May 2025 07:22:18 -0700 Subject: [PATCH 1/3] Better safety checks --- src/mod-player-bot-level-brackets.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/mod-player-bot-level-brackets.cpp b/src/mod-player-bot-level-brackets.cpp index d50d881..bf54a3a 100644 --- a/src/mod-player-bot-level-brackets.cpp +++ b/src/mod-player-bot-level-brackets.cpp @@ -210,7 +210,12 @@ 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 >= g_NumRanges) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) + { + return; + } + + if (targetRangeIndex < 0 || targetRangeIndex >= g_NumRanges) { return; } @@ -329,7 +334,7 @@ static void LogAllBotLevels() // ----------------------------------------------------------------------------- static bool BotInGuildWithRealPlayer(Player* bot) { - if (!bot) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { return false; } @@ -356,7 +361,7 @@ static bool BotInGuildWithRealPlayer(Player* bot) static bool BotInFriendList(Player* bot) { - if (!bot) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { return false; } @@ -459,7 +464,7 @@ static void ClampAndBalanceBrackets() // ----------------------------------------------------------------------------- static bool IsBotSafeForLevelReset(Player* bot) { - if (!bot) + if (!bot || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { if (g_BotDistFullDebugMode) { @@ -555,7 +560,7 @@ static void ProcessPendingLevelResets() Player* bot = it->bot; - if (!bot || !bot->IsInWorld()) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { it = g_PendingLevelResets.erase(it); continue; @@ -976,7 +981,7 @@ public: while (allianceActualCounts[i] > allianceDesiredCounts[i] && !safeBots.empty()) { Player* bot = safeBots.back(); - if (!bot || !bot->IsInWorld()) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { safeBots.pop_back(); continue; @@ -1045,7 +1050,7 @@ public: while (allianceActualCounts[i] > allianceDesiredCounts[i] && !flaggedBots.empty()) { Player* bot = flaggedBots.back(); - if (!bot || !bot->IsInWorld()) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { flaggedBots.pop_back(); continue; @@ -1152,7 +1157,7 @@ public: while (hordeActualCounts[i] > hordeDesiredCounts[i] && !safeBots.empty()) { Player* bot = safeBots.back(); - if (!bot || !bot->IsInWorld()) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { safeBots.pop_back(); continue; @@ -1221,7 +1226,7 @@ public: while (hordeActualCounts[i] > hordeDesiredCounts[i] && !flaggedBots.empty()) { Player* bot = flaggedBots.back(); - if (!bot || !bot->IsInWorld()) + if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) { flaggedBots.pop_back(); continue; From f1367a0f00c277059eee65bb2f23e42aeb88252c Mon Sep 17 00:00:00 2001 From: Dustin Hendrickson Date: Tue, 27 May 2025 08:17:39 -0700 Subject: [PATCH 2/3] Performance update. --- src/mod-player-bot-level-brackets.cpp | 62 ++++++++++++++++++--------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/mod-player-bot-level-brackets.cpp b/src/mod-player-bot-level-brackets.cpp index bf54a3a..95ea2d4 100644 --- a/src/mod-player-bot-level-brackets.cpp +++ b/src/mod-player-bot-level-brackets.cpp @@ -69,7 +69,11 @@ static float g_RealPlayerWeight = 1.0f; static bool g_SyncFactions = false; // Array for character social list friends -std::vector SocialFriendsList; +std::vector g_SocialFriendsList; + +// Array for real player guild IDs. +std::unordered_set g_RealPlayerGuildIds; + // ----------------------------------------------------------------------------- // Loads the configuration from the config file. @@ -141,7 +145,7 @@ static void LoadBotLevelBracketsConfig() // ----------------------------------------------------------------------------- static void LoadSocialFriendList() { - SocialFriendsList.clear(); + g_SocialFriendsList.clear(); QueryResult result = CharacterDatabase.Query("SELECT friend FROM character_social WHERE flags = 1"); if (!result) @@ -160,7 +164,7 @@ static void LoadSocialFriendList() do { uint32 socialFriendGUID = result->Fetch()->Get(); - SocialFriendsList.push_back(socialFriendGUID); + g_SocialFriendsList.push_back(socialFriendGUID); if (g_BotDistFullDebugMode) { LOG_INFO("server.load", "[BotLevelBrackets] Adding GUID {} to Social Friend List", socialFriendGUID); @@ -168,6 +172,32 @@ static void LoadSocialFriendList() } while (result->NextRow()); } +// ----------------------------------------------------------------------------- +// Loads the guild IDs of real players into a global set. +// This is used to check if a bot is in a guild with at least one real player online. +// ----------------------------------------------------------------------------- +static void LoadRealPlayerGuildIds(const std::unordered_map& players) +{ + g_RealPlayerGuildIds.clear(); + for (const auto& itr : players) + { + Player* player = itr.second; + if (!player || !player->IsInWorld()) + { + continue; + } + if (!IsPlayerBot(player)) + { + uint32 guildId = player->GetGuildId(); + if (guildId != 0) + { + g_RealPlayerGuildIds.insert(guildId); + } + } + } +} + + // 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) @@ -343,20 +373,7 @@ static bool BotInGuildWithRealPlayer(Player* bot) { return false; } - - 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; + return g_RealPlayerGuildIds.count(guildId) > 0; } static bool BotInFriendList(Player* bot) @@ -366,9 +383,9 @@ static bool BotInFriendList(Player* bot) return false; } - for (size_t i = 0; i < SocialFriendsList.size(); ++i) + for (size_t i = 0; i < g_SocialFriendsList.size(); ++i) { - if (SocialFriendsList[i] == bot->GetGUID().GetRawValue()) + if (g_SocialFriendsList[i] == bot->GetGUID().GetRawValue()) { if (g_BotDistFullDebugMode) { @@ -725,6 +742,10 @@ public: } m_timer = 0; + const auto& allPlayers = ObjectAccessor::GetPlayers(); + + LoadRealPlayerGuildIds(allPlayers); + LoadSocialFriendList(); if (g_UseDynamicDistribution) @@ -735,7 +756,7 @@ public: uint32 totalAllianceReal = 0; uint32 totalHordeReal = 0; - for (auto const& itr : ObjectAccessor::GetPlayers()) + for (auto const& itr : allPlayers) { Player* player = itr.second; if (!player || !player->IsInWorld()) @@ -847,7 +868,6 @@ public: std::vector hordeActualCounts(g_NumRanges, 0); std::vector< std::vector > hordeBotsByRange(g_NumRanges); - auto const& allPlayers = ObjectAccessor::GetPlayers(); if (g_BotDistFullDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Starting processing of {} players.", allPlayers.size()); From c8ed4f4631d7298bd33907a9a4e18d63db1d4ada Mon Sep 17 00:00:00 2001 From: Dustin Hendrickson Date: Tue, 27 May 2025 10:43:57 -0700 Subject: [PATCH 3/3] Performance update refined. --- src/mod-player-bot-level-brackets.cpp | 404 ++++++++++---------------- 1 file changed, 147 insertions(+), 257 deletions(-) diff --git a/src/mod-player-bot-level-brackets.cpp b/src/mod-player-bot-level-brackets.cpp index 95ea2d4..fea2d4c 100644 --- a/src/mod-player-bot-level-brackets.cpp +++ b/src/mod-player-bot-level-brackets.cpp @@ -140,6 +140,63 @@ static void LoadBotLevelBracketsConfig() ClampAndBalanceBrackets(); } +// ----------------------------------------------------------------------------- +// BOT DETECTION HELPERS +// ----------------------------------------------------------------------------- +static bool IsPlayerBot(Player* player) +{ + if (!player) + { + return false; + } + PlayerbotAI* botAI = sPlayerbotsMgr->GetPlayerbotAI(player); + return botAI && botAI->IsBotAI(); +} + +static bool IsPlayerRandomBot(Player* player) +{ + if (!player) + { + return false; + } + return sRandomPlayerbotMgr->IsRandomBot(player); +} + +static bool IsAlliancePlayerBot(Player* bot) +{ + return bot && (bot->GetTeamId() == TEAM_ALLIANCE); +} + +static bool IsHordePlayerBot(Player* bot) +{ + return bot && (bot->GetTeamId() == TEAM_HORDE); +} + +static void LogAllBotLevels() +{ + if (g_BotDistFullDebugMode) + { + std::map botLevelCount; + for (auto const& itr : ObjectAccessor::GetPlayers()) + { + Player* player = itr.second; + if (!player || !player->IsInWorld()) + { + continue; + } + if (!IsPlayerBot(player)) + { + continue; + } + botLevelCount[player->GetLevel()]++; + } + for (const auto& entry : botLevelCount) + { + LOG_INFO("server.loading", "[BotLevelBrackets] Level {}: {} bots", entry.first, entry.second); + } + } +} + // ----------------------------------------------------------------------------- // Loads the friend guid(s) from character_social into array // ----------------------------------------------------------------------------- @@ -302,63 +359,6 @@ static void AdjustBotToRange(Player* bot, int targetRangeIndex, const LevelRange ChatHandler(bot->GetSession()).SendSysMessage("[mod-bot-level-brackets] Your level has been reset."); } -// ----------------------------------------------------------------------------- -// BOT DETECTION HELPERS -// ----------------------------------------------------------------------------- -static bool IsPlayerBot(Player* player) -{ - if (!player) - { - return false; - } - PlayerbotAI* botAI = sPlayerbotsMgr->GetPlayerbotAI(player); - return botAI && botAI->IsBotAI(); -} - -static bool IsPlayerRandomBot(Player* player) -{ - if (!player) - { - return false; - } - return sRandomPlayerbotMgr->IsRandomBot(player); -} - -static bool IsAlliancePlayerBot(Player* bot) -{ - return bot && (bot->GetTeamId() == TEAM_ALLIANCE); -} - -static bool IsHordePlayerBot(Player* bot) -{ - return bot && (bot->GetTeamId() == TEAM_HORDE); -} - -static void LogAllBotLevels() -{ - if (g_BotDistFullDebugMode) - { - std::map botLevelCount; - for (auto const& itr : ObjectAccessor::GetPlayers()) - { - Player* player = itr.second; - if (!player || !player->IsInWorld()) - { - continue; - } - if (!IsPlayerBot(player)) - { - continue; - } - botLevelCount[player->GetLevel()]++; - } - for (const auto& entry : botLevelCount) - { - LOG_INFO("server.loading", "[BotLevelBrackets] Level {}: {} bots", entry.first, entry.second); - } - } -} - // ----------------------------------------------------------------------------- // HELPER FUNCTION: Check if a bot is in a guild with at least one real player online. // ----------------------------------------------------------------------------- @@ -956,6 +956,7 @@ public: LOG_INFO("server.loading", "[BotLevelBrackets] ========================================="); } + // Process Alliance bots. // Process Alliance bots. if (totalAllianceBots > 0) { @@ -970,82 +971,49 @@ public: if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Alliance Range {} ({}-{}): Desired = {}, Actual = {}.", - i + 1, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper, - allianceDesiredCounts[i], allianceActualCounts[i]); + i + 1, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper, + allianceDesiredCounts[i], allianceActualCounts[i]); } } + for (int i = 0; i < g_NumRanges; ++i) { - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] >>> Processing Alliance bots in range {}.", i + 1); - } + // Collect safe and flagged bots std::vector safeBots; std::vector flaggedBots; for (Player* bot : allianceBotsByRange[i]) { - if (IsBotSafeForLevelReset(bot)) - { + if (IsBotSafeForLevelReset(bot)) { safeBots.push_back(bot); - } - else - { + } 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()) + + // --------- Efficient surplus redistribution for safeBots ---------- + // Build a list of target ranges that need bots + std::vector targetRanges; + for (int j = 0; j < g_NumRanges; ++j) + { + if (allianceActualCounts[j] < allianceDesiredCounts[j]) + targetRanges.push_back(j); + } + size_t targetIdx = 0; + while (allianceActualCounts[i] > allianceDesiredCounts[i] && !safeBots.empty() && targetIdx < targetRanges.size()) { Player* bot = safeBots.back(); - if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) + safeBots.pop_back(); + + int targetRange = targetRanges[targetIdx]; + + // Skip if no need (already filled by earlier loop) + if (allianceActualCounts[targetRange] >= allianceDesiredCounts[targetRange]) { - safeBots.pop_back(); + targetIdx++; continue; } - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] Alliance 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 < g_NumRanges; ++j) - { - if (allianceActualCounts[j] < allianceDesiredCounts[j] && g_AllianceLevelRanges[j].upper >= 55) - { - targetRange = j; - break; - } - } - } - else - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (allianceActualCounts[j] < allianceDesiredCounts[j]) - { - targetRange = j; - break; - } - } - } - if (targetRange == -1) - { - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] No valid target range found for alliance safe bot '{}'.", bot->GetName()); - } - break; - } - 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); - } + + // Only flag if not already flagged bool alreadyFlagged = false; for (auto& entry : g_PendingLevelResets) { @@ -1061,55 +1029,30 @@ public: 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); + bot->GetName(), g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); } } allianceActualCounts[i]--; allianceActualCounts[targetRange]++; + if (allianceActualCounts[targetRange] >= allianceDesiredCounts[targetRange]) + targetIdx++; } - while (allianceActualCounts[i] > allianceDesiredCounts[i] && !flaggedBots.empty()) + // --------- Efficient surplus redistribution for flaggedBots ---------- + // Reset for flagged bots + targetIdx = 0; + while (allianceActualCounts[i] > allianceDesiredCounts[i] && !flaggedBots.empty() && targetIdx < targetRanges.size()) { Player* bot = flaggedBots.back(); - if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) + flaggedBots.pop_back(); + + int targetRange = targetRanges[targetIdx]; + + if (allianceActualCounts[targetRange] >= allianceDesiredCounts[targetRange]) { - flaggedBots.pop_back(); + targetIdx++; continue; } - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] Alliance flagged bot '{}' from range {} will be processed for pending reset.", bot->GetName(), i + 1); - } - int targetRange = -1; - if (bot->getClass() == CLASS_DEATH_KNIGHT) - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (allianceActualCounts[j] < allianceDesiredCounts[j] && g_AllianceLevelRanges[j].upper >= 55) - { - targetRange = j; - break; - } - } - } - else - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (allianceActualCounts[j] < allianceDesiredCounts[j]) - { - targetRange = j; - break; - } - } - } - if (targetRange == -1) - { - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] No valid target range found for flagged alliance bot '{}' for pending reset.", bot->GetName()); - } - break; - } + bool alreadyFlagged = false; for (auto& entry : g_PendingLevelResets) { @@ -1124,14 +1067,19 @@ public: 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 flagged bot '{}' flagged for pending level reset to range {}-{}.", + bot->GetName(), g_AllianceLevelRanges[targetRange].lower, g_AllianceLevelRanges[targetRange].upper); } } + allianceActualCounts[i]--; + allianceActualCounts[targetRange]++; + if (allianceActualCounts[targetRange] >= allianceDesiredCounts[targetRange]) + targetIdx++; } } } + // Process Horde bots. if (totalHordeBots > 0) { @@ -1146,82 +1094,45 @@ public: if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] Horde Range {} ({}-{}): Desired = {}, Actual = {}.", - i + 1, g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper, - hordeDesiredCounts[i], hordeActualCounts[i]); + i + 1, g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper, + hordeDesiredCounts[i], hordeActualCounts[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]) { - if (IsBotSafeForLevelReset(bot)) - { + if (IsBotSafeForLevelReset(bot)) { safeBots.push_back(bot); - } - else - { + } 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()) + + // Efficient surplus redistribution for safeBots + std::vector targetRanges; + for (int j = 0; j < g_NumRanges; ++j) + { + if (hordeActualCounts[j] < hordeDesiredCounts[j]) + targetRanges.push_back(j); + } + size_t targetIdx = 0; + while (hordeActualCounts[i] > hordeDesiredCounts[i] && !safeBots.empty() && targetIdx < targetRanges.size()) { Player* bot = safeBots.back(); - if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) + safeBots.pop_back(); + + int targetRange = targetRanges[targetIdx]; + + if (hordeActualCounts[targetRange] >= hordeDesiredCounts[targetRange]) { - safeBots.pop_back(); + targetIdx++; continue; } - 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 < g_NumRanges; ++j) - { - if (hordeActualCounts[j] < hordeDesiredCounts[j] && g_HordeLevelRanges[j].upper >= 55) - { - targetRange = j; - break; - } - } - } - else - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (hordeActualCounts[j] < hordeDesiredCounts[j]) - { - targetRange = j; - break; - } - } - } - if (targetRange == -1) - { - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] No valid target range found for safe horde bot '{}'.", bot->GetName()); - } - break; - } - 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); - } + bool alreadyFlagged = false; for (auto& entry : g_PendingLevelResets) { @@ -1237,55 +1148,29 @@ public: 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); + bot->GetName(), g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); } } hordeActualCounts[i]--; hordeActualCounts[targetRange]++; + if (hordeActualCounts[targetRange] >= hordeDesiredCounts[targetRange]) + targetIdx++; } - while (hordeActualCounts[i] > hordeDesiredCounts[i] && !flaggedBots.empty()) + // Efficient surplus redistribution for flaggedBots + targetIdx = 0; + while (hordeActualCounts[i] > hordeDesiredCounts[i] && !flaggedBots.empty() && targetIdx < targetRanges.size()) { Player* bot = flaggedBots.back(); - if (!bot || !bot->IsInWorld() || !bot->GetSession() || bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) + flaggedBots.pop_back(); + + int targetRange = targetRanges[targetIdx]; + + if (hordeActualCounts[targetRange] >= hordeDesiredCounts[targetRange]) { - flaggedBots.pop_back(); + targetIdx++; continue; } - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] Horde flagged bot '{}' from range {} will be processed for pending reset.", bot->GetName(), i + 1); - } - int targetRange = -1; - if (bot->getClass() == CLASS_DEATH_KNIGHT) - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (hordeActualCounts[j] < hordeDesiredCounts[j] && g_HordeLevelRanges[j].upper >= 55) - { - targetRange = j; - break; - } - } - } - else - { - for (int j = 0; j < g_NumRanges; ++j) - { - if (hordeActualCounts[j] < hordeDesiredCounts[j]) - { - targetRange = j; - break; - } - } - } - if (targetRange == -1) - { - if (g_BotDistFullDebugMode) - { - LOG_INFO("server.loading", "[BotLevelBrackets] No valid target range found for flagged horde bot '{}' for pending reset.", bot->GetName()); - } - break; - } + bool alreadyFlagged = false; for (auto& entry : g_PendingLevelResets) { @@ -1300,14 +1185,19 @@ public: 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 flagged bot '{}' flagged for pending level reset to range {}-{}.", + bot->GetName(), g_HordeLevelRanges[targetRange].lower, g_HordeLevelRanges[targetRange].upper); } } + hordeActualCounts[i]--; + hordeActualCounts[targetRange]++; + if (hordeActualCounts[targetRange] >= hordeDesiredCounts[targetRange]) + targetIdx++; } } } + if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode) { LOG_INFO("server.loading", "[BotLevelBrackets] ========================================= COMPLETE");