void SpellHit(Unit* caster, const SpellInfo* spell) override { if (withhead) return; if (spell->Id == SPELL_FLYING_HEAD) { if (Phase < 3) ++Phase; else Phase = 3; withhead = true; me->RemoveAllAuras(); me->SetName("Headless Horseman"); me->SetFullHealth(); SaySound(SAY_REJOINED); DoCast(me, SPELL_HEAD); caster->GetMotionMaster()->Clear(false); caster->GetMotionMaster()->MoveFollow(me, 6, float(urand(0, 5))); //DoResetThreat();//not sure if need ThreatContainer::StorageType threatlist = caster->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) { Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); if (unit && unit->IsAlive() && unit != caster) me->AddThreat(unit, caster->getThreatManager().getThreat(unit)); } } }
void BossAI::TeleportCheaters() { float x, y, z; me->GetPosition(x, y, z); ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) if (Unit* target = (*itr)->getTarget()) if (target->GetTypeId() == TYPEID_PLAYER && !CheckBoundary(target)) target->NearTeleportTo(x, y, z, 0); }
bool GuardAI::CanSeeAlways(WorldObject const* obj) { if (!obj->isType(TYPEMASK_UNIT)) return false; ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) if ((*itr)->getUnitGuid() == obj->GetGUID()) return true; return false; }
void CastGravityLapseKnockUp() { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) // Knockback into the air unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, me->GetGUID()); } }
void SetBloodvenomTarget() { ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator hostileReference = threatList.begin(); SummonList::const_iterator bloodvenomGUID = BloodVenoms.begin(); while (bloodvenomGUID != BloodVenoms.end() && hostileReference != threatList.end()) { if (Creature* bloodvenom = ObjectAccessor::GetCreature(*me, *bloodvenomGUID)) bloodvenom->AI()->SetGUID((*hostileReference)->getUnitGuid()); ++hostileReference; ++bloodvenomGUID; } }
void RemoveGravityLapse() { ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) { unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); unit->SetCanFly(false); } } }
void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... { ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) { // Also needs an exception in spell system. unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); unit->SetCanFly(true); } } }
void TeleportPlayersToSelf() { float x = KaelLocations[0][0]; float y = KaelLocations[0][1]; me->SetPosition(x, y, LOCATION_Z, 0.0f); ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) unit->CastSpell(unit, SPELL_TELEPORT_CENTER, true); } DoCast(me, SPELL_TELEPORT_CENTER, true); }
bool IsInThreatList(Unit* target) { Unit* owner = me->GetCharmerOrOwner(); std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(40.0f, searcher); for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { if ((*iter) == target) { // Consider only units without CC if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) { ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) { // Try to find threat referenced to owner if ((*trig_citr)->getTarget() == owner) return true; } } } } return false; }
void MergeThreatList(Creature* target) { if (!target) return; ThreatContainer::StorageType threatlist = target->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) { Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); if (unit) { DoModifyThreatPercent(unit, -100); float threat = target->getThreatManager().getThreat(unit); me->AddThreat(unit, threat); // This makes it so that the unit has the same amount of threat in Reliquary's threatlist as in the target creature's (One of the Essences). } } }
void ScriptedAI::DoResetThreat() { if (!me->CanHaveThreatList() || me->getThreatManager().isThreatListEmpty()) { sLog->outError(LOG_FILTER_TSCR, "DoResetThreat called for creature that either cannot have threat list or has empty threat list (me entry = %d)", me->GetEntry()); return; } ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) { Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid()); if (unit && DoGetThreat(unit)) DoModifyThreatPercent(unit, -100); } }
void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) { // Also needs an exception in spell system. unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, me->GetGUID()); // Use packet hack WorldPacket data(SMSG_MOVE_SET_CAN_FLY, 12); data.append(unit->GetPackGUID()); data << uint32(0); unit->SendMessageToSet(&data, true); } } }
void RemoveGravityLapse() { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()); if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) { unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY); unit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT); WorldPacket data(SMSG_MOVE_UNSET_CAN_FLY, 12); data.append(unit->GetPackGUID()); data << uint32(0); unit->SendMessageToSet(&data, true); } } }
Unit* CalculateHatefulStrikeTarget() { uint32 health = 0; Unit* target = nullptr; ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) { Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); if (unit && me->IsWithinMeleeRange(unit)) { if (unit->GetHealth() > health) { health = unit->GetHealth(); target = unit; } } } return target; }
Unit* ScriptedAI::SelectUnit(SelectAggroTarget pTarget, uint32 uiPosition) { ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator itr = threatList.begin(); ThreatContainer::StorageType::reverse_iterator ritr = threatList.rbegin(); if (uiPosition >= threatList.size() || !threatList.size()) return NULL; switch (pTarget) { case SELECT_TARGET_RANDOM: advance (itr , uiPosition + (rand() % (threatList.size() - uiPosition))); return Unit::GetUnit((*me), (*itr)->getUnitGuid()); break; case SELECT_TARGET_TOPAGGRO: advance (itr , uiPosition); return Unit::GetUnit((*me), (*itr)->getUnitGuid()); break; case SELECT_TARGET_BOTTOMAGGRO: advance (ritr , uiPosition); return Unit::GetUnit((*me), (*ritr)->getUnitGuid()); break; default: return UnitAI::SelectTarget(pTarget, uiPosition); } }
void UpdateAI(uint32 diff) { if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) return; events.Update(diff); switch (events.GetEvent()) { case EVENT_SPELL_SONIC_BOOM: Talk(EMOTE_SONIC_BOOM); me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_CAST_N, SPELL_SONIC_BOOM_CAST_H), false); events.RepeatEvent(28500); events.DelayEvents(1500); events.ScheduleEvent(EVENT_SPELL_SONIC_BOOM_EFFECT, 0); return; case EVENT_SPELL_SONIC_BOOM_EFFECT: me->CastSpell(me, DUNGEON_MODE(SPELL_SONIC_BOOM_EFFECT_N, SPELL_SONIC_BOOM_EFFECT_H), true); events.PopEvent(); break; case EVENT_SPELL_MURMURS_TOUCH: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true)) me->CastSpell(target, DUNGEON_MODE(SPELL_MURMURS_TOUCH_N, SPELL_MURMURS_TOUCH_H), false); events.RepeatEvent(urand(25000, 35000)); break; case EVENT_SPELL_RESONANCE: if (!me->IsWithinMeleeRange(me->GetVictim())) me->CastSpell(me, SPELL_RESONANCE, false); events.RepeatEvent(5000); break; case EVENT_SPELL_MAGNETIC: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true)) { me->CastSpell(target, SPELL_MAGNETIC_PULL, false); events.RepeatEvent(urand(15000, 30000)); return; } events.RepeatEvent(500); break; case EVENT_SPELL_THUNDERING: me->CastSpell(me, SPELL_THUNDERING_STORM, true); events.RepeatEvent(15000); break; case EVENT_SPELL_SONIC_SHOCK: me->CastSpell(me->GetVictim(), SPELL_SONIC_SHOCK, false); events.RepeatEvent(urand(10000, 20000)); break; } if (!me->isAttackReady()) return; if (!me->IsWithinMeleeRange(me->GetVictim())) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) if (target->IsAlive() && me->IsWithinMeleeRange(target)) { me->TauntApply(target); break; } } DoMeleeAttackIfReady(); }
void Init() { Unit* owner = me->GetCharmerOrOwner(); std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(40.0f, searcher); Unit* highestThreatUnit = nullptr; float highestThreat = 0.0f; Unit* nearestPlayer = nullptr; for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { // Consider only units without CC if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) { // Take first found unit if (!highestThreatUnit && (*iter)->GetTypeId() != TYPEID_PLAYER) { highestThreatUnit = (*iter); continue; } if (!nearestPlayer && ((*iter)->GetTypeId() == TYPEID_PLAYER)) { nearestPlayer = (*iter); continue; } // else compare best fit unit with current unit ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) { // Try to find threat referenced to owner if ((*trig_citr)->getTarget() == owner) { // Check if best fit hostile unit hs lower threat than this current unit if (highestThreat < (*trig_citr)->getThreat()) { // If so, update best fit unit highestThreat = (*trig_citr)->getThreat(); highestThreatUnit = (*iter); break; } } } // In case no unit with threat was found so far, always check for nearest unit (only for players) if ((*iter)->GetTypeId() == TYPEID_PLAYER) { // If this player is closer than the previous one, update it if (me->GetDistance((*iter)->GetPosition()) < me->GetDistance(nearestPlayer->GetPosition())) nearestPlayer = (*iter); } } } // Prioritize units with threat referenced to owner if (highestThreat > 0.0f && highestThreatUnit) me->Attack(highestThreatUnit, false); // If there is no such target, try to attack nearest hostile unit if such exists else if (nearestPlayer) me->Attack(nearestPlayer, false); }
void UpdateAI(uint32 diff) { //Return since we have no target or casting if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) return; // Sonic Boom if (SonicBoom) { DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); SonicBoomEffect(); SonicBoom = false; Resonance_Timer = 1500; } if (SonicBoom_Timer <= diff) { Talk(EMOTE_SONIC_BOOM); DoCast(me, SPELL_SONIC_BOOM_CAST); SonicBoom_Timer = 30000; SonicBoom = true; return; } else SonicBoom_Timer -= diff; // Murmur's Touch if (MurmursTouch_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80, true)) DoCast(target, SPELL_MURMURS_TOUCH); MurmursTouch_Timer = urand(25000, 35000); } else MurmursTouch_Timer -= diff; // Resonance if (!SonicBoom && !(me->IsWithinMeleeRange(me->GetVictim()))) { if (Resonance_Timer <= diff) { DoCast(me, SPELL_RESONANCE); Resonance_Timer = 5000; } else Resonance_Timer -= diff; } // Magnetic Pull if (MagneticPull_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive()) { DoCast(target, SPELL_MAGNETIC_PULL); MagneticPull_Timer = 15000+rand()%15000; return; } MagneticPull_Timer = 500; } else MagneticPull_Timer -= diff; if (IsHeroic()) { // Thundering Storm if (ThunderingStorm_Timer <= diff) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) if (Unit* target = Unit::GetUnit(*me, (*i)->getUnitGuid())) if (target->IsAlive() && !me->IsWithinDist(target, 35, false)) DoCast(target, SPELL_THUNDERING_STORM, true); ThunderingStorm_Timer = 15000; } else ThunderingStorm_Timer -= diff; // Sonic Shock if (SonicShock_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20, false)) if (target->IsAlive()) DoCast(target, SPELL_SONIC_SHOCK); SonicShock_Timer = 10000+rand()%10000; } else SonicShock_Timer -= diff; } // Select nearest most aggro target if top aggro too far if (!me->isAttackReady()) return; if (!me->IsWithinMeleeRange(me->GetVictim())) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) if (Unit* target = Unit::GetUnit(*me, (*i)->getUnitGuid())) if (target->IsAlive() && me->IsWithinMeleeRange(target)) { me->TauntApply(target); break; } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_SONIC_BOOM: Talk(EMOTE_SONIC_BOOM); DoCast(me, SPELL_SONIC_BOOM_CAST); events.ScheduleEvent(EVENT_SONIC_BOOM, 30000); events.ScheduleEvent(EVENT_RESONANCE, 1500); break; case EVENT_MURMURS_TOUCH: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true)) DoCast(target, SPELL_MURMURS_TOUCH); events.ScheduleEvent(EVENT_MURMURS_TOUCH, urand(25000, 35000)); break; case EVENT_RESONANCE: if (!(me->IsWithinMeleeRange(me->GetVictim()))) { DoCast(me, SPELL_RESONANCE); events.ScheduleEvent(EVENT_RESONANCE, 5000); } break; case EVENT_MAGNETIC_PULL: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { DoCast(target, SPELL_MAGNETIC_PULL); events.ScheduleEvent(EVENT_MAGNETIC_PULL, urand(15000, 30000)); break; } events.ScheduleEvent(EVENT_MAGNETIC_PULL, 500); break; case EVENT_THUNDERING_STORM: DoCastAOE(SPELL_THUNDERING_STORM, true); events.ScheduleEvent(EVENT_THUNDERING_STORM, 15000); break; case EVENT_SONIC_SHOCK: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, false)) DoCast(target, SPELL_SONIC_SHOCK); events.ScheduleEvent(EVENT_SONIC_SHOCK, urand(10000, 20000)); break; } if (me->HasUnitState(UNIT_STATE_CASTING)) return; } // Select nearest most aggro target if top aggro too far if (!me->isAttackReady()) return; if (!me->IsWithinMeleeRange(me->GetVictim())) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) if (me->IsWithinMeleeRange(target)) { me->TauntApply(target); break; } } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) { if (!UpdateVictim()) return; //Shimmer_Timer Timer if (Shimmer_Timer <= diff) { //Remove old vulnerabilty spell if (CurrentVurln_Spell) me->RemoveAurasDueToSpell(CurrentVurln_Spell); //Cast new random vulnerabilty on self uint32 spell = RAND(SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY); DoCast(me, spell); CurrentVurln_Spell = spell; Talk(EMOTE_SHIMMER); Shimmer_Timer = 45000; } else Shimmer_Timer -= diff; //Breath1_Timer if (Breath1_Timer <= diff) { DoCastVictim(Breath1_Spell); Breath1_Timer = 60000; } else Breath1_Timer -= diff; //Breath2_Timer if (Breath2_Timer <= diff) { DoCastVictim(Breath2_Spell); Breath2_Timer = 60000; } else Breath2_Timer -= diff; //Affliction_Timer if (Affliction_Timer <= diff) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) { if ((*i) && (*i)->GetSource()) { if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid())) { //Cast affliction DoCast(unit, RAND(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN), true); //Chromatic mutation if target is effected by all afflictions if (unit->HasAura(SPELL_BROODAF_BLUE) && unit->HasAura(SPELL_BROODAF_BLACK) && unit->HasAura(SPELL_BROODAF_RED) && unit->HasAura(SPELL_BROODAF_BRONZE) && unit->HasAura(SPELL_BROODAF_GREEN)) { //target->RemoveAllAuras(); //DoCast(target, SPELL_CHROMATIC_MUT_1); //Chromatic mutation is causing issues //Assuming it is caused by a lack of core support for Charm //So instead we instant kill our target //WORKAROUND if (unit->GetTypeId() == TYPEID_PLAYER) unit->CastSpell(unit, 5, false); } } } } Affliction_Timer = 10000; } else Affliction_Timer -= diff; //Frenzy_Timer if (Frenzy_Timer <= diff) { DoCast(me, SPELL_FRENZY); Talk(EMOTE_FRENZY); Frenzy_Timer = urand(10000, 15000); } else Frenzy_Timer -= diff; //Enrage if not already enraged and below 20% if (!Enraged && HealthBelowPct(20)) { DoCast(me, SPELL_ENRAGE); Enraged = true; } DoMeleeAttackIfReady(); }
void UpdateAI(uint32 diff) override { if (!me->HasAura(AURA_SPECTRAL_INVISIBILITY)) me->CastSpell(me, AURA_SPECTRAL_INVISIBILITY, true); if (!UpdateVictim()) return; if (CheckTimer <= diff) { Creature* Kalec = ObjectAccessor::GetCreature(*me, KalecGUID); if (!Kalec || !Kalec->IsAlive()) { if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->EnterEvadeMode(); return; } if (HealthBelowPct(10) && !isEnraged) { if (Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->DoAction(DO_ENRAGE); DoAction(DO_ENRAGE); } Creature* Kalecgos = ObjectAccessor::GetCreature(*me, KalecgosGUID); if (Kalecgos && !Kalecgos->IsInCombat()) { EnterEvadeMode(); return; } if (!isBanished && HealthBelowPct(1)) { if (Kalecgos) { if (Kalecgos->HasAura(SPELL_BANISH)) { me->DealDamage(me, me->GetHealth()); return; } DoAction(DO_BANISH); } else { me->MonsterTextEmote(EMOTE_UNABLE_TO_FIND, NULL); EnterEvadeMode(); return; } } CheckTimer = 1000; } else CheckTimer -= diff; if (ResetThreat <= diff) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) { if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) if (unit->GetPositionZ() > me->GetPositionZ() + 5) me->getThreatManager().modifyThreatPercent(unit, -100); } ResetThreat = 1000; } else ResetThreat -= diff; if (ShadowBoltTimer <= diff) { if (!(rand32() % 5)) Talk(SAY_SATH_SPELL1); DoCast(me, SPELL_SHADOW_BOLT); ShadowBoltTimer = 7000 + (rand32() % 3000); } else ShadowBoltTimer -= diff; if (AgonyCurseTimer <= diff) { Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); if (!target) target = me->GetVictim(); DoCast(target, SPELL_AGONY_CURSE); AgonyCurseTimer = 20000; } else AgonyCurseTimer -= diff; if (CorruptionStrikeTimer <= diff) { if (!(rand32() % 5))Talk(SAY_SATH_SPELL2); DoCastVictim(SPELL_CORRUPTION_STRIKE); CorruptionStrikeTimer = 13000; } else CorruptionStrikeTimer -= diff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { //Phase 1 switch (Phase) { case 1: { Unit* pTarget = NULL; Creature* Advisor = NULL; //Subphase switch switch (PhaseSubphase) { //Subphase 1 - Start case 0: if (Phase_Timer <= diff) { DoScriptText(SAY_INTRO_THALADRED, me); //start advisor within 7 seconds Phase_Timer = 7000; PhaseSubphase++; } else Phase_Timer -= diff; break; //Subphase 1 - Unlock advisor case 1: if (Phase_Timer <= diff) { Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[0])); if (Advisor) { Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Advisor->setFaction(me->getFaction()); pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (pTarget) Advisor->AI()->AttackStart(pTarget); } PhaseSubphase++; } else Phase_Timer -= diff; break; //Subphase 2 - Start case 2: Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[0])); if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_SANGUINAR, me); //start advisor within 12.5 seconds Phase_Timer = 12500; PhaseSubphase++; } break; //Subphase 2 - Unlock advisor case 3: if (Phase_Timer <= diff) { Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[1])); if (Advisor) { Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Advisor->setFaction(me->getFaction()); pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (pTarget) Advisor->AI()->AttackStart(pTarget); } PhaseSubphase++; } else Phase_Timer -= diff; break; //Subphase 3 - Start case 4: Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[1])); if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_CAPERNIAN, me); //start advisor within 7 seconds Phase_Timer = 7000; PhaseSubphase++; } break; //Subphase 3 - Unlock advisor case 5: if (Phase_Timer <= diff) { Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[2])); if (Advisor) { Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Advisor->setFaction(me->getFaction()); pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (pTarget) Advisor->AI()->AttackStart(pTarget); } PhaseSubphase++; } else Phase_Timer -= diff; break; //Subphase 4 - Start case 6: Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[2])); if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_TELONICUS, me); //start advisor within 8.4 seconds Phase_Timer = 8400; PhaseSubphase++; } break; //Subphase 4 - Unlock advisor case 7: if (Phase_Timer <= diff) { Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[3])); if (Advisor) { Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Advisor->setFaction(me->getFaction()); pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); if (pTarget) Advisor->AI()->AttackStart(pTarget); } Phase_Timer = 3000; PhaseSubphase++; } else Phase_Timer -= diff; break; //End of phase 1 case 8: Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[3])); if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) { Phase = 2; m_pInstance->SetData(DATA_KAELTHASEVENT, 2); DoScriptText(SAY_PHASE2_WEAPON, me); PhaseSubphase = 0; Phase_Timer = 3500; DoCast(me, SPELL_SUMMON_WEAPONS); } break; } } break; case 2: { if (PhaseSubphase == 0) { if (Phase_Timer <= diff) PhaseSubphase = 1; else Phase_Timer -= diff; } //Spawn weapons if (PhaseSubphase == 1) { me->CastSpell(me, SPELL_SUMMON_WEAPONS, false); uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon) / sizeof(uint32); for (uint32 i = 0; i < uiMaxWeapon; ++i) me->CastSpell(me, m_auiSpellSummonWeapon[i], true); PhaseSubphase = 2; Phase_Timer = TIME_PHASE_2_3; } if (PhaseSubphase == 2) { if (Phase_Timer < diff) { DoScriptText(SAY_PHASE3_ADVANCE, me); m_pInstance->SetData(DATA_KAELTHASEVENT, 3); Phase = 3; PhaseSubphase = 0; } else Phase_Timer -= diff; } } break; case 3: { if (PhaseSubphase == 0) { //Respawn advisors Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); Creature* Advisor; for (uint32 i = 0; i < MAX_ADVISORS; i++) { Advisor = (Creature*)(Unit::GetUnit((*me), m_auiAdvisorGuid[i])); if (!Advisor) error_log("OSCR: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); else if (pTarget) ((advisorbase_ai*)Advisor->AI())->Revive(pTarget); } PhaseSubphase = 1; Phase_Timer = TIME_PHASE_3_4; } if (Phase_Timer <= diff) { DoScriptText(SAY_PHASE4_INTRO2, me); Phase = 4; m_pInstance->SetData(DATA_KAELTHASEVENT, 4); // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. DoResetThreat(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) AttackStart(pTarget); Phase_Timer = 30000; } else Phase_Timer -= diff; } break; case 4: case 5: case 6: { //Return since we have no target if (!UpdateVictim()) return; //Fireball_Timer if (!InGravityLapse && !ChainPyros && Phase != 5) { if (Fireball_Timer <= diff) { if (!IsCastingFireball) { if (!me->IsNonMeleeSpellCast(false)) { //interruptable me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); int32 dmg = 20000 + rand() % 5000; me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); IsCastingFireball = true; Fireball_Timer = 2500; } } else { //apply resistance me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); IsCastingFireball = false; Fireball_Timer = 5000 + rand() % 10000; } } else Fireball_Timer -= diff; //ArcaneDisruption_Timer if (ArcaneDisruption_Timer <= diff) { DoCastVictim( SPELL_ARCANE_DISRUPTION, true); ArcaneDisruption_Timer = 60000; } else ArcaneDisruption_Timer -= diff; if (FlameStrike_Timer <= diff) { if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) DoCast(pUnit, SPELL_FLAME_STRIKE); FlameStrike_Timer = 30000; } FlameStrike_Timer -= diff; if (MindControl_Timer <= diff) { if (me->getThreatManager().getThreatList().size() >= 2) for (uint32 i = 0; i < 3; i++) { debug_log("OSCR: Kael'Thas mind control not supported."); //DoCast(pTarget, SPELL_MIND_CONTROL); } MindControl_Timer = 60000; } MindControl_Timer -= diff; } //Phoenix_Timer if (Phoenix_Timer <= diff) { DoCast(me, SPELL_PHOENIX_ANIMATION); if (Creature* pPhoenix = me->SummonCreature(NPC_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000)) { if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) pPhoenix->AI()->AttackStart(pTarget); } else error_log("OSCR: Kael'Thas Phoenix could not be spawned"); switch (rand() % 2) { case 0: DoScriptText(SAY_SUMMON_PHOENIX1, me); break; case 1: DoScriptText(SAY_SUMMON_PHOENIX2, me); break; } Phoenix_Timer = 60000; } else Phoenix_Timer -= diff; //Phase 4 specific spells if (Phase == 4) { if (me->GetHealth() * 100 / me->GetMaxHealth() < 50) { m_pInstance->SetData(DATA_KAELTHASEVENT, 4); Phase = 5; Phase_Timer = 10000; DoScriptText(SAY_PHASE5_NUTS, me); me->StopMoving(); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); me->Relocate(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); Movement::MoveSplineInit init(*me); init.MoveTo(afGravityPos[0], afGravityPos[1], afGravityPos[2], true); init.Launch(); me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_FULLPOWER); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } //ShockBarrier_Timer if (ShockBarrier_Timer <= diff) { DoCast(me, SPELL_SHOCK_BARRIER); ChainPyros = true; PyrosCasted = 0; ShockBarrier_Timer = 60000; } else ShockBarrier_Timer -= diff; //Chain Pyros (3 of them max) if (ChainPyros && !me->IsNonMeleeSpellCast(false)) { if (PyrosCasted < 3) { DoCastVictim( SPELL_PYROBLAST); PyrosCasted++; } else { ChainPyros = false; Fireball_Timer = 2500; ArcaneDisruption_Timer = 60000; } } } if (Phase == 5) { if (Phase_Timer <= diff) { me->InterruptNonMeleeSpells(false); me->RemoveAurasDueToSpell(SPELL_FULLPOWER); DoCast(me, SPELL_EXPLODE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Phase = 6; AttackStart(me->getVictim()); } else Phase_Timer -= diff; } //Phase 5 if (Phase == 6) { //GravityLapse_Timer if (GravityLapse_Timer <= diff) { ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); Movement::MoveSplineInit init(*me); switch (GravityLapse_Phase) { case 0: me->StopMoving(); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); me->Relocate(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); init.MoveTo(afGravityPos[0], afGravityPos[1], afGravityPos[2], true); init.Launch(); // 1) Kael'thas will portal the whole raid right into his body for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) { //Use work around packet to prevent player from being dropped from combat DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); } } GravityLapse_Timer = 500; ++GravityLapse_Phase; InGravityLapse = true; ShockBarrier_Timer = 1000; NetherBeam_Timer = 5000; break; case 1: switch (rand() % 2) { case 0: DoScriptText(SAY_GRAVITYLAPSE1, me); break; case 1: DoScriptText(SAY_GRAVITYLAPSE2, me); break; } // 2) At that point he will put a Gravity Lapse debuff on everyone for (i = threatlist.begin(); i != threatlist.end(); ++i) { if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) { me->CastSpell(pUnit, SPELL_KNOCKBACK, true); //Gravity lapse - needs an exception in Spell system to work pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); //Using packet workaround WorldPacket data(12); data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); data << pUnit->GetPackGUID(); data << uint32(0); pUnit->SendMessageToSet(&data, true); } } GravityLapse_Timer = 10000; GravityLapse_Phase++; break; case 2: //Cast nether vapor aura on self me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_NETHER_VAPOR); GravityLapse_Timer = 20000; GravityLapse_Phase++; break; case 3: //Remove flight for (i = threatlist.begin(); i != threatlist.end(); ++i) { if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) { //Using packet workaround WorldPacket data(12); data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); data << pUnit->GetPackGUID(); data << uint32(0); pUnit->SendMessageToSet(&data, true); } } me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); InGravityLapse = false; GravityLapse_Timer = 60000; GravityLapse_Phase = 0; AttackStart(me->getVictim()); break; } } else GravityLapse_Timer -= diff; if (InGravityLapse) { //ShockBarrier_Timer if (ShockBarrier_Timer <= diff) { DoCast(me, SPELL_SHOCK_BARRIER); ShockBarrier_Timer = 20000; } else ShockBarrier_Timer -= diff; //NetherBeam_Timer if (NetherBeam_Timer <= diff) { if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) DoCast(pUnit, SPELL_NETHER_BEAM); NetherBeam_Timer = 4000; } else NetherBeam_Timer -= diff; } } if (!InGravityLapse) DoMeleeAttackIfReady(); } } }
void UpdateAI(uint32 diff) { if(!UpdateVictim()) return; ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; while(uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_DISTANCE: distanceMelee = true; for (i = threatlist.begin(); i != threatlist.end(); ++i) { if (Unit* player = Unit::GetUnit(*me, (*i)->getUnitGuid())) if (player && (player->GetTypeId() == TYPEID_PLAYER) && me->IsWithinMeleeRange(player, 5.0f)) { distanceMelee = false; break; } } if (distanceMelee) events.ScheduleEvent(EVENT_SEETHE, 2*IN_MILLISECONDS); events.ScheduleEvent(EVENT_DISTANCE, 200); break; case EVENT_SEETHE: me->CastSpell(me->getVictim(), SPELL_SEETHE); distanceMelee = false; break; case EVENT_ENDLESS_RAGE: me->CastSpell(me->getVictim(), SPELL_ENDLESS_RAGE); Talk(SAY_ENDLESS_RAGE); break; case EVENT_GROWING_ANGER: me->CastSpell(me, SPELL_GROWING_ANGER); Talk(SAY_GROWING_ANGER); break; case EVENT_PHASE_GROWING_ANGER: events.SetPhase(PHASE_GROWING_ANGER); events.ScheduleEvent(EVENT_ENDLESS_RAGE, 20*IN_MILLISECONDS); events.ScheduleEvent(EVENT_GROWING_ANGER, urand(30*IN_MILLISECONDS, 35*IN_MILLISECONDS)); events.ScheduleEvent(EVENT_UNLEASHED_WRATH, 50*IN_MILLISECONDS); break; case EVENT_UNLEASHED_WRATH: DoCast(SPELL_UNLEASHED_WRATH); events.SetPhase(PHASE_UNLEASHED_WRATH); events.ScheduleEvent(EVENT_PHASE_GROWING_ANGER, 25*IN_MILLISECONDS, 0, PHASE_GROWING_ANGER); events.ScheduleEvent(EVENT_ENDLESS_RAGE, 15*IN_MILLISECONDS); break; case EVENT_BERSERK: DoCast(SPELL_BERSERK); break; default: break; } } DoMeleeAttackIfReady(); }