diff options
author | Trazom62 <none@none> | 2010-05-20 20:09:18 +0200 |
---|---|---|
committer | Trazom62 <none@none> | 2010-05-20 20:09:18 +0200 |
commit | d2cad4b14e27c8c7b7ba5be7449dbb908f34497d (patch) | |
tree | 722ed1fb40c1b90ff5668cbe8be6063d2233026b /src | |
parent | ce7886aeb0df0257aa953bdf83ef51c4251a6ebf (diff) |
Script HoR instance. 1st part.
Fixes issue #1311.
- Intro event.
- 10 waves including Falric and Marwyn.
- Script based on proposal of Synric on trinitycore forum (submitted by Skarabex on GC).
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/ScriptLoader.cpp | 8 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 23 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 1 | ||||
-rw-r--r-- | src/scripts/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp | 142 | ||||
-rw-r--r-- | src/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp | 133 | ||||
-rw-r--r-- | src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp | 1022 | ||||
-rw-r--r-- | src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h | 133 | ||||
-rw-r--r-- | src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp | 321 |
9 files changed, 1751 insertions, 35 deletions
diff --git a/src/game/ScriptLoader.cpp b/src/game/ScriptLoader.cpp index 971ff4cbe35..20bda66a611 100644 --- a/src/game/ScriptLoader.cpp +++ b/src/game/ScriptLoader.cpp @@ -416,6 +416,10 @@ void AddSC_pit_of_saron(); void AddSC_boss_garfrost(); void AddSC_boss_ick(); void AddSC_boss_tyrannus(); +void AddSC_instance_halls_of_reflection(); // Halls of Reflection +void AddSC_halls_of_reflection(); +void AddSC_boss_falric(); +void AddSC_boss_marwyn(); void AddSC_dalaran(); void AddSC_borean_tundra(); @@ -912,6 +916,10 @@ void AddScripts() AddSC_boss_garfrost(); AddSC_boss_ick(); AddSC_boss_tyrannus(); + AddSC_instance_halls_of_reflection(); // Halls of Reflection + AddSC_halls_of_reflection(); + AddSC_boss_falric(); + AddSC_boss_marwyn(); AddSC_dalaran(); AddSC_borean_tundra(); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a531f24922e..1b2e0f5b6fd 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1089,9 +1089,26 @@ void Aura::HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster, switch(GetSpellProto()->SpellFamilyName) { case SPELLFAMILY_GENERIC: - // Remove the immunity shield marker on Avenging Wrath removal if Forbearance is not present - if (GetId() == 61987 && target->HasAura(61988) && !target->HasAura(25771)) - target->RemoveAura(61988); + switch(GetId()) + { + case 61987: // Avenging Wrath + // Remove the immunity shield marker on Avenging Wrath removal if Forbearance is not present + if (target->HasAura(61988) && !target->HasAura(25771)) + target->RemoveAura(61988); + break; + case 72368: // Shared Suffering + case 72369: + if (caster) + { + if (AuraEffect* aurEff = GetEffect(0)) + { + int32 remainingDamage = aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber()); + if (remainingDamage > 0) + caster->CastCustomSpell(caster, 72373, NULL, &remainingDamage, NULL, true); + } + } + break; + } break; case SPELLFAMILY_MAGE: switch(GetId()) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 81c4ebaa76f..d7da9bb1e3b 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -3629,6 +3629,7 @@ void SpellMgr::LoadSpellCustomAttr() case 42384: // Brutal Swipe case 45150: // Meteor Slash case 64422: case 64688: // Sonic Screech + case 72373: // Shared Suffering // ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE; count++; diff --git a/src/scripts/CMakeLists.txt b/src/scripts/CMakeLists.txt index e51130881f6..47dffe924dc 100644 --- a/src/scripts/CMakeLists.txt +++ b/src/scripts/CMakeLists.txt @@ -346,7 +346,10 @@ SET(scripts_STAT_SRCS northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp northrend/frozen_halls/forge_of_souls/forge_of_souls.h northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp + northrend/frozen_halls/halls_of_reflection/boss_falric.cpp + northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp + northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp diff --git a/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp b/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp new file mode 100644 index 00000000000..c9978faca6e --- /dev/null +++ b/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2010 TrinityCore <https://www.trinitycore.org/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668050, + SAY_SLAY_1 = -1668051, + SAY_SLAY_2 = -1668052, + SAY_DEATH = -1668053, + SAY_IMPENDING_DESPAIR = -1668054, + SAY_DEFILING_HORROR = -1668055, +}; + +enum Spells +{ + SPELL_QUIVERING_STRIKE = 72422, + SPELL_IMPENDING_DESPAIR = 72426, + SPELL_DEFILING_HORROR = 72435, + SPELL_HOPELESSNESS = 72395, + H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. +}; + +enum Events +{ + EVENT_NONE, + EVENT_QUIVERING_STRIKE, + EVENT_IMPENDING_DESPAIR, + EVENT_DEFILING_HORROR, +}; + +struct boss_falricAI : public boss_horAI +{ + boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} + + uint8 uiHopelessnessCount; + + void Reset() + { + boss_horAI::Reset(); + + uiHopelessnessCount = 0; + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_QUIVERING_STRIKE: + DoCast(SPELL_QUIVERING_STRIKE); + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); + break; + case EVENT_IMPENDING_DESPAIR: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + { + DoScriptText(SAY_IMPENDING_DESPAIR, me); + DoCast(pTarget, SPELL_IMPENDING_DESPAIR); + } + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); + break; + case EVENT_DEFILING_HORROR: + DoCast(SPELL_DEFILING_HORROR); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + break; + } + + if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) + || (uiHopelessnessCount < 2 && HealthBelowPct(33)) + || (uiHopelessnessCount < 3 && HealthBelowPct(10))) + { + uiHopelessnessCount++; + DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_falric(Creature* pCreature) +{ + return new boss_falricAI(pCreature); +} + +void AddSC_boss_falric() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_falric"; + newscript->GetAI = &GetAI_boss_falric; + newscript->RegisterSelf(); +} diff --git a/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp b/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp new file mode 100644 index 00000000000..95fb2737ce9 --- /dev/null +++ b/src/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2010 TrinityCore <https://www.trinitycore.org/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668060, + SAY_SLAY_1 = -1668061, + SAY_SLAY_2 = -1668062, + SAY_DEATH = -1668063, + SAY_CORRUPTED_FLESH_1 = -1668064, + SAY_CORRUPTED_FLESH_2 = -1668065, +}; + +enum Spells +{ + SPELL_OBLITERATE = 72360, + SPELL_WELL_OF_CORRUPTION = 72362, + SPELL_CORRUPTED_FLESH = 72363, + SPELL_SHARED_SUFFERING = 72368, +}; + +enum Events +{ + EVENT_NONE, + EVENT_OBLITERATE, + EVENT_WELL_OF_CORRUPTION, + EVENT_CORRUPTED_FLESH, + EVENT_SHARED_SUFFERING, +}; + +struct boss_marwynAI : public boss_horAI +{ + boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} + + void Reset() + { + boss_horAI::Reset(); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_OBLITERATE: + DoCast(SPELL_OBLITERATE); + events.ScheduleEvent(EVENT_OBLITERATE, 30000); + break; + case EVENT_WELL_OF_CORRUPTION: + DoCast(SPELL_WELL_OF_CORRUPTION); + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + break; + case EVENT_CORRUPTED_FLESH: + DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); + DoCast(SPELL_CORRUPTED_FLESH); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + break; + case EVENT_SHARED_SUFFERING: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHARED_SUFFERING); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marwyn(Creature* pCreature) +{ + return new boss_marwynAI(pCreature); +} + +void AddSC_boss_marwyn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_marwyn"; + newscript->GetAI = &GetAI_boss_marwyn; + newscript->RegisterSelf(); +} diff --git a/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp b/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp new file mode 100644 index 00000000000..fb3d3d5d752 --- /dev/null +++ b/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp @@ -0,0 +1,1022 @@ +/* Copyright (C) 2006 - 2010 TrinityCore <https://www.trinitycore.org/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1668001, + SAY_JAINA_INTRO_2 = -1668002, + SAY_JAINA_INTRO_3 = -1668003, + SAY_JAINA_INTRO_4 = -1668004, + SAY_UTHER_INTRO_A2_1 = -1668005, + SAY_JAINA_INTRO_5 = -1668006, + SAY_UTHER_INTRO_A2_2 = -1668007, + SAY_JAINA_INTRO_6 = -1668008, + SAY_UTHER_INTRO_A2_3 = -1668009, + SAY_JAINA_INTRO_7 = -1668010, + SAY_UTHER_INTRO_A2_4 = -1668011, + SAY_JAINA_INTRO_8 = -1668012, + SAY_UTHER_INTRO_A2_5 = -1668013, + SAY_JAINA_INTRO_9 = -1668014, + SAY_UTHER_INTRO_A2_6 = -1668015, + SAY_UTHER_INTRO_A2_7 = -1668016, + SAY_JAINA_INTRO_10 = -1668017, + SAY_UTHER_INTRO_A2_8 = -1668018, + SAY_JAINA_INTRO_11 = -1668019, + SAY_UTHER_INTRO_A2_9 = -1668020, + + SAY_SYLVANAS_INTRO_1 = -1668021, + SAY_SYLVANAS_INTRO_2 = -1668022, + SAY_SYLVANAS_INTRO_3 = -1668023, + SAY_UTHER_INTRO_H2_1 = -1668024, + SAY_SYLVANAS_INTRO_4 = -1668025, + SAY_UTHER_INTRO_H2_2 = -1668026, + SAY_SYLVANAS_INTRO_5 = -1668027, + SAY_UTHER_INTRO_H2_3 = -1668028, + SAY_SYLVANAS_INTRO_6 = -1668029, + SAY_UTHER_INTRO_H2_4 = -1668030, + SAY_SYLVANAS_INTRO_7 = -1668031, + SAY_UTHER_INTRO_H2_5 = -1668032, + SAY_UTHER_INTRO_H2_6 = -1668033, + SAY_SYLVANAS_INTRO_8 = -1668034, + SAY_UTHER_INTRO_H2_7 = -1668035, + + SAY_LK_INTRO_1 = -1668036, + SAY_LK_INTRO_2 = -1668037, + SAY_LK_INTRO_3 = -1668038, + SAY_FALRIC_INTRO_1 = -1668039, + SAY_MARWYN_INTRO_1 = -1668040, + SAY_FALRIC_INTRO_2 = -1668041, + + SAY_JAINA_INTRO_END = -1668042, + SAY_SYLVANAS_INTRO_END = -1668043, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_START_INTRO, + EVENT_SKIP_INTRO, + + EVENT_INTRO_A2_1, + EVENT_INTRO_A2_2, + EVENT_INTRO_A2_3, + EVENT_INTRO_A2_4, + EVENT_INTRO_A2_5, + EVENT_INTRO_A2_6, + EVENT_INTRO_A2_7, + EVENT_INTRO_A2_8, + EVENT_INTRO_A2_9, + EVENT_INTRO_A2_10, + EVENT_INTRO_A2_11, + EVENT_INTRO_A2_12, + EVENT_INTRO_A2_13, + EVENT_INTRO_A2_14, + EVENT_INTRO_A2_15, + EVENT_INTRO_A2_16, + EVENT_INTRO_A2_17, + EVENT_INTRO_A2_18, + EVENT_INTRO_A2_19, + + EVENT_INTRO_H2_1, + EVENT_INTRO_H2_2, + EVENT_INTRO_H2_3, + EVENT_INTRO_H2_4, + EVENT_INTRO_H2_5, + EVENT_INTRO_H2_6, + EVENT_INTRO_H2_7, + EVENT_INTRO_H2_8, + EVENT_INTRO_H2_9, + EVENT_INTRO_H2_10, + EVENT_INTRO_H2_11, + EVENT_INTRO_H2_12, + EVENT_INTRO_H2_13, + EVENT_INTRO_H2_14, + EVENT_INTRO_H2_15, + + EVENT_INTRO_LK_1, + EVENT_INTRO_LK_2, + EVENT_INTRO_LK_3, + EVENT_INTRO_LK_4, + EVENT_INTRO_LK_5, + EVENT_INTRO_LK_6, + EVENT_INTRO_LK_7, + EVENT_INTRO_LK_8, + EVENT_INTRO_LK_9, + + EVENT_INTRO_END, +}; + +enum eEnum +{ + ACTION_START_INTRO, + ACTION_SKIP_INTRO, + + QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, + QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, + QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, + QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, +}; + +static Position HallsofReflectionLocs[]= +{ + {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows + {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows + {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows +}; + +static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position +static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne +static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; +static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; +static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne +static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away + +// AI of Part1: handle the intro till start of gauntlet event. +struct npc_jaina_or_sylvanas_horAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 uiUther; + uint64 uiLichKing; + + EventMap events; + + void Reset() + { + events.Reset(); + + uiUther = 0; + uiLichKing = 0; + + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetVisibility(VISIBILITY_ON); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_START_INTRO: + events.ScheduleEvent(EVENT_START_INTRO, 0); + break; + case ACTION_SKIP_INTRO: + events.ScheduleEvent(EVENT_SKIP_INTRO, 0); + break; + } + } + + void UpdateAI(const uint32 diff) + { + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_START_INTRO: + me->GetMotionMaster()->MovePoint(0, MoveThronePos); + // Begining of intro is differents between factions as the speech sequence and timers are differents. + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + events.ScheduleEvent(EVENT_INTRO_A2_1, 0); + else + events.ScheduleEvent(EVENT_INTRO_H2_1, 0); + break; + + // A2 Intro Events + case EVENT_INTRO_A2_1: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); + break; + case EVENT_INTRO_A2_2: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); + break; + case EVENT_INTRO_A2_3: + // TODO: she's doing some kind of spell casting emote + pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); + events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); + break; + case EVENT_INTRO_A2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); + break; + case EVENT_INTRO_A2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); + break; + case EVENT_INTRO_A2_6: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); + break; + case EVENT_INTRO_A2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); + break; + case EVENT_INTRO_A2_8: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); + break; + case EVENT_INTRO_A2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); + break; + case EVENT_INTRO_A2_10: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); + break; + case EVENT_INTRO_A2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); + break; + case EVENT_INTRO_A2_12: + DoScriptText(SAY_JAINA_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); + break; + case EVENT_INTRO_A2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); + break; + case EVENT_INTRO_A2_14: + DoScriptText(SAY_JAINA_INTRO_9, me); + events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); + break; + case EVENT_INTRO_A2_15: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); + break; + case EVENT_INTRO_A2_16: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); + break; + case EVENT_INTRO_A2_17: + DoScriptText(SAY_JAINA_INTRO_10, me); + events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); + break; + case EVENT_INTRO_A2_18: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); + } + events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); + break; + case EVENT_INTRO_A2_19: + DoScriptText(SAY_JAINA_INTRO_11, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // H2 Intro Events + case EVENT_INTRO_H2_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); + break; + case EVENT_INTRO_H2_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); + break; + case EVENT_INTRO_H2_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + // TODO: she's doing some kind of spell casting emote + events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); + break; + case EVENT_INTRO_H2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); + break; + case EVENT_INTRO_H2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); + break; + case EVENT_INTRO_H2_6: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); + break; + case EVENT_INTRO_H2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); + break; + case EVENT_INTRO_H2_8: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); + break; + case EVENT_INTRO_H2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); + break; + case EVENT_INTRO_H2_10: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); + break; + case EVENT_INTRO_H2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); + break; + case EVENT_INTRO_H2_12: + DoScriptText(SAY_SYLVANAS_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); + break; + case EVENT_INTRO_H2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); + } + events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); + break; + case EVENT_INTRO_H2_14: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); + break; + case EVENT_INTRO_H2_15: + DoScriptText(SAY_SYLVANAS_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // Remaining Intro Events common for both faction + case EVENT_INTRO_LK_1: + // Spawn LK in front of door, and make him move to the sword. + if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); + pLichKing->SetReactState(REACT_PASSIVE); + uiLichKing = pLichKing->GetGUID(); + } + + if (Creature* pUther = me->GetCreature(*me, uiUther)) + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); + else + DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); + + events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); + break; + + case EVENT_INTRO_LK_2: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_1, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); + break; + + case EVENT_INTRO_LK_3: + // The Lich King banishes Uther to the abyss. + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->DisappearAndDie(); + uiUther = 0; + } + + // He steps forward and removes the runeblade from the heap of skulls. + + events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); + break; + + case EVENT_INTRO_LK_4: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_2, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); + break; + + case EVENT_INTRO_LK_5: + // summon Falric and Marwyn. then go back to the door + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + DoScriptText(SAY_LK_INTRO_3, pLichKing); + } + + events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); + break; + + case EVENT_INTRO_LK_6: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_1, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); + break; + + case EVENT_INTRO_LK_7: + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); + + events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); + break; + + case EVENT_INTRO_LK_8: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_2, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); + break; + + case EVENT_INTRO_LK_9: + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_JAINA_INTRO_END, me); + else + DoScriptText(SAY_SYLVANAS_INTRO_END, me); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + events.ScheduleEvent(EVENT_INTRO_END, 10000); + break; + + case EVENT_INTRO_END: + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave + + // Loralen or Koreln disappearAndDie() + me->DisappearAndDie(); + break; + + case EVENT_SKIP_INTRO: + // TODO: implement + + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + + events.ScheduleEvent(EVENT_INTRO_END, 15000); + break; + } + } +}; + +bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + + return true; +} + +bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest of the series is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_START_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_SKIP_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + } + + return true; +} + +enum TrashSpells +{ + // Ghostly Priest + SPELL_SHADOW_WORD_PAIN = 72318, + SPELL_CIRCLE_OF_DESTRUCTION = 72320, + SPELL_COWER_IN_FEAR = 72321, + SPELL_DARK_MENDING = 72322, + + // Phantom Mage + SPELL_FIREBALL = 72163, + SPELL_FLAMESTRIKE = 72169, + SPELL_FROSTBOLT = 72166, + SPELL_CHAINS_OF_ICE = 72121, + SPELL_HALLUCINATION = 72342, + + // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) + SPELL_HALLUCINATION_2 = 72344, + + // Shadowy Mercenary + SPELL_SHADOW_STEP = 72326, + SPELL_DEADLY_POISON = 72329, + SPELL_ENVENOMED_DAGGER_THROW = 72333, + SPELL_KIDNEY_SHOT = 72335, + + // Spectral Footman + SPELL_SPECTRAL_STRIKE = 72198, + SPELL_SHIELD_BASH = 72194, + SPELL_TORTURED_ENRAGE = 72203, + + // Tortured Rifleman + SPELL_SHOOT = 72208, + SPELL_CURSED_ARROW = 72222, + SPELL_FROST_TRAP = 72215, + SPELL_ICE_SHOT = 72268, +}; + +enum TrashEvents +{ + EVENT_TRASH_NONE, + + // Ghostly Priest + EVENT_SHADOW_WORD_PAIN, + EVENT_CIRCLE_OF_DESTRUCTION, + EVENT_COWER_IN_FEAR, + EVENT_DARK_MENDING, + + // Phantom Mage + EVENT_FIREBALL, + EVENT_FLAMESTRIKE, + EVENT_FROSTBOLT, + EVENT_CHAINS_OF_ICE, + EVENT_HALLUCINATION, + + // Shadowy Mercenary + EVENT_SHADOW_STEP, + EVENT_DEADLY_POISON, + EVENT_ENVENOMED_DAGGER_THROW, + EVENT_KIDNEY_SHOT, + + // Spectral Footman + EVENT_SPECTRAL_STRIKE, + EVENT_SHIELD_BASH, + EVENT_TORTURED_ENRAGE, + + // Tortured Rifleman + EVENT_SHOOT, + EVENT_CURSED_ARROW, + EVENT_FROST_TRAP, + EVENT_ICE_SHOT, +}; + +struct npc_ghostly_priestAI: public ScriptedAI +{ + npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_WORD_PAIN: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); + return; + case EVENT_CIRCLE_OF_DESTRUCTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + return; + case EVENT_COWER_IN_FEAR: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_COWER_IN_FEAR); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + return; + case EVENT_DARK_MENDING: + // find an ally with missing HP + if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) + { + DoCast(pTarget, SPELL_DARK_MENDING); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + else + { + // no friendly unit with missing hp. re-check in just 5 sec. + events.ScheduleEvent(EVENT_DARK_MENDING, 5000); + } + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_mageAI: public ScriptedAI +{ + npc_phantom_mageAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers + events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); + events.ScheduleEvent(EVENT_FROSTBOLT, 9000); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); + events.ScheduleEvent(EVENT_HALLUCINATION, 40000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 15000); + return; + case EVENT_FLAMESTRIKE: + DoCast(SPELL_FLAMESTRIKE); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 15000); + return; + case EVENT_CHAINS_OF_ICE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CHAINS_OF_ICE); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); + return; + case EVENT_HALLUCINATION: + DoCast(SPELL_HALLUCINATION); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_hallucinationAI: public npc_phantom_mageAI +{ + npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) + { + } + + void JustDied(Unit * /*pWho*/) + { + DoCast(SPELL_HALLUCINATION_2); + } +}; + +struct npc_shadowy_mercenaryAI: public ScriptedAI +{ + npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_STEP: + DoCast(SPELL_SHADOW_STEP); + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); + return; + case EVENT_DEADLY_POISON: + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); + return; + case EVENT_ENVENOMED_DAGGER_THROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + return; + case EVENT_KIDNEY_SHOT: + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_spectral_footmanAI: public ScriptedAI +{ + npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers + events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPECTRAL_STRIKE: + DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); + return; + case EVENT_SHIELD_BASH: + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); + return; + case EVENT_TORTURED_ENRAGE: + DoCast(SPELL_TORTURED_ENRAGE); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_tortured_riflemanAI : public ScriptedAI +{ + npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + events.ScheduleEvent(EVENT_FROST_TRAP, 1000); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHOOT); + events.ScheduleEvent(EVENT_SHOOT, 2000); + return; + case EVENT_CURSED_ARROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CURSED_ARROW); + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + return; + case EVENT_FROST_TRAP: + DoCast(SPELL_FROST_TRAP); + events.ScheduleEvent(EVENT_FROST_TRAP, 30000); + return; + case EVENT_ICE_SHOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ICE_SHOT); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_horAI(pCreature); +} + +CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) +{ + return new npc_ghostly_priestAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) +{ + return new npc_phantom_mageAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) +{ + return new npc_phantom_hallucinationAI(pCreature); +} + +CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) +{ + return new npc_shadowy_mercenaryAI(pCreature); +} + +CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) +{ + return new npc_spectral_footmanAI(pCreature); +} + +CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) +{ + return new npc_tortured_riflemanAI(pCreature); +} + +void AddSC_halls_of_reflection() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_jaina_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ghostly_priest"; + newscript->GetAI = &GetAI_npc_ghostly_priestAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_mage"; + newscript->GetAI = &GetAI_npc_phantom_mageAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_hallucination"; + newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shadowy_mercenary"; + newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spectral_footman"; + newscript->GetAI = &GetAI_npc_spectral_footmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tortured_rifleman"; + newscript->GetAI = &GetAI_npc_tortured_riflemanAI; + newscript->RegisterSelf(); +} diff --git a/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h b/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h index ac7ddc09b6d..46ae0cb283c 100644 --- a/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h +++ b/src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h @@ -16,16 +16,141 @@ #ifndef DEF_HALLS_OF_REFLECTION_H #define DEF_HALLS_OF_REFLECTION_H + enum Data { DATA_FALRIC_EVENT, DATA_MARWYN_EVENT, - DATA_LICHKING_EVENT + DATA_LICHKING_EVENT, + DATA_WAVE_COUNT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_FALRIC, + DATA_MARWYN, + DATA_LICHKING, + DATA_FROSTMOURNE, }; + enum Creatures { - CREATURE_FALRIC = 36494, - CREATURE_MARWYN = 36476, - CREATURE_LICHKING = 36658 + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, + NPC_LICH_KING_EVENT = 37226, + NPC_LICH_KING_BOSS = 36954, + + NPC_UTHER = 37225, + NPC_JAINA_PART1 = 37221, + NPC_JAINA_PART2 = 36955, + NPC_SYLVANAS_PART1 = 37223, + NPC_SYLVANAS_PART2 = 37554, + + NPC_WAVE_MERCENARY = 38177, + NPC_WAVE_FOOTMAN = 38173, + NPC_WAVE_RIFLEMAN = 38176, + NPC_WAVE_PRIEST = 38175, + NPC_WAVE_MAGE = 38172, +}; + +enum GameObjects +{ + GO_FROSTMOURNE = 202302, + GO_FROSTMOURNE_ALTAR = 202236, + GO_FRONT_DOOR = 201976, + GO_ARTHAS_DOOR = 197341, }; + +enum HorWorldStates +{ + WORLD_STATE_HOR = 4884, + WORLD_STATE_HOR_WAVE_COUNT = 4882, +}; + +// Common actions from Instance Script to Boss Script +enum Actions +{ + ACTION_ENTER_COMBAT, +}; + +// Base class for FALRIC and MARWYN +// handled the summonList and the notification events to/from the InstanceData +struct boss_horAI : ScriptedAI +{ + boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) + { + pInstance = me->GetInstanceData(); + } + + InstanceData* pInstance; + EventMap events; + SummonList summons; + + void Reset() + { + events.Reset(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + } + + void DamageTaken(Unit *pWho, uint32 &uiDamage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + uiDamage = 0; + } + + void DoAction(const int32 actionID) + { + switch(actionID) + { + case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. + // Just in case. Should have been done by InstanceData + me->SetVisibility(VISIBILITY_ON); + + // Reset flags + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + if (Unit *pUnit = me->SelectNearestTarget()) + AttackStart(pUnit); + + DoZoneInCombat(); + break; + } + } + + void JustSummoned(Creature *pSummoned) + { + summons.Summon(pSummoned); + + if (Unit *pUnit = pSummoned->SelectNearestTarget()) + { + if (pSummoned->AI()) + pSummoned->AI()->AttackStart(pUnit); + else + { + pSummoned->GetMotionMaster()->MoveChase(pUnit); + pSummoned->Attack(pUnit, true); + } + } + + if (pSummoned->AI()) + pSummoned->AI()->DoZoneInCombat(); + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + summons.Despawn(pSummoned); + if (summons.empty()) + { + if (pSummoned->isAlive()) + pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); + else + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); + } + } +}; + #endif diff --git a/src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp index 3c0c1321a77..7a5d2479b7c 100644 --- a/src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp +++ b/src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp @@ -25,61 +25,212 @@ 2- The Lich King */ +enum eEnum +{ + ENCOUNTER_WAVE_MERCENARY = 6, + ENCOUNTER_WAVE_FOOTMAN = 10, + ENCOUNTER_WAVE_RIFLEMAN = 6, + ENCOUNTER_WAVE_PRIEST = 6, + ENCOUNTER_WAVE_MAGE = 6, +}; + +enum Events +{ + EVENT_NONE, + EVENT_NEXT_WAVE, + EVENT_START_LICH_KING, +}; + +static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = +{ + {5277.74,2016.88,707.778,5.96903}, + {5295.88,2040.34,707.778,5.07891}, + {5320.37,1980.13,707.778,2.00713}, + {5280.51,1997.84,707.778,0.296706}, + {5302.45,2042.22,707.778,4.90438}, + {5306.57,1977.47,707.778,1.50098}, +}; + +static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = +{ + {5312.75,2037.12,707.778,4.59022}, + {5309.58,2042.67,707.778,4.69494}, + {5275.08,2008.72,707.778,6.21337}, + {5279.65,2004.66,707.778,0.069813}, + {5275.48,2001.14,707.778,0.174533}, + {5316.7,2041.55,707.778,4.50295}, +}; + +static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = +{ + {5302.25,1972.41,707.778,1.37881}, + {5311.03,1972.23,707.778,1.64061}, + {5277.36,1993.23,707.778,0.401426}, + {5318.7,2036.11,707.778,4.2237}, + {5335.72,1996.86,707.778,2.74017}, + {5299.43,1979.01,707.778,1.23918}, +}; + +static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = +{ + {5306.06,2037,707.778,4.81711}, + {5344.15,2007.17,707.778,3.15905}, + {5337.83,2010.06,707.778,3.22886}, + {5343.29,1999.38,707.778,2.9147}, + {5340.84,1992.46,707.778,2.75762}, + {5325.07,1977.6,707.778,2.07694}, + {5336.6,2017.28,707.778,3.47321}, + {5313.82,1978.15,707.778,1.74533}, + {5280.63,2012.16,707.778,6.05629}, + {5322.96,2040.29,707.778,4.34587}, +}; + +static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = +{ + {5343.47,2015.95,707.778,3.49066}, + {5337.86,2003.4,707.778,2.98451}, + {5319.16,1974,707.778,1.91986}, + {5299.25,2036,707.778,5.02655}, + {5295.64,1973.76,707.778,1.18682}, + {5282.9,2019.6,707.778,5.88176}, +}; + struct instance_halls_of_reflection : public ScriptedInstance { - instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; uint64 uiFalric; uint64 uiMarwyn; - uint64 uiLichKing; + uint64 uiLichKingEvent; + uint64 uiJainaPart1; + uint64 uiSylvanasPart1; - uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 uiFrostmourne; + uint64 uiFrostmourneAltar; + uint64 uiArthasDoor; + uint64 uiFrontDoor; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + uint32 uiWaveCount; + bool bIntroDone; + + EventMap events; void Initialize() { + events.Reset(); + uiFalric = 0; uiMarwyn = 0; - uiLichKing = 0; + uiLichKingEvent = 0; + uiJainaPart1 = 0; + uiSylvanasPart1 = 0; + + uiFrostmourne = 0; + uiFrostmourneAltar = 0; + uiArthasDoor = 0; + uiFrontDoor = 0; + uiTeamInInstance = 0; + uiWaveCount = 0; + bIntroDone = false; for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; + uiEncounter[i] = NOT_STARTED; } - void OnCreatureCreate(Creature* pCreature, bool /*add*/) + void OnCreatureCreate(Creature* pCreature, bool add) { + if (!add) + return; + + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + switch(pCreature->GetEntry()) { - case CREATURE_FALRIC: + case NPC_FALRIC: uiFalric = pCreature->GetGUID(); break; - case CREATURE_MARWYN: + case NPC_MARWYN: uiMarwyn = pCreature->GetGUID(); break; - case CREATURE_LICHKING: - uiLichKing = pCreature->GetGUID(); + case NPC_LICH_KING_EVENT: + uiLichKingEvent = pCreature->GetGUID(); + break; + case NPC_JAINA_PART1: + uiJainaPart1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + uiSylvanasPart1 = pCreature->GetGUID(); break; } } -/* + void OnGameObjectCreate(GameObject* pGo, bool add) { + if (!add) + return; + + // TODO: init state depending on encounters switch(pGo->GetEntry()) { + case GO_FROSTMOURNE: + uiFrostmourne = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, false, pGo); + break; + case GO_FROSTMOURNE_ALTAR: + uiFrostmourneAltar = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_FRONT_DOOR: + uiFrontDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_ARTHAS_DOOR: + uiArthasDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + + if (uiEncounter[1] == DONE) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; } } -*/ + void SetData(uint32 type, uint32 data) { + if (type == DATA_WAVE_COUNT && data == SPECIAL) + { + bIntroDone = true; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + return; + } + + + if (uiWaveCount && data == NOT_STARTED) + DoWipe(); + switch(type) { case DATA_FALRIC_EVENT: - m_auiEncounter[0] = data; + uiEncounter[0] = data; + if (data == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); break; case DATA_MARWYN_EVENT: - m_auiEncounter[1] = data; + uiEncounter[1] = data; + if (data == DONE) + HandleGameObject(uiArthasDoor, true); break; case DATA_LICHKING_EVENT: - m_auiEncounter[2] = data; + uiEncounter[2] = data; break; } @@ -91,29 +242,35 @@ struct instance_halls_of_reflection : public ScriptedInstance { switch(type) { - case DATA_FALRIC_EVENT: return m_auiEncounter[0]; - case DATA_MARWYN_EVENT: return m_auiEncounter[1]; - case DATA_LICHKING_EVENT: return m_auiEncounter[2]; + case DATA_FALRIC_EVENT: return uiEncounter[0]; + case DATA_MARWYN_EVENT: return uiEncounter[1]; + case DATA_LICHKING_EVENT: return uiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; } return 0; } -/* + uint64 GetData64(uint32 identifier) { switch(identifier) { + case DATA_FALRIC: return uiFalric; + case DATA_MARWYN: return uiMarwyn; + case DATA_LICHKING: return uiLichKingEvent; + case DATA_FROSTMOURNE: return uiFrostmourne; } return 0; } -*/ + std::string GetSaveData() { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << "H R " << m_auiEncounter[0] << " " << m_auiEncounter[1] << m_auiEncounter[2]; + saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); @@ -130,25 +287,133 @@ struct instance_halls_of_reflection : public ScriptedInstance OUT_LOAD_INST_DATA(in); char dataHead1, dataHead2; + uint16 version; uint16 data0, data1, data2; std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; if (dataHead1 == 'H' && dataHead2 == 'R') { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; } else OUT_LOAD_INST_DATA_FAIL; + if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) + bIntroDone = true; + OUT_LOAD_INST_DATA_COMPLETE; } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + + switch(uiWaveCount) + { + case 1: + case 2: + case 3: + case 4: + if (Creature *pFalric = instance->GetCreature(uiFalric)) + SpawnWave(pFalric); + break; + case 5: + if (GetData(DATA_FALRIC_EVENT) == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + else if (Creature *pFalric = instance->GetCreature(uiFalric)) + if (pFalric->AI()) + pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + case 6: + case 7: + case 8: + case 9: + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + SpawnWave(pMarwyn); + break; + case 10: + if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + if (pMarwyn->AI()) + pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + } + } + + // Wipe has been detected. Perform cleanup and reset. + void DoWipe() + { + uiWaveCount = 0; + events.Reset(); + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + HandleGameObject(uiFrontDoor, true); + + // TODO + // in case of wipe, the event is normally restarted by jumping into the center of the room. + // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. + if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) + pJaina->Respawn(); + if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) + pSylvanas->Respawn(); + + if (Creature* pFalric = instance->GetCreature(uiFalric)) + pFalric->SetVisibility(VISIBILITY_OFF); + if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) + pMarwyn->SetVisibility(VISIBILITY_OFF); + } + + // spawn a wave on behalf of the summoner. + void SpawnWave(Creature *pSummoner) + { + uint32 index; + + pSummoner->SetVisibility(VISIBILITY_ON); + + // TODO: do composition at random. # of spawn also depends on uiWaveCount + // As of now, it is just one of each. + index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); + pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); + pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); + pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_PRIEST-1); + pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_MAGE-1); + pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + events.Update(diff); + + switch(uint32 eventId = events.ExecuteEvent()) + { + case EVENT_NEXT_WAVE: + uiWaveCount++; + AddWave(); + break; + case EVENT_START_LICH_KING: + // TODO + break; + } + } }; InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) @@ -156,7 +421,7 @@ InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) return new instance_halls_of_reflection(pMap); } -void AddSC_halls_of_reflection() +void AddSC_instance_halls_of_reflection() { Script *newscript; newscript = new Script; |