diff options
author | Wyrserth <wyrserth@protonmail.com> | 2019-07-07 02:32:53 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-12-14 22:13:56 +0100 |
commit | 569660a93320e45dc991a3c3d9858aba56a88c08 (patch) | |
tree | 51b0da39befe6b1d53aeb253175502167155878e /src | |
parent | 2efb6b618798b11f0c57a80661e04955ff63ed58 (diff) |
Script/TheOculus: adapt Mage-Lord Urom's script to use EventMap, fix various issues with Teleport and Empowered Arcane Explosion, add missing heroic-mode spell Frost Buffet.
Closes #19452.
(cherry picked from commit 37862942ce61ceffe5440d67efe7db553fa22f9b)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp | 299 |
1 files changed, 161 insertions, 138 deletions
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 3e8dac1693d..c1e6a515863 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -15,33 +15,37 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Urom -SD%Complete: 80 -SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. -SDCategory: Instance Script -EndScriptData */ - -#include "ScriptMgr.h" +#include "oculus.h" #include "Containers.h" +#include "Map.h" #include "MotionMaster.h" -#include "oculus.h" #include "ScriptedCreature.h" +#include "ScriptMgr.h" #include "SpellInfo.h" +#include "SpellScript.h" enum Spells { - SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. - SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, - SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, - SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. - SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. + SPELL_ARCANE_SHIELD = 53813, + SPELL_SUMMON_MENAGERIE = 50476, SPELL_SUMMON_MENAGERIE_2 = 50495, SPELL_SUMMON_MENAGERIE_3 = 50496, - SPELL_TELEPORT = 51112, //Teleports to the center of Oculus - SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. - SPELL_TIME_BOMB_2 = 59376, - SPELL_EVOCATE = 51602 // He always cast it on reset or after teleportation + SPELL_FROSTBOMB = 51103, + SPELL_TELEPORT = 51112, + SPELL_EVOCATE = 51602, + SPELL_FROST_BUFFET = 58025 +}; + +#define SPELL_EMPOWERED_ARCANE_EXPLOSION DUNGEON_MODE(51110, 59377) +#define SPELL_TIME_BOMB DUNGEON_MODE(51121, 59376) + +enum Events +{ + EVENT_FROST_BOMB = 1, + EVENT_TIME_BOMB, + EVENT_CAST_EXPLOSION, + EVENT_TELEPORT, + EVENT_TELEPORT_BACK }; enum Yells @@ -97,42 +101,53 @@ class boss_urom : public CreatureScript { boss_uromAI(Creature* creature) : BossAI(creature, DATA_UROM) { - Initialize(); - platform = 0; + _platform = 0; + _x = 0.0f; + _y = 0.0f; + _isInCenter = false; for (uint8 i = 0; i < 3; ++i) - group[i] = i; + _group[i] = i; - Trinity::Containers::RandomShuffle(group); + Trinity::Containers::RandomShuffle(_group); } - void Initialize() + void EnterEvadeMode(EvadeReason why) override { - x = 0.0f; - y = 0.0f; - canCast = false; - canGoBack = false; - - teleportTimer = urand(30000, 35000); - arcaneExplosionTimer = 9000; - castArcaneExplosionTimer = 2000; - frostBombTimer = urand(5000, 8000); - timeBombTimer = urand(20000, 25000); + // We can only evade if we're in the center platform + if (_platform > 2) + { + _EnterEvadeMode(why); + + // If we're in the center, teleport to start position + if (_isInCenter) + me->NearTeleportTo(1118.3101f, 1080.3800f, 508.3610f, 4.25f); + else + me->GetMotionMaster()->MoveTargetedHome(); + + Reset(); + events.Reset(); + } } void Reset() override { - me->CastSpell(me, SPELL_EVOCATE); - + _isInCenter = false; + me->SetControlled(false, UNIT_STATE_ROOT); + me->SetDisableGravity(false); + me->SetReactState(REACT_AGGRESSIVE); + DoCastSelf(SPELL_EVOCATE); _Reset(); + } - me->GetMotionMaster()->MoveIdle(); + void JustReachedHome() override + { + DoCastSelf(SPELL_EVOCATE); } void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); - StartAttack(); } @@ -152,20 +167,20 @@ class boss_urom : public CreatureScript switch (i) { case 0: - x = me->GetPositionX() + 4; - y = me->GetPositionY() - 4; + _x = me->GetPositionX() + 4; + _y = me->GetPositionY() - 4; break; case 1: - x = me->GetPositionX() + 4; - y = me->GetPositionY() + 4; + _x = me->GetPositionX() + 4; + _y = me->GetPositionY() + 4; break; case 2: - x = me->GetPositionX() - 4; - y = me->GetPositionY() + 4; + _x = me->GetPositionX() - 4; + _y = me->GetPositionY() + 4; break; case 3: - x = me->GetPositionX() - 4; - y = me->GetPositionY() - 4; + _x = me->GetPositionX() - 4; + _y = me->GetPositionY() - 4; break; default: break; @@ -174,23 +189,28 @@ class boss_urom : public CreatureScript void StartAttack() { - if (platform > 2) + // We're in center - start fight normally + if (_platform > 2) { + me->CastStop(); // Stop casting of Evocation Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_TELEPORT, 30s, 35s); + events.ScheduleEvent(EVENT_FROST_BOMB, 5s, 8s); + events.ScheduleEvent(EVENT_TIME_BOMB, 20s, 25s); return; } - // summon guards and jump to next platform + // We're on one of the three platforms - summon guards and jump to next platform for (uint8 i = 0; i < 4; ++i) { SetPosition(i); - me->SummonCreature(Group[group[platform]].entry[i], x, y, me->GetPositionZ(), me->GetOrientation()); + me->SummonCreature(Group[_group[_platform]].entry[i], _x, _y, me->GetPositionZ(), me->GetOrientation()); } - Talk(platform); - DoCast(TeleportSpells[platform]); + Talk(_platform); + DoCast(TeleportSpells[_platform]); - ++platform; + ++_platform; } void KilledUnit(Unit* who) override @@ -204,77 +224,59 @@ class boss_urom : public CreatureScript if (!UpdateVictim()) return; - if (platform < 3) + if (_platform < 3) return; events.Update(diff); - if (teleportTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->GetMotionMaster()->MoveIdle(); - DoCast(SPELL_TELEPORT); - teleportTimer = urand(30000, 35000); - } - else - teleportTimer -= diff; - - if (canCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) - { - if (castArcaneExplosionTimer <= diff) - { - canCast = false; - canGoBack = true; - DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); - castArcaneExplosionTimer = 2000; - } - else - castArcaneExplosionTimer -= diff; - } - - if (canGoBack) - { - if (arcaneExplosionTimer <= diff) - { - if (me->GetVictim()) - { - Position pos = me->EnsureVictim()->GetPosition(); - - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - } - me->SetWalk(true); - - Talk(EMOTE_ARCANE_EXPLOSION); - Talk(SAY_ARCANE_EXPLOSION); - - canCast = false; - canGoBack = false; - arcaneExplosionTimer = 9000; - } - else - arcaneExplosionTimer -= diff; - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (!me->IsNonMeleeSpellCast(false, true, true)) + while (uint32 eventId = events.ExecuteEvent()) { - if (frostBombTimer <= diff) + switch (eventId) { - DoCastVictim(SPELL_FROSTBOMB); - frostBombTimer = urand(5000, 8000); + case EVENT_TELEPORT: + events.DelayEvents(10s); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->StopMoving(); + me->SetDisableGravity(true); + me->SetCanFly(true); + me->SetControlled(true, UNIT_STATE_ROOT); // @hack: disabling gravity isn't enough to prevent falling + DoCast(SPELL_TELEPORT); + _isInCenter = true; + events.ScheduleEvent(EVENT_CAST_EXPLOSION, 2s); + break; + case EVENT_CAST_EXPLOSION: + Talk(EMOTE_ARCANE_EXPLOSION); + Talk(SAY_ARCANE_EXPLOSION); + DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); + events.ScheduleEvent(EVENT_TELEPORT_BACK, DUNGEON_MODE<uint32>(10000, 8000)); + break; + case EVENT_TELEPORT_BACK: + me->SetReactState(REACT_AGGRESSIVE); + me->SetDisableGravity(false); + me->SetCanFly(false); + me->SetControlled(false, UNIT_STATE_ROOT); + if (Unit* victim = me->SelectVictim()) + { + me->NearTeleportTo(victim->GetPosition()); + AttackStart(victim); + } + _isInCenter = false; + events.ScheduleEvent(EVENT_TELEPORT, 30s, 35s); + break; + case EVENT_FROST_BOMB: + DoCastVictim(SPELL_FROSTBOMB); + events.ScheduleEvent(EVENT_FROST_BOMB, 5s, 8s); + break; + case EVENT_TIME_BOMB: + if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(unit, SPELL_TIME_BOMB); + events.ScheduleEvent(EVENT_TIME_BOMB, 20s, 25s); + break; } - else - frostBombTimer -= diff; - - if (timeBombTimer <= diff) - { - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(unit, SPELL_TIME_BOMB); - - timeBombTimer = urand(20000, 25000); - } - else - timeBombTimer -= diff; } DoMeleeAttackIfReady(); @@ -284,7 +286,7 @@ class boss_urom : public CreatureScript { _JustDied(); Talk(SAY_DEATH); - DoCast(me, SPELL_DEATH_SPELL, true); // we cast the spell as triggered or the summon effect does not occur + DoCastSelf(SPELL_DEATH_SPELL, true); } void LeaveCombat() @@ -301,44 +303,41 @@ class boss_urom : public CreatureScript case SPELL_SUMMON_MENAGERIE: me->SetHomePosition(968.66f, 1042.53f, 527.32f, 0.077f); LeaveCombat(); - me->CastSpell(me, SPELL_EVOCATE); + DoCastSelf(SPELL_EVOCATE, true); break; case SPELL_SUMMON_MENAGERIE_2: me->SetHomePosition(1164.02f, 1170.85f, 527.321f, 3.66f); LeaveCombat(); - me->CastSpell(me, SPELL_EVOCATE); + DoCastSelf(SPELL_EVOCATE, true); break; case SPELL_SUMMON_MENAGERIE_3: me->SetHomePosition(1118.31f, 1080.377f, 508.361f, 4.25f); LeaveCombat(); - me->CastSpell(me, SPELL_EVOCATE); - break; - case SPELL_TELEPORT: - //! Unconfirmed, previous below - me->SetDisableGravity(true); - //me->AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); // with out it the npc will fall down while is casting - canCast = true; + DoCastSelf(SPELL_EVOCATE, true); break; default: break; } } - private: - float x, y; - - bool canCast; - bool canGoBack; - - uint8 platform; - - uint8 group[3]; + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + // If killed while in center, teleport to a valid ground position before dying + if (damage >= me->GetHealth()) + { + if (_isInCenter) + { + _isInCenter = false; + me->NearTeleportTo(1124.0432f, 1078.2109f, 508.3597f, 5.4623f); + } + } + } - uint32 teleportTimer; - uint32 arcaneExplosionTimer; - uint32 castArcaneExplosionTimer; - uint32 frostBombTimer; - uint32 timeBombTimer; + private: + float _x, _y; + bool _isInCenter; + uint8 _platform; + std::array<uint8, 3> _group; }; CreatureAI* GetAI(Creature* creature) const override @@ -347,7 +346,31 @@ class boss_urom : public CreatureScript } }; +class spell_urom_frostbomb : public AuraScript +{ + PrepareAuraScript(spell_urom_frostbomb); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_FROST_BUFFET }); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetMap()->IsHeroic() && caster->IsInCombat()) + if (Unit* target = GetTarget()) + caster->CastSpell(target, SPELL_FROST_BUFFET, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_urom_frostbomb::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE); + } +}; + void AddSC_boss_urom() { new boss_urom(); + RegisterAuraScript(spell_urom_frostbomb); } |