From 1ec85e3212abe2d490b2ef8015b2af442d28ae6d Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Mon, 12 Aug 2019 21:00:53 +0200 Subject: [PATCH] Scripts/VP: reworked Grandvizier Ertan encounter * optimized code * updated code to new scripting model * updated texts with broadcast text entries * fixed some visual threat issues caused by Ertan's Vortex by hitting players with their damage spell --- .../custom/custom_2019_08_12_00_world.sql | 33 ++ .../boss_grand_vizier_ertan.cpp | 431 ++++++++---------- .../instance_vortex_pinnacle.cpp | 6 +- .../VortexPinnacle/vortex_pinnacle.cpp | 2 +- .../Kalimdor/VortexPinnacle/vortex_pinnacle.h | 12 +- 5 files changed, 227 insertions(+), 257 deletions(-) create mode 100644 sql/updates/world/custom/custom_2019_08_12_00_world.sql diff --git a/sql/updates/world/custom/custom_2019_08_12_00_world.sql b/sql/updates/world/custom/custom_2019_08_12_00_world.sql new file mode 100644 index 00000000000..76d7451c6e2 --- /dev/null +++ b/sql/updates/world/custom/custom_2019_08_12_00_world.sql @@ -0,0 +1,33 @@ +UPDATE `creature_template` SET `ScriptName`= 'npc_ertan_ertans_vortex' WHERE `entry`= 46007; + +DELETE FROM `creature_template_addon` WHERE `entry`= 46007; +INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES +(46007, '86267'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_storms_edge_script', +'spell_storms_edge', +'spell_ertan_storms_edge', +'spell_ertan_storms_edge_script'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(86284, 'spell_ertan_storms_edge'), +(86311, 'spell_ertan_storms_edge'), +(86299, 'spell_ertan_storms_edge_script'); + +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (43878, 43879); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Flight`, `Swim`, `Rooted`) VALUES +(43878, 0, 1, 0, 1), +(43879, 0, 1, 0, 1); + +DELETE FROM `spell_custom_attr` WHERE `entry` IN (86299, 86309, 93992); +INSERT INTO `spell_custom_attr` (`entry`, `attributes`) VALUES +(86299, 0x00000010), +(86309, 0x00000010), +(93992, 0x00000010); + +DELETE FROM `creature_text` WHERE `CreatureID` IN (43878, 45704); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES +(43878, 0, 0, 'Filthy beasts! Your presence in Skywall will not be tolerated!', 14, 0, 100, 0, 0, 20876, 49570, 'Grandvizier Ertan - Aggro'), +(43878, 1, 0, '%s retracts her cyclone shield!', 41, 0, 100, 0, 0, 0, 47800, 'Grandvizier Ertan - Announce Storms Edge'), +(45704, 0, 0, '%s realizes it''s been spotted and quickly plays dead!', 16, 0, 100, 0, 0, 0, 46485, 'Lurking Tempest'); diff --git a/src/server/scripts/Kalimdor/VortexPinnacle/boss_grand_vizier_ertan.cpp b/src/server/scripts/Kalimdor/VortexPinnacle/boss_grand_vizier_ertan.cpp index 3667279dace..e59792ea64e 100644 --- a/src/server/scripts/Kalimdor/VortexPinnacle/boss_grand_vizier_ertan.cpp +++ b/src/server/scripts/Kalimdor/VortexPinnacle/boss_grand_vizier_ertan.cpp @@ -25,64 +25,52 @@ enum Spells { - SPELL_STORMS_EDGE_AURA = 86295, + // Grandvizier Ertan + SPELL_STORMS_EDGE_PERIODIC = 86295, SPELL_LIGHTNING_BOLT = 86331, SPELL_SUMMON_TEMPEST = 86340, SPELL_STORMS_EDGE_VISUAL = 86329, - SPELL_STORMS_EDGE_CYCLONE_SHIELD_AURA = 86310, // periodically triggers 86311 - - // Ertan's Vortex - SPELL_CYCLONE_SHIELD = 86267, - SPELL_CYCLONE_SHIELD_TRIGGER = 86292, - - SPELL_STORMS_EDGE_SCRIPT = 86299, // targets closest cyclone and makes it cast SPELL_STORMS_EDGE_DAMAGE on caster - // SPELL_STORMS_EDGE_DAMAGE = 86309, -}; - -enum NPCs -{ - NPC_ERTANS_VORTEX = 46007, + SPELL_STORMS_EDGE_PERIODIC_2 = 86310, + SPELL_STORMS_EDGE_TRIGGERED_1 = 86284, + SPELL_STORMS_EDGE_SCRIPT = 86299 }; enum Texts { - SAY_AGGRO = 0, - SAY_STORMS_EDGE = 1, -}; - -enum Actions -{ - ACTION_STORMS_EDGE = 1, + // Grand Vizier Ertan + SAY_AGGRO = 0, + SAY_ANNOUNCE_STORMS_EDGE = 1 }; enum Events { - EVENT_NONE, - EVENT_SUMMON_TEMPEST, - EVENT_STORMS_EDGE_SPAWN, + // Grandvizier Ertan + EVENT_SUMMON_TEMPEST = 1, EVENT_STORMS_EDGE, EVENT_STORMS_EDGE_AURA, - EVENT_STORMS_EDGE_END, + EVENT_END_STORMS_EDGE, + EVENT_LIGHTNING_BOLT, // Ertan's Vortex - EVENT_MOVE_POINT, + EVENT_MOVE_POINT +}; + +enum Actions +{ + // Ertan's Vortex + ACTION_STORMS_EDGE = 1 }; enum Points { - POINT_ERTANS_VORTEX_S = 0, - POINT_ERTANS_VORTEX_SW = 1, - POINT_ERTANS_VORTEX_W = 2, - POINT_ERTANS_VORTEX_NW = 3, - POINT_ERTANS_VORTEX_N = 4, - POINT_ERTANS_VORTEX_NE = 5, - POINT_ERTANS_VORTEX_E = 6, - POINT_ERTANS_VORTEX_SE = 7, - POINT_ERTANS_VORTEX_MAX = 8, - POINT_NONE, + // Ertan's Vortex + POINT_NONE = 0, + POINT_ROTATE = 1 }; -const Position ErtansVortexPoints[POINT_ERTANS_VORTEX_MAX] = +#define MAX_VORTEX_POINTS 8 + +const Position ErtansVortexPoints[MAX_VORTEX_POINTS] = { { -744.889f, 3.98611f, 635.6728f }, // South { -737.552f, 21.592f, 635.6728f }, // South-West @@ -94,7 +82,7 @@ const Position ErtansVortexPoints[POINT_ERTANS_VORTEX_MAX] = { -737.649f, -13.5347f, 635.6728f }, // South-East }; -const Position ErtansVortexMiddlePoints[POINT_ERTANS_VORTEX_MAX] = +const Position ErtansVortexMiddlePoints[MAX_VORTEX_POINTS] = { { -724.3819f, 2.915083f, 635.6728f }, // South { -724.0161f, 6.648534f, 635.6728f }, // South-West @@ -106,247 +94,192 @@ const Position ErtansVortexMiddlePoints[POINT_ERTANS_VORTEX_MAX] = { -721.9816f, -0.05864143f, 635.6728f }, // South-East }; -class boss_grand_vizier_ertan : public CreatureScript +struct boss_grand_vizier_ertan : public BossAI { - public: - boss_grand_vizier_ertan() : CreatureScript("boss_grand_vizier_ertan") { } + boss_grand_vizier_ertan(Creature* creature) : BossAI(creature, DATA_GRAND_VIZIER_ERTAN) { } - struct boss_grand_vizier_ertanAI : public BossAI - { - boss_grand_vizier_ertanAI(Creature* creature) : BossAI(creature, DATA_GRAND_VIZIER_ERTAN) - { - me->SetDisableGravity(true); - SetCombatMovement(false); - } - - void JustEngagedWith(Unit* /*target*/) override - { - _JustEngagedWith(); - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - - SummonErtansVortexes(); - DoCast(me, SPELL_STORMS_EDGE_AURA); - Talk(SAY_AGGRO); - - events.ScheduleEvent(EVENT_STORMS_EDGE_SPAWN, 400); - events.ScheduleEvent(EVENT_STORMS_EDGE, 23000); - if (IsHeroic()) - events.ScheduleEvent(EVENT_SUMMON_TEMPEST, 17000); - } - - void EnterEvadeMode(EvadeReason /*why*/) override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - summons.DespawnAll(); - _EnterEvadeMode(); - _DespawnAtEvade(); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - _JustDied(); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SUMMON_TEMPEST: - DoCast(me, SPELL_SUMMON_TEMPEST); - events.ScheduleEvent(EVENT_SUMMON_TEMPEST, 17000); - break; - case EVENT_STORMS_EDGE: - { - DoCast(me, SPELL_STORMS_EDGE_VISUAL); - EntryCheckPredicate pred(NPC_ERTANS_VORTEX); - summons.DoAction(ACTION_STORMS_EDGE, pred, 8); - Talk(SAY_STORMS_EDGE); - events.ScheduleEvent(EVENT_STORMS_EDGE_AURA, 3000); - events.ScheduleEvent(EVENT_STORMS_EDGE, 32000); - break; - } - case EVENT_STORMS_EDGE_AURA: - me->RemoveAurasDueToSpell(SPELL_STORMS_EDGE_AURA); - DoCast(me, SPELL_STORMS_EDGE_CYCLONE_SHIELD_AURA); - events.ScheduleEvent(EVENT_STORMS_EDGE_END, 6000); - break; - case EVENT_STORMS_EDGE_END: - me->RemoveAurasDueToSpell(SPELL_STORMS_EDGE_CYCLONE_SHIELD_AURA); - DoCast(me, SPELL_STORMS_EDGE_AURA); - break; - default: - break; - } - } - - DoSpellAttackIfReady(SPELL_LIGHTNING_BOLT); - } - - private: - void SummonErtansVortexes() // Summons Ertan's Vortex at each point and makes them move to the next point - { - for (int8 i = 0; i < POINT_ERTANS_VORTEX_MAX; i++) - { - if (Creature* ertansVortex = me->SummonCreature(NPC_ERTANS_VORTEX, ErtansVortexPoints[i])) - { - if (i == POINT_ERTANS_VORTEX_SE) - ertansVortex->GetMotionMaster()->MovePoint(POINT_ERTANS_VORTEX_S, ErtansVortexPoints[POINT_ERTANS_VORTEX_S]); - else - ertansVortex->GetMotionMaster()->MovePoint(i + 1, ErtansVortexPoints[i + 1]); - } - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetVortexPinnacleAI(creature); - } -}; - -// 46007 - Ertan's Vortex -class npc_ertans_vortex : public CreatureScript -{ -public: - npc_ertans_vortex() : CreatureScript("npc_ertans_vortex") { } - - struct npc_ertans_vortexAI : public PassiveAI + void JustEngagedWith(Unit* /*target*/) override { - npc_ertans_vortexAI(Creature* creature) : PassiveAI(creature) - { - Initialize(); - } + _JustEngagedWith(); + DoCastSelf(SPELL_STORMS_EDGE_PERIODIC); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + Talk(SAY_AGGRO); - void Initialize() - { - _currentPointId = 0; - } + for (uint8 i = 0; i < MAX_VORTEX_POINTS; i++) + if (Creature * ertansVortex = me->SummonCreature(NPC_ERTANS_VORTEX, ErtansVortexPoints[i])) + ertansVortex->GetMotionMaster()->MovePoint(POINT_ROTATE + i, ErtansVortexPoints[i + 1 < MAX_VORTEX_POINTS ? i + 1 : 0]); - void IsSummonedBy(Unit* /*summoner*/) override - { - DoCast(me, SPELL_CYCLONE_SHIELD, true); - } + events.ScheduleEvent(EVENT_STORMS_EDGE, 24s); + events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 1ms); + if (IsHeroic()) + events.ScheduleEvent(EVENT_SUMMON_TEMPEST, 16s, 17s); + } - void DoAction(int32 action) override - { - if (action == ACTION_STORMS_EDGE) - { - me->GetMotionMaster()->MovePoint(POINT_NONE, ErtansVortexMiddlePoints[_currentPointId]); - events.ScheduleEvent(EVENT_MOVE_POINT, 9000); - } - } - - void MovementInform(uint32 movementType, uint32 pointId) override - { - if (movementType != POINT_MOTION_TYPE || pointId == POINT_NONE) - return; - - if (pointId < POINT_ERTANS_VORTEX_SE) - _currentPointId = pointId + 1; - else - _currentPointId = POINT_ERTANS_VORTEX_S; - - events.ScheduleEvent(EVENT_MOVE_POINT, 1); - }; - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_MOVE_POINT: - me->GetMotionMaster()->MovePoint(_currentPointId, ErtansVortexPoints[_currentPointId]); - break; - default: - break; - } - } - } - - private: - EventMap events; - uint32 _currentPointId; - }; - - CreatureAI* GetAI(Creature* creature) const override + void EnterEvadeMode(EvadeReason /*why*/) override { - return GetVortexPinnacleAI(creature); + _EnterEvadeMode(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + summons.DespawnAll(); + _DespawnAtEvade(); + } + + void JustDied(Unit* /*killer*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + _JustDied(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SUMMON_TEMPEST: + DoCast(me, SPELL_SUMMON_TEMPEST); + events.Repeat(17s); + break; + case EVENT_STORMS_EDGE: + { + Talk(SAY_ANNOUNCE_STORMS_EDGE); + DoCastSelf(SPELL_STORMS_EDGE_VISUAL); + EntryCheckPredicate pred(NPC_ERTANS_VORTEX); + summons.DoAction(ACTION_STORMS_EDGE, pred, 8); + events.ScheduleEvent(EVENT_STORMS_EDGE_AURA, 3s); + events.Repeat(31s); + break; + } + case EVENT_STORMS_EDGE_AURA: + me->RemoveAurasDueToSpell(SPELL_STORMS_EDGE_PERIODIC); + DoCastSelf(SPELL_STORMS_EDGE_PERIODIC_2); + events.ScheduleEvent(EVENT_END_STORMS_EDGE, 6s); + break; + case EVENT_END_STORMS_EDGE: + me->RemoveAurasDueToSpell(SPELL_STORMS_EDGE_PERIODIC_2); + DoCastSelf(SPELL_STORMS_EDGE_PERIODIC); + break; + case EVENT_LIGHTNING_BOLT: + DoCastVictim(SPELL_LIGHTNING_BOLT); + events.Repeat(2s + 400ms); + break; + default: + break; + } + } } }; -// 86284 - Storm's Edge (targets players outside cyclone ring/further than 25 yards and makes them cast 86299) -// 86311 - Storm's Edge (targets all players and makes them cast 86299) -class spell_storms_edge : public SpellScriptLoader +struct npc_ertan_ertans_vortex : public NullCreatureAI { -public: - spell_storms_edge() : SpellScriptLoader("spell_storms_edge") { } + npc_ertan_ertans_vortex(Creature* creature) : NullCreatureAI(creature), _nextPointId(0) { } - class spell_storms_edge_SpellScript : public SpellScript + void DoAction(int32 action) override { - PrepareSpellScript(spell_storms_edge_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) + switch (action) { - GetHitUnit()->CastSpell(GetHitUnit(), SPELL_STORMS_EDGE_SCRIPT, true); + case ACTION_STORMS_EDGE: + me->GetMotionMaster()->MovePoint(POINT_NONE, ErtansVortexMiddlePoints[_nextPointId]); + _events.ScheduleEvent(EVENT_MOVE_POINT, 9s); + break; + default: + break; } + } - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_storms_edge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } + void MovementInform(uint32 movementType, uint32 pointId) override + { + if (movementType != POINT_MOTION_TYPE || pointId == POINT_NONE) + return; + + _nextPointId = pointId < MAX_VORTEX_POINTS ? pointId : 0; + _events.ScheduleEvent(EVENT_MOVE_POINT, 1ms); }; - SpellScript* GetSpellScript() const override + void UpdateAI(uint32 diff) override { - return new spell_storms_edge_SpellScript(); + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_POINT: + me->GetMotionMaster()->MovePoint(_nextPointId + 1, ErtansVortexPoints[_nextPointId]); + break; + default: + break; + } + } + } + +private: + EventMap _events; + uint32 _nextPointId; +}; + +class spell_ertan_storms_edge : public SpellScript +{ + PrepareSpellScript(spell_ertan_storms_edge); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_STORMS_EDGE_TRIGGERED_1, + SPELL_STORMS_EDGE_SCRIPT + }); + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + Unit* target = GetHitUnit(); + Unit* caster = GetCaster(); + if (!caster) + return; + + if (GetSpellInfo()->Id == SPELL_STORMS_EDGE_TRIGGERED_1) + { + if (caster->GetExactDist2d(target) > GetEffectValue()) + target->CastSpell(target, SPELL_STORMS_EDGE_SCRIPT, true); + } + else + target->CastSpell(target, SPELL_STORMS_EDGE_SCRIPT, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ertan_storms_edge::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; -// 86299 - Storm's Edge (targets closest Ertan's Vortex and makes it cast 86309 on caster) -class spell_storms_edge_script : public SpellScriptLoader +class spell_ertan_storms_edge_script : public SpellScript { -public: - spell_storms_edge_script() : SpellScriptLoader("spell_storms_edge_script") { } + PrepareSpellScript(spell_ertan_storms_edge_script); - class spell_storms_edge_script_SpellScript : public SpellScript + void HandleScript(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_storms_edge_script_SpellScript); + if (Unit* caster = GetCaster()) + GetHitUnit()->CastSpell(caster, uint32(GetEffectValue()), true); + } - void HandleScript(SpellEffIndex /*effIndex*/) - { - GetHitUnit()->CastSpell(GetCaster(), uint32(GetEffectValue()), true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_storms_edge_script_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_storms_edge_script_SpellScript(); + OnEffectHitTarget += SpellEffectFn(spell_ertan_storms_edge_script::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; void AddSC_boss_grand_vizier_ertan() { - new boss_grand_vizier_ertan(); - new npc_ertans_vortex(); - new spell_storms_edge(); - new spell_storms_edge_script(); + RegisterVortexPinnacleCreatureAI(boss_grand_vizier_ertan); + RegisterVortexPinnacleCreatureAI(npc_ertan_ertans_vortex); + RegisterSpellScript(spell_ertan_storms_edge); + RegisterSpellScript(spell_ertan_storms_edge_script); } diff --git a/src/server/scripts/Kalimdor/VortexPinnacle/instance_vortex_pinnacle.cpp b/src/server/scripts/Kalimdor/VortexPinnacle/instance_vortex_pinnacle.cpp index f934efca11a..9487bbf0256 100644 --- a/src/server/scripts/Kalimdor/VortexPinnacle/instance_vortex_pinnacle.cpp +++ b/src/server/scripts/Kalimdor/VortexPinnacle/instance_vortex_pinnacle.cpp @@ -85,9 +85,9 @@ Position const SecondPrismGroundingFieldPoints[PrismGroundingFieldPoints] = ObjectData const creatureData[] = { - { NPC_GRAND_VIZIER_ERTAN, DATA_GRAND_VIZIER_ERTAN }, - { NPC_ALTAIRUS, DATA_ALTAIRUS }, - { NPC_ASAAD, DATA_ASAAD }, + { BOSS_GRAND_VIZIER_ERTAN, DATA_GRAND_VIZIER_ERTAN }, + { BOSS_ALTAIRUS, DATA_ALTAIRUS }, + { BOSS_ASAAD, DATA_ASAAD }, { 0, 0 } // END }; diff --git a/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.cpp b/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.cpp index e111bbe5d84..bedbb2fa559 100644 --- a/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.cpp +++ b/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.cpp @@ -145,7 +145,7 @@ public: void IsSummonedBy(Unit* summoner) override { if (Creature* creature = summoner->ToCreature()) - ertan = (creature->GetEntry() == NPC_GRAND_VIZIER_ERTAN); + ertan = (creature->GetEntry() == BOSS_GRAND_VIZIER_ERTAN); } void MoveInLineOfSight(Unit* who) override diff --git a/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.h b/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.h index 7203d4eba53..cc9508db138 100644 --- a/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.h +++ b/src/server/scripts/Kalimdor/VortexPinnacle/vortex_pinnacle.h @@ -48,12 +48,16 @@ enum DataTypes DATA_SLIPSTREAM_11, }; -enum Misc +enum VPCreatureIds { // Bosses - NPC_GRAND_VIZIER_ERTAN = 43878, - NPC_ALTAIRUS = 43873, - NPC_ASAAD = 43875, + BOSS_GRAND_VIZIER_ERTAN = 43878, + BOSS_ALTAIRUS = 43873, + BOSS_ASAAD = 43875, + + // Encounter Related Data + /*Grandvizier Ertan*/ + NPC_ERTANS_VORTEX = 46007, NPC_INVISIBLE_STALKER = 42844, NPC_AIR_CURRENT = 47305,