diff options
author | Sirikfoll <sirikfoll@hotmail.com> | 2016-02-06 02:05:40 -0200 |
---|---|---|
committer | sirikfoll <sirikfoll@hotmail.com> | 2016-02-23 23:07:55 -0300 |
commit | 6002acf376556eb413a6b514f14b8a07f8de5099 (patch) | |
tree | 5f19bade362c270d35803ab854091e34a38eb4e8 /src | |
parent | d1a185e3d5af9db2c85e04df846167ce9c4a4cf9 (diff) |
Script/SWP Full Rework on M'uru Encounter
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp | 833 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h | 3 |
2 files changed, 489 insertions, 347 deletions
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 04d23cd7d4e..6c84677708e 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -15,88 +15,119 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Muru -SD%Complete: 80 -SDComment: all sounds, black hole effect triggers to often (46228) -*/ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "sunwell_plateau.h" -#include "Player.h" -#include "SpellInfo.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" -// Muru & Entropius's spells enum Spells { - SPELL_ENRAGE = 26662, - // Muru's spells - SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) - SPELL_DARKNESS = 45999, - SPELL_OPEN_ALL_PORTALS = 46177, - SPELL_OPEN_PORTAL = 45977, - SPELL_OPEN_PORTAL_2 = 45976, - SPELL_SUMMON_BERSERKER = 46037, - SPELL_SUMNON_FURY_MAGE = 46038, - SPELL_SUMMON_VOID_SENTINEL = 45988, - SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_OPEN_PORTAL_PERIODIC = 45994, + SPELL_DARKNESS_PERIODIC = 45998, + SPELL_NEGATIVE_ENERGY_PERIODIC = 46009, + SPELL_SUMMON_VOID_SPAWN = 46071, + SPELL_SUMMON_BLOOD_ELVES_SCRIPT = 46050, + SPELL_SUMMON_BLOOD_ELVES_PERIODIC = 46041, + SPELL_OPEN_ALL_PORTALS = 46177, + SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_ENRAGE = 26662, + SPELL_SUMMON_DARK_FIEND_0 = 46000, + SPELL_SUMMON_DARK_FIEND_1 = 46001, + SPELL_SUMMON_DARK_FIEND_2 = 46002, + SPELL_SUMMON_DARK_FIEND_3 = 46003, + SPELL_SUMMON_DARK_FIEND_4 = 46004, + SPELL_SUMMON_DARK_FIEND_5 = 46005, + SPELL_SUMMON_DARK_FIEND_6 = 46006, + SPELL_SUMMON_DARK_FIEND_7 = 46007, + SPELL_SUMMON_BERSERKER = 46037, + SPELL_SUMMON_BERSERKER_2 = 46040, + SPELL_SUMMON_FURY_MAGE = 46038, + SPELL_SUMMON_FURY_MAGE_2 = 46039, // Entropius's spells - SPELL_DARKNESS_E = 46269, - SPELL_BLACKHOLE = 46282, - SPELL_NEGATIVE_ENERGY_E = 46284, - SPELL_ENTROPIUS_SPAWN = 46223, - - // Shadowsword Berserker's spells - SPELL_FLURRY = 46160, - SPELL_DUAL_WIELD = 29651, + SPELL_ENTROPIUS_COSMETIC_SPAWN = 46223, + SPELL_DARKNESS_E = 46269, + SPELL_NEGATIVE_ENERGY_PERIODIC_E = 46284, + SPELL_BLACKHOLE = 46282, + SPELL_SUMMON_DARKFIEND_E = 46263, + + // Myruu's Portal Target + SPELL_SUMMON_VOID_SENTINEL_SUMMONER = 45978, + SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL = 45989, + SPELL_SUMMON_VOID_SENTINEL = 45988, + SPELL_TRANSFORM_VISUAL_MISSILE = 46205, + TRANSFORM_VISUAL_MISSILE_1 = 46208, + TRANSFORM_VISUAL_MISSILE_2 = 46178, + SPELL_OPEN_PORTAL = 45977, + SPELL_OPEN_PORTAL_2 = 45976, - // Shadowsword Fury Mage's spells - SPELL_FEL_FIREBALL = 46101, - SPELL_SPELL_FURY = 46102, + //Dark Fiend Spells + SPELL_DARKFIEND_DAMAGE = 45944, + SPELL_DARKFIEND_VISUAL = 45936, + SPELL_DARKFIEND_SKIN = 45934, // Void Sentinel's spells - SPELL_SHADOW_PULSE = 46087, - SPELL_VOID_BLAST = 46161, + SPELL_SHADOW_PULSE_PERIODIC = 46086, + SPELL_VOID_BLAST = 46161, - // Void Spawn's spells - SPELL_SHADOW_BOLT_VOLLEY = 46082, + //Black Hole Spells + SPELL_BLACKHOLE_SUMMON_VISUAL = 46242, + SPELL_BLACKHOLE_SUMMON_VISUAL_2 = 46247, + SPELL_BLACKHOLE_PASSIVE = 46228, + SPELL_BLACK_HOLE_VISUAL_2 = 46235 +}; - //Dark Fiend Spells - SPELL_DARKFIEND_AOE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - //Black Hole Spells - SPELL_BLACKHOLE_SPAWN = 46242, - SPELL_BLACKHOLE_GROW = 46228 +enum Misc +{ + MAX_VOID_SPAWNS = 6, + MAX_SUMMON_BLOOD_ELVES = 4, + MAX_SUMMON_DARK_FIEND = 8 }; -enum Events +uint32 const SummonDarkFiendSpells[MAX_SUMMON_DARK_FIEND] = { - // M'uru - EVENT_DARKNESS = 1, - EVENT_SUMMON_HUMANOIDS, - EVENT_SUMMON_SENTINEL, - EVENT_PHASE_TRANSITION, // Delayed phase transition. - EVENT_ENRAGE, - - // Entropius - EVENT_SUMMON_BLACK_HOLE + SPELL_SUMMON_DARK_FIEND_0, + SPELL_SUMMON_DARK_FIEND_1, + SPELL_SUMMON_DARK_FIEND_2, + SPELL_SUMMON_DARK_FIEND_3, + SPELL_SUMMON_DARK_FIEND_4, + SPELL_SUMMON_DARK_FIEND_5, + SPELL_SUMMON_DARK_FIEND_6, + SPELL_SUMMON_DARK_FIEND_7 }; -enum Phases +uint32 const SummonBloodElvesSpells[MAX_SUMMON_BLOOD_ELVES] = { - PHASE_ONE = 1, - PHASE_TWO, + SPELL_SUMMON_BERSERKER, + SPELL_SUMMON_BERSERKER_2, + SPELL_SUMMON_FURY_MAGE, + SPELL_SUMMON_FURY_MAGE_2 }; -enum CreatureGroups +class VoidSpawnSummon : public BasicEvent { - CREATURE_GROUP_HUMANOIDS, - CREATURE_GROUP_DARKFIENDS + public: + explicit VoidSpawnSummon(Creature* owner) + : _owner(owner) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->CastSpell((Unit*)nullptr, SPELL_SUMMON_VOID_SENTINEL, true); + return true; + } + + private: + Creature* _owner; }; class boss_entropius : public CreatureScript @@ -110,53 +141,78 @@ public: void Reset() override { - DoCastAOE(SPELL_NEGATIVE_ENERGY_E); + _Reset(); + DoCast(me, SPELL_ENTROPIUS_COSMETIC_SPAWN, true); } - void EnterCombat(Unit* /*who*/) override + void ScheduleTasks() override { - _EnterCombat(); - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); - DoCast(me, SPELL_ENTROPIUS_SPAWN); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); + scheduler.Schedule(Milliseconds(2000), [this](TaskContext /*context*/) + { + DoResetPortals(); + DoCastAOE(SPELL_NEGATIVE_ENERGY_PERIODIC_E, true); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext context) + { + DoCastAOE(SPELL_DARKNESS_E, true); + DoCastAOE(SPELL_BLACKHOLE, true); + + context.Repeat(); + }); } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + switch (summon->GetEntry()) { case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); + summon->CastSpell(summon, SPELL_DARKFIEND_VISUAL); break; case NPC_DARKNESS: - summoned->AddUnitState(UNIT_STATE_STUNNED); - float x, y, z, o; - summoned->GetHomePosition(x, y, z, o); - me->SummonCreature(NPC_DARK_FIENDS, x, y, z, o, TEMPSUMMON_CORPSE_DESPAWN, 0); + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_BLACKHOLE); + summon->CastSpell(summon, SPELL_SUMMON_DARKFIEND_E, true); break; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + summons.Summon(summon); } - void ExecuteEvent(uint32 eventId) override + void EnterEvadeMode(EvadeReason /*why*/) override { - if (eventId == EVENT_SUMMON_BLACK_HOLE) - { - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(random, SPELL_DARKNESS_E); - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - random->CastSpell(random, SPELL_BLACKHOLE); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); - } + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) + muru->AI()->EnterEvadeMode(); + + DoResetPortals(); + summons.DespawnAll(); + me->DespawnOrUnsummon(); } - void EnterEvadeMode(EvadeReason /*why*/) override + void JustDied(Unit* /*killer*/) override { + _JustDied(); + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) - muru->AI()->Reset(); // Reset encounter. - me->DisappearAndDie(); - summons.DespawnAll(); + muru->DisappearAndDie(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + + void DoResetPortals() + { + std::list<Creature*> portals; + me->GetCreatureListWithEntryInGrid(portals, NPC_MURU_PORTAL_TARGET, 100.0f); + for (Creature* portal : portals) + portal->RemoveAllAuras(); } }; @@ -181,101 +237,96 @@ public: void Initialize() { - DarkFiend = false; - HasEnraged = false; - EntropiusGUID.Clear(); + _hasEnraged = false; + _phase = PHASE_ONE; + _entropiusGUID.Clear(); } void Reset() override { - Initialize(); _Reset(); + Initialize(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); } + void EnterEvadeMode(EvadeReason /*why*/) override + { + BossAI::EnterEvadeMode(); + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->AI()->EnterEvadeMode(); + } + + void ScheduleTasks() override + { + scheduler.Schedule(Minutes(10), [this](TaskContext /*context*/) + { + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->CastSpell(entropius, SPELL_ENRAGE); + DoCast(me, SPELL_ENRAGE); + _hasEnraged = true; + }); + + scheduler.Schedule(Seconds(10), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_PERIODIC, true); + }); + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.SetPhase(PHASE_ONE); - events.ScheduleEvent(EVENT_ENRAGE, 600000); - events.ScheduleEvent(EVENT_DARKNESS, 45000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 10000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 31500, 0, PHASE_ONE); - DoCastAOE(SPELL_NEGATIVE_ENERGY); + DoCast(me, SPELL_OPEN_PORTAL_PERIODIC, true); + DoCast(me, SPELL_DARKNESS_PERIODIC, true); + DoCast(me, SPELL_NEGATIVE_ENERGY_PERIODIC, true); } void DamageTaken(Unit* /*done_by*/, uint32 &damage) override { - if (damage >= me->GetHealth() && events.IsInPhase(PHASE_ONE)) + if (damage >= me->GetHealth()) { - damage = 0; + damage = me->GetHealth() - 1; + if (_phase != PHASE_ONE) + return; + + _phase = PHASE_TWO; me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS); + DoCast(me, SPELL_OPEN_ALL_PORTALS, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.SetPhase(PHASE_TWO); - events.ScheduleEvent(EVENT_PHASE_TRANSITION, 2000); + + scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_ENTROPIUS, true); + }); } } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + if (summon->GetEntry() == NPC_ENTROPIUS) { - case NPC_ENTROPIUS: - me->SetVisible(false); - EntropiusGUID = summoned->GetGUID(); - if (HasEnraged) // If we hit phase transition while enraged, enrage Entropius as well. - summoned->CastSpell(summoned, SPELL_ENRAGE); - break; - case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); - break; + me->SetVisible(false); + _entropiusGUID = summon->GetGUID(); + if (_hasEnraged) + summon->CastSpell(summon, SPELL_ENRAGE, true); + return; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + BossAI::JustSummoned(summon); } - void ExecuteEvent(uint32 eventId) override + void UpdateAI(uint32 diff) override { - switch (eventId) - { - case EVENT_DARKNESS: - if (!DarkFiend) - { - DarkFiend = true; - DoCastAOE(SPELL_DARKNESS); - } - else - me->SummonCreatureGroup(CREATURE_GROUP_DARKFIENDS); - events.ScheduleEvent(EVENT_DARKNESS, DarkFiend ? 3000 : 42000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_HUMANOIDS: - me->SummonCreatureGroup(CREATURE_GROUP_HUMANOIDS); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 60000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_SENTINEL: - DoCastAOE(SPELL_OPEN_PORTAL_2); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 30000, 0, PHASE_ONE); - break; - case EVENT_PHASE_TRANSITION: - DoCast(me, SPELL_SUMMON_ENTROPIUS); - break; - case EVENT_ENRAGE: - if (Creature* entropius = ObjectAccessor::GetCreature(*me, EntropiusGUID)) - entropius->CastSpell(entropius, SPELL_ENRAGE); - DoCast(me, SPELL_ENRAGE); - HasEnraged = true; - break; - default: - break; - } + if (!UpdateVictim()) + return; + + scheduler.Update(diff); } private: - bool DarkFiend; - bool HasEnraged; - ObjectGuid EntropiusGUID; + ObjectGuid _entropiusGUID; + bool _hasEnraged; + uint8 _phase; }; CreatureAI* GetAI(Creature* creature) const override @@ -289,89 +340,50 @@ class npc_muru_portal : public CreatureScript public: npc_muru_portal() : CreatureScript("npc_muru_portal") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_muru_portalAI>(creature); - } - struct npc_muru_portalAI : public ScriptedAI { - npc_muru_portalAI(Creature* creature) : ScriptedAI(creature), Summons(creature) - { - Initialize(); - SetCombatMovement(false); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - SummonTimer = 5000; - - InAction = false; - SummonSentinel = false; - } - - InstanceScript* instance; - - SummonList Summons; - - bool SummonSentinel; - bool InAction; - - uint32 SummonTimer; - - void Reset() override - { - Initialize(); + npc_muru_portalAI(Creature* creature) : ScriptedAI(creature) { } - me->AddUnitState(UNIT_STATE_STUNNED); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - if (Player* target = ObjectAccessor::GetPlayer(*me, instance->GetGuidData(DATA_PLAYER_GUID))) - summoned->AI()->AttackStart(target); + DoCast(summon, SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL, true); - Summons.Summon(summoned); + summon->m_Events.AddEvent(new VoidSpawnSummon(summon), summon->m_Events.CalculateTime(1500)); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - InAction = true; - switch (Spell->Id) + switch (spell->Id) { case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL); + DoCastAOE(SPELL_OPEN_PORTAL, true); + DoCastAOE(SPELL_TRANSFORM_VISUAL_MISSILE, true); break; case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL); - SummonSentinel = true; + DoCastAOE(SPELL_OPEN_PORTAL, true); + _scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCastAOE(SPELL_SUMMON_VOID_SENTINEL_SUMMONER, true); + }); + break; + default: break; } } void UpdateAI(uint32 diff) override { - if (!SummonSentinel) - { - if (InAction && instance->GetBossState(DATA_MURU) == NOT_STARTED) - Reset(); - return; - } - - if (SummonTimer <= diff) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); - SummonTimer = 5000; - SummonSentinel = false; - } else SummonTimer -= diff; + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_muru_portalAI>(creature); + } }; class npc_dark_fiend : public CreatureScript @@ -379,11 +391,6 @@ class npc_dark_fiend : public CreatureScript public: npc_dark_fiend() : CreatureScript("npc_dark_fiend") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_dark_fiendAI(creature); - } - struct npc_dark_fiendAI : public ScriptedAI { npc_dark_fiendAI(Creature* creature) : ScriptedAI(creature) @@ -393,54 +400,56 @@ public: void Initialize() { - WaitTimer = 2000; - InAction = false; - } + me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_DARKFIEND_SKIN, true); - uint32 WaitTimer; - bool InAction; + _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/) + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - void Reset() override - { - Initialize(); + if (Creature* _summoner = ObjectAccessor::GetCreature(*me, _summonerGUID)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0)) + AttackStart(target); + }); - me->AddUnitState(UNIT_STATE_STUNNED); + _scheduler.Schedule(Seconds(3), [this](TaskContext context) + { + if (me->IsWithinDist(me->GetVictim(), 5.0f) && me->HasAura(SPELL_DARKFIEND_SKIN)) + { + DoCastAOE(SPELL_DARKFIEND_DAMAGE, false); + me->DisappearAndDie(); + } + + context.Repeat(Milliseconds(500)); + }); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void IsSummonedBy(Unit* summoner) override { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effects[i].Effect == 38) - me->DisappearAndDie(); + _summonerGUID = summoner->GetGUID(); } - void UpdateAI(uint32 diff) override + bool CanAIAttack(Unit const* /*target*/) const override { - if (!UpdateVictim()) - return; + return me->HasAura(SPELL_DARKFIEND_SKIN); + } - if (WaitTimer <= diff) - { - if (!InAction) - { - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_DARKFIEND_SKIN, false); - AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); - InAction = true; - WaitTimer = 500; - } - else - { - if (me->IsWithinDist(me->GetVictim(), 5)) - { - DoCastAOE(SPELL_DARKFIEND_AOE, false); - me->DisappearAndDie(); - } - WaitTimer = 500; - } - } else WaitTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + ObjectGuid _summonerGUID; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_dark_fiendAI>(creature); + } }; class npc_void_sentinel : public CreatureScript @@ -448,63 +457,54 @@ class npc_void_sentinel : public CreatureScript public: npc_void_sentinel() : CreatureScript("npc_void_sentinel") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_void_sentinelAI(creature); - } - struct npc_void_sentinelAI : public ScriptedAI { npc_void_sentinelAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); + _instance = me->GetInstanceScript(); } - void Initialize() + void IsSummonedBy(Unit* /*summoner*/) override { - PulseTimer = 3000; - VoidBlastTimer = 45000; //is this a correct timer? + if (Creature* muru = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MURU))) + muru->AI()->JustSummoned(me); } - uint32 PulseTimer; - uint32 VoidBlastTimer; - - void Reset() override + void EnterCombat(Unit* /*who*/) override { - Initialize(); + DoCast(me, SPELL_SHADOW_PULSE_PERIODIC, true); - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, 71, o); + _scheduler.Schedule(Seconds(45), [this](TaskContext context) + { + DoCastVictim(SPELL_VOID_BLAST, false); + + context.Repeat(); + }); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { - for (uint8 i = 0; i < 8; ++i) - if (Creature* temp = me->SummonCreature(NPC_VOID_SPAWN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 6), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) - temp->AI()->AttackStart(killer); + for (uint8 i = 0; i < MAX_VOID_SPAWNS; ++i) + DoCastAOE(SPELL_SUMMON_VOID_SPAWN, true); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) - return; - - if (PulseTimer <= diff) - { - DoCastAOE(SPELL_SHADOW_PULSE, true); - PulseTimer = 3000; - } else PulseTimer -= diff; - - if (VoidBlastTimer <= diff) + _scheduler.Update(diff, [this] { - DoCastVictim(SPELL_VOID_BLAST, false); - VoidBlastTimer = 45000; - } else VoidBlastTimer -= diff; - - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + }); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_void_sentinelAI>(creature); + } }; class npc_blackhole : public CreatureScript @@ -512,84 +512,220 @@ class npc_blackhole : public CreatureScript public: npc_blackhole() : CreatureScript("npc_blackhole") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_blackholeAI>(creature); - } - struct npc_blackholeAI : public ScriptedAI { npc_blackholeAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } - void Initialize() - { - DespawnTimer = 15000; - SpellTimer = 5000; - Phase = 0; - NeedForAHack = 0; - } - - InstanceScript* instance; - - uint32 DespawnTimer; - uint32 SpellTimer; - uint8 Phase; - uint8 NeedForAHack; - void Reset() override { - Initialize(); + me->SetReactState(REACT_PASSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); - me->AddUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); - } + _scheduler.Schedule(Seconds(15), [this](TaskContext /*context*/) + { + me->DisappearAndDie(); + }); - void UpdateAI(uint32 diff) override - { - if (SpellTimer <= diff) + _scheduler.Schedule(Seconds(1), [this](TaskContext context) { - Unit* Victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID)); - switch (NeedForAHack) + switch (context.GetRepeatCounter()) { case 0: - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_GROW, false); - if (Victim) - AttackStart(Victim); - SpellTimer = 700; - NeedForAHack = 2; + me->SetReactState(REACT_AGGRESSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL_2); + if (Unit* victim = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_PLAYER_GUID))) + AttackStart(victim); + context.Repeat(Milliseconds(1200)); break; case 1: - me->AddAura(SPELL_BLACKHOLE_GROW, me); - NeedForAHack = 2; - SpellTimer = 600; + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); + context.Repeat(Seconds(2)); break; case 2: - SpellTimer = 400; - NeedForAHack = 3; - me->RemoveAura(SPELL_BLACKHOLE_GROW); + DoCast(SPELL_BLACKHOLE_PASSIVE); + DoCast(SPELL_BLACK_HOLE_VISUAL_2); + break; + default: break; - case 3: - SpellTimer = urand(400, 900); - NeedForAHack = 1; - if (Unit* Temp = me->GetVictim()) - { - if (Temp->GetPositionZ() > 73 && Victim) - AttackStart(Victim); - } else - return; } - } else SpellTimer -= diff; + }); + } - if (DespawnTimer <= diff) - me->DisappearAndDie(); - else DespawnTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_blackholeAI>(creature); + } +}; + +class spell_summon_blood_elves_script : SpellScriptLoader +{ + public: + spell_summon_blood_elves_script() : SpellScriptLoader("spell_summon_blood_elves_script") { } + + class spell_summon_blood_elves_script_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_blood_elves_script_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + if (!sSpellMgr->GetSpellInfo(SummonBloodElvesSpells[i])) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonBloodElvesSpells[urand(0,3)], true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_summon_blood_elves_script_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_summon_blood_elves_script_SpellScript(); + } +}; + +class spell_muru_darkness : SpellScriptLoader +{ + public: + spell_muru_darkness() : SpellScriptLoader("spell_muru_darkness") { } + + class spell_muru_darkness_SpellScript : public SpellScript + { + PrepareSpellScript(spell_muru_darkness_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + if (!sSpellMgr->GetSpellInfo(SummonDarkFiendSpells[i])) + return false; + return true; + } + + void HandleAfterCast() + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonDarkFiendSpells[i], true); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_muru_darkness_SpellScript::HandleAfterCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_muru_darkness_SpellScript(); + } +}; + +class spell_dark_fiend_skin : public SpellScriptLoader +{ + public: + spell_dark_fiend_skin() : SpellScriptLoader("spell_dark_fiend_skin") { } + + class spell_dark_fiend_skin_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dark_fiend_skin_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + if (Creature* target = GetTarget()->ToCreature()) + { + target->SetReactState(REACT_PASSIVE); + target->AttackStop(); + target->StopMoving(); + target->CastSpell(target, SPELL_DARKFIEND_VISUAL, true); + target->DespawnOrUnsummon(3000); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_dark_fiend_skin_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dark_fiend_skin_AuraScript(); + } +}; + +class spell_transform_visual_missile_periodic : public SpellScriptLoader +{ + public: + spell_transform_visual_missile_periodic() : SpellScriptLoader("spell_transform_visual_missile_periodic") { } + + class spell_transform_visual_missile_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_transform_visual_missile_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_transform_visual_missile_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_transform_visual_missile_periodic_AuraScript(); + } +}; + +class spell_summon_blood_elves_periodic : public SpellScriptLoader +{ + public: + spell_summon_blood_elves_periodic() : SpellScriptLoader("spell_summon_blood_elves_periodic") { } + + class spell_summon_blood_elves_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summon_blood_elves_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_blood_elves_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summon_blood_elves_periodic_AuraScript(); + } }; void AddSC_boss_muru() @@ -600,4 +736,9 @@ void AddSC_boss_muru() new npc_dark_fiend(); new npc_void_sentinel(); new npc_blackhole(); + new spell_summon_blood_elves_script(); + new spell_muru_darkness(); + new spell_dark_fiend_skin(); + new spell_transform_visual_missile_periodic(); + new spell_summon_blood_elves_periodic(); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h index c6b4ae753a5..7ea0fc4bc7d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -97,7 +97,8 @@ enum CreatureIds NPC_FURY_MAGE = 25799, NPC_VOID_SENTINEL = 25772, NPC_VOID_SPAWN = 25824, - NPC_BLACK_HOLE = 25855 + NPC_BLACK_HOLE = 25855, + NPC_MURU_PORTAL_TARGET = 25770 }; enum GameObjectIds |