fix(warmpool): Handle already-online bots in WarmUpBot - queue directly for BG

Root cause: When warm pool bots were already logged in, BotSpawner::SpawnBot()
would return failure (bot already in _botSessions). WarmUpBot treated this as
a failure and moved bots to Maintenance, so they never queued for BG.

The fix: At the start of WarmUpBot, check if bot is already online via
ObjectAccessor::FindPlayer(). If so:
- Mark as instance bot
- Queue directly for BG using BGBotManager::QueueBotForBG()
- Set slot state to Assigned
- Call OnBotWarmupComplete(true)
- Return early (skip spawning)

This ensures warm pool bots that are already online get properly queued
for battlegrounds instead of being moved to Maintenance.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
This commit is contained in:
agatho
2026-02-04 20:19:02 -03:00
committed by luis
co-authored by Claude Opus 4.5
parent 6c812394cb
commit 61d7aec8f5
@@ -17,9 +17,12 @@
#include "Account/BotAccountMgr.h"
#include "Config/PlayerbotConfig.h"
#include "Session/BotWorldSessionMgr.h"
#include "PvP/BGBotManager.h"
#include "BattlegroundMgr.h"
#include "CharacterCache.h"
#include "DatabaseEnv.h"
#include "Database/PlayerbotDatabase.h"
#include "DB2Stores.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "Player.h"
@@ -1617,6 +1620,74 @@ bool InstanceBotPool::WarmUpBot(ObjectGuid botGuid)
instanceType = it->second.currentInstanceType;
}
// ========================================================================
// CRITICAL FIX (2026-02-03): Handle already-online bots
// ========================================================================
// If the bot is already logged in, we should NOT try to spawn it again.
// Instead, queue it directly for the content (BG/Dungeon/Arena).
// Previously, spawn would "fail" and bot would be moved to Maintenance,
// causing warm pool bots to never actually join BG queues.
// ========================================================================
if (Player* existingPlayer = ObjectAccessor::FindPlayer(botGuid))
{
TC_LOG_INFO("playerbot.pool", "InstanceBotPool::WarmUpBot - Bot {} already online, queueing directly for content {}",
botGuid.ToString(), contentId);
// Mark as instance bot if not already
sBotWorldSessionMgr->MarkAsInstanceBot(botGuid);
// Queue for content based on instance type
bool queueSuccess = false;
if (contentId > 0)
{
switch (instanceType)
{
case InstanceType::Battleground:
{
BattlegroundTypeId bgTypeId = static_cast<BattlegroundTypeId>(contentId);
BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(bgTypeId);
if (bgTemplate && !bgTemplate->MapIDs.empty())
{
PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(
bgTemplate->MapIDs.front(), existingPlayer->GetLevel());
if (bracketEntry)
{
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
queueSuccess = sBGBotManager->QueueBotForBG(existingPlayer, bgTypeId, bracketId);
TC_LOG_INFO("playerbot.pool", "InstanceBotPool::WarmUpBot - Queued already-online bot {} for BG {} bracket {}: {}",
botGuid.ToString(), contentId, static_cast<uint8>(bracketId), queueSuccess ? "SUCCESS" : "FAILED");
}
}
break;
}
case InstanceType::Dungeon:
// TODO: Implement direct dungeon queueing for already-online bots
TC_LOG_WARN("playerbot.pool", "InstanceBotPool::WarmUpBot - Direct dungeon queueing not yet implemented for bot {}",
botGuid.ToString());
break;
case InstanceType::Arena:
// TODO: Implement direct arena queueing for already-online bots
TC_LOG_WARN("playerbot.pool", "InstanceBotPool::WarmUpBot - Direct arena queueing not yet implemented for bot {}",
botGuid.ToString());
break;
default:
break;
}
}
// Update slot state to Assigned (queued for content)
{
std::unique_lock lock(_slotsMutex);
auto it = _slots.find(botGuid);
if (it != _slots.end())
it->second.ForceState(PoolSlotState::Assigned);
}
// Call warmup complete with success (bot is already usable)
OnBotWarmupComplete(botGuid, true);
return true;
}
// Fallback: Try to get account ID from CharacterCache if not in slot
if (accountId == 0)
{