From 387c4912653c88d81ac19c909344de01c59da66e Mon Sep 17 00:00:00 2001 From: root Date: Fri, 3 Oct 2025 15:58:36 +1000 Subject: [PATCH] fix(Playerbots): Remove auras before teleporting to prevent crash Add RemoveAurasWithInterruptFlags call before all TeleportTo operations to prevent race condition crash in battlegrounds. The crash occurs when area auras (like "Entering Battleground") are queued for removal in Aura::UpdateTargetMap's targetsToRemove list, but the unit is deleted before the 500ms update cycle completes, causing SIGSEGV when accessing the dangling pointer. This fix removes auras with AURA_INTERRUPT_FLAG_TELEPORTED and AURA_INTERRUPT_FLAG_CHANGE_MAP before teleporting, matching the behavior in Player::TeleportTo for real players. Affected locations: - BattleGround join/teleport - Spirit healer/graveyard teleport - Corpse resurrection teleport - Meeting stone teleport - Master follow teleport - RPG unstuck teleport - Random bot teleport - Chat command teleport Raid-specific teleports excluded as they require separate testing. --- src/RandomPlayerbotMgr.cpp | 2 ++ src/strategy/actions/BattleGroundJoinAction.cpp | 1 + src/strategy/actions/BattleGroundTactics.cpp | 6 ++++++ src/strategy/actions/ChatShortcutActions.cpp | 1 + src/strategy/actions/MovementActions.cpp | 2 ++ src/strategy/actions/ReleaseSpiritAction.cpp | 2 ++ src/strategy/actions/ReviveFromCorpseAction.cpp | 2 ++ src/strategy/actions/UseMeetingStoneAction.cpp | 1 + src/strategy/rpg/NewRpgBaseAction.cpp | 1 + 9 files changed, 18 insertions(+) diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 557450d0..61b1df49 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1853,6 +1853,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); if (botAI) botAI->Reset(true); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(loc.GetMapId(), x, y, z, 0); bot->SendMovementFlagUpdate(); @@ -3245,6 +3246,7 @@ void RandomPlayerbotMgr::OnPlayerLogin(Player* player) } while (true); } + player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); player->TeleportTo(botPos); // player->Relocate(botPos.getX(), botPos.getY(), botPos.getZ(), botPos.getO()); diff --git a/src/strategy/actions/BattleGroundJoinAction.cpp b/src/strategy/actions/BattleGroundJoinAction.cpp index f4581624..542c7566 100644 --- a/src/strategy/actions/BattleGroundJoinAction.cpp +++ b/src/strategy/actions/BattleGroundJoinAction.cpp @@ -176,6 +176,7 @@ bool BGJoinAction::gatherArenaTeam(ArenaType type) continue; memberBotAI->Reset(); + member->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); member->TeleportTo(bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 0); LOG_INFO("playerbots", "Bot {} <{}>: Member of <{}>", member->GetGUID().ToString().c_str(), diff --git a/src/strategy/actions/BattleGroundTactics.cpp b/src/strategy/actions/BattleGroundTactics.cpp index 74bc236a..5e9e7daf 100644 --- a/src/strategy/actions/BattleGroundTactics.cpp +++ b/src/strategy/actions/BattleGroundTactics.cpp @@ -4289,9 +4289,15 @@ bool ArenaTactics::moveToCenter(Battleground* bg) { // they like to hang around at the tip of the pipes doing nothing, so we just teleport them down if (bot->GetDistance(1333.07f, 817.18f, 13.35f) < 4) + { + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(bg->GetMapId(), 1330.96f, 816.75f, 3.2f, bot->GetOrientation()); + } if (bot->GetDistance(1250.13f, 764.79f, 13.34f) < 4) + { + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(bg->GetMapId(), 1252.19f, 765.41f, 3.2f, bot->GetOrientation()); + } } break; case BATTLEGROUND_RV: diff --git a/src/strategy/actions/ChatShortcutActions.cpp b/src/strategy/actions/ChatShortcutActions.cpp index 0e99c5fe..40d66697 100644 --- a/src/strategy/actions/ChatShortcutActions.cpp +++ b/src/strategy/actions/ChatShortcutActions.cpp @@ -106,6 +106,7 @@ bool FollowChatShortcutAction::Execute(Event event) else botAI->TellMaster("You are too far away from me! I will there soon."); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(master->GetMapId(), master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), master->GetOrientation()); return true; } diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 371d11c2..6758b916 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1148,6 +1148,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) if ((target->GetMap() && target->GetMap()->IsBattlegroundOrArena()) || (bot->GetMap() && bot->GetMap()->IsBattlegroundOrArena())) return false; + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(target->GetMapId(), x, y, z, bot->GetOrientation()); } else @@ -1175,6 +1176,7 @@ bool MovementAction::Follow(Unit* target, float distance, float angle) bot->CombatStop(true); botAI->TellMasterNoFacing("I will there soon."); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(target->GetMapId(), target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation()); return false; } diff --git a/src/strategy/actions/ReleaseSpiritAction.cpp b/src/strategy/actions/ReleaseSpiritAction.cpp index 92b7ac55..0d725f74 100644 --- a/src/strategy/actions/ReleaseSpiritAction.cpp +++ b/src/strategy/actions/ReleaseSpiritAction.cpp @@ -147,6 +147,7 @@ bool AutoReleaseSpiritAction::HandleBattlegroundSpiritHealer() // and in IOC it's not within clicking range when they res in own base // Teleport to nearest friendly Spirit Healer when not currently in range of one. + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(bot->GetMapId(), spiritHealer->GetPositionX(), spiritHealer->GetPositionY(), spiritHealer->GetPositionZ(), 0.f); RESET_AI_VALUE(bool, "combat::self target"); RESET_AI_VALUE(WorldPosition, "current position"); @@ -244,6 +245,7 @@ int64 RepopAction::CalculateDeadTime() const void RepopAction::PerformGraveyardTeleport(const GraveyardStruct* graveyard) const { + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(graveyard->Map, graveyard->x, graveyard->y, graveyard->z, 0.f); RESET_AI_VALUE(bool, "combat::self target"); RESET_AI_VALUE(WorldPosition, "current position"); diff --git a/src/strategy/actions/ReviveFromCorpseAction.cpp b/src/strategy/actions/ReviveFromCorpseAction.cpp index f2810747..83897dc2 100644 --- a/src/strategy/actions/ReviveFromCorpseAction.cpp +++ b/src/strategy/actions/ReviveFromCorpseAction.cpp @@ -169,6 +169,7 @@ bool FindCorpseAction::Execute(Event event) if (deadTime > delay) { bot->GetMotionMaster()->Clear(); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); bot->TeleportTo(moveToPos.getMapId(), moveToPos.getX(), moveToPos.getY(), moveToPos.getZ(), 0); } @@ -350,6 +351,7 @@ bool SpiritHealerAction::Execute(Event event) // if (!botAI->HasActivePlayerMaster()) // { context->GetValue("death count")->Set(dCount + 1); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); return bot->TeleportTo(ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f); // } diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index 68eecce6..24d58aff 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -225,6 +225,7 @@ bool SummonAction::Teleport(Player* summoner, Player* player) player->GetMotionMaster()->Clear(); AI_VALUE(LastMovement&, "last movement").clear(); + player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); player->TeleportTo(mapId, x, y, z, 0); if (botAI->HasStrategy("stay", botAI->GetState())) diff --git a/src/strategy/rpg/NewRpgBaseAction.cpp b/src/strategy/rpg/NewRpgBaseAction.cpp index 9af540dc..acd34078 100644 --- a/src/strategy/rpg/NewRpgBaseAction.cpp +++ b/src/strategy/rpg/NewRpgBaseAction.cpp @@ -67,6 +67,7 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest) bot->GetName(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), bot->GetMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.getMapId(), bot->GetZoneId(), zone_name); + bot->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TELEPORTED | AURA_INTERRUPT_FLAG_CHANGE_MAP); return bot->TeleportTo(dest); }