diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp | 1804 |
1 files changed, 791 insertions, 1013 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index d4fe34984da..4dcd5bcd8d2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -256,1208 +256,981 @@ class ValithriaDespawner : public BasicEvent Creature* _creature; }; -class boss_valithria_dreamwalker : public CreatureScript +struct boss_valithria_dreamwalker : public ScriptedAI { - public: - boss_valithria_dreamwalker() : CreatureScript("boss_valithria_dreamwalker") - { - } - - struct boss_valithria_dreamwalkerAI : public ScriptedAI - { - boss_valithria_dreamwalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _portalCount(RAID_MODE<uint32>(3, 8, 3, 8)) - { - Initialize(); - _spawnHealth = me->GetHealth(); - } - - void Initialize() - { - _missedPortals = 0; - _under25PercentTalkDone = false; - _over75PercentTalkDone = false; - _justDied = false; - _done = false; - } + boss_valithria_dreamwalker(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _portalCount(RAID_MODE<uint32>(3, 8, 3, 8)) + { + Initialize(); + _spawnHealth = me->GetHealth(); + } - void InitializeAI() override - { - if (CreatureData const* data = me->GetCreatureData()) - if (data->curhealth) - _spawnHealth = data->curhealth; + void Initialize() + { + _missedPortals = 0; + _under25PercentTalkDone = false; + _over75PercentTalkDone = false; + _justDied = false; + _done = false; + } - ScriptedAI::InitializeAI(); - } + void InitializeAI() override + { + if (CreatureData const* data = me->GetCreatureData()) + if (data->curhealth) + _spawnHealth = data->curhealth; - void Reset() override - { - _events.Reset(); - me->SetHealth(_spawnHealth); - me->SetReactState(REACT_PASSIVE); - me->LoadCreaturesAddon(); - // immune to percent heals - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_OBS_MOD_HEALTH, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL_PCT, true); - // Glyph of Dispel Magic - not a percent heal by effect, its cast with custom basepoints - me->ApplySpellImmune(0, IMMUNITY_ID, 56131, true); - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - Initialize(); - } + ScriptedAI::InitializeAI(); + } - void AttackStart(Unit* /*target*/) override - { - } + void Reset() override + { + _events.Reset(); + me->SetHealth(_spawnHealth); + me->SetReactState(REACT_PASSIVE); + me->LoadCreaturesAddon(); + // immune to percent heals + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_OBS_MOD_HEALTH, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL_PCT, true); + // Glyph of Dispel Magic - not a percent heal by effect, its cast with custom basepoints + me->ApplySpellImmune(0, IMMUNITY_ID, 56131, true); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + Initialize(); + } - void DoAction(int32 action) override - { - if (action != ACTION_ENTER_COMBAT) - return; + void AttackStart(Unit* /*target*/) override + { + } - DoCastSelf(SPELL_COPY_DAMAGE); - _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - _events.ScheduleEvent(EVENT_INTRO_TALK, 15s); - _events.ScheduleEvent(EVENT_DREAM_PORTAL, 45s, 48s); - if (IsHeroic()) - _events.ScheduleEvent(EVENT_BERSERK, 420s); - } + void DoAction(int32 action) override + { + if (action != ACTION_ENTER_COMBAT) + return; + + DoCastSelf(SPELL_COPY_DAMAGE); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + _events.ScheduleEvent(EVENT_INTRO_TALK, 15s); + _events.ScheduleEvent(EVENT_DREAM_PORTAL, 45s, 48s); + if (IsHeroic()) + _events.ScheduleEvent(EVENT_BERSERK, 420s); + } - void HealReceived(Unit* healer, uint32& heal) override - { - if (!me->hasLootRecipient()) - me->SetLootRecipient(healer); + void HealReceived(Unit* healer, uint32& heal) override + { + if (!me->hasLootRecipient()) + me->SetLootRecipient(healer); - me->LowerPlayerDamageReq(heal); + me->LowerPlayerDamageReq(heal); - // encounter complete - if (me->HealthAbovePctHealed(100, heal) && !_done) - { - _done = true; - Talk(SAY_VALITHRIA_SUCCESS); - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->RemoveAurasDueToSpell(SPELL_CORRUPTION_VALITHRIA); - DoCastSelf(SPELL_ACHIEVEMENT_CHECK); - DoCastAOE(SPELL_DREAMWALKERS_RAGE); - _events.ScheduleEvent(EVENT_DREAM_SLIP, 3500ms); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) - lichKing->AI()->EnterEvadeMode(); - } - else if (!_over75PercentTalkDone && me->HealthAbovePctHealed(75, heal)) - { - _over75PercentTalkDone = true; - Talk(SAY_VALITHRIA_75_PERCENT); - } - else if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == NOT_STARTED) - { - if (Creature* archmage = me->FindNearestCreature(NPC_RISEN_ARCHMAGE, 30.0f)) - DoZoneInCombat(archmage); // on one of them, that will make it all start - } - } + // encounter complete + if (me->HealthAbovePctHealed(100, heal) && !_done) + { + _done = true; + Talk(SAY_VALITHRIA_SUCCESS); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->RemoveAurasDueToSpell(SPELL_CORRUPTION_VALITHRIA); + DoCastSelf(SPELL_ACHIEVEMENT_CHECK); + DoCastAOE(SPELL_DREAMWALKERS_RAGE); + _events.ScheduleEvent(EVENT_DREAM_SLIP, 3500ms); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) + lichKing->AI()->EnterEvadeMode(); + } + else if (!_over75PercentTalkDone && me->HealthAbovePctHealed(75, heal)) + { + _over75PercentTalkDone = true; + Talk(SAY_VALITHRIA_75_PERCENT); + } + else if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == NOT_STARTED) + { + if (Creature* archmage = me->FindNearestCreature(NPC_RISEN_ARCHMAGE, 30.0f)) + DoZoneInCombat(archmage); // on one of them, that will make it all start + } + } - void DamageTaken(Unit* /*attacker*/, uint32& damage) override + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (me->HealthBelowPctDamaged(25, damage)) + { + if (!_under25PercentTalkDone) { - if (me->HealthBelowPctDamaged(25, damage)) - { - if (!_under25PercentTalkDone) - { - _under25PercentTalkDone = true; - Talk(SAY_VALITHRIA_25_PERCENT); - } - - if (damage >= me->GetHealth()) - { - damage = 0; - if (!_justDied) - { - _justDied = true; - Talk(SAY_VALITHRIA_DEATH); - _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) - trigger->AI()->DoAction(ACTION_DEATH); - } - } - } + _under25PercentTalkDone = true; + Talk(SAY_VALITHRIA_25_PERCENT); } - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + if (damage >= me->GetHealth()) { - if (spellInfo->Id == SPELL_DREAM_SLIP) + damage = 0; + if (!_justDied) { - DoCastSelf(SPELL_CLEAR_ALL); - DoCastSelf(SPELL_REPUTATION_BOSS_KILL, true); - // this display id was found in sniff instead of the one on aura - me->SetDisplayId(11686); - me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->DespawnOrUnsummon(4s); + _justDied = true; + Talk(SAY_VALITHRIA_DEATH); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) - Unit::Kill(me, trigger); - - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) - lichKing->CastSpell(lichKing, SPELL_SPAWN_CHEST); - } - } - - void JustSummoned(Creature* summon) override - { - if (summon->GetEntry() == NPC_DREAM_PORTAL_PRE_EFFECT) - { - summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_SUMMON_DREAM_PORTAL, me->GetGUID(), 6s), summon->m_Events.CalculateTime(15s)); - summon->m_Events.AddEvent(new ValithriaAuraRemoveEvent(summon, SPELL_DREAM_PORTAL_VISUAL_PRE), summon->m_Events.CalculateTime(15s)); - } - else if (summon->GetEntry() == NPC_NIGHTMARE_PORTAL_PRE_EFFECT) - { - summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_SUMMON_NIGHTMARE_PORTAL, me->GetGUID(), 6s), summon->m_Events.CalculateTime(15s)); - summon->m_Events.AddEvent(new ValithriaAuraRemoveEvent(summon, SPELL_NIGHTMARE_PORTAL_VISUAL_PRE), summon->m_Events.CalculateTime(15s)); - } - } - - void SummonedCreatureDespawn(Creature* summon) override - { - if (summon->GetEntry() == NPC_DREAM_PORTAL || summon->GetEntry() == NPC_NIGHTMARE_PORTAL) - if (summon->AI()->GetData(MISSED_PORTALS)) - ++_missedPortals; - } - - void UpdateAI(uint32 diff) override - { - // does not enter combat - if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) - return; - - _events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_INTRO_TALK: - Talk(SAY_VALITHRIA_ENTER_COMBAT); - break; - case EVENT_BERSERK: - Talk(SAY_VALITHRIA_BERSERK); - break; - case EVENT_DREAM_PORTAL: - if (!IsHeroic()) - Talk(SAY_VALITHRIA_DREAM_PORTAL); - for (uint32 i = 0; i < _portalCount; ++i) - DoCastSelf(SUMMON_PORTAL); - _events.ScheduleEvent(EVENT_DREAM_PORTAL, 45s, 48s); - break; - case EVENT_DREAM_SLIP: - DoCastSelf(SPELL_DREAM_SLIP); - break; - default: - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + trigger->AI()->DoAction(ACTION_DEATH); } } + } + } - uint32 GetData(uint32 type) const override - { - if (type == MISSED_PORTALS) - return _missedPortals; - - return 0; - } - - private: - EventMap _events; - InstanceScript* _instance; - uint32 _spawnHealth; - uint32 const _portalCount; - uint32 _missedPortals; - bool _under25PercentTalkDone; - bool _over75PercentTalkDone; - bool _justDied; - bool _done; - }; - - CreatureAI* GetAI(Creature* creature) const override + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_DREAM_SLIP) { - return GetIcecrownCitadelAI<boss_valithria_dreamwalkerAI>(creature); + DoCastSelf(SPELL_CLEAR_ALL); + DoCastSelf(SPELL_REPUTATION_BOSS_KILL, true); + // this display id was found in sniff instead of the one on aura + me->SetDisplayId(11686); + me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->DespawnOrUnsummon(4s); + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) + Unit::Kill(me, trigger); + + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) + lichKing->CastSpell(lichKing, SPELL_SPAWN_CHEST); } -}; - -class npc_green_dragon_combat_trigger : public CreatureScript -{ - public: - npc_green_dragon_combat_trigger() : CreatureScript("npc_green_dragon_combat_trigger") { } + } - struct npc_green_dragon_combat_triggerAI : public BossAI + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_DREAM_PORTAL_PRE_EFFECT) { - npc_green_dragon_combat_triggerAI(Creature* creature) : BossAI(creature, DATA_VALITHRIA_DREAMWALKER) - { - } - - void Reset() override - { - _Reset(); - me->SetReactState(REACT_PASSIVE); - summons.DespawnAll(); - // Setup Archmages - me->SummonCreatureGroup(SUMMON_GROUP_ALL); - if (Is25ManRaid()) - me->SummonCreatureGroup(SUMMON_GROUP_25); - else - me->SummonCreatureGroup(SUMMON_GROUP_10); - - EntryCheckPredicate pred(NPC_RISEN_ARCHMAGE); - summons.DoAction(ACTION_SETUP_ARCHMAGES, pred); - } - - void JustEnteredCombat(Unit* target) override - { - if (IsEngaged()) - return; - - if (!instance->CheckRequiredBosses(DATA_VALITHRIA_DREAMWALKER, target->ToPlayer())) - { - EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); - instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); - return; - } - - EngagementStart(target); + summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_SUMMON_DREAM_PORTAL, me->GetGUID(), 6s), summon->m_Events.CalculateTime(15s)); + summon->m_Events.AddEvent(new ValithriaAuraRemoveEvent(summon, SPELL_DREAM_PORTAL_VISUAL_PRE), summon->m_Events.CalculateTime(15s)); + } + else if (summon->GetEntry() == NPC_NIGHTMARE_PORTAL_PRE_EFFECT) + { + summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_SUMMON_NIGHTMARE_PORTAL, me->GetGUID(), 6s), summon->m_Events.CalculateTime(15s)); + summon->m_Events.AddEvent(new ValithriaAuraRemoveEvent(summon, SPELL_NIGHTMARE_PORTAL_VISUAL_PRE), summon->m_Events.CalculateTime(15s)); + } + } - me->setActive(true); - DoZoneInCombat(); - instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, IN_PROGRESS); - if (Creature* valithria = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))) - valithria->AI()->DoAction(ACTION_ENTER_COMBAT); - EntryCheckPredicate pred(NPC_RISEN_ARCHMAGE); - summons.DoAction(ACTION_ENTER_COMBAT, pred); - } + void SummonedCreatureDespawn(Creature* summon) override + { + if (summon->GetEntry() == NPC_DREAM_PORTAL || summon->GetEntry() == NPC_NIGHTMARE_PORTAL) + if (summon->AI()->GetData(MISSED_PORTALS)) + ++_missedPortals; + } - void JustExitedCombat() override - { - EngagementOver(); + void UpdateAI(uint32 diff) override + { + // does not enter combat + if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) + return; - me->setActive(false); + _events.Update(diff); - // JustExitedCombat is called on death too, so if creature is dead, avoid "respawn" event - if (!me->IsAlive()) - return; - DoAction(ACTION_DEATH); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void DoAction(int32 action) override + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - if (action == ACTION_DEATH) - { - instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED); - me->m_Events.AddEventAtOffset(new ValithriaDespawner(me), 5s); - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) - lichKing->AI()->EnterEvadeMode(); - } + case EVENT_INTRO_TALK: + Talk(SAY_VALITHRIA_ENTER_COMBAT); + break; + case EVENT_BERSERK: + Talk(SAY_VALITHRIA_BERSERK); + break; + case EVENT_DREAM_PORTAL: + if (!IsHeroic()) + Talk(SAY_VALITHRIA_DREAM_PORTAL); + for (uint32 i = 0; i < _portalCount; ++i) + DoCastSelf(SUMMON_PORTAL); + _events.ScheduleEvent(EVENT_DREAM_PORTAL, 45s, 48s); + break; + case EVENT_DREAM_SLIP: + DoCastSelf(SPELL_DREAM_SLIP); + break; + default: + break; } - }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_green_dragon_combat_triggerAI>(creature); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } -}; + } -class npc_the_lich_king_controller : public CreatureScript -{ - public: - npc_the_lich_king_controller() : CreatureScript("npc_the_lich_king_controller") { } + uint32 GetData(uint32 type) const override + { + if (type == MISSED_PORTALS) + return _missedPortals; - struct npc_the_lich_king_controllerAI : public ScriptedAI - { - npc_the_lich_king_controllerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) - { - } + return 0; + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_GLUTTONOUS_ABOMINATION_SUMMONER, 5s); - _events.ScheduleEvent(EVENT_SUPPRESSER_SUMMONER, 10s); - _events.ScheduleEvent(EVENT_BLISTERING_ZOMBIE_SUMMONER, 15s); - _events.ScheduleEvent(EVENT_RISEN_ARCHMAGE_SUMMONER, 20s); - _events.ScheduleEvent(EVENT_BLAZING_SKELETON_SUMMONER, 30s); - me->SetReactState(REACT_PASSIVE); - } +private: + EventMap _events; + InstanceScript* _instance; + uint32 _spawnHealth; + uint32 const _portalCount; + uint32 _missedPortals; + bool _under25PercentTalkDone; + bool _over75PercentTalkDone; + bool _justDied; + bool _done; +}; - void JustReachedHome() override - { - me->setActive(false); - } +struct npc_green_dragon_combat_trigger : public BossAI +{ + npc_green_dragon_combat_trigger(Creature* creature) : BossAI(creature, DATA_VALITHRIA_DREAMWALKER) { } - void JustEngagedWith(Unit* /*target*/) override - { - Talk(SAY_LICH_KING_INTRO); - me->setActive(true); - } + void Reset() override + { + _Reset(); + me->SetReactState(REACT_PASSIVE); + summons.DespawnAll(); + // Setup Archmages + me->SummonCreatureGroup(SUMMON_GROUP_ALL); + if (Is25ManRaid()) + me->SummonCreatureGroup(SUMMON_GROUP_25); + else + me->SummonCreatureGroup(SUMMON_GROUP_10); + + EntryCheckPredicate pred(NPC_RISEN_ARCHMAGE); + summons.DoAction(ACTION_SETUP_ARCHMAGES, pred); + } - uint32 GetData(uint32 data) const override - { - if (data == DATA_SUPPRESSERS_COUNT) - return RAID_MODE<uint32>(4, 6, 4, 6); - else - return 0; - } + void JustEnteredCombat(Unit* target) override + { + if (IsEngaged()) + return; - void JustSummoned(Creature* summon) override - { - // must not be in dream phase - PhasingHandler::RemovePhase(summon, 173, true); - DoZoneInCombat(summon); - if (summon->GetEntry() != NPC_SUPPRESSER) - if (Unit* target = me->GetCombatManager().GetAnyTarget()) - summon->AI()->AttackStart(target); - } + if (!instance->CheckRequiredBosses(DATA_VALITHRIA_DREAMWALKER, target->ToPlayer())) + { + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); + instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); + return; + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + EngagementStart(target); - _events.Update(diff); + me->setActive(true); + DoZoneInCombat(); + instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, IN_PROGRESS); + if (Creature* valithria = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))) + valithria->AI()->DoAction(ACTION_ENTER_COMBAT); + EntryCheckPredicate pred(NPC_RISEN_ARCHMAGE); + summons.DoAction(ACTION_ENTER_COMBAT, pred); + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + void JustExitedCombat() override + { + EngagementOver(); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_GLUTTONOUS_ABOMINATION_SUMMONER: - DoCastSelf(SPELL_TIMER_GLUTTONOUS_ABOMINATION); - break; - case EVENT_SUPPRESSER_SUMMONER: - DoCastSelf(SPELL_TIMER_SUPPRESSER); - break; - case EVENT_BLISTERING_ZOMBIE_SUMMONER: - DoCastSelf(SPELL_TIMER_BLISTERING_ZOMBIE); - break; - case EVENT_RISEN_ARCHMAGE_SUMMONER: - DoCastSelf(SPELL_TIMER_RISEN_ARCHMAGE); - break; - case EVENT_BLAZING_SKELETON_SUMMONER: - DoCastSelf(SPELL_TIMER_BLAZING_SKELETON); - break; - default: - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } - } + me->setActive(false); - private: - EventMap _events; - InstanceScript* _instance; - }; + // JustExitedCombat is called on death too, so if creature is dead, avoid "respawn" event + if (!me->IsAlive()) + return; + DoAction(ACTION_DEATH); + } - CreatureAI* GetAI(Creature* creature) const override + void DoAction(int32 action) override + { + if (action == ACTION_DEATH) { - return GetIcecrownCitadelAI<npc_the_lich_king_controllerAI>(creature); + instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED); + me->m_Events.AddEventAtOffset(new ValithriaDespawner(me), 5s); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) + lichKing->AI()->EnterEvadeMode(); } + } }; -class npc_risen_archmage : public CreatureScript +struct npc_the_lich_king_controller : public ScriptedAI { - public: - npc_risen_archmage() : CreatureScript("npc_risen_archmage") { } - - struct npc_risen_archmageAI : public ScriptedAI - { - npc_risen_archmageAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) - { - Initialize(); - } + npc_the_lich_king_controller(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - void Initialize() - { - _isInitialArchmage = false; - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_GLUTTONOUS_ABOMINATION_SUMMONER, 5s); + _events.ScheduleEvent(EVENT_SUPPRESSER_SUMMONER, 10s); + _events.ScheduleEvent(EVENT_BLISTERING_ZOMBIE_SUMMONER, 15s); + _events.ScheduleEvent(EVENT_RISEN_ARCHMAGE_SUMMONER, 20s); + _events.ScheduleEvent(EVENT_BLAZING_SKELETON_SUMMONER, 30s); + me->SetReactState(REACT_PASSIVE); + } - bool CanAIAttack(Unit const* target) const override - { - return target->GetEntry() != NPC_VALITHRIA_DREAMWALKER; - } + void JustReachedHome() override + { + me->setActive(false); + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5s, 15s); - _events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s); - _events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 10s, 20s); - Initialize(); - } + void JustEngagedWith(Unit* /*target*/) override + { + Talk(SAY_LICH_KING_INTRO); + me->setActive(true); + } - void JustEnteredCombat(Unit* who) override - { - if (IsEngaged()) - return; + uint32 GetData(uint32 data) const override + { + if (data == DATA_SUPPRESSERS_COUNT) + return RAID_MODE<uint32>(4, 6, 4, 6); + else + return 0; + } - me->InterruptNonMeleeSpells(false); + void JustSummoned(Creature* summon) override + { + // must not be in dream phase + PhasingHandler::RemovePhase(summon, 173, true); + DoZoneInCombat(summon); + if (summon->GetEntry() != NPC_SUPPRESSER) + if (Unit* target = me->GetCombatManager().GetAnyTarget()) + summon->AI()->AttackStart(target); + } - EngagementStart(who); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (_isInitialArchmage) - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) - DoZoneInCombat(lichKing); + _events.Update(diff); - if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) - DoZoneInCombat(trigger); - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void DoAction(int32 action) override + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - if (action == ACTION_ENTER_COMBAT) - DoZoneInCombat(); - else if (action == ACTION_SETUP_ARCHMAGES) - _isInitialArchmage = true; + case EVENT_GLUTTONOUS_ABOMINATION_SUMMONER: + DoCastSelf(SPELL_TIMER_GLUTTONOUS_ABOMINATION); + break; + case EVENT_SUPPRESSER_SUMMONER: + DoCastSelf(SPELL_TIMER_SUPPRESSER); + break; + case EVENT_BLISTERING_ZOMBIE_SUMMONER: + DoCastSelf(SPELL_TIMER_BLISTERING_ZOMBIE); + break; + case EVENT_RISEN_ARCHMAGE_SUMMONER: + DoCastSelf(SPELL_TIMER_RISEN_ARCHMAGE); + break; + case EVENT_BLAZING_SKELETON_SUMMONER: + DoCastSelf(SPELL_TIMER_BLAZING_SKELETON); + break; + default: + break; } - void JustSummoned(Creature* summon) override - { - if (summon->GetEntry() == NPC_COLUMN_OF_FROST) - { - summon->CastSpell(summon, SPELL_COLUMN_OF_FROST_AURA, true); - summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_COLUMN_OF_FROST_DAMAGE, ObjectGuid::Empty, 8s), summon->m_Events.CalculateTime(2s)); - } - else if (summon->GetEntry() == NPC_MANA_VOID) - { - summon->CastSpell(summon, SPELL_MANA_VOID_AURA, true); - summon->DespawnOrUnsummon(36s); - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + } - void UpdateAI(uint32 diff) override - { - if (!me->IsInCombat() && me->IsAlive() && _isInitialArchmage && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - DoCastSelf(SPELL_CORRUPTION); +private: + EventMap _events; + InstanceScript* _instance; +}; - if (!UpdateVictim()) - return; +struct npc_risen_archmage : public ScriptedAI +{ + npc_risen_archmage(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + { + Initialize(); + } - _events.Update(diff); + void Initialize() + { + _isInitialArchmage = false; + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + bool CanAIAttack(Unit const* target) const override + { + return target->GetEntry() != NPC_VALITHRIA_DREAMWALKER; + } - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_FROSTBOLT_VOLLEY: - DoCastSelf(SPELL_FROSTBOLT_VOLLEY); - _events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 8s, 15s); - break; - case EVENT_MANA_VOID: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ValithriaManaVoidSelector(me))) - DoCast(target, SPELL_MANA_VOID); - _events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s); - break; - case EVENT_COLUMN_OF_FROST: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, -10.0f, true)) - DoCast(target, SPELL_COLUMN_OF_FROST); - _events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 15s, 25s); - break; - default: - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5s, 15s); + _events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s); + _events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 10s, 20s); + Initialize(); + } - DoMeleeAttackIfReady(); - } + void JustEnteredCombat(Unit* who) override + { + if (IsEngaged()) + return; - private: - EventMap _events; - InstanceScript* _instance; - bool _isInitialArchmage; - }; + me->InterruptNonMeleeSpells(false); - CreatureAI* GetAI(Creature* creature) const override + EngagementStart(who); + + if (_isInitialArchmage) { - return GetIcecrownCitadelAI<npc_risen_archmageAI>(creature); + if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING))) + DoZoneInCombat(lichKing); + + if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER))) + DoZoneInCombat(trigger); } -}; + } -class npc_blazing_skeleton : public CreatureScript -{ - public: - npc_blazing_skeleton() : CreatureScript("npc_blazing_skeleton") { } + void DoAction(int32 action) override + { + if (action == ACTION_ENTER_COMBAT) + DoZoneInCombat(); + else if (action == ACTION_SETUP_ARCHMAGES) + _isInitialArchmage = true; + } - struct npc_blazing_skeletonAI : public ScriptedAI + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_COLUMN_OF_FROST) { - npc_blazing_skeletonAI(Creature* creature) : ScriptedAI(creature) - { - } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_FIREBALL, 2s, 4s); - _events.ScheduleEvent(EVENT_LEY_WASTE, 15s, 20s); - } + summon->CastSpell(summon, SPELL_COLUMN_OF_FROST_AURA, true); + summon->m_Events.AddEvent(new ValithriaDelayedCastEvent(summon, SPELL_COLUMN_OF_FROST_DAMAGE, ObjectGuid::Empty, 8s), summon->m_Events.CalculateTime(2s)); + } + else if (summon->GetEntry() == NPC_MANA_VOID) + { + summon->CastSpell(summon, SPELL_MANA_VOID_AURA, true); + summon->DespawnOrUnsummon(36s); + } + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) override + { + if (!me->IsInCombat() && me->IsAlive() && _isInitialArchmage && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + DoCastSelf(SPELL_CORRUPTION); - _events.Update(diff); + if (!UpdateVictim()) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_FIREBALL: - if (!me->IsWithinMeleeRange(me->GetVictim())) - DoCastVictim(SPELL_FIREBALL); - _events.ScheduleEvent(EVENT_FIREBALL, 2s, 4s); - break; - case EVENT_LEY_WASTE: - DoCastSelf(SPELL_LEY_WASTE); - _events.ScheduleEvent(EVENT_LEY_WASTE, 15s, 20s); - break; - default: - break; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - DoMeleeAttackIfReady(); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FROSTBOLT_VOLLEY: + DoCastSelf(SPELL_FROSTBOLT_VOLLEY); + _events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 8s, 15s); + break; + case EVENT_MANA_VOID: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, ValithriaManaVoidSelector(me))) + DoCast(target, SPELL_MANA_VOID); + _events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s); + break; + case EVENT_COLUMN_OF_FROST: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, -10.0f, true)) + DoCast(target, SPELL_COLUMN_OF_FROST); + _events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 15s, 25s); + break; + default: + break; } - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_blazing_skeletonAI>(creature); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; + InstanceScript* _instance; + bool _isInitialArchmage; }; -class npc_suppresser : public CreatureScript +struct npc_blazing_skeleton : public ScriptedAI { - public: - npc_suppresser() : CreatureScript("npc_suppresser") { } + npc_blazing_skeleton(Creature* creature) : ScriptedAI(creature) { } - struct npc_suppresserAI : public ScriptedAI - { - npc_suppresserAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) - { - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_FIREBALL, 2s, 4s); + _events.ScheduleEvent(EVENT_LEY_WASTE, 15s, 20s); + } - void Reset() override - { - _events.Reset(); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void IsSummonedBy(WorldObject* /*summoner*/) override - { - if (Creature* valithria = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))) - { - me->EngageWithTarget(valithria); - me->GetThreatManager().FixateTarget(valithria); - } - else - me->DespawnOrUnsummon(); - } + _events.Update(diff); - void MovementInform(uint32 type, uint32 /*id*/) override - { - if (type == CHASE_MOTION_TYPE) - _events.RescheduleEvent(EVENT_SUPPRESSION, 1ms); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void UpdateAI(uint32 diff) override + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - if (!UpdateVictim()) - return; + case EVENT_FIREBALL: + if (!me->IsWithinMeleeRange(me->GetVictim())) + DoCastVictim(SPELL_FIREBALL); + _events.ScheduleEvent(EVENT_FIREBALL, 2s, 4s); + break; + case EVENT_LEY_WASTE: + DoCastSelf(SPELL_LEY_WASTE); + _events.ScheduleEvent(EVENT_LEY_WASTE, 15s, 20s); + break; + default: + break; + } - _events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + DoMeleeAttackIfReady(); + } - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SUPPRESSION: - DoCastAOE(SPELL_SUPPRESSION); - _events.Repeat(5s); - break; - default: - break; - } - } +private: + EventMap _events; +}; - DoMeleeAttackIfReady(); - } +struct npc_suppresser : public ScriptedAI +{ + npc_suppresser(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - private: - EventMap _events; - InstanceScript* const _instance; - }; + void Reset() override + { + _events.Reset(); + } - CreatureAI* GetAI(Creature* creature) const override + void IsSummonedBy(WorldObject* /*summoner*/) override + { + if (Creature* valithria = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))) { - return GetIcecrownCitadelAI<npc_suppresserAI>(creature); + me->EngageWithTarget(valithria); + me->GetThreatManager().FixateTarget(valithria); } -}; - -class npc_blistering_zombie : public CreatureScript -{ - public: - npc_blistering_zombie() : CreatureScript("npc_blistering_zombie") { } + else + me->DespawnOrUnsummon(); + } - struct npc_blistering_zombieAI : public ScriptedAI - { - npc_blistering_zombieAI(Creature* creature) : ScriptedAI(creature) - { - } + void MovementInform(uint32 type, uint32 /*id*/) override + { + if (type == CHASE_MOTION_TYPE) + _events.RescheduleEvent(EVENT_SUPPRESSION, 1ms); + } - void JustDied(Unit* /*killer*/) override - { - DoCastSelf(SPELL_ACID_BURST, true); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void UpdateAI(uint32 /*diff*/) override - { - if (!UpdateVictim()) - return; + _events.Update(diff); - DoMeleeAttackIfReady(); - } - }; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - CreatureAI* GetAI(Creature* creature) const override + while (uint32 eventId = _events.ExecuteEvent()) { - return GetIcecrownCitadelAI<npc_blistering_zombieAI>(creature); + switch (eventId) + { + case EVENT_SUPPRESSION: + DoCastAOE(SPELL_SUPPRESSION); + _events.Repeat(5s); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); + } + +private: + EventMap _events; + InstanceScript* const _instance; }; -class npc_gluttonous_abomination : public CreatureScript +struct npc_blistering_zombie : public ScriptedAI { - public: - npc_gluttonous_abomination() : CreatureScript("npc_gluttonous_abomination") { } + npc_blistering_zombie(Creature* creature) : ScriptedAI(creature) { } - struct npc_gluttonous_abominationAI : public ScriptedAI - { - npc_gluttonous_abominationAI(Creature* creature) : ScriptedAI(creature) - { - } + void JustDied(Unit* /*killer*/) override + { + DoCastSelf(SPELL_ACID_BURST, true); + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_GUT_SPRAY, 10s, 13s); - } + void UpdateAI(uint32 /*diff*/) override + { + if (!UpdateVictim()) + return; - void JustDied(Unit* killer) override - { - if (killer && killer->GetEntry() == NPC_VALITHRIA_DREAMWALKER) - return; + DoMeleeAttackIfReady(); + } +}; - DoCastSelf(SPELL_ROT_WORM_SPAWNER, true); - } +struct npc_gluttonous_abomination : public ScriptedAI +{ + npc_gluttonous_abomination(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_GUT_SPRAY, 10s, 13s); + } - _events.Update(diff); + void JustDied(Unit* killer) override + { + if (killer && killer->GetEntry() == NPC_VALITHRIA_DREAMWALKER) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + DoCastSelf(SPELL_ROT_WORM_SPAWNER, true); + } - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_GUT_SPRAY: - DoCastSelf(SPELL_GUT_SPRAY); - _events.ScheduleEvent(EVENT_GUT_SPRAY, 10s, 13s); - break; - default: - break; - } - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - DoMeleeAttackIfReady(); - } + _events.Update(diff); - private: - EventMap _events; - }; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - CreatureAI* GetAI(Creature* creature) const override + while (uint32 eventId = _events.ExecuteEvent()) { - return GetIcecrownCitadelAI<npc_gluttonous_abominationAI>(creature); + switch (eventId) + { + case EVENT_GUT_SPRAY: + DoCastSelf(SPELL_GUT_SPRAY); + _events.ScheduleEvent(EVENT_GUT_SPRAY, 10s, 13s); + break; + default: + break; + } } -}; -class npc_dream_portal : public CreatureScript -{ - public: - npc_dream_portal() : CreatureScript("npc_dream_portal") { } + DoMeleeAttackIfReady(); + } - struct npc_dream_portalAI : public CreatureAI - { - npc_dream_portalAI(Creature* creature) : CreatureAI(creature), _used(false) - { - } +private: + EventMap _events; +}; - void OnSpellClick(Unit* /*clicker*/, bool spellClickHandled) override - { - if (!spellClickHandled) - return; +struct npc_dream_portal : public CreatureAI +{ + npc_dream_portal(Creature* creature) : CreatureAI(creature), _used(false) { } - _used = true; - me->DespawnOrUnsummon(); - } + void OnSpellClick(Unit* /*clicker*/, bool spellClickHandled) override + { + if (!spellClickHandled) + return; - uint32 GetData(uint32 type) const override - { - return (type == MISSED_PORTALS && _used) ? 0 : 1; - } + _used = true; + me->DespawnOrUnsummon(); + } - void UpdateAI(uint32 /*diff*/) override - { - UpdateVictim(); - } + uint32 GetData(uint32 type) const override + { + return (type == MISSED_PORTALS && _used) ? 0 : 1; + } - private: - bool _used; - }; + void UpdateAI(uint32 /*diff*/) override + { + UpdateVictim(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_dream_portalAI>(creature); - } +private: + bool _used; }; -class npc_dream_cloud : public CreatureScript +struct npc_dream_cloud : public ScriptedAI { - public: - npc_dream_cloud() : CreatureScript("npc_dream_cloud") { } - - struct npc_dream_cloudAI : public ScriptedAI - { - npc_dream_cloudAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) - { - } + npc_dream_cloud(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_CHECK_PLAYER, 1s); - me->SetCorpseDelay(0); // remove corpse immediately - me->LoadCreaturesAddon(); - } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_CHECK_PLAYER, 1s); + me->SetCorpseDelay(0); // remove corpse immediately + me->LoadCreaturesAddon(); + } - void UpdateAI(uint32 diff) override - { - // trigger - if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) - return; + void UpdateAI(uint32 diff) override + { + // trigger + if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) + return; - _events.Update(diff); + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CHECK_PLAYER: { - switch (eventId) - { - case EVENT_CHECK_PLAYER: - { - Player* player = nullptr; - Trinity::AnyPlayerInObjectRangeCheck check(me, 5.0f); - Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(me, player, check); - Cell::VisitWorldObjects(me, searcher, 7.5f); - _events.ScheduleEvent(player ? EVENT_EXPLODE : EVENT_CHECK_PLAYER, 1s); - break; - } - case EVENT_EXPLODE: - me->GetMotionMaster()->MoveIdle(); - // must use originalCaster the same for all clouds to allow stacking - me->CastSpell(me, EMERALD_VIGOR, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(_instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))); - me->DespawnOrUnsummon(100ms); - break; - default: - break; - } + Player* player = nullptr; + Trinity::AnyPlayerInObjectRangeCheck check(me, 5.0f); + Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(me, player, check); + Cell::VisitWorldObjects(me, searcher, 7.5f); + _events.ScheduleEvent(player ? EVENT_EXPLODE : EVENT_CHECK_PLAYER, 1s); + break; } + case EVENT_EXPLODE: + me->GetMotionMaster()->MoveIdle(); + // must use originalCaster the same for all clouds to allow stacking + me->CastSpell(me, EMERALD_VIGOR, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(_instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))); + me->DespawnOrUnsummon(100ms); + break; + default: + break; } - - private: - EventMap _events; - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_dream_cloudAI>(creature); } + } + +private: + EventMap _events; + InstanceScript* _instance; }; -class spell_dreamwalker_mana_void : public SpellScriptLoader +class spell_dreamwalker_mana_void : public AuraScript { - public: - spell_dreamwalker_mana_void() : SpellScriptLoader("spell_dreamwalker_mana_void") { } - - class spell_dreamwalker_mana_void_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dreamwalker_mana_void_AuraScript); - - void PeriodicTick(AuraEffect const* aurEff) - { - // first 3 ticks have amplitude 1 second - // remaining tick every 500ms - if (aurEff->GetTickNumber() <= 5) - if (!(aurEff->GetTickNumber() & 1)) - PreventDefaultAction(); - } + PrepareAuraScript(spell_dreamwalker_mana_void); - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_mana_void_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; + void PeriodicTick(AuraEffect const* aurEff) + { + // first 3 ticks have amplitude 1 second + // remaining tick every 500ms + if (aurEff->GetTickNumber() <= 5) + if (!(aurEff->GetTickNumber() & 1)) + PreventDefaultAction(); + } - AuraScript* GetAuraScript() const override - { - return new spell_dreamwalker_mana_void_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_mana_void::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } }; -class spell_dreamwalker_decay_periodic_timer : public SpellScriptLoader +class spell_dreamwalker_decay_periodic_timer : public AuraScript { - public: - spell_dreamwalker_decay_periodic_timer() : SpellScriptLoader("spell_dreamwalker_decay_periodic_timer") { } + PrepareAuraScript(spell_dreamwalker_decay_periodic_timer); - class spell_dreamwalker_decay_periodic_timer_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dreamwalker_decay_periodic_timer_AuraScript); - - bool Load() override - { - _decayRate = GetId() != SPELL_TIMER_BLAZING_SKELETON ? 1000 : 5000; - return true; - } - - void DecayPeriodicTimer(AuraEffect* aurEff) - { - int32 timer = aurEff->GetPeriodicTimer(); - if (timer <= 5) - return; + bool Load() override + { + _decayRate = GetId() != SPELL_TIMER_BLAZING_SKELETON ? 1000 : 5000; + return true; + } - aurEff->SetPeriodicTimer(timer - _decayRate); - } + void DecayPeriodicTimer(AuraEffect* aurEff) + { + int32 timer = aurEff->GetPeriodicTimer(); + if (timer <= 5) + return; - void Register() override - { - OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_dreamwalker_decay_periodic_timer_AuraScript::DecayPeriodicTimer, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } + aurEff->SetPeriodicTimer(timer - _decayRate); + } - int32 _decayRate = 0; - }; + void Register() override + { + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_dreamwalker_decay_periodic_timer::DecayPeriodicTimer, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } - AuraScript* GetAuraScript() const override - { - return new spell_dreamwalker_decay_periodic_timer_AuraScript(); - } + int32 _decayRate = 0; }; -class spell_dreamwalker_summoner : public SpellScriptLoader +class spell_dreamwalker_summoner : public SpellScript { - public: - spell_dreamwalker_summoner() : SpellScriptLoader("spell_dreamwalker_summoner") { } - - class spell_dreamwalker_summoner_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dreamwalker_summoner_SpellScript); - - bool Load() override - { - if (!GetCaster()->GetInstanceScript()) - return false; - return true; - } + PrepareSpellScript(spell_dreamwalker_summoner); - void FilterTargets(std::list<WorldObject*>& targets) - { - targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); - if (targets.empty()) - return; + bool Load() override + { + if (!GetCaster()->GetInstanceScript()) + return false; + return true; + } - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - targets.clear(); - targets.push_back(target); - } + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); + if (targets.empty()) + return; - void HandleForceCast(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (!GetHitUnit()) - return; + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } - GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING))); - } + void HandleForceCast(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (!GetHitUnit()) + return; - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dreamwalker_summoner_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summoner_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); - } - }; + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING))); + } - SpellScript* GetSpellScript() const override - { - return new spell_dreamwalker_summoner_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dreamwalker_summoner::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summoner::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); + } }; -class spell_dreamwalker_summon_suppresser : public SpellScriptLoader +class spell_dreamwalker_summon_suppresser : public AuraScript { - public: - spell_dreamwalker_summon_suppresser() : SpellScriptLoader("spell_dreamwalker_summon_suppresser") { } - - class spell_dreamwalker_summon_suppresser_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dreamwalker_summon_suppresser_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_SUMMON_SUPPRESSER }); - } + PrepareAuraScript(spell_dreamwalker_summon_suppresser); - void PeriodicTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - HandleSummon(GetCaster()); - } + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_SUPPRESSER }); + } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - HandleSummon(GetCaster()); - } + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + HandleSummon(GetCaster()); + } - void HandleSummon(Unit* caster) - { - if (!caster || !caster->IsAIEnabled()) - return; + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + HandleSummon(GetCaster()); + } - std::list<Creature*> summoners; - GetCreatureListWithEntryInGrid(summoners, caster, NPC_WORLD_TRIGGER, 90.0f); - if (summoners.empty()) - return; + void HandleSummon(Unit* caster) + { + if (!caster || !caster->IsAIEnabled()) + return; - uint8 suppresserNumber = caster->GetAI()->GetData(DATA_SUPPRESSERS_COUNT); - for (uint8 i = 0; i < suppresserNumber; ++i) - caster->CastSpell(Trinity::Containers::SelectRandomContainerElement(summoners), SPELL_SUMMON_SUPPRESSER, true); - } + std::list<Creature*> summoners; + GetCreatureListWithEntryInGrid(summoners, caster, NPC_WORLD_TRIGGER, 90.0f); + if (summoners.empty()) + return; - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_summon_suppresser_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - AfterEffectApply += AuraEffectApplyFn(spell_dreamwalker_summon_suppresser_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; + uint8 suppresserNumber = caster->GetAI()->GetData(DATA_SUPPRESSERS_COUNT); + for (uint8 i = 0; i < suppresserNumber; ++i) + caster->CastSpell(Trinity::Containers::SelectRandomContainerElement(summoners), SPELL_SUMMON_SUPPRESSER, true); + } - AuraScript* GetAuraScript() const override - { - return new spell_dreamwalker_summon_suppresser_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_summon_suppresser::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + AfterEffectApply += AuraEffectApplyFn(spell_dreamwalker_summon_suppresser::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_dreamwalker_summon_suppresser_effect : public SpellScriptLoader +class spell_dreamwalker_summon_suppresser_effect : public SpellScript { - public: - spell_dreamwalker_summon_suppresser_effect() : SpellScriptLoader("spell_dreamwalker_summon_suppresser_effect") { } - - class spell_dreamwalker_summon_suppresser_effect_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dreamwalker_summon_suppresser_effect_SpellScript); + PrepareSpellScript(spell_dreamwalker_summon_suppresser_effect); - bool Load() override - { - if (!GetCaster()->GetInstanceScript()) - return false; - return true; - } - - void HandleForceCast(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (!GetHitUnit()) - return; + bool Load() override + { + if (!GetCaster()->GetInstanceScript()) + return false; + return true; + } - GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING))); - } + void HandleForceCast(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (!GetHitUnit()) + return; - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_suppresser_effect_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); - } - }; + GetHitUnit()->CastSpell(GetCaster(), GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING))); + } - SpellScript* GetSpellScript() const override - { - return new spell_dreamwalker_summon_suppresser_effect_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_suppresser_effect::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); + } }; -class spell_dreamwalker_summon_dream_portal : public SpellScriptLoader +class spell_dreamwalker_summon_dream_portal : public SpellScript { - public: - spell_dreamwalker_summon_dream_portal() : SpellScriptLoader("spell_dreamwalker_summon_dream_portal") { } + PrepareSpellScript(spell_dreamwalker_summon_dream_portal); - class spell_dreamwalker_summon_dream_portal_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dreamwalker_summon_dream_portal_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (!GetHitUnit()) - return; - - uint32 spellId = RAND(71301, 72220, 72223, 72225); - GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); - } + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (!GetHitUnit()) + return; - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_dream_portal_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + uint32 spellId = RAND(71301, 72220, 72223, 72225); + GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_dreamwalker_summon_dream_portal_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_dream_portal::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_dreamwalker_summon_nightmare_portal : public SpellScriptLoader +class spell_dreamwalker_summon_nightmare_portal : public SpellScript { - public: - spell_dreamwalker_summon_nightmare_portal() : SpellScriptLoader("spell_dreamwalker_summon_nightmare_portal") { } + PrepareSpellScript(spell_dreamwalker_summon_nightmare_portal); - class spell_dreamwalker_summon_nightmare_portal_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dreamwalker_summon_nightmare_portal_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (!GetHitUnit()) - return; - - uint32 spellId = RAND(71977, 72481, 72482, 72483); - GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); - } + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (!GetHitUnit()) + return; - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_nightmare_portal_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + uint32 spellId = RAND(71977, 72481, 72482, 72483); + GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_dreamwalker_summon_nightmare_portal_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summon_nightmare_portal::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; -class spell_dreamwalker_nightmare_cloud : public SpellScriptLoader +class spell_dreamwalker_nightmare_cloud : public AuraScript { - public: - spell_dreamwalker_nightmare_cloud() : SpellScriptLoader("spell_dreamwalker_nightmare_cloud") { } - - class spell_dreamwalker_nightmare_cloud_AuraScript : public AuraScript - { - PrepareAuraScript(spell_dreamwalker_nightmare_cloud_AuraScript); + PrepareAuraScript(spell_dreamwalker_nightmare_cloud); - public: - spell_dreamwalker_nightmare_cloud_AuraScript() - { - _instance = nullptr; - } - - private: - bool Load() override - { - _instance = GetOwner()->GetInstanceScript(); - return _instance != nullptr; - } +public: + spell_dreamwalker_nightmare_cloud() + { + _instance = nullptr; + } - void PeriodicTick(AuraEffect const* /*aurEff*/) - { - if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) - PreventDefaultAction(); - } +private: + bool Load() override + { + _instance = GetOwner()->GetInstanceScript(); + return _instance != nullptr; + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_nightmare_cloud_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS) + PreventDefaultAction(); + } - InstanceScript* _instance; - }; + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_dreamwalker_nightmare_cloud::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } - AuraScript* GetAuraScript() const override - { - return new spell_dreamwalker_nightmare_cloud_AuraScript(); - } + InstanceScript* _instance; }; -class spell_dreamwalker_twisted_nightmares : public SpellScriptLoader +class spell_dreamwalker_twisted_nightmares : public SpellScript { - public: - spell_dreamwalker_twisted_nightmares() : SpellScriptLoader("spell_dreamwalker_twisted_nightmares") { } + PrepareSpellScript(spell_dreamwalker_twisted_nightmares); - class spell_dreamwalker_twisted_nightmares_SpellScript : public SpellScript - { - PrepareSpellScript(spell_dreamwalker_twisted_nightmares_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - - if (GetHitUnit()->GetInstanceScript()) - GetHitUnit()->CastSpell(nullptr, GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) - .SetOriginalCaster(GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_DREAMWALKER))); - } + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_twisted_nightmares_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_FORCE_CAST); - } - }; + if (InstanceScript* instance = GetHitUnit()->GetInstanceScript()) + GetHitUnit()->CastSpell(nullptr, GetEffectInfo().TriggerSpell, CastSpellExtraArgs(TRIGGERED_FULL_MASK) + .SetOriginalCaster(instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER))); + } - SpellScript* GetSpellScript() const override - { - return new spell_dreamwalker_twisted_nightmares_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_twisted_nightmares::HandleScript, EFFECT_2, SPELL_EFFECT_FORCE_CAST); + } }; // 47788 - Guardian Spirit @@ -1501,25 +1274,30 @@ class achievement_portal_jockey : public AchievementCriteriaScript void AddSC_boss_valithria_dreamwalker() { - new boss_valithria_dreamwalker(); - new npc_green_dragon_combat_trigger(); - new npc_the_lich_king_controller(); - new npc_risen_archmage(); - new npc_blazing_skeleton(); - new npc_suppresser(); - new npc_blistering_zombie(); - new npc_gluttonous_abomination(); - new npc_dream_portal(); - new npc_dream_cloud(); - new spell_dreamwalker_mana_void(); - new spell_dreamwalker_decay_periodic_timer(); - new spell_dreamwalker_summoner(); - new spell_dreamwalker_summon_suppresser(); - new spell_dreamwalker_summon_suppresser_effect(); - new spell_dreamwalker_summon_dream_portal(); - new spell_dreamwalker_summon_nightmare_portal(); - new spell_dreamwalker_nightmare_cloud(); - new spell_dreamwalker_twisted_nightmares(); + // Creatures + RegisterIcecrownCitadelCreatureAI(boss_valithria_dreamwalker); + RegisterIcecrownCitadelCreatureAI(npc_green_dragon_combat_trigger); + RegisterIcecrownCitadelCreatureAI(npc_the_lich_king_controller); + RegisterIcecrownCitadelCreatureAI(npc_risen_archmage); + RegisterIcecrownCitadelCreatureAI(npc_blazing_skeleton); + RegisterIcecrownCitadelCreatureAI(npc_suppresser); + RegisterIcecrownCitadelCreatureAI(npc_blistering_zombie); + RegisterIcecrownCitadelCreatureAI(npc_gluttonous_abomination); + RegisterIcecrownCitadelCreatureAI(npc_dream_portal); + RegisterIcecrownCitadelCreatureAI(npc_dream_cloud); + + // Spells + RegisterSpellScript(spell_dreamwalker_mana_void); + RegisterSpellScript(spell_dreamwalker_decay_periodic_timer); + RegisterSpellScript(spell_dreamwalker_summoner); + RegisterSpellScript(spell_dreamwalker_summon_suppresser); + RegisterSpellScript(spell_dreamwalker_summon_suppresser_effect); + RegisterSpellScript(spell_dreamwalker_summon_dream_portal); + RegisterSpellScript(spell_dreamwalker_summon_nightmare_portal); + RegisterSpellScript(spell_dreamwalker_nightmare_cloud); + RegisterSpellScript(spell_dreamwalker_twisted_nightmares); + + // Achievements RegisterSpellScript(spell_dreamwalker_guardian_spirit_restriction); new achievement_portal_jockey(); } |