Yogg-Saron strategy (#1565)

* - wip

* - Added Yogg-Saron strategy

* - Added Yogg-Saron sanity strategy

* - WIP

* - WIP

* - WIP

* - WIP

* - Added Yogg-Saron strategy

* - code refactoring

* - Code fix after pr
This commit is contained in:
kadeshar
2025-08-18 12:02:19 +02:00
committed by GitHub
parent b369b1f9ae
commit 77c2354c3f
17 changed files with 2320 additions and 48 deletions

View File

@@ -12,11 +12,33 @@
#include "Trigger.h"
#include "Vehicle.h"
#include <MovementActions.h>
#include <FollowMasterStrategy.h>
#include <RtiTargetValue.h>
const std::vector<uint32> availableVehicles = {NPC_VEHICLE_CHOPPER, NPC_SALVAGED_DEMOLISHER,
NPC_SALVAGED_DEMOLISHER_TURRET, NPC_SALVAGED_SIEGE_ENGINE,
NPC_SALVAGED_SIEGE_ENGINE_TURRET};
const std::vector<uint32> illusionMobs =
{
NPC_INFLUENCE_TENTACLE,
NPC_RUBY_CONSORT,
NPC_AZURE_CONSORT,
NPC_BRONZE_CONSORT,
NPC_EMERALD_CONSORT,
NPC_OBSIDIAN_CONSORT,
NPC_ALEXTRASZA,
NPC_MALYGOS_ILLUSION,
NPC_NELTHARION,
NPC_YSERA,
NPC_DEATHSWORN_ZEALOT,
NPC_LICH_KING_ILLUSION,
NPC_IMMOLATED_CHAMPION,
NPC_SUIT_OF_ARMOR,
NPC_GARONA,
NPC_KING_LLANE
};
bool FlameLeviathanOnVehicleTrigger::IsActive()
{
Unit* vehicleBase = bot->GetVehicleBase();
@@ -448,8 +470,8 @@ bool KologarnAttackDpsTargetTrigger::IsActive()
if (!group)
return false;
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
ObjectGuid crossTarget = group->GetTargetIcon(crossIndex);
ObjectGuid skullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
ObjectGuid crossTarget = group->GetTargetIcon(RtiTargetValue::crossIndex);
if (crossTarget && (botAI->IsMainTank(bot) || botAI->IsAssistTankOfIndex(bot, 0)))
{
@@ -745,7 +767,7 @@ bool ThorimUnbalancingStrikeTrigger::IsActive()
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
// Check boss and it is alive
if (!boss || !boss->IsAlive())
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
return false;
return bot->HasAura(SPELL_UNBALANCING_STRIKE);
@@ -762,7 +784,7 @@ bool ThorimMarkDpsTargetTrigger::IsActive()
if (botAI->IsMainTank(bot))
{
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
ObjectGuid currentSkullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
Unit* currentSkullUnit = botAI->GetUnit(currentSkullTarget);
if (currentSkullUnit && !currentSkullUnit->IsAlive())
{
@@ -783,13 +805,13 @@ bool ThorimMarkDpsTargetTrigger::IsActive()
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
// Check boss and it is alive
if (!boss || !boss->IsAlive())
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD && (!currentSkullUnit || !currentSkullUnit->IsAlive()))
{
group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID());
group->SetTargetIcon(RtiTargetValue::skullIndex, bot->GetGUID(), boss->GetGUID());
return true;
}
@@ -811,7 +833,7 @@ bool ThorimMarkDpsTargetTrigger::IsActive()
if (mainTank && bot->GetDistance(mainTank) < 30.0f)
return false;
ObjectGuid currentCrossTarget = group->GetTargetIcon(crossIndex);
ObjectGuid currentCrossTarget = group->GetTargetIcon(RtiTargetValue::crossIndex);
Unit* currentCrossUnit = botAI->GetUnit(currentCrossTarget);
if (currentCrossUnit && !currentCrossUnit->IsAlive())
{
@@ -963,7 +985,7 @@ bool ThorimArenaPositioningTrigger::IsActive()
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
// Check boss and it is alive
if (!boss || !boss->IsAlive())
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD)
@@ -1061,7 +1083,7 @@ bool ThorimPhase2PositioningTrigger::IsActive()
Unit* boss = AI_VALUE2(Unit*, "find target", "thorim");
// Check boss and it is alive
if (!boss || !boss->IsAlive())
if (!boss || !boss->IsAlive() || !boss->IsHostileTo(bot))
return false;
if (boss->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD)
@@ -1408,8 +1430,8 @@ bool MimironAerialCommandUnitTrigger::IsActive()
return false;
}
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
ObjectGuid crossTarget = group->GetTargetIcon(crossIndex);
ObjectGuid skullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
ObjectGuid crossTarget = group->GetTargetIcon(RtiTargetValue::crossIndex);
//if (bombBot && bombBot->GetGUID() != crossTarget)
//{
@@ -1515,7 +1537,7 @@ bool MimironPhase4MarkDpsTrigger::IsActive()
highestHealthUnit = aerialCommandUnit;
}
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
ObjectGuid skullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
if (!skullTarget)
{
return true;
@@ -1619,3 +1641,748 @@ bool VezaxMarkOfTheFacelessTrigger::IsActive()
return distance > 2.0f;
}
Unit* YoggSaronTrigger::GetSaraIfAlive()
{
Unit* sara = AI_VALUE2(Unit*, "find target", "sara");
if (!sara || !sara->IsAlive())
{
return nullptr;
}
return sara;
}
bool YoggSaronTrigger::IsPhase2()
{
Creature* target = bot->FindNearestCreature(NPC_YOGG_SARON, 200.0f, true);
return target && target->IsAlive() && target->HasAura(SPELL_SHADOW_BARRIER);
}
bool YoggSaronTrigger::IsPhase3()
{
Creature* target = bot->FindNearestCreature(NPC_YOGG_SARON, 200.0f, true);
Creature* guardian = bot->FindNearestCreature(NPC_GUARDIAN_OF_YS, 200.0f, true);
return target && target->IsAlive() && !target->HasAura(SPELL_SHADOW_BARRIER) && !guardian;
}
bool YoggSaronTrigger::IsInBrainLevel()
{
return bot->GetPositionZ() > 230.0f && bot->GetPositionZ() < 250.0f;
}
bool YoggSaronTrigger::IsYoggSaronFight()
{
Unit* sara = AI_VALUE2(Unit*, "find target", "sara");
Unit* yoggsaron = AI_VALUE2(Unit*, "find target", "yogg-saron");
if ((sara && sara->IsAlive()) || (yoggsaron && yoggsaron->IsAlive()))
{
return true;
}
}
bool YoggSaronTrigger::IsInIllusionRoom()
{
if (!IsInBrainLevel())
{
return false;
}
if (IsInStormwindKeeperIllusion())
{
return true;
}
if (IsInIcecrownKeeperIllusion())
{
return true;
}
if (IsInChamberOfTheAspectsIllusion())
{
return true;
}
return false;
}
bool YoggSaronTrigger::IsInStormwindKeeperIllusion()
{
return bot->GetDistance2d(ULDUAR_YOGG_SARON_STORMWIND_KEEPER_MIDDLE.GetPositionX(),
ULDUAR_YOGG_SARON_STORMWIND_KEEPER_MIDDLE.GetPositionY()) <
ULDUAR_YOGG_SARON_STORMWIND_KEEPER_RADIUS;
}
bool YoggSaronTrigger::IsInIcecrownKeeperIllusion()
{
return bot->GetDistance2d(ULDUAR_YOGG_SARON_ICECROWN_CITADEL_MIDDLE.GetPositionX(),
ULDUAR_YOGG_SARON_ICECROWN_CITADEL_MIDDLE.GetPositionY()) <
ULDUAR_YOGG_SARON_ICECROWN_CITADEL_RADIUS;
}
bool YoggSaronTrigger::IsInChamberOfTheAspectsIllusion()
{
return bot->GetDistance2d(ULDUAR_YOGG_SARON_CHAMBER_OF_ASPECTS_MIDDLE.GetPositionX(),
ULDUAR_YOGG_SARON_CHAMBER_OF_ASPECTS_MIDDLE.GetPositionY()) <
ULDUAR_YOGG_SARON_CHAMBER_OF_ASPECTS_RADIUS;
}
bool YoggSaronTrigger::IsMasterIsInIllusionGroup()
{
Player* master = botAI->GetMaster();
return master && !botAI->IsTank(master);
}
bool YoggSaronTrigger::IsMasterIsInBrainRoom()
{
Player* master = botAI->GetMaster();
if (!master)
{
return false;
}
return master->GetDistance2d(ULDUAR_YOGG_SARON_BRAIN_ROOM_MIDDLE.GetPositionX(),
ULDUAR_YOGG_SARON_BRAIN_ROOM_MIDDLE.GetPositionY()) <
ULDUAR_YOGG_SARON_BRAIN_ROOM_RADIUS &&
master->GetPositionZ() > 230.0f && master->GetPositionZ() < 250.0f;
}
Position YoggSaronTrigger::GetIllusionRoomEntrancePosition()
{
if (IsInChamberOfTheAspectsIllusion())
{
return ULDUAR_YOGG_SARON_CHAMBER_OF_ASPECTS_ENTRANCE;
}
else if (IsInIcecrownKeeperIllusion())
{
return ULDUAR_YOGG_SARON_ICECROWN_CITADEL_ENTRANCE;
}
else if (IsInStormwindKeeperIllusion())
{
return ULDUAR_YOGG_SARON_STORMWIND_KEEPER_ENTRANCE;
}
else
{
return Position();
}
}
Unit* YoggSaronTrigger::GetIllusionRoomRtiTarget()
{
Group* group = bot->GetGroup();
if (!group)
{
return nullptr;
}
uint8 rtiIndex = RtiTargetValue::GetRtiIndex(AI_VALUE(std::string, "rti"));
if (rtiIndex == -1)
{
return nullptr; // Invalid RTI mark
}
ObjectGuid currentRtiTarget = group->GetTargetIcon(rtiIndex);
Unit* currentRtiTargetUnit = botAI->GetUnit(currentRtiTarget);
if (!currentRtiTargetUnit || !currentRtiTargetUnit->IsAlive())
{
currentRtiTargetUnit = nullptr;
}
return currentRtiTargetUnit;
}
Unit* YoggSaronTrigger::GetNextIllusionRoomRtiTarget()
{
float detectionRadius = 0.0f;
if (IsInStormwindKeeperIllusion())
{
detectionRadius = ULDUAR_YOGG_SARON_STORMWIND_KEEPER_RADIUS;
}
else if (IsInIcecrownKeeperIllusion())
{
detectionRadius = ULDUAR_YOGG_SARON_ICECROWN_CITADEL_RADIUS;
}
else if (IsInChamberOfTheAspectsIllusion())
{
detectionRadius = ULDUAR_YOGG_SARON_CHAMBER_OF_ASPECTS_RADIUS;
}
else
{
return nullptr;
}
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
if (botAI->HasCheat(BotCheatMask::raid))
{
for (const ObjectGuid& guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (unit && unit->IsAlive() && unit->GetEntry() == NPC_LAUGHING_SKULL)
{
return unit;
}
}
}
float nearestDistance = std::numeric_limits<float>::max();
Unit* nextIllusionRoomRtiTarget = nullptr;
for (const uint32& creatureId : illusionMobs)
{
for (const ObjectGuid& guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (unit && unit->IsAlive() && unit->GetEntry() == creatureId)
{
float distance = bot->GetDistance(unit);
if (distance < nearestDistance)
{
nextIllusionRoomRtiTarget = unit;
nearestDistance = distance;
}
}
}
}
if (nextIllusionRoomRtiTarget)
{
return nextIllusionRoomRtiTarget;
}
if (IsInStormwindKeeperIllusion())
{
Creature* target = bot->FindNearestCreature(NPC_SUIT_OF_ARMOR, detectionRadius, true);
if (target)
{
return target;
}
}
return nullptr;
}
bool YoggSaronOminousCloudCheatTrigger::IsActive()
{
if (!botAI->HasCheat(BotCheatMask::raid))
{
return false;
}
Unit* boss = GetSaraIfAlive();
if (!boss)
{
return false;
}
if (!botAI->IsBotMainTank(bot))
{
return false;
}
if (bot->GetDistance2d(boss->GetPositionX(), boss->GetPositionY()) > 50.0f)
{
return false;
}
Creature* target = boss->FindNearestCreature(NPC_OMINOUS_CLOUD, 25.0f, true);
return target;
}
bool YoggSaronGuardianPositioningTrigger::IsActive()
{
if (!GetSaraIfAlive())
{
return false;
}
if (!botAI->IsTank(bot))
{
return false;
}
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
bool thereIsAnyGuardian = false;
for (const ObjectGuid& guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsAlive())
{
continue;
}
if (unit->GetEntry() == NPC_GUARDIAN_OF_YS)
{
thereIsAnyGuardian = true;
ObjectGuid unitTargetGuid = unit->GetTarget();
Player* targetedPlayer = botAI->GetPlayer(unitTargetGuid);
if (!targetedPlayer || !botAI->IsTank(targetedPlayer))
{
return false;
}
}
}
return thereIsAnyGuardian &&
bot->GetDistance2d(ULDUAR_YOGG_SARON_MIDDLE.GetPositionX(), ULDUAR_YOGG_SARON_MIDDLE.GetPositionY()) > 1.0f;
}
bool YoggSaronSanityTrigger::IsActive()
{
Aura* sanityAura = bot->GetAura(SPELL_SANITY);
if (!sanityAura)
{
return false;
}
int sanityAuraStacks = sanityAura->GetStackAmount();
Creature* sanityWell = bot->FindNearestCreature(NPC_SANITY_WELL, 200.0f);
if (!sanityWell)
{
return false;
}
float distanceToSanityWell = bot->GetDistance(sanityWell);
return (distanceToSanityWell >= 1.0f && sanityAuraStacks < 40) ||
(distanceToSanityWell < 1.0f && sanityAuraStacks < 100);
}
bool YoggSaronDeathOrbTrigger::IsActive()
{
TooCloseToCreatureTrigger tooCloseToDeathOrbTrigger(botAI);
return IsPhase2() && tooCloseToDeathOrbTrigger.TooCloseToCreature(NPC_DEATH_ORB, 10.0f);
}
bool YoggSaronMaladyOfTheMindTrigger::IsActive()
{
TooCloseToPlayerWithDebuffTrigger tooCloseToPlayerWithDebuffTrigger(botAI);
return IsPhase2() && tooCloseToPlayerWithDebuffTrigger.TooCloseToPlayerWithDebuff(SPELL_MALADY_OF_THE_MIND, 15.0f) && botAI->CanMove();
}
bool YoggSaronMarkTargetTrigger::IsActive()
{
if (!IsYoggSaronFight())
{
return false;
}
if (!botAI->IsBotMainTank(bot))
{
return false;
}
Group* group = bot->GetGroup();
if (!group)
{
return false;
}
if (IsPhase2())
{
ObjectGuid currentMoonTarget = group->GetTargetIcon(RtiTargetValue::moonIndex);
Creature* yogg_saron = bot->FindNearestCreature(NPC_YOGG_SARON, 200.0f, true);
if (!currentMoonTarget || currentMoonTarget != yogg_saron->GetGUID())
{
return true;
}
ObjectGuid currentSkullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
Creature* nextPossibleTarget = bot->FindNearestCreature(NPC_CONSTRICTOR_TENTACLE, 200.0f, true);
if (!nextPossibleTarget)
{
nextPossibleTarget = bot->FindNearestCreature(NPC_CORRUPTOR_TENTACLE, 200.0f, true);
if (!nextPossibleTarget)
{
return false;
}
}
if (currentSkullTarget)
{
Unit* currentSkullUnit = botAI->GetUnit(currentSkullTarget);
if (!currentSkullUnit)
{
return true;
}
if (currentSkullUnit->IsAlive() && currentSkullUnit->GetGUID() == nextPossibleTarget->GetGUID())
{
return false;
}
}
return true;
}
else if (IsPhase3())
{
ObjectGuid currentSkullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
Unit* currentSkullUnit = nullptr;
if (currentSkullTarget)
{
currentSkullUnit = botAI->GetUnit(currentSkullTarget);
}
if (currentSkullUnit &&
(currentSkullUnit->GetEntry() == NPC_IMMORTAL_GUARDIAN ||
currentSkullUnit->GetEntry() == NPC_MARKED_IMMORTAL_GUARDIAN) &&
currentSkullUnit->GetHealthPct() > 10)
{
return false;
}
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
for (const ObjectGuid& guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsAlive())
{
continue;
}
if ((unit->GetEntry() == NPC_IMMORTAL_GUARDIAN || unit->GetEntry() == NPC_MARKED_IMMORTAL_GUARDIAN) &&
unit->GetHealthPct() > 10)
{
return true;
}
}
if (!currentSkullUnit || currentSkullUnit->GetEntry() != NPC_YOGG_SARON)
{
return true;
}
return false;
}
return false;
}
bool YoggSaronBrainLinkTrigger::IsActive()
{
TooFarFromPlayerWithAuraTrigger tooFarFromPlayerWithAuraTrigger(botAI);
return IsPhase2() && bot->HasAura(SPELL_BRAIN_LINK) &&
tooFarFromPlayerWithAuraTrigger.TooFarFromPlayerWithAura(SPELL_BRAIN_LINK, 20.0f, false);
}
bool YoggSaronMoveToEnterPortalTrigger::IsActive()
{
if (!IsPhase2())
{
return false;
}
Creature* portal = bot->FindNearestCreature(NPC_DESCEND_INTO_MADNESS, 100.0f, true);
if (!portal)
{
return false;
}
if (bot->GetDistance2d(portal->GetPositionX(), portal->GetPositionY()) < 2.0f)
{
return false;
}
if (AI_VALUE(std::string, "rti") != "skull")
{
return false;
}
Group* group = bot->GetGroup();
if (!group)
{
return false;
}
int brainRoomTeamCount = 10;
if (bot->GetRaidDifficulty() == Difficulty::RAID_DIFFICULTY_10MAN_NORMAL)
{
brainRoomTeamCount = 4;
}
if (IsMasterIsInIllusionGroup())
{
brainRoomTeamCount--;
}
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
{
Player* member = gref->GetSource();
if (!member || !member->IsAlive() || botAI->IsTank(member))
{
continue;
}
if (member->GetGUID() == bot->GetGUID())
{
return true;
}
brainRoomTeamCount--;
if (brainRoomTeamCount == 0)
{
break;
}
}
return false;
}
bool YoggSaronFallFromFloorTrigger::IsActive()
{
if (!IsYoggSaronFight())
{
return false;
}
std::string rtiMark = AI_VALUE(std::string, "rti");
if (rtiMark == "skull" && bot->GetPositionZ() < ULDUAR_YOGG_SARON_BOSS_ROOM_AXIS_Z_PATHING_ISSUE_DETECT)
{
return true;
}
if ((rtiMark == "cross" || rtiMark == "circle" || rtiMark == "star") && bot->GetPositionZ() < ULDUAR_YOGG_SARON_BRAIN_ROOM_AXIS_Z_PATHING_ISSUE_DETECT)
{
return true;
}
return false;
}
bool YoggSaronBossRoomMovementCheatTrigger::IsActive()
{
if (!IsYoggSaronFight() || !IsPhase2())
{
return false;
}
FollowMasterStrategy followMasterStrategy(botAI);
if (botAI->HasStrategy(followMasterStrategy.getName(), BotState::BOT_STATE_NON_COMBAT))
{
return true;
}
if (!botAI->HasCheat(BotCheatMask::raid))
{
return false;
}
if (AI_VALUE(std::string, "rti") != "skull")
{
return false;
}
Group* group = bot->GetGroup();
if (!group)
{
return false;
}
ObjectGuid currentSkullTarget = group->GetTargetIcon(RtiTargetValue::skullIndex);
if (!currentSkullTarget)
{
return false;
}
Unit* currentSkullUnit = botAI->GetUnit(currentSkullTarget);
if (!currentSkullUnit || !currentSkullUnit->IsAlive() || bot->GetDistance2d(currentSkullUnit->GetPositionX(), currentSkullUnit->GetPositionY()) < 40.0f)
{
return false;
}
return true;
}
bool YoggSaronUsePortalTrigger::IsActive()
{
if (!IsPhase2())
{
return false;
}
if (AI_VALUE(std::string, "rti") != "diamond")
{
return false;
}
return bot->FindNearestCreature(NPC_DESCEND_INTO_MADNESS, 2.0f, true) != nullptr;
}
bool YoggSaronIllusionRoomTrigger::IsActive()
{
if (!IsYoggSaronFight() || !IsInIllusionRoom() || AI_VALUE(std::string, "rti") == "square")
{
return false;
}
if (SetRtiMarkRequired())
{
return true;
}
if (SetRtiTargetRequired())
{
return true;
}
if (GoToBrainRoomRequired())
{
return true;
}
return false;
}
bool YoggSaronIllusionRoomTrigger::GoToBrainRoomRequired()
{
if (AI_VALUE(std::string, "rti") == "square")
{
return false;
}
return IsMasterIsInBrainRoom();
}
bool YoggSaronIllusionRoomTrigger::SetRtiMarkRequired()
{
return AI_VALUE(std::string, "rti") == "diamond";
}
bool YoggSaronIllusionRoomTrigger::SetRtiTargetRequired()
{
Unit const* currentRtiTarget = GetIllusionRoomRtiTarget();
if (currentRtiTarget != nullptr)
{
return false;
}
return GetNextIllusionRoomRtiTarget() != nullptr;
}
bool YoggSaronMoveToExitPortalTrigger::IsActive()
{
if (!IsYoggSaronFight() || !IsInBrainLevel())
{
return false;
}
Creature const* brain = bot->FindNearestCreature(NPC_BRAIN, 60.0f, true);
if (!brain || !brain->IsAlive())
{
return false;
}
if (brain->HasUnitState(UNIT_STATE_CASTING))
{
Spell* induceMadnessSpell = brain->GetCurrentSpell(CURRENT_GENERIC_SPELL);
if (induceMadnessSpell && induceMadnessSpell->m_spellInfo->Id == SPELL_INDUCE_MADNESS)
{
uint32 castingTimeLeft = induceMadnessSpell->GetCastTimeRemaining();
if ((botAI->HasCheat(BotCheatMask::raid) && castingTimeLeft < 6000) ||
(!botAI->HasCheat(BotCheatMask::raid) && castingTimeLeft < 8000))
{
return true;
}
}
}
else if (brain->GetHealth() < brain->GetMaxHealth() * 0.3f)
{
return true;
}
return false;
}
bool YoggSaronLunaticGazeTrigger::IsActive()
{
Unit* yoggsaron = AI_VALUE2(Unit*, "find target", "yogg-saron");
if (yoggsaron && yoggsaron->IsAlive() && yoggsaron->HasUnitState(UNIT_STATE_CASTING))
{
Spell* currentSpell = yoggsaron->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
if (currentSpell && currentSpell->m_spellInfo->Id == SPELL_LUNATIC_GAZE_YS)
{
return true;
}
}
return false;
}
bool YoggSaronPhase3PositioningTrigger::IsActive()
{
if (!IsYoggSaronFight() || !IsPhase3())
{
return false;
}
YoggSaronSanityTrigger sanityTrigger(botAI);
if (sanityTrigger.IsActive())
{
return false;
}
if (botAI->IsRanged(bot) && bot->GetDistance2d(ULDUAR_YOGG_SARON_PHASE_3_RANGED_SPOT.GetPositionX(),
ULDUAR_YOGG_SARON_PHASE_3_RANGED_SPOT.GetPositionY()) > 15.0f)
{
return true;
}
if (botAI->IsMelee(bot) && !botAI->IsTank(bot) &&
bot->GetDistance2d(ULDUAR_YOGG_SARON_PHASE_3_MELEE_SPOT.GetPositionX(),
ULDUAR_YOGG_SARON_PHASE_3_MELEE_SPOT.GetPositionY()) > 15.0f)
{
return true;
}
if (botAI->IsTank(bot))
{
if (bot->GetDistance(ULDUAR_YOGG_SARON_PHASE_3_MELEE_SPOT) > 30.0f)
{
return true;
}
GuidVector targets = AI_VALUE(GuidVector, "nearest npcs");
bool thereIsAnyGuardian = false;
for (const ObjectGuid& guid : targets)
{
Unit* unit = botAI->GetUnit(guid);
if (!unit || !unit->IsAlive())
{
continue;
}
if (unit->GetEntry() == NPC_IMMORTAL_GUARDIAN || unit->GetEntry() == NPC_MARKED_IMMORTAL_GUARDIAN)
{
thereIsAnyGuardian = true;
ObjectGuid unitTargetGuid = unit->GetTarget();
Player* targetedPlayer = botAI->GetPlayer(unitTargetGuid);
if (!targetedPlayer || !botAI->IsTank(targetedPlayer))
{
return false;
}
}
}
if (thereIsAnyGuardian && bot->GetDistance2d(ULDUAR_YOGG_SARON_PHASE_3_MELEE_SPOT.GetPositionX(),
ULDUAR_YOGG_SARON_PHASE_3_MELEE_SPOT.GetPositionY()) > 3.0f)
{
return true;
}
}
return false;
}