diff options
| author | offl <11556157+offl@users.noreply.github.com> | 2025-11-08 17:20:20 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-08 16:20:20 +0100 |
| commit | 806a44526d3787ec5c9bb9931f46947d29c0cd6f (patch) | |
| tree | a3ef30657fda744f9f85e5408df17dd97156616a | |
| parent | d1a2f20b56aebc220b48560dfcd0e6bb72e90f7e (diff) | |
Scripts/Sunwell Plateau: Rewrite M'uru (#31323)
4 files changed, 745 insertions, 309 deletions
diff --git a/sql/updates/world/3.3.5/2025_11_08_00_world.sql b/sql/updates/world/3.3.5/2025_11_08_00_world.sql new file mode 100644 index 00000000000..fabacf921c0 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_11_08_00_world.sql @@ -0,0 +1,35 @@ +-- +UPDATE `creature_template_movement` SET `Rooted` = 1 WHERE `CreatureId` = 25741; + +UPDATE `spell_script_names` SET `ScriptName` = 'spell_muru_summon_blood_elves_periodic' WHERE `ScriptName` = 'spell_summon_blood_elves_periodic'; +UPDATE `spell_script_names` SET `ScriptName` = 'spell_muru_summon_blood_elves_script' WHERE `ScriptName` = 'spell_summon_blood_elves_script'; +UPDATE `spell_script_names` SET `ScriptName` = 'spell_muru_dark_fiend_magic' WHERE `ScriptName` = 'spell_dark_fiend_skin'; +UPDATE `spell_script_names` SET `ScriptName` = 'spell_muru_transform_visual_missile_periodic' WHERE `ScriptName` = 'spell_transform_visual_missile_periodic'; + +UPDATE `spell_target_position` SET `PositionX` = 1723.2922, `PositionY` = 712.71094, `PositionZ` = 71.190320 WHERE `ID` = 46037; +UPDATE `spell_target_position` SET `PositionX` = 1728.3705, `PositionY` = 707.41840, `PositionZ` = 71.190315 WHERE `ID` = 46038; +UPDATE `spell_target_position` SET `PositionX` = 1905.3964, `PositionY` = 548.84240, `PositionZ` = 71.304535 WHERE `ID` = 46039; +UPDATE `spell_target_position` SET `PositionX` = 1908.0374, `PositionY` = 547.56110, `PositionZ` = 71.310750 WHERE `ID` = 46040; + +UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_void_spawn' WHERE `entry` = 25824; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25824 AND `source_type` = 0; + +UPDATE `creature_template` SET `ScriptName` = 'npc_darkness' WHERE `entry` = 25879; + +UPDATE `creature_template` SET `ScriptName` = 'npc_singularity' WHERE `entry` = 25855; + +UPDATE `creature_template` SET `ScriptName` = 'npc_void_sentinel_summoner' WHERE `entry` = 25782; + +UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_shadowsword_berserker' WHERE `entry` = 25798; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25798 AND `source_type` = 0; + +UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_shadowsword_fury_mage' WHERE `entry` = 25799; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 25799 AND `source_type` = 0; + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (46228,46242,46262); + +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_muru_summon_void_sentinel_summoner'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(45978, 'spell_muru_summon_void_sentinel_summoner'); + +UPDATE `creature_template` SET `speed_run` = 0.428571 WHERE `entry` = 25744; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 44c339f8310..0d0c98871ed 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -15,166 +15,327 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* + * Combat timers requires to be revisited + * Singularity may be much trickier: + 1. Check if singularity should change targets + 2. Check if despawn timer depends on how much targets singularity hits by passive spells + * Check if Dark Fiend should change target + * Berserk for Entropius should be triggered from Entropius' AI since M'uru originally despawns after summoning Entropius, + NYI, currently triggered from M'uru's AI + */ + #include "ScriptMgr.h" #include "InstanceScript.h" -#include "ObjectAccessor.h" +#include "MotionMaster.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" #include "SpellAuras.h" +#include "SpellInfo.h" #include "SpellScript.h" #include "sunwell_plateau.h" -enum Spells +enum MuruSpells { - // Muru's spells + // M'uru - Initial 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, + + // M'uru - Combat + SPELL_BERSERK = 26662, + + // M'uru - Transition 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 + // Entropius - Initial SPELL_ENTROPIUS_COSMETIC_SPAWN = 46223, - SPELL_DARKNESS_E = 46269, SPELL_NEGATIVE_ENERGY_PERIODIC_E = 46284, - SPELL_NEGATIVE_ENERGY_DAMAGE = 46285, - SPELL_BLACKHOLE = 46282, - SPELL_SUMMON_DARKFIEND_E = 46263, - // Myruu's Portal Target + // Entropius - Combat + SPELL_DARKNESS = 46269, + SPELL_BLACK_HOLE = 46282, + + // M'uru Portal Target + SPELL_OPEN_PORTAL = 45976, + SPELL_OPEN_PORTAL_VISUAL = 45977, 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, - //Dark Fiend Spells - SPELL_DARKFIEND_DAMAGE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, + // Void Sentinel Summoner + SPELL_SUMMON_VOID_SENTINEL = 45988, - // Void Sentinel's spells + // Void Sentinel SPELL_SHADOW_PULSE_PERIODIC = 46086, SPELL_VOID_BLAST = 46161, + SPELL_SUMMON_VOID_SPAWN = 46071, + + // Void Spawn + SPELL_SHADOW_BOLT_VOLLEY = 46082, + + // Dark Fiend + SPELL_DARK_FIEND_MAGIC = 45934, + SPELL_DARK_FIEND_VISUAL = 45936, + SPELL_DARK_FIEND_TRAP = 45943, + SPELL_DARK_FIEND_DAMAGE = 45944, + + // Darkness + SPELL_VOID_ZONE_PRE_EFFECT_VISUAL = 46265, + SPELL_VOID_ZONE_PERIODIC = 46262, + SPELL_SUMMON_DARK_FIEND = 46263, + + // Singularity + SPELL_BLACK_HOLE_SUMMON_VISUAL = 46242, + SPELL_BLACK_HOLE_SUMMON_VISUAL_2 = 46247, + SPELL_BLACK_HOLE_PASSIVE = 46228, + SPELL_BLACK_HOLE_VISUAL_2 = 46235, + + // Shadowsword Berserker + SPELL_DUAL_WIELD_PASSIVE = 42459, + SPELL_FLURRY = 46160, + + // Shadowsword Fury Mage + SPELL_FEL_FIREBALL = 46101, + SPELL_SPELL_FURY = 46102, + + // Scripts + SPELL_SUMMON_BLOOD_ELVES_SCRIPT = 46050, + + SPELL_SUMMON_BERSERKER_1 = 46037, + SPELL_SUMMON_BERSERKER_2 = 46040, + SPELL_SUMMON_FURY_MAGE_1 = 46038, + SPELL_SUMMON_FURY_MAGE_2 = 46039, - //Black Hole Spells - SPELL_BLACKHOLE_SUMMON_VISUAL = 46242, - SPELL_BLACKHOLE_SUMMON_VISUAL_2 = 46247, - SPELL_BLACKHOLE_PASSIVE = 46228, - SPELL_BLACK_HOLE_VISUAL_2 = 46235 + SPELL_SUMMON_DARK_FIEND_1 = 46000, + SPELL_SUMMON_DARK_FIEND_2 = 46001, + SPELL_SUMMON_DARK_FIEND_3 = 46002, + SPELL_SUMMON_DARK_FIEND_4 = 46003, + SPELL_SUMMON_DARK_FIEND_5 = 46004, + SPELL_SUMMON_DARK_FIEND_6 = 46005, + SPELL_SUMMON_DARK_FIEND_7 = 46006, + SPELL_SUMMON_DARK_FIEND_8 = 46007, + + SPELL_TRANSFORM_VISUAL_MISSILE_1 = 46178, + SPELL_TRANSFORM_VISUAL_MISSILE_2 = 46208, + + SPELL_NEGATIVE_ENERGY_DAMAGE = 46285 }; -enum Phases +enum MuruEvents { - PHASE_ONE = 1, - PHASE_TWO = 2 + // M'uru + EVENT_SUMMON_BLOOD_ELVES = 1, + EVENT_SUMMON_ENTROPIUS, + EVENT_SET_INVISIBLE, + EVENT_BERSERK, + + // Entropius + EVENT_SPAWN_1, + EVENT_SPAWN_2, + EVENT_DARKNESS, + EVENT_BLACK_HOLE }; -enum Misc +enum MuruMisc { + ACTION_BERSERK = 0, + ACTION_DISPELLED_MAGIC = 1, + ACTION_CANCEL_SUMMON = 2, MAX_VOID_SPAWNS = 6, - MAX_SUMMON_BLOOD_ELVES = 4, - MAX_SUMMON_DARK_FIEND = 8 + NPC_WORLD_TRIGGER_MOVE_TO = 22515, + POINT_ROOM = 0 }; -uint32 const SummonDarkFiendSpells[MAX_SUMMON_DARK_FIEND] = +static constexpr std::array<uint32, 8> SummonDarkFiendSpells = { - 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 + SPELL_SUMMON_DARK_FIEND_7, + SPELL_SUMMON_DARK_FIEND_8 }; -uint32 const SummonBloodElvesSpells[MAX_SUMMON_BLOOD_ELVES] = +void DoResetPortals(Creature* creature) { - SPELL_SUMMON_BERSERKER, - SPELL_SUMMON_BERSERKER_2, - SPELL_SUMMON_FURY_MAGE, - SPELL_SUMMON_FURY_MAGE_2 -}; + std::vector<Creature*> portals; + GetCreatureListWithEntryInGrid(portals, creature, NPC_MURU_PORTAL_TARGET, 100.0f); + for (Creature* portal : portals) + portal->RemoveAllAuras(); +} + +void DoDespawnSummons(Creature* creature) +{ + std::vector<Creature*> spawns; + GetCreatureListWithEntryInGrid(spawns, creature, NPC_ENTROPIUS, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_VOID_SENTINEL_SUMMONER, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_VOID_SENTINEL, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_VOID_SPAWN, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_DARK_FIEND, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_DARKNESS, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_SINGULARITY, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_BERSERKER, 250.0f); + GetCreatureListWithEntryInGrid(spawns, creature, NPC_FURY_MAGE, 250.0f); + for (Creature* spawn : spawns) + spawn->DespawnOrUnsummon(); + + std::vector<Creature*> portals; + GetCreatureListWithEntryInGrid(portals, creature, NPC_MURU_PORTAL_TARGET, 100.0f); + for (Creature* portal : portals) + portal->AI()->DoAction(ACTION_CANCEL_SUMMON); +} -class VoidSpawnSummon : public BasicEvent +// 25741 - M'uru +struct boss_muru : public BossAI { - public: - explicit VoidSpawnSummon(Creature* owner) - : _owner(owner) + boss_muru(Creature* creature) : BossAI(creature, DATA_MURU), _isBerserkTriggered(false), _isInTransition(false) { } + + void Reset() override + { + _Reset(); + + _isBerserkTriggered = false; + _isInTransition = false; + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + + DoCastSelf(SPELL_OPEN_PORTAL_PERIODIC); + DoCastSelf(SPELL_DARKNESS_PERIODIC); + DoCastSelf(SPELL_NEGATIVE_ENERGY_PERIODIC); + + me->SetReactState(REACT_PASSIVE); + + events.ScheduleEvent(EVENT_SUMMON_BLOOD_ELVES, 5s); + events.ScheduleEvent(EVENT_BERSERK, 10min); + } + + void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override + { + if (damage >= me->GetHealth()) { + damage = me->GetHealth() - 1; + + if (_isInTransition) + return; + + _isInTransition = true; + me->RemoveAurasDueToSpell(SPELL_SUMMON_BLOOD_ELVES_PERIODIC); + me->RemoveAurasDueToSpell(SPELL_NEGATIVE_ENERGY_PERIODIC); + me->RemoveAurasDueToSpell(SPELL_DARKNESS_PERIODIC); + me->RemoveAurasDueToSpell(SPELL_OPEN_PORTAL_PERIODIC); + DoCastSelf(SPELL_OPEN_ALL_PORTALS); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + events.CancelEvent(EVENT_SUMMON_BLOOD_ELVES); + events.ScheduleEvent(EVENT_SUMMON_ENTROPIUS, 6s); } + } + + void OnSpellCast(SpellInfo const* spell) override + { + if (spell->Id == SPELL_SUMMON_ENTROPIUS) + /// @todo: Temporarily replaced with SetVisible. Otherwise we will be not able to respawn M'uru in case of wipe + /// me->DespawnOrUnsummon(1500ms); + events.ScheduleEvent(EVENT_SET_INVISIBLE, 1500ms); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + DoResetPortals(me); + DoDespawnSummons(me); + _DespawnAtEvade(); + } + + // Do not store anything, despawn is handled in DoDespawnSummons + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_ENTROPIUS) + if (_isBerserkTriggered) + summon->AI()->DoAction(ACTION_BERSERK); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); - bool Execute(uint64 /*time*/, uint32 /*diff*/) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - _owner->CastSpell(nullptr, SPELL_SUMMON_VOID_SENTINEL, true); - return true; + switch (eventId) + { + case EVENT_SUMMON_BLOOD_ELVES: + DoCastSelf(SPELL_SUMMON_BLOOD_ELVES_PERIODIC); + break; + case EVENT_SUMMON_ENTROPIUS: + DoCastSelf(SPELL_SUMMON_ENTROPIUS); + break; + case EVENT_SET_INVISIBLE: + me->SetVisible(false); + break; + case EVENT_BERSERK: + { + _isBerserkTriggered = true; + DoCastSelf(SPELL_BERSERK); + + if (Creature* entropius = instance->GetCreature(DATA_ENTROPIUS)) + entropius->AI()->DoAction(ACTION_BERSERK); + break; + } + default: + break; + } } + } - private: - Creature* _owner; +private: + bool _isBerserkTriggered; + bool _isInTransition; }; +// 25840 - Entropius struct boss_entropius : public BossAI { boss_entropius(Creature* creature) : BossAI(creature, DATA_MURU) { } - void Reset() override + void InitializeAI() override { - _Reset(); - DoCast(me, SPELL_ENTROPIUS_COSMETIC_SPAWN, true); + me->SetReactState(REACT_PASSIVE); } - void ScheduleTasks() override + void JustAppeared() override { - scheduler.Schedule(Milliseconds(2000), [this](TaskContext /*context*/) - { - DoResetPortals(); - DoCastAOE(SPELL_NEGATIVE_ENERGY_PERIODIC_E, true); - }); + DoCastSelf(SPELL_ENTROPIUS_COSMETIC_SPAWN); - scheduler.Schedule(Seconds(15), [this](TaskContext context) - { - DoCastAOE(SPELL_DARKNESS_E, true); - DoCastAOE(SPELL_BLACKHOLE, true); + events.ScheduleEvent(EVENT_SPAWN_1, 1500ms); + } - context.Repeat(); - }); + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + + events.ScheduleEvent(EVENT_DARKNESS, 10s, 15s); + events.ScheduleEvent(EVENT_BLACK_HOLE, 10s, 15s); } - void JustSummoned(Creature* summon) override + // Do not store anything, despawn is handled in DoDespawnSummons + void JustSummoned(Creature* /*summon*/) override { } + + void DoAction(int32 action) override { - switch (summon->GetEntry()) - { - case NPC_DARK_FIENDS: - summon->CastSpell(summon, SPELL_DARKFIEND_VISUAL); - break; - case NPC_DARKNESS: - summon->SetReactState(REACT_PASSIVE); - summon->CastSpell(summon, SPELL_BLACKHOLE); - summon->CastSpell(summon, SPELL_SUMMON_DARKFIEND_E, true); - break; - } - summons.Summon(summon); + if (action == ACTION_BERSERK) + DoCastSelf(SPELL_BERSERK); } void EnterEvadeMode(EvadeReason /*why*/) override @@ -182,8 +343,8 @@ struct boss_entropius : public BossAI if (Creature* muru = instance->GetCreature(DATA_MURU)) muru->AI()->EnterEvadeMode(); - DoResetPortals(); - summons.DespawnAll(); + DoResetPortals(me); + DoDespawnSummons(me); me->DespawnOrUnsummon(); } @@ -191,307 +352,394 @@ struct boss_entropius : public BossAI { _JustDied(); + DoDespawnSummons(me); + if (Creature* muru = instance->GetCreature(DATA_MURU)) muru->DisappearAndDie(); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) return; - scheduler.Update(diff, [this] + while (uint32 eventId = events.ExecuteEvent()) { - DoMeleeAttackIfReady(); - }); - } + switch (eventId) + { + case EVENT_SPAWN_1: + DoResetPortals(me); + events.ScheduleEvent(EVENT_SPAWN_2, 1500ms); + break; + case EVENT_SPAWN_2: + DoCastSelf(SPELL_NEGATIVE_ENERGY_PERIODIC_E); + DoZoneInCombat(); + me->SetReactState(REACT_AGGRESSIVE); + break; + case EVENT_DARKNESS: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true)) + DoCast(target, SPELL_DARKNESS); + events.Repeat(10s, 15s); + break; + case EVENT_BLACK_HOLE: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true)) + DoCast(target, SPELL_BLACK_HOLE); + events.Repeat(20s, 25s); + break; + default: + break; + } - void DoResetPortals() - { - std::list<Creature*> portals; - me->GetCreatureListWithEntryInGrid(portals, NPC_MURU_PORTAL_TARGET, 100.0f); - for (Creature* portal : portals) - portal->RemoveAllAuras(); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + if (UpdateVictim()) + DoMeleeAttackIfReady(); } }; -struct boss_muru : public BossAI +// 25770 - M'uru Portal Target +struct npc_muru_portal : public ScriptedAI { - boss_muru(Creature* creature) : BossAI(creature, DATA_MURU) + npc_muru_portal(Creature* creature) : ScriptedAI(creature) { } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override { - Initialize(); - SetCombatMovement(false); + switch (spellInfo->Id) + { + case SPELL_OPEN_PORTAL: + DoCastSelf(SPELL_OPEN_PORTAL_VISUAL); + _scheduler.Schedule(5s, [this](TaskContext /*task*/) + { + DoCastSelf(SPELL_SUMMON_VOID_SENTINEL_SUMMONER); + }); + break; + case SPELL_OPEN_ALL_PORTALS: + DoCastSelf(SPELL_OPEN_PORTAL_VISUAL); + _scheduler.Schedule(2s, [this](TaskContext /*task*/) + { + DoCastSelf(SPELL_TRANSFORM_VISUAL_MISSILE); + }); + break; + default: + break; + } } - void Initialize() + void JustSummoned(Creature* summon) override { - _hasEnraged = false; - _phase = PHASE_ONE; - _entropiusGUID.Clear(); + DoCast(summon, SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL); } - void Reset() override + void DoAction(int32 action) override { - _Reset(); - Initialize(); - me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); - me->SetVisible(true); + if (action == ACTION_CANCEL_SUMMON) + _scheduler.CancelAll(); } - void EnterEvadeMode(EvadeReason /*why*/) override + void UpdateAI(uint32 diff) override { - BossAI::EnterEvadeMode(); - if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) - entropius->AI()->EnterEvadeMode(); + _scheduler.Update(diff); } - 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; - }); +private: + TaskScheduler _scheduler; +}; - scheduler.Schedule(Seconds(10), [this](TaskContext /*context*/) +// 25782 - Void Sentinel Summoner +struct npc_void_sentinel_summoner : public ScriptedAI +{ + npc_void_sentinel_summoner(Creature* creature) : ScriptedAI(creature) { } + + void JustAppeared() override + { + _scheduler.Schedule(1500ms, [this](TaskContext /*task*/) { - DoCast(me, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); - DoCast(me, SPELL_SUMMON_BLOOD_ELVES_PERIODIC, true); + DoCastSelf(SPELL_SUMMON_VOID_SENTINEL); + me->DespawnOrUnsummon(3500ms); }); } - void JustEngagedWith(Unit* who) override + void UpdateAI(uint32 diff) override { - BossAI::JustEngagedWith(who); - DoCast(me, SPELL_OPEN_PORTAL_PERIODIC, true); - DoCast(me, SPELL_DARKNESS_PERIODIC, true); - DoCast(me, SPELL_NEGATIVE_ENERGY_PERIODIC, true); + _scheduler.Update(diff); } - void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override +private: + TaskScheduler _scheduler; +}; + +// 25772 - Void Sentinel +struct npc_void_sentinel : public ScriptedAI +{ + npc_void_sentinel(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override { - if (damage >= me->GetHealth()) - { - damage = me->GetHealth() - 1; - if (_phase != PHASE_ONE) - return; + me->SetCorpseDelay(5, true); + me->SetReactState(REACT_PASSIVE); + } - _phase = PHASE_TWO; - me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS, true); - me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + void JustAppeared() override + { + DoCastSelf(SPELL_SHADOW_PULSE_PERIODIC); - scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) - { - DoCast(me, SPELL_SUMMON_ENTROPIUS, true); - }); - } + _scheduler.Schedule(2500ms, [this](TaskContext /*task*/) + { + DoZoneInCombat(); + me->SetReactState(REACT_AGGRESSIVE); + }); } - void JustSummoned(Creature* summon) override + void JustEngagedWith(Unit* /*who*/) override { - if (summon->GetEntry() == NPC_ENTROPIUS) + _scheduler.Schedule(10s, 15s, [this](TaskContext task) { - me->SetVisible(false); - _entropiusGUID = summon->GetGUID(); - DoZoneInCombat(summon); - if (_hasEnraged) - summon->CastSpell(summon, SPELL_ENRAGE, true); - return; - } - BossAI::JustSummoned(summon); + DoCastVictim(SPELL_VOID_BLAST); + task.Repeat(20s, 30s); + }); + } + + void JustDied(Unit* /*killer*/) override + { + for (uint8 i = 0; i < MAX_VOID_SPAWNS; ++i) + DoCastSelf(SPELL_SUMMON_VOID_SPAWN); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) - return; + _scheduler.Update(diff); - scheduler.Update(diff); + if (UpdateVictim()) + DoMeleeAttackIfReady(); } private: - ObjectGuid _entropiusGUID; - bool _hasEnraged; - uint8 _phase; + TaskScheduler _scheduler; }; -struct npc_muru_portal : public ScriptedAI +// 25824 - Void Spawn +struct npc_void_spawn : public ScriptedAI { - npc_muru_portal(Creature* creature) : ScriptedAI(creature) { } + npc_void_spawn(Creature* creature) : ScriptedAI(creature) { } - void JustSummoned(Creature* summon) override + void InitializeAI() override { - DoCast(summon, SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL, true); + me->SetCorpseDelay(5, true); + me->SetReactState(REACT_PASSIVE); + } - summon->m_Events.AddEvent(new VoidSpawnSummon(summon), summon->m_Events.CalculateTime(1500ms)); + void JustAppeared() override + { + _scheduler.Schedule(2s, [this](TaskContext /*task*/) + { + DoZoneInCombat(); + me->SetReactState(REACT_AGGRESSIVE); + }); } - void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + void JustEngagedWith(Unit* /*who*/) override { - switch (spellInfo->Id) + _scheduler.Schedule(10s, 20s, [this](TaskContext task) { - case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL, true); - DoCastAOE(SPELL_TRANSFORM_VISUAL_MISSILE, true); - break; - case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL, true); - _scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL_SUMMONER, true); - }); - break; - default: - break; - } + DoCastSelf(SPELL_SHADOW_BOLT_VOLLEY); + task.Repeat(20s, 30s); + }); } void UpdateAI(uint32 diff) override { _scheduler.Update(diff); + + if (UpdateVictim()) + DoMeleeAttackIfReady(); } private: TaskScheduler _scheduler; }; +// 25744 - Dark Fiend struct npc_dark_fiend : public ScriptedAI { - npc_dark_fiend(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - } + npc_dark_fiend(Creature* creature) : ScriptedAI(creature), _isKilled(false) { } - void Initialize() + void InitializeAI() override { me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); me->SetReactState(REACT_PASSIVE); - DoCast(me, SPELL_DARKFIEND_SKIN, true); + } - _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/) + void JustAppeared() override + { + DoCastSelf(SPELL_DARK_FIEND_MAGIC); + + _scheduler.Schedule(2s, [this](TaskContext /*task*/) { + DoZoneInCombat(); me->SetReactState(REACT_AGGRESSIVE); - me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + }); - if (Creature* _summoner = ObjectAccessor::GetCreature(*me, _summonerGUID)) - if (Unit* target = _summoner->AI()->SelectTarget(SelectTargetMethod::Random, 0)) - AttackStart(target); + _scheduler.Schedule(2s, [this](TaskContext task) + { + if (me->IsWithinDist(me->GetVictim(), 2.0f)) + DoCastVictim(SPELL_DARK_FIEND_TRAP); + else + task.Repeat(100ms); }); + } - _scheduler.Schedule(Seconds(3), [this](TaskContext context) + void SpellHitTarget(WorldObject* /*target*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_DARK_FIEND_TRAP) { - if (me->IsWithinDist(me->GetVictim(), 5.0f) && me->HasAura(SPELL_DARKFIEND_SKIN)) + _scheduler.Schedule(0s, [this](TaskContext task) { - DoCastAOE(SPELL_DARKFIEND_DAMAGE, false); - me->DisappearAndDie(); - } - - context.Repeat(Milliseconds(500)); - }); + switch (task.GetRepeatCounter()) + { + case 0: + me->RemoveAurasDueToSpell(SPELL_DARK_FIEND_MAGIC); + DoCastSelf(SPELL_DARK_FIEND_DAMAGE); + me->SetReactState(REACT_PASSIVE); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + task.Repeat(2500ms); + break; + case 1: + DoCastSelf(SPELL_DARK_FIEND_VISUAL); + me->DespawnOrUnsummon(3500ms); + break; + default: + break; + } + }); + } } - void IsSummonedBy(WorldObject* summoner) override + void DoAction(int32 action) override { - _summonerGUID = summoner->GetGUID(); + /// @todo: This part requires sniff verification + if (action == ACTION_DISPELLED_MAGIC) + { + me->SetReactState(REACT_PASSIVE); + DoCastSelf(SPELL_DARK_FIEND_VISUAL); + me->DespawnOrUnsummon(3s); + } } - bool CanAIAttack(Unit const* /*target*/) const override + void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override { - return me->HasAura(SPELL_DARKFIEND_SKIN); + if (damage >= me->GetHealth()) + { + damage = me->GetHealth() -1; + + if (!_isKilled) + { + _isKilled = true; + me->RemoveAurasDueToSpell(SPELL_DARK_FIEND_MAGIC); + DoCastSelf(SPELL_DARK_FIEND_VISUAL); + me->SetReactState(REACT_PASSIVE); + me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE); + me->DespawnOrUnsummon(4500ms); + } + } } void UpdateAI(uint32 diff) override { + UpdateVictim(); + _scheduler.Update(diff); } private: + bool _isKilled; TaskScheduler _scheduler; - ObjectGuid _summonerGUID; }; -struct npc_void_sentinel : public ScriptedAI +// 25879 - Darkness +struct npc_darkness : public ScriptedAI { - npc_void_sentinel(Creature* creature) : ScriptedAI(creature) - { - _instance = me->GetInstanceScript(); - } + npc_darkness(Creature* creature) : ScriptedAI(creature) { } - void IsSummonedBy(WorldObject* /*summoner*/) override + void InitializeAI() override { - if (Creature* muru = _instance->GetCreature(DATA_MURU)) - muru->AI()->JustSummoned(me); + me->SetReactState(REACT_PASSIVE); } - void JustEngagedWith(Unit* /*who*/) override + void JustAppeared() override { - DoCast(me, SPELL_SHADOW_PULSE_PERIODIC, true); - - _scheduler.Schedule(Seconds(45), [this](TaskContext context) + _scheduler.Schedule(1s, [this](TaskContext task) { - DoCastVictim(SPELL_VOID_BLAST, false); - - context.Repeat(); + switch (task.GetRepeatCounter()) + { + case 0: + DoCastSelf(SPELL_VOID_ZONE_PRE_EFFECT_VISUAL); + task.Repeat(3s); + break; + case 1: + me->RemoveAurasDueToSpell(SPELL_VOID_ZONE_PRE_EFFECT_VISUAL); + DoCastSelf(SPELL_VOID_ZONE_PERIODIC); + task.Repeat(2500ms); + break; + case 2: + DoCastSelf(SPELL_SUMMON_DARK_FIEND); + break; + default: + break; + } }); } - void JustDied(Unit* /*killer*/) override - { - for (uint8 i = 0; i < MAX_VOID_SPAWNS; ++i) - DoCastAOE(SPELL_SUMMON_VOID_SPAWN, true); - } - void UpdateAI(uint32 diff) override { - _scheduler.Update(diff, [this] - { - DoMeleeAttackIfReady(); - }); + _scheduler.Update(diff); } private: TaskScheduler _scheduler; - InstanceScript* _instance; }; -struct npc_blackhole : public ScriptedAI +// 25855 - Singularity +struct npc_singularity : public ScriptedAI { - npc_blackhole(Creature* creature) : ScriptedAI(creature) - { - _instance = creature->GetInstanceScript(); - } + npc_singularity(Creature* creature) : ScriptedAI(creature) { } - void Reset() override + void InitializeAI() override { me->SetReactState(REACT_PASSIVE); - DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); - - _scheduler.Schedule(Seconds(15), [this](TaskContext /*context*/) - { - me->DisappearAndDie(); - }); + } - _scheduler.Schedule(Seconds(1), [this](TaskContext context) + void JustAppeared() override + { + _scheduler.Schedule(1s, [this](TaskContext task) { - switch (context.GetRepeatCounter()) + switch (task.GetRepeatCounter()) { case 0: - 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)); + DoCastSelf(SPELL_BLACK_HOLE_SUMMON_VISUAL); + task.Repeat(1s); break; case 1: - DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); - context.Repeat(Seconds(2)); + DoCastSelf(SPELL_BLACK_HOLE_SUMMON_VISUAL_2); + task.Repeat(1s); break; case 2: - DoCast(SPELL_BLACKHOLE_PASSIVE); - DoCast(SPELL_BLACK_HOLE_VISUAL_2); + DoCastSelf(SPELL_BLACK_HOLE_SUMMON_VISUAL); + task.Repeat(2s); + break; + case 3: + me->RemoveAurasDueToSpell(SPELL_BLACK_HOLE_SUMMON_VISUAL_2); + DoCastSelf(SPELL_BLACK_HOLE_PASSIVE); + DoCastSelf(SPELL_BLACK_HOLE_VISUAL_2); + task.Repeat(1s); + break; + case 4: + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + me->DespawnOrUnsummon(15s); break; default: break; @@ -501,113 +749,256 @@ struct npc_blackhole : public ScriptedAI void UpdateAI(uint32 diff) override { + UpdateVictim(); + _scheduler.Update(diff); } private: TaskScheduler _scheduler; - InstanceScript* _instance; +}; + +struct ShadowswordBaseAI : public ScriptedAI +{ + ShadowswordBaseAI(Creature* creature) : ScriptedAI(creature) { } + + void InitializeAI() override + { + me->SetReactState(REACT_PASSIVE); + me->SetCorpseDelay(3, true); + } + + void JustAppeared() override + { + scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); + + if (Creature* trigger = me->FindNearestCreature(NPC_WORLD_TRIGGER_MOVE_TO, 120.0f)) + { + float x, y, z; + trigger->GetClosePoint(x, y, z, 0.0f, 3.0f, float(M_PI)); + me->GetMotionMaster()->MovePoint(POINT_ROOM, x, y, z); + } + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId == POINT_ROOM) + { + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); + } + } + + void JustEngagedWith(Unit* /*who*/) override + { + ScheduleEvents(); + } + + virtual void ScheduleEvents() = 0; + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff); + + DoMeleeAttackIfReady(); + } + +protected: + TaskScheduler scheduler; +}; + +// 25798 - Shadowsword Berserker +struct npc_shadowsword_berserker : public ShadowswordBaseAI +{ + npc_shadowsword_berserker(Creature* creature) : ShadowswordBaseAI(creature) { } + + void JustAppeared() override + { + DoCastSelf(SPELL_DUAL_WIELD_PASSIVE); + ShadowswordBaseAI::JustAppeared(); + } + + void ScheduleEvents() override + { + scheduler.Schedule(10s, 20s, [this](TaskContext task) + { + DoCastSelf(SPELL_FLURRY); + task.Repeat(15s, 25s); + }); + } +}; + +// 25799 - Shadowsword Fury Mage +struct npc_shadowsword_fury_mage : public ShadowswordBaseAI +{ + npc_shadowsword_fury_mage(Creature* creature) : ShadowswordBaseAI(creature) { } + + void ScheduleEvents() override + { + scheduler.Schedule(5s, 10s, [this](TaskContext task) + { + DoCastVictim(SPELL_FEL_FIREBALL); + task.Repeat(5s, 10s); + }); + + scheduler.Schedule(20s, 40s, [this](TaskContext task) + { + DoCastSelf(SPELL_SPELL_FURY); + task.Repeat(40s, 60s); + }); + } +}; + +// 46041 - Summon Blood Elves Periodic +class spell_muru_summon_blood_elves_periodic : public AuraScript +{ + PrepareAuraScript(spell_muru_summon_blood_elves_periodic); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SUMMON_BLOOD_ELVES_SCRIPT }); + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_BLOOD_ELVES_SCRIPT); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_BLOOD_ELVES_SCRIPT); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_muru_summon_blood_elves_periodic::AfterApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_muru_summon_blood_elves_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } }; // 46050 - Summon Blood Elves Script -class spell_summon_blood_elves_script : public SpellScript +class spell_muru_summon_blood_elves_script : public SpellScript { - PrepareSpellScript(spell_summon_blood_elves_script); + PrepareSpellScript(spell_muru_summon_blood_elves_script); - bool Validate(SpellInfo const* /*spell*/) override + bool Validate(SpellInfo const* /*spellInfo*/) override { - return ValidateSpellInfo(SummonBloodElvesSpells); + return ValidateSpellInfo( + { + SPELL_SUMMON_BERSERKER_1, + SPELL_SUMMON_BERSERKER_2, + SPELL_SUMMON_FURY_MAGE_1, + SPELL_SUMMON_FURY_MAGE_2 + }); } void HandleScript(SpellEffIndex /*effIndex*/) { - for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) - GetCaster()->CastSpell(nullptr, SummonBloodElvesSpells[urand(0,3)], true); + Unit* caster = GetCaster(); + caster->CastSpell(caster, SPELL_SUMMON_BERSERKER_1); + caster->CastSpell(caster, SPELL_SUMMON_BERSERKER_1); + caster->CastSpell(caster, SPELL_SUMMON_FURY_MAGE_1); + caster->CastSpell(caster, SPELL_SUMMON_FURY_MAGE_2); + caster->CastSpell(caster, SPELL_SUMMON_BERSERKER_2); + caster->CastSpell(caster, SPELL_SUMMON_BERSERKER_2); } void Register() override { - OnEffectHitTarget += SpellEffectFn(spell_summon_blood_elves_script::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHit += SpellEffectFn(spell_muru_summon_blood_elves_script::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; // 45996 - Darkness -class spell_muru_darkness : public SpellScript +class spell_muru_darkness : public AuraScript { - PrepareSpellScript(spell_muru_darkness); + PrepareAuraScript(spell_muru_darkness); - bool Validate(SpellInfo const* /*spell*/) override + bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo(SummonDarkFiendSpells); } - void HandleAfterCast() + void HandleEffectPeriodic(AuraEffect const* aurEff) { - for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) - GetCaster()->CastSpell(nullptr, SummonDarkFiendSpells[i], true); + if (aurEff->GetTickNumber() == 2) + { + Unit* target = GetTarget(); + for (uint32 SummonSpell : SummonDarkFiendSpells) + target->CastSpell(target, SummonSpell); + } } void Register() override { - AfterCast += SpellCastFn(spell_muru_darkness::HandleAfterCast); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_muru_darkness::HandleEffectPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY); } }; // 45934 - Dark Fiend -class spell_dark_fiend_skin : public AuraScript +class spell_muru_dark_fiend_magic : public AuraScript { - PrepareAuraScript(spell_dark_fiend_skin); + PrepareAuraScript(spell_muru_dark_fiend_magic); - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void AfterRemove(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(3s); - } + target->AI()->DoAction(ACTION_DISPELLED_MAGIC); } void Register() override { - AfterEffectRemove += AuraEffectRemoveFn(spell_dark_fiend_skin::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_muru_dark_fiend_magic::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; // 46205 - Transform Visual Missile Periodic -class spell_transform_visual_missile_periodic : public AuraScript +class spell_muru_transform_visual_missile_periodic : public AuraScript { - PrepareAuraScript(spell_transform_visual_missile_periodic); + PrepareAuraScript(spell_muru_transform_visual_missile_periodic); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_TRANSFORM_VISUAL_MISSILE_1, SPELL_TRANSFORM_VISUAL_MISSILE_2 }); + } void OnPeriodic(AuraEffect const* /*aurEff*/) { - GetTarget()->CastSpell(nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true); + GetTarget()->CastSpell(nullptr, RAND(SPELL_TRANSFORM_VISUAL_MISSILE_1, SPELL_TRANSFORM_VISUAL_MISSILE_2)); } void Register() override { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_transform_visual_missile_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_muru_transform_visual_missile_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; -// 46041 - Summon Blood Elves Periodic -class spell_summon_blood_elves_periodic : public AuraScript +// 45978 - Summon Void Sentinel Summoner +class spell_muru_summon_void_sentinel_summoner : public SpellScript { - PrepareAuraScript(spell_summon_blood_elves_periodic); + PrepareSpellScript(spell_muru_summon_void_sentinel_summoner); - void OnPeriodic(AuraEffect const* /*aurEff*/) + void SetDest(SpellDestination& dest) { - GetTarget()->CastSpell(nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + Unit* caster = GetCaster(); + dest._position.m_positionZ = caster->GetMapHeight(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); } void Register() override { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_blood_elves_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_muru_summon_void_sentinel_summoner::SetDest, EFFECT_0, TARGET_DEST_CASTER_FRONT); } }; @@ -662,14 +1053,20 @@ void AddSC_boss_muru() RegisterSunwellPlateauCreatureAI(boss_muru); RegisterSunwellPlateauCreatureAI(boss_entropius); RegisterSunwellPlateauCreatureAI(npc_muru_portal); - RegisterSunwellPlateauCreatureAI(npc_dark_fiend); + RegisterSunwellPlateauCreatureAI(npc_void_sentinel_summoner); RegisterSunwellPlateauCreatureAI(npc_void_sentinel); - RegisterSunwellPlateauCreatureAI(npc_blackhole); - RegisterSpellScript(spell_summon_blood_elves_script); + RegisterSunwellPlateauCreatureAI(npc_void_spawn); + RegisterSunwellPlateauCreatureAI(npc_dark_fiend); + RegisterSunwellPlateauCreatureAI(npc_darkness); + RegisterSunwellPlateauCreatureAI(npc_singularity); + RegisterSunwellPlateauCreatureAI(npc_shadowsword_berserker); + RegisterSunwellPlateauCreatureAI(npc_shadowsword_fury_mage); + RegisterSpellScript(spell_muru_summon_blood_elves_periodic); + RegisterSpellScript(spell_muru_summon_blood_elves_script); RegisterSpellScript(spell_muru_darkness); - RegisterSpellScript(spell_dark_fiend_skin); - RegisterSpellScript(spell_transform_visual_missile_periodic); - RegisterSpellScript(spell_summon_blood_elves_periodic); + RegisterSpellScript(spell_muru_dark_fiend_magic); + RegisterSpellScript(spell_muru_transform_visual_missile_periodic); + RegisterSpellScript(spell_muru_summon_void_sentinel_summoner); RegisterSpellScript(spell_muru_negative_energy_periodic); RegisterSpellScript(spell_muru_negative_energy); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp index 248480c65ff..ac4c33e8f7e 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp @@ -56,6 +56,7 @@ ObjectData const creatureData[] = { NPC_GRAND_WARLOCK_ALYTHESS, DATA_ALYTHESS }, { NPC_LADY_SACROLASH, DATA_SACROLASH }, { NPC_MURU, DATA_MURU }, + { NPC_ENTROPIUS, DATA_ENTROPIUS }, { NPC_KILJAEDEN, DATA_KILJAEDEN }, { NPC_KILJAEDEN_CONTROLLER, DATA_KILJAEDEN_CONTROLLER }, { NPC_ANVEENA, DATA_ANVEENA }, diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h index 7dfc6e55329..28946c17e98 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -45,6 +45,7 @@ enum SWPDataTypes DATA_KILJAEDEN_CONTROLLER, DATA_ANVEENA, DATA_KALECGOS_KJ, + DATA_ENTROPIUS, // GameObject GUIDs DATA_ORB_OF_THE_BLUE_DRAGONFLIGHT_1, @@ -99,13 +100,15 @@ enum SWPCreatureIds NPC_SPIKE_TARGET2 = 30614, NPC_SINISTER_REFLECTION = 25708, // Sinister Relection spawnd on Phase swichtes + // M'uru + NPC_VOID_SENTINEL_SUMMONER = 25782, + NPC_VOID_SENTINEL = 25772, + NPC_VOID_SPAWN = 25824, + NPC_DARK_FIEND = 25744, NPC_DARKNESS = 25879, - NPC_DARK_FIENDS = 25744, + NPC_SINGULARITY = 25855, NPC_BERSERKER = 25798, NPC_FURY_MAGE = 25799, - NPC_VOID_SENTINEL = 25772, - NPC_VOID_SPAWN = 25824, - NPC_BLACK_HOLE = 25855, NPC_MURU_PORTAL_TARGET = 25770 }; |
