#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; return true; } //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; Unit* mount1 = bot->FindNearestCreature(36838, 100.0f); Unit* mount2 = bot->FindNearestCreature(36839, 100.0f); if (!mount1 && !mount2) 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 = bot->FindNearestCreature(36939, 100.0f); if (!boss) return false; if (!boss->IsHostileTo(bot)) return false; return true; } bool IccGunshipTeleportHordeTrigger::IsActive() { Unit* boss = bot->FindNearestCreature(36948, 100.0f); if (!boss) return false; if (!boss->IsHostileTo(bot)) 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() { // Early return if boss doesn't exist Unit* boss = AI_VALUE2(Unit*, "find target", "professor putricide"); if (!boss) return false; // Early return if bot has debuffs that would make movement dangerous if (botAI->HasAura("Gaseous Bloat", bot) || botAI->HasAura("Volatile Ooze Adhesive", bot)) return false; // Check for nearby dangerous puddles static const uint32 PUDDLE_IDS[] = {37690, 70341}; // Growing Ooze Puddle, Slime Puddle const GuidVector& npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); for (const auto& npc : npcs) { if (Unit* unit = botAI->GetUnit(npc)) { const uint32 entry = unit->GetEntry(); if (entry == PUDDLE_IDS[0] || entry == PUDDLE_IDS[1]) 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() { 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"); if (!(valanar || taldaram || keleseth)) return false; // Early exit condition - if Shadow Prison has too many stacks if (Aura* aura = botAI->GetAura("Shadow Prison", bot, false, true)) { if (aura->GetStackAmount() > 12) return false; } // Check for kinetic bombs const GuidVector& npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); bool bombFound = false; for (const auto& npc : npcs) { Unit* unit = botAI->GetUnit(npc); if (!unit || unit->GetName() != "Kinetic Bomb") continue; // Check if bomb is within valid Z-axis range if (unit->GetPositionZ() - bot->GetPositionZ() < 25.0f) { bombFound = true; break; } } // If no bomb is found, no need to handle it if (!bombFound) return false; // Check if the bot should handle the bomb if (bot->getClass() == CLASS_HUNTER) return true; // Hunters always handle bombs // If not a hunter, check if there are hunters in the group 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()) return false; // Let the hunter handle it } } // If no hunters are available, any ranged DPS should handle bombs return botAI->IsRangedDps(bot); } //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"); if (!boss) return false; Aura* aura = botAI->GetAura("Pact of the Darkfallen", bot); if (!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() { Unit* boss = bot->FindNearestCreature(36789, 100.0f); if (!boss) return false; //for gruop position for non healers if(!botAI->IsHeal(bot) && (bot->GetDistance(ICC_VDW_GROUP_POSITION) > 35.0f)) return true; // 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 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 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; Aura* aura = botAI->GetAura("mystic buffet", bot, false, false); if (botAI->IsTank(bot) && aura) //main tank will delete mystic buffet until I find a better way to swap tanks, atm it is not great since while swapping they will wipe group 7/10 times. bot->RemoveAura(aura->GetId()); 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() { Unit* boss = AI_VALUE2(Unit*, "find target", "sindragosa"); if (!boss) return false; 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; if (boss->HealthBelowPct(70)) return false; // search for all nearby traps GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); std::vector nearbyTraps; bool needToMove = false; for (auto& npc : npcs) { Unit* unit = botAI->GetUnit(npc); if (!unit || !unit->IsAlive()) continue; if (unit->GetEntry() == 39137) // shadow trap return true; } return false; } 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"); if (!boss) return false; return true; }