diff --git a/src/Bot/PlayerbotAI.cpp b/src/Bot/PlayerbotAI.cpp index 7edc48aff..25c93676f 100644 --- a/src/Bot/PlayerbotAI.cpp +++ b/src/Bot/PlayerbotAI.cpp @@ -243,22 +243,10 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) nextAICheckDelay = 0; // Early return if bot is in invalid state - if (!bot || !bot->GetSession() || !bot->IsInWorld() || bot->IsBeingTeleported() || bot->IsDuringRemoveFromWorld()) + if (!bot || !bot->GetSession() || !bot->IsInWorld() || bot->IsBeingTeleported() || + bot->GetSession()->isLogingOut() || bot->IsDuringRemoveFromWorld()) return; - // During timed logout countdown, cancel if bot enters combat (this cancellation is handled client-side for real players). - if (bot->GetSession()->isLogingOut()) - { - bool canLogoutInCombat = bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - if (bot->IsInCombat() && !canLogoutInCombat) - { - WorldPackets::Character::LogoutCancel cancelData = WorldPacket(CMSG_LOGOUT_CANCEL); - bot->GetSession()->HandleLogoutCancelOpcode(cancelData); - } - else - return; - } - // Handle cheat options (set bot health and power if cheats are enabled) if (bot->IsAlive() && (static_cast(GetCheat()) > 0 || static_cast(sPlayerbotAIConfig.botCheatMask) > 0)) @@ -727,9 +715,30 @@ void PlayerbotAI::HandleCommand(uint32 type, const std::string& text, Player& fr Reset(true); } - // Commented-out logout commands blocks removed from here and implemented in HandleCommand. - // Remaining is a commented-out action delay command block. - /* + // TODO: missing implementation to port + /*else if (filtered == "logout") + { + if (!(bot->IsStunnedByLogout() || bot->GetSession()->isLogingOut())) + { + if (type == CHAT_MSG_WHISPER) + TellPlayer(&fromPlayer, BOT_TEXT("logout_start")); + + if (master && master->GetPlayerbotMgr()) + SetShouldLogOut(true); + } + } + else if (filtered == "logout cancel") + { + if (bot->IsStunnedByLogout() || bot->GetSession()->isLogingOut()) + { + if (type == CHAT_MSG_WHISPER) + TellPlayer(&fromPlayer, BOT_TEXT("logout_cancel")); + + WorldPacket p; + bot->GetSession()->HandleLogoutCancelOpcode(p); + SetShouldLogOut(false); + } + } else if ((filtered.size() > 5) && (filtered.substr(0, 5) == "wait ") && (filtered.find("wait for attack") == std::string::npos)) { @@ -1075,7 +1084,7 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro TellMaster(message); } } - else if (filtered == "cancel logout" || filtered == "logout cancel") + else if (filtered == "logout cancel") { if (!bot->GetSession()->isLogingOut()) return; @@ -1091,7 +1100,9 @@ void PlayerbotAI::HandleCommand(uint32 type, std::string const text, Player* fro bot->GetSession()->HandleLogoutCancelOpcode(data); } else + { chatCommands.push_back(ChatCommandHolder(filtered, fromPlayer, type)); + } } void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) diff --git a/src/Bot/PlayerbotMgr.cpp b/src/Bot/PlayerbotMgr.cpp index fd205fe23..8327e2f36 100644 --- a/src/Bot/PlayerbotMgr.cpp +++ b/src/Bot/PlayerbotMgr.cpp @@ -299,11 +299,6 @@ void PlayerbotHolder::LogoutAllBots() if (!botAI || botAI->IsRealPlayer()) continue; - // If bot is mid-countdown, cancel the timer so LogoutPlayerBot proceeds immediately. - WorldSession* session = bot->GetSession(); - if (session && session->isLogingOut()) - session->SetLogoutStartTime(0); - LogoutPlayerBot(bot->GetGUID()); } } @@ -366,50 +361,36 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid) WorldSession* botWorldSessionPtr = bot->GetSession(); WorldSession* masterWorldSessionPtr = nullptr; - // If already in timed logout countdown, complete it once the 20-second timer expires. if (botWorldSessionPtr->isLogingOut()) - { - if (botWorldSessionPtr->ShouldLogOut(time(nullptr))) - { - std::string message = PlayerbotTextMgr::instance().GetBotTextOrDefault( - "goodbye", "Goodbye!", {}); - botAI->TellMaster(message); - RemoveFromPlayerbotsMap(guid); - botWorldSessionPtr->LogoutPlayer(true); - delete botWorldSessionPtr; - } return; - } Player* master = botAI->GetMaster(); if (master) masterWorldSessionPtr = master->GetSession(); - // Instant logout checking: - bool logout = - bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || - bot->HasUnitState(UNIT_STATE_IN_FLIGHT) || - (masterWorldSessionPtr && !masterWorldSessionPtr->GetPlayer()) || - // Master's socket is already gone (EXIT GAME -> EXIT NOW is the most typical cause). - // Force instant logout. Without this, the bot restarts its 20-second countdown and fires LogoutPlayer() 20 seconds - // after the master's Player object has been deleted, causing the bot's logout to crash on the now deleted master. - (masterWorldSessionPtr && masterWorldSessionPtr->IsSocketClosed()) || - (masterWorldSessionPtr && masterWorldSessionPtr->ShouldLogOut(time(nullptr))) || - // If the bot's master has security clearance for `InstantLogout` in worldserver.conf, so does the bot. - (master && - (master->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || - master->HasUnitState(UNIT_STATE_IN_FLIGHT) || - (masterWorldSessionPtr && - masterWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)))); + // TODO: Review whether or not to implement timed logout. + // Unused block. Useful only for timed logout. +/* + // check for instant logout + bool logout = botWorldSessionPtr->ShouldLogOut(time(nullptr)); - if (!logout) - { - // Start the 20-second logout countdown. CancelLogout() can interrupt this. - WorldPackets::Character::LogoutRequest data = WorldPacket(CMSG_LOGOUT_REQUEST); - botWorldSessionPtr->HandleLogoutRequestOpcode(data); - return; - } + if (masterWorldSessionPtr && masterWorldSessionPtr->ShouldLogOut(time(nullptr))) + logout = true; + if (masterWorldSessionPtr && !masterWorldSessionPtr->GetPlayer()) + logout = true; + + if (bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || bot->HasUnitState(UNIT_STATE_IN_FLIGHT) || + botWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)) + logout = true; + + if (master && + (master->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || master->HasUnitState(UNIT_STATE_IN_FLIGHT) || + (masterWorldSessionPtr && + masterWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)))) + logout = true; +*/ + // Instant logout (the only option right now) { std::string message = PlayerbotTextMgr::instance().GetBotTextOrDefault( "goodbye", "Goodbye!", {}); @@ -1497,15 +1478,6 @@ void PlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/) { SetNextCheckDelay(sPlayerbotAIConfig.reactDelay); CheckTellErrors(elapsed); - - // Complete timed logouts for added bots once the 20-second countdown has elapsed. - std::vector expiredLogouts; - for (auto const& [botGuid, bot] : playerBots) - if (bot && bot->GetSession() && bot->GetSession()->ShouldLogOut(time(nullptr))) - expiredLogouts.push_back(botGuid); - - for (ObjectGuid const& guid : expiredLogouts) - LogoutPlayerBot(guid); } void PlayerbotMgr::HandleCommand(uint32 type, std::string const text)