aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp8
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp8
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp850
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h134
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp631
5 files changed, 1008 insertions, 623 deletions
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
index 58dc74d0f0a..9d266c77b77 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
@@ -19,7 +19,7 @@
#include "ScriptedCreature.h"
#include "halls_of_reflection.h"
-enum Yells
+enum Texts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
@@ -68,14 +68,14 @@ public:
uiHopelessnessCount = 0;
if (instance)
- instance->SetData(DATA_FALRIC_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_FALRIC_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
if (instance)
- instance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_FALRIC_EVENT, IN_PROGRESS);
events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000);
events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000);
@@ -87,7 +87,7 @@ public:
Talk(SAY_DEATH);
if (instance)
- instance->SetData(DATA_FALRIC_EVENT, DONE);
+ instance->SetBossState(DATA_FALRIC_EVENT, DONE);
}
void KilledUnit(Unit* /*victim*/)
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
index 08d5cf70ee1..e82f0d48ebd 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
@@ -19,7 +19,7 @@
#include "ScriptedCreature.h"
#include "halls_of_reflection.h"
-enum Yells
+enum Texts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
@@ -63,14 +63,14 @@ public:
boss_horAI::Reset();
if (instance)
- instance->SetData(DATA_MARWYN_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_MARWYN_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
Talk(SAY_AGGRO);
if (instance)
- instance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_MARWYN_EVENT, IN_PROGRESS);
events.ScheduleEvent(EVENT_OBLITERATE, 30000); /// @todo Check timer
events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
@@ -83,7 +83,7 @@ public:
Talk(SAY_DEATH);
if (instance)
- instance->SetData(DATA_MARWYN_EVENT, DONE);
+ instance->SetBossState(DATA_MARWYN_EVENT, DONE);
}
void KilledUnit(Unit* /*victim*/)
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index b140801d8f1..eab4b100da2 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -17,11 +17,9 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
#include "halls_of_reflection.h"
-#include "Player.h"
-enum Yells
+enum Text
{
SAY_JAINA_INTRO_1 = 0,
SAY_JAINA_INTRO_2 = 1,
@@ -66,17 +64,19 @@ enum Yells
SAY_LK_INTRO_1 = 0,
SAY_LK_INTRO_2 = 1,
SAY_LK_INTRO_3 = 2,
+ SAY_LK_JAINA_INTRO_END = 3,
+ SAY_LK_SYLVANAS_INTRO_END = 4,
SAY_FALRIC_INTRO_1 = 5,
SAY_FALRIC_INTRO_2 = 6,
- SAY_MARWYN_INTRO_1 = 4
+ SAY_MARWYN_INTRO_1 = 4,
};
enum Events
{
- EVENT_NONE,
-
+ EVENT_WALK_INTRO1 = 1,
+ EVENT_WALK_INTRO2,
EVENT_START_INTRO,
EVENT_SKIP_INTRO,
@@ -125,8 +125,13 @@ enum Events
EVENT_INTRO_LK_7,
EVENT_INTRO_LK_8,
EVENT_INTRO_LK_9,
+ EVENT_INTRO_LK_10,
+ EVENT_INTRO_LK_11,
EVENT_INTRO_END,
+
+ EVENT_OPEN_FROSTWORN_DOOR,
+ EVENT_CLOSE_FROSTWORN_DOOR,
};
enum eEnum
@@ -140,6 +145,17 @@ enum eEnum
QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802,
};
+enum Spells
+{
+ SPELL_CAST_VISUAL = 65633, // Jaina/Sylavana
+ SPELL_BOSS_SPAWN_AURA = 72712, // Falric and Marwyn
+ SPELL_UTHER_DESPAWN = 70693,
+ SPELL_TAKE_FROSTMOURNE = 72729,
+ SPELL_FROSTMOURNE_DESPAWN = 72726,
+ SPELL_FROSTMOURNE_VISUAL = 73220,
+ SPELL_FROSTMOURNE_SOUNDS = 70667,
+};
+
const Position HallsofReflectionLocs[]=
{
{5283.234863f, 1990.946777f, 707.695679f, 0.929097f}, // 2 Loralen Follows
@@ -147,7 +163,7 @@ const Position HallsofReflectionLocs[]=
{5401.866699f, 2110.837402f, 707.695251f, 0.800610f}, // 10 Loralen follows
};
-const Position SpawnPos = {5262.540527f, 1949.693726f, 707.695007f, 0.808736f}; // Jaina/Sylvanas Beginning Position
+const Position IntroPos = {5265.89f, 1952.98f, 707.6978f, 0.0f}; // Jaina/Sylvanas Intro Start Position
const Position MoveThronePos = {5306.952148f, 1998.499023f, 709.341431f, 1.277278f}; // Jaina/Sylvanas walks to throne
const Position UtherSpawnPos = {5308.310059f, 2003.857178f, 709.341431f, 4.650315f};
const Position LichKingSpawnPos = {5362.917480f, 2062.307129f, 707.695374f, 3.945812f};
@@ -156,58 +172,10 @@ const Position LichKingMoveAwayPos = {5400.069824f, 2102.7131689f, 707.69525f,
class npc_jaina_or_sylvanas_hor : public CreatureScript
{
-private:
- bool m_isSylvana;
-
-public:
- npc_jaina_or_sylvanas_hor(bool isSylvana, const char* name) : CreatureScript(name), m_isSylvana(isSylvana) { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->CLOSE_GOSSIP_MENU();
- if (creature->AI())
- creature->AI()->DoAction(ACTION_START_INTRO);
- creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->CLOSE_GOSSIP_MENU();
- if (creature->AI())
- creature->AI()->DoAction(ACTION_SKIP_INTRO);
- creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- }
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature)
- {
- if (creature->isQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- QuestStatus status = player->GetQuestStatus(m_isSylvana ? QUEST_DELIVRANCE_FROM_THE_PIT_H2 : QUEST_DELIVRANCE_FROM_THE_PIT_A2);
- if (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_REWARDED)
- player->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
- status = player->GetQuestStatus(m_isSylvana ? QUEST_WRATH_OF_THE_LICH_KING_H2 : QUEST_WRATH_OF_THE_LICH_KING_A2);
- if (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_REWARDED)
- player->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);
-
- player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const
- {
- return new npc_jaina_or_sylvanas_horAI(creature);
- }
+ public:
+ npc_jaina_or_sylvanas_hor() : CreatureScript("npc_jaina_or_sylvanas_hor") { }
- // AI of Part1: handle the intro till start of gauntlet event.
+ // AI of Part1
struct npc_jaina_or_sylvanas_horAI : public ScriptedAI
{
npc_jaina_or_sylvanas_horAI(Creature* creature) : ScriptedAI(creature)
@@ -221,6 +189,24 @@ public:
EventMap events;
+ void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action)
+ {
+ player->PlayerTalkClass->ClearMenus();
+ switch (action)
+ {
+ case 0:
+ player->CLOSE_GOSSIP_MENU();
+ events.ScheduleEvent(EVENT_START_INTRO, 1000);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ case 1:
+ player->CLOSE_GOSSIP_MENU();
+ events.ScheduleEvent(EVENT_SKIP_INTRO, 1000);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ }
+ }
+
void Reset()
{
events.Reset();
@@ -228,22 +214,9 @@ public:
utherGUID = 0;
lichkingGUID = 0;
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
me->SetStandState(UNIT_STAND_STATE_STAND);
- me->SetVisible(true);
- }
-
- void DoAction(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;
- }
+ events.ScheduleEvent(EVENT_WALK_INTRO1, 3000);
}
void UpdateAI(uint32 diff)
@@ -251,6 +224,26 @@ public:
events.Update(diff);
switch (events.ExecuteEvent())
{
+ case EVENT_WALK_INTRO1:
+ me->GetMotionMaster()->MovePoint(0, IntroPos);
+ if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ {
+ Talk(SAY_JAINA_INTRO_1);
+ events.ScheduleEvent(EVENT_WALK_INTRO2, 7000);
+ }
+ else
+ {
+ Talk(SAY_SYLVANAS_INTRO_1);
+ events.ScheduleEvent(EVENT_WALK_INTRO2, 9000);
+ }
+ break;
+ case EVENT_WALK_INTRO2:
+ if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ Talk(SAY_JAINA_INTRO_2);
+ else
+ Talk(SAY_SYLVANAS_INTRO_2);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
+ break;
case EVENT_START_INTRO:
me->GetMotionMaster()->MovePoint(0, MoveThronePos);
// Begining of intro is differents between fActions as the speech sequence and timers are differents.
@@ -259,27 +252,25 @@ public:
else
events.ScheduleEvent(EVENT_INTRO_H2_1, 0);
break;
-
- // A2 Intro Events
+ // A2 Intro Events
case EVENT_INTRO_A2_1:
Talk(SAY_JAINA_INTRO_3);
- events.ScheduleEvent(EVENT_INTRO_A2_2, 5000);
+ events.ScheduleEvent(EVENT_INTRO_A2_2, 7000);
break;
case EVENT_INTRO_A2_2:
Talk(SAY_JAINA_INTRO_4);
events.ScheduleEvent(EVENT_INTRO_A2_3, 10000);
break;
case EVENT_INTRO_A2_3:
- /// @todo she's doing some kind of spell casting emote
+ me->CastSpell(me, SPELL_CAST_VISUAL, false);
+ me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
instance->HandleGameObject(instance->GetData64(DATA_FROSTMOURNE), true);
events.ScheduleEvent(EVENT_INTRO_A2_4, 10000);
break;
case EVENT_INTRO_A2_4:
- // spawn UTHER during speach 2
if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
{
uther->GetMotionMaster()->MoveIdle();
- uther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas
utherGUID = uther->GetGUID();
}
events.ScheduleEvent(EVENT_INTRO_A2_5, 2000);
@@ -291,57 +282,57 @@ public:
break;
case EVENT_INTRO_A2_6:
Talk(SAY_JAINA_INTRO_5);
- events.ScheduleEvent(EVENT_INTRO_A2_7, 6000);
+ events.ScheduleEvent(EVENT_INTRO_A2_7, 7000);
break;
case EVENT_INTRO_A2_7:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_2);
- events.ScheduleEvent(EVENT_INTRO_A2_8, 6500);
+ events.ScheduleEvent(EVENT_INTRO_A2_8, 7000);
break;
case EVENT_INTRO_A2_8:
Talk(SAY_JAINA_INTRO_6);
- events.ScheduleEvent(EVENT_INTRO_A2_9, 2000);
+ events.ScheduleEvent(EVENT_INTRO_A2_9, 1200);
break;
case EVENT_INTRO_A2_9:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_3);
- events.ScheduleEvent(EVENT_INTRO_A2_10, 9000);
+ events.ScheduleEvent(EVENT_INTRO_A2_10, 11000);
break;
case EVENT_INTRO_A2_10:
Talk(SAY_JAINA_INTRO_7);
- events.ScheduleEvent(EVENT_INTRO_A2_11, 5000);
+ events.ScheduleEvent(EVENT_INTRO_A2_11, 6000);
break;
case EVENT_INTRO_A2_11:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_4);
- events.ScheduleEvent(EVENT_INTRO_A2_12, 11000);
+ events.ScheduleEvent(EVENT_INTRO_A2_12, 12000);
break;
case EVENT_INTRO_A2_12:
Talk(SAY_JAINA_INTRO_8);
- events.ScheduleEvent(EVENT_INTRO_A2_13, 4000);
+ events.ScheduleEvent(EVENT_INTRO_A2_13, 6000);
break;
case EVENT_INTRO_A2_13:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_5);
- events.ScheduleEvent(EVENT_INTRO_A2_14, 12500);
+ events.ScheduleEvent(EVENT_INTRO_A2_14, 13000);
break;
case EVENT_INTRO_A2_14:
Talk(SAY_JAINA_INTRO_9);
- events.ScheduleEvent(EVENT_INTRO_A2_15, 10000);
+ events.ScheduleEvent(EVENT_INTRO_A2_15, 12000);
break;
case EVENT_INTRO_A2_15:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_6);
- events.ScheduleEvent(EVENT_INTRO_A2_16, 22000);
+ events.ScheduleEvent(EVENT_INTRO_A2_16, 25000);
break;
case EVENT_INTRO_A2_16:
if (Creature* uther = me->GetCreature(*me, utherGUID))
uther->AI()->Talk(SAY_UTHER_INTRO_A2_7);
- events.ScheduleEvent(EVENT_INTRO_A2_17, 4000);
+ events.ScheduleEvent(EVENT_INTRO_A2_17, 6000);
break;
case EVENT_INTRO_A2_17:
Talk(SAY_JAINA_INTRO_10);
- events.ScheduleEvent(EVENT_INTRO_A2_18, 2000);
+ events.ScheduleEvent(EVENT_INTRO_A2_18, 5000);
break;
case EVENT_INTRO_A2_18:
if (Creature* uther = me->GetCreature(*me, utherGUID))
@@ -349,14 +340,13 @@ public:
uther->HandleEmoteCommand(EMOTE_ONESHOT_NO);
uther->AI()->Talk(SAY_UTHER_INTRO_A2_8);
}
- events.ScheduleEvent(EVENT_INTRO_A2_19, 11000);
+ events.ScheduleEvent(EVENT_INTRO_A2_19, 12000);
break;
case EVENT_INTRO_A2_19:
Talk(SAY_JAINA_INTRO_11);
- events.ScheduleEvent(EVENT_INTRO_LK_1, 2000);
+ events.ScheduleEvent(EVENT_INTRO_LK_1, 3000);
break;
-
- // H2 Intro Events
+ // H2 Intro Events
case EVENT_INTRO_H2_1:
Talk(SAY_SYLVANAS_INTRO_1);
events.ScheduleEvent(EVENT_INTRO_H2_2, 8000);
@@ -367,7 +357,9 @@ public:
break;
case EVENT_INTRO_H2_3:
Talk(SAY_SYLVANAS_INTRO_3);
- /// @todo she's doing some kind of spell casting emote
+ me->CastSpell(me, SPELL_CAST_VISUAL, false);
+ me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
+ instance->HandleGameObject(instance->GetData64(DATA_FROSTMOURNE), true);
events.ScheduleEvent(EVENT_INTRO_H2_4, 6000);
break;
case EVENT_INTRO_H2_4:
@@ -375,7 +367,6 @@ public:
if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
{
uther->GetMotionMaster()->MoveIdle();
- uther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas
utherGUID = uther->GetGUID();
}
events.ScheduleEvent(EVENT_INTRO_H2_5, 2000);
@@ -433,126 +424,160 @@ public:
Talk(SAY_SYLVANAS_INTRO_8);
events.ScheduleEvent(EVENT_INTRO_LK_1, 2000);
break;
-
- // Remaining Intro Events common for both faction
+ // 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* lichking = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
+ if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
{
+ lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos);
- lichking->SetReactState(REACT_PASSIVE);
+ //lichking->SetReactState(REACT_PASSIVE);
lichkingGUID = lichking->GetGUID();
+ events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0);
+ events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000);
}
-
if (Creature* uther = me->GetCreature(*me, utherGUID))
{
+ uther->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER);
if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
uther->AI()->Talk(SAY_UTHER_INTRO_A2_9);
else
uther->AI()->Talk(SAY_UTHER_INTRO_H2_7);
}
-
- events.ScheduleEvent(EVENT_INTRO_LK_2, 11000);
+ events.ScheduleEvent(EVENT_INTRO_LK_2, 10000);
break;
-
case EVENT_INTRO_LK_2:
- if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
- lichking->AI()->Talk(SAY_LK_INTRO_1);
- events.ScheduleEvent(EVENT_INTRO_LK_3, 2000);
- break;
-
+ if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
+ lichking->AI()->Talk(SAY_LK_INTRO_1);
+ events.ScheduleEvent(EVENT_INTRO_LK_3, 1000);
+ break;
case EVENT_INTRO_LK_3:
- // The Lich King banishes Uther to the abyss.
- if (Creature* uther = me->GetCreature(*me, utherGUID))
- {
- uther->DisappearAndDie();
- utherGUID = 0;
- }
-
- // He steps forward and removes the runeblade from the heap of skulls.
-
- events.ScheduleEvent(EVENT_INTRO_LK_4, 4000);
- break;
-
+ // The Lich King banishes Uther to the abyss.
+ if (Creature* uther = me->GetCreature(*me, utherGUID))
+ {
+ uther->CastSpell(uther, SPELL_UTHER_DESPAWN, true);
+ uther->DespawnOrUnsummon(5000);
+ utherGUID = 0;
+ }
+ events.ScheduleEvent(EVENT_INTRO_LK_4, 9000);
+ break;
case EVENT_INTRO_LK_4:
- if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
- lichking->AI()->Talk(SAY_LK_INTRO_2);
- events.ScheduleEvent(EVENT_INTRO_LK_5, 10000);
+ // He steps forward and removes the runeblade from the heap of skulls.
+ if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
+ {
+ if (GameObject* frostmourne = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTMOURNE)))
+ frostmourne->SetPhaseMask(2, true);
+ lichking->CastSpell(lichking, SPELL_TAKE_FROSTMOURNE, true);
+ lichking->CastSpell(lichking, SPELL_FROSTMOURNE_VISUAL, true);
+ }
+ events.ScheduleEvent(EVENT_INTRO_LK_5, 8000);
break;
-
case EVENT_INTRO_LK_5:
+ if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
+ lichking->AI()->Talk(SAY_LK_INTRO_2);
+ events.ScheduleEvent(EVENT_INTRO_LK_6, 8000);
+ break;
+ case EVENT_INTRO_LK_6:
// summon Falric and Marwyn. then go back to the door
- if (Creature* pFalric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC)))
- pFalric->SetVisible(true);
- if (Creature* pMarwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN)))
- pMarwyn->SetVisible(true);
-
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT)))
+ {
+ falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
+ falric->SetVisible(true);
+ }
+ if (Creature* marwyn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MARWYN_EVENT)))
+ {
+ marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
+ marwyn->SetVisible(true);
+ }
if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
{
- lichking->GetMotionMaster()->MovePoint(0, LichKingSpawnPos);
lichking->AI()->Talk(SAY_LK_INTRO_3);
+ lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
+ lichking->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
}
-
- events.ScheduleEvent(EVENT_INTRO_LK_6, 8000);
- break;
-
- case EVENT_INTRO_LK_6:
- if (Creature* falric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC)))
- falric->AI()->Talk(SAY_FALRIC_INTRO_1);
-
- events.ScheduleEvent(EVENT_INTRO_LK_7, 2000);
+ events.ScheduleEvent(EVENT_INTRO_LK_7, 10000);
+ events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 5000);
break;
-
case EVENT_INTRO_LK_7:
- if (Creature* marwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN)))
+ if (Creature* marwyn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MARWYN_EVENT)))
marwyn->AI()->Talk(SAY_MARWYN_INTRO_1);
-
- events.ScheduleEvent(EVENT_INTRO_LK_8, 2000);
+ events.ScheduleEvent(EVENT_INTRO_LK_8, 1000);
break;
-
case EVENT_INTRO_LK_8:
- if (Creature* falric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC)))
- falric->AI()->Talk(SAY_FALRIC_INTRO_2);
-
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT)))
+ falric->AI()->Talk(SAY_FALRIC_INTRO_1);
events.ScheduleEvent(EVENT_INTRO_LK_9, 5000);
break;
-
case EVENT_INTRO_LK_9:
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT)))
+ falric->AI()->Talk(SAY_FALRIC_INTRO_2);
+ events.ScheduleEvent(EVENT_INTRO_LK_10, 7000);
+ break;
+ case EVENT_INTRO_LK_10:
if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
Talk(SAY_JAINA_INTRO_END);
else
Talk(SAY_SYLVANAS_INTRO_END);
-
- me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos);
+ me->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
/// @todo Loralen/Koreln shall run also
- events.ScheduleEvent(EVENT_INTRO_END, 10000);
+ events.ScheduleEvent(EVENT_INTRO_LK_11, 5000);
+ break;
+ case EVENT_INTRO_LK_11:
+ if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
+ {
+ if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ lichking->AI()->Talk(SAY_LK_JAINA_INTRO_END);
+ else
+ lichking->AI()->Talk(SAY_LK_SYLVANAS_INTRO_END);
+ }
+ events.ScheduleEvent(EVENT_INTRO_END, 5000);
break;
-
case EVENT_INTRO_END:
if (instance)
- instance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave
-
+ {
+ instance->SetData(DATA_INTRO_EVENT, DONE);
+ instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
+ //instance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave
+ }
// Loralen or Koreln disappearAndDie()
- me->DisappearAndDie();
+ if (Creature* lichking = me->GetCreature(*me, lichkingGUID))
+ {
+ lichking->DespawnOrUnsummon(5000);
+ lichkingGUID = 0;
+ }
+ me->DespawnOrUnsummon(10000);
+ events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 7000);
break;
-
case EVENT_SKIP_INTRO:
- /// @todo implement
-
- if (Creature* pFalric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC)))
- pFalric->SetVisible(true);
- if (Creature* pMarwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN)))
- pMarwyn->SetVisible(true);
-
- me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos);
+ me->GetMotionMaster()->MovePoint(0, MoveThronePos);
/// @todo Loralen/Koreln shall run also
-
- events.ScheduleEvent(EVENT_INTRO_END, 15000);
+ if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
+ {
+ lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING);
+ lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos);
+ lichking->SetReactState(REACT_PASSIVE);
+ lichkingGUID = lichking->GetGUID();
+ events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0);
+ events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000);
+ }
+ events.ScheduleEvent(EVENT_INTRO_LK_4, 15000);
+ break;
+ case EVENT_OPEN_FROSTWORN_DOOR:
+ if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTWORN_DOOR)))
+ instance->HandleGameObject(0 ,true, gate);
+ break;
+ case EVENT_CLOSE_FROSTWORN_DOOR:
+ if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTWORN_DOOR)))
+ instance->HandleGameObject(0 ,false, gate);
break;
}
}
};
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_jaina_or_sylvanas_horAI(creature);
+ }
};
enum TrashSpells
@@ -640,13 +665,19 @@ public:
{
npc_ghostly_priestAI(Creature* creature) : ScriptedAI(creature)
{
+ instance = me->GetInstanceScript();
+ me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
}
+ InstanceScript* instance;
+
EventMap events;
void Reset()
{
events.Reset();
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
@@ -667,39 +698,36 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ switch (events.ExecuteEvent())
{
- switch (eventId)
- {
- case EVENT_SHADOW_WORD_PAIN:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SHADOW_WORD_PAIN);
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000);
- return;
- case EVENT_CIRCLE_OF_DESTRUCTION:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION);
- events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
- return;
- case EVENT_COWER_IN_FEAR:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_COWER_IN_FEAR);
- events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
- return;
- case EVENT_DARK_MENDING:
- // find an ally with missing HP
- if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000)))
- {
- DoCast(target, 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;
- }
+ case EVENT_SHADOW_WORD_PAIN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_SHADOW_WORD_PAIN);
+ events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000);
+ break;
+ case EVENT_CIRCLE_OF_DESTRUCTION:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION);
+ events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
+ break;
+ case EVENT_COWER_IN_FEAR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_COWER_IN_FEAR);
+ events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
+ break;
+ case EVENT_DARK_MENDING:
+ // find an ally with missing HP
+ if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000)))
+ {
+ DoCast(target, 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);
+ }
+ break;
}
DoMeleeAttackIfReady();
@@ -722,13 +750,19 @@ public:
{
npc_phantom_mageAI(Creature* creature) : ScriptedAI(creature)
{
+ instance = me->GetInstanceScript();
+ me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
}
+ InstanceScript* instance;
+
EventMap events;
void Reset()
{
events.Reset();
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
@@ -750,33 +784,30 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ switch (events.ExecuteEvent())
{
- switch (eventId)
- {
- case EVENT_FIREBALL:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, 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* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_FROSTBOLT);
- events.ScheduleEvent(EVENT_FROSTBOLT, 15000);
- return;
- case EVENT_CHAINS_OF_ICE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_CHAINS_OF_ICE);
- events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000);
- return;
- case EVENT_HALLUCINATION:
- DoCast(SPELL_HALLUCINATION);
- return;
- }
+ case EVENT_FIREBALL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_FIREBALL);
+ events.ScheduleEvent(EVENT_FIREBALL, 15000);
+ break;
+ case EVENT_FLAMESTRIKE:
+ DoCast(SPELL_FLAMESTRIKE);
+ events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000);
+ break;
+ case EVENT_FROSTBOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_FROSTBOLT);
+ events.ScheduleEvent(EVENT_FROSTBOLT, 15000);
+ break;
+ case EVENT_CHAINS_OF_ICE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_CHAINS_OF_ICE);
+ events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000);
+ break;
+ case EVENT_HALLUCINATION:
+ DoCast(SPELL_HALLUCINATION);
+ break;
}
DoMeleeAttackIfReady();
@@ -797,9 +828,7 @@ public:
struct npc_phantom_hallucinationAI : public npc_phantom_mage::npc_phantom_mageAI
{
- npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature)
- {
- }
+ npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) {}
void JustDied(Unit* /*killer*/)
{
@@ -823,13 +852,19 @@ public:
{
npc_shadowy_mercenaryAI(Creature* creature) : ScriptedAI(creature)
{
+ instance = me->GetInstanceScript();
+ me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
}
+ InstanceScript* instance;
+
EventMap events;
void Reset()
{
events.Reset();
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
@@ -850,28 +885,25 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ switch (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* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, 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;
- }
+ case EVENT_SHADOW_STEP:
+ DoCast(SPELL_SHADOW_STEP);
+ events.ScheduleEvent(EVENT_SHADOW_STEP, 8000);
+ break;
+ case EVENT_DEADLY_POISON:
+ DoCast(me->getVictim(), SPELL_DEADLY_POISON);
+ events.ScheduleEvent(EVENT_DEADLY_POISON, 10000);
+ break;
+ case EVENT_ENVENOMED_DAGGER_THROW:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_ENVENOMED_DAGGER_THROW);
+ events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000);
+ break;
+ case EVENT_KIDNEY_SHOT:
+ DoCast(me->getVictim(), SPELL_KIDNEY_SHOT);
+ events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000);
+ break;
}
DoMeleeAttackIfReady();
@@ -894,13 +926,19 @@ public:
{
npc_spectral_footmanAI(Creature* creature) : ScriptedAI(creature)
{
+ instance = me->GetInstanceScript();
+ me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
}
+ InstanceScript* instance;
+
EventMap events;
void Reset()
{
events.Reset();
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
@@ -920,23 +958,20 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ switch (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;
- }
+ case EVENT_SPECTRAL_STRIKE:
+ DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE);
+ events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000);
+ break;
+ case EVENT_SHIELD_BASH:
+ DoCast(me->getVictim(), SPELL_SHIELD_BASH);
+ events.ScheduleEvent(EVENT_SHIELD_BASH, 5000);
+ break;
+ case EVENT_TORTURED_ENRAGE:
+ DoCast(SPELL_TORTURED_ENRAGE);
+ events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000);
+ break;
}
DoMeleeAttackIfReady();
@@ -959,13 +994,19 @@ public:
{
npc_tortured_riflemanAI(Creature* creature) : ScriptedAI(creature)
{
+ instance = me->GetInstanceScript();
+ me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
}
+ InstanceScript* instance;
+
EventMap events;
void Reset()
{
events.Reset();
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
@@ -986,46 +1027,273 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ switch (events.ExecuteEvent())
{
- switch (eventId)
- {
- case EVENT_SHOOT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SHOOT);
- events.ScheduleEvent(EVENT_SHOOT, 2000);
- return;
- case EVENT_CURSED_ARROW:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, 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* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_ICE_SHOT);
- events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
- return;
- }
+ case EVENT_SHOOT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_SHOOT);
+ events.ScheduleEvent(EVENT_SHOOT, 2000);
+ break;
+ case EVENT_CURSED_ARROW:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_CURSED_ARROW);
+ events.ScheduleEvent(EVENT_CURSED_ARROW, 10000);
+ break;
+ case EVENT_FROST_TRAP:
+ DoCast(SPELL_FROST_TRAP);
+ events.ScheduleEvent(EVENT_FROST_TRAP, 30000);
+ break;
+ case EVENT_ICE_SHOT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_ICE_SHOT);
+ events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+};
+
+
+enum GeneralEvents
+{
+ //General
+ EVENT_SHIELD = 0,
+ EVENT_SPIKE = 1,
+ EVENT_CLONE = 2,
+
+ SAY_AGGRO = 0,
+ SAY_DEATH = 1,
+
+ SPELL_SHIELD_THROWN = 69222, // 73076 on hc
+ SPELL_SPIKE = 69184, // 70399 on hc
+ SPELL_CLONE_NAME = 57507,
+ SPELL_CLONE_MODEL = 45204,
+
+ // Reflection
+ EVENT_BALEFUL_STRIKE = 0,
+
+ SPELL_BALEFUL_STRIKE = 69933, // 70400 on hc
+ SPELL_SPIRIT_BURST = 69900, // 73046 on hc
+};
+
+class npc_frostworn_general : public CreatureScript
+{
+public:
+ npc_frostworn_general() : CreatureScript("npc_frostworn_general") { }
+
+ struct npc_frostworn_generalAI : public ScriptedAI
+ {
+ npc_frostworn_generalAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = me->GetInstanceScript();
+ Reset();
+ }
+
+ InstanceScript* instance;
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ instance->SetData(DATA_FROSWORN_EVENT, NOT_STARTED);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ Talk(SAY_DEATH);
+ instance->SetData(DATA_FROSWORN_EVENT, DONE);
+ }
+
+ void EnterCombat(Unit* /*victim*/)
+ {
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_SHIELD, 5000);
+ events.ScheduleEvent(EVENT_SPIKE, 14000);
+ events.ScheduleEvent(EVENT_CLONE, 22000);
+ instance->SetData(DATA_FROSWORN_EVENT, IN_PROGRESS);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (events.ExecuteEvent())
+ {
+ case EVENT_SHIELD:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_SHIELD_THROWN);
+ events.ScheduleEvent(EVENT_SHIELD, urand(8000, 12000));
+ break;
+ case EVENT_SPIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_SPIKE);
+ events.ScheduleEvent(EVENT_SPIKE, urand(15000, 20000));
+ break;
+ case EVENT_CLONE:
+ SummonClones();
+ events.ScheduleEvent(EVENT_CLONE, 60000);
+ break;
}
DoMeleeAttackIfReady();
}
+
+ void SummonClones()
+ {
+ std::list<Unit *> playerList;
+ SelectTargetList(playerList, 5, SELECT_TARGET_TOPAGGRO, 0, true);
+ for (std::list<Unit*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
+ {
+ Unit* temp = (*itr);
+ Creature* reflection = me->SummonCreature(NPC_REFLECTION, temp->GetPositionX(), temp->GetPositionY(), temp->GetPositionZ(), temp->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000);
+ reflection->SetName(temp->GetName());
+ temp->CastSpell(reflection, SPELL_CLONE_NAME, true);
+ temp->CastSpell(reflection, SPELL_CLONE_MODEL, true);
+ reflection->setFaction(me->getFaction());
+ reflection->AI()->AttackStart(temp);
+ }
+
+ }
};
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_frostworn_generalAI(creature);
+ }
+};
+
+class npc_spiritual_reflection : public CreatureScript
+{
+public:
+ npc_spiritual_reflection() : CreatureScript("npc_spiritual_reflection") { }
+
+ struct npc_spiritual_reflectionAI : public ScriptedAI
+ {
+ npc_spiritual_reflectionAI(Creature *creature) : ScriptedAI(creature)
+ {
+ Reset();
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* /*victim*/)
+ {
+ events.ScheduleEvent(EVENT_BALEFUL_STRIKE, 3000);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoCast(killer, SPELL_SPIRIT_BURST);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (events.ExecuteEvent())
+ {
+ case EVENT_BALEFUL_STRIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_BALEFUL_STRIKE);
+ events.ScheduleEvent(EVENT_BALEFUL_STRIKE, urand(3000, 8000));
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_spiritual_reflectionAI(creature);
+ }
+};
+
+class at_hor_intro_start : public AreaTriggerScript
+{
+ public:
+ at_hor_intro_start() : AreaTriggerScript("at_hor_intro_start") {}
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/)
+ {
+ InstanceScript* instance = player->GetInstanceScript();
+
+ if (player->isGameMaster())
+ return true;
+
+ if (instance->GetData(DATA_INTRO_EVENT) == NOT_STARTED)
+ {
+ instance->SetData(DATA_INTRO_EVENT, IN_PROGRESS);
+ }
+
+ return true;
+ }
+};
+
+class at_hor_waves_restarter : public AreaTriggerScript
+{
+ public:
+ at_hor_waves_restarter() : AreaTriggerScript("at_hor_waves_restarter") {}
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/)
+ {
+ InstanceScript* instance = player->GetInstanceScript();
+
+ if (player->isGameMaster())
+ return true;
+
+ if (instance->GetData(DATA_WAVE_COUNT))
+ return true;
+
+ if (instance->GetData(DATA_INTRO_EVENT) == DONE && instance->GetBossState(DATA_MARWYN_EVENT) != DONE && instance->GetData(DATA_WAVE_COUNT) == NOT_STARTED)
+ {
+ instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
+ //instance->SetData(DATA_WAVE_COUNT, SPECIAL);
+
+ if (Creature* falric = player->GetCreature(*player, instance->GetData64(DATA_FALRIC_EVENT)))
+ {
+ falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
+ falric->SetVisible(true);
+ }
+ if (Creature* marwyn = player->GetCreature(*player, instance->GetData64(DATA_MARWYN_EVENT)))
+ {
+ marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
+ marwyn->SetVisible(true);
+ }
+ }
+ return true;
+ }
};
void AddSC_halls_of_reflection()
{
- new npc_jaina_or_sylvanas_hor(true, "npc_sylvanas_hor_part1");
- new npc_jaina_or_sylvanas_hor(false, "npc_jaina_hor_part1");
+ new npc_jaina_or_sylvanas_hor();
new npc_ghostly_priest();
new npc_phantom_mage();
new npc_phantom_hallucination();
new npc_shadowy_mercenary();
new npc_spectral_footman();
new npc_tortured_rifleman();
+ new at_hor_intro_start();
+ new at_hor_waves_restarter();
+ new npc_frostworn_general();
+ new npc_spiritual_reflection();
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
index 2cab1cca214..958ecc24aa1 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
@@ -18,49 +18,78 @@
#ifndef DEF_HALLS_OF_REFLECTION_H
#define DEF_HALLS_OF_REFLECTION_H
-enum Data
-{
- DATA_FALRIC_EVENT,
- DATA_MARWYN_EVENT,
- DATA_LICHKING_EVENT,
- DATA_WAVE_COUNT,
- DATA_TEAM_IN_INSTANCE,
-};
+#define HoRScriptName "instance_halls_of_reflection"
+#define MAX_ENCOUNTER 3
-enum Data64
+/* Halls of Reflection encounters:
+0- Falric
+1- Marwyn
+2- The Lich King
+*/
+
+enum Data
{
- DATA_FALRIC,
- DATA_MARWYN,
- DATA_LICHKING,
- DATA_FROSTMOURNE,
+ DATA_FALRIC_EVENT = 0,
+ DATA_MARWYN_EVENT = 1,
+ DATA_LICHKING_EVENT = 2,
+ DATA_INTRO_EVENT = 3,
+ DATA_FROSWORN_EVENT = 4,
+
+ DATA_WAVE_COUNT = 5,
+ DATA_TEAM_IN_INSTANCE = 6,
+ DATA_FROSTMOURNE = 7,
+ DATA_FROSTWORN_DOOR = 8,
};
enum Creatures
{
- 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_UTHER = 37225,
+ NPC_LICH_KING_PART1 = 37226,
+ NPC_LORALEN = 37779,
+ NPC_KORELN = 37582,
+ NPC_FALRIC = 38112,
+ NPC_MARWYN = 38113,
NPC_WAVE_MERCENARY = 38177,
NPC_WAVE_FOOTMAN = 38173,
NPC_WAVE_RIFLEMAN = 38176,
NPC_WAVE_PRIEST = 38175,
NPC_WAVE_MAGE = 38172,
+
+ NPC_FROSTWORN_GENERAL = 36723,
+ NPC_REFLECTION = 37068, // 37107 for tank only?
+
+ NPC_JAINA_PART2 = 36955,
+ NPC_SYLVANAS_PART2 = 37554,
+ NPC_LICH_KING_PART2 = 36954,
+ NPC_BARTLETT = 37182, // High Captain Justin Bartlett
+ NPC_KORM = 37833, // Sky-Reaver Korm Blackscar
+ NPC_ICE_WALL = 37014, // Ice Wall Target
};
enum GameObjects
{
GO_FROSTMOURNE = 202302,
- GO_FROSTMOURNE_ALTAR = 202236,
- GO_FRONT_DOOR = 201976,
- GO_ARTHAS_DOOR = 197341,
+ GO_ENTRANCE_DOOR = 201976,
+ GO_FROSTWORN_DOOR = 197341,
+ GO_ARTHAS_DOOR = 197342,
+ //GO_ESCAPE_DOOR = 197343, // always open ?
+
+ GO_ICE_WALL = 201385,
+ GO_CAVE = 201596,
+
+ GO_STAIRS_SKYBREAKER = 201709,
+ GO_SKYBREAKER = 201598,
+ GO_STAIRS_ORGRIM_HAMMER = 202211,
+ GO_ORGRIM_HAMMER = 201599,
+ GO_PORTAL = 202079,
+
+ GO_CAPTAIN_CHEST_1 = 202212, //3145
+ GO_CAPTAIN_CHEST_2 = 201710, //30357
+ GO_CAPTAIN_CHEST_3 = 202337, //3246
+ GO_CAPTAIN_CHEST_4 = 202336, //3333
};
enum HorWorldStates
@@ -75,6 +104,21 @@ enum Actions
ACTION_ENTER_COMBAT,
};
+enum TrashGeneralSpells
+{
+ // General spells
+ SPELL_WELL_OF_SOULS = 72630, // cast when spawn(become visible)
+ SPELL_SPIRIT_ACTIVATE = 72130, // cast when unit activates
+};
+
+enum InstanceEvents
+{
+ EVENT_SPAWN_WAVES = 1,
+ EVENT_NEXT_WAVE = 2,
+ EVENT_DO_WIPE = 3,
+ EVENT_ADD_WAVE = 4,
+};
+
// Base class for FALRIC and MARWYN
// handled the summonList and the notification events to/from the InstanceScript
struct boss_horAI : ScriptedAI
@@ -92,14 +136,10 @@ struct boss_horAI : ScriptedAI
{
events.Reset();
me->SetVisible(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_PASSIVE);
- }
-
- void DamageTaken(Unit* /*who*/, uint32 &uiDamage)
- {
- if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- uiDamage = 0;
+ if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
+ instance->ProcessEvent(0, EVENT_DO_WIPE);
}
void DoAction(int32 actionID)
@@ -107,11 +147,7 @@ struct boss_horAI : ScriptedAI
switch (actionID)
{
case ACTION_ENTER_COMBAT: // called by InstanceScript when boss shall enter in combat.
- // Just in case. Should have been done by InstanceScript
- me->SetVisible(true);
-
- // Reset flags
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_AGGRESSIVE);
if (Unit* unit = me->SelectNearestTarget())
@@ -125,32 +161,6 @@ struct boss_horAI : ScriptedAI
void JustSummoned(Creature* summoned)
{
summons.Summon(summoned);
-
- if (Unit* target = summoned->SelectNearestTarget())
- {
- if (summoned->AI())
- summoned->AI()->AttackStart(target);
- else
- {
- summoned->GetMotionMaster()->MoveChase(target);
- summoned->Attack(target, true);
- }
- }
-
- if (summoned->AI())
- summoned->AI()->DoZoneInCombat();
- }
-
- void SummonedCreatureDespawn(Creature* summoned)
- {
- summons.Despawn(summoned);
- if (summons.empty())
- {
- if (summoned->isAlive())
- instance->SetData(DATA_WAVE_COUNT, NOT_STARTED);
- else
- instance->SetData(DATA_WAVE_COUNT, SPECIAL);
- }
}
};
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
index dde3f7acc67..82d270fdb95 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
@@ -19,84 +19,47 @@
#include "ScriptedCreature.h"
#include "InstanceScript.h"
#include "halls_of_reflection.h"
-#include "Player.h"
-#define MAX_ENCOUNTER 3
+const Position JainaSpawnPos = {5236.659f, 1929.894f, 707.7781f, 0.8726646f}; // Jaina Spawn Position
+const Position SylvanasSpawnPos = {5236.667f, 1929.906f, 707.7781f, 0.8377581f}; // Sylvanas Spawn Position
+const Position GeneralSpawnPos = {5415.538f, 2117.842f, 707.7781f, 3.944444f}; // Frostsworn General
-/* Halls of Reflection encounters:
-0- Falric
-1- Marwyn
-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
+static Position SpawnPos[] =
{
- EVENT_NONE,
- EVENT_NEXT_WAVE,
- EVENT_START_LICH_KING,
-};
-
-static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] =
-{
- {5277.74f, 2016.88f, 707.778f, 5.96903f},
- {5295.88f, 2040.34f, 707.778f, 5.07891f},
- {5320.37f, 1980.13f, 707.778f, 2.00713f},
- {5280.51f, 1997.84f, 707.778f, 0.296706f},
- {5302.45f, 2042.22f, 707.778f, 4.90438f},
- {5306.57f, 1977.47f, 707.778f, 1.50098f},
-};
-
-static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] =
-{
- {5312.75f, 2037.12f, 707.778f, 4.59022f},
- {5309.58f, 2042.67f, 707.778f, 4.69494f},
- {5275.08f, 2008.72f, 707.778f, 6.21337f},
- {5279.65f, 2004.66f, 707.778f, 0.069813f},
- {5275.48f, 2001.14f, 707.778f, 0.174533f},
- {5316.7f, 2041.55f, 707.778f, 4.50295f},
-};
-
-static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] =
-{
- {5302.25f, 1972.41f, 707.778f, 1.37881f},
- {5311.03f, 1972.23f, 707.778f, 1.64061f},
- {5277.36f, 1993.23f, 707.778f, 0.401426f},
- {5318.7f, 2036.11f, 707.778f, 4.2237f},
- {5335.72f, 1996.86f, 707.778f, 2.74017f},
- {5299.43f, 1979.01f, 707.778f, 1.23918f},
-};
-
-static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] =
-{
- {5306.06f, 2037, 707.778f, 4.81711f},
- {5344.15f, 2007.17f, 707.778f, 3.15905f},
- {5337.83f, 2010.06f, 707.778f, 3.22886f},
- {5343.29f, 1999.38f, 707.778f, 2.9147f},
- {5340.84f, 1992.46f, 707.778f, 2.75762f},
- {5325.07f, 1977.6f, 707.778f, 2.07694f},
- {5336.6f, 2017.28f, 707.778f, 3.47321f},
- {5313.82f, 1978.15f, 707.778f, 1.74533f},
- {5280.63f, 2012.16f, 707.778f, 6.05629f},
- {5322.96f, 2040.29f, 707.778f, 4.34587f},
-};
-
-static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] =
-{
- {5343.47f, 2015.95f, 707.778f, 3.49066f},
- {5337.86f, 2003.4f, 707.778f, 2.98451f},
- {5319.16f, 1974, 707.778f, 1.91986f},
- {5299.25f, 2036, 707.778f, 5.02655f},
- {5295.64f, 1973.76f, 707.778f, 1.18682f},
- {5282.9f, 2019.6f, 707.778f, 5.88176f},
+ {5309.577f, 2042.668f, 707.7781f, 4.694936f},
+ {5295.885f, 2040.342f, 707.7781f, 5.078908f},
+ {5340.836f, 1992.458f, 707.7781f, 2.757620f},
+ {5325.072f, 1977.597f, 707.7781f, 2.076942f},
+ {5277.365f, 1993.229f, 707.7781f, 0.401426f},
+ {5275.479f, 2001.135f, 707.7781f, 0.174533f},
+ {5302.448f, 2042.222f, 707.7781f, 4.904375f},
+ {5343.293f, 1999.384f, 707.7781f, 2.914700f},
+ {5295.635f, 1973.757f, 707.7781f, 1.186824f},
+ {5311.031f, 1972.229f, 707.7781f, 1.640610f},
+ {5275.076f, 2008.724f, 707.7781f, 6.213372f},
+ {5316.701f, 2041.550f, 707.7781f, 4.502949f},
+ {5344.150f, 2007.168f, 707.7781f, 3.159046f},
+ {5319.158f, 1973.998f, 707.7781f, 1.919862f},
+ {5302.247f, 1972.415f, 707.7781f, 1.378810f},
+ {5277.739f, 2016.882f, 707.7781f, 5.969026f},
+ {5322.964f, 2040.288f, 707.7781f, 4.345870f},
+ {5343.467f, 2015.951f, 707.7781f, 3.490659f},
+ {5313.820f, 1978.146f, 707.7781f, 1.745329f},
+ {5279.649f, 2004.656f, 707.7781f, 0.069814f},
+ {5306.057f, 2037.002f, 707.7781f, 4.817109f},
+ {5337.865f, 2003.403f, 707.7781f, 2.984513f},
+ {5299.434f, 1979.009f, 707.7781f, 1.239184f},
+ {5312.752f, 2037.122f, 707.7781f, 4.590216f},
+ {5335.724f, 1996.859f, 707.7781f, 2.740167f},
+ {5280.632f, 2012.156f, 707.7781f, 6.056293f},
+ {5320.369f, 1980.125f, 707.7781f, 2.007129f},
+ {5306.572f, 1977.474f, 707.7781f, 1.500983f},
+ {5336.599f, 2017.278f, 707.7781f, 3.473205f},
+ {5282.897f, 2019.597f, 707.7781f, 5.881760f},
+ {5318.704f, 2036.108f, 707.7781f, 4.223697f},
+ {5280.513f, 1997.842f, 707.7781f, 0.296706f},
+ {5337.833f, 2010.057f, 707.7781f, 3.228859f},
+ {5299.250f, 2035.998f, 707.7781f, 5.026548f},
};
class instance_halls_of_reflection : public InstanceMapScript
@@ -104,53 +67,37 @@ class instance_halls_of_reflection : public InstanceMapScript
public:
instance_halls_of_reflection() : InstanceMapScript("instance_halls_of_reflection", 668) { }
- InstanceScript* GetInstanceScript(InstanceMap* map) const
- {
- return new instance_halls_of_reflection_InstanceMapScript(map);
- }
-
struct instance_halls_of_reflection_InstanceMapScript : public InstanceScript
{
- instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map) {};
-
- uint64 uiFalric;
- uint64 uiMarwyn;
- uint64 uiLichKingEvent;
- uint64 uiJainaPart1;
- uint64 uiSylvanasPart1;
-
- uint64 uiFrostmourne;
- uint64 uiFrostmourneAltar;
- uint64 uiArthasDoor;
- uint64 uiFrontDoor;
-
- uint32 uiEncounter[MAX_ENCOUNTER];
- uint32 uiTeamInInstance;
- uint32 uiWaveCount;
- bool bIntroDone;
-
- EventMap events;
+ instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map) {}
void Initialize()
{
+ SetBossNumber(MAX_ENCOUNTER);
events.Reset();
+ _falricGUID = 0;
+ _marwynGUID = 0;
+ _jainaOrSylvanasPart1GUID = 0;
+ _frostwornGeneralGUID = 0;
+ _frostmourneGUID = 0;
+ _entranceDoorGUID = 0;
+ _frostwornDoorGUID = 0;
+ _arthasDoorGUID = 0;
+ _teamInInstance = 0;
+ _waveCount = 0;
+ _introEvent = NOT_STARTED;
+ _frostwornGeneral = NOT_STARTED;
+
+ for (uint8 i = 0; i < 8; i++)
+ {
+ waveGuidList[i].clear();
+ }
+ }
- uiFalric = 0;
- uiMarwyn = 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)
- uiEncounter[i] = NOT_STARTED;
+ void OnPlayerEnter(Player* player)
+ {
+ if (!_teamInInstance)
+ _teamInInstance = player->GetTeam();
}
void OnCreatureCreate(Creature* creature)
@@ -158,53 +105,57 @@ public:
Map::PlayerList const &players = instance->GetPlayers();
if (!players.isEmpty())
if (Player* player = players.begin()->getSource())
- uiTeamInInstance = player->GetTeam();
+ _teamInInstance = player->GetTeam();
switch (creature->GetEntry())
{
+ case NPC_JAINA_PART1:
+ case NPC_SYLVANAS_PART1:
+ _jainaOrSylvanasPart1GUID = creature->GetGUID();
+ break;
case NPC_FALRIC:
- uiFalric = creature->GetGUID();
+ _falricGUID = creature->GetGUID();
break;
case NPC_MARWYN:
- uiMarwyn = creature->GetGUID();
+ _marwynGUID = creature->GetGUID();
break;
- case NPC_LICH_KING_EVENT:
- uiLichKingEvent = creature->GetGUID();
- break;
- case NPC_JAINA_PART1:
- uiJainaPart1 = creature->GetGUID();
- break;
- case NPC_SYLVANAS_PART1:
- uiSylvanasPart1 = creature->GetGUID();
+ case NPC_FROSTWORN_GENERAL:
+ _frostwornGeneralGUID = creature->GetGUID();
+ if (GetBossState(DATA_MARWYN_EVENT) == DONE)
+ if (Creature* general = instance->GetCreature(_frostwornGeneralGUID))
+ general->SetPhaseMask(1, true);
break;
}
}
void OnGameObjectCreate(GameObject* go)
{
- /// @todo init state depending on encounters
switch (go->GetEntry())
{
case GO_FROSTMOURNE:
- uiFrostmourne = go->GetGUID();
+ _frostmourneGUID = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
HandleGameObject(0, false, go);
+ if (GetData(DATA_INTRO_EVENT) == DONE)
+ go->SetPhaseMask(2, true);
break;
- case GO_FROSTMOURNE_ALTAR:
- uiFrostmourneAltar = go->GetGUID();
+ case GO_ENTRANCE_DOOR:
+ _entranceDoorGUID = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
HandleGameObject(0, true, go);
break;
- case GO_FRONT_DOOR:
- uiFrontDoor = go->GetGUID();
+ case GO_FROSTWORN_DOOR:
+ _frostwornDoorGUID = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- HandleGameObject(0, true, go);
+ if (GetBossState(DATA_MARWYN_EVENT) == DONE)
+ HandleGameObject(0, true, go);
+ else
+ HandleGameObject(0, false, go);
break;
case GO_ARTHAS_DOOR:
- uiArthasDoor = go->GetGUID();
+ _arthasDoorGUID = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
-
- if (uiEncounter[1] == DONE)
+ if (GetBossState(DATA_FROSWORN_EVENT) == DONE)
HandleGameObject(0, true, go);
else
HandleGameObject(0, false, go);
@@ -212,61 +163,108 @@ public:
}
}
- void SetData(uint32 type, uint32 data)
+ bool SetBossState(uint32 type, EncounterState state)
{
- if (type == DATA_WAVE_COUNT && data == SPECIAL)
- {
- bIntroDone = true;
- events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
- return;
- }
-
- if (uiWaveCount && data == NOT_STARTED)
- DoWipe();
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
switch (type)
{
case DATA_FALRIC_EVENT:
- uiEncounter[0] = data;
- if (data == DONE)
+ if (state == DONE)
events.ScheduleEvent(EVENT_NEXT_WAVE, 60000);
break;
case DATA_MARWYN_EVENT:
- uiEncounter[1] = data;
- if (data == DONE)
- HandleGameObject(uiArthasDoor, true);
+ if (state == DONE)
+ {
+ HandleGameObject(_entranceDoorGUID, true);
+ HandleGameObject(_frostwornDoorGUID, true);
+ if (Creature* general = instance->GetCreature(_frostwornGeneralGUID))
+ general->SetPhaseMask(1, true);
+ }
break;
case DATA_LICHKING_EVENT:
- uiEncounter[2] = data;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ void SetData(uint32 type, uint32 data)
+ {
+ if (_waveCount && data == NOT_STARTED)
+ ProcessEvent(0, EVENT_DO_WIPE);
+
+ switch (type)
+ {
+ case DATA_INTRO_EVENT:
+ if (data == IN_PROGRESS)
+ {
+ if (!_introEvent)
+ {
+ if (_teamInInstance == ALLIANCE)
+ instance->SummonCreature(NPC_JAINA_PART1, JainaSpawnPos);
+ else
+ instance->SummonCreature(NPC_SYLVANAS_PART1, SylvanasSpawnPos);
+ }
+ }
+ _introEvent = data;
+ break;
+ case DATA_WAVE_COUNT:
+ if (data == SPECIAL)
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
+ break;
+ case DATA_FROSWORN_EVENT:
+ if (data == DONE)
+ {
+ HandleGameObject(_arthasDoorGUID, true);
+ // spawn Jaina part 2
+ // spawn LK part 2
+ }
+ _frostwornGeneral = data;
break;
}
- if (data == DONE)
- SaveToDB();
+ SaveToDB();
}
uint32 GetData(uint32 type) const
{
switch (type)
{
- 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;
+ case DATA_WAVE_COUNT:
+ return _waveCount;
+ case DATA_TEAM_IN_INSTANCE:
+ return _teamInInstance;
+ case DATA_INTRO_EVENT:
+ return _introEvent;
+ case DATA_FROSWORN_EVENT:
+ return _frostwornGeneral;
+ default:
+ break;
}
return 0;
}
- uint64 GetData64(uint32 identifier) const
+ uint64 GetData64(uint32 type) const
{
- switch (identifier)
+ switch (type)
{
- case DATA_FALRIC: return uiFalric;
- case DATA_MARWYN: return uiMarwyn;
- case DATA_LICHKING: return uiLichKingEvent;
- case DATA_FROSTMOURNE: return uiFrostmourne;
+ case DATA_FALRIC_EVENT:
+ return _falricGUID;
+ case DATA_MARWYN_EVENT:
+ return _marwynGUID;
+ case DATA_FROSWORN_EVENT:
+ return _frostwornGeneralGUID;
+ case DATA_FROSTWORN_DOOR:
+ return _frostwornDoorGUID;
+ case DATA_FROSTMOURNE:
+ return _frostmourneGUID;
+ default:
+ break;
}
return 0;
@@ -277,7 +275,7 @@ public:
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
- saveStream << "H R 1 " << uiEncounter[0] << ' ' << uiEncounter[1] << ' ' << uiEncounter[2];
+ saveStream << "H R " << GetBossSaveData() << _introEvent << ' ' << _frostwornGeneral;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
@@ -294,115 +292,82 @@ public:
OUT_LOAD_INST_DATA(in);
char dataHead1, dataHead2;
- uint16 version;
- uint16 data0, data1, data2;
std::istringstream loadStream(in);
- loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2;
+ loadStream >> dataHead1 >> dataHead2;
if (dataHead1 == 'H' && dataHead2 == 'R')
{
- uiEncounter[0] = data0;
- uiEncounter[1] = data1;
- uiEncounter[2] = data2;
-
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (uiEncounter[i] == IN_PROGRESS)
- uiEncounter[i] = NOT_STARTED;
-
- } else OUT_LOAD_INST_DATA_FAIL;
-
- if (uiEncounter[0] == DONE || uiEncounter[1] == DONE)
- bIntroDone = true;
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+
+ SetBossState(i, EncounterState(tmpState));
+ }
+
+ uint32 temp = 0;
+ loadStream >> temp;
+ if (temp == DONE)
+ SetData(DATA_INTRO_EVENT, DONE);
+ else
+ SetData(DATA_INTRO_EVENT, NOT_STARTED);
+
+ loadStream >> temp;
+ if (temp == DONE)
+ SetData(DATA_FROSWORN_EVENT, DONE);
+ else
+ SetData(DATA_FROSWORN_EVENT, NOT_STARTED);
+ }
+ else
+ OUT_LOAD_INST_DATA_FAIL;
OUT_LOAD_INST_DATA_COMPLETE;
}
- void AddWave()
+ // wave scheduling,checked when wave npcs die
+ void OnUnitDeath(Unit* unit)
{
- DoUpdateWorldState(WORLD_STATE_HOR, 1);
- DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount);
+ Creature* creature = unit->ToCreature();
+ if (!creature)
+ return;
- switch (uiWaveCount)
+ switch (creature->GetEntry())
{
- 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);
+ case NPC_WAVE_MERCENARY:
+ case NPC_WAVE_FOOTMAN:
+ case NPC_WAVE_RIFLEMAN:
+ case NPC_WAVE_PRIEST:
+ case NPC_WAVE_MAGE:
+ uint32 deadNpcs = 0;
+ if (_waveCount < 5)
+ {
+ for (std::set<uint64>::const_iterator itr = waveGuidList[_waveCount-1].begin(); itr != waveGuidList[_waveCount-1].end(); ++itr)
+ if ((instance->GetCreature(*itr)->isDying()) || (instance->GetCreature(*itr)->isDead()))
+ deadNpcs++;
+
+ // because the current npc returns isAlive when OnUnitDeath happens
+ // we check if the number of dead npcs is equal to the list-1
+ if (deadNpcs == waveGuidList[_waveCount-1].size() - 1)
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
+ }
+ else
+ {
+ for (std::set<uint64>::const_iterator itr = waveGuidList[_waveCount-2].begin(); itr != waveGuidList[_waveCount-2].end(); ++itr)
+ if ((instance->GetCreature(*itr)->isDying()) || (instance->GetCreature(*itr)->isDead()))
+ deadNpcs++;
+
+ // because the current npc returns isAlive when OnUnitDeath happens
+ // we check if the number of dead npcs is equal to the list-1
+ if (deadNpcs == waveGuidList[_waveCount-2].size() - 1)
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
+ }
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->SetVisible(false);
- if (Creature* pMarwyn = instance->GetCreature(uiMarwyn))
- pMarwyn->SetVisible(false);
- }
-
- // spawn a wave on behalf of the summoner.
- void SpawnWave(Creature* summoner)
- {
- uint32 index;
-
- summoner->SetVisible(true);
-
- /// @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);
- summoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- index = urand(0, ENCOUNTER_WAVE_FOOTMAN-1);
- summoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- index = urand(0, ENCOUNTER_WAVE_RIFLEMAN-1);
- summoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- index = urand(0, ENCOUNTER_WAVE_PRIEST-1);
- summoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- index = urand(0, ENCOUNTER_WAVE_MAGE-1);
- summoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
- }
-
void Update(uint32 diff)
{
if (!instance->HavePlayers())
@@ -413,16 +378,158 @@ public:
switch (events.ExecuteEvent())
{
case EVENT_NEXT_WAVE:
- uiWaveCount++;
- AddWave();
+ _waveCount++;
+ ProcessEvent(0, EVENT_ADD_WAVE);
+ break;
+ }
+ }
+
+ void ProcessEvent(WorldObject* /*go*/, uint32 eventId)
+ {
+ switch (eventId)
+ {
+ // spawning all wave npcs at once
+ case EVENT_SPAWN_WAVES:
+ DoUpdateWorldState(WORLD_STATE_HOR, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ {
+ std::vector<uint32> possibilityList,tempList;
+ uint32 posIndex = 0;
+
+ possibilityList.push_back(NPC_WAVE_MERCENARY);
+ possibilityList.push_back(NPC_WAVE_FOOTMAN);
+ possibilityList.push_back(NPC_WAVE_RIFLEMAN);
+ possibilityList.push_back(NPC_WAVE_PRIEST);
+ possibilityList.push_back(NPC_WAVE_MAGE);
+
+ // iterate each wave
+ for (uint8 i = 0; i < 8; i++)
+ {
+ tempList = possibilityList;
+
+ uint64 guid = i <= 3 ? _falricGUID : _marwynGUID;
+
+ if (i == 0)
+ {
+ tempList.erase(tempList.begin() + urand(0, tempList.size() - 1));
+ tempList.erase(tempList.begin() + urand(0, tempList.size() - 1));
+ }
+ else if (i == 1 || i == 2 || i == 4 || i == 5)
+ tempList.erase(tempList.begin() + urand(0, tempList.size() - 1));
+
+ for (uint8 itr = 0; itr < tempList.size(); ++itr)
+ {
+ if (Creature* falric = instance->GetCreature(guid))
+ if (Creature* temp = falric->SummonCreature(tempList[itr], SpawnPos[posIndex], TEMPSUMMON_DEAD_DESPAWN))
+ waveGuidList[i].insert(temp->GetGUID());
+ posIndex++;
+ }
+
+ tempList.clear();
+ }
+ }
+ SetData(DATA_WAVE_COUNT, SPECIAL);
+ break;
+ case EVENT_ADD_WAVE:
+ DoUpdateWorldState(WORLD_STATE_HOR, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ HandleGameObject(_entranceDoorGUID, false);
+
+ switch (_waveCount)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (std::set<uint64>::const_iterator itr = waveGuidList[_waveCount-1].begin(); itr != waveGuidList[_waveCount-1].end(); ++itr)
+ {
+ if (Creature* temp = instance->GetCreature(*itr))
+ {
+ temp->CastSpell(temp, SPELL_SPIRIT_ACTIVATE, true);
+ temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC|UNIT_FLAG_NOT_SELECTABLE);
+ temp->AI()->DoZoneInCombat();
+ }
+ }
+ break;
+ case 5:
+ if (GetBossState(DATA_FALRIC_EVENT) == DONE)
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 10000);
+ else
+ if (Creature* falric = instance->GetCreature(_falricGUID))
+ if (falric->AI())
+ falric->AI()->DoAction(ACTION_ENTER_COMBAT);
+ break;
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ for (std::set<uint64>::const_iterator itr = waveGuidList[_waveCount-2].begin(); itr != waveGuidList[_waveCount-2].end(); ++itr)
+ {
+ if (Creature* temp = instance->GetCreature(*itr))
+ {
+ temp->CastSpell(temp, SPELL_SPIRIT_ACTIVATE, true);
+ temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC|UNIT_FLAG_NOT_SELECTABLE);
+ temp->AI()->DoZoneInCombat();
+ }
+ }
+ break;
+ case 10:
+ if (GetBossState(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit!
+ if (Creature* marwyn = instance->GetCreature(_marwynGUID))
+ if (marwyn->AI())
+ marwyn->AI()->DoAction(ACTION_ENTER_COMBAT);
+ break;
+ }
break;
- case EVENT_START_LICH_KING:
- /// @todo
+ case EVENT_DO_WIPE:
+ //SetData(DATA_WAVE_COUNT, NOT_STARTED);
+ _waveCount = 0;
+ events.Reset();
+ DoUpdateWorldState(WORLD_STATE_HOR, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ HandleGameObject(_entranceDoorGUID, true);
+
+ if (Creature* falric = instance->GetCreature(_falricGUID))
+ falric->SetVisible(false);
+ if (Creature* marwyn = instance->GetCreature(_marwynGUID))
+ marwyn->SetVisible(false);
+
+ //despawn wave npcs
+ for (uint8 i = 0; i < 8; i++)
+ {
+ for (std::set<uint64>::const_iterator itr = waveGuidList[i].begin(); itr != waveGuidList[i].end(); ++itr)
+ instance->GetCreature(*itr)->DespawnOrUnsummon();
+ }
break;
}
}
+
+ private:
+ uint64 _falricGUID;
+ uint64 _marwynGUID;
+ uint64 _jainaOrSylvanasPart1GUID;
+ uint64 _frostwornGeneralGUID;
+
+ uint64 _frostmourneGUID;
+ uint64 _entranceDoorGUID;
+ uint64 _frostwornDoorGUID;
+ uint64 _arthasDoorGUID;
+ uint64 _escapeDoorGUID;
+
+ uint32 _teamInInstance;
+ uint32 _waveCount;
+ uint32 _introEvent;
+ uint32 _frostwornGeneral;
+
+ EventMap events;
+
+ std::set<uint64> waveGuidList[8];
};
+ InstanceScript* GetInstanceScript(InstanceMap* map) const
+ {
+ return new instance_halls_of_reflection_InstanceMapScript(map);
+ }
};
void AddSC_instance_halls_of_reflection()