diff --git a/src/modules/Playerbot/Lifecycle/Instance/BotCloneEngine.cpp b/src/modules/Playerbot/Lifecycle/Instance/BotCloneEngine.cpp index 6922004a6..39e3a5280 100644 --- a/src/modules/Playerbot/Lifecycle/Instance/BotCloneEngine.cpp +++ b/src/modules/Playerbot/Lifecycle/Instance/BotCloneEngine.cpp @@ -620,6 +620,10 @@ CloneResult BotCloneEngine::ExecuteClone( pendingConfig.battlegroundIdToQueue = battlegroundIdToQueue; pendingConfig.arenaTypeToQueue = arenaTypeToQueue; + // Mark as instance bot - this will be applied after login by BotPostLoginConfigurator + // CRITICAL: This ensures JIT bots get proper idle timeout and restricted behavior + pendingConfig.markAsInstanceBot = true; + sBotPostLoginConfigurator->RegisterPendingConfig(std::move(pendingConfig)); TC_LOG_DEBUG("playerbot.clone", diff --git a/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.cpp b/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.cpp index 76f3cabd5..9ce60f09e 100644 --- a/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.cpp +++ b/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.cpp @@ -12,6 +12,7 @@ #include "Equipment/BotGearFactory.h" #include "LFG/LFGBotManager.h" #include "PvP/BGBotManager.h" +#include "Session/BotWorldSessionMgr.h" #include "BattlegroundMgr.h" #include "Player.h" #include "Item.h" @@ -434,6 +435,19 @@ bool BotPostLoginConfigurator::ApplyPendingConfiguration(Player* player) player->GetName(), durationMs); } + // Step 9: Mark as instance bot if flagged + // CRITICAL FIX (2026-02-03): Instance bot marking must happen AFTER login completes + // Previously, MarkAsInstanceBot() was called immediately after AddPlayerBot() in JITBotFactory, + // but AddPlayerBot() only queues the spawn - the session doesn't exist yet! + // Now we mark the bot here, where the session is guaranteed to exist. + if (config.markAsInstanceBot) + { + sBotWorldSessionMgr->MarkAsInstanceBot(playerGuid); + TC_LOG_INFO("module.playerbot.configurator", + "Marked bot {} as INSTANCE BOT (idle timeout enabled, restricted behavior)", + player->GetName()); + } + // CRITICAL: Add to recently configured set BEFORE removing pending config // This prevents the race condition where: // 1. We remove pending config diff --git a/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.h b/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.h index 17bdba6ec..7c5107547 100644 --- a/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.h +++ b/src/modules/Playerbot/Lifecycle/Instance/BotPostLoginConfigurator.h @@ -47,6 +47,9 @@ struct BotPendingConfiguration uint32 battlegroundIdToQueue = 0; // If > 0, queue bot for this BG after configuration uint32 arenaTypeToQueue = 0; // If > 0, queue bot for this arena type after configuration + // Instance Bot Flag - marks bot for idle timeout and restricted behavior + bool markAsInstanceBot = false; // If true, mark as instance bot after login + // Timing std::chrono::steady_clock::time_point createdAt; diff --git a/src/modules/Playerbot/Lifecycle/Instance/InstanceBotPool.cpp b/src/modules/Playerbot/Lifecycle/Instance/InstanceBotPool.cpp index bb3bbc39d..849e9b4d1 100644 --- a/src/modules/Playerbot/Lifecycle/Instance/InstanceBotPool.cpp +++ b/src/modules/Playerbot/Lifecycle/Instance/InstanceBotPool.cpp @@ -1687,6 +1687,10 @@ bool InstanceBotPool::WarmUpBot(ObjectGuid botGuid) } } + // Mark as instance bot - this will be applied after login by BotPostLoginConfigurator + // CRITICAL: This ensures warm pool bots get proper idle timeout and restricted behavior + pendingConfig.markAsInstanceBot = true; + sBotPostLoginConfigurator->RegisterPendingConfig(std::move(pendingConfig)); TC_LOG_INFO("playerbot.pool", "InstanceBotPool::WarmUpBot - Registered pending config for bot {} (level={}, spec={}, gearScore={}, contentId={}, type={})", diff --git a/src/modules/Playerbot/Lifecycle/Instance/JITBotFactory.cpp b/src/modules/Playerbot/Lifecycle/Instance/JITBotFactory.cpp index 540d83cb1..5fc99503e 100644 --- a/src/modules/Playerbot/Lifecycle/Instance/JITBotFactory.cpp +++ b/src/modules/Playerbot/Lifecycle/Instance/JITBotFactory.cpp @@ -1022,21 +1022,18 @@ RequestProgress JITBotFactory::ProcessRequest(FactoryRequest& request) ++loginSuccessCount; // ==================================================================== - // CRITICAL FIX (2026-01-22): Mark JIT bots as INSTANCE BOTS! + // NOTE: Instance bot marking is now handled via BotPostLoginConfigurator! // ==================================================================== - // Without this, JIT bots would: - // - NOT get the 60-second idle logout timeout - // - Stay online forever causing bot explosion (1500+ bots) - // - Do quests and other activities (pool flag not set) - // - Cause massive server lag (50s+ response times) + // Previously, we called MarkAsInstanceBot() here, but AddPlayerBot() + // only queues the spawn to _pendingSpawns - the session doesn't exist yet! + // This caused "session not found" errors and bots not being properly tracked. // - // By marking as instance bot, they get: - // - Auto-logout after 60 seconds if not in queue/group/instance - // - Restricted behavior (no questing, just queue and fight) + // The fix: Set markAsInstanceBot=true in BotPendingConfiguration (done in + // BotCloneEngine.cpp), and BotPostLoginConfigurator::ApplyPendingConfiguration() + // will call MarkAsInstanceBot() AFTER the session is created. // ==================================================================== - sBotWorldSessionMgr->MarkAsInstanceBot(botGuid); - TC_LOG_DEBUG("playerbot.jit", "JITBotFactory::ProcessRequest - Logged in bot {} (account {}), marked as INSTANCE BOT", + TC_LOG_DEBUG("playerbot.jit", "JITBotFactory::ProcessRequest - Logged in bot {} (account {}), will be marked as INSTANCE BOT after login completes", botGuid.ToString(), accountId); BOT_TRACK_SUCCESS(BotOperationCategory::SPAWN, "JITBotFactory::LoginBot", botGuid); } @@ -1052,7 +1049,7 @@ RequestProgress JITBotFactory::ProcessRequest(FactoryRequest& request) } } - TC_LOG_INFO("playerbot.jit", "JITBotFactory::ProcessRequest - Logged in {}/{} bots (all marked as INSTANCE BOTS)", + TC_LOG_INFO("playerbot.jit", "JITBotFactory::ProcessRequest - Logged in {}/{} bots (will be marked as INSTANCE BOTS after post-login config)", loginSuccessCount, progress.created); // Determine status - STRICT requirements to ensure full groups