mod-playerbots/src/strategy/raids/icecrown/RaidIccTriggers.cpp
Noscopezz bdf8c6cc14
ICC BQL/VDW major update + minor fixes/improvements (#929)
LDW
Improved spreading for ranged, tanks will move boss in the middle of the room now when shield is depleted which will make bots bug less around pillars

GS
Assist tank will not teleport to enemy ship and will keep tanking adds on our ship now

DBS
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum), fixed bug where in 25 man ranged bots would go behind walls, making them unable to dps boss, improved rune of blood tanking

Festergut
Ranged spread improved (they will calcualte spot for each bot and stick with it reducing movment to minimum)

BQL
Melee spread improved, bite logic improved, added swarming shadows logic (not perfect but at least it wont be all over the room anymore), Tanks will properly handle blood mirror now

VDW
Boss and raid healers will be automatically assinged depening by number of healers(if more than 3 healers in group, 2 will focus on raid and others will heal boss, otherwise one healer will heal raid).
Druids will be assigned to raid healing if no druid present then some other random heal class.
Added rotations for druid healers if they end up healing the boss.
Raid healers will not use portals anymore.
Healers will come to the ground now after using portals (they were stuck in air)
2025-01-30 17:07:01 +01:00

1001 lines
26 KiB
C++

#include "RaidIccTriggers.h"
#include "RaidIccActions.h"
#include "strategy/values/NearestNpcsValue.h"
#include "PlayerbotAIConfig.h"
#include "ObjectAccessor.h"
#include "GenericTriggers.h"
#include "DungeonStrategyUtils.h"
#include "EventMap.h"
#include "Playerbots.h"
#include "ScriptedCreature.h"
#include "Trigger.h"
//Lord Marrogwar
bool IccLmTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "lord marrowgar");
if (!boss) { return false; }
return botAI->IsTank(bot);
}
bool IccSpikeNearTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "lord marrowgar");
if (!boss)
return false;
GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
for (auto& npc : npcs)
{
Unit* unit = botAI->GetUnit(npc);
if (unit)
{
if (unit->GetEntry() == 36619 || unit->GetEntry() == 38711 || unit->GetEntry() == 38712 ) //spike ID
{
if (unit->GetDistance(bot) <= 20.0f)
{
return botAI->IsDps(bot);
}
return botAI->IsRangedDps(bot);
}
}
}
return false;
}
//Lady Deathwhisper
bool IccDarkReckoningTrigger::IsActive()
{
Unit* add = AI_VALUE2(Unit*, "find target", "deathspeaker high priest");
if (add || bot->HasAura(69483))
return true;
return false;
}
bool IccRangedPositionLadyDeathwhisperTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper");
if (!boss)
return false;
return (botAI->IsRangedDps(bot) || botAI->IsHeal(bot));
}
bool IccAddsLadyDeathwhisperTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper");
if (!boss)
return false;
return true;
}
bool IccShadeLadyDeathwhisperTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "lady deathwhisper");
if (!boss) { return false; }
GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
for (auto& npc : npcs)
{
Unit* unit = botAI->GetUnit(npc);
if (unit)
{
if (unit->GetEntry() == 38222 ) //vengeful sahde ID
{
return true;
}
}
}
return false;
}
//Gunship Battle
bool IccRottingFrostGiantTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "rotting frost giant");
if (!boss) { return false; }
return true;
}
bool IccInCannonTrigger::IsActive()
{
Unit* vehicleBase = bot->GetVehicleBase();
Vehicle* vehicle = bot->GetVehicle();
if (!vehicleBase || !vehicle)
return false;
uint32 entry = vehicleBase->GetEntry();
return entry == 36838 || entry == 36839;
}
bool IccGunshipCannonNearTrigger::IsActive()
{
if (bot->GetVehicle())
return false;
if (!botAI->IsDps(bot))
return false;
// Player* master = botAI->GetMaster();
// if (!master)
// return false;
// if (!master->GetVehicle())
// return false;
return true;
}
bool IccGunshipTeleportAllyTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "kor'kron battle-mage");
if (!boss) { return false; }
return true;
}
bool IccGunshipTeleportHordeTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "skybreaker sorcerer");
if (!boss) { return false; }
return true;
}
//DBS
bool IccDbsTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang");
if (!boss) { return false; }
return true;
}
bool IccDbsMainTankRuneOfBloodTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang");
if (!boss)
return false;
if (!botAI->IsAssistTankOfIndex(bot, 0))
return false;
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
return false;
Aura* aura = botAI->GetAura("rune of blood", mt);
if (!aura)
return false;
return true;
}
bool IccAddsDbsTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "deathbringer saurfang");
if (!boss) { return false; }
return true;
}
//DOGS
bool IccStinkyPreciousMainTankMortalWoundTrigger::IsActive()
{
bool bossPresent = false;
if (AI_VALUE2(Unit*, "find target", "stinky") || AI_VALUE2(Unit*, "find target", "precious"))
bossPresent = true;
if (!bossPresent)
return false;
if (!botAI->IsAssistTankOfIndex(bot, 0))
{
return false;
}
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
{
return false;
}
Aura* aura = botAI->GetAura("mortal wound", mt, false, true);
if (!aura || aura->GetStackAmount() < 8)
{
return false;
}
return true;
}
//FESTERGUT
bool IccFestergutTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "festergut");
if (!boss || !(botAI->IsTank(bot) || botAI->IsRanged(bot) || botAI->IsHeal(bot)))
return false;
return true;
}
bool IccFestergutMainTankGastricBloatTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "festergut");
if (!boss)
{
return false;
}
if (!botAI->IsAssistTankOfIndex(bot, 0))
{
return false;
}
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
{
return false;
}
Aura* aura = botAI->GetAura("Gastric Bloat", mt, false, true);
if (!aura || aura->GetStackAmount() < 6)
{
return false;
}
return true;
}
bool IccFestergutSporeTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "festergut");
if (!boss || botAI->IsTank(bot))
return false;
// Check for spore aura (ID: 69279) on any bot in the group
Group* group = bot->GetGroup();
if (!group)
return false;
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* member = itr->GetSource();
if (!member)
continue;
if (member->HasAura(69279)) // Spore aura ID
return true;
}
return false;
}
//ROTFACE
bool IccRotfaceTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "rotface");
if (!boss || !(botAI->IsTank(bot) || botAI->IsMainTank(bot) || botAI->IsAssistTank(bot)))
return false;
return true;
}
bool IccRotfaceGroupPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "rotface");
if (!boss) { return false; }
return true;
}
bool IccRotfaceMoveAwayFromExplosionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "big ooze");
if (!boss) { return false; }
return boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(69839);
}
//PP
bool IccPutricideGrowingOozePuddleTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "professor putricide");
bool botHasAura = botAI->HasAura("Gaseous Bloat", bot) || botAI->HasAura("Volatile Ooze Adhesive", bot);
if (!boss || botHasAura)
return false;
// Check for nearby growing ooze puddles (37690) and slime puddles (70341)
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 == 37690 || entry == 70341) // Growing Ooze Puddle or Slime Puddle
{
return true;
}
}
return false;
}
bool IccPutricideVolatileOozeTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "volatile ooze");
if (!boss)
return false;
if (botAI->HasAura("Gaseous Bloat", bot))
return false;
return true;
}
bool IccPutricideGasCloudTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "gas cloud");
if (!boss)
return false;
return true;
}
bool IccPutricideMainTankMutatedPlagueTrigger::IsActive()
{
bool bossPresent = false;
if (AI_VALUE2(Unit*, "find target", "professor putricide"))
bossPresent = true;
if (!bossPresent)
return false;
if (!botAI->IsAssistTankOfIndex(bot, 0))
{
return false;
}
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
{
return false;
}
Aura* aura = botAI->GetAura("Mutated Plague", mt, false, true);
if (!aura || aura->GetStackAmount() < 4)
{
return false;
}
return true;
}
bool IccPutricideMalleableGooTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "professor putricide");
if (!boss)
return false;
Unit* boss1 = AI_VALUE2(Unit*, "find target", "volatile ooze");
if (boss1)
return false;
Unit* boss2 = AI_VALUE2(Unit*, "find target", "gas cloud");
if (boss2)
return false;
return true;
}
//BPC
bool IccBpcKelesethTankTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
if (!boss)
return false;
if (!botAI->IsAssistTank(bot))
return false;
Aura* aura = botAI->GetAura("Shadow Prison", bot, false, true);
if (aura)
if (aura->GetStackAmount() > 18)
return false;
// First priority is to check for nucleuses that need to be picked up
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
for (auto i = targets.begin(); i != targets.end(); ++i)
{
Unit* unit = botAI->GetUnit(*i);
if (unit && unit->IsAlive() && unit->GetEntry() == 38369) // Dark Nucleus entry
{
if (!unit->GetVictim() || unit->GetVictim() != bot)
return false; // Don't tank Keleseth if there's a nucleus to grab
}
}
return true;
}
bool IccBpcNucleusTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "prince keleseth");
if (!boss)
return false;
if (!botAI->IsAssistTank(bot))
return false;
Aura* aura = botAI->GetAura("Shadow Prison", bot, false, true);
if (aura)
if (aura->GetStackAmount() > 18)
return false;
// Actively look for any nucleus that isn't targeting us
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
for (auto i = targets.begin(); i != targets.end(); ++i)
{
Unit* unit = botAI->GetUnit(*i);
if (unit && unit->IsAlive() && unit->GetEntry() == 38369) // Dark Nucleus entry
{
if (!unit->GetVictim() || unit->GetVictim() != bot)
return true; // Found a nucleus that needs to be picked up
}
}
return false;
}
bool IccBpcMainTankTrigger::IsActive()
{
Unit* valanar = AI_VALUE2(Unit*, "find target", "prince valanar");
Unit* taldaram = AI_VALUE2(Unit*, "find target", "prince taldaram");
Unit* keleseth = AI_VALUE2(Unit*, "find target", "prince keleseth");
return valanar != nullptr || taldaram != nullptr || keleseth != nullptr;
}
bool IccBpcEmpoweredVortexTrigger::IsActive()
{
// Tanks should ignore this mechanic
if (botAI->IsMainTank(bot) || botAI->IsAssistTank(bot))
return false;
Unit* valanar = AI_VALUE2(Unit*, "find target", "prince valanar");
if (!valanar)
return false;
Aura* aura = botAI->GetAura("Shadow Prison", bot, false, true);
if (aura)
if (aura->GetStackAmount() > 12)
return false;
Aura* auraValanar = botAI->GetAura("Invocation of Blood", valanar);
if (!auraValanar)
return false;
// For ranged, spread whenever Valanar is empowered
//if (botAI->IsRanged(bot) && auraValanar)
//return true;
// For melee, only spread during vortex cast
if (auraValanar && valanar->HasUnitState(UNIT_STATE_CASTING))
return true;
return false;
}
bool IccBpcKineticBombTrigger::IsActive()
{
GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
// Check for hunters first
bool hasHunter = false;
Group* group = bot->GetGroup();
if (group)
{
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* member = itr->GetSource();
if (member && member->getClass() == CLASS_HUNTER && member->IsAlive())
{
hasHunter = true;
break;
}
}
}
for (auto& npc : npcs)
{
Unit* unit = botAI->GetUnit(npc);
if (unit && unit->GetName() == "Kinetic Bomb" &&
((unit->GetPositionZ() - bot->GetPositionZ()) < 25.0f))
{
if (hasHunter)
{
return bot->getClass() == CLASS_HUNTER; // Only hunters can handle bombs
}
else if (botAI->IsRangedDps(bot))
{
return true; // If no hunters, any ranged DPS can handle bombs
}
}
}
return false;
}
//BQL
bool IccBqlTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel");
if (!boss)
return false;
return true;
}
bool IccBqlPactOfDarkfallenTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel");
Aura* aura = botAI->GetAura("Pact of the Darkfallen", bot);
if (!boss || !aura)
return false;
return true;
}
bool IccBqlVampiricBiteTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "blood-queen lana'thel");
if (!boss)
return false;
Aura* aura = botAI->GetAura("Frenzied Bloodthirst", bot);
// Only trigger when bot has Frenzied Bloodthirst
if (!aura)
return false;
return true;
}
//VDW
bool IccValkyreSpearTrigger::IsActive()
{
// Check if there's a spear nearby
if (Creature* spear = bot->FindNearestCreature(38248, 100.0f))
return true;
return false;
}
bool IccSisterSvalnaTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sister svalna");
if (!boss)
{
return false;
}
return true;
}
bool IccValithriaPortalTrigger::IsActive()
{
// Only healers should use portals
if (!botAI->IsHeal(bot) || bot->HasAura(70766))
return false;
Group* group = bot->GetGroup();
if (!group)
return false;
// Count healers and collect their GUIDs
std::vector<ObjectGuid> healerGuids;
int healerCount = 0;
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* member = itr->GetSource();
if (!member || !member->IsAlive())
continue;
if (botAI->IsHeal(member))
{
healerCount++;
healerGuids.push_back(member->GetGUID());
}
}
// Sort GUIDs to ensure consistent ordering
std::sort(healerGuids.begin(), healerGuids.end());
// Find position of current bot's GUID in the sorted list
auto botGuidPos = std::find(healerGuids.begin(), healerGuids.end(), bot->GetGUID());
if (botGuidPos == healerGuids.end())
return false;
int healerIndex = std::distance(healerGuids.begin(), botGuidPos);
// Determine if this healer should focus on raid
bool shouldHealRaid = false;
if (healerCount > 3)
{
// If more than 3 healers, 2 should heal raid
if (bot->getClass() == CLASS_DRUID)
shouldHealRaid = true; // Druids prioritize raid healing
else
shouldHealRaid = (healerIndex >= (healerCount - 2)); // Last 2 healers (by GUID) heal raid if no druid
}
else
{
// If 3 or fewer healers, 1 should heal raid
if (bot->getClass() == CLASS_DRUID)
shouldHealRaid = true; // Druids prioritize raid healing
else
shouldHealRaid = (healerIndex == (healerCount - 1)); // Last healer (by GUID) heals raid if no druid
}
// Raid healers should not use portals
if (shouldHealRaid)
return false;
// Find the nearest portal creature
Creature* portal = bot->FindNearestCreature(37945, 100.0f); // Only check within 10 yards
Creature* portal2 = bot->FindNearestCreature(38430, 100.0f); // Only check within 10 yards
return portal || portal2;
}
bool IccValithriaHealTrigger::IsActive()
{
Unit* boss = bot->FindNearestCreature(36789, 100.0f);
if (!boss)
return false;
// Only healers should use healing
if (!botAI->IsHeal(bot) || bot->HasAura(70766))
return false;
Group* group = bot->GetGroup();
if (!group)
return false;
// Count healers and collect their GUIDs
std::vector<ObjectGuid> healerGuids;
int healerCount = 0;
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
Player* member = itr->GetSource();
if (!member || !member->IsAlive())
continue;
if (botAI->IsHeal(member))
{
healerCount++;
healerGuids.push_back(member->GetGUID());
}
}
// Sort GUIDs to ensure consistent ordering
std::sort(healerGuids.begin(), healerGuids.end());
// Find position of current bot's GUID in the sorted list
auto botGuidPos = std::find(healerGuids.begin(), healerGuids.end(), bot->GetGUID());
if (botGuidPos == healerGuids.end())
return false;
int healerIndex = std::distance(healerGuids.begin(), botGuidPos);
// Determine if this healer should focus on raid
bool shouldHealRaid = false;
if (healerCount > 3)
{
// If more than 3 healers, 2 should heal raid
if (bot->getClass() == CLASS_DRUID)
shouldHealRaid = true; // Druids prioritize raid healing
else
shouldHealRaid = (healerIndex >= (healerCount - 2)); // Last 2 healers (by GUID) heal raid if no druid
}
else
{
// If 3 or fewer healers, 1 should heal raid
if (bot->getClass() == CLASS_DRUID)
shouldHealRaid = true; // Druids prioritize raid healing
else
shouldHealRaid = (healerIndex == (healerCount - 1)); // Last healer (by GUID) heals raid if no druid
}
// If assigned to raid healing, return false to not heal Valithria
if (shouldHealRaid)
return false;
// For Valithria healers, check portal logic
// If no portal is found within 100 yards, we should heal
if (!bot->FindNearestCreature(37945, 100.0f) && !bot->FindNearestCreature(38430, 100.0f))
return true;
// If portal is nearby (10 yards), don't heal
if (bot->FindNearestCreature(37945, 20.0f) || bot->FindNearestCreature(38430, 10.0f))
return false;
// If portal is far but within 100 yards, heal while moving to it
return true;
}
bool IccValithriaDreamCloudTrigger::IsActive()
{
// Only active if we're in dream state
if (!bot->HasAura(70766))
return false;
// Find nearest cloud of either type
Creature* dreamCloud = bot->FindNearestCreature(37985, 100.0f);
Creature* nightmareCloud = bot->FindNearestCreature(38421, 100.0f);
return (dreamCloud || nightmareCloud);
}
//SINDRAGOSA
bool IccSindragosaTankPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss || bot->HasAura(70126) /*|| bot->HasAura(69762)*/ || boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY))
return false;
return true;
}
bool IccSindragosaFrostBeaconTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss)
return false;
Group* group = bot->GetGroup();
if (!group)
return false;
if (boss->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && !boss->HealthBelowPct(35))
return true;
Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); ++itr)
{
Player* member = ObjectAccessor::FindPlayer(itr->guid);
if (!member || !member->IsAlive())
continue;
if (member->HasAura(70126)) // If any player has Frost Beacon, keep trigger active
return true;
}
return false;
}
bool IccSindragosaBlisteringColdTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss)
return false;
if (botAI->IsMainTank(bot))
return false;
// Don't move if any bot in group has ice tomb
Group* group = bot->GetGroup();
if (!group)
return false;
float dist = bot->GetDistance(boss);
if (dist >= 30.0f)
return false;
bool isCasting = boss->HasUnitState(UNIT_STATE_CASTING);
bool isBlisteringCold = boss->FindCurrentSpellBySpellId(70123) || boss->FindCurrentSpellBySpellId(71047) ||
boss->FindCurrentSpellBySpellId(71048) || boss->FindCurrentSpellBySpellId(71049);
return isCasting && isBlisteringCold;
}
bool IccSindragosaUnchainedMagicTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss || (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(70123)))
return false;
return bot->HasAura(69762);
}
bool IccSindragosaChilledToTheBoneTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss || (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(70123)))
return false;
return bot->HasAura(70106);
}
bool IccSindragosaMysticBuffetTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss)
return false;
if (botAI->IsTank(bot) && boss->GetVictim() == bot)
return false;
Aura* aura = botAI->GetAura("mystic buffet", bot, false, true);
if (!aura)
return false;
if (bot->HasAura(70126)) // Frost Beacon
return false;
if (aura->GetStackAmount() >= 2 && botAI->IsAssistTank(bot))
return true;
if (aura->GetStackAmount() >= 3)
return true;
return false;
}
bool IccSindragosaMainTankMysticBuffetTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss)
return false;
if (botAI->IsTank(bot) && boss->GetVictim() == bot)
return false;
// Only for assist tank
if (!botAI->IsAssistTankOfIndex(bot, 0))
return false;
// Don't swap if we have frost beacon
if (bot->HasAura(70126)) // Frost Beacon
return false;
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
return false;
// Check main tank stacks
Aura* mtAura = botAI->GetAura("mystic buffet", mt, false, true);
if (!mtAura || mtAura->GetStackAmount() < 9)
return false;
// Check our own stacks - don't taunt if we have too many
Aura* selfAura = botAI->GetAura("mystic buffet", bot, false, true);
if (selfAura && selfAura->GetStackAmount() > 6)
return false;
// Only taunt if we're in position
float distToTankPos = bot->GetExactDist2d(ICC_SINDRAGOSA_TANK_POSITION);
if (distToTankPos > 3.0f)
return false;
return true;
}
bool IccSindragosaTankSwapPositionTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa");
if (!boss)
return false;
// Only for assist tank
if (!botAI->IsAssistTankOfIndex(bot, 0))
return false;
// Don't move to position if we have frost beacon
if (bot->HasAura(70126)) // Frost Beacon
return false;
// Check our own stacks - don't try to tank if we have too many
Aura* selfAura = botAI->GetAura("mystic buffet", bot, false, true);
if (selfAura && selfAura->GetStackAmount() > 6)
return false;
// Check if main tank has high stacks
Unit* mt = AI_VALUE(Unit*, "main tank");
if (!mt)
return false;
Aura* mtAura = botAI->GetAura("mystic buffet", mt, false, true);
if (!mtAura)
return false;
uint32 mtStacks = mtAura->GetStackAmount();
if (mtStacks < 9) // Only start moving when MT has 5+ stacks
return false;
// Check if we're already in position
float distToTankPos = bot->GetExactDist2d(ICC_SINDRAGOSA_TANK_POSITION);
if (distToTankPos <= 3.0f)
return false;
return true; // Move to position if all conditions are met
}
bool IccSindragosaFrostBombTrigger::IsActive()
{
if (!bot->IsAlive() || bot->HasAura(70157)) // Skip if dead or in Ice Tomb
return false;
// Simply check if frost bomb marker exists
GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
for (auto& npc : npcs)
{
Unit* unit = botAI->GetUnit(npc);
if (!unit || !unit->IsAlive())
continue;
if (unit->HasAura(70022)) // Frost bomb visual
return true;
}
return false;
}
//LK
bool IccLichKingShadowTrapTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king");
if (!boss)
return false;
return true;
}
bool IccLichKingNecroticPlagueTrigger::IsActive()
{
if (!bot || !bot->IsAlive())
return false;
// Check for plague by name instead of ID
bool hasPlague = botAI->HasAura("Necrotic Plague", bot);
return hasPlague;
}
bool IccLichKingWinterTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king");
if (!boss)
return false;
// Check for either Remorseless Winter
bool hasWinterAura = boss->HasAura(72259) || boss->HasAura(74273) || boss->HasAura(74274) || boss->HasAura(74275);
bool hasWinter2Aura = boss->HasAura(68981) || boss->HasAura(74270) || boss->HasAura(74271) || boss->HasAura(74272);
bool isCasting = boss->HasUnitState(UNIT_STATE_CASTING);
bool isWinter = boss->FindCurrentSpellBySpellId(77259) || boss->FindCurrentSpellBySpellId(74273) || boss->FindCurrentSpellBySpellId(68981) || boss->FindCurrentSpellBySpellId(74270) ||
boss->FindCurrentSpellBySpellId(74274) || boss->FindCurrentSpellBySpellId(74275) || boss->FindCurrentSpellBySpellId(74271) || boss->FindCurrentSpellBySpellId(74272);
if (hasWinterAura || hasWinter2Aura)
return true;
if (isCasting && isWinter)
return true;
return false;
}
bool IccLichKingAddsTrigger::IsActive()
{
Unit* boss = AI_VALUE2(Unit*, "find target", "the lich king");
Unit* spiritWarden = AI_VALUE2(Unit*, "find target", "spirit warden");
if (!boss && !spiritWarden)
return false;
return true;
}