diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp | 306 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_generic.cpp | 19 |
2 files changed, 156 insertions, 169 deletions
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp index 1c209c21aec..0604e9e62db 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp @@ -15,109 +15,88 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* -Name: Boss_Grandmaster_Vorpil -%Complete: 100 -Category: Auchindoun, Shadow Labyrinth -*/ - #include "ScriptMgr.h" #include "InstanceScript.h" -#include "Map.h" #include "MotionMaster.h" #include "ObjectAccessor.h" -#include "Player.h" #include "ScriptedCreature.h" #include "shadow_labyrinth.h" -#include "TemporarySummon.h" -enum GrandmasterVorpil +enum Texts { - SAY_INTRO = 0, - SAY_AGGRO = 1, - SAY_HELP = 2, - SAY_SLAY = 3, - SAY_DEATH = 4, - - SPELL_RAIN_OF_FIRE = 33617, - H_SPELL_RAIN_OF_FIRE = 39363, - - SPELL_DRAW_SHADOWS = 33563, - SPELL_SHADOWBOLT_VOLLEY = 33841, - SPELL_BANISH = 38791, - - NPC_VOID_TRAVELER = 19226, - SPELL_SUMMON_VOID_TRAVELER_A = 33582, - SPELL_SUMMON_VOID_TRAVELER_B = 33583, - SPELL_SUMMON_VOID_TRAVELER_C = 33584, - SPELL_SUMMON_VOID_TRAVELER_D = 33585, - SPELL_SUMMON_VOID_TRAVELER_E = 33586, - - SPELL_SACRIFICE = 33587, - SPELL_SHADOW_NOVA = 33846, - SPELL_EMPOWERING_SHADOWS = 33783, - - NPC_VOID_PORTAL = 19224, - SPELL_SUMMON_PORTAL = 33566, - SPELL_VOID_PORTAL_VISUAL = 33569 + SAY_HELP = 0, + SAY_AGGRO = 1, + SAY_SLAY = 2, + SAY_DEATH = 3, + SAY_DRAW = 4, + SAY_WIPE = 5 }; -Position const VorpilPosition = { -252.8820f, -264.3030f, 17.1f, 0.0f }; - -float VoidPortalCoords[5][3] = +enum Spells { - {-283.5894f, -239.5718f, 12.7f}, - {-306.5853f, -258.4539f, 12.7f}, - {-295.8789f, -269.0899f, 12.7f}, - {-209.3401f, -262.7564f, 17.1f}, - {-261.4533f, -297.3298f, 17.1f} + SPELL_SHADOWBOLT_VOLLEY = 33841, + SPELL_BANISH = 38791, + SPELL_DRAW_SHADOWS = 33563, + SPELL_RAIN_OF_FIRE = 33617, + + SPELL_SUMMON_VOID_PORTAL_A = 33566, + SPELL_SUMMON_VOID_PORTAL_B = 33614, + SPELL_SUMMON_VOID_PORTAL_C = 33615, + SPELL_SUMMON_VOID_PORTAL_D = 33567, + SPELL_SUMMON_VOID_PORTAL_E = 33616, + SPELL_SUMMON_VOID_SUMMONER = 33927, + + SPELL_DESPAWN_VOID_PORTALS = 33568, + SPELL_GREAT_SACRIFICE = 33618, + + // Voidwalker Summoner + SPELL_SUMMON_VOIDWALKER_A = 33582, + SPELL_SUMMON_VOIDWALKER_B = 33583, + SPELL_SUMMON_VOIDWALKER_C = 33584, + SPELL_SUMMON_VOIDWALKER_D = 33585, + SPELL_SUMMON_VOIDWALKER_E = 33586, + + // Void Traveler + SPELL_SACRIFICE = 33587, + SPELL_SHADOW_NOVA = 33846, + SPELL_EMPOWERING_SHADOWS = 33783, + SPELL_INSTAKILL_SELF = 29878 }; enum Events { - EVENT_SHADOWBOLT_VOLLEY = 1, - EVENT_BANISH = 2, - EVENT_DRAW_SHADOWS = 3, - EVENT_SUMMON_TRAVELER = 4 + EVENT_HELP = 1, + EVENT_SHADOWBOLT_VOLLEY, + EVENT_BANISH, + EVENT_DRAW_SHADOWS, + EVENT_RAIN_OF_FIRE }; -struct boss_grandmaster_vorpil : public BossAI +std::array<uint32, 5> const VoidwalkerSummonSpells = { - boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL) - { - Initialize(); - _intro = false; - } - - void Initialize() - { - _helpYell = false; - } + SPELL_SUMMON_VOIDWALKER_A, SPELL_SUMMON_VOIDWALKER_B, SPELL_SUMMON_VOIDWALKER_C, SPELL_SUMMON_VOIDWALKER_D, SPELL_SUMMON_VOIDWALKER_E +}; - void Reset() override - { - _Reset(); - Initialize(); - } +struct boss_grandmaster_vorpil : public BossAI +{ + boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL) { } - void SummonPortals() + void JustEngagedWith(Unit* who) override { - for (uint8 i = 0; i < 5; ++i) - if (Creature* portal = me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 50min)) - portal->CastSpell(portal, SPELL_VOID_PORTAL_VISUAL, true); - - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5s); - } + BossAI::JustEngagedWith(who); + events.ScheduleEvent(EVENT_HELP, 6s); + events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 10s, 15s); + if (IsHeroic()) + events.ScheduleEvent(EVENT_BANISH, 10s, 20s); + events.ScheduleEvent(EVENT_DRAW_SHADOWS, 35s, 45s); - void spawnVoidTraveler() - { - uint8 pos = urand(0, 4); - me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5s); - if (!_helpYell) - { - Talk(SAY_HELP); - _helpYell = true; - } + Talk(SAY_AGGRO); + DoCastSelf(SPELL_SUMMON_VOID_PORTAL_A); + DoCastSelf(SPELL_SUMMON_VOID_PORTAL_B); + DoCastSelf(SPELL_SUMMON_VOID_PORTAL_C); + DoCastSelf(SPELL_SUMMON_VOID_PORTAL_D); + DoCastSelf(SPELL_SUMMON_VOID_PORTAL_E); + DoCastSelf(SPELL_SUMMON_VOID_SUMMONER); } void KilledUnit(Unit* who) override @@ -126,34 +105,23 @@ struct boss_grandmaster_vorpil : public BossAI Talk(SAY_SLAY); } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } + // Despawn is handled by spells, don't store anything + void JustSummoned(Creature* /*summon*/) override { } - void JustEngagedWith(Unit* who) override + void EnterEvadeMode(EvadeReason why) override { - BossAI::JustEngagedWith(who); - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 7s, 14s); - if (IsHeroic()) - events.ScheduleEvent(EVENT_BANISH, 15s); - events.ScheduleEvent(EVENT_DRAW_SHADOWS, 45s); - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 90s); - - Talk(SAY_AGGRO); - SummonPortals(); + Talk(SAY_WIPE); + DoCastSelf(SPELL_DESPAWN_VOID_PORTALS, true); + DoCastSelf(SPELL_GREAT_SACRIFICE, true); + ScriptedAI::EnterEvadeMode(why); } - void MoveInLineOfSight(Unit* who) override + void JustDied(Unit* /*killer*/) override { - BossAI::MoveInLineOfSight(who); - - if (!_intro && me->IsWithinLOSInMap(who) && me->IsWithinDistInMap(who, 100) && me->IsValidAttackTarget(who)) - { - Talk(SAY_INTRO); - _intro = true; - } + _JustDied(); + Talk(SAY_DEATH); + DoCastSelf(SPELL_DESPAWN_VOID_PORTALS, true); + DoCastSelf(SPELL_GREAT_SACRIFICE, true); } void UpdateAI(uint32 diff) override @@ -170,36 +138,27 @@ struct boss_grandmaster_vorpil : public BossAI { switch (eventId) { + case EVENT_HELP: + Talk(SAY_HELP); + break; case EVENT_SHADOWBOLT_VOLLEY: - DoCast(me, SPELL_SHADOWBOLT_VOLLEY); - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 15s, 30s); + DoCastSelf(SPELL_SHADOWBOLT_VOLLEY); + events.Repeat(10s, 25s); break; case EVENT_BANISH: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30.0f, false)) - DoCast(target, SPELL_BANISH); - events.ScheduleEvent(EVENT_BANISH, 15s); + DoCast(target, SPELL_BANISH); + events.Repeat(20s, 30s); break; case EVENT_DRAW_SHADOWS: - { - instance->instance->DoOnPlayers([this](Player* player) - { - if (player->IsAlive() && !player->HasAura(SPELL_BANISH)) - player->TeleportTo(me->GetMapId(), VorpilPosition.GetPositionX(), VorpilPosition.GetPositionY(), VorpilPosition.GetPositionZ(), VorpilPosition.GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT); - }); - - me->UpdatePosition(VorpilPosition); - DoCast(me, SPELL_DRAW_SHADOWS, true); - DoCast(me, SPELL_RAIN_OF_FIRE); - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 6s); - events.ScheduleEvent(EVENT_DRAW_SHADOWS, 30s); - break; - } - case EVENT_SUMMON_TRAVELER: - spawnVoidTraveler(); - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10s); - // enrage at 20% - if (HealthBelowPct(20)) - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5s); + if (roll_chance_i(50)) + Talk(SAY_DRAW); + DoCastSelf(SPELL_DRAW_SHADOWS); + events.Repeat(35s, 45s); + events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 1s); + break; + case EVENT_RAIN_OF_FIRE: + DoCastSelf(SPELL_RAIN_OF_FIRE); break; } @@ -209,70 +168,79 @@ struct boss_grandmaster_vorpil : public BossAI DoMeleeAttackIfReady(); } - - private: - bool _intro; - bool _helpYell; }; -struct npc_voidtraveler : public ScriptedAI +struct npc_voidwalker_summoner : public ScriptedAI { - npc_voidtraveler(Creature* creature) : ScriptedAI(creature) + npc_voidwalker_summoner(Creature* creature) : ScriptedAI(creature) { } + + void JustAppeared() override { - Initialize(); - _instance = creature->GetInstanceScript(); + _scheduler.Schedule(10s, [this](TaskContext task) + { + DoCastSelf(Trinity::Containers::SelectRandomContainerElement(VoidwalkerSummonSpells)); + task.Repeat(10s, 15s); + }); } - void Initialize() + void UpdateAI(uint32 diff) override { - _moveTimer = 0; - _sacrificed = false; + _scheduler.Update(diff); } - void Reset() override +private: + TaskScheduler _scheduler; +}; + +struct npc_void_traveler : public ScriptedAI +{ + npc_void_traveler(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void InitializeAI() override { - Initialize(); + me->SetReactState(REACT_PASSIVE); } - void JustEngagedWith(Unit* /*who*/) override { } - - void UpdateAI(uint32 diff) override + // This part needs more work + void JustAppeared() override { - if (_moveTimer <= diff) - { - Creature* Vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL)); - if (!Vorpil) - return; + if (Creature* vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL))) + me->GetMotionMaster()->MoveFollow(vorpil, 0, 0); - if (_sacrificed) - { - DoCastAOE(SPELL_EMPOWERING_SHADOWS, true); - DoCast(me, SPELL_SHADOW_NOVA, true); - me->KillSelf(); - return; - } - me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0); - if (me->IsWithinDist(Vorpil, 3)) + _scheduler.Schedule(500ms, [this](TaskContext task) + { + if (Creature* vorpil = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_GRANDMASTER_VORPIL))) { - DoCast(me, SPELL_SACRIFICE, false); - _sacrificed = true; - _moveTimer = 500; - return; + if (me->IsWithinDist(vorpil, 3)) + { + DoCastSelf(SPELL_SACRIFICE); + + task.Schedule(1s, [this](TaskContext /*task*/) + { + DoCastSelf(SPELL_EMPOWERING_SHADOWS); + DoCastSelf(SPELL_SHADOW_NOVA); + DoCastSelf(SPELL_INSTAKILL_SELF); + }); + } + else + task.Repeat(); } - _moveTimer = 1000; - } - else - _moveTimer -= diff; + }); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } private: + TaskScheduler _scheduler; InstanceScript* _instance; - uint32 _moveTimer; - bool _sacrificed; }; void AddSC_boss_grandmaster_vorpil() { RegisterShadowLabyrinthCreatureAI(boss_grandmaster_vorpil); - RegisterShadowLabyrinthCreatureAI(npc_voidtraveler); + RegisterShadowLabyrinthCreatureAI(npc_voidwalker_summoner); + RegisterShadowLabyrinthCreatureAI(npc_void_traveler); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 7f56fce52af..03e1cdf0a1b 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1276,6 +1276,7 @@ class spell_gen_despawn_aura : public AuraScript } }; +/// @todo: migrate spells to spell_gen_despawn_target, then remove this class spell_gen_despawn_self : public SpellScript { PrepareSpellScript(spell_gen_despawn_self); @@ -1297,6 +1298,23 @@ class spell_gen_despawn_self : public SpellScript } }; +class spell_gen_despawn_target : public SpellScript +{ + PrepareSpellScript(spell_gen_despawn_target); + + void HandleDespawn(SpellEffIndex /*effIndex*/) + { + if (GetEffectInfo().IsEffect(SPELL_EFFECT_DUMMY) || GetEffectInfo().IsEffect(SPELL_EFFECT_SCRIPT_EFFECT)) + if (Creature* target = GetHitCreature()) + target->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_despawn_target::HandleDespawn, EFFECT_ALL, SPELL_EFFECT_ANY); + } +}; + enum DivineStormSpell { SPELL_DIVINE_STORM = 53385, @@ -4863,6 +4881,7 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_defend); RegisterSpellScript(spell_gen_despawn_aura); RegisterSpellScript(spell_gen_despawn_self); + RegisterSpellScript(spell_gen_despawn_target); RegisterSpellScript(spell_gen_divine_storm_cd_reset); RegisterSpellScript(spell_gen_ds_flush_knockback); RegisterSpellScript(spell_gen_dungeon_credit); |