diff options
Diffstat (limited to 'src')
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; |