mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #1714 from avirar/fix/remove-auras-before-teleport
[fix crash] several crashes
This commit is contained in:
@@ -601,6 +601,7 @@ public:
|
||||
NewRpgInfo rpgInfo;
|
||||
NewRpgStatistic rpgStatistic;
|
||||
std::unordered_set<uint32> lowPriorityQuest;
|
||||
time_t bgReleaseAttemptTime = 0;
|
||||
|
||||
// Schedules a callback to run once after <delayMs> milliseconds.
|
||||
void AddTimedEvent(std::function<void()> callback, uint32 delayMs);
|
||||
|
||||
@@ -87,7 +87,8 @@ public:
|
||||
PLAYERHOOK_ON_BEFORE_CRITERIA_PROGRESS,
|
||||
PLAYERHOOK_ON_BEFORE_ACHI_COMPLETE,
|
||||
PLAYERHOOK_CAN_PLAYER_USE_PRIVATE_CHAT,
|
||||
PLAYERHOOK_ON_GIVE_EXP
|
||||
PLAYERHOOK_ON_GIVE_EXP,
|
||||
PLAYERHOOK_ON_BEFORE_TELEPORT
|
||||
}) {}
|
||||
|
||||
void OnPlayerLogin(Player* player) override
|
||||
@@ -121,6 +122,26 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool OnPlayerBeforeTeleport(Player* player, uint32 mapid, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override
|
||||
{
|
||||
// Only apply to bots to prevent affecting real players
|
||||
if (!player || !player->GetSession()->IsBot())
|
||||
return true;
|
||||
|
||||
// If changing maps, proactively clean visibility references to prevent
|
||||
// stale pointers in other players' visibility maps during the teleport.
|
||||
// This fixes a race condition where:
|
||||
// 1. Bot A teleports and its visible objects start getting cleaned up
|
||||
// 2. Bot B is simultaneously updating visibility and tries to access objects in Bot A's old visibility map
|
||||
// 3. Those objects may already be freed, causing a segmentation fault
|
||||
if (player->GetMapId() != mapid && player->IsInWorld())
|
||||
{
|
||||
player->GetObjectVisibilityContainer().CleanVisibilityReferences();
|
||||
}
|
||||
|
||||
return true; // Allow teleport to continue
|
||||
}
|
||||
|
||||
void OnPlayerAfterUpdate(Player* player, uint32 diff) override
|
||||
{
|
||||
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
|
||||
|
||||
@@ -1771,6 +1771,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
||||
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();
|
||||
|
||||
@@ -3090,6 +3091,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());
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
@@ -191,12 +192,11 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const
|
||||
{
|
||||
// The below delays release to spirit with 6 seconds.
|
||||
// This prevents currently casted (ranged) spells to be re-directed to the died bot's ghost.
|
||||
const int32_t botId = bot->GetGUID().GetRawValue();
|
||||
|
||||
// If the bot already is a spirit, erase release time and return true
|
||||
// If the bot already is a spirit, reset release time and return true
|
||||
if (bot->HasPlayerFlag(PLAYER_FLAGS_GHOST))
|
||||
{
|
||||
m_botReleaseTimes.erase(botId);
|
||||
botAI->bgReleaseAttemptTime = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -204,14 +204,13 @@ bool AutoReleaseSpiritAction::ShouldDelayBattlegroundRelease() const
|
||||
const time_t now = time(nullptr);
|
||||
constexpr time_t RELEASE_DELAY = 6;
|
||||
|
||||
auto& lastReleaseTime = m_botReleaseTimes[botId];
|
||||
if (lastReleaseTime == 0)
|
||||
lastReleaseTime = now;
|
||||
if (botAI->bgReleaseAttemptTime == 0)
|
||||
botAI->bgReleaseAttemptTime = now;
|
||||
|
||||
if (now - lastReleaseTime < RELEASE_DELAY)
|
||||
if (now - botAI->bgReleaseAttemptTime < RELEASE_DELAY)
|
||||
return false;
|
||||
|
||||
m_botReleaseTimes.erase(botId);
|
||||
botAI->bgReleaseAttemptTime = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -244,6 +243,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");
|
||||
|
||||
@@ -38,7 +38,6 @@ private:
|
||||
bool ShouldAutoRelease() const;
|
||||
bool ShouldDelayBattlegroundRelease() const;
|
||||
|
||||
inline static std::unordered_map<uint32_t, time_t> m_botReleaseTimes;
|
||||
time_t m_bgGossipTime = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -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<uint32>("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);
|
||||
// }
|
||||
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user