mirror of
https://github.com/kadeshar/mod-player-bot-level-brackets.git
synced 2026-01-13 17:19:08 +00:00
Compare commits
10 Commits
ASP-0.8.1
...
disablewit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceb27c5ae4 | ||
|
|
ccbe8ae63f | ||
|
|
d7b1618cc0 | ||
|
|
894bc68f4e | ||
|
|
2cb23fe201 | ||
|
|
356901c9d4 | ||
|
|
06b36677ba | ||
|
|
f0f316e5e2 | ||
|
|
a2cc3aaad3 | ||
|
|
87b92eefe4 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -46,3 +46,5 @@ local.properties
|
||||
.loadpath
|
||||
.project
|
||||
.cproject
|
||||
.vscode/
|
||||
.vsconfig/
|
||||
|
||||
@@ -26,6 +26,8 @@ Features
|
||||
When enabled, bots that are on real players' friend lists are excluded from level bracket adjustments.
|
||||
- **Dynamic Distribution:**
|
||||
Optionally enable dynamic recalculation of bot distribution percentages based on the number of non-bot players present in each bracket.
|
||||
- **Sync Factions Bracket:**
|
||||
Requires Dynamic Distribution to be on. Optionally enable synchronized bracket and weighting logic between Alliance and Horde. When enabled, both bracket range definitions must match exactly for both factions and real player activity from either faction influences bot bracket distribution for both factions.
|
||||
- **Debug Modes:**
|
||||
Full and Lite debug modes provide detailed logging for troubleshooting and monitoring bot adjustments.
|
||||
|
||||
@@ -76,8 +78,9 @@ BotLevelBrackets.FullDebugMode | Enables full debug logging for th
|
||||
BotLevelBrackets.LiteDebugMode | Enables lite debug logging for the Bot Level Brackets module. | 0 | 0 (off) / 1 (on)
|
||||
BotLevelBrackets.CheckFrequency | Frequency (in seconds) at which the bot level distribution check is performed. | 300 | Positive Integer
|
||||
BotLevelBrackets.CheckFlaggedFrequency | Frequency (in seconds) at which the bot level reset is performed for flagged bots that initially failed safety checks. | 15 | Positive Integer
|
||||
BotLevelBrackets.UseDynamicDistribution | Enables dynamic recalculation of bot distribution percentages based on non-bot player counts per bracket. | 0 | 0 (off) / 1 (on)
|
||||
BotLevelBrackets.RealPlayerWeight | Multiplier applied to each real player's contribution (active only if dynamic distribution is enabled). | 1.0 | Floating point number
|
||||
BotLevelBrackets.Dynamic.UseDynamicDistribution | Enables dynamic recalculation of bot distribution percentages based on non-bot player counts per bracket. | 0 | 0 (off) / 1 (on)
|
||||
BotLevelBrackets.Dynamic.RealPlayerWeight | Multiplier applied to each real player's contribution (active only if dynamic distribution is enabled). | 1.0 | Floating point number
|
||||
BotLevelBrackets.Dynamic.SyncFactions | Enables synchronized brackets and weighting between Alliance and Horde factions when Dynamic Distribution is also enabled. | 0 | 0 (off) / 1 (on)
|
||||
BotLevelBrackets.IgnoreFriendListed | Ignores bots that are on real players' friend lists from any bracket calculations. | 1 | 0 (off) / 1 (on)
|
||||
BotLevelBrackets.IgnoreGuildBotsWithRealPlayers | Excludes bots in a guild with at least one real (non-bot) player online from adjustments. | 1 | 0 (disabled) / 1 (enabled)
|
||||
BotLevelBrackets.NumRanges | Number of level brackets used for bot distribution. Both factions must have the same number defined. | 9 | Positive Integer
|
||||
|
||||
@@ -32,10 +32,16 @@ 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
|
||||
# Description: The frequency (in seconds) at which the bot level reset is performed for processing safe bots and checking flagged bots that failed safety checks initially.
|
||||
# Default: 15
|
||||
BotLevelBrackets.CheckFlaggedFrequency = 15
|
||||
|
||||
# BotLevelBrackets.FlaggedProcessLimit
|
||||
# Description: Maximum number of flagged bots to process per flagged check step.
|
||||
# 0 = unlimited (process all flagged bots each step)
|
||||
# Default: 5
|
||||
BotLevelBrackets.FlaggedProcessLimit = 5
|
||||
|
||||
#
|
||||
# BotLevelBrackets.IgnoreGuildBotsWithRealPlayers
|
||||
# Description: When enabled, bots that are in a guild with at least one real (non-bot) player online are excluded
|
||||
@@ -44,22 +50,6 @@ BotLevelBrackets.CheckFlaggedFrequency = 15
|
||||
# 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.
|
||||
# Default: 0 (disabled)
|
||||
# Valid values: 0 (off) / 1 (on)
|
||||
BotLevelBrackets.UseDynamicDistribution = 0
|
||||
|
||||
#
|
||||
# BotLevelBrackets.RealPlayerWeight
|
||||
# Description: A multiplier applied to each real player's contribution in their level bracket.
|
||||
# When combined with inverse scaling by total player count, a higher value significantly boosts the effective weight
|
||||
# of a real player when few are online.
|
||||
# Default: 1.0
|
||||
BotLevelBrackets.RealPlayerWeight = 1.0
|
||||
|
||||
#
|
||||
# BotLevelBrackets.IgnoreFriendListed
|
||||
# Description: Ignore bots that are on real players friend's lists from any brackets.
|
||||
@@ -79,6 +69,32 @@ BotLevelBrackets.IgnoreFriendListed = 1
|
||||
# sum of the Pct values for each faction remains 100.
|
||||
BotLevelBrackets.NumRanges = 9
|
||||
|
||||
#
|
||||
# BotLevelBrackets.Dynamic.UseDynamicDistribution
|
||||
# Description: Enables dynamic recalculation of bot distribution percentages based on the number of non-bot players
|
||||
# present in each level bracket.
|
||||
# Default: 0 (disabled)
|
||||
# Valid values: 0 (off) / 1 (on)
|
||||
BotLevelBrackets.Dynamic.UseDynamicDistribution = 0
|
||||
|
||||
#
|
||||
# BotLevelBrackets.Dynamic.RealPlayerWeight
|
||||
# Description: A multiplier applied to each real player's contribution in their level bracket.
|
||||
# When combined with inverse scaling by total player count, a higher value significantly boosts the effective weight
|
||||
# of a real player when few are online.
|
||||
# Default: 1.0
|
||||
BotLevelBrackets.Dynamic.RealPlayerWeight = 1.0
|
||||
|
||||
#
|
||||
# BotLevelBrackets.Dynamic.SyncFactions
|
||||
# Description: If enabled, both Alliance and Horde must have identical bracket definitions (same number, same level bounds).
|
||||
# All real players (regardless of faction) influence the dynamic distribution for both factions.
|
||||
# Default: 0 (disabled)
|
||||
# Valid values: 0 (off) / 1 (on)
|
||||
# WARNING: Server will fail to start if brackets do not match when enabled.
|
||||
#
|
||||
BotLevelBrackets.Dynamic.SyncFactions = 0
|
||||
|
||||
##############################################
|
||||
# Alliance Level Brackets Configuration
|
||||
##############################################
|
||||
|
||||
@@ -42,9 +42,9 @@ static uint8 g_NumRanges = 9;
|
||||
static uint8 g_RandomBotMinLevel = 1;
|
||||
static uint8 g_RandomBotMaxLevel = 80;
|
||||
|
||||
// New configuration option to enable/disable the mod. Default is true.
|
||||
// Enable/disable the mod. Default is true.
|
||||
static bool g_BotLevelBracketsEnabled = true;
|
||||
// New configuration option to ignore bots in guilds with a real player online. Default is true.
|
||||
// Ignore bots in guilds with a real player online. Default is true.
|
||||
static bool g_IgnoreGuildBotsWithRealPlayers = true;
|
||||
|
||||
// Use vectors to store the level ranges.
|
||||
@@ -57,10 +57,17 @@ static bool g_BotDistFullDebugMode = false;
|
||||
static bool g_BotDistLiteDebugMode = false;
|
||||
static bool g_UseDynamicDistribution = false;
|
||||
static bool g_IgnoreFriendListed = true;
|
||||
static uint32 g_FlaggedProcessLimit = 5; // 0 = unlimited
|
||||
|
||||
|
||||
// Real player weight to boost bracket contributions.
|
||||
static float g_RealPlayerWeight = 1.0f;
|
||||
|
||||
// If true, synchronize bracket logic and real player influence across both factions.
|
||||
// This option requires both Alliance and Horde bracket definitions to match perfectly.
|
||||
// When enabled, all real players (regardless of faction) affect the dynamic distribution for both factions.
|
||||
static bool g_SyncFactions = false;
|
||||
|
||||
// Array for character social list friends
|
||||
std::vector<int> SocialFriendsList;
|
||||
|
||||
@@ -76,9 +83,11 @@ static void LoadBotLevelBracketsConfig()
|
||||
g_BotDistLiteDebugMode = sConfigMgr->GetOption<bool>("BotLevelBrackets.LiteDebugMode", false);
|
||||
g_BotDistCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFrequency", 300);
|
||||
g_BotDistFlaggedCheckFrequency = sConfigMgr->GetOption<uint32>("BotLevelBrackets.CheckFlaggedFrequency", 15);
|
||||
g_UseDynamicDistribution = sConfigMgr->GetOption<bool>("BotLevelBrackets.UseDynamicDistribution", false);
|
||||
g_RealPlayerWeight = sConfigMgr->GetOption<float>("BotLevelBrackets.RealPlayerWeight", 1.0f);
|
||||
g_UseDynamicDistribution = sConfigMgr->GetOption<bool>("BotLevelBrackets.Dynamic.UseDynamicDistribution", false);
|
||||
g_RealPlayerWeight = sConfigMgr->GetOption<float>("BotLevelBrackets.Dynamic.RealPlayerWeight", 1.0f);
|
||||
g_SyncFactions = sConfigMgr->GetOption<bool>("BotLevelBrackets.Dynamic.SyncFactions", false);
|
||||
g_IgnoreFriendListed = sConfigMgr->GetOption<bool>("BotLevelBrackets.IgnoreFriendListed", true);
|
||||
g_FlaggedProcessLimit = sConfigMgr->GetOption<uint32>("BotLevelBrackets.FlaggedProcessLimit", 5);
|
||||
|
||||
// Load the bot level restrictions.
|
||||
g_RandomBotMinLevel = static_cast<uint8>(sConfigMgr->GetOption<uint32>("AiPlayerbot.RandomBotMinLevel", 1));
|
||||
@@ -107,6 +116,23 @@ static void LoadBotLevelBracketsConfig()
|
||||
g_HordeLevelRanges[i].desiredPercent = static_cast<uint8>(sConfigMgr->GetOption<uint32>("BotLevelBrackets.Horde.Range" + idx + ".Pct", 11));
|
||||
}
|
||||
|
||||
// If SyncFactions is enabled, ensure bracket definitions match exactly for both factions.
|
||||
// Any mismatch results in immediate server shutdown with an error message.
|
||||
if (g_SyncFactions) {
|
||||
for (uint8 i = 0; i < g_NumRanges; ++i) {
|
||||
if (g_AllianceLevelRanges[i].lower != g_HordeLevelRanges[i].lower ||
|
||||
g_AllianceLevelRanges[i].upper != g_HordeLevelRanges[i].upper) {
|
||||
LOG_ERROR("server.loading", "[BotLevelBrackets] FATAL: Bracket mismatch detected between factions at index {}. "
|
||||
"Alliance: {}-{}, Horde: {}-{}. "
|
||||
"When SyncFactions is enabled, both bracket number and min/max levels must match exactly. "
|
||||
"Check your configuration.",
|
||||
i, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper,
|
||||
g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper);
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClampAndBalanceBrackets();
|
||||
}
|
||||
|
||||
@@ -337,10 +363,6 @@ static bool BotInFriendList(Player* bot)
|
||||
|
||||
for (size_t i = 0; i < SocialFriendsList.size(); ++i)
|
||||
{
|
||||
if (g_BotDistFullDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Check bot {} against SocialFriendsList Array Character GUID {}", bot->GetName(), SocialFriendsList[i]);
|
||||
}
|
||||
if (SocialFriendsList[i] == bot->GetGUID().GetRawValue())
|
||||
{
|
||||
if (g_BotDistFullDebugMode)
|
||||
@@ -445,6 +467,14 @@ static bool IsBotSafeForLevelReset(Player* bot)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (bot->GetSession()->isLogingOut())
|
||||
{
|
||||
if (g_BotDistFullDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Bot {} (Level {}) is logging out.", bot->GetName(), bot->GetLevel());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!bot->IsInWorld())
|
||||
{
|
||||
if (g_BotDistFullDebugMode)
|
||||
@@ -515,6 +545,11 @@ static std::vector<PendingResetEntry> g_PendingLevelResets;
|
||||
|
||||
static void ProcessPendingLevelResets()
|
||||
{
|
||||
if (!sRandomPlayerbotMgr->GetDisabledWithoutRealPlayerLogoutInProgress())
|
||||
{
|
||||
g_PendingLevelResets.clear();
|
||||
return;
|
||||
}
|
||||
if (g_BotDistFullDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Processing {} pending resets...", g_PendingLevelResets.size());
|
||||
@@ -524,34 +559,40 @@ static void ProcessPendingLevelResets()
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit the number of resets processed in one cycle if configured.
|
||||
uint32 processed = 0;
|
||||
for (auto it = g_PendingLevelResets.begin(); it != g_PendingLevelResets.end(); )
|
||||
{
|
||||
Player* bot = it->bot;
|
||||
int targetRange = it->targetRange;
|
||||
if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(bot))
|
||||
{
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (g_IgnoreFriendListed && BotInFriendList(bot))
|
||||
{
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (bot && bot->IsInWorld() && IsBotSafeForLevelReset(bot))
|
||||
{
|
||||
AdjustBotToRange(bot, targetRange, it->factionRanges);
|
||||
if (g_BotDistFullDebugMode)
|
||||
if (g_FlaggedProcessLimit > 0 && processed >= g_FlaggedProcessLimit)
|
||||
break;
|
||||
|
||||
Player* bot = it->bot;
|
||||
int targetRange = it->targetRange;
|
||||
if (g_IgnoreGuildBotsWithRealPlayers && BotInGuildWithRealPlayer(bot))
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Bot '{}' successfully reset to level range {}-{}.", bot->GetName(), it->factionRanges[targetRange].lower, it->factionRanges[targetRange].upper);
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (g_IgnoreFriendListed && BotInFriendList(bot))
|
||||
{
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (bot && bot->IsInWorld() && IsBotSafeForLevelReset(bot))
|
||||
{
|
||||
AdjustBotToRange(bot, targetRange, it->factionRanges);
|
||||
if (g_BotDistFullDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Bot '{}' successfully reset to level range {}-{}.", bot->GetName(), it->factionRanges[targetRange].lower, it->factionRanges[targetRange].upper);
|
||||
}
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
++processed;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
it = g_PendingLevelResets.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns a valid bracket index for the given player's level.
|
||||
@@ -687,26 +728,22 @@ public:
|
||||
|
||||
if (g_UseDynamicDistribution)
|
||||
{
|
||||
// Calculate real player bracket counts
|
||||
std::vector<int> allianceRealCounts(g_NumRanges, 0);
|
||||
std::vector<int> hordeRealCounts(g_NumRanges, 0);
|
||||
uint32 totalAllianceReal = 0;
|
||||
uint32 totalHordeReal = 0;
|
||||
|
||||
for (auto const& itr : ObjectAccessor::GetPlayers())
|
||||
{
|
||||
Player* player = itr.second;
|
||||
if (!player || !player->IsInWorld())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (IsPlayerBot(player))
|
||||
{
|
||||
continue; // Skip bots.
|
||||
}
|
||||
continue; // Only count real players.
|
||||
int rangeIndex = GetOrFlagPlayerBracket(player);
|
||||
if (rangeIndex < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (player->GetTeamId() == TEAM_ALLIANCE)
|
||||
{
|
||||
allianceRealCounts[rangeIndex]++;
|
||||
@@ -718,127 +755,89 @@ public:
|
||||
totalHordeReal++;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
|
||||
// SYNCED MODE: Real player weighting is combined for both factions, applied to both bracket tables.
|
||||
if (g_SyncFactions)
|
||||
{
|
||||
if (g_AllianceLevelRanges[i].lower > g_AllianceLevelRanges[i].upper)
|
||||
uint32 totalCombinedReal = totalAllianceReal + totalHordeReal;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
{
|
||||
allianceWeights[i] = 0.0f;
|
||||
int combinedReal = allianceRealCounts[i] + hordeRealCounts[i];
|
||||
float weight = baseline + g_RealPlayerWeight *
|
||||
(totalCombinedReal > 0 ? (1.0f / float(totalCombinedReal)) : 1.0f) *
|
||||
log(1 + combinedReal);
|
||||
allianceWeights[i] = weight;
|
||||
hordeWeights[i] = weight;
|
||||
}
|
||||
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];
|
||||
}
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
else
|
||||
{
|
||||
g_AllianceLevelRanges[i].desiredPercent = static_cast<uint8>(round((allianceWeights[i] / allianceTotalWeight) * 100));
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
// Separate dynamic weighting for each faction
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Dynamic Distribution - Alliance Range {}: {}-{}, Real Players: {} (weight: {:.2f}), New Desired: {}%",
|
||||
i + 1, g_AllianceLevelRanges[i].lower, g_AllianceLevelRanges[i].upper, allianceRealCounts[i], allianceWeights[i], g_AllianceLevelRanges[i].desiredPercent);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 sumAlliance = 0;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
// Helper for normalizing weights so percentages sum to 100
|
||||
auto applyWeights = [](std::vector<LevelRangeConfig>& ranges, const std::vector<float>& weights)
|
||||
{
|
||||
sumAlliance += g_AllianceLevelRanges[i].desiredPercent;
|
||||
}
|
||||
if (sumAlliance < 100 && allianceTotalWeight > 0)
|
||||
{
|
||||
uint8 missing = 100 - sumAlliance;
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
float total = 0.0f;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
total += weights[i];
|
||||
int pctSum = 0;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Alliance normalization: current sum = {}, missing = {}", sumAlliance, missing);
|
||||
uint8 pct = (total > 0.0f) ? static_cast<uint8>(round((weights[i] / total) * 100)) : 0;
|
||||
ranges[i].desiredPercent = pct;
|
||||
pctSum += pct;
|
||||
}
|
||||
while (missing > 0)
|
||||
// Fix rounding drift so sum = 100
|
||||
int missing = 100 - pctSum;
|
||||
for (int i = 0; i < g_NumRanges && missing > 0; ++i)
|
||||
{
|
||||
for (int i = 0; i < g_NumRanges && missing > 0; ++i)
|
||||
if (ranges[i].lower <= ranges[i].upper && ranges[i].desiredPercent > 0)
|
||||
{
|
||||
if (g_AllianceLevelRanges[i].lower <= g_AllianceLevelRanges[i].upper && allianceWeights[i] > 0)
|
||||
{
|
||||
g_AllianceLevelRanges[i].desiredPercent++;
|
||||
missing--;
|
||||
}
|
||||
ranges[i].desiredPercent++;
|
||||
missing--;
|
||||
}
|
||||
}
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Alliance normalized percentages:");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Dynamic Distribution - Horde Range {}: {}-{}, Real Players: {} (weight: {:.2f}), New Desired: {}%",
|
||||
i + 1, g_HordeLevelRanges[i].lower, g_HordeLevelRanges[i].upper, hordeRealCounts[i], hordeWeights[i], g_HordeLevelRanges[i].desiredPercent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uint8 sumHorde = 0;
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
applyWeights(g_AllianceLevelRanges, allianceWeights);
|
||||
applyWeights(g_HordeLevelRanges, hordeWeights);
|
||||
|
||||
// Debug output for new bracket percentages after normalization
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
{
|
||||
sumHorde += g_HordeLevelRanges[i].desiredPercent;
|
||||
}
|
||||
if (sumHorde < 100 && hordeTotalWeight > 0)
|
||||
{
|
||||
uint8 missing = 100 - sumHorde;
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
for (int i = 0; i < g_NumRanges; ++i)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Horde normalization: current sum = {}, missing = {}", sumHorde, missing);
|
||||
}
|
||||
while (missing > 0)
|
||||
{
|
||||
for (int i = 0; i < g_NumRanges && missing > 0; ++i)
|
||||
{
|
||||
if (g_HordeLevelRanges[i].lower <= g_HordeLevelRanges[i].upper && hordeWeights[i] > 0)
|
||||
{
|
||||
g_HordeLevelRanges[i].desiredPercent++;
|
||||
missing--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_BotDistFullDebugMode || g_BotDistLiteDebugMode)
|
||||
{
|
||||
LOG_INFO("server.loading", "[BotLevelBrackets] Horde normalized percentages:");
|
||||
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", "[BotLevelBrackets] Final Range {}: {}-{}, Alliance Desired: {}%, Horde Desired: {}%",
|
||||
i + 1,
|
||||
g_AllianceLevelRanges[i].lower,
|
||||
g_AllianceLevelRanges[i].upper,
|
||||
g_AllianceLevelRanges[i].desiredPercent,
|
||||
g_HordeLevelRanges[i].desiredPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32 totalAllianceBots = 0;
|
||||
std::vector<int> allianceActualCounts(g_NumRanges, 0);
|
||||
std::vector< std::vector<Player*> > allianceBotsByRange(g_NumRanges);
|
||||
@@ -1022,7 +1021,24 @@ public:
|
||||
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.data());
|
||||
bool alreadyFlagged = false;
|
||||
for (auto& entry : g_PendingLevelResets)
|
||||
{
|
||||
if (entry.bot == bot)
|
||||
{
|
||||
alreadyFlagged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyFlagged)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
allianceActualCounts[i]--;
|
||||
allianceActualCounts[targetRange]++;
|
||||
}
|
||||
@@ -1173,7 +1189,24 @@ public:
|
||||
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.data());
|
||||
bool alreadyFlagged = false;
|
||||
for (auto& entry : g_PendingLevelResets)
|
||||
{
|
||||
if (entry.bot == bot)
|
||||
{
|
||||
alreadyFlagged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyFlagged)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
hordeActualCounts[i]--;
|
||||
hordeActualCounts[targetRange]++;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
#define MOD_BOT_LEVEL_BRACKETS_H
|
||||
|
||||
// Registers the Bot Level Brackets module scripts.
|
||||
void Addmod_bot_level_bracketsScripts();
|
||||
void Addmod_player_bot_level_bracketsScripts();
|
||||
|
||||
#endif // MOD_BOT_LEVEL_BRACKETS_H
|
||||
|
||||
Reference in New Issue
Block a user