Files
mod-playerbots/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp
bash 8d51092d42 As requested revert for threadfixes last few days (#1552)
* Revert "[Large server fix] #1537 Serialize playerBots/botLoading with a mutex and use snapshot-based loops to fix concurrency crashes (#1540)"

This reverts commit 3fff58df1a.

* Revert "[Fix] teleport to invalid map or invalid coordinates (x , y , z  200000, o ) given when teleporting player (g UI d full type player low , name , map , x , y , z , o )  (#1538)"

This reverts commit ca2e2ef0db.

* Revert "Fix: prevent MoveSplineInitArgs::Validate velocity asserts (velocity > 0.01f) for bots, pets, and charmed units (#1534)"

This reverts commit 4e3ac609bd.

* Revert "[Fix issue #1527] : startup crash in tank target selection — add TOCTOU & null-safety guards (#1532)"

This reverts commit c6b0424c29.

* Revert "[Fix issue #1528] Close small window where the “in a BG/arena” state can change between the check (InBattleground() / InArena()) and grabbing the pointer (GetBattleground()), which leads to a null dereference. (#1530)"

This reverts commit 2e0a161623.

* Revert "Harden playerbot logout & packet dispatch; add null-safety in chat hooks and RPG checks (#1529)"

This reverts commit e4ea8e2694.

* Revert "Dont wait to travel when in combat. (#1524)"

This reverts commit ddfa919154.

* Revert "nullptr fix (#1523)"

This reverts commit 380312ffd2.

* Revert "Playerbots/LFG: fix false not eligible & dungeon 0/type 0, add clear diagnostics (#1521)"

This reverts commit 872e417613.

* Revert "nullptr exception (#1520)"

This reverts commit 3d28a81508.

* Revert "Removed bot freezing at startup and system message, not relevant anymore (#1519)"

This reverts commit bcd6f5bc06.
2025-08-12 22:10:47 +02:00

188 lines
6.0 KiB
C++

#include "RaidVoAActions.h"
#include "RaidVoATriggers.h"
#include "Define.h"
#include "Event.h"
#include "Group.h"
#include "ObjectGuid.h"
#include "Player.h"
#include "Playerbots.h"
#include "Unit.h"
const Position VOA_EMALON_RESTORE_POSITION = Position(-221.8f, -243.8f, 96.8f, 4.7f);
bool EmalonMarkBossAction::Execute(Event event)
{
Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher");
if (!boss || !boss->IsAlive())
{
return false;
}
bool isMainTank = botAI->IsMainTank(bot);
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
{
// Iterate through the first 3 bot tanks to assign the Skull marker
for (int i = 0; i < 3; ++i)
{
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
{
Group* group = bot->GetGroup();
if (group && boss)
{
int8 skullIndex = 7; // Skull
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
// If there's no skull set yet, or the skull is on a different target, set boss
if (!currentSkullTarget || (boss->GetGUID() != currentSkullTarget))
{
group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID());
return true;
}
}
break; // Stop after finding the first valid bot tank
}
}
}
else if (isMainTank) // Bot is the main tank
{
Group* group = bot->GetGroup();
if (group)
{
int8 skullIndex = 7; // Skull
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
// If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift
if (!currentSkullTarget || (boss->GetGUID() != currentSkullTarget))
{
group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID());
return true;
}
}
}
return false;
}
bool EmalonMarkBossAction::isUseful()
{
EmalonMarkBossTrigger emalonMarkBossTrigger(botAI);
return emalonMarkBossTrigger.IsActive();
}
bool EmalonLightingNovaAction::Execute(Event event)
{
const float radius = 25.0f; // 20 yards + 5 yard for safety for 10 man. For 25man there is no maximum range but 25 yards should be ok
Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher");
if (!boss)
return false;
float currentDistance = bot->GetDistance2d(boss);
if (currentDistance < radius)
{
return MoveAway(boss, radius - currentDistance);
}
return false;
}
bool EmalonLightingNovaAction::isUseful()
{
EmalonLightingNovaTrigger emalonLightingNovaTrigger(botAI);
return emalonLightingNovaTrigger.IsActive();
}
bool EmalonOverchargeAction::Execute(Event event)
{
// Check if there is any overcharged minion
Unit* minion = nullptr;
GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
for (auto& npc : npcs)
{
Unit* unit = botAI->GetUnit(npc);
if (!unit)
continue;
uint32 entry = unit->GetEntry();
if (entry == NPC_TEMPEST_MINION && unit->HasAura(AURA_OVERCHARGE))
{
minion = unit;
break;
}
}
if (!minion)
{
return false;
}
bool isMainTank = botAI->IsMainTank(bot);
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
{
// Iterate through the first 3 bot tanks to assign the Skull marker
for (int i = 0; i < 3; ++i)
{
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
{
Group* group = bot->GetGroup();
if (group && minion)
{
int8 skullIndex = 7; // Skull
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
// If there's no skull set yet, or the skull is on a different target, set Tempest Minion
if (!currentSkullTarget || (minion->GetGUID() != currentSkullTarget))
{
group->SetTargetIcon(skullIndex, bot->GetGUID(), minion->GetGUID());
return true;
}
}
break; // Stop after finding the first valid bot tank
}
}
}
else if (isMainTank) // Bot is the main tank
{
Group* group = bot->GetGroup();
if (group)
{
int8 skullIndex = 7; // Skull
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
// If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift
if (!currentSkullTarget || (minion->GetGUID() != currentSkullTarget))
{
group->SetTargetIcon(skullIndex, bot->GetGUID(), minion->GetGUID());
return true;
}
}
}
return false;
}
bool EmalonOverchargeAction::isUseful()
{
EmalonOverchargeTrigger emalonOverchargeTrigger(botAI);
return emalonOverchargeTrigger.IsActive();
}
bool EmalonFallFromFloorAction::Execute(Event event)
{
return bot->TeleportTo(bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(),
VOA_EMALON_RESTORE_POSITION.GetPositionY(), VOA_EMALON_RESTORE_POSITION.GetPositionZ(),
VOA_EMALON_RESTORE_POSITION.GetOrientation());
}
bool EmalonFallFromFloorAction::isUseful()
{
EmalonFallFromFloorTrigger emalonFallFromFloorTrigger(botAI);
return emalonFallFromFloorTrigger.IsActive();
}