Adding support to change bracket ranges/number of brackets in the conf

This commit is contained in:
Dustin Hendrickson
2025-03-06 17:09:29 -08:00
parent 53cb413df8
commit f34341ad79
2 changed files with 360 additions and 279 deletions

View File

@@ -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
# 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

View File

@@ -17,8 +17,9 @@
#include "PlayerbotFactory.h"
#include "DatabaseEnv.h"
#include "QueryResult.h"
#include <string>
// 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<LevelRangeConfig> g_AllianceLevelRanges;
static std::vector<LevelRangeConfig> g_HordeLevelRanges;
static uint32 g_BotDistCheckFrequency = 300; // in seconds
static uint32 g_BotDistFlaggedCheckFrequency = 15; // in seconds
@@ -69,7 +70,6 @@ std::vector<int> SocialFriendsList;
static void LoadBotLevelBracketsConfig()
{
g_BotLevelBracketsEnabled = sConfigMgr->GetOption<bool>("BotLevelBrackets.Enabled", true);
// Load the new option to ignore guild bots with a real player online.
g_IgnoreGuildBotsWithRealPlayers = sConfigMgr->GetOption<bool>("BotLevelBrackets.IgnoreGuildBotsWithRealPlayers", true);
g_BotDistFullDebugMode = sConfigMgr->GetOption<bool>("BotLevelBrackets.FullDebugMode", false);
@@ -84,27 +84,28 @@ static void LoadBotLevelBracketsConfig()
g_RandomBotMinLevel = static_cast<uint8>(sConfigMgr->GetOption<uint32>("AiPlayerbot.RandomBotMinLevel", 1));
g_RandomBotMaxLevel = static_cast<uint8>(sConfigMgr->GetOption<uint32>("AiPlayerbot.RandomBotMaxLevel", 80));
// Alliance configuration.
g_AllianceLevelRanges[0] = { 1, 9, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range1Pct", 12)) };
g_AllianceLevelRanges[1] = { 10, 19, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range2Pct", 11)) };
g_AllianceLevelRanges[2] = { 20, 29, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range3Pct", 11)) };
g_AllianceLevelRanges[3] = { 30, 39, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range4Pct", 11)) };
g_AllianceLevelRanges[4] = { 40, 49, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range5Pct", 11)) };
g_AllianceLevelRanges[5] = { 50, 59, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range6Pct", 11)) };
g_AllianceLevelRanges[6] = { 60, 69, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range7Pct", 11)) };
g_AllianceLevelRanges[7] = { 70, 79, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range8Pct", 11)) };
g_AllianceLevelRanges[8] = { 80, 80, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range9Pct", 11)) };
// Load the custom number of brackets.
g_NumRanges = static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.NumRanges", 9));
g_AllianceLevelRanges.resize(g_NumRanges);
g_HordeLevelRanges.resize(g_NumRanges);
// Horde configuration.
g_HordeLevelRanges[0] = { 1, 9, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range1Pct", 12)) };
g_HordeLevelRanges[1] = { 10, 19, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range2Pct", 11)) };
g_HordeLevelRanges[2] = { 20, 29, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range3Pct", 11)) };
g_HordeLevelRanges[3] = { 30, 39, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range4Pct", 11)) };
g_HordeLevelRanges[4] = { 40, 49, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range5Pct", 11)) };
g_HordeLevelRanges[5] = { 50, 59, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range6Pct", 11)) };
g_HordeLevelRanges[6] = { 60, 69, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range7Pct", 11)) };
g_HordeLevelRanges[7] = { 70, 79, static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range8Pct", 11)) };
g_HordeLevelRanges[8] = { 80, 80, static_cast<uint8>(sConfigMgr->GetOption<uint32>("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<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range" + idx + ".Lower", (i == 0 ? 1 : i * 10)));
g_AllianceLevelRanges[i].upper = static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Alliance.Range" + idx + ".Upper", (i < g_NumRanges - 1 ? i * 10 + 9 : g_RandomBotMaxLevel)));
g_AllianceLevelRanges[i].desiredPercent = static_cast<uint8>(sConfigMgr->GetOption<uint32>("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<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range" + idx + ".Lower", (i == 0 ? 1 : i * 10)));
g_HordeLevelRanges[i].upper = static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range" + idx + ".Upper", (i < g_NumRanges - 1 ? i * 10 + 9 : g_RandomBotMaxLevel)));
g_HordeLevelRanges[i].desiredPercent = static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range" + idx + ".Pct", 11));
}
ClampAndBalanceBrackets();
}
@@ -118,11 +119,13 @@ static void LoadSocialFriendList()
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<int>::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,12 +660,13 @@ 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)
@@ -644,32 +677,36 @@ public:
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<int> allianceRealCounts(g_NumRanges, 0);
std::vector<int> 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<float> allianceWeights(g_NumRanges, 0.0f);
std::vector<float> 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<uint8>(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<uint8>(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<Player*> allianceBotsByRange[NUM_RANGES];
std::vector<int> allianceActualCounts(g_NumRanges, 0);
std::vector< std::vector<Player*> > allianceBotsByRange(g_NumRanges);
// Containers for Horde bots.
uint32 totalHordeBots = 0;
int hordeActualCounts[NUM_RANGES] = {0};
std::vector<Player*> hordeBotsByRange[NUM_RANGES];
std::vector<int> hordeActualCounts(g_NumRanges, 0);
std::vector< std::vector<Player*> > 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<int> allianceDesiredCounts(g_NumRanges, 0);
for (int i = 0; i < g_NumRanges; ++i)
{
allianceDesiredCounts[i] = static_cast<int>(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<Player*> safeBots;
std::vector<Player*> 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<int> hordeDesiredCounts(g_NumRanges, 0);
for (int i = 0; i < g_NumRanges; ++i)
{
hordeDesiredCounts[i] = static_cast<int>(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<Player*> safeBots;
std::vector<Player*> 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<int> allianceDesiredCounts(g_NumRanges, 0);
for (int i = 0; i < g_NumRanges; ++i)
{
allianceDesiredCounts[i] = static_cast<int>(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<int> hordeDesiredCounts(g_NumRanges, 0);
for (int i = 0; i < g_NumRanges; ++i)
{
hordeDesiredCounts[i] = static_cast<int>(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] =========================================");
}
}