aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/CreatureAIImpl.h35
-rw-r--r--src/game/ScriptLoader.cpp8
-rw-r--r--src/scripts/CMakeLists.txt2
-rw-r--r--src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp180
-rw-r--r--src/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp349
-rw-r--r--src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp899
-rw-r--r--src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h25
-rw-r--r--src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp54
8 files changed, 1458 insertions, 94 deletions
diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h
index 45bc4e0dab0..a6cb52dedc5 100644
--- a/src/game/CreatureAIImpl.h
+++ b/src/game/CreatureAIImpl.h
@@ -405,18 +405,27 @@ class EventMap : private std::map<uint32, uint32>
return 0;
}
- void DelayEvents(uint32 time, uint32 gcd)
+ // Delay all events
+ void DelayEvents(uint32 delay)
{
- time += m_time;
+ if (delay < m_time)
+ m_time -= delay;
+ else
+ m_time = 0;
+ }
+
+ // Delay all events having the specified Global Cooldown.
+ void DelayEvents(uint32 delay, uint32 gcd)
+ {
+ uint32 nextTime = m_time + delay;
gcd = (1 << (gcd + 16));
- for (iterator itr = begin(); itr != end();)
+ for (iterator itr = begin(); itr != end() && itr->first < nextTime;)
{
- if (itr->first >= time)
- break;
if (itr->second & gcd)
{
- ScheduleEvent(time, itr->second);
- erase(itr++);
+ ScheduleEvent(itr->second, itr->first-m_time+delay);
+ erase(itr);
+ itr = begin();
}
else
++itr;
@@ -428,7 +437,10 @@ class EventMap : private std::map<uint32, uint32>
for (iterator itr = begin(); itr != end();)
{
if (eventId == (itr->second & 0x0000FFFF))
- erase(itr++);
+ {
+ erase(itr);
+ itr = begin();
+ }
else
++itr;
}
@@ -436,10 +448,15 @@ class EventMap : private std::map<uint32, uint32>
void CancelEventsByGCD(uint32 gcd)
{
+ gcd = (1 << (gcd + 16));
+
for (iterator itr = begin(); itr != end();)
{
if (itr->second & gcd)
- erase(itr++);
+ {
+ erase(itr);
+ itr = begin();
+ }
else
++itr;
}
diff --git a/src/game/ScriptLoader.cpp b/src/game/ScriptLoader.cpp
index 5cf488fe156..971ff4cbe35 100644
--- a/src/game/ScriptLoader.cpp
+++ b/src/game/ScriptLoader.cpp
@@ -407,6 +407,10 @@ void AddSC_boss_xevozz();
void AddSC_boss_zuramat();
void AddSC_instance_violet_hold();
void AddSC_violet_hold();
+void AddSC_instance_forge_of_souls(); //Forge of Souls
+void AddSC_forge_of_souls();
+void AddSC_boss_bronjahm();
+void AddSC_boss_devourer_of_souls();
void AddSC_instance_pit_of_saron(); //Pit of Saron
void AddSC_pit_of_saron();
void AddSC_boss_garfrost();
@@ -899,6 +903,10 @@ void AddScripts()
AddSC_boss_zuramat();
AddSC_instance_violet_hold();
AddSC_violet_hold();
+ AddSC_instance_forge_of_souls(); //Forge of Souls
+ AddSC_forge_of_souls();
+ AddSC_boss_bronjahm();
+ AddSC_boss_devourer_of_souls();
AddSC_instance_pit_of_saron(); //Pit of Saron
AddSC_pit_of_saron();
AddSC_boss_garfrost();
diff --git a/src/scripts/CMakeLists.txt b/src/scripts/CMakeLists.txt
index 462c31266be..54627091ec2 100644
--- a/src/scripts/CMakeLists.txt
+++ b/src/scripts/CMakeLists.txt
@@ -341,7 +341,9 @@ SET(scripts_STAT_SRCS
northrend/draktharon_keep/drak_tharon_keep.h
northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp
northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp
+ 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/instance_halls_of_reflection.cpp
northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h
northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp
diff --git a/src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp
index 601125da336..08548399665 100644
--- a/src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp
+++ b/src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp
@@ -17,28 +17,53 @@
#include "ScriptedPch.h"
#include "forge_of_souls.h"
+/*
+ * TODO:
+ * - Fix Soul Storm spell and remove work around.
+ */
+
+enum Yells
+{
+ SAY_AGGRO = -1632001,
+ SAY_SLAY_1 = -1632002,
+ SAY_SLAY_2 = -1632003,
+ SAY_DEATH = -1632004,
+ SAY_SOUL_STORM = -1632005,
+ SAY_CORRUPT_SOUL = -1632006,
+};
+
enum Spells
{
SPELL_MAGIC_S_BANE = 68793,
- SPELL_MAGIC_S_BANE_H = 69050,
+ H_SPELL_MAGIC_S_BANE = 69050,
SPELL_CORRUPT_SOUL = 68839,
SPELL_CONSUME_SOUL = 68858,
- SPELL_CONSUME_SOUL_H = 69047,
+ H_SPELL_CONSUME_SOUL = 69047,
SPELL_TELEPORT = 68988,
SPELL_FEAR = 68950,
SPELL_SOULSTORM = 68872,
- SPELL_SOULSTORM_H = 69049,
- SPELL_SHADOW_BOLT = 70043
+ SPELL_SOULSTORM_AURA = 68921,
+ H_SPELL_SOULSTORM_AURA = 69049,
+ SPELL_SHADOW_BOLT = 70043,
};
+
+enum Events
+{
+ EVENT_NONE,
+ EVENT_SHADOW_BOLT,
+ EVENT_MAGIC_BANE,
+ EVENT_CORRUPT_SOUL,
+ EVENT_SOUL_STORM,
+ EVENT_SOUL_STORM_AURA,
+ EVENT_FEAR,
+};
+
enum CombatPhases
{
PHASE_1,
PHASE_2
};
-/*enum Adds
-{
- CREATURE_CORRUPTED_SOUL_FRAGMENT = 36535
-};*/
+
struct boss_bronjahmAI : public ScriptedAI
{
boss_bronjahmAI(Creature *c) : ScriptedAI(c)
@@ -46,23 +71,20 @@ struct boss_bronjahmAI : public ScriptedAI
pInstance = m_creature->GetInstanceData();
}
- uint32 uiFearTimer;
- uint32 uiShadowBoltTimer;
- uint32 uiMagicsBaneTimer;
- uint32 uiCorruptSoulTimer;
-
- CombatPhases Phase;
-
ScriptedInstance* pInstance;
+ EventMap events;
+
+ CombatPhases phase;
void Reset()
{
- Phase = PHASE_1;
+ phase = PHASE_1;
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
- uiFearTimer = urand(8000,12000);
- uiShadowBoltTimer = 2000;
- uiMagicsBaneTimer = urand(8000,15000);
- uiCorruptSoulTimer = urand(15000,25000);
+ events.Reset();
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
+ events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000));
+ events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(15000,25000));
if (pInstance)
pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED);
@@ -70,7 +92,7 @@ struct boss_bronjahmAI : public ScriptedAI
void EnterCombat(Unit* who)
{
- //DoScriptText(SAY_AGGRO, m_creature);
+ DoScriptText(SAY_AGGRO, m_creature);
if (pInstance)
pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS);
@@ -78,56 +100,92 @@ struct boss_bronjahmAI : public ScriptedAI
void JustDied(Unit* killer)
{
- //DoScriptText(SAY_DEATH, m_creature);
+ DoScriptText(SAY_DEATH, m_creature);
if (pInstance)
pInstance->SetData(DATA_BRONJAHM_EVENT, DONE);
}
+ void KilledUnit(Unit *pWho)
+ {
+ DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), m_creature);
+ }
+
+ // Cast aura spell on all players farther than 10y
+ void ApplySoulStorm()
+ {
+ const std::list<HostileReference*>& threatlist = m_creature->getThreatManager().getThreatList();
+ if (threatlist.empty())
+ return;
+
+ for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
+ {
+ Unit* pUnit = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
+ if (pUnit && pUnit->isAlive() && pUnit->GetDistance(m_creature) > 10.0f)
+ m_creature->CastSpell(pUnit, DUNGEON_MODE(SPELL_SOULSTORM_AURA,H_SPELL_SOULSTORM_AURA), true);
+ }
+ }
+
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
- switch (Phase)
+ if (phase == PHASE_1 && HealthBelowPct(30))
{
- case PHASE_1:
- if (uiCorruptSoulTimer <= diff)
- {
+ phase = PHASE_2;
+ DoCast(m_creature,SPELL_TELEPORT);
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ events.CancelEvent(EVENT_CORRUPT_SOUL);
+ events.ScheduleEvent(EVENT_SOUL_STORM, 1000);
+ events.ScheduleEvent(EVENT_FEAR, urand(8000,12000));
+ return;
+ }
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_CORRUPT_SOUL:
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1))
+ {
+ DoScriptText(SAY_CORRUPT_SOUL, m_creature);
DoCast(pTarget,SPELL_CORRUPT_SOUL);
- uiCorruptSoulTimer = urand(15000,25000);
- } else uiCorruptSoulTimer -= diff;
- break;
- case PHASE_2:
- if (!me->HasAura(SPELL_SOULSTORM) || !me->HasAura(SPELL_SOULSTORM_H))
- DoCast(m_creature, DUNGEON_MODE(SPELL_SOULSTORM,SPELL_SOULSTORM_H));
- if (uiFearTimer <= diff)
- {
+ }
+ events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(15000,25000));
+ break;
+ case EVENT_SOUL_STORM:
+ DoScriptText(SAY_SOUL_STORM, m_creature);
+ // DoCast(m_creature, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards.
+ events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000);
+ break;
+ case EVENT_SOUL_STORM_AURA:
+ ApplySoulStorm();
+ events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000);
+ break;
+ case EVENT_FEAR:
if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1))
- DoCast(m_creature->getVictim(),SPELL_FEAR);
- uiFearTimer = urand(8000,12000);
- } else uiFearTimer -= diff;
- break;
+ DoCast(pTarget,SPELL_FEAR);
+ events.ScheduleEvent(EVENT_FEAR, urand(8000,12000));
+ break;
+ case EVENT_SHADOW_BOLT:
+ DoCastVictim(SPELL_SHADOW_BOLT);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
+ break;
+ case EVENT_MAGIC_BANE:
+ DoCastVictim(DUNGEON_MODE(SPELL_MAGIC_S_BANE,H_SPELL_MAGIC_S_BANE));
+ events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000));
+ break;
+ }
}
- if (HealthBelowPct(30))
- DoCast(m_creature,SPELL_TELEPORT);
-
- if (uiShadowBoltTimer <= diff)
- {
- if (m_creature->IsWithinMeleeRange(m_creature->getVictim()))
- DoCastVictim(SPELL_SHADOW_BOLT);
- uiShadowBoltTimer = 2000;
- } else uiShadowBoltTimer -= diff;
-
- if (uiMagicsBaneTimer <= diff)
- {
- DoCastVictim(DUNGEON_MODE(SPELL_MAGIC_S_BANE,SPELL_MAGIC_S_BANE_H));
- uiMagicsBaneTimer = urand(8000,15000);
- } else uiMagicsBaneTimer -= diff;
-
DoMeleeAttackIfReady();
}
};
@@ -159,7 +217,7 @@ struct mob_corrupted_soul_fragmentAI : public ScriptedAI
{
if (pInstance)
if (Creature* pBronjham = Unit::GetCreature(*m_creature,pInstance->GetData64(DATA_BRONJAHM)))
- DoCast(pBronjham,DUNGEON_MODE(SPELL_CONSUME_SOUL,SPELL_CONSUME_SOUL_H));
+ DoCast(pBronjham,DUNGEON_MODE(SPELL_CONSUME_SOUL,H_SPELL_CONSUME_SOUL));
}
void UpdateAI(const uint32 diff) {}
@@ -175,12 +233,12 @@ void AddSC_boss_bronjahm()
Script *newscript;
newscript = new Script;
- newscript->Name = "mob_corruptel_soul_fragment";
- newscript->GetAI = &GetAI_mob_corrupted_soul_fragment;
- newscript->RegisterSelf();
-
- newscript = new Script;
newscript->Name = "boss_bronjahm";
newscript->GetAI = &GetAI_boss_bronjahm;
newscript->RegisterSelf();
-} \ No newline at end of file
+
+ newscript = new Script;
+ newscript->Name = "mob_corrupted_soul_fragment";
+ newscript->GetAI = &GetAI_mob_corrupted_soul_fragment;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp b/src/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp
new file mode 100644
index 00000000000..a1d2621b2ca
--- /dev/null
+++ b/src/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp
@@ -0,0 +1,349 @@
+/* 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 "forge_of_souls.h"
+
+/*
+ * TODO:
+ * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing).
+ * - Fix outro npc movement
+ */
+
+#define PI 3.1415f
+
+enum Yells
+{
+ SAY_FACE_ANGER_AGGRO = -1632010,
+ SAY_FACE_DESIRE_AGGRO = -1632011,
+ SAY_FACE_ANGER_SLAY_1 = -1632012,
+ SAY_FACE_SORROW_SLAY_1 = -1632013,
+ SAY_FACE_DESIRE_SLAY_1 = -1632014,
+ SAY_FACE_ANGER_SLAY_2 = -1632015,
+ SAY_FACE_SORROW_SLAY_2 = -1632016,
+ SAY_FACE_DESIRE_SLAY_2 = -1632017,
+ SAY_FACE_SORROW_DEATH = -1632019,
+ SAY_FACE_DESIRE_DEATH = -1632020,
+ EMOTE_MIRRORED_SOUL = -1632021,
+ EMOTE_UNLEASH_SOUL = -1632022,
+ SAY_FACE_ANGER_UNLEASH_SOUL = -1632023,
+ SAY_FACE_SORROW_UNLEASH_SOUL = -1632024,
+ SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025,
+ EMOTE_WAILING_SOUL = -1632026,
+ SAY_FACE_ANGER_WAILING_SOUL = -1632027,
+ SAY_FACE_DESIRE_WAILING_SOUL = -1632028,
+
+ SAY_JAINA_OUTRO = -1632029,
+ SAY_SYLVANAS_OUTRO = -1632030,
+};
+
+enum Spells
+{
+ SPELL_PHANTOM_BLAST = 68982,
+ H_SPELL_PHANTOM_BLAST = 70322,
+ SPELL_MIRRORED_SOUL = 69051,
+ SPELL_WELL_OF_SOULS = 68820,
+ SPELL_WELL_OF_SOULS_VIS = 68854,
+ SPELL_UNLEASHED_SOULS = 68939,
+ SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase
+ SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual
+ SPELL_WAILING_SOULS = 68873, // the actual spell
+ H_SPELL_WAILING_SOULS = 70324,
+// 68871,68873,68875,68876,68899,68912,70324,
+// 68899 trigger 68871
+};
+
+enum Events
+{
+ EVENT_NONE,
+ EVENT_PHANTOM_BLAST,
+ EVENT_MIRRORED_SOUL,
+ EVENT_WELL_OF_SOULS,
+ EVENT_UNLEASHED_SOULS,
+ EVENT_WAILING_SOULS,
+ EVENT_WAILING_SOULS_TICK,
+ EVENT_FACE_ANGER,
+};
+
+enum eEnum
+{
+ ACHIEV_THREE_FACED = 4523,
+ DISPLAY_ANGER = 30148,
+ DISPLAY_SORROW = 30149,
+ DISPLAY_DESIRE = 30150,
+};
+
+struct
+{
+ uint32 entry[2];
+ Position movePosition;
+} outroPositions[] =
+{
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } },
+ { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } },
+ { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } },
+
+ { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } },
+ { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } },
+ { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } },
+
+ { 0, 0, { 0, 0, 0, 0 } }
+};
+
+struct boss_devourer_of_soulsAI : public ScriptedAI
+{
+ boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = c->GetInstanceData();
+ }
+
+ bool bThreeFaceAchievement;
+
+ ScriptedInstance* pInstance;
+ EventMap events;
+
+ // wailing soul event
+ float beamAngle;
+ float beamAngleDiff;
+ int8 wailingSoulTick;
+
+ uint64 uiMirroredSoulTarget;
+
+ void Reset()
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ m_creature->SetDisplayId(DISPLAY_ANGER);
+ m_creature->SetReactState(REACT_AGGRESSIVE);
+
+ events.Reset();
+
+ bThreeFaceAchievement = true;
+ uiMirroredSoulTarget = 0;
+
+ if (pInstance)
+ pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ if (pInstance)
+ pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS);
+
+ DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), m_creature);
+
+ events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000);
+ events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000);
+ events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000);
+ events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000);
+ events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000));
+ }
+
+ void DamageTaken(Unit *pDoneBy, uint32 &uiDamage)
+ {
+ if (uiMirroredSoulTarget && m_creature->HasAura(SPELL_MIRRORED_SOUL))
+ {
+ if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget))
+ {
+ if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL))
+ {
+ int32 mirrorDamage = (uiDamage * 45)/100;
+ m_creature->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true);
+// m_creature->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW);
+ }
+ else
+ uiMirroredSoulTarget = 0;
+ }
+ }
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1,
+ SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), m_creature);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ Position spawnPoint = { 5618.139, 2451.873, 705.854 };
+
+ DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), m_creature);
+
+ if (pInstance)
+ {
+ pInstance->SetData(DATA_DEVOURER_EVENT, DONE);
+
+ if (bThreeFaceAchievement && IsHeroic())
+ pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED);
+
+ int32 entryIndex;
+ if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE)
+ entryIndex = 0;
+ else
+ entryIndex = 1;
+
+ for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i)
+ {
+ if (Creature *pSummon = m_creature->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN))
+ {
+ pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition);
+
+ if (pSummon->GetEntry() == NPC_JAINA_PART2)
+ DoScriptText(SAY_JAINA_OUTRO, pSummon);
+ else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2)
+ DoScriptText(SAY_SYLVANAS_OUTRO, pSummon);
+ }
+ }
+ }
+ }
+
+ void SpellHitTarget(Unit* pTarget, const SpellEntry *pSpell)
+ {
+ if (pSpell->Id == SPELL_PHANTOM_BLAST)
+ bThreeFaceAchievement = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ // Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_PHANTOM_BLAST:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_PHANTOM_BLAST,H_SPELL_PHANTOM_BLAST));
+ events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000);
+ break;
+ case EVENT_MIRRORED_SOUL:
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true))
+ {
+ uiMirroredSoulTarget = pTarget->GetGUID();
+ DoCast(pTarget, SPELL_MIRRORED_SOUL);
+ DoScriptText(EMOTE_MIRRORED_SOUL, m_creature);
+ }
+ events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000));
+ break;
+ case EVENT_WELL_OF_SOULS:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_WELL_OF_SOULS);
+ events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000);
+ break;
+ case EVENT_UNLEASHED_SOULS:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_UNLEASHED_SOULS);
+ m_creature->SetDisplayId(DISPLAY_SORROW);
+ DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), m_creature);
+ DoScriptText(EMOTE_UNLEASH_SOUL, m_creature);
+ events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000);
+ events.ScheduleEvent(EVENT_FACE_ANGER, 5000);
+ break;
+ case EVENT_FACE_ANGER:
+ m_creature->SetDisplayId(DISPLAY_ANGER);
+ break;
+
+ case EVENT_WAILING_SOULS:
+ m_creature->SetDisplayId(DISPLAY_DESIRE);
+ DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), m_creature);
+ DoScriptText(EMOTE_WAILING_SOUL, m_creature);
+ DoCast(m_creature, SPELL_WAILING_SOULS_STARTING);
+
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ {
+ m_creature->SetOrientation(m_creature->GetAngle(pTarget));
+ DoCast(m_creature, SPELL_WAILING_SOULS_BEAM);
+ }
+
+ beamAngle = m_creature->GetOrientation();
+
+ beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick
+ if (RAND(true,false))
+ beamAngleDiff = -beamAngleDiff;
+
+ m_creature->InterruptNonMeleeSpells(false);
+ m_creature->SetReactState(REACT_PASSIVE);
+
+ //Remove any target
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+
+ wailingSoulTick = 15;
+ events.DelayEvents(18000); // no other events during wailing souls
+ events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs.
+ break;
+
+ case EVENT_WAILING_SOULS_TICK:
+ beamAngle += beamAngleDiff;
+ m_creature->SetOrientation(beamAngle);
+ m_creature->StopMoving();
+
+ DoCast(m_creature, SPELL_WAILING_SOULS);
+
+ if (--wailingSoulTick)
+ events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000);
+ else
+ {
+ m_creature->SetReactState(REACT_AGGRESSIVE);
+ m_creature->SetDisplayId(DISPLAY_ANGER);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000));
+ }
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature)
+{
+ return new boss_devourer_of_soulsAI(pCreature);
+}
+
+void AddSC_boss_devourer_of_souls()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name="boss_devourer_of_souls";
+ newscript->GetAI = &GetAI_boss_devourer_of_souls;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp b/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp
new file mode 100644
index 00000000000..842e7498015
--- /dev/null
+++ b/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp
@@ -0,0 +1,899 @@
+/* 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 "forge_of_souls.h"
+
+enum Spells
+{
+ //Spiteful Apparition
+ SPELL_SPITE = 68895,
+ H_SPELL_SPITE = 70212,
+
+ //Spectral Warden
+ SPELL_VEIL_OF_SHADOWS = 69633,
+ SPELL_WAIL_OF_SOULS = 69148,
+ H_SPELL_WAIL_OF_SOULS = 70210,
+
+ //Soulguard Watchman
+ SPELL_SHROUD_OF_RUNES = 69056,
+ SPELL_UNHOLY_RAGE = 69053,
+
+ //Soulguard Reaper
+ SPELL_FROST_NOVA = 69060,
+ H_SPELL_FROST_NOVA = 70209,
+ SPELL_SHADOW_LANCE = 69058,
+
+ //Soulguard Bonecaster
+ SPELL_BONE_VOLLEY = 69080,
+ H_SPELL_BONE_VOLLEY = 70206,
+ SPELL_RAISE_DEAD = 69562,
+ SPELL_SHIELD_OF_BONES = 69069,
+ H_SPELL_SHIELD_OF_BONES = 70207,
+
+ //Soulguard Animator
+ // Raise dead 69562
+ SPELL_SHADOW_BOLT = 69068,
+ H_SPELL_SHADOW_BOLT = 70208,
+ SPELL_SOUL_SICKNESS = 69131,
+ SPELL_SOUL_SIPHON = 69128,
+
+ //Soulguard Adept
+ //Raise dead 69562
+ //Shadow Bolt 69068/70208
+ SPELL_DRAIN_LIFE = 69066,
+ H_SPELL_DRAIN_LIFE = 70213,
+ SPELL_SHADOW_MEND = 69564,
+ H_SPELL_SHADOW_MEND = 70205,
+
+ //Soul Horror
+ SPELL_SOUL_STRIKE = 69088,
+ H_SPELL_SOUL_STRIKE = 70211,
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ // Jaina/Sylvanas Intro
+ EVENT_INTRO_1,
+ EVENT_INTRO_2,
+ EVENT_INTRO_3,
+ EVENT_INTRO_4,
+ EVENT_INTRO_5,
+ EVENT_INTRO_6,
+ EVENT_INTRO_7,
+ EVENT_INTRO_8,
+
+ //Spiteful Apparition
+ EVENT_SPITE,
+
+ //Spectral Warden
+ EVENT_VEIL_OF_SHADOWS,
+ EVENT_WAIL_OF_SOULS,
+
+ //Soulguard Watchman
+ EVENT_SHROUD_OF_RUNES,
+ EVENT_UNHOLY_RAGE,
+
+ //Soulguard Reaper
+ EVENT_FROST_NOVA,
+ EVENT_SHADOW_LANCE,
+
+ //Soulguard Bonecaster
+ EVENT_BONE_VOLLEY,
+ EVENT_RAISE_DEAD,
+ EVENT_SHIELD_OF_BONES,
+
+ //Soulguard Animator
+ EVENT_SHADOW_BOLT,
+ EVENT_SOUL_SICKNESS,
+ EVENT_SOUL_SIPHON,
+
+ //Soulguard Adept
+ EVENT_DRAIN_LIFE,
+ EVENT_SHADOW_MEND,
+
+ //Soul Horror
+ EVENT_SOUL_STRIKE,
+};
+
+/****************************************SYLVANAS************************************/
+#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?"
+#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?"
+
+enum Yells
+{
+ SAY_JAINA_INTRO_1 = -1632040,
+ SAY_JAINA_INTRO_2 = -1632041,
+ SAY_JAINA_INTRO_3 = -1632042,
+ SAY_JAINA_INTRO_4 = -1632043,
+ SAY_JAINA_INTRO_5 = -1632044,
+ SAY_JAINA_INTRO_6 = -1632045,
+ SAY_JAINA_INTRO_7 = -1632046,
+ SAY_JAINA_INTRO_8 = -1632047,
+
+ SAY_SYLVANAS_INTRO_1 = -1632050,
+ SAY_SYLVANAS_INTRO_2 = -1632051,
+ SAY_SYLVANAS_INTRO_3 = -1632052,
+ SAY_SYLVANAS_INTRO_4 = -1632053,
+ SAY_SYLVANAS_INTRO_5 = -1632054,
+ SAY_SYLVANAS_INTRO_6 = -1632055,
+};
+
+enum eSylvanas
+{
+ GOSSIP_SPEECHINTRO = 13525,
+ ACTION_INTRO,
+};
+
+enum Phase
+{
+ PHASE_NORMAL,
+ PHASE_INTRO,
+};
+
+struct npc_sylvanas_fosAI: public ScriptedAI
+{
+ npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = m_creature->GetInstanceData();
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+
+ ScriptedInstance* pInstance;
+
+ EventMap events;
+ Phase phase;
+
+ void Reset()
+ {
+ events.Reset();
+ phase = PHASE_NORMAL;
+ }
+
+ void DoAction(const int32 actionId)
+ {
+ switch(actionId)
+ {
+ case ACTION_INTRO:
+ {
+ phase = PHASE_INTRO;
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ events.Reset();
+ events.ScheduleEvent(EVENT_INTRO_1, 1000);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (phase == PHASE_INTRO)
+ {
+ if (!pInstance)
+ return;
+
+ events.Update(diff);
+ switch(events.ExecuteEvent())
+ {
+ case EVENT_INTRO_1:
+ DoScriptText(SAY_SYLVANAS_INTRO_1, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_2, 11500);
+ break;
+
+ case EVENT_INTRO_2:
+ DoScriptText(SAY_SYLVANAS_INTRO_2, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_3, 10500);
+ break;
+
+ case EVENT_INTRO_3:
+ DoScriptText(SAY_SYLVANAS_INTRO_3, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_4, 9500);
+ break;
+
+ case EVENT_INTRO_4:
+ DoScriptText(SAY_SYLVANAS_INTRO_4, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_5, 10500);
+ break;
+
+ case EVENT_INTRO_5:
+ DoScriptText(SAY_SYLVANAS_INTRO_5, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_6, 9500);
+ break;
+
+ case EVENT_INTRO_6:
+ DoScriptText(SAY_SYLVANAS_INTRO_6, m_creature);
+ // End of Intro
+ phase = PHASE_NORMAL;
+ break;
+ }
+ }
+
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ //if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ // return;
+
+ //while(uint32 eventId = events.ExecuteEvent())
+ //{
+ // switch(eventId)
+ // {
+ // }
+ //}
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct npc_jaina_fosAI: public ScriptedAI
+{
+ npc_jaina_fosAI(Creature *c) : ScriptedAI(c)
+ {
+ pInstance = m_creature->GetInstanceData();
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+
+ ScriptedInstance* pInstance;
+
+ EventMap events;
+ Phase phase;
+
+ void Reset()
+ {
+ events.Reset();
+ phase = PHASE_NORMAL;
+ }
+
+ void DoAction(const int32 actionId)
+ {
+ switch(actionId)
+ {
+ case ACTION_INTRO:
+ {
+ phase = PHASE_INTRO;
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ events.Reset();
+ events.ScheduleEvent(EVENT_INTRO_1, 1000);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (phase == PHASE_INTRO)
+ {
+ if (!pInstance)
+ return;
+
+ events.Update(diff);
+ switch(events.ExecuteEvent())
+ {
+ case EVENT_INTRO_1:
+ DoScriptText(SAY_JAINA_INTRO_1, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_2, 8000);
+ break;
+
+ case EVENT_INTRO_2:
+ DoScriptText(SAY_JAINA_INTRO_2, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_3, 8500);
+ break;
+
+ case EVENT_INTRO_3:
+ DoScriptText(SAY_JAINA_INTRO_3, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_4, 8000);
+ break;
+
+ case EVENT_INTRO_4:
+ DoScriptText(SAY_JAINA_INTRO_4, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_5, 10000);
+ break;
+
+ case EVENT_INTRO_5:
+ DoScriptText(SAY_JAINA_INTRO_5, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_6, 8000);
+ break;
+
+ case EVENT_INTRO_6:
+ DoScriptText(SAY_JAINA_INTRO_6, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_7, 12000);
+ break;
+
+ case EVENT_INTRO_7:
+ DoScriptText(SAY_JAINA_INTRO_7, m_creature);
+ events.ScheduleEvent(EVENT_INTRO_8, 8000);
+ break;
+
+ case EVENT_INTRO_8:
+ DoScriptText(SAY_JAINA_INTRO_8, m_creature);
+ // End of Intro
+ phase = PHASE_NORMAL;
+ break;
+ }
+ }
+
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ //if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ // return;
+
+ //while(uint32 eventId = events.ExecuteEvent())
+ //{
+ // switch(eventId)
+ // {
+ // }
+ //}
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->GetEntry() == NPC_JAINA_PART1)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ else
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_jaina_or_slyvanas_fos(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_INTRO);
+ break;
+ }
+
+ return true;
+}
+
+struct mob_spiteful_apparitionAI: public ScriptedAI
+{
+ mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_SPITE, 8000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_SPITE:
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_SPITE,H_SPELL_SPITE));
+ events.RescheduleEvent(EVENT_SPITE, 8000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_spectral_wardenAI: public ScriptedAI
+{
+ mob_spectral_wardenAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000);
+ events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_VEIL_OF_SHADOWS:
+ DoCast(m_creature->getVictim(), SPELL_VEIL_OF_SHADOWS);
+ events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000);
+ return;
+ case EVENT_WAIL_OF_SOULS:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_WAIL_OF_SOULS,H_SPELL_WAIL_OF_SOULS));
+ events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000);
+ return;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soulguard_watchmanAI: public ScriptedAI
+{
+ mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000);
+ events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_SHROUD_OF_RUNES:
+ DoCast(m_creature, SPELL_SHROUD_OF_RUNES);
+ events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000);
+ return;
+ case EVENT_UNHOLY_RAGE:
+ DoCast(m_creature, SPELL_UNHOLY_RAGE);
+ events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999);
+ return;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soulguard_reaperAI: public ScriptedAI
+{
+ mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_FROST_NOVA, 8000);
+ events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_FROST_NOVA:
+ DoCast(m_creature, DUNGEON_MODE(SPELL_FROST_NOVA,H_SPELL_FROST_NOVA));
+ events.RescheduleEvent(EVENT_FROST_NOVA, 9600);
+ return;
+ case EVENT_SHADOW_LANCE:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_SHADOW_LANCE);
+ events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soulguard_bonecasterAI: public ScriptedAI
+{
+ mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000);
+ events.ScheduleEvent(EVENT_RAISE_DEAD, 25000);
+ events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_BONE_VOLLEY:
+ DoCastAOE(DUNGEON_MODE(SPELL_BONE_VOLLEY,H_SPELL_BONE_VOLLEY));
+ events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000);
+ return;
+ case EVENT_RAISE_DEAD:
+ DoCast(m_creature, SPELL_RAISE_DEAD);
+ events.RescheduleEvent(EVENT_RAISE_DEAD, 25000);
+ return;
+ case EVENT_SHIELD_OF_BONES:
+ DoCast(m_creature, DUNGEON_MODE(SPELL_SHIELD_OF_BONES,H_SPELL_SHIELD_OF_BONES));
+ events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soulguard_animatorAI: public ScriptedAI
+{
+ mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_RAISE_DEAD, 25000);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000);
+ events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000);
+ events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_RAISE_DEAD:
+ DoCast(m_creature, SPELL_RAISE_DEAD);
+ events.RescheduleEvent(EVENT_RAISE_DEAD, 25000);
+ return;
+ case EVENT_SHADOW_BOLT:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_SHADOW_BOLT,H_SPELL_SHADOW_BOLT));
+ events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000);
+ return;
+ case EVENT_SOUL_SICKNESS:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_SOUL_SICKNESS);
+ events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000);
+ return;
+ case EVENT_SOUL_SIPHON:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, SPELL_SOUL_SIPHON);
+ events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soulguard_adeptAI: public ScriptedAI
+{
+ mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_RAISE_DEAD, 25000);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000);
+ events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000);
+ events.ScheduleEvent(EVENT_SHADOW_MEND, 35000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_RAISE_DEAD:
+ DoCast(m_creature, SPELL_RAISE_DEAD);
+ events.RescheduleEvent(EVENT_RAISE_DEAD, 25000);
+ return;
+ case EVENT_SHADOW_BOLT:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_SHADOW_BOLT,H_SPELL_SHADOW_BOLT));
+ events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000);
+ return;
+ case EVENT_DRAIN_LIFE:
+ if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
+ DoCast(pTarget, DUNGEON_MODE(SPELL_DRAIN_LIFE,H_SPELL_DRAIN_LIFE));
+ events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000);
+ return;
+ case EVENT_SHADOW_MEND:
+ DoCast(m_creature, DUNGEON_MODE(SPELL_SHADOW_MEND,H_SPELL_SHADOW_MEND));
+ events.RescheduleEvent(EVENT_SHADOW_MEND, 20000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct mob_soul_horrorAI: public ScriptedAI
+{
+ mob_soul_horrorAI(Creature *c) : ScriptedAI(c)
+ {
+ }
+
+ EventMap events;
+
+ void Reset()
+ {
+ events.Reset();
+ }
+
+ void EnterCombat(Unit* who)
+ {
+ events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (m_creature->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_SOUL_STRIKE:
+ DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_SOUL_STRIKE,H_SPELL_SOUL_STRIKE));
+ events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature)
+{
+ return new npc_jaina_fosAI(pCreature);
+};
+
+CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature)
+{
+ return new npc_sylvanas_fosAI(pCreature);
+};
+
+CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature)
+{
+ return new mob_spiteful_apparitionAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature)
+{
+ return new mob_spectral_wardenAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature)
+{
+ return new mob_soulguard_watchmanAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature)
+{
+ return new mob_soulguard_reaperAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature)
+{
+ return new mob_soulguard_bonecasterAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature)
+{
+ return new mob_soulguard_animatorAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature)
+{
+ return new mob_soulguard_adeptAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature)
+{
+ return new mob_soul_horrorAI(pCreature);
+}
+
+void AddSC_forge_of_souls()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_sylvanas_fos";
+ newscript->GetAI = &GetAI_npc_sylvanas_fosAI;
+ newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos;
+ newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_jaina_fos";
+ newscript->GetAI = &GetAI_npc_jaina_fosAI;
+ newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos;
+ newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_spiteful_apparition";
+ newscript->GetAI = &GetAI_mob_spiteful_apparitionAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_spectral_warden";
+ newscript->GetAI = &GetAI_mob_spectral_wardenAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soulguard_watchman";
+ newscript->GetAI = &GetAI_mob_soulguard_watchmanAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soulguard_reaper";
+ newscript->GetAI = &GetAI_mob_soulguard_reaperAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soulguard_bonecaster";
+ newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soulguard_animator";
+ newscript->GetAI = &GetAI_mob_soulguard_animatorAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soulguard_adept";
+ newscript->GetAI = &GetAI_mob_soulguard_adeptAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name="mob_soul_horror";
+ newscript->GetAI = &GetAI_mob_soul_horrorAI;
+ newscript->RegisterSelf();
+}
diff --git a/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h b/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h
index 6f7a3987cee..e0479eb4d2b 100644
--- a/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h
+++ b/src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h
@@ -16,18 +16,37 @@
#ifndef DEF_FORGE_OF_SOULS_H
#define DEF_FORGE_OF_SOULS_H
+
enum Data
{
DATA_BRONJAHM_EVENT,
- DATA_DEVOURER_EVENT
+ DATA_DEVOURER_EVENT,
+ DATA_TEAM_IN_INSTANCE,
};
+
enum Data64
{
- DATA_BRONJAHM
+ DATA_BRONJAHM,
+ DATA_DEVOURER,
};
+
enum Creatures
{
CREATURE_BRONJAHM = 36497,
- CREATURE_DEVOURER = 36502
+ CREATURE_DEVOURER = 36502,
+
+ NPC_SYLVANAS_PART1 = 37596,
+ NPC_SYLVANAS_PART2 = 38161,
+ NPC_JAINA_PART1 = 37597,
+ NPC_JAINA_PART2 = 38160,
+ NPC_KALIRA = 37583,
+ NPC_ELANDRA = 37774,
+ NPC_LORALEN = 37779,
+ NPC_KORELN = 37582,
+ NPC_CHAMPION_1_HORDE = 37584,
+ NPC_CHAMPION_2_HORDE = 37587,
+ NPC_CHAMPION_3_HORDE = 37588,
+ NPC_CHAMPION_1_ALLIANCE = 37496,
+ NPC_CHAMPION_2_ALLIANCE = 37497,
};
#endif
diff --git a/src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp
index cfdd2a30114..814380db4fd 100644
--- a/src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp
+++ b/src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp
@@ -26,24 +26,41 @@
struct instance_forge_of_souls : public ScriptedInstance
{
- instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+ instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {};
uint64 uiBronjahm;
uint64 uiDevourer;
- uint32 m_auiEncounter[MAX_ENCOUNTER];
+ uint32 uiEncounter[MAX_ENCOUNTER];
+ uint32 uiTeamInInstance;
void Initialize()
{
uiBronjahm = 0;
uiDevourer = 0;
+ uiTeamInInstance = 0;
+
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- m_auiEncounter[i] = NOT_STARTED;
+ uiEncounter[i] = NOT_STARTED;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (uiEncounter[i] == IN_PROGRESS) return true;
+
+ return false;
}
void OnCreatureCreate(Creature* pCreature, bool add)
{
+ Map::PlayerList const &players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ if (Player* pPlayer = players.begin()->getSource())
+ uiTeamInInstance = pPlayer->GetTeam();
+
switch(pCreature->GetEntry())
{
case CREATURE_BRONJAHM:
@@ -54,23 +71,16 @@ struct instance_forge_of_souls : public ScriptedInstance
break;
}
}
-/*
- void OnGameObjectCreate(GameObject* pGo, bool add)
- {
- switch(pGo->GetEntry())
- {
- }
- }
-*/
+
void SetData(uint32 type, uint32 data)
{
switch(type)
{
case DATA_BRONJAHM_EVENT:
- m_auiEncounter[0] = data;
+ uiEncounter[0] = data;
break;
case DATA_DEVOURER_EVENT:
- m_auiEncounter[1] = data;
+ uiEncounter[1] = data;
break;
}
@@ -82,8 +92,9 @@ struct instance_forge_of_souls : public ScriptedInstance
{
switch(type)
{
- case DATA_BRONJAHM_EVENT: return m_auiEncounter[0];
- case DATA_DEVOURER_EVENT: return m_auiEncounter[1];
+ case DATA_BRONJAHM_EVENT: return uiEncounter[0];
+ case DATA_DEVOURER_EVENT: return uiEncounter[1];
+ case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance;
}
return 0;
@@ -94,6 +105,7 @@ struct instance_forge_of_souls : public ScriptedInstance
switch(identifier)
{
case DATA_BRONJAHM: return uiBronjahm;
+ case DATA_DEVOURER: return uiBronjahm;
}
return 0;
@@ -104,7 +116,7 @@ struct instance_forge_of_souls : public ScriptedInstance
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
- saveStream << "F S " << m_auiEncounter[0] << " " << m_auiEncounter[1];
+ saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1];
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
@@ -128,12 +140,12 @@ struct instance_forge_of_souls : public ScriptedInstance
if (dataHead1 == 'F' && dataHead2 == 'S')
{
- m_auiEncounter[0] = data0;
- m_auiEncounter[1] = data1;
+ uiEncounter[0] = data0;
+ uiEncounter[1] = data1;
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;
@@ -146,7 +158,7 @@ InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap)
return new instance_forge_of_souls(pMap);
}
-void AddSC_forge_of_souls()
+void AddSC_instance_forge_of_souls()
{
Script *newscript;
newscript = new Script;