diff options
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp | 4297 |
1 files changed, 1923 insertions, 2374 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 51aafdf0c6e..566444dcb43 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -488,1964 +488,1739 @@ class TriggerWickedSpirit : public BasicEvent uint32 _counter; }; -class boss_the_lich_king : public CreatureScript +struct boss_the_lich_king : public BossAI { - public: - boss_the_lich_king() : CreatureScript("boss_the_lich_king") { } - - struct boss_the_lich_kingAI : public BossAI - { - boss_the_lich_kingAI(Creature* creature) : BossAI(creature, DATA_THE_LICH_KING) - { - Initialize(); - } - - void Initialize() - { - _necroticPlagueStack = 0; - _vileSpiritExplosions = 0; - } + boss_the_lich_king(Creature* creature) : BossAI(creature, DATA_THE_LICH_KING) + { + Initialize(); + } - void Reset() override - { - _Reset(); - me->SetImmuneToPC(true); - me->SetReactState(REACT_PASSIVE); - events.SetPhase(PHASE_INTRO); - Initialize(); - SetEquipmentSlots(true); - - // Reset The Frozen Throne gameobjects - FrozenThroneResetWorker reset; - Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset); - Cell::VisitGridObjects(me, worker, 333.0f); - - // Reset any light override - me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, 0, 5000); + void Initialize() + { + _necroticPlagueStack = 0; + _vileSpiritExplosions = 0; + } - if (!ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN); - } + void Reset() override + { + _Reset(); + me->SetImmuneToPC(true); + me->SetReactState(REACT_PASSIVE); + events.SetPhase(PHASE_INTRO); + Initialize(); + SetEquipmentSlots(true); + + // Reset The Frozen Throne gameobjects + FrozenThroneResetWorker reset; + Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset); + Cell::VisitGridObjects(me, worker, 333.0f); + + // Reset any light override + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, 0, 5000); + + if (!ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN); + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - DoCastAOE(SPELL_PLAY_MOVIE, false); - me->SetDisableGravity(false); - me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); - me->GetMotionMaster()->MoveFall(); - if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) - frostmourne->DespawnOrUnsummon(); - me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_FOG, 5000); - me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_FOG, 0.0f); + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + DoCastAOE(SPELL_PLAY_MOVIE, false); + me->SetDisableGravity(false); + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); + me->GetMotionMaster()->MoveFall(); + if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) + frostmourne->DespawnOrUnsummon(); + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_FOG, 5000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_FOG, 0.0f); + + if (Is25ManRaid()) + if (Player* player = me->GetLootRecipient()) + player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player); + } - if (Is25ManRaid()) - if (Player* player = me->GetLootRecipient()) - player->RewardPlayerAndGroupAtEvent(NPC_THE_LICH_KING_QUEST, player); - } + void JustEngagedWith(Unit* target) override + { + if (!instance->CheckRequiredBosses(DATA_THE_LICH_KING, target->ToPlayer())) + { + EnterEvadeMode(EVADE_REASON_OTHER); + instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); + return; + } - void JustEngagedWith(Unit* target) override - { - if (!instance->CheckRequiredBosses(DATA_THE_LICH_KING, target->ToPlayer())) - { - EnterEvadeMode(EVADE_REASON_OTHER); - instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); - return; - } + me->setActive(true); + me->SetCombatPulseDelay(5); + DoZoneInCombat(); + + events.SetPhase(PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 20s, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 10s, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_INFEST, 5s, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 30s, 33s, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_BERSERK, 15min, EVENT_GROUP_BERSERK); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500ms, 0, PHASE_ONE); + } - me->setActive(true); - me->SetCombatPulseDelay(5); - DoZoneInCombat(); + bool CanAIAttack(Unit const* target) const override + { + // The Lich King must not select targets in frostmourne room if he killed everyone outside + return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target); + } - events.SetPhase(PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 20s, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 10s, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_INFEST, 5s, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 30s, 33s, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_BERSERK, 15min, EVENT_GROUP_BERSERK); - if (IsHeroic()) - events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500ms, 0, PHASE_ONE); - } + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->DespawnOrUnsummon(); + DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS); + EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE); + summons.DoAction(ACTION_TELEPORT_BACK, pred); + summons.DespawnAll(); + _DespawnAtEvade(); + } - bool CanAIAttack(Unit const* target) const override - { - // The Lich King must not select targets in frostmourne room if he killed everyone outside - return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode() && !events.IsInPhase(PHASE_OUTRO)) + Talk(SAY_LK_KILL); + } - void EnterEvadeMode(EvadeReason /*why*/) override + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_START_ENCOUNTER: + instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS); + Talk(SAY_LK_INTRO_1); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FROZEN_THRONE); + // schedule talks + me->SetStandState(UNIT_STAND_STATE_STAND); + events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4s); + break; + case ACTION_START_ATTACK: + events.ScheduleEvent(EVENT_START_ATTACK, 5s); + break; + case ACTION_PLAY_MUSIC: + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); + break; + case ACTION_RESTORE_LIGHT: + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, 0, 5000); + break; + case ACTION_BREAK_FROSTMOURNE: + me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_2, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + SetEquipmentSlots(false, EQUIP_BROKEN_FROSTMOURNE); + events.ScheduleEvent(EVENT_OUTRO_TALK_6, 2500ms, 0, PHASE_OUTRO); + break; + case ACTION_FINISH_OUTRO: + events.ScheduleEvent(EVENT_OUTRO_TALK_7, 7s, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_TALK_8, 17s, 0, PHASE_OUTRO); + break; + case ACTION_TELEPORT_BACK: { - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->DespawnOrUnsummon(); - DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS); EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE); summons.DoAction(ACTION_TELEPORT_BACK, pred); - summons.DespawnAll(); - _DespawnAtEvade(); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode() && !events.IsInPhase(PHASE_OUTRO)) - Talk(SAY_LK_KILL); + if (!IsHeroic()) + Talk(SAY_LK_FROSTMOURNE_ESCAPE); + break; } + default: + break; + } + } - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_START_ENCOUNTER: - instance->SetBossState(DATA_THE_LICH_KING, IN_PROGRESS); - Talk(SAY_LK_INTRO_1); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FROZEN_THRONE); - // schedule talks - me->SetStandState(UNIT_STAND_STATE_STAND); - events.ScheduleEvent(EVENT_INTRO_MOVE_1, 4s); - break; - case ACTION_START_ATTACK: - events.ScheduleEvent(EVENT_START_ATTACK, 5s); - break; - case ACTION_PLAY_MUSIC: - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); - break; - case ACTION_RESTORE_LIGHT: - me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, 0, 5000); - break; - case ACTION_BREAK_FROSTMOURNE: - me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); - me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_2, TRIGGERED_IGNORE_CAST_IN_PROGRESS); - SetEquipmentSlots(false, EQUIP_BROKEN_FROSTMOURNE); - events.ScheduleEvent(EVENT_OUTRO_TALK_6, 2500ms, 0, PHASE_OUTRO); - break; - case ACTION_FINISH_OUTRO: - events.ScheduleEvent(EVENT_OUTRO_TALK_7, 7s, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_TALK_8, 17s, 0, PHASE_OUTRO); - break; - case ACTION_TELEPORT_BACK: - { - EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE); - summons.DoAction(ACTION_TELEPORT_BACK, pred); - if (!IsHeroic()) - Talk(SAY_LK_FROSTMOURNE_ESCAPE); - break; - } - default: - break; - } - } + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_PLAGUE_STACK: + return _necroticPlagueStack; + case DATA_VILE: + return _vileSpiritExplosions; + default: + break; + } - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_PLAGUE_STACK: - return _necroticPlagueStack; - case DATA_VILE: - return _vileSpiritExplosions; - default: - break; - } + return 0; + } - return 0; - } + void SetData(uint32 type, uint32 value) override + { + switch (type) + { + case DATA_PLAGUE_STACK: + _necroticPlagueStack = std::max(value, _necroticPlagueStack); + break; + case DATA_VILE: + _vileSpiritExplosions += value; + break; + default: + break; + } + } - void SetData(uint32 type, uint32 value) override - { - switch (type) - { - case DATA_PLAGUE_STACK: - _necroticPlagueStack = std::max(value, _necroticPlagueStack); - break; - case DATA_VILE: - _vileSpiritExplosions += value; - break; - default: - break; - } - } + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override + { + if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(70)) + { + events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->InterruptNonMeleeSpells(true); + me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition); + return; + } - void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override - { - if (events.IsInPhase(PHASE_ONE) && !HealthAbovePct(70)) - { - events.SetPhase(PHASE_TRANSITION); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - me->InterruptNonMeleeSpells(true); - me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition); - return; - } + if (events.IsInPhase(PHASE_TWO) && !HealthAbovePct(40)) + { + events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->InterruptNonMeleeSpells(true); + me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition); + return; + } - if (events.IsInPhase(PHASE_TWO) && !HealthAbovePct(40)) - { - events.SetPhase(PHASE_TRANSITION); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - me->InterruptNonMeleeSpells(true); - me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition); - return; - } + if (events.IsInPhase(PHASE_THREE) && !HealthAbovePct(10)) + { + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + events.Reset(); + events.SetPhase(PHASE_OUTRO); + summons.DespawnAll(); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FURY_OF_FROSTMOURNE); + me->InterruptNonMeleeSpells(true); + me->CastSpell(nullptr, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); + me->SetWalk(true); + events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 17600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 27600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_TALK_2, 34600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_TALK_3, 43600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 54600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 58600ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_MOVE_CENTER, 69600ms, 0, PHASE_OUTRO); + // stop here. rest will get scheduled from MovementInform + return; + } + } - if (events.IsInPhase(PHASE_THREE) && !HealthAbovePct(10)) + void JustSummoned(Creature* summon) override + { + switch (summon->GetEntry()) + { + case NPC_SHAMBLING_HORROR: + case NPC_DRUDGE_GHOUL: + summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true); + summon->SetReactState(REACT_PASSIVE); + summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + summon->m_Events.AddEvent(new LichKingStartMovementEvent(me, summon), summon->m_Events.CalculateTime(5s)); + break; + case NPC_SHADOW_TRAP: + summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true); + break; + case NPC_ICE_SPHERE: + { + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) { - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - events.Reset(); - events.SetPhase(PHASE_OUTRO); - summons.DespawnAll(); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FURY_OF_FROSTMOURNE); - me->InterruptNonMeleeSpells(true); - me->CastSpell(nullptr, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); - me->SetWalk(true); - events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 17600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 27600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_TALK_2, 34600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_TALK_3, 43600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 54600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 58600ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_MOVE_CENTER, 69600ms, 0, PHASE_OUTRO); - // stop here. rest will get scheduled from MovementInform - return; + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_ICE_SPHERE, false); + summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false); + summon->CastSpell(target, SPELL_ICE_PULSE, false); + summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f); } - } - - void JustSummoned(Creature* summon) override - { - switch (summon->GetEntry()) - { - case NPC_SHAMBLING_HORROR: - case NPC_DRUDGE_GHOUL: - summon->CastSpell(summon, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true); - summon->SetReactState(REACT_PASSIVE); - summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); - summon->m_Events.AddEvent(new LichKingStartMovementEvent(me, summon), summon->m_Events.CalculateTime(5s)); - break; - case NPC_SHADOW_TRAP: - summon->CastSpell(summon, SPELL_SHADOW_TRAP_VISUAL, true); - break; - case NPC_ICE_SPHERE: - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - summon->SetReactState(REACT_PASSIVE); - summon->CastSpell(summon, SPELL_ICE_SPHERE, false); - summon->CastSpell(summon, SPELL_ICE_BURST_TARGET_SEARCH, false); - summon->CastSpell(target, SPELL_ICE_PULSE, false); - summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f); - } - else - summon->DespawnOrUnsummon(); - break; - } - case NPC_DEFILE: - summon->SetReactState(REACT_PASSIVE); - summon->CastSpell(summon, SPELL_DEFILE_AURA, false); - break; - case NPC_FROSTMOURNE_TRIGGER: - { - summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true); + else + summon->DespawnOrUnsummon(); + break; + } + case NPC_DEFILE: + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_DEFILE_AURA, false); + break; + case NPC_FROSTMOURNE_TRIGGER: + { + summon->CastSpell(nullptr, SPELL_BROKEN_FROSTMOURNE, true); + + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_SOULSTORM, 10000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_BLACKSNOW, 0.5f); + + events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5s, 0, PHASE_OUTRO); + return; + } + case NPC_VILE_SPIRIT: + { + summons.Summon(summon); + summon->SetReactState(REACT_PASSIVE); + summon->SetSpeedRate(MOVE_FLIGHT, 0.5f); + summon->GetMotionMaster()->MoveRandom(10.0f); + if (!events.IsInPhase(PHASE_FROSTMOURNE)) + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s)); + return; + } + case NPC_STRANGULATE_VEHICLE: + summons.Summon(summon); + return; + case NPC_HIGHLORD_TIRION_FORDRING_LK: + return; + default: + break; + } - me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_SOULSTORM, 10000); - me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_BLACKSNOW, 0.5f); + BossAI::JustSummoned(summon); + } - events.ScheduleEvent(EVENT_OUTRO_SOUL_BARRAGE, 5s, 0, PHASE_OUTRO); - return; - } - case NPC_VILE_SPIRIT: - { - summons.Summon(summon); - summon->SetReactState(REACT_PASSIVE); - summon->SetSpeedRate(MOVE_FLIGHT, 0.5f); - summon->GetMotionMaster()->MoveRandom(10.0f); - if (!events.IsInPhase(PHASE_FROSTMOURNE)) - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15s)); - return; - } - case NPC_STRANGULATE_VEHICLE: - summons.Summon(summon); - return; - case NPC_HIGHLORD_TIRION_FORDRING_LK: - return; - default: - break; - } + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + switch (summon->GetEntry()) + { + case NPC_SHAMBLING_HORROR: + case NPC_DRUDGE_GHOUL: + case NPC_ICE_SPHERE: + case NPC_VALKYR_SHADOWGUARD: + case NPC_RAGING_SPIRIT: + case NPC_VILE_SPIRIT: + summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); + break; + default: + break; + } + } - BossAI::JustSummoned(summon); - } + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic()) + Talk(SAY_LK_FROSTMOURNE_KILL); - void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override - { - switch (summon->GetEntry()) - { - case NPC_SHAMBLING_HORROR: - case NPC_DRUDGE_GHOUL: - case NPC_ICE_SPHERE: - case NPC_VALKYR_SHADOWGUARD: - case NPC_RAGING_SPIRIT: - case NPC_VILE_SPIRIT: - summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); - break; - default: - break; - } - } + if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2) + { + me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_SNOWSTORM, 5000); + me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_LIGHT_SNOW, 0.5f); + summons.DespawnEntry(NPC_SHADOW_TRAP); + } + } - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_HARVESTED_SOUL && me->IsInCombat() && !IsHeroic()) - Talk(SAY_LK_FROSTMOURNE_KILL); + void MovementInform(uint32 type, uint32 pointId) override + { + if (type != POINT_MOTION_TYPE) + return; + + switch (pointId) + { + case POINT_LK_INTRO_1: + // schedule for next update cycle, current update must finalize movement + events.ScheduleEvent(EVENT_INTRO_MOVE_2, 1ms, 0, PHASE_INTRO); + break; + case POINT_LK_INTRO_2: + events.ScheduleEvent(EVENT_INTRO_MOVE_3, 1ms, 0, PHASE_INTRO); + break; + case POINT_LK_INTRO_3: + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->AI()->DoAction(ACTION_CONTINUE_INTRO); + events.ScheduleEvent(EVENT_INTRO_TALK_1, 9s, 0, PHASE_INTRO); + break; + case POINT_CENTER_1: + me->SetFacingTo(0.0f); + Talk(SAY_LK_REMORSELESS_WINTER); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + DoCastSelf(SPELL_REMORSELESS_WINTER_1); + events.ScheduleEvent(EVENT_QUAKE, 62500ms, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 6s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_VALKYR, 78s, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_INFEST, 70s, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_DEFILE, 97s, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_SOUL_REAPER, 94s, 0, PHASE_TWO); + break; + case POINT_CENTER_2: + me->SetFacingTo(0.0f); + Talk(SAY_LK_REMORSELESS_WINTER); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + DoCastSelf(SPELL_REMORSELESS_WINTER_2); + summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); + events.ScheduleEvent(EVENT_QUAKE_2, 62500ms, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT_2, 5s, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_DEFILE, 95500ms, 0, PHASE_THREE); + events.ScheduleEvent(EVENT_SOUL_REAPER, 99500ms, 0, PHASE_THREE); + events.ScheduleEvent(EVENT_VILE_SPIRITS, 79500ms, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); + events.ScheduleEvent(IsHeroic() ? EVENT_HARVEST_SOULS : EVENT_HARVEST_SOUL, 73500ms, 0, PHASE_THREE); + break; + case POINT_LK_OUTRO_1: + events.ScheduleEvent(EVENT_OUTRO_TALK_4, 1ms, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_RAISE_DEAD, 1s, 0, PHASE_OUTRO); + events.ScheduleEvent(EVENT_OUTRO_TALK_5, 29s, 0, PHASE_OUTRO); + break; + case POINT_LK_OUTRO_2: + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->AI()->Talk(SAY_TIRION_OUTRO_2); + if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) + frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS); + break; + default: + break; + } + } - if (spellInfo->Id == REMORSELESS_WINTER_1 || spellInfo->Id == REMORSELESS_WINTER_2) - { - me->GetMap()->SetZoneOverrideLight(AREA_ICECROWN_CITADEL, LIGHT_DEFAULT, LIGHT_SNOWSTORM, 5000); - me->GetMap()->SetZoneWeather(AREA_ICECROWN_CITADEL, WEATHER_STATE_LIGHT_SNOW, 0.5f); - summons.DespawnEntry(NPC_SHADOW_TRAP); - } - } + void UpdateAI(uint32 diff) override + { + // check phase first to prevent updating victim and entering evade mode when not wanted + if (!(events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_INTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) + if (!UpdateVictim()) + return; - void MovementInform(uint32 type, uint32 pointId) override - { - if (type != POINT_MOTION_TYPE) - return; + events.Update(diff); - switch (pointId) - { - case POINT_LK_INTRO_1: - // schedule for next update cycle, current update must finalize movement - events.ScheduleEvent(EVENT_INTRO_MOVE_2, 1ms, 0, PHASE_INTRO); - break; - case POINT_LK_INTRO_2: - events.ScheduleEvent(EVENT_INTRO_MOVE_3, 1ms, 0, PHASE_INTRO); - break; - case POINT_LK_INTRO_3: - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->AI()->DoAction(ACTION_CONTINUE_INTRO); - events.ScheduleEvent(EVENT_INTRO_TALK_1, 9s, 0, PHASE_INTRO); - break; - case POINT_CENTER_1: - me->SetFacingTo(0.0f); - Talk(SAY_LK_REMORSELESS_WINTER); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - DoCast(me, SPELL_REMORSELESS_WINTER_1); - events.ScheduleEvent(EVENT_QUAKE, 62500ms, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 4s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 6s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_VALKYR, 78s, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_INFEST, 70s, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_DEFILE, 97s, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_SOUL_REAPER, 94s, 0, PHASE_TWO); - break; - case POINT_CENTER_2: - me->SetFacingTo(0.0f); - Talk(SAY_LK_REMORSELESS_WINTER); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - DoCast(me, SPELL_REMORSELESS_WINTER_2); - summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); - events.ScheduleEvent(EVENT_QUAKE_2, 62500ms, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 6s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 8s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT_2, 5s, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_DEFILE, 95500ms, 0, PHASE_THREE); - events.ScheduleEvent(EVENT_SOUL_REAPER, 99500ms, 0, PHASE_THREE); - events.ScheduleEvent(EVENT_VILE_SPIRITS, 79500ms, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); - events.ScheduleEvent(IsHeroic() ? EVENT_HARVEST_SOULS : EVENT_HARVEST_SOUL, 73500ms, 0, PHASE_THREE); - break; - case POINT_LK_OUTRO_1: - events.ScheduleEvent(EVENT_OUTRO_TALK_4, 1ms, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_RAISE_DEAD, 1s, 0, PHASE_OUTRO); - events.ScheduleEvent(EVENT_OUTRO_TALK_5, 29s, 0, PHASE_OUTRO); - break; - case POINT_LK_OUTRO_2: - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->AI()->Talk(SAY_TIRION_OUTRO_2); - if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) - frostmourne->AI()->DoAction(ACTION_SUMMON_TERENAS); - break; - default: - break; - } - } + // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells + if (me->HasUnitState(UNIT_STATE_CASTING) && !(events.IsInPhase(PHASE_TRANSITION) || events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) + return; - void UpdateAI(uint32 diff) override + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - // check phase first to prevent updating victim and entering evade mode when not wanted - if (!(events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_INTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) - if (!UpdateVictim()) - return; - - events.Update(diff); - - // during Remorseless Winter phases The Lich King is channeling a spell, but we must continue casting other spells - if (me->HasUnitState(UNIT_STATE_CASTING) && !(events.IsInPhase(PHASE_TRANSITION) || events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + case EVENT_INTRO_MOVE_1: + me->SetSheath(SHEATH_STATE_MELEE); + me->RemoveAurasDueToSpell(SPELL_EMOTE_SIT_NO_SHEATH); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_1, LichKingIntro[0]); + break; + case EVENT_INTRO_MOVE_2: + me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_2, LichKingIntro[1]); + break; + case EVENT_INTRO_MOVE_3: + me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_3, LichKingIntro[2]); + break; + case EVENT_INTRO_TALK_1: + Talk(SAY_LK_INTRO_2); + // for some reason blizz sends 2 emotes in row here so (we handle one in Talk) + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 7s, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 13s, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 18s, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_CAST_FREEZE, 31s, 0, PHASE_INTRO); + break; + case EVENT_EMOTE_CAST_SHOUT: + DoCastSelf(SPELL_EMOTE_SHOUT_NO_SHEATH, false); + break; + case EVENT_INTRO_EMOTE_1: + me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE); + break; + case EVENT_INTRO_CAST_FREEZE: + Talk(SAY_LK_INTRO_3); + DoCastAOE(SPELL_ICE_LOCK, false); + events.ScheduleEvent(EVENT_FINISH_INTRO, 1s, 0, PHASE_INTRO); + break; + case EVENT_FINISH_INTRO: + me->SetWalk(false); + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + events.SetPhase(PHASE_ONE); + DoZoneInCombat(); + break; + case EVENT_SUMMON_SHAMBLING_HORROR: + DoCastSelf(SPELL_SUMMON_SHAMBLING_HORROR); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 1min, 0, PHASE_ONE); + break; + case EVENT_SUMMON_DRUDGE_GHOUL: + DoCastSelf(SPELL_SUMMON_DRUDGE_GHOULS); + events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 30s, 0, PHASE_ONE); + break; + case EVENT_INFEST: + DoCastSelf(SPELL_INFEST); + events.ScheduleEvent(EVENT_INFEST, 21s, 24s, 0, events.IsInPhase(PHASE_ONE) ? PHASE_ONE : PHASE_TWO); + break; + case EVENT_NECROTIC_PLAGUE: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, NecroticPlagueTargetCheck(me, NECROTIC_PLAGUE_LK, NECROTIC_PLAGUE_PLR))) { - case EVENT_INTRO_MOVE_1: - me->SetSheath(SHEATH_STATE_MELEE); - me->RemoveAurasDueToSpell(SPELL_EMOTE_SIT_NO_SHEATH); - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_1, LichKingIntro[0]); - break; - case EVENT_INTRO_MOVE_2: - me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_2, LichKingIntro[1]); - break; - case EVENT_INTRO_MOVE_3: - me->GetMotionMaster()->MovePoint(POINT_LK_INTRO_3, LichKingIntro[2]); - break; - case EVENT_INTRO_TALK_1: - Talk(SAY_LK_INTRO_2); - // for some reason blizz sends 2 emotes in row here so (we handle one in Talk) - me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); - events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 7s, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 13s, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_EMOTE_CAST_SHOUT, 18s, 0, PHASE_INTRO); - events.ScheduleEvent(EVENT_INTRO_CAST_FREEZE, 31s, 0, PHASE_INTRO); - break; - case EVENT_EMOTE_CAST_SHOUT: - DoCast(me, SPELL_EMOTE_SHOUT_NO_SHEATH, false); - break; - case EVENT_INTRO_EMOTE_1: - me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE); - break; - case EVENT_INTRO_CAST_FREEZE: - Talk(SAY_LK_INTRO_3); - DoCastAOE(SPELL_ICE_LOCK, false); - events.ScheduleEvent(EVENT_FINISH_INTRO, 1s, 0, PHASE_INTRO); - break; - case EVENT_FINISH_INTRO: - me->SetWalk(false); - me->SetImmuneToPC(false); - me->SetReactState(REACT_AGGRESSIVE); - events.SetPhase(PHASE_ONE); - break; - case EVENT_SUMMON_SHAMBLING_HORROR: - DoCast(me, SPELL_SUMMON_SHAMBLING_HORROR); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - events.ScheduleEvent(EVENT_SUMMON_SHAMBLING_HORROR, 1min, 0, PHASE_ONE); - break; - case EVENT_SUMMON_DRUDGE_GHOUL: - DoCast(me, SPELL_SUMMON_DRUDGE_GHOULS); - events.ScheduleEvent(EVENT_SUMMON_DRUDGE_GHOUL, 30s, 0, PHASE_ONE); - break; - case EVENT_INFEST: - DoCast(me, SPELL_INFEST); - events.ScheduleEvent(EVENT_INFEST, 21s, 24s, 0, events.IsInPhase(PHASE_ONE) ? PHASE_ONE : PHASE_TWO); - break; - case EVENT_NECROTIC_PLAGUE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, NecroticPlagueTargetCheck(me, NECROTIC_PLAGUE_LK, NECROTIC_PLAGUE_PLR))) - { - Talk(EMOTE_NECROTIC_PLAGUE_WARNING, target); - DoCast(target, SPELL_NECROTIC_PLAGUE); - } - events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 30s, 33s, 0, PHASE_ONE); - break; - case EVENT_SHADOW_TRAP: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, SpellTargetSelector(me, SPELL_SHADOW_TRAP))) - DoCast(target, SPELL_SHADOW_TRAP); - events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500ms, 0, PHASE_ONE); - break; - case EVENT_SOUL_REAPER: - DoCastVictim(SPELL_SOUL_REAPER); - events.ScheduleEvent(EVENT_SOUL_REAPER, 33s, 35s, 0, PHASE_TWO_THREE); - break; - case EVENT_DEFILE: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR)) - { - Talk(EMOTE_DEFILE_WARNING); - DoCast(target, SPELL_DEFILE); - } - events.ScheduleEvent(EVENT_DEFILE, 32s, 35s, 0, PHASE_TWO_THREE); - break; - case EVENT_HARVEST_SOUL: - Talk(SAY_LK_HARVEST_SOUL); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, SpellTargetSelector(me, SPELL_HARVEST_SOUL))) - DoCast(target, SPELL_HARVEST_SOUL); - events.ScheduleEvent(EVENT_HARVEST_SOUL, 75s, 0, PHASE_THREE); - break; - case EVENT_PAIN_AND_SUFFERING: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - me->CastSpell(target, SPELL_PAIN_AND_SUFFERING, TRIGGERED_NONE); - events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 1500ms, 4s, 0, PHASE_TRANSITION); - break; - case EVENT_SUMMON_ICE_SPHERE: - DoCastAOE(SPELL_SUMMON_ICE_SPHERE); - events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 7500ms, 8500ms, 0, PHASE_TRANSITION); - break; - case EVENT_SUMMON_RAGING_SPIRIT: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 22s, 23s, 0, PHASE_TRANSITION); - break; - case EVENT_SUMMON_RAGING_SPIRIT_2: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); - events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 18s, 0, PHASE_TRANSITION); - break; - case EVENT_QUAKE: - events.SetPhase(PHASE_TWO); - me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes - DoCastAOE(SPELL_QUAKE); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - Talk(SAY_LK_QUAKE); - break; - case EVENT_QUAKE_2: - events.SetPhase(PHASE_THREE); - me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes - DoCastAOE(SPELL_QUAKE); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - Talk(SAY_LK_QUAKE); - break; - case EVENT_SUMMON_VALKYR: - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - Talk(SAY_LK_SUMMON_VALKYR); - DoCastAOE(SUMMON_VALKYR, true); - events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45s, 50s, 0, PHASE_TWO); - break; - case EVENT_START_ATTACK: - me->SetReactState(REACT_AGGRESSIVE); - if (events.IsInPhase(PHASE_FROSTMOURNE)) - events.SetPhase(PHASE_THREE); - break; - case EVENT_VILE_SPIRITS: - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); - DoCastAOE(SPELL_VILE_SPIRITS); - events.ScheduleEvent(EVENT_VILE_SPIRITS, 35s, 40s, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); - break; - case EVENT_HARVEST_SOULS: - Talk(SAY_LK_HARVEST_SOUL); - DoCastAOE(SPELL_HARVEST_SOULS); - events.ScheduleEvent(EVENT_HARVEST_SOULS, 100s, 110s, 0, PHASE_THREE); - events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading) - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - events.DelayEvents(50s, EVENT_GROUP_VILE_SPIRITS); - events.RescheduleEvent(EVENT_DEFILE, 50s, 0, PHASE_THREE); - events.RescheduleEvent(EVENT_SOUL_REAPER, 57s, 62s, 0, PHASE_THREE); - events.ScheduleEvent(EVENT_START_ATTACK, 49s); - events.ScheduleEvent(EVENT_FROSTMOURNE_HEROIC, 6500ms); - for (ObjectGuid guid : summons) - { - if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) - { - if (summon->GetEntry() == NPC_VILE_SPIRIT) - { - summon->m_Events.KillAllEvents(true); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms)); - summon->SetReactState(REACT_PASSIVE); - summon->CombatStop(true); - summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH); - summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH); - summon->GetMotionMaster()->MoveTargetedHome(); - } - else if (summon->GetEntry() == NPC_RAGING_SPIRIT) - summon->AI()->DoAction(ACTION_DISABLE_RAGING); - } - } - break; - case EVENT_FROSTMOURNE_HEROIC: - if (TempSummon* terenas = me->GetMap()->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE_H, TerenasSpawnHeroic, nullptr, 50000)) + Talk(EMOTE_NECROTIC_PLAGUE_WARNING, target); + DoCast(target, SPELL_NECROTIC_PLAGUE); + } + events.ScheduleEvent(EVENT_NECROTIC_PLAGUE, 30s, 33s, 0, PHASE_ONE); + break; + case EVENT_SHADOW_TRAP: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, SpellTargetSelector(me, SPELL_SHADOW_TRAP))) + DoCast(target, SPELL_SHADOW_TRAP); + events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500ms, 0, PHASE_ONE); + break; + case EVENT_SOUL_REAPER: + DoCastVictim(SPELL_SOUL_REAPER); + events.ScheduleEvent(EVENT_SOUL_REAPER, 33s, 35s, 0, PHASE_TWO_THREE); + break; + case EVENT_DEFILE: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR)) + { + Talk(EMOTE_DEFILE_WARNING); + DoCast(target, SPELL_DEFILE); + } + events.ScheduleEvent(EVENT_DEFILE, 32s, 35s, 0, PHASE_TWO_THREE); + break; + case EVENT_HARVEST_SOUL: + Talk(SAY_LK_HARVEST_SOUL); + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, SpellTargetSelector(me, SPELL_HARVEST_SOUL))) + DoCast(target, SPELL_HARVEST_SOUL); + events.ScheduleEvent(EVENT_HARVEST_SOUL, 75s, 0, PHASE_THREE); + break; + case EVENT_PAIN_AND_SUFFERING: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) + me->CastSpell(target, SPELL_PAIN_AND_SUFFERING, TRIGGERED_NONE); + events.ScheduleEvent(EVENT_PAIN_AND_SUFFERING, 1500ms, 4s, 0, PHASE_TRANSITION); + break; + case EVENT_SUMMON_ICE_SPHERE: + DoCastAOE(SPELL_SUMMON_ICE_SPHERE); + events.ScheduleEvent(EVENT_SUMMON_ICE_SPHERE, 7500ms, 8500ms, 0, PHASE_TRANSITION); + break; + case EVENT_SUMMON_RAGING_SPIRIT: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) + me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 22s, 23s, 0, PHASE_TRANSITION); + break; + case EVENT_SUMMON_RAGING_SPIRIT_2: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) + me->CastSpell(target, SPELL_RAGING_SPIRIT, TRIGGERED_NONE); + events.ScheduleEvent(EVENT_SUMMON_RAGING_SPIRIT, 18s, 0, PHASE_TRANSITION); + break; + case EVENT_QUAKE: + events.SetPhase(PHASE_TWO); + me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes + DoCastAOE(SPELL_QUAKE); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + Talk(SAY_LK_QUAKE); + break; + case EVENT_QUAKE_2: + events.SetPhase(PHASE_THREE); + me->ClearUnitState(UNIT_STATE_CASTING); // clear state to ensure check in DoCastAOE passes + DoCastAOE(SPELL_QUAKE); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + Talk(SAY_LK_QUAKE); + break; + case EVENT_SUMMON_VALKYR: + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + Talk(SAY_LK_SUMMON_VALKYR); + DoCastAOE(SUMMON_VALKYR, true); + events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45s, 50s, 0, PHASE_TWO); + break; + case EVENT_START_ATTACK: + me->SetReactState(REACT_AGGRESSIVE); + if (events.IsInPhase(PHASE_FROSTMOURNE)) + events.SetPhase(PHASE_THREE); + break; + case EVENT_VILE_SPIRITS: + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_SPECIAL); + DoCastAOE(SPELL_VILE_SPIRITS); + events.ScheduleEvent(EVENT_VILE_SPIRITS, 35s, 40s, EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); + break; + case EVENT_HARVEST_SOULS: + Talk(SAY_LK_HARVEST_SOUL); + DoCastAOE(SPELL_HARVEST_SOULS); + events.ScheduleEvent(EVENT_HARVEST_SOULS, 100s, 110s, 0, PHASE_THREE); + events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading) + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + events.DelayEvents(50s, EVENT_GROUP_VILE_SPIRITS); + events.RescheduleEvent(EVENT_DEFILE, 50s, 0, PHASE_THREE); + events.RescheduleEvent(EVENT_SOUL_REAPER, 57s, 62s, 0, PHASE_THREE); + events.ScheduleEvent(EVENT_START_ATTACK, 49s); + events.ScheduleEvent(EVENT_FROSTMOURNE_HEROIC, 6500ms); + for (ObjectGuid guid : summons) + { + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + { + if (summon->GetEntry() == NPC_VILE_SPIRIT) { - terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO); - std::list<Creature*> triggers; - GetCreatureListWithEntryInGrid(triggers, terenas, NPC_WORLD_TRIGGER_INFINITE_AOI, 100.0f); - if (!triggers.empty()) - { - triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true)); - Creature* spawner = triggers.front(); - spawner->setActive(true); - spawner->SetFarVisible(true); - spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly - spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players - spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s)); - } + summon->m_Events.KillAllEvents(true); + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(56500ms)); + summon->SetReactState(REACT_PASSIVE); + summon->CombatStop(true); + summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_MOVE_SEARCH); + summon->RemoveAurasDueToSpell(SPELL_VILE_SPIRIT_DAMAGE_SEARCH); + summon->GetMotionMaster()->MoveTargetedHome(); } - break; - case EVENT_OUTRO_TALK_1: - Talk(SAY_LK_OUTRO_1); - DoCastAOE(SPELL_FURY_OF_FROSTMOURNE_NO_REZ, true); - break; - case EVENT_OUTRO_TALK_2: - Talk(SAY_LK_OUTRO_2); - DoCastAOE(SPELL_EMOTE_QUESTION_NO_SHEATH); - break; - case EVENT_OUTRO_EMOTE_TALK: - me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); - break; - case EVENT_OUTRO_TALK_3: - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - me->SetFacingToObject(tirion); - Talk(SAY_LK_OUTRO_3); - break; - case EVENT_OUTRO_MOVE_CENTER: - me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_1, CenterPosition); - break; - case EVENT_OUTRO_TALK_4: - me->SetFacingTo(0.01745329f); - Talk(SAY_LK_OUTRO_4); - break; - case EVENT_OUTRO_RAISE_DEAD: - DoCastAOE(SPELL_RAISE_DEAD); - me->ClearUnitState(UNIT_STATE_CASTING); - me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); - break; - case EVENT_OUTRO_TALK_5: - Talk(SAY_LK_OUTRO_5); - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->AI()->DoAction(ACTION_OUTRO); - break; - case EVENT_OUTRO_TALK_6: - Talk(SAY_LK_OUTRO_6); - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->SetFacingToObject(me); - me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_3, TRIGGERED_IGNORE_CAST_IN_PROGRESS); - SetEquipmentSlots(false, EQUIP_UNEQUIP); - break; - case EVENT_OUTRO_SOUL_BARRAGE: - me->CastSpell(nullptr, SPELL_SOUL_BARRAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); - CreatureTextMgr::SendSound(me, SOUND_PAIN, CHAT_MSG_MONSTER_YELL); - // set flight - me->SetDisableGravity(true); - me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); - me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_2, OutroFlying); - break; - case EVENT_OUTRO_TALK_7: - Talk(SAY_LK_OUTRO_7); - break; - case EVENT_OUTRO_TALK_8: - Talk(SAY_LK_OUTRO_8); - break; - case EVENT_BERSERK: - Talk(SAY_LK_BERSERK); - DoCast(me, SPELL_BERSERK2); - break; - default: - break; + else if (summon->GetEntry() == NPC_RAGING_SPIRIT) + summon->AI()->DoAction(ACTION_DISABLE_RAGING); + } } - - if (me->HasUnitState(UNIT_STATE_CASTING) && !(events.IsInPhase(PHASE_TRANSITION) || events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) - return; - } - - DoMeleeAttackIfReady(); + break; + case EVENT_FROSTMOURNE_HEROIC: + if (TempSummon* terenas = me->GetMap()->SummonCreature(NPC_TERENAS_MENETHIL_FROSTMOURNE_H, TerenasSpawnHeroic, nullptr, 50000)) + { + terenas->AI()->DoAction(ACTION_FROSTMOURNE_INTRO); + std::list<Creature*> triggers; + GetCreatureListWithEntryInGrid(triggers, terenas, NPC_WORLD_TRIGGER_INFINITE_AOI, 100.0f); + if (!triggers.empty()) + { + triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true)); + Creature* spawner = triggers.front(); + spawner->setActive(true); + spawner->SetFarVisible(true); + spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly + spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players + spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3s)); + } + } + break; + case EVENT_OUTRO_TALK_1: + Talk(SAY_LK_OUTRO_1); + DoCastAOE(SPELL_FURY_OF_FROSTMOURNE_NO_REZ, true); + break; + case EVENT_OUTRO_TALK_2: + Talk(SAY_LK_OUTRO_2); + DoCastAOE(SPELL_EMOTE_QUESTION_NO_SHEATH); + break; + case EVENT_OUTRO_EMOTE_TALK: + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + break; + case EVENT_OUTRO_TALK_3: + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + me->SetFacingToObject(tirion); + Talk(SAY_LK_OUTRO_3); + break; + case EVENT_OUTRO_MOVE_CENTER: + me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_1, CenterPosition); + break; + case EVENT_OUTRO_TALK_4: + me->SetFacingTo(0.01745329f); + Talk(SAY_LK_OUTRO_4); + break; + case EVENT_OUTRO_RAISE_DEAD: + DoCastAOE(SPELL_RAISE_DEAD); + me->ClearUnitState(UNIT_STATE_CASTING); + me->GetMap()->SetZoneMusic(AREA_ICECROWN_CITADEL, MUSIC_FINAL); + break; + case EVENT_OUTRO_TALK_5: + Talk(SAY_LK_OUTRO_5); + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->AI()->DoAction(ACTION_OUTRO); + break; + case EVENT_OUTRO_TALK_6: + Talk(SAY_LK_OUTRO_6); + if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->SetFacingToObject(me); + me->CastSpell(nullptr, SPELL_SUMMON_BROKEN_FROSTMOURNE_3, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + SetEquipmentSlots(false, EQUIP_UNEQUIP); + break; + case EVENT_OUTRO_SOUL_BARRAGE: + me->CastSpell(nullptr, SPELL_SOUL_BARRAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + CreatureTextMgr::SendSound(me, SOUND_PAIN, CHAT_MSG_MONSTER_YELL, 0, TEXT_RANGE_NORMAL, TEAM_OTHER, false); + // set flight + me->SetDisableGravity(true); + me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); + me->GetMotionMaster()->MovePoint(POINT_LK_OUTRO_2, OutroFlying); + break; + case EVENT_OUTRO_TALK_7: + Talk(SAY_LK_OUTRO_7); + break; + case EVENT_OUTRO_TALK_8: + Talk(SAY_LK_OUTRO_8); + break; + case EVENT_BERSERK: + Talk(SAY_LK_BERSERK); + DoCastSelf(SPELL_BERSERK2); + break; + default: + break; } - private: - uint32 _necroticPlagueStack; - uint32 _vileSpiritExplosions; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<boss_the_lich_kingAI>(creature); + if (me->HasUnitState(UNIT_STATE_CASTING) && !(events.IsInPhase(PHASE_TRANSITION) || events.IsInPhase(PHASE_OUTRO) || events.IsInPhase(PHASE_FROSTMOURNE))) + return; } -}; -class npc_tirion_fordring_tft : public CreatureScript -{ - public: - npc_tirion_fordring_tft() : CreatureScript("npc_tirion_fordring_tft") { } + DoMeleeAttackIfReady(); + } - struct npc_tirion_fordringAI : public ScriptedAI - { - npc_tirion_fordringAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } +private: + uint32 _necroticPlagueStack; + uint32 _vileSpiritExplosions; +}; - void Reset() override - { - _events.Reset(); - if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE) - me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); - me->LoadEquipment(1); - } +struct npc_tirion_fordring_tft : public ScriptedAI +{ + npc_tirion_fordring_tft(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; + void Reset() override + { + _events.Reset(); + if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE) + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); + } - switch (id) - { - case POINT_TIRION_INTRO: - me->SetEmoteState(EMOTE_STATE_READY2H); - if (Creature* theLichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER); - break; - case POINT_TIRION_OUTRO_1: - _events.ScheduleEvent(EVENT_OUTRO_JUMP, 1ms, 0, PHASE_OUTRO); - break; - } - } + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + return; + + switch (id) + { + case POINT_TIRION_INTRO: + me->SetEmoteState(EMOTE_STATE_READY2H); + if (Creature* theLichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + theLichKing->AI()->DoAction(ACTION_START_ENCOUNTER); + break; + case POINT_TIRION_OUTRO_1: + _events.ScheduleEvent(EVENT_OUTRO_JUMP, 1ms, 0, PHASE_OUTRO); + break; + } + } - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_CONTINUE_INTRO: - Talk(SAY_TIRION_INTRO_1); - _events.ScheduleEvent(EVENT_INTRO_TALK_1, 34s, 0, PHASE_INTRO); - break; - case ACTION_OUTRO: - _events.SetPhase(PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_TALK_1, 7s, 0, PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_BLESS, 18s, 0, PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_REMOVE_ICE, 23s, 0, PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_MOVE_1, 25s, 0, PHASE_OUTRO); - break; - } - } + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CONTINUE_INTRO: + Talk(SAY_TIRION_INTRO_1); + _events.ScheduleEvent(EVENT_INTRO_TALK_1, 34s, 0, PHASE_INTRO); + break; + case ACTION_OUTRO: + _events.SetPhase(PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_TALK_1, 7s, 0, PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_BLESS, 18s, 0, PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_REMOVE_ICE, 23s, 0, PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_MOVE_1, 25s, 0, PHASE_OUTRO); + break; + } + } - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_ICE_LOCK) - me->SetFacingTo(3.085098f); - else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK) - me->LoadEquipment(1); // remove glow on ashbringer - } + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_ICE_LOCK) + me->SetFacingTo(3.085098f); + else if (spellInfo->Id == SPELL_BROKEN_FROSTMOURNE_KNOCK) + me->LoadEquipment(1); // remove glow on ashbringer + } - bool GossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override - { - if (me->GetCreatureTemplate()->GossipMenuId == menuId && !gossipListId) - { - _events.SetPhase(PHASE_INTRO); - me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_TIRION_INTRO, TirionIntro); - } - return false; - } + bool GossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override + { + if (me->GetCreatureTemplate()->GossipMenuId == menuId && !gossipListId) + { + _events.SetPhase(PHASE_INTRO); + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_TIRION_INTRO, TirionIntro); + } + return false; + } - void JustReachedHome() override - { - me->SetEmoteState(EMOTE_ONESHOT_NONE); - } + void JustReachedHome() override + { + me->SetEmoteState(EMOTE_ONESHOT_NONE); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && !(_events.IsInPhase(PHASE_OUTRO) || _events.IsInPhase(PHASE_INTRO))) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !(_events.IsInPhase(PHASE_OUTRO) || _events.IsInPhase(PHASE_INTRO))) + return; - _events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INTRO_TALK_1: + Talk(SAY_TIRION_INTRO_2); + _events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 2s, 0, PHASE_INTRO); + _events.ScheduleEvent(EVENT_INTRO_CHARGE, 5s, 0, PHASE_INTRO); + break; + case EVENT_INTRO_EMOTE_1: + me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE); + break; + case EVENT_INTRO_CHARGE: + me->SetWalk(false); + me->GetMotionMaster()->MovePoint(POINT_TIRION_CHARGE, TirionCharge); + break; + case EVENT_OUTRO_TALK_1: + Talk(SAY_TIRION_OUTRO_1); + break; + case EVENT_OUTRO_BLESS: + DoCastSelf(SPELL_LIGHTS_BLESSING); + break; + case EVENT_OUTRO_REMOVE_ICE: + me->RemoveAurasDueToSpell(SPELL_ICE_LOCK); + SetEquipmentSlots(false, EQUIP_ASHBRINGER_GLOWING); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) { - case EVENT_INTRO_TALK_1: - Talk(SAY_TIRION_INTRO_2); - _events.ScheduleEvent(EVENT_INTRO_EMOTE_1, 2s, 0, PHASE_INTRO); - _events.ScheduleEvent(EVENT_INTRO_CHARGE, 5s, 0, PHASE_INTRO); - break; - case EVENT_INTRO_EMOTE_1: - me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE); - break; - case EVENT_INTRO_CHARGE: - me->SetWalk(false); - me->GetMotionMaster()->MovePoint(POINT_TIRION_CHARGE, TirionCharge); - break; - case EVENT_OUTRO_TALK_1: - Talk(SAY_TIRION_OUTRO_1); - break; - case EVENT_OUTRO_BLESS: - DoCast(me, SPELL_LIGHTS_BLESSING); - break; - case EVENT_OUTRO_REMOVE_ICE: - me->RemoveAurasDueToSpell(SPELL_ICE_LOCK); - SetEquipmentSlots(false, EQUIP_ASHBRINGER_GLOWING); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - { - me->SetFacingToObject(lichKing); - lichKing->AI()->DoAction(ACTION_PLAY_MUSIC); - } - break; - case EVENT_OUTRO_MOVE_1: - me->GetMotionMaster()->MovePoint(POINT_TIRION_OUTRO_1, OutroPosition1); - break; - case EVENT_OUTRO_JUMP: - DoCastAOE(SPELL_JUMP); - break; - default: - break; + me->SetFacingToObject(lichKing); + lichKing->AI()->DoAction(ACTION_PLAY_MUSIC); } - } - - DoMeleeAttackIfReady(); + break; + case EVENT_OUTRO_MOVE_1: + me->GetMotionMaster()->MovePoint(POINT_TIRION_OUTRO_1, OutroPosition1); + break; + case EVENT_OUTRO_JUMP: + DoCastAOE(SPELL_JUMP); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_tirion_fordringAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; }; -class npc_shambling_horror_icc : public CreatureScript +struct npc_shambling_horror_icc : public ScriptedAI { - public: - npc_shambling_horror_icc() : CreatureScript("npc_shambling_horror_icc") { } - - struct npc_shambling_horror_iccAI : public ScriptedAI - { - npc_shambling_horror_iccAI(Creature* creature) : ScriptedAI(creature) - { - _frenzied = false; - } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_SHOCKWAVE, 20s, 25s); - _events.ScheduleEvent(EVENT_ENRAGE, 11s, 14s); - } + npc_shambling_horror_icc(Creature* creature) : ScriptedAI(creature) + { + _frenzied = false; + } - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage)) - { - _frenzied = true; - DoCast(me, SPELL_FRENZY, true); - } - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_SHOCKWAVE, 20s, 25s); + _events.ScheduleEvent(EVENT_ENRAGE, 11s, 14s); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (!_frenzied && IsHeroic() && me->HealthBelowPctDamaged(20, damage)) + { + _frenzied = true; + DoCastSelf(SPELL_FRENZY, true); + } + } - _events.Update(diff); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHOCKWAVE: - DoCast(me, SPELL_SHOCKWAVE); - _events.ScheduleEvent(EVENT_SHOCKWAVE, 20s, 25s); - break; - case EVENT_ENRAGE: - if (SPELL_CAST_OK != DoCast(me, SPELL_ENRAGE)) - _events.ScheduleEvent(EVENT_ENRAGE, 1s); - else - _events.ScheduleEvent(EVENT_ENRAGE, 20s, 25s); - break; - default: - break; - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - DoMeleeAttackIfReady(); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHOCKWAVE: + DoCastSelf(SPELL_SHOCKWAVE); + _events.ScheduleEvent(EVENT_SHOCKWAVE, 20s, 25s); + break; + case EVENT_ENRAGE: + if (SPELL_CAST_OK != DoCastSelf(SPELL_ENRAGE)) + _events.ScheduleEvent(EVENT_ENRAGE, 1s); + else + _events.ScheduleEvent(EVENT_ENRAGE, 20s, 25s); + break; + default: + break; } + } - void OnSpellCastInterrupt(SpellInfo const* spell) override - { - ScriptedAI::OnSpellCastInterrupt(spell); + DoMeleeAttackIfReady(); + } - // When enrage is interrupted, reschedule the event - if (spell->Id == ENRAGE) - _events.RescheduleEvent(EVENT_ENRAGE, 1s); - } + void OnSpellCastInterrupt(SpellInfo const* spell) override + { + ScriptedAI::OnSpellCastInterrupt(spell); - private: - EventMap _events; - bool _frenzied; - }; + // When enrage is interrupted, reschedule the event + if (spell->Id == ENRAGE) + _events.RescheduleEvent(EVENT_ENRAGE, 1s); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_shambling_horror_iccAI>(creature); - } +private: + EventMap _events; + bool _frenzied; }; -class npc_raging_spirit : public CreatureScript +struct npc_raging_spirit : public ScriptedAI { - public: - npc_raging_spirit() : CreatureScript("npc_raging_spirit") { } - - struct npc_raging_spiritAI : public ScriptedAI - { - npc_raging_spiritAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } + npc_raging_spirit(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - void Reset() override - { - me->SetReactState(REACT_PASSIVE); - _events.Reset(); - _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 2s); - _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); - DoCast(me, SPELL_PLAGUE_AVOIDANCE, true); - DoCast(me, SPELL_RAGING_SPIRIT_VISUAL, true); - if (TempSummon* summon = me->ToTempSummon()) - if (Unit* summoner = summon->GetSummonerUnit()) - summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true); - DoCast(me, SPELL_BOSS_HITTIN_YA, true); - } + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + _events.Reset(); + _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 2s); + _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); + DoCastSelf(SPELL_PLAGUE_AVOIDANCE, true); + DoCastSelf(SPELL_RAGING_SPIRIT_VISUAL, true); + if (TempSummon* summon = me->ToTempSummon()) + if (Unit* summoner = summon->GetSummonerUnit()) + summoner->CastSpell(me, SPELL_RAGING_SPIRIT_VISUAL_CLONE, true); + DoCastSelf(SPELL_BOSS_HITTIN_YA, true); + } - void DoAction(int32 action) override - { - if (action == ACTION_DISABLE_RAGING) - { - _events.Reset(); - _events.SetPhase(PHASE_FROSTMOURNE); - _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 52s); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - me->InterruptNonMeleeSpells(true); - } - } + void DoAction(int32 action) override + { + if (action == ACTION_DISABLE_RAGING) + { + _events.Reset(); + _events.SetPhase(PHASE_FROSTMOURNE); + _events.ScheduleEvent(EVENT_SET_AGRESSIVE, 52s); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->InterruptNonMeleeSpells(true); + } + } - void IsSummonedBy(WorldObject* /*summoner*/) override - { - // player is the spellcaster so register summon manually - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->JustSummoned(me); - } + void IsSummonedBy(WorldObject* /*summoner*/) override + { + // player is the spellcaster so register summon manually + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->JustSummoned(me); + } - void JustDied(Unit* /*killer*/) override - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->SummonedCreatureDespawn(me); - if (TempSummon* summon = me->ToTempSummon()) - summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); - } + void JustDied(Unit* /*killer*/) override + { + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->SummonedCreatureDespawn(me); + if (TempSummon* summon = me->ToTempSummon()) + summon->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); + } - void UpdateAI(uint32 diff) override - { - if (!_events.IsInPhase(PHASE_FROSTMOURNE) && !UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + if (!_events.IsInPhase(PHASE_FROSTMOURNE) && !UpdateVictim()) + return; - _events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SOUL_SHRIEK: + DoCastAOE(SPELL_SOUL_SHRIEK); + _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); + break; + case EVENT_SET_AGRESSIVE: + me->SetReactState(REACT_AGGRESSIVE); + if (_events.IsInPhase(PHASE_FROSTMOURNE)) { - case EVENT_SOUL_SHRIEK: - DoCastAOE(SPELL_SOUL_SHRIEK); - _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); - break; - case EVENT_SET_AGRESSIVE: - me->SetReactState(REACT_AGGRESSIVE); - if (_events.IsInPhase(PHASE_FROSTMOURNE)) - { - _events.SetPhase(PHASE_THREE); - _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); - } - break; - default: - break; + _events.SetPhase(PHASE_THREE); + _events.ScheduleEvent(EVENT_SOUL_SHRIEK, 12s, 15s); } - } - - DoMeleeAttackIfReady(); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_raging_spiritAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; }; -class npc_valkyr_shadowguard : public CreatureScript +struct npc_valkyr_shadowguard : public ScriptedAI { - public: - npc_valkyr_shadowguard() : CreatureScript("npc_valkyr_shadowguard") { } - - struct npc_valkyr_shadowguardAI : public ScriptedAI - { - npc_valkyr_shadowguardAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } + npc_valkyr_shadowguard(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - void Reset() override - { - _events.Reset(); - me->SetReactState(REACT_PASSIVE); - DoCast(me, SPELL_WINGS_OF_THE_DAMNED, false); - } + void Reset() override + { + _events.Reset(); + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_WINGS_OF_THE_DAMNED, false); + } - void IsSummonedBy(WorldObject* /*summoner*/) override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2500ms); - } + void IsSummonedBy(WorldObject* /*summoner*/) override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2500ms); + } - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (!IsHeroic()) - return; + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (!IsHeroic()) + return; - if (!me->HasAuraType(SPELL_AURA_CONTROL_VEHICLE)) - return; + if (!me->HasAuraType(SPELL_AURA_CONTROL_VEHICLE)) + return; - if (me->HealthBelowPctDamaged(50, damage)) - { - DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); - ScheduleHeroicEvents(); - } - } + if (me->HealthBelowPctDamaged(50, damage)) + { + DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); + ScheduleHeroicEvents(); + } + } - void ScheduleHeroicEvents() - { - _events.Reset(); - _events.ScheduleEvent(EVENT_MOVE_TO_CENTER, 1ms); - me->ClearUnitState(UNIT_STATE_EVADE); - } + void ScheduleHeroicEvents() + { + _events.Reset(); + _events.ScheduleEvent(EVENT_MOVE_TO_CENTER, 1ms); + me->ClearUnitState(UNIT_STATE_EVADE); + } - void AttackStart(Unit* /*target*/) override - { - } + void AttackStart(Unit* /*target*/) override + { + } - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + return; - switch (id) + switch (id) + { + case POINT_DROP_PLAYER: + DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); + if (IsHeroic()) + ScheduleHeroicEvents(); + else + me->DespawnOrUnsummon(1s); + break; + case POINT_CHARGE: + if (Player* target = ObjectAccessor::GetPlayer(*me, _grabbedPlayer)) { - case POINT_DROP_PLAYER: - DoCastAOE(SPELL_EJECT_ALL_PASSENGERS); - if (IsHeroic()) - ScheduleHeroicEvents(); - else - me->DespawnOrUnsummon(1s); - break; - case POINT_CHARGE: - if (Player* target = ObjectAccessor::GetPlayer(*me, _grabbedPlayer)) - { - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - if (GameObject* platform = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_ARTHAS_PLATFORM))) - { - std::list<Creature*> triggers; - GetCreatureListWithEntryInGrid(triggers, me, NPC_WORLD_TRIGGER, 150.0f); - triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true)); - if (triggers.empty()) - return; - - triggers.sort(Trinity::ObjectDistanceOrderPred(me)); - DoCast(target, SPELL_VALKYR_CARRY); - _dropPoint.Relocate(triggers.front()); - _events.ScheduleEvent(EVENT_MOVE_TO_DROP_POS, 1500ms); - } - } - else - me->DespawnOrUnsummon(); - break; - case POINT_SIPHON: - DoZoneInCombat(); - _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2s); - break; - default: - break; + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + if (GameObject* platform = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_ARTHAS_PLATFORM))) + { + std::list<Creature*> triggers; + GetCreatureListWithEntryInGrid(triggers, me, NPC_WORLD_TRIGGER, 150.0f); + triggers.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, true)); + if (triggers.empty()) + return; + + triggers.sort(Trinity::ObjectDistanceOrderPred(me)); + DoCast(target, SPELL_VALKYR_CARRY); + _dropPoint.Relocate(triggers.front()); + _events.ScheduleEvent(EVENT_MOVE_TO_DROP_POS, 1500ms); + } } - } + else + me->DespawnOrUnsummon(); + break; + case POINT_SIPHON: + DoZoneInCombat(); + _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2s); + break; + default: + break; + } + } - void SetGUID(ObjectGuid const& guid, int32 /*id*/) override - { - _grabbedPlayer = guid; - } + void SetGUID(ObjectGuid const& guid, int32 /*id*/) override + { + _grabbedPlayer = guid; + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - _events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_GRAB_PLAYER: + if (!_grabbedPlayer) { - case EVENT_GRAB_PLAYER: - if (!_grabbedPlayer) - { - DoCastAOE(SPELL_VALKYR_TARGET_SEARCH); - _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2s); - } - break; - case EVENT_MOVE_TO_DROP_POS: - me->GetMotionMaster()->MovePoint(POINT_DROP_PLAYER, _dropPoint); - break; - case EVENT_LIFE_SIPHON: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) - DoCast(target, SPELL_LIFE_SIPHON); - _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2500ms); - break; - case EVENT_MOVE_TO_CENTER: - { - Position pos = me->GetRandomPoint(CenterPosition, 4.0f); - pos.m_positionZ = me->GetHomePosition().m_positionZ; - me->GetMotionMaster()->MovePoint(POINT_SIPHON, pos); - break; - } - default: - break; + DoCastAOE(SPELL_VALKYR_TARGET_SEARCH); + _events.ScheduleEvent(EVENT_GRAB_PLAYER, 2s); } + break; + case EVENT_MOVE_TO_DROP_POS: + me->GetMotionMaster()->MovePoint(POINT_DROP_PLAYER, _dropPoint); + break; + case EVENT_LIFE_SIPHON: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1)) + DoCast(target, SPELL_LIFE_SIPHON); + _events.ScheduleEvent(EVENT_LIFE_SIPHON, 2500ms); + break; + case EVENT_MOVE_TO_CENTER: + { + Position pos = me->GetRandomPoint(CenterPosition, 4.0f); + pos.m_positionZ = me->GetHomePosition().m_positionZ; + me->GetMotionMaster()->MovePoint(POINT_SIPHON, pos); + break; } - - // no melee attacks + default: + break; } + } - private: - EventMap _events; - Position _dropPoint; - ObjectGuid _grabbedPlayer; - InstanceScript* _instance; - }; + // no melee attacks + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_valkyr_shadowguardAI>(creature); - } +private: + EventMap _events; + Position _dropPoint; + ObjectGuid _grabbedPlayer; + InstanceScript* _instance; }; -class npc_strangulate_vehicle : public CreatureScript +struct npc_strangulate_vehicle : public ScriptedAI { - public: - npc_strangulate_vehicle() : CreatureScript("npc_strangulate_vehicle") { } + npc_strangulate_vehicle(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_strangulate_vehicleAI : public ScriptedAI - { - npc_strangulate_vehicleAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } + void IsSummonedBy(WorldObject* summonerWO) override + { + Unit* summoner = summonerWO->ToUnit(); + if (!summoner) + return; + me->SetFacingToObject(summoner); + DoCast(summoner, SPELL_HARVEST_SOUL_VEHICLE); + _events.Reset(); + _events.ScheduleEvent(EVENT_MOVE_TO_LICH_KING, 2s); + _events.ScheduleEvent(EVENT_TELEPORT, 6s); + + // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->JustSummoned(me); + } - void IsSummonedBy(WorldObject* summonerWO) override - { - Unit* summoner = summonerWO->ToUnit(); - if (!summoner) - return; - me->SetFacingToObject(summoner); - DoCast(summoner, SPELL_HARVEST_SOUL_VEHICLE); - _events.Reset(); - _events.ScheduleEvent(EVENT_MOVE_TO_LICH_KING, 2s); - _events.ScheduleEvent(EVENT_TELEPORT, 6s); + void DoAction(int32 action) override + { + if (action != ACTION_TELEPORT_BACK) + return; - // this will let us easily access all creatures of this entry on heroic mode when its time to teleport back - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->JustSummoned(me); + if (TempSummon* summ = me->ToTempSummon()) + { + if (Unit* summoner = summ->GetSummonerUnit()) + { + DoCast(summoner, SPELL_HARVEST_SOUL_TELEPORT_BACK); + summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOULS_TELEPORT); } + } - void DoAction(int32 action) override - { - if (action != ACTION_TELEPORT_BACK) - return; + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->SummonedCreatureDespawn(me); + me->DespawnOrUnsummon(); + } - if (TempSummon* summ = me->ToTempSummon()) - { - if (Unit* summoner = summ->GetSummonerUnit()) - { - DoCast(summoner, SPELL_HARVEST_SOUL_TELEPORT_BACK); - summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOULS_TELEPORT); - } - } + void UpdateAI(uint32 diff) override + { + UpdateVictim(); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->SummonedCreatureDespawn(me); - me->DespawnOrUnsummon(); - } + _events.Update(diff); - void UpdateAI(uint32 diff) override + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - UpdateVictim(); - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + case EVENT_TELEPORT: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + if (TempSummon* summ = me->ToTempSummon()) { - case EVENT_TELEPORT: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - if (TempSummon* summ = me->ToTempSummon()) + if (Unit* summoner = summ->GetSummonerUnit()) + { + summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true); + summoner->ExitVehicle(summoner); + if (!IsHeroic()) + summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true); + else { - if (Unit* summoner = summ->GetSummonerUnit()) - { - summoner->CastSpell(nullptr, SPELL_HARVEST_SOUL_VISUAL, true); - summoner->ExitVehicle(summoner); - if (!IsHeroic()) - summoner->CastSpell(summoner, SPELL_HARVEST_SOUL_TELEPORT, true); - else - { - summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true); - summoner->RemoveAurasDueToSpell(HARVEST_SOUL, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE); - } - } + summoner->CastSpell(summoner, SPELL_HARVEST_SOULS_TELEPORT, true); + summoner->RemoveAurasDueToSpell(HARVEST_SOUL, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE); } + } + } - _events.ScheduleEvent(EVENT_DESPAWN_SELF, 65s); - break; - case EVENT_MOVE_TO_LICH_KING: - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - { - if (me->GetExactDist(lichKing) > 10.0f) - { - Position pos = lichKing->GetNearPosition(float(rand_norm()) * 5.0f + 7.5f, lichKing->GetAbsoluteAngle(me)); - me->GetMotionMaster()->MovePoint(0, pos); - } - } - break; - case EVENT_DESPAWN_SELF: - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->SummonedCreatureDespawn(me); - me->DespawnOrUnsummon(1ms); - break; - default: - break; + _events.ScheduleEvent(EVENT_DESPAWN_SELF, 65s); + break; + case EVENT_MOVE_TO_LICH_KING: + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + { + if (me->GetExactDist(lichKing) > 10.0f) + { + Position pos = lichKing->GetNearPosition(float(rand_norm()) * 5.0f + 7.5f, lichKing->GetAbsoluteAngle(me)); + me->GetMotionMaster()->MovePoint(0, pos); + } } - } + break; + case EVENT_DESPAWN_SELF: + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->SummonedCreatureDespawn(me); + me->DespawnOrUnsummon(1ms); + break; + default: + break; } - - private: - EventMap _events; - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_strangulate_vehicleAI>(creature); } + } + +private: + EventMap _events; + InstanceScript* _instance; }; -class npc_terenas_menethil : public CreatureScript +struct npc_terenas_menethil : public ScriptedAI { - public: - npc_terenas_menethil() : CreatureScript("npc_terenas_menethil") { } + npc_terenas_menethil(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_terenas_menethilAI : public ScriptedAI - { - npc_terenas_menethilAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } - - bool CanAIAttack(Unit const* target) const override - { - return target->GetEntry() != NPC_THE_LICH_KING; - } + bool CanAIAttack(Unit const* target) const override + { + return target->GetEntry() != NPC_THE_LICH_KING; + } - void DoAction(int32 action) override - { - switch (action) + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_FROSTMOURNE_INTRO: + me->setActive(true); + me->SetFarVisible(false); + if (!IsHeroic()) + me->SetHealth(me->GetMaxHealth() / 2); + DoCastSelf(SPELL_LIGHTS_FAVOR); + _events.Reset(); + _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_1, 2s, PHASE_FROSTMOURNE); + _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_2, 11s, PHASE_FROSTMOURNE); + if (!IsHeroic()) { - case ACTION_FROSTMOURNE_INTRO: - me->setActive(true); - me->SetFarVisible(false); - if (!IsHeroic()) - me->SetHealth(me->GetMaxHealth() / 2); - DoCast(me, SPELL_LIGHTS_FAVOR); - _events.Reset(); - _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_1, 2s, PHASE_FROSTMOURNE); - _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_2, 11s, PHASE_FROSTMOURNE); - if (!IsHeroic()) - { - _events.ScheduleEvent(EVENT_DESTROY_SOUL, 1min, PHASE_FROSTMOURNE); - _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_3, 25s); - } - break; - case ACTION_TELEPORT_BACK: - me->CastSpell(nullptr, SPELL_RESTORE_SOUL, TRIGGERED_NONE); - me->DespawnOrUnsummon(3s); - break; - default: - break; + _events.ScheduleEvent(EVENT_DESTROY_SOUL, 1min, PHASE_FROSTMOURNE); + _events.ScheduleEvent(EVENT_FROSTMOURNE_TALK_3, 25s); } - } + break; + case ACTION_TELEPORT_BACK: + me->CastSpell(nullptr, SPELL_RESTORE_SOUL, TRIGGERED_NONE); + me->DespawnOrUnsummon(3s); + break; + default: + break; + } + } - void EnterEvadeMode(EvadeReason /*why*/) override - { - // no running back home - if (!me->IsAlive()) - return; + void EnterEvadeMode(EvadeReason /*why*/) override + { + // no running back home + if (!me->IsAlive()) + return; - me->CombatStop(false); - EngagementOver(); - } + me->CombatStop(false); + EngagementOver(); + } - void DamageTaken(Unit* /*attacker*/, uint32& damage) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() - 1; + if (!me->HasAura(SPELL_TERENAS_LOSES_INSIDE) && !IsHeroic()) { - if (damage >= me->GetHealth()) + me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + DoCast(SPELL_TERENAS_LOSES_INSIDE); + _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1s); + if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f)) { - damage = me->GetHealth() - 1; - if (!me->HasAura(SPELL_TERENAS_LOSES_INSIDE) && !IsHeroic()) - { - me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - DoCast(SPELL_TERENAS_LOSES_INSIDE); - _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1s); - if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f)) - { - warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE); - warden->DespawnOrUnsummon(2s); - } - - me->DespawnOrUnsummon(2s); - } + warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE); + warden->DespawnOrUnsummon(2s); } + + me->DespawnOrUnsummon(2s); } + } + } - void IsSummonedBy(WorldObject* /*summoner*/) override - { - _events.Reset(); - _events.SetPhase(PHASE_OUTRO); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - me->SetFacingToObject(lichKing); + void IsSummonedBy(WorldObject* /*summoner*/) override + { + _events.Reset(); + _events.SetPhase(PHASE_OUTRO); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + me->SetFacingToObject(lichKing); - _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_1, 2s, 0, PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_2, 14s, 0, PHASE_OUTRO); - } + _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_1, 2s, 0, PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_TERENAS_TALK_2, 14s, 0, PHASE_OUTRO); + } - void UpdateAI(uint32 diff) override - { - UpdateVictim(); + void UpdateAI(uint32 diff) override + { + UpdateVictim(); - _events.Update(diff); + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FROSTMOURNE_TALK_1: + Talk(SAY_TERENAS_INTRO_1); + if (IsHeroic()) + DoCastAOE(SPELL_RESTORE_SOULS); + break; + case EVENT_FROSTMOURNE_TALK_2: + Talk(SAY_TERENAS_INTRO_2); + break; + case EVENT_FROSTMOURNE_TALK_3: + Talk(SAY_TERENAS_INTRO_3); + break; + case EVENT_OUTRO_TERENAS_TALK_1: + Talk(SAY_TERENAS_OUTRO_1); + break; + case EVENT_OUTRO_TERENAS_TALK_2: + Talk(SAY_TERENAS_OUTRO_2); + DoCastAOE(SPELL_MASS_RESURRECTION); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) { - case EVENT_FROSTMOURNE_TALK_1: - Talk(SAY_TERENAS_INTRO_1); - if (IsHeroic()) - DoCastAOE(SPELL_RESTORE_SOULS); - break; - case EVENT_FROSTMOURNE_TALK_2: - Talk(SAY_TERENAS_INTRO_2); - break; - case EVENT_FROSTMOURNE_TALK_3: - Talk(SAY_TERENAS_INTRO_3); - break; - case EVENT_OUTRO_TERENAS_TALK_1: - Talk(SAY_TERENAS_OUTRO_1); - break; - case EVENT_OUTRO_TERENAS_TALK_2: - Talk(SAY_TERENAS_OUTRO_2); - DoCastAOE(SPELL_MASS_RESURRECTION); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - { - lichKing->AI()->DoAction(ACTION_FINISH_OUTRO); - lichKing->SetImmuneToNPC(false); - if (Creature* tirion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->AI()->AttackStart(lichKing); - } - break; - case EVENT_DESTROY_SOUL: - me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f)) - warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE); - DoCast(SPELL_TERENAS_LOSES_INSIDE); - _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1s); - break; - case EVENT_TELEPORT_BACK: - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); - break; - default: - break; + lichKing->AI()->DoAction(ACTION_FINISH_OUTRO); + lichKing->SetImmuneToNPC(false); + if (Creature* tirion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) + tirion->AI()->AttackStart(lichKing); } - } - - // fighting Spirit Warden - if (me->IsInCombat()) - DoMeleeAttackIfReady(); + break; + case EVENT_DESTROY_SOUL: + me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + if (Creature* warden = me->FindNearestCreature(NPC_SPIRIT_WARDEN, 20.0f)) + warden->CastSpell(nullptr, SPELL_DESTROY_SOUL, TRIGGERED_NONE); + DoCast(SPELL_TERENAS_LOSES_INSIDE); + _events.ScheduleEvent(EVENT_TELEPORT_BACK, 1s); + break; + case EVENT_TELEPORT_BACK: + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - }; + // fighting Spirit Warden + if (me->IsInCombat()) + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_terenas_menethilAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; }; -class npc_spirit_warden : public CreatureScript +struct npc_spirit_warden : public ScriptedAI { - public: - npc_spirit_warden() : CreatureScript("npc_spirit_warden") { } + npc_spirit_warden(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_spirit_wardenAI : public ScriptedAI - { - npc_spirit_wardenAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) - { - } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_SOUL_RIP, 12s, 15s); - DoCast(SPELL_DARK_HUNGER); - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_SOUL_RIP, 12s, 15s); + DoCast(SPELL_DARK_HUNGER); + } - void JustDied(Unit* /*killer*/) override - { - if (Creature* terenas = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TERENAS_MENETHIL))) - terenas->AI()->DoAction(ACTION_TELEPORT_BACK); - } + void JustDied(Unit* /*killer*/) override + { + if (Creature* terenas = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TERENAS_MENETHIL))) + terenas->AI()->DoAction(ACTION_TELEPORT_BACK); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - _events.Update(diff); + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SOUL_RIP: - DoCastVictim(SPELL_SOUL_RIP); - _events.ScheduleEvent(EVENT_SOUL_RIP, 23s, 27s); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SOUL_RIP: + DoCastVictim(SPELL_SOUL_RIP); + _events.ScheduleEvent(EVENT_SOUL_RIP, 23s, 27s); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_spirit_wardenAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; }; -class npc_spirit_bomb : public CreatureScript +struct npc_spirit_bomb : public CreatureAI { - public: - npc_spirit_bomb() : CreatureScript("npc_spirit_bomb") { } - - struct npc_spirit_bombAI : public CreatureAI - { - npc_spirit_bombAI(Creature* creature) : CreatureAI(creature) - { - } + npc_spirit_bomb(Creature* creature) : CreatureAI(creature) { } - void IsSummonedBy(WorldObject* /*summoner*/) override - { - float destX, destY, destZ; - me->GetPosition(destX, destY); - destZ = 1055.0f; // approximation, gets more precise later - me->UpdateGroundPositionZ(destX, destY, destZ); - me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ); - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != POINT_MOTION_TYPE || point != POINT_GROUND) - return; - - _events.ScheduleEvent(EVENT_BOMB_EXPLOSION, 3s); - } + void IsSummonedBy(WorldObject* /*summoner*/) override + { + float destX, destY, destZ; + me->GetPosition(destX, destY); + destZ = 1055.0f; // approximation, gets more precise later + me->UpdateGroundPositionZ(destX, destY, destZ); + me->GetMotionMaster()->MovePoint(POINT_GROUND, destX, destY, destZ); + } - void AttackStart(Unit* /*victim*/) override - { - } + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE || point != POINT_GROUND) + return; - void UpdateAI(uint32 diff) override - { - UpdateVictim(); + _events.ScheduleEvent(EVENT_BOMB_EXPLOSION, 3s); + } - _events.Update(diff); + void AttackStart(Unit* /*victim*/) override + { + } - if (_events.ExecuteEvent() == EVENT_BOMB_EXPLOSION) - { - me->RemoveAllAuras(); - DoCastAOE(SPELL_EXPLOSION); - me->DespawnOrUnsummon(1s); - } - } + void UpdateAI(uint32 diff) override + { + UpdateVictim(); - private: - EventMap _events; - }; + _events.Update(diff); - CreatureAI* GetAI(Creature* creature) const override + if (_events.ExecuteEvent() == EVENT_BOMB_EXPLOSION) { - return GetIcecrownCitadelAI<npc_spirit_bombAI>(creature); + me->RemoveAllAuras(); + DoCastAOE(SPELL_EXPLOSION); + me->DespawnOrUnsummon(1s); } + } + +private: + EventMap _events; }; -class npc_broken_frostmourne : public CreatureScript +struct npc_broken_frostmourne : public CreatureAI { - public: - npc_broken_frostmourne() : CreatureScript("npc_broken_frostmourne") { } - - struct npc_broken_frostmourneAI : public CreatureAI - { - npc_broken_frostmourneAI(Creature* creature) : CreatureAI(creature) - { - } + npc_broken_frostmourne(Creature* creature) : CreatureAI(creature) { } - void Reset() override - { - _events.Reset(); - } - - void IsSummonedBy(WorldObject* /*summoner*/) override - { - _events.SetPhase(PHASE_OUTRO); - _events.ScheduleEvent(EVENT_OUTRO_KNOCK_BACK, 3s, 0, PHASE_OUTRO); - } + void Reset() override + { + _events.Reset(); + } - void DoAction(int32 action) override - { - if (action == ACTION_SUMMON_TERENAS) - _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6s, 0, PHASE_OUTRO); - } + void IsSummonedBy(WorldObject* /*summoner*/) override + { + _events.SetPhase(PHASE_OUTRO); + _events.ScheduleEvent(EVENT_OUTRO_KNOCK_BACK, 3s, 0, PHASE_OUTRO); + } - void EnterEvadeMode(EvadeReason /*why*/) override - { - } + void DoAction(int32 action) override + { + if (action == ACTION_SUMMON_TERENAS) + _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6s, 0, PHASE_OUTRO); + } - void UpdateAI(uint32 diff) override - { - UpdateVictim(); + void EnterEvadeMode(EvadeReason /*why*/) override + { + } - _events.Update(diff); + void UpdateAI(uint32 diff) override + { + UpdateVictim(); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_OUTRO_KNOCK_BACK: - DoCastAOE(SPELL_BROKEN_FROSTMOURNE_KNOCK); - break; - case EVENT_OUTRO_SUMMON_TERENAS: - DoCastAOE(SPELL_SUMMON_TERENAS); - break; - default: - break; - } - } + _events.Update(diff); - // no melee attacks + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_OUTRO_KNOCK_BACK: + DoCastAOE(SPELL_BROKEN_FROSTMOURNE_KNOCK); + break; + case EVENT_OUTRO_SUMMON_TERENAS: + DoCastAOE(SPELL_SUMMON_TERENAS); + break; + default: + break; } + } - private: - EventMap _events; - }; + // no melee attacks + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_broken_frostmourneAI>(creature); - } +private: + EventMap _events; }; -class spell_the_lich_king_infest : public SpellScriptLoader +class spell_the_lich_king_infest : public AuraScript { - public: - spell_the_lich_king_infest() : SpellScriptLoader("spell_the_lich_king_infest") { } + PrepareAuraScript(spell_the_lich_king_infest); - class spell_the_lich_king_infest_AuraScript : public AuraScript + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (GetUnitOwner()->HealthAbovePct(90)) { - PrepareAuraScript(spell_the_lich_king_infest_AuraScript); - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - if (GetUnitOwner()->HealthAbovePct(90)) - { - PreventDefaultAction(); - Remove(AURA_REMOVE_BY_ENEMY_SPELL); - } - } - - void OnUpdate(AuraEffect* aurEff) - { - // multiply, starting from 2nd tick - if (aurEff->GetTickNumber() == 1) - return; + PreventDefaultAction(); + Remove(AURA_REMOVE_BY_ENEMY_SPELL); + } + } - aurEff->SetAmount(int32(aurEff->GetAmount() * 1.15f)); - } + void OnUpdate(AuraEffect* aurEff) + { + // multiply, starting from 2nd tick + if (aurEff->GetTickNumber() == 1) + return; - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_infest_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); - OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_the_lich_king_infest_AuraScript::OnUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); - } - }; + aurEff->SetAmount(int32(aurEff->GetAmount() * 1.15f)); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_infest_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_infest::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_the_lich_king_infest::OnUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } }; -class spell_the_lich_king_necrotic_plague : public SpellScriptLoader +class spell_the_lich_king_necrotic_plague : public AuraScript { - public: - spell_the_lich_king_necrotic_plague() : SpellScriptLoader("spell_the_lich_king_necrotic_plague") { } - - class spell_the_lich_king_necrotic_plague_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_necrotic_plague_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_NECROTIC_PLAGUE_JUMP }); - } + PrepareAuraScript(spell_the_lich_king_necrotic_plague); - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - switch (GetTargetApplication()->GetRemoveMode()) - { - case AURA_REMOVE_BY_ENEMY_SPELL: - case AURA_REMOVE_BY_EXPIRE: - case AURA_REMOVE_BY_DEATH: - break; - default: - return; - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_NECROTIC_PLAGUE_JUMP }); + } - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.SetOriginalCaster(GetCasterGUID()); - args.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1); - GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); - if (Unit* caster = GetCaster()) - caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); - } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + switch (GetTargetApplication()->GetRemoveMode()) + { + case AURA_REMOVE_BY_ENEMY_SPELL: + case AURA_REMOVE_BY_EXPIRE: + case AURA_REMOVE_BY_DEATH: + break; + default: + return; + } - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); - } - }; + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SetOriginalCaster(GetCasterGUID()); + args.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1); + GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_necrotic_plague_AuraScript(); - } + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader +class spell_the_lich_king_necrotic_plague_jump : public SpellScript { - public: - spell_the_lich_king_necrotic_plague_jump() : SpellScriptLoader("spell_the_lich_king_necrotic_plague_jump") { } + PrepareSpellScript(spell_the_lich_king_necrotic_plague_jump); - class spell_the_lich_king_necrotic_plague_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_necrotic_plague_SpellScript); - - public: - spell_the_lich_king_necrotic_plague_SpellScript() - { - _hadAura = false; - } - - private: - void SelectTarget(std::list<WorldObject*>& targets) - { - targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); - if (targets.size() < 2) - return; - - targets.resize(1); - } +public: + spell_the_lich_king_necrotic_plague_jump() + { + _hadAura = false; + } - void CheckAura(SpellMissInfo missInfo) - { - if (missInfo != SPELL_MISS_NONE) - return; +private: + void SelectTarget(std::list<WorldObject*>& targets) + { + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); + if (targets.size() < 2) + return; - if (GetHitUnit()->HasAura(GetSpellInfo()->Id)) - _hadAura = true; - } + targets.resize(1); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_necrotic_plague_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - BeforeHit += BeforeSpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura); - } + void CheckAura(SpellMissInfo missInfo) + { + if (missInfo != SPELL_MISS_NONE) + return; - bool _hadAura; - }; + if (GetHitUnit()->HasAura(GetSpellInfo()->Id)) + _hadAura = true; + } - class spell_the_lich_king_necrotic_plague_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_necrotic_plague_AuraScript); + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_necrotic_plague_jump::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + BeforeHit += BeforeSpellHitFn(spell_the_lich_king_necrotic_plague_jump::CheckAura); + } - public: - spell_the_lich_king_necrotic_plague_AuraScript() - { - _lastAmount = 0; - } + bool _hadAura; +}; - private: - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Unit* caster = GetCaster()) - if (caster->GetAI()) - caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount()); - } +class spell_the_lich_king_necrotic_plague_jump_aura : public AuraScript +{ + PrepareAuraScript(spell_the_lich_king_necrotic_plague_jump_aura); - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - _lastAmount = aurEff->GetAmount(); - switch (GetTargetApplication()->GetRemoveMode()) - { - case AURA_REMOVE_BY_EXPIRE: - case AURA_REMOVE_BY_DEATH: - break; - default: - return; - } +public: + spell_the_lich_king_necrotic_plague_jump_aura() + { + _lastAmount = 0; + } - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.SetOriginalCaster(GetCasterGUID()); - args.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount() + 1); - GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); - if (Unit* caster = GetCaster()) - caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); - } +private: + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetAI()) + caster->GetAI()->SetData(DATA_PLAGUE_STACK, GetStackAmount()); + } - void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - _lastAmount = aurEff->GetAmount(); - } + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + _lastAmount = aurEff->GetAmount(); + switch (GetTargetApplication()->GetRemoveMode()) + { + case AURA_REMOVE_BY_EXPIRE: + case AURA_REMOVE_BY_DEATH: + break; + default: + return; + } - void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - // this means the stack increased so don't process as if dispelled - if (aurEff->GetAmount() > _lastAmount) - return; - - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.SetOriginalCaster(GetCasterGUID()); - args.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount()); - args.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1) - GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); - if (Unit* caster = GetCaster()) - caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); - - Remove(AURA_REMOVE_BY_ENEMY_SPELL); - } + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SetOriginalCaster(GetCasterGUID()); + args.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount() + 1); + GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); + } - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_the_lich_king_necrotic_plague_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::OnDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY); - AfterEffectApply += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_AuraScript::AfterDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY); - } + void OnDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + _lastAmount = aurEff->GetAmount(); + } - int32 _lastAmount; - }; + void AfterDispel(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + // this means the stack increased so don't process as if dispelled + if (aurEff->GetAmount() > _lastAmount) + return; + + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SetOriginalCaster(GetCasterGUID()); + args.AddSpellMod(SPELLVALUE_AURA_STACK, GetStackAmount()); + args.AddSpellMod(SPELLVALUE_BASE_POINT1, AURA_REMOVE_BY_ENEMY_SPELL); // add as marker (spell has no effect 1) + GetTarget()->CastSpell(nullptr, SPELL_NECROTIC_PLAGUE_JUMP, args); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_PLAGUE_SIPHON, true); + + Remove(AURA_REMOVE_BY_ENEMY_SPELL); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_necrotic_plague_SpellScript(); - } + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_the_lich_king_necrotic_plague_jump_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_jump_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_jump_aura::OnDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY); + AfterEffectApply += AuraEffectRemoveFn(spell_the_lich_king_necrotic_plague_jump_aura::AfterDispel, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_necrotic_plague_AuraScript(); - } + int32 _lastAmount; }; -class spell_the_lich_king_shadow_trap_visual : public SpellScriptLoader +class spell_the_lich_king_shadow_trap_visual : public AuraScript { - public: - spell_the_lich_king_shadow_trap_visual() : SpellScriptLoader("spell_the_lich_king_shadow_trap_visual") { } - - class spell_the_lich_king_shadow_trap_visual_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_shadow_trap_visual_AuraScript); + PrepareAuraScript(spell_the_lich_king_shadow_trap_visual); - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) - GetTarget()->CastSpell(GetTarget(), SPELL_SHADOW_TRAP_AURA, TRIGGERED_NONE); - } - - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_shadow_trap_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + GetTarget()->CastSpell(GetTarget(), SPELL_SHADOW_TRAP_AURA, TRIGGERED_NONE); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_shadow_trap_visual_AuraScript(); - } + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_shadow_trap_visual::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader +class spell_the_lich_king_shadow_trap_periodic : public SpellScript { - public: - spell_the_lich_king_shadow_trap_periodic() : SpellScriptLoader("spell_the_lich_king_shadow_trap_periodic") { } - - class spell_the_lich_king_shadow_trap_periodic_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic_SpellScript); + PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic); - void CheckTargetCount(std::list<WorldObject*>& targets) - { - if (targets.empty()) - return; - - GetCaster()->CastSpell(nullptr, SPELL_SHADOW_TRAP_KNOCKBACK, true); - } + void CheckTargetCount(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; + GetCaster()->CastSpell(nullptr, SPELL_SHADOW_TRAP_KNOCKBACK, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_shadow_trap_periodic_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_shadow_trap_periodic::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } }; -class spell_the_lich_king_quake : public SpellScriptLoader +class spell_the_lich_king_quake : public SpellScript { - public: - spell_the_lich_king_quake() : SpellScriptLoader("spell_the_lich_king_quake") { } - - class spell_the_lich_king_quake_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_quake_SpellScript); + PrepareSpellScript(spell_the_lich_king_quake); - bool Load() override - { - return GetCaster()->GetInstanceScript() != nullptr; - } - - void FilterTargets(std::list<WorldObject*>& targets) - { - if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetGuidData(DATA_ARTHAS_PLATFORM))) - targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false)); - } + bool Load() override + { + return GetCaster()->GetInstanceScript() != nullptr; + } - void HandleSendEvent(SpellEffIndex /*effIndex*/) - { - if (UnitAI* AI = GetCaster()->GetAI()) - AI->DoAction(ACTION_START_ATTACK); - } + void FilterTargets(std::list<WorldObject*>& targets) + { + if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetGuidData(DATA_ARTHAS_PLATFORM))) + targets.remove_if(Trinity::HeightDifferenceCheck(platform, 5.0f, false)); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHit += SpellEffectFn(spell_the_lich_king_quake_SpellScript::HandleSendEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT); - } - }; + void HandleSendEvent(SpellEffIndex /*effIndex*/) + { + if (UnitAI* AI = GetCaster()->GetAI()) + AI->DoAction(ACTION_START_ATTACK); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_quake_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_quake::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHit += SpellEffectFn(spell_the_lich_king_quake::HandleSendEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT); + } }; -class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader +class spell_the_lich_king_ice_burst_target_search : public SpellScript { - public: - spell_the_lich_king_ice_burst_target_search() : SpellScriptLoader("spell_the_lich_king_ice_burst_target_search") { } - - class spell_the_lich_king_ice_burst_target_search_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_ice_burst_target_search_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_ICE_BURST }); - } - - void CheckTargetCount(std::list<WorldObject*>& unitList) - { - if (unitList.empty()) - return; + PrepareSpellScript(spell_the_lich_king_ice_burst_target_search); - // if there is at least one affected target cast the explosion - GetCaster()->CastSpell(GetCaster(), SPELL_ICE_BURST, true); - if (GetCaster()->GetTypeId() == TYPEID_UNIT) - { - GetCaster()->ToCreature()->SetReactState(REACT_PASSIVE); - GetCaster()->AttackStop(); - GetCaster()->ToCreature()->DespawnOrUnsummon(500ms); - } - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_ICE_BURST }); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; + void CheckTargetCount(std::list<WorldObject*>& unitList) + { + if (unitList.empty()) + return; - SpellScript* GetSpellScript() const override + // if there is at least one affected target cast the explosion + GetCaster()->CastSpell(GetCaster(), SPELL_ICE_BURST, true); + if (GetCaster()->GetTypeId() == TYPEID_UNIT) { - return new spell_the_lich_king_ice_burst_target_search_SpellScript(); + GetCaster()->ToCreature()->SetReactState(REACT_PASSIVE); + GetCaster()->AttackStop(); + GetCaster()->ToCreature()->DespawnOrUnsummon(500ms); } + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_ice_burst_target_search::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } }; -class spell_the_lich_king_raging_spirit : public SpellScriptLoader +class spell_the_lich_king_raging_spirit : public SpellScript { - public: - spell_the_lich_king_raging_spirit() : SpellScriptLoader("spell_the_lich_king_raging_spirit") { } + PrepareSpellScript(spell_the_lich_king_raging_spirit); - class spell_the_lich_king_raging_spirit_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_raging_spirit_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_raging_spirit_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_raging_spirit_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_raging_spirit::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; class ExactDistanceCheck @@ -2463,774 +2238,543 @@ class ExactDistanceCheck float _dist; }; -class spell_the_lich_king_defile : public SpellScriptLoader +class spell_the_lich_king_defile : public SpellScript { - public: - spell_the_lich_king_defile() : SpellScriptLoader("spell_the_lich_king_defile") { } - - class spell_the_lich_king_defile_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_defile_SpellScript); + PrepareSpellScript(spell_the_lich_king_defile); - void CorrectRange(std::list<WorldObject*>& targets) - { - targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale())); - targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR)); - } - - void ChangeDamageAndGrow() - { - SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale())); - // HACK: target player should cast this spell on defile - // however with current aura handling auras cast by different units - // cannot stack on the same aura object increasing the stack count - GetCaster()->CastSpell(GetCaster(), SPELL_DEFILE_GROW, true); - } + void CorrectRange(std::list<WorldObject*>& targets) + { + targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale())); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR)); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnHit += SpellHitFn(spell_the_lich_king_defile_SpellScript::ChangeDamageAndGrow); - } - }; + void ChangeDamageAndGrow() + { + SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale())); + // HACK: target player should cast this spell on defile + // however with current aura handling auras cast by different units + // cannot stack on the same aura object increasing the stack count + GetCaster()->CastSpell(GetCaster(), SPELL_DEFILE_GROW, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_defile_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnHit += SpellHitFn(spell_the_lich_king_defile::ChangeDamageAndGrow); + } }; -class spell_the_lich_king_summon_into_air : public SpellScriptLoader +class spell_the_lich_king_summon_into_air : public SpellScript { - public: - spell_the_lich_king_summon_into_air() : SpellScriptLoader("spell_the_lich_king_summon_into_air") { } - - class spell_the_lich_king_summon_into_air_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_summon_into_air_SpellScript); - - void ModDestHeight(SpellEffIndex /*effIndex*/) - { - static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f}; - WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest()); - dest->RelocateOffset(offset); - GetHitDest()->RelocateOffset(offset); - // spirit bombs get higher - if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB) - { - static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f }; - dest->RelocateOffset(offsetExtra); - GetHitDest()->RelocateOffset(offsetExtra); - } - } - - void Register() override - { - OnEffectHit += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); - } - }; + PrepareSpellScript(spell_the_lich_king_summon_into_air); - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_summon_into_air_SpellScript(); + void ModDestHeight(SpellEffIndex /*effIndex*/) + { + static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f}; + WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest()); + dest->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); + // spirit bombs get higher + if (GetEffectInfo().MiscValue == NPC_SPIRIT_BOMB) + { + static Position const offsetExtra = { 0.0f, 0.0f, 5.0f, 0.0f }; + dest->RelocateOffset(offsetExtra); + GetHitDest()->RelocateOffset(offsetExtra); } + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_the_lich_king_summon_into_air::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + } }; -class spell_the_lich_king_soul_reaper : public SpellScriptLoader +class spell_the_lich_king_soul_reaper : public AuraScript { - public: - spell_the_lich_king_soul_reaper() : SpellScriptLoader("spell_the_lich_king_soul_reaper") { } - - class spell_the_lich_king_soul_reaper_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_soul_reaper_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_SOUL_REAPER_BUFF }); - } + PrepareAuraScript(spell_the_lich_king_soul_reaper); - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* caster = GetCaster()) - GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_SOUL_REAPER_BUFF }); + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_reaper_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); - } - }; + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + GetTarget()->CastSpell(caster, SPELL_SOUL_REAPER_BUFF, true); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_soul_reaper_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_reaper::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); + } }; -class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader +class spell_the_lich_king_valkyr_target_search : public SpellScript { - public: - spell_the_lich_king_valkyr_target_search() : SpellScriptLoader("spell_the_lich_king_valkyr_target_search") { } - - class spell_the_lich_king_valkyr_target_search_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_valkyr_target_search_SpellScript); + PrepareSpellScript(spell_the_lich_king_valkyr_target_search); - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_CHARGE }); - } - - void SelectTarget(std::list<WorldObject*>& targets) - { - if (targets.empty()) - return; + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_CHARGE }); + } - targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); - if (targets.empty()) - return; + void SelectTarget(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; - _target = Trinity::Containers::SelectRandomContainerElement(targets); - targets.clear(); - targets.push_back(_target); - GetCaster()->GetAI()->SetGUID(_target->GetGUID()); - } + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + if (targets.empty()) + return; - void ReplaceTarget(std::list<WorldObject*>& targets) - { - targets.clear(); - if (_target) - targets.push_back(_target); - } + _target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(_target); + GetCaster()->GetAI()->SetGUID(_target->GetGUID()); + } - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetCaster()->CastSpell(GetHitUnit(), SPELL_CHARGE, true); - } + void ReplaceTarget(std::list<WorldObject*>& targets) + { + targets.clear(); + if (_target) + targets.push_back(_target); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_valkyr_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), SPELL_CHARGE, true); + } - WorldObject* _target = nullptr; - }; + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_valkyr_target_search::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_valkyr_target_search_SpellScript(); - } + WorldObject* _target = nullptr; }; -class spell_the_lich_king_cast_back_to_caster : public SpellScriptLoader +class spell_the_lich_king_cast_back_to_caster : public SpellScript { - public: - spell_the_lich_king_cast_back_to_caster() : SpellScriptLoader("spell_the_lich_king_cast_back_to_caster") { } - - class spell_the_lich_king_cast_back_to_caster_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_cast_back_to_caster_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true); - } + PrepareSpellScript(spell_the_lich_king_cast_back_to_caster); - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_cast_back_to_caster_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_cast_back_to_caster_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_cast_back_to_caster::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_the_lich_king_life_siphon : public SpellScriptLoader +class spell_the_lich_king_life_siphon : public SpellScript { - public: - spell_the_lich_king_life_siphon() : SpellScriptLoader("spell_the_lich_king_life_siphon") { } - - class spell_the_lich_king_life_siphon_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_life_siphon_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_LIFE_SIPHON_HEAL }); - } + PrepareSpellScript(spell_the_lich_king_life_siphon); - void TriggerHeal() - { - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.AddSpellBP0(GetHitDamage() * 10); - GetHitUnit()->CastSpell(GetCaster(), SPELL_LIFE_SIPHON_HEAL, args); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_LIFE_SIPHON_HEAL }); + } - void Register() override - { - AfterHit += SpellHitFn(spell_the_lich_king_life_siphon_SpellScript::TriggerHeal); - } - }; + void TriggerHeal() + { + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.AddSpellBP0(GetHitDamage() * 10); + GetHitUnit()->CastSpell(GetCaster(), SPELL_LIFE_SIPHON_HEAL, args); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_life_siphon_SpellScript(); - } + void Register() override + { + AfterHit += SpellHitFn(spell_the_lich_king_life_siphon::TriggerHeal); + } }; -class spell_the_lich_king_vile_spirits : public SpellScriptLoader +class spell_the_lich_king_vile_spirits : public AuraScript { - public: - spell_the_lich_king_vile_spirits() : SpellScriptLoader("spell_the_lich_king_vile_spirits") { } + PrepareAuraScript(spell_the_lich_king_vile_spirits); - class spell_the_lich_king_vile_spirits_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_vile_spirits_AuraScript); - - public: - spell_the_lich_king_vile_spirits_AuraScript() - { - _is25Man = false; - } - - private: - bool Load() override - { - _is25Man = GetUnitOwner()->GetMap()->Is25ManRaid(); - return true; - } +public: + spell_the_lich_king_vile_spirits() + { + _is25Man = false; + } - void OnPeriodic(AuraEffect const* aurEff) - { - if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5)) - GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, CastSpellExtraArgs(aurEff) - .SetOriginalCaster(GetCasterGUID())); - } +private: + bool Load() override + { + _is25Man = GetUnitOwner()->GetMap()->Is25ManRaid(); + return true; + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_vile_spirits_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } + void OnPeriodic(AuraEffect const* aurEff) + { + if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5)) + GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, CastSpellExtraArgs(aurEff) + .SetOriginalCaster(GetCasterGUID())); + } - bool _is25Man; - }; + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_vile_spirits::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_vile_spirits_AuraScript(); - } + bool _is25Man; }; -class spell_the_lich_king_vile_spirits_visual : public SpellScriptLoader +class spell_the_lich_king_vile_spirits_visual : public SpellScript { - public: - spell_the_lich_king_vile_spirits_visual() : SpellScriptLoader("spell_the_lich_king_vile_spirits_visual") { } + PrepareSpellScript(spell_the_lich_king_vile_spirits_visual); - class spell_the_lich_king_vile_spirits_visual_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_vile_spirits_visual_SpellScript); - - void ModDestHeight(SpellEffIndex /*effIndex*/) - { - Position offset = {0.0f, 0.0f, 15.0f, 0.0f}; - const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); - } - - void Register() override - { - OnEffectLaunch += SpellEffectFn(spell_the_lich_king_vile_spirits_visual_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; + void ModDestHeight(SpellEffIndex /*effIndex*/) + { + Position offset = {0.0f, 0.0f, 15.0f, 0.0f}; + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_vile_spirits_visual_SpellScript(); - } + void Register() override + { + OnEffectLaunch += SpellEffectFn(spell_the_lich_king_vile_spirits_visual::ModDestHeight, EFFECT_0, SPELL_EFFECT_DUMMY); + } }; -class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoader +class spell_the_lich_king_vile_spirit_move_target_search : public SpellScript { - public: - spell_the_lich_king_vile_spirit_move_target_search() : SpellScriptLoader("spell_the_lich_king_vile_spirit_move_target_search") { } - - class spell_the_lich_king_vile_spirit_move_target_search_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_vile_spirit_move_target_search_SpellScript); - - public: - spell_the_lich_king_vile_spirit_move_target_search_SpellScript() - { - _target = nullptr; - } + PrepareSpellScript(spell_the_lich_king_vile_spirit_move_target_search); - private: - bool Load() override - { - return GetCaster()->GetTypeId() == TYPEID_UNIT; - } +public: + spell_the_lich_king_vile_spirit_move_target_search() + { + _target = nullptr; + } - void SelectTarget(std::list<WorldObject*>& targets) - { - if (targets.empty()) - return; +private: + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } - _target = Trinity::Containers::SelectRandomContainerElement(targets); - } + void SelectTarget(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - // for this spell, all units are in target map, however it should select one to attack - if (GetHitUnit() != _target) - return; + _target = Trinity::Containers::SelectRandomContainerElement(targets); + } - GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); - GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), 100000.0f); - } + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + // for this spell, all units are in target map, however it should select one to attack + if (GetHitUnit() != _target) + return; - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } + GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); + GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), 100000.0f); + } - WorldObject* _target; - }; + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_move_target_search::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_vile_spirit_move_target_search::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_vile_spirit_move_target_search_SpellScript(); - } + WorldObject* _target; }; -class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptLoader +class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScript { - public: - spell_the_lich_king_vile_spirit_damage_target_search() : SpellScriptLoader("spell_the_lich_king_vile_spirit_damage_target_search") { } - - class spell_the_lich_king_vile_spirit_damage_target_search_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript); + PrepareSpellScript(spell_the_lich_king_vile_spirit_damage_target_search); - bool Load() override - { - return GetCaster()->GetTypeId() == TYPEID_UNIT; - } - - void CheckTargetCount(std::list<WorldObject*>& targets) - { - if (targets.empty()) - return; - - // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this - // searcher spell will be blocked - if (TempSummon* summon = GetCaster()->ToTempSummon()) - if (Unit* summoner = summon->GetSummonerUnit()) - summoner->GetAI()->SetData(DATA_VILE, 1); - GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true); - GetCaster()->ToCreature()->DespawnOrUnsummon(3s); - GetCaster()->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - } + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; + void CheckTargetCount(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; + + // this spell has SPELL_AURA_BLOCK_SPELL_FAMILY so every next cast of this + // searcher spell will be blocked + if (TempSummon* summon = GetCaster()->ToTempSummon()) + if (Unit* summoner = summon->GetSummonerUnit()) + summoner->GetAI()->SetData(DATA_VILE, 1); + GetCaster()->CastSpell(nullptr, SPELL_SPIRIT_BURST, true); + GetCaster()->ToCreature()->DespawnOrUnsummon(3s); + GetCaster()->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_vile_spirit_damage_target_search_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_damage_target_search::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } }; -class spell_the_lich_king_harvest_soul : public SpellScriptLoader +class spell_the_lich_king_harvest_soul : public AuraScript { - public: - spell_the_lich_king_harvest_soul() : SpellScriptLoader("spell_the_lich_king_harvest_soul") { } - - class spell_the_lich_king_harvest_soul_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_harvest_soul_AuraScript); + PrepareAuraScript(spell_the_lich_king_harvest_soul); - bool Load() override - { - return GetOwner()->GetInstanceScript() != nullptr; - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - // m_originalCaster to allow stacking from different casters, meh - if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) - GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING))); - } + bool Load() override + { + return GetOwner()->GetInstanceScript() != nullptr; + } - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_harvest_soul_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); - } - }; + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + // m_originalCaster to allow stacking from different casters, meh + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) + GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING))); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_harvest_soul_AuraScript(); - } + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_harvest_soul::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_the_lich_king_lights_favor : public SpellScriptLoader +class spell_the_lich_king_lights_favor : public AuraScript { - public: - spell_the_lich_king_lights_favor() : SpellScriptLoader("spell_the_lich_king_lights_favor") { } + PrepareAuraScript(spell_the_lich_king_lights_favor); - class spell_the_lich_king_lights_favor_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_lights_favor_AuraScript); - - void OnPeriodic(AuraEffect const* /*aurEff*/) - { - if (Unit* caster = GetCaster()) - if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1)) - effect->RecalculateAmount(caster); - } - - void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) - { - canBeRecalculated = true; - amount = 0; - if (Unit* caster = GetCaster()) - amount = int32(caster->GetHealthPct()); - } + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + if (AuraEffect* effect = GetAura()->GetEffect(EFFECT_1)) + effect->RecalculateAmount(caster); + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_lights_favor_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_the_lich_king_lights_favor_AuraScript::CalculateBonus, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - } - }; + void CalculateBonus(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = true; + amount = 0; + if (Unit* caster = GetCaster()) + amount = int32(caster->GetHealthPct()); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_lights_favor_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_lights_favor::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_the_lich_king_lights_favor::CalculateBonus, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + } }; -class spell_the_lich_king_soul_rip : public SpellScriptLoader +class spell_the_lich_king_soul_rip : public AuraScript { - public: - spell_the_lich_king_soul_rip() : SpellScriptLoader("spell_the_lich_king_soul_rip") { } - - class spell_the_lich_king_soul_rip_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_soul_rip_AuraScript); - - void OnPeriodic(AuraEffect const* aurEff) - { - PreventDefaultAction(); - // shouldn't be needed, this is channeled - if (Unit* caster = GetCaster()) - { - CastSpellExtraArgs args(aurEff); - args.OriginalCaster = GetCasterGUID(); - args.AddSpellBP0(5000 * aurEff->GetTickNumber()); - caster->CastSpell(GetTarget(), SPELL_SOUL_RIP_DAMAGE, args); - } - } + PrepareAuraScript(spell_the_lich_king_soul_rip); - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_rip_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_soul_rip_AuraScript(); + void OnPeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + // shouldn't be needed, this is channeled + if (Unit* caster = GetCaster()) + { + CastSpellExtraArgs args(aurEff); + args.OriginalCaster = GetCasterGUID(); + args.AddSpellBP0(5000 * aurEff->GetTickNumber()); + caster->CastSpell(GetTarget(), SPELL_SOUL_RIP_DAMAGE, args); } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_the_lich_king_soul_rip::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } }; -class spell_the_lich_king_restore_soul : public SpellScriptLoader +class spell_the_lich_king_restore_soul : public SpellScript { - public: - spell_the_lich_king_restore_soul() : SpellScriptLoader("spell_the_lich_king_restore_soul") { } + PrepareSpellScript(spell_the_lich_king_restore_soul); - class spell_the_lich_king_restore_soul_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_restore_soul_SpellScript); - - public: - spell_the_lich_king_restore_soul_SpellScript() - { - _instance = nullptr; - } - - private: - bool Load() override - { - _instance = GetCaster()->GetInstanceScript(); - return _instance != nullptr; - } +public: + spell_the_lich_king_restore_soul() + { + _instance = nullptr; + } - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*GetCaster(), _instance->GetGuidData(DATA_THE_LICH_KING))) - lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); - if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f)) - spawner->RemoveAllAuras(); - - std::list<Creature*> spirits; - GetCaster()->GetCreatureListWithEntryInGrid(spirits, NPC_WICKED_SPIRIT, 200.0f); - for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr) - { - (*itr)->m_Events.KillAllEvents(true); - (*itr)->SetReactState(REACT_PASSIVE); - (*itr)->AI()->EnterEvadeMode(); - } - } +private: + bool Load() override + { + _instance = GetCaster()->GetInstanceScript(); + return _instance != nullptr; + } - void RemoveAura(SpellMissInfo missInfo) - { - if (missInfo != SPELL_MISS_NONE) - return; + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Creature* lichKing = ObjectAccessor::GetCreature(*GetCaster(), _instance->GetGuidData(DATA_THE_LICH_KING))) + lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); + if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f)) + spawner->RemoveAllAuras(); + + std::list<Creature*> spirits; + GetCaster()->GetCreatureListWithEntryInGrid(spirits, NPC_WICKED_SPIRIT, 200.0f); + for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr) + { + (*itr)->m_Events.KillAllEvents(true); + (*itr)->SetReactState(REACT_PASSIVE); + (*itr)->AI()->EnterEvadeMode(); + } + } - if (Unit* target = GetHitUnit()) - target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT); - } + void RemoveAura(SpellMissInfo missInfo) + { + if (missInfo != SPELL_MISS_NONE) + return; - void Register() override - { - OnEffectHit += SpellEffectFn(spell_the_lich_king_restore_soul_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - BeforeHit += BeforeSpellHitFn(spell_the_lich_king_restore_soul_SpellScript::RemoveAura); - } + if (Unit* target = GetHitUnit()) + target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT); + } - InstanceScript* _instance; - }; + void Register() override + { + OnEffectHit += SpellEffectFn(spell_the_lich_king_restore_soul::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + BeforeHit += BeforeSpellHitFn(spell_the_lich_king_restore_soul::RemoveAura); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_restore_soul_SpellScript(); - } + InstanceScript* _instance; }; -class spell_the_lich_king_dark_hunger : public SpellScriptLoader +class spell_the_lich_king_dark_hunger : public AuraScript { - public: - spell_the_lich_king_dark_hunger() : SpellScriptLoader("spell_the_lich_king_dark_hunger") { } - - class spell_the_lich_king_dark_hunger_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_dark_hunger_AuraScript); + PrepareAuraScript(spell_the_lich_king_dark_hunger); - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo({ SPELL_DARK_HUNGER_HEAL }); - } - - void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) - { - PreventDefaultAction(); - DamageInfo* damageInfo = eventInfo.GetDamageInfo(); - if (!damageInfo || !damageInfo->GetDamage()) - return; - - CastSpellExtraArgs args(aurEff); - args.AddSpellBP0(damageInfo->GetDamage() / 2); - GetTarget()->CastSpell(GetTarget(), SPELL_DARK_HUNGER_HEAL, args); - } + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_DARK_HUNGER_HEAL }); + } - void Register() override - { - OnEffectProc += AuraEffectProcFn(spell_the_lich_king_dark_hunger_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); - } - }; + void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + DamageInfo* damageInfo = eventInfo.GetDamageInfo(); + if (!damageInfo || !damageInfo->GetDamage()) + return; + + CastSpellExtraArgs args(aurEff); + args.AddSpellBP0(damageInfo->GetDamage() / 2); + GetTarget()->CastSpell(GetTarget(), SPELL_DARK_HUNGER_HEAL, args); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_dark_hunger_AuraScript(); - } + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_the_lich_king_dark_hunger::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } }; -class spell_the_lich_king_in_frostmourne_room : public SpellScriptLoader +class spell_the_lich_king_in_frostmourne_room : public AuraScript { - public: - spell_the_lich_king_in_frostmourne_room() : SpellScriptLoader("spell_the_lich_king_in_frostmourne_room") { } - - class spell_the_lich_king_in_frostmourne_room_AuraScript : public AuraScript - { - PrepareAuraScript(spell_the_lich_king_in_frostmourne_room_AuraScript); + PrepareAuraScript(spell_the_lich_king_in_frostmourne_room); - bool Load() override - { - return GetOwner()->GetInstanceScript() != nullptr; - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - // m_originalCaster to allow stacking from different casters, meh - if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) - GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING))); - } + bool Load() override + { + return GetOwner()->GetInstanceScript() != nullptr; + } - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_in_frostmourne_room_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + // m_originalCaster to allow stacking from different casters, meh + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH) + GetTarget()->CastSpell(nullptr, SPELL_HARVESTED_SOUL, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(GetTarget()->GetInstanceScript()->GetGuidData(DATA_THE_LICH_KING))); + } - AuraScript* GetAuraScript() const override - { - return new spell_the_lich_king_in_frostmourne_room_AuraScript(); - } + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_the_lich_king_in_frostmourne_room::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_the_lich_king_summon_spirit_bomb : public SpellScriptLoader +class spell_the_lich_king_summon_spirit_bomb : public SpellScript { - public: - spell_the_lich_king_summon_spirit_bomb() : SpellScriptLoader("spell_the_lich_king_summon_spirit_bomb") { } + PrepareSpellScript(spell_the_lich_king_summon_spirit_bomb); - class spell_the_lich_king_summon_spirit_bomb_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_summon_spirit_bomb_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(nullptr, uint32(GetEffectValue()), true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_summon_spirit_bomb_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(nullptr, uint32(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_summon_spirit_bomb_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_summon_spirit_bomb::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_the_lich_king_trigger_vile_spirit : public SpellScriptLoader +class spell_the_lich_king_trigger_vile_spirit : public SpellScript { - public: - spell_the_lich_king_trigger_vile_spirit() : SpellScriptLoader("spell_the_lich_king_trigger_vile_spirit") { } - - class spell_the_lich_king_trigger_vile_spirit_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit_SpellScript); - - void ActivateSpirit() - { - Creature* target = GetHitCreature(); - if (!target) - return; + PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit); - VileSpiritActivateEvent(target).Execute(0, 0); - } + void ActivateSpirit() + { + Creature* target = GetHitCreature(); + if (!target) + return; - void Register() override - { - OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::ActivateSpirit); - } - }; + VileSpiritActivateEvent(target).Execute(0, 0); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_trigger_vile_spirit_SpellScript(); - } + void Register() override + { + OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit::ActivateSpirit); + } }; -class spell_the_lich_king_jump : public SpellScriptLoader +class spell_the_lich_king_jump : public SpellScript { - public: - spell_the_lich_king_jump() : SpellScriptLoader("spell_the_lich_king_jump") { } - - class spell_the_lich_king_jump_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_jump_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit()->RemoveAurasDueToSpell(SPELL_RAISE_DEAD); - GetHitUnit()->CastSpell(nullptr, SPELL_JUMP_2, true); - if (Creature* creature = GetHitCreature()) - creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE); - } + PrepareSpellScript(spell_the_lich_king_jump); - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->RemoveAurasDueToSpell(SPELL_RAISE_DEAD); + GetHitUnit()->CastSpell(nullptr, SPELL_JUMP_2, true); + if (Creature* creature = GetHitCreature()) + creature->AI()->DoAction(ACTION_BREAK_FROSTMOURNE); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_jump_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_the_lich_king_jump_remove_aura : public SpellScriptLoader +class spell_the_lich_king_jump_remove_aura : public SpellScript { - public: - spell_the_lich_king_jump_remove_aura() : SpellScriptLoader("spell_the_lich_king_jump_remove_aura") { } + PrepareSpellScript(spell_the_lich_king_jump_remove_aura); - class spell_the_lich_king_jump_SpellScript : public SpellScript - { - PrepareSpellScript(spell_the_lich_king_jump_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit()->RemoveAurasDueToSpell(uint32(GetEffectValue())); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->RemoveAurasDueToSpell(uint32(GetEffectValue())); + } - SpellScript* GetSpellScript() const override - { - return new spell_the_lich_king_jump_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_jump_remove_aura::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_the_lich_king_harvest_souls_teleport : public SpellScriptLoader +class spell_the_lich_king_harvest_souls_teleport : public SpellScript { -public: - spell_the_lich_king_harvest_souls_teleport() : SpellScriptLoader("spell_the_lich_king_harvest_souls_teleport") { } + PrepareSpellScript(spell_the_lich_king_harvest_souls_teleport); - class spell_the_lich_king_harvest_souls_teleport_SpellScript : public SpellScript + void RelocateTransportOffset(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_the_lich_king_harvest_souls_teleport_SpellScript); - - void RelocateTransportOffset(SpellEffIndex /*effIndex*/) - { - float randCoordX = frand(-18.0f, 18.0f); - float randCoordY = frand(-18.0f, 18.0f); - GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f }); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_harvest_souls_teleport_SpellScript::RelocateTransportOffset, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS); - } - }; + float randCoordX = frand(-18.0f, 18.0f); + float randCoordY = frand(-18.0f, 18.0f); + GetHitDest()->RelocateOffset({ randCoordX, randCoordY, 0.0f, 0.0f }); + } - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_the_lich_king_harvest_souls_teleport_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_harvest_souls_teleport::RelocateTransportOffset, EFFECT_1, SPELL_EFFECT_TELEPORT_UNITS); } }; @@ -3264,46 +2808,51 @@ class achievement_neck_deep_in_vile : public AchievementCriteriaScript void AddSC_boss_the_lich_king() { - new boss_the_lich_king(); - new npc_tirion_fordring_tft(); - new npc_shambling_horror_icc(); - new npc_raging_spirit(); - new npc_valkyr_shadowguard(); - new npc_strangulate_vehicle(); - new npc_terenas_menethil(); - new npc_spirit_warden(); - new npc_spirit_bomb(); - new npc_broken_frostmourne(); - new spell_the_lich_king_infest(); - new spell_the_lich_king_necrotic_plague(); - new spell_the_lich_king_necrotic_plague_jump(); - new spell_the_lich_king_shadow_trap_visual(); - new spell_the_lich_king_shadow_trap_periodic(); - new spell_the_lich_king_quake(); - new spell_the_lich_king_ice_burst_target_search(); - new spell_the_lich_king_raging_spirit(); - new spell_the_lich_king_defile(); - new spell_the_lich_king_summon_into_air(); - new spell_the_lich_king_soul_reaper(); - new spell_the_lich_king_valkyr_target_search(); - new spell_the_lich_king_cast_back_to_caster(); - new spell_the_lich_king_life_siphon(); - new spell_the_lich_king_vile_spirits(); - new spell_the_lich_king_vile_spirits_visual(); - new spell_the_lich_king_vile_spirit_move_target_search(); - new spell_the_lich_king_vile_spirit_damage_target_search(); - new spell_the_lich_king_harvest_soul(); - new spell_the_lich_king_lights_favor(); - new spell_the_lich_king_soul_rip(); - new spell_the_lich_king_restore_soul(); - new spell_the_lich_king_dark_hunger(); - new spell_the_lich_king_in_frostmourne_room(); - new spell_the_lich_king_summon_spirit_bomb(); - new spell_the_lich_king_trigger_vile_spirit(); - new spell_the_lich_king_jump(); - new spell_the_lich_king_jump_remove_aura(); + // Creatures + RegisterIcecrownCitadelCreatureAI(boss_the_lich_king); + RegisterIcecrownCitadelCreatureAI(npc_tirion_fordring_tft); + RegisterIcecrownCitadelCreatureAI(npc_shambling_horror_icc); + RegisterIcecrownCitadelCreatureAI(npc_raging_spirit); + RegisterIcecrownCitadelCreatureAI(npc_valkyr_shadowguard); + RegisterIcecrownCitadelCreatureAI(npc_strangulate_vehicle); + RegisterIcecrownCitadelCreatureAI(npc_terenas_menethil); + RegisterIcecrownCitadelCreatureAI(npc_spirit_warden); + RegisterIcecrownCitadelCreatureAI(npc_spirit_bomb); + RegisterIcecrownCitadelCreatureAI(npc_broken_frostmourne); + + // Spells + RegisterSpellScript(spell_the_lich_king_infest); + RegisterSpellScript(spell_the_lich_king_necrotic_plague); + RegisterSpellAndAuraScriptPair(spell_the_lich_king_necrotic_plague_jump, spell_the_lich_king_necrotic_plague_jump_aura); + RegisterSpellScript(spell_the_lich_king_shadow_trap_visual); + RegisterSpellScript(spell_the_lich_king_shadow_trap_periodic); + RegisterSpellScript(spell_the_lich_king_quake); + RegisterSpellScript(spell_the_lich_king_ice_burst_target_search); + RegisterSpellScript(spell_the_lich_king_raging_spirit); + RegisterSpellScript(spell_the_lich_king_defile); + RegisterSpellScript(spell_the_lich_king_summon_into_air); + RegisterSpellScript(spell_the_lich_king_soul_reaper); + RegisterSpellScript(spell_the_lich_king_valkyr_target_search); + RegisterSpellScript(spell_the_lich_king_cast_back_to_caster); + RegisterSpellScript(spell_the_lich_king_life_siphon); + RegisterSpellScript(spell_the_lich_king_vile_spirits); + RegisterSpellScript(spell_the_lich_king_vile_spirits_visual); + RegisterSpellScript(spell_the_lich_king_vile_spirit_move_target_search); + RegisterSpellScript(spell_the_lich_king_vile_spirit_damage_target_search); + RegisterSpellScript(spell_the_lich_king_harvest_soul); + RegisterSpellScript(spell_the_lich_king_lights_favor); + RegisterSpellScript(spell_the_lich_king_soul_rip); + RegisterSpellScript(spell_the_lich_king_restore_soul); + RegisterSpellScript(spell_the_lich_king_dark_hunger); + RegisterSpellScript(spell_the_lich_king_in_frostmourne_room); + RegisterSpellScript(spell_the_lich_king_summon_spirit_bomb); + RegisterSpellScript(spell_the_lich_king_trigger_vile_spirit); + RegisterSpellScript(spell_the_lich_king_jump); + RegisterSpellScript(spell_the_lich_king_jump_remove_aura); new spell_trigger_spell_from_caster("spell_the_lich_king_mass_resurrection", SPELL_MASS_RESURRECTION_REAL); - new spell_the_lich_king_harvest_souls_teleport(); + RegisterSpellScript(spell_the_lich_king_harvest_souls_teleport); + + // Achievements new achievement_been_waiting_long_time(); new achievement_neck_deep_in_vile(); } |