From be21018f0cffcdc38dba3436edf9e346b3e20fff Mon Sep 17 00:00:00 2001 From: SaW Date: Mon, 20 Jan 2025 14:21:35 +0100 Subject: [PATCH] Feature: Have bots auto join/start all supported BG's (if enabled) (#877) * Update RandomPlayerbotMgr.cpp * Update playerbots.conf.dist * Update PlayerbotAIConfig.h * Update PlayerbotAIConfig.cpp * Update playerbots.conf.dist * Update playerbots.conf.dist * Updated information * Update RandomPlayerbotMgr.cpp Avoid reverting https://github.com/liyunfan1223/mod-playerbots/pull/870/files * Update playerbots.conf.dist set capitals on Random * Final update on settings documentation * Update playerbots.conf.dist * Fix bots loving to do BG's a bit too much * Final fix bots over-queuing * pt2 - Limit over-queuing to ~1 instance Try and prevent over-queuing to a max of 1 instance. * Add new queue instead of instance if necessary * Update RandomPlayerbotMgr.cpp * Final commit * Update RandomPlayerbotMgr.cpp * Fix timer * Updated docu * Update playerbots.conf.dist * Update RandomPlayerbotMgr.cpp Set BgCheckTimer to 45 as it is sufficient. --- conf/playerbots.conf.dist | 56 +++++++++++++--- src/PlayerbotAIConfig.cpp | 16 ++++- src/PlayerbotAIConfig.h | 17 ++++- src/RandomPlayerbotMgr.cpp | 133 +++++++++++++++++++++---------------- 4 files changed, 152 insertions(+), 70 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 3f61ef188..7811986f9 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -768,18 +768,56 @@ AiPlayerbot.AutoTeleportForLevel = 1 # Enable BG/Arena for random Bots AiPlayerbot.RandomBotJoinBG = 1 -# Enable Auto join BG - bots randomly join WSG and 2v2 Arena if server is not lagging +# Enable Auto join BG - have bots start BG's and Arenas on their own AiPlayerbot.RandomBotAutoJoinBG = 0 -# Required for RandomBotAutoJoinBG -# Currently you can select 1 bracket (level range) for bots to auto join. -# Brackets for warsong 0:10-19, 1:20-29, 2:30-39, 3:40-49 etc. Default: 7 (level 80) -# Brackets for rated arena: 0:10-14, 1:15-19 etc. Default: 14 (80-84) -# For lower level ranges to work in Rated Arena, custom code changes need to be made. -# Count = amount of games Bots auto fill. (Count 1 for WSG = 20 bots). -AiPlayerbot.RandomBotAutoJoinWarsongBracket = 7 +# Required Configuration for RandomBotAutoJoinBG +# +# Known issue: When enabling a lot of brackats in combination with multiple instances, +# can lead to more instances created by bots than intended (over-queuing). +# +# This section controls the level brackets and +# automatic bot participation in battlegrounds and arenas. +# +# Brackets: +# - Specify the level ranges for bots to auto-join: +# - Warsong Gulch (WS): 0 = 10-19, 1 = 20-29, 2 = 30-39, ..., 7 = 80 (default: 7) +# - Rated Arena: 0 = 10-14, 1 = 15-19, ..., 14 = 80-84 (default: 14) +# - Multiple brackets can be specified as a comma-separated list (e.g., "0,2,5"). +# +# Counts: +# - Specify the number of Battlegrounds to auto-fill per bracket. +# - For battlegrounds, Count is the number of bots per bracket. For example: +# - Warsong Gulch Count = 1 adds 20 bots (10 per team). +# - Ensure there are enough eligible bots to meet the specified counts. +# +# Arena Considerations: +# - Rated Arena brackets default to level 80-84 (bracket 14). +# - Custom code changes are required for lower-level arena brackets to function properly. +# +# Battleground bracket range possibilities: +# AiPlayerbot.RandomBotAutoJoinICBrackets = 0,1 +# AiPlayerbot.RandomBotAutoJoinEYBrackets = 0,1,2 +# AiPlayerbot.RandomBotAutoJoinAVBrackets = 0,1,2,3 +# AiPlayerbot.RandomBotAutoJoinABBrackets = 0,1,2,3,4,5,6 +# AiPlayerbot.RandomBotAutoJoinWSBrackets = 0,1,2,3,4,5,6,7 + +AiPlayerbot.RandomBotAutoJoinICBrackets = 1 +AiPlayerbot.RandomBotAutoJoinEYBrackets = 2 +AiPlayerbot.RandomBotAutoJoinAVBrackets = 3 +AiPlayerbot.RandomBotAutoJoinABBrackets = 6 +AiPlayerbot.RandomBotAutoJoinWSBrackets = 7 + +# Battlegrounds count (per bracket!): +AiPlayerbot.RandomBotAutoJoinBGICCount = 0 +AiPlayerbot.RandomBotAutoJoinBGEYCount = 1 +AiPlayerbot.RandomBotAutoJoinBGAVCount = 0 +AiPlayerbot.RandomBotAutoJoinBGABCount = 1 +AiPlayerbot.RandomBotAutoJoinBGWSCount = 1 + +# Arena configuration: AiPlayerbot.RandomBotAutoJoinArenaBracket = 14 -AiPlayerbot.RandomBotAutoJoinBGWarsongCount = 0 + AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count = 0 AiPlayerbot.RandomBotAutoJoinBGRatedArena3v3Count = 0 AiPlayerbot.RandomBotAutoJoinBGRatedArena5v5Count = 0 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 739b400e5..ea03f95ce 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -278,9 +278,21 @@ bool PlayerbotAIConfig::Initialize() randomBotJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotJoinBG", true); randomBotAutoJoinBG = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBG", false); - randomBotAutoJoinWarsongBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWarsongBracket", 14); + randomBotAutoJoinArenaBracket = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); - randomBotAutoJoinBGWarsongCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGWarsongCount", 0); + + randomBotAutoJoinICBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinICBrackets", "0,1"); + randomBotAutoJoinEYBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinEYBrackets", "0,1,2"); + randomBotAutoJoinAVBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinAVBrackets", "0,1,2,3"); + randomBotAutoJoinABBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinABBrackets", "0,1,2,3,4,5,6"); + randomBotAutoJoinWSBrackets = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinWSBrackets", "0,1,2,3,4,5,6,7"); + + randomBotAutoJoinBGICCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGICCount", 0); + randomBotAutoJoinBGEYCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGEYCount", 0); + randomBotAutoJoinBGAVCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGAVCount", 0); + randomBotAutoJoinBGABCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGABCount", 0); + randomBotAutoJoinBGWSCount = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGWSCount", 0); + randomBotAutoJoinBGRatedArena2v2Count = sConfigMgr->GetOption("AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count", 0); randomBotAutoJoinBGRatedArena3v3Count = diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 14ee21c89..1667cdd06 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -173,12 +173,25 @@ class PlayerbotAIConfig bool randomBotJoinBG; bool randomBotAutoJoinBG; - uint32 randomBotAutoJoinWarsongBracket; + + std::string randomBotAutoJoinICBrackets; + std::string randomBotAutoJoinEYBrackets; + std::string randomBotAutoJoinAVBrackets; + std::string randomBotAutoJoinABBrackets; + std::string randomBotAutoJoinWSBrackets; + + uint32 randomBotAutoJoinBGICCount; + uint32 randomBotAutoJoinBGEYCount; + uint32 randomBotAutoJoinBGAVCount; + uint32 randomBotAutoJoinBGABCount; + uint32 randomBotAutoJoinBGWSCount; + uint32 randomBotAutoJoinArenaBracket; - uint32 randomBotAutoJoinBGWarsongCount; + uint32 randomBotAutoJoinBGRatedArena2v2Count; uint32 randomBotAutoJoinBGRatedArena3v3Count; uint32 randomBotAutoJoinBGRatedArena5v5Count; + bool randomBotLoginAtStartup; uint32 randomBotTeleLowerLevel, randomBotTeleHigherLevel; bool logInGroupOnly, logValuesPerTick; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index d8137e9ff..b5de8a65c 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -360,7 +360,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) if (sPlayerbotAIConfig->randomBotJoinBG /* && !players.empty()*/) { - if (time(nullptr) > (BgCheckTimer + 30)) + if (time(nullptr) > (BgCheckTimer + 45)) sRandomPlayerbotMgr->CheckBgQueue(); } @@ -622,20 +622,39 @@ void RandomPlayerbotMgr::LoadBattleMastersCache() LOG_INFO("playerbots", ">> Loaded {} battlemaster entries", count); } +std::vector parseBrackets(const std::string& str) +{ + std::vector brackets; + std::stringstream ss(str); + std::string item; + + while (std::getline(ss, item, ',')) + { + brackets.push_back(static_cast(std::stoi(item))); + } + + return brackets; +} + void RandomPlayerbotMgr::CheckBgQueue() { - if (!BgCheckTimer) + if (!BgCheckTimer) { BgCheckTimer = time(nullptr); + return; // Exit immediately after initializing the timer + } - if (time(nullptr) < BgCheckTimer + 30) - return; + if (time(nullptr) < BgCheckTimer) { + return; // No need to proceed if the current time is less than the timer + } + // Update the timer to the current time BgCheckTimer = time(nullptr); LOG_DEBUG("playerbots", "Checking BG Queue..."); BattlegroundData.clear(); + // Initialize Battleground Data for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket) { for (int queueType = BATTLEGROUND_QUEUE_AV; queueType < MAX_BATTLEGROUND_QUEUE_TYPES; ++queueType) @@ -644,6 +663,7 @@ void RandomPlayerbotMgr::CheckBgQueue() } } + // Process players for (Player* player : players) { if (!player->InBattlegroundQueue()) @@ -654,6 +674,7 @@ void RandomPlayerbotMgr::CheckBgQueue() continue; TeamId teamId = player->GetTeamId(); + for (uint8 queueType = 0; queueType < PLAYER_MAX_BATTLEGROUND_QUEUES; ++queueType) { BattlegroundQueueTypeId queueTypeId = player->GetBattlegroundQueueTypeId(queueType); @@ -668,7 +689,6 @@ void RandomPlayerbotMgr::CheckBgQueue() continue; BattlegroundBracketId bracketId = pvpDiff->GetBracketId(); - BattlegroundData[queueTypeId][bracketId].minLevel = pvpDiff->minLevel; BattlegroundData[queueTypeId][bracketId].maxLevel = pvpDiff->maxLevel; @@ -680,12 +700,10 @@ void RandomPlayerbotMgr::CheckBgQueue() if (bgQueue.GetPlayerGroupInfoData(player->GetGUID(), &ginfo)) { - if (ginfo.IsRated) - isRated = true; + isRated = ginfo.IsRated; } - if (bgQueue.IsPlayerInvitedToRatedArena(player->GetGUID()) || - (player->InArena() && player->GetBattleground()->isRated())) + if (bgQueue.IsPlayerInvitedToRatedArena(player->GetGUID()) || (player->InArena() && player->GetBattleground()->isRated())) isRated = true; if (isRated) @@ -728,16 +746,10 @@ void RandomPlayerbotMgr::CheckBgQueue() } } - for (PlayerBotMap::iterator i = playerBots.begin(); i != playerBots.end(); ++i) + // Process player bots + for (auto& [guid, bot] : playerBots) { - Player* bot = i->second; - if (!bot || !bot->IsInWorld()) - continue; - - if (!bot->InBattlegroundQueue()) - continue; - - if (!IsRandomBot(bot)) + if (!bot || !bot->IsInWorld() || !bot->InBattlegroundQueue() || !IsRandomBot(bot)) continue; Battleground* bg = bot->GetBattleground(); @@ -760,7 +772,6 @@ void RandomPlayerbotMgr::CheckBgQueue() continue; BattlegroundBracketId bracketId = pvpDiff->GetBracketId(); - BattlegroundData[queueTypeId][bracketId].minLevel = pvpDiff->minLevel; BattlegroundData[queueTypeId][bracketId].maxLevel = pvpDiff->maxLevel; @@ -772,12 +783,10 @@ void RandomPlayerbotMgr::CheckBgQueue() if (bgQueue.GetPlayerGroupInfoData(bot->GetGUID(), &ginfo)) { - if (ginfo.IsRated) - isRated = true; + isRated = ginfo.IsRated; } - if (bgQueue.IsPlayerInvitedToRatedArena(bot->GetGUID()) || - (bot->InArena() && bot->GetBattleground()->isRated())) + if (bgQueue.IsPlayerInvitedToRatedArena(bot->GetGUID()) || (bot->InArena() && bot->GetBattleground()->isRated())) isRated = true; if (isRated) @@ -818,11 +827,8 @@ void RandomPlayerbotMgr::CheckBgQueue() instanceIds = &BattlegroundData[queueTypeId][bracketId].bgInstances; } - if (instanceIds) - { - if (std::find(instanceIds->begin(), instanceIds->end(), instanceId) == instanceIds->end()) - instanceIds->push_back(instanceId); - } + if (instanceIds && std::find(instanceIds->begin(), instanceIds->end(), instanceId) == instanceIds->end()) + instanceIds->push_back(instanceId); if (isArena) { @@ -839,39 +845,52 @@ void RandomPlayerbotMgr::CheckBgQueue() } } - // Increase instance count if Bots are required to autojoin BG/Arenas - if (sPlayerbotAIConfig->randomBotAutoJoinBG) + // If enabled, wait for all bots to have logged in before queueing for Arena's / BG's + if (sPlayerbotAIConfig->randomBotAutoJoinBG && playerBots.size() >= GetMaxAllowedBotCount()) { - uint32 randomBotAutoJoinArenaBracket = sPlayerbotAIConfig->randomBotAutoJoinArenaBracket; - uint32 randomBotAutoJoinWarsongBracket = sPlayerbotAIConfig->randomBotAutoJoinWarsongBracket; + uint32 randomBotAutoJoinArenaBracket = sPlayerbotAIConfig->randomBotAutoJoinArenaBracket; uint32 randomBotAutoJoinBGRatedArena2v2Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena2v2Count; uint32 randomBotAutoJoinBGRatedArena3v3Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena3v3Count; uint32 randomBotAutoJoinBGRatedArena5v5Count = sPlayerbotAIConfig->randomBotAutoJoinBGRatedArena5v5Count; - uint32 randomBotAutoJoinBGWarsongCount = sPlayerbotAIConfig->randomBotAutoJoinBGWarsongCount; - - BattlegroundData[BATTLEGROUND_QUEUE_2v2][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount = - std::max(randomBotAutoJoinBGRatedArena2v2Count, - (BattlegroundData[BATTLEGROUND_QUEUE_2v2][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount - - randomBotAutoJoinBGRatedArena2v2Count) + - randomBotAutoJoinBGRatedArena2v2Count); - - BattlegroundData[BATTLEGROUND_QUEUE_3v3][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount = - std::max(randomBotAutoJoinBGRatedArena3v3Count, - (BattlegroundData[BATTLEGROUND_QUEUE_3v3][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount - - randomBotAutoJoinBGRatedArena3v3Count) + - randomBotAutoJoinBGRatedArena3v3Count); - - BattlegroundData[BATTLEGROUND_QUEUE_5v5][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount = - std::max(randomBotAutoJoinBGRatedArena5v5Count, - (BattlegroundData[BATTLEGROUND_QUEUE_5v5][randomBotAutoJoinArenaBracket].ratedArenaInstanceCount - - randomBotAutoJoinBGRatedArena5v5Count) + - randomBotAutoJoinBGRatedArena5v5Count); - - BattlegroundData[BATTLEGROUND_QUEUE_WS][randomBotAutoJoinWarsongBracket].bgInstanceCount = - std::max(randomBotAutoJoinBGWarsongCount, - (BattlegroundData[BATTLEGROUND_QUEUE_WS][randomBotAutoJoinWarsongBracket].bgInstanceCount - - randomBotAutoJoinBGWarsongCount) + - randomBotAutoJoinBGWarsongCount); + + uint32 randomBotAutoJoinBGICCount = sPlayerbotAIConfig->randomBotAutoJoinBGICCount; + uint32 randomBotAutoJoinBGEYCount = sPlayerbotAIConfig->randomBotAutoJoinBGEYCount; + uint32 randomBotAutoJoinBGAVCount = sPlayerbotAIConfig->randomBotAutoJoinBGAVCount; + uint32 randomBotAutoJoinBGABCount = sPlayerbotAIConfig->randomBotAutoJoinBGABCount; + uint32 randomBotAutoJoinBGWSCount = sPlayerbotAIConfig->randomBotAutoJoinBGWSCount; + + std::vector icBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinICBrackets); + std::vector eyBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinEYBrackets); + std::vector avBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinAVBrackets); + std::vector abBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinABBrackets); + std::vector wsBrackets = parseBrackets(sPlayerbotAIConfig->randomBotAutoJoinWSBrackets); + + auto updateRatedArenaInstanceCount = [&](uint32 queueType, uint32 bracket, uint32 minCount) { + if (BattlegroundData[queueType][bracket].activeRatedArenaQueue == 0 && + BattlegroundData[queueType][bracket].ratedArenaInstanceCount < minCount) + BattlegroundData[queueType][bracket].activeRatedArenaQueue = 1; + }; + + auto updateBGInstanceCount = [&](uint32 queueType, std::vector brackets, uint32 minCount) { + for (uint32 bracket : brackets) + { + if (BattlegroundData[queueType][bracket].activeBgQueue == 0 && + BattlegroundData[queueType][bracket].bgInstanceCount < minCount) + BattlegroundData[queueType][bracket].activeBgQueue = 1; + } + }; + + // Update rated arena instance counts + updateRatedArenaInstanceCount(BATTLEGROUND_QUEUE_2v2, randomBotAutoJoinArenaBracket, randomBotAutoJoinBGRatedArena2v2Count); + updateRatedArenaInstanceCount(BATTLEGROUND_QUEUE_3v3, randomBotAutoJoinArenaBracket, randomBotAutoJoinBGRatedArena3v3Count); + updateRatedArenaInstanceCount(BATTLEGROUND_QUEUE_5v5, randomBotAutoJoinArenaBracket, randomBotAutoJoinBGRatedArena5v5Count); + + // Update battleground instance counts + updateBGInstanceCount(BATTLEGROUND_QUEUE_IC, icBrackets, randomBotAutoJoinBGICCount); + updateBGInstanceCount(BATTLEGROUND_QUEUE_EY, eyBrackets, randomBotAutoJoinBGEYCount); + updateBGInstanceCount(BATTLEGROUND_QUEUE_AV, avBrackets, randomBotAutoJoinBGAVCount); + updateBGInstanceCount(BATTLEGROUND_QUEUE_AB, abBrackets, randomBotAutoJoinBGABCount); + updateBGInstanceCount(BATTLEGROUND_QUEUE_WS, wsBrackets, randomBotAutoJoinBGWSCount); } LogBattlegroundInfo();