From fa07b45655a02bc1eb847cf20589baf35977deb6 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 13 Apr 2019 22:14:14 +0200 Subject: [PATCH] Scripts/BWD: more work on Magmaw encounter --- sql/updates/WIP/magmaw.sql | 57 ++- .../BlackwingDescent/blackwing_descent.h | 33 +- .../BlackwingDescent/boss_magmaw.cpp | 340 ++++++++++++++---- .../instance_blackwing_descent.cpp | 104 +++++- src/server/scripts/Spells/spell_generic.cpp | 41 +++ 5 files changed, 492 insertions(+), 83 deletions(-) diff --git a/sql/updates/WIP/magmaw.sql b/sql/updates/WIP/magmaw.sql index 3473981f984..41b4e678311 100644 --- a/sql/updates/WIP/magmaw.sql +++ b/sql/updates/WIP/magmaw.sql @@ -1,12 +1,15 @@ -- Magmaw -UPDATE `creature_template` SET `InhabitType`= 12, `ScriptName`= 'boss_magmaw' WHERE `entry`= 41570; -UPDATE `creature_template` SET `InhabitType`= 12 WHERE `entry` IN (51101, 51102, 51103); +UPDATE `creature_template` SET `ScriptName`= 'boss_magmaw' WHERE `entry`= 41570; +UPDATE `creature_template` SET `DamageModifier`= 120, `BaseVariance`= 0.5, `npcflag`= 0 WHERE `entry` IN (41570, 51101, 51102, 51103); -- Magmaw's Pincer -UPDATE `creature_template` SET `InhabitType`= 4 WHERE `entry` IN (41620, 41789); +UPDATE `creature_template` SET `spell1`= 77917 WHERE `entry`= 41620; +UPDATE `creature_template` SET `spell1`= 77941 WHERE `entry`= 41789; -- Pillar of Flame UPDATE `creature_template` SET `unit_flags`= 33587264, `unit_flags2`= 34816, `flags_extra`= 2 WHERE `entry`= 41843; -- Lava Parasite UPDATE `creature_template` SET `speed_run`= 0.3571, `speed_walk`= 1 WHERE `entry`= 41806; +-- Exposed Head of Magmaw +UPDATE `creature_template` SET `AIName`= '' WHERE `entry` IN (42347, 51248, 51249, 51250); -- Addons DELETE FROM `creature_template_addon` WHERE `entry` IN (41806); @@ -17,30 +20,66 @@ INSERT INTO `creature_template_addon` (`entry`, `auras`) VALUES DELETE FROM `vehicle_template_accessory` WHERE `entry`= 41570; -- Spellclicks -DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`= 41570; +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (41570, 51101, 51102, 51103); INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES -(41570, 77901, 1, 1); +(41570, 77901, 1, 0), +(51101, 77901, 1, 0), +(51102, 77901, 1, 0), +(51103, 77901, 1, 0); + +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (41570, 51101, 51102, 51103, 41620, 41789, 42347, 51248, 51249, 51250); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES +-- Magmaw +(41570, 1, 0, 1, 1), +(51101, 1, 0, 1, 1), +(51102, 1, 0, 1, 1), +(51103, 1, 0, 1, 1), +-- Magmaw's Pincer +(41620, 0, 0, 1, 0), +(41789, 0, 0, 1, 0), +-- Exposed Head of Magmaw +(42347, 0, 0, 1, 0), +(51248, 0, 0, 1, 0), +(51249, 0, 0, 1, 0), +(51250, 0, 0, 1, 0); -- Spells DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_magmaw_magma_spit', 'spell_magmaw_mangle', 'spell_magmaw_pillar_of_flame_dummy', -'spell_magmaw_pillar_of_flame_forcecast'); +'spell_magmaw_pillar_of_flame_forcecast', +'spell_magmaw_ride_vehicle', +'spell_magmaw_launch_hook'); + +DELETE FROM `spell_script_names` WHERE `ScriptName`= 'spell_gen_eject_passenger' AND `spell_id` IN (77946, 95204); +DELETE FROM `spell_script_names` WHERE `ScriptName`= 'spell_gen_eject_passenger_1' AND `spell_id`= 77946; +DELETE FROM `spell_script_names` WHERE `ScriptName`= 'spell_gen_eject_passenger_3' AND `spell_id`= 95204; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (95280, 'spell_magmaw_magma_spit'), (92047, 'spell_magmaw_mangle'), (78017, 'spell_magmaw_pillar_of_flame_dummy'), -(77998, 'spell_magmaw_pillar_of_flame_forcecast'); +(77998, 'spell_magmaw_pillar_of_flame_forcecast'), +(77901, 'spell_magmaw_ride_vehicle'), +(77946, 'spell_gen_eject_passenger_1'), +(95204, 'spell_gen_eject_passenger_3'), +(77917, 'spell_magmaw_launch_hook'), +(77941, 'spell_magmaw_launch_hook'); + -- Conditions -DELETE FROM `conditions` WHERE `SourceEntry` IN (89743, 78360, 78017, 78010); +DELETE FROM `conditions` WHERE `SourceEntry` IN (89743, 78360, 78017, 78010, 94996, 77917, 77941, 77940, 77929) AND `SourceTypeOrReferenceId`= 13; INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES (13, 1, 89743, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Ride Vehicle - Target Magmaw'), (13, 1, 78360, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Ride Vehicle - Target Magmaw'), (13, 2, 78017, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Pillar of Flame - Target Magmaw'), -(13, 1, 78010, 0, 0, 31, 0, 3, 41843, 0, 0, 0, '', 'Pillar of Flame - Target Pillar of Flame'); +(13, 1, 78010, 0, 0, 31, 0, 3, 41843, 0, 0, 0, '', 'Pillar of Flame - Target Pillar of Flame'), +(13, 1, 94996, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Ride Vehicle - Target Magmaw'), +(13, 1, 77917, 0, 0, 31, 0, 3, 41767, 0, 0, 0, '', 'Launch Hook - Target Magmaw Spike Stalker'), +(13, 1, 77941, 0, 0, 31, 0, 3, 41767, 0, 0, 0, '', 'Launch Hook - Target Magmaw Spike Stalker'), +(13, 1, 77940, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Chain Visual - Target Magmaw'), +(13, 1, 77929, 0, 0, 31, 0, 3, 41570, 0, 0, 0, '', 'Chain Visual - Target Magmaw'); -- Texts DELETE FROM `creature_text` WHERE `CreatureID` IN (41570); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h index fed40771b04..dec706cdcd4 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/blackwing_descent.h @@ -28,12 +28,15 @@ uint32 const EncounterCount = 6; enum BWDDataTypes { // Bosses - DATA_MAGMAW = 0, - DATA_OMNOTRON_DEFENSE_SYSTEM = 1, - DATA_CHIMAERON = 2, - DATA_ATRAMEDES = 3, - DATA_MALORIAK = 4, - DATA_NEFARIANS_END = 5 + DATA_MAGMAW = 0, + DATA_OMNOTRON_DEFENSE_SYSTEM = 1, + DATA_CHIMAERON = 2, + DATA_ATRAMEDES = 3, + DATA_MALORIAK = 4, + DATA_NEFARIANS_END = 5, + + // Encounter Data + DATA_PREPARE_MASSIVE_CRASH_AND_GET_TARGET_GUID }; enum BWDCreatureIds @@ -57,12 +60,30 @@ enum BWDCreatureIds NPC_EXPOSED_HEAD_OF_MAGMAW_2 = 48270, NPC_PILLAR_OF_FLAME = 41843, NPC_LAVA_PARASITE = 41806, + NPC_MASSIVE_CRASH = 47330, + NPC_ROOM_STALKER = 47196, + NPC_MAGMAW_SPIKE_STALKER = 41767, }; enum BWDGameObjectIds { }; +enum BWDMisc +{ + MASSIVE_CRASH_SIDE_LEFT = 0, + MASSIVE_CRASH_SIDE_RIGHT = 1 +}; + +enum BWDSpells +{ + // Room Stalker + SPELL_LIGHT_SHOW = 87949, + + // Massive Crash + SPELL_MASSIVE_CRASH_DAMAGE = 88287, +}; + template inline AI* GetBlackwingDescentAI(T* obj) { diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_magmaw.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_magmaw.cpp index 177e318dcb7..6c37fd5d554 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_magmaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/boss_magmaw.cpp @@ -36,24 +36,32 @@ enum Spells SPELL_MANGLE_1 = 89773, SPELL_MANGLE_2 = 78412, SPELL_MANGLE_TARGETING = 92047, + SPELL_SWELTERING_ARMOR = 78199, SPELL_PILLAR_OF_FLAME = 77998, SPELL_PILLAR_OF_FLAME_MISSILE_PERIODIC = 78006, - SPELL_MASSIVE_CRASH = 88253, - SPELL_MASSIVE_CRASH_DAMAGE = 88287, + SPELL_IMPALE_SELF = 77907, + SPELL_EJECT_PASSENGER_3 = 95204, // Exposed Head of Magmaw SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE = 79010, SPELL_POINT_OF_VULNERABILITY = 79011, SPELL_RIDE_VEHICLE_EXPOSED_HEAD = 89743, SPELL_QUEST_INVIS_5 = 95478, + SPELL_RIDE_VEHICLE_HEAD = 94996, // Pillar of Flame SPELL_PILLAR_OF_FLAME_DUMMY = 78017, SPELL_PILLAR_OF_FLAME_PERIODIC = 77970, - // Room Stalker - SPELL_LIGHT_SHOW = 87949, + // Magmaw's Pincer + SPELL_LAUNCH_HOOK_1 = 77917, + SPELL_LAUNCH_HOOK_2 = 77941, + SPELL_EJECT_PASSENGER_1 = 77946, + + // Magmaw Spike Stalker + SPELL_CHAIN_VISUAL_1 = 77940, + SPELL_CHAIN_VISUAL_2 = 77929, }; enum Events @@ -62,16 +70,28 @@ enum Events EVENT_MAGMA_PROJECTILE = 1, EVENT_LAVA_SPEW, EVENT_MANGLE, + EVENT_PREPARE_MASSIVE_CRASH, + EVENT_MASSIVE_CRASH, + EVENT_ANNOUNCE_PINCERS_EXPOSED, + EVENT_FINISH_MASSIVE_CRASH, + EVENT_IMPALE_SELF, + EVENT_EJECT_PASSENGER_1, + EVENT_EXPOSE_HEAD, + EVENT_HIDE_HEAD, + EVENT_FINISH_IMPALE_SELF, }; enum Actions { + ACTION_IMPALE_MAGMAW = 0 }; enum Texts { // Magmaw SAY_ANNOUNCE_LAVA_PARASITES = 0, + SAY_ANNOUNCE_EXPOSE_PINCERS = 1, + SAY_ANNOUNCE_EXPOSED_HEAD = 2 }; enum VehicleSeats @@ -82,31 +102,16 @@ enum VehicleSeats SEAT_EXPOSED_HEAD_OF_MAGMAW_2 = 4, }; -Position const ExposedHeadOfMagmawPos = { -299.0f, -28.9861f, 191.0293f, 4.118977f }; - -class DelayedSpellCastEvent : public BasicEvent +enum Data { - public: - DelayedSpellCastEvent(Unit* owner, ObjectGuid targetGUID, uint32 spellId, bool triggered = false) : - _owner(owner), _targetGUID(targetGUID), _spellId(spellId), _triggered(triggered) { } - - bool Execute(uint64 /*time*/, uint32 /*diff*/) override - { - if (Unit* target = ObjectAccessor::GetUnit(*_owner, _targetGUID)) - _owner->CastSpell(target, _spellId, _triggered); - return true; - } - - private: - Unit* _owner; - ObjectGuid _targetGUID; - uint32 _spellId; - bool _triggered; + DATA_FREE_PINCER = 0 }; +Position const ExposedHeadOfMagmawPos = { -299.0f, -28.9861f, 191.0293f, 4.118977f }; + struct boss_magmaw : public BossAI { - boss_magmaw(Creature* creature) : BossAI(creature, DATA_MAGMAW), vehicle(me->GetVehicleKit()) + boss_magmaw(Creature* creature) : BossAI(creature, DATA_MAGMAW), _vehicle(me->GetVehicleKit()) { Initialize(); } @@ -114,6 +119,12 @@ struct boss_magmaw : public BossAI void Initialize() { _magmaProjectileCount = 0; + _exposedHead1 = nullptr; + _exposedHead2 = nullptr; + _pincer1 = nullptr; + _pincer2 = nullptr; + _hasExposedHead = false; + _headEngaged = false; } void Reset() override @@ -134,16 +145,31 @@ struct boss_magmaw : public BossAI events.ScheduleEvent(EVENT_MAGMA_PROJECTILE, 5s, 6s); events.ScheduleEvent(EVENT_LAVA_SPEW, 19s); //events.ScheduleEvent(EVENT_MANGLE, 1min + 30s); + events.ScheduleEvent(EVENT_PREPARE_MASSIVE_CRASH, 10s); + + _exposedHead1->SetInCombatWithZone(); + _exposedHead2->SetInCombatWithZone(); } void EnterEvadeMode(EvadeReason /*why*/) override { _EnterEvadeMode(); instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (_headEngaged) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, _exposedHead1); + instance->SetData(DATA_MAGMAW, FAIL); summons.DespawnAll(); _DespawnAtEvade(); } + void JustDied(Unit* /*killer*/) override + { + if (_headEngaged) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, _exposedHead1); + _JustDied(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + } + void JustSummoned(Creature* summon) override { summons.Summon(summon); @@ -160,13 +186,78 @@ struct boss_magmaw : public BossAI } } + void SpellHit(Unit* caster, SpellInfo const* spell) override + { + switch (spell->Id) + { + case SPELL_MASSIVE_CRASH: + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_ENEMY_INTERACT); + _exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_HEAD, true); + events.ScheduleEvent(EVENT_ANNOUNCE_PINCERS_EXPOSED, 1s); + events.ScheduleEvent(EVENT_FINISH_MASSIVE_CRASH, 7s); + Unit* head = _exposedHead1; + head->m_Events.AddEventAtOffset([head]() + { + head->CastSpell(head, SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true); + }, 6s); + + break; + } + case SPELL_IMPALE_SELF: + DoCastSelf(SPELL_EJECT_PASSENGER_3); + Talk(SAY_ANNOUNCE_EXPOSED_HEAD); + me->RemoveAurasDueToSpell(SPELL_CHAIN_VISUAL_1); + me->RemoveAurasDueToSpell(SPELL_CHAIN_VISUAL_2); + events.ScheduleEvent(EVENT_HIDE_HEAD, 29s); + events.ScheduleEvent(EVENT_FINISH_IMPALE_SELF, 33s); + break; + default: + break; + } + } + void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override { if (!passenger) return; + } - if (passenger->GetEntry() == NPC_EXPOSED_HEAD_OF_MAGMAW) - passenger->SetFacingTo(me->GetOrientation()); + ObjectGuid GetGUID(int32 type) const override + { + switch (type) + { + case DATA_FREE_PINCER: + if (_pincer1->GetVehicleKit() && _pincer1->GetVehicleKit()->GetAvailableSeatCount()) + return _pincer1->GetGUID(); + else if (_pincer2->GetVehicleKit() && _pincer2->GetVehicleKit()->GetAvailableSeatCount()) + return _pincer2->GetGUID(); + default: + return ObjectGuid::Empty; + } + + return ObjectGuid::Empty; + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_IMPALE_MAGMAW: + events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + if (Creature* spikeStalker = me->FindNearestCreature(NPC_MAGMAW_SPIKE_STALKER, 50.0f)) + me->SetFacingToObject(spikeStalker); + events.ScheduleEvent(EVENT_IMPALE_SELF, 1s); + events.ScheduleEvent(EVENT_EJECT_PASSENGER_1, 2s + 300ms); + events.ScheduleEvent(EVENT_EXPOSE_HEAD, 4s + 700ms); + _hasExposedHead = true; + break; + default: + break; + } } void UpdateAI(uint32 diff) override @@ -176,7 +267,7 @@ struct boss_magmaw : public BossAI events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) + if (me->HasUnitState(UNIT_STATE_CASTING) && !_hasExposedHead) return; while (uint32 eventId = events.ExecuteEvent()) @@ -204,6 +295,56 @@ struct boss_magmaw : public BossAI case EVENT_MANGLE: DoCastAOE(SPELL_MANGLE_TARGETING); break; + case EVENT_PREPARE_MASSIVE_CRASH: + if (ObjectGuid guid = instance->GetGuidData(DATA_PREPARE_MASSIVE_CRASH_AND_GET_TARGET_GUID)) + { + if (Creature* stalker = ObjectAccessor::GetCreature(*me, guid)) + { + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->SetFacingToObject(stalker, true); + events.ScheduleEvent(EVENT_MASSIVE_CRASH, 5s); + } + } + break; + case EVENT_MASSIVE_CRASH: + DoCast(SPELL_MASSIVE_CRASH); + _pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1); + _pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1); + break; + case EVENT_ANNOUNCE_PINCERS_EXPOSED: + Talk(SAY_ANNOUNCE_EXPOSE_PINCERS); + break; + case EVENT_FINISH_MASSIVE_CRASH: + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_ENEMY_INTERACT); + me->SetReactState(REACT_AGGRESSIVE); + break; + case EVENT_IMPALE_SELF: + DoCastSelf(SPELL_IMPALE_SELF); + break; + case EVENT_EJECT_PASSENGER_1: + _pincer1->CastSpell(_pincer1, SPELL_EJECT_PASSENGER_1); + _pincer2->CastSpell(_pincer2, SPELL_EJECT_PASSENGER_1); + break; + case EVENT_EXPOSE_HEAD: + if (!_headEngaged) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, _exposedHead1, 2); + instance->SendEncounterUnit(ENCOUNTER_FRAME_UPDATE_PRIORITY, me); + _headEngaged = true; + } + _exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_HEAD, true); + _exposedHead1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case EVENT_HIDE_HEAD: + _exposedHead1->CastSpell(_exposedHead1, SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true); + _exposedHead1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case EVENT_FINISH_IMPALE_SELF: + _hasExposedHead = false; + me->SetReactState(REACT_AGGRESSIVE); + break; default: break; } @@ -221,58 +362,69 @@ struct boss_magmaw : public BossAI private: void SetupBody() { - if (Creature* pincer1 = DoSummon(NPC_MAGMAWS_PINCER_1, me->GetPosition())) + if (_pincer1 = DoSummon(NPC_MAGMAWS_PINCER_1, me->GetPosition())) { - pincer1->EnterVehicle(me, SEAT_MAGMAWS_PINCER_1); - pincer1->SetDisplayId(pincer1->GetCreatureTemplate()->Modelid3); + _pincer1->EnterVehicle(me, SEAT_MAGMAWS_PINCER_1); + _pincer1->SetDisplayId(_pincer1->GetCreatureTemplate()->Modelid3); } - if (Creature* pincer2 = DoSummon(NPC_MAGMAWS_PINCER_2, me->GetPosition())) + if (_pincer2 = DoSummon(NPC_MAGMAWS_PINCER_2, me->GetPosition())) { - pincer2->EnterVehicle(me, SEAT_MAGMAWS_PINCER_2); - pincer2->SetDisplayId(pincer2->GetCreatureTemplate()->Modelid3); + _pincer2->EnterVehicle(me, SEAT_MAGMAWS_PINCER_2); + _pincer2->SetDisplayId(_pincer2->GetCreatureTemplate()->Modelid3); } - Creature* exposedHead = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW, ExposedHeadOfMagmawPos); - Creature* exposedHead2 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW_2, me->GetPosition()); + _exposedHead1 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW, ExposedHeadOfMagmawPos); + _exposedHead2 = DoSummon(NPC_EXPOSED_HEAD_OF_MAGMAW_2, me->GetPosition()); - if (!exposedHead || !exposedHead2) + if (!_exposedHead1 || !_exposedHead2) return; - exposedHead->SetReactState(REACT_PASSIVE); - exposedHead2->SetReactState(REACT_PASSIVE); + _exposedHead1->SetReactState(REACT_PASSIVE); + _exposedHead2->SetReactState(REACT_PASSIVE); - exposedHead2->EnterVehicle(me, SEAT_EXPOSED_HEAD_OF_MAGMAW_2); + _exposedHead2->EnterVehicle(me, SEAT_EXPOSED_HEAD_OF_MAGMAW_2); DoCastSelf(SPELL_BIRTH); // First we link the real exposed head - exposedHead->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); - exposedHead->CastSpell(exposedHead, SPELL_POINT_OF_VULNERABILITY); - exposedHead->CastSpell(exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); + _exposedHead1->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); + _exposedHead1->CastSpell(_exposedHead1, SPELL_POINT_OF_VULNERABILITY); + _exposedHead1->CastSpell(_exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); // ... now the dummy exposed head - exposedHead2->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); - exposedHead2->CastSpell(exposedHead2, SPELL_POINT_OF_VULNERABILITY); + _exposedHead2->CastSpell(me, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); + _exposedHead2->CastSpell(_exposedHead2, SPELL_POINT_OF_VULNERABILITY); // ... and now Magmaw - DoCast(exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); - DoCast(exposedHead, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); + DoCast(_exposedHead2, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); + DoCast(_exposedHead1, SPELL_POINT_OF_VULNERABILITY_SHARE_DAMAGE); - exposedHead2->CastSpell(exposedHead2, SPELL_QUEST_INVIS_5); + _exposedHead2->CastSpell(_exposedHead2, SPELL_QUEST_INVIS_5); - exposedHead->m_Events.AddEventAtOffset( - new DelayedSpellCastEvent(exposedHead, me->GetGUID(), SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true), 1s + 200ms); + ObjectGuid guid = me->GetGUID(); + Unit* head = _exposedHead1; + head->m_Events.AddEventAtOffset([head, guid]() + { + if (Unit* target = ObjectAccessor::GetUnit(*head, guid)) + head->CastSpell(target, SPELL_RIDE_VEHICLE_EXPOSED_HEAD, true); + }, 1s + 200ms); } Creature* GetExposedHeadOfMagmaw() { - if (Unit* passenger = vehicle->GetPassenger(SEAT_EXPOSED_HEAD_OF_MAGMAW_1)) + if (Unit* passenger = _vehicle->GetPassenger(SEAT_EXPOSED_HEAD_OF_MAGMAW_1)) if (passenger->GetTypeId() == TYPEID_UNIT) return passenger->ToCreature(); return nullptr; } - Vehicle const* vehicle; + Vehicle const* _vehicle; + Creature* _exposedHead1; + Creature* _exposedHead2; + Creature* _pincer1; + Creature* _pincer2; uint8 _magmaProjectileCount; + bool _hasExposedHead; + bool _headEngaged; }; class IsOnVehicleCheck @@ -324,14 +476,14 @@ class spell_magmaw_magma_spit: public SpellScript class VictimCheck { public: - VictimCheck(Unit* _attacker) : attacker(_attacker) { } + VictimCheck(Unit* attacker) : _attacker(attacker) { } bool operator()(WorldObject* object) { - return (attacker->GetVictim() && attacker->GetVictim() != object->ToUnit()); + return (_attacker->GetVictim() && _attacker->GetVictim() != object->ToUnit()); } private: - Unit* attacker; + Unit* _attacker; }; class spell_magmaw_mangle : public SpellScript @@ -343,7 +495,8 @@ class spell_magmaw_mangle : public SpellScript return ValidateSpellInfo( { SPELL_MANGLE_1, - SPELL_MANGLE_2 + SPELL_MANGLE_2, + SPELL_SWELTERING_ARMOR }); } @@ -364,6 +517,7 @@ class spell_magmaw_mangle : public SpellScript Unit* target = GetHitUnit(); caster->CastSpell(target, SPELL_MANGLE_1, true); target->CastSpell(target, SPELL_MANGLE_2, true); + target->CastSpell(target, SPELL_SWELTERING_ARMOR, true); } void Register() override @@ -390,7 +544,10 @@ class spell_magmaw_pillar_of_flame_dummy : public SpellScript { GetHitUnit()->CastSpell(GetHitUnit(), SPELL_PILLAR_OF_FLAME_MISSILE_PERIODIC); if (Unit* caster = GetCaster()) - caster->m_Events.AddEventAtOffset(new DelayedSpellCastEvent(caster, caster->GetGUID(), SPELL_PILLAR_OF_FLAME_PERIODIC), 2s); + caster->m_Events.AddEventAtOffset([caster]() + { + caster->CastSpell(caster, SPELL_PILLAR_OF_FLAME_PERIODIC); + }, 2s); } void Register() override @@ -403,15 +560,6 @@ class spell_magmaw_pillar_of_flame_forcecast : public SpellScript { PrepareSpellScript(spell_magmaw_pillar_of_flame_forcecast); - bool Validate(SpellInfo const* /*spellInfo*/) override - { - return ValidateSpellInfo( - { - SPELL_MANGLE_1, - SPELL_MANGLE_2 - }); - } - void FilterTargets(std::list& targets) { if (targets.empty()) @@ -431,6 +579,66 @@ class spell_magmaw_pillar_of_flame_forcecast : public SpellScript } }; +class spell_magmaw_ride_vehicle : public SpellScript +{ + PrepareSpellScript(spell_magmaw_ride_vehicle); + + void SetTarget(WorldObject*& target) + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + { + if (Creature* magmaw = instance->GetCreature(DATA_MAGMAW)) + { + if (Creature* pincer = ObjectAccessor::GetCreature(*GetCaster(), magmaw->AI()->GetGUID(DATA_FREE_PINCER))) + target = pincer; + else + target = nullptr; + } + } + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_magmaw_ride_vehicle::SetTarget, EFFECT_0, TARGET_UNIT_TARGET_ANY); + } +}; + +class spell_magmaw_launch_hook : public AuraScript +{ + PrepareAuraScript(spell_magmaw_launch_hook); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_LAUNCH_HOOK_1, + SPELL_LAUNCH_HOOK_2, + SPELL_CHAIN_VISUAL_1, + SPELL_CHAIN_VISUAL_2 + }); + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + + if (target->HasAura(SPELL_LAUNCH_HOOK_1) /*&&*/ || target->HasAura(SPELL_LAUNCH_HOOK_2)) + { + if (InstanceScript* instance = target->GetInstanceScript()) + if (Creature* magmaw = instance->GetCreature(DATA_MAGMAW)) + magmaw->AI()->DoAction(ACTION_IMPALE_MAGMAW); + + target->CastSpell(target, SPELL_CHAIN_VISUAL_1); + target->CastSpell(target, SPELL_CHAIN_VISUAL_2); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_magmaw_launch_hook::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + void AddSC_boss_magmaw() { RegisterBlackwingDescentCreatureAI(boss_magmaw); @@ -438,4 +646,6 @@ void AddSC_boss_magmaw() RegisterSpellScript(spell_magmaw_mangle); RegisterSpellScript(spell_magmaw_pillar_of_flame_dummy); RegisterSpellScript(spell_magmaw_pillar_of_flame_forcecast); + RegisterSpellScript(spell_magmaw_ride_vehicle); + RegisterAuraScript(spell_magmaw_launch_hook); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp index 31ae5ead9f6..b6fa50ac17d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingDescent/instance_blackwing_descent.cpp @@ -37,6 +37,10 @@ DoorData const doorData[] = { 0, 0, DOOR_TYPE_ROOM } // END }; +Position const MassiveCrashRightSpawnPosition = { -288.59f, -14.8472f, 211.2573f }; +Position const MassiveCrashTargetPositionLeft = { -304.181f, -90.1806f, 214.1653f }; +Position const MassiveCrashTargetPositionRight = { -337.375f, -43.6615f, 212.0853f }; + class instance_blackwing_descent : public InstanceMapScript { public: @@ -68,6 +72,20 @@ class instance_blackwing_descent : public InstanceMapScript if (Creature* magmaw = GetCreature(DATA_MAGMAW)) magmaw->AI()->JustSummoned(creature); break; + case NPC_MASSIVE_CRASH: + if (creature->GetExactDist2d(MassiveCrashRightSpawnPosition) < 1.0f) + _massiveCrashRightDummyGUID = creature->GetGUID(); + else + _massiveCrashLeftDummyGUID = creature->GetGUID(); + + break; + case NPC_ROOM_STALKER: + _roomStalkerGUIDs.insert(creature->GetGUID()); + + if (creature->GetExactDist2d(MassiveCrashTargetPositionLeft) < 1.0f) + _roomStalkerTargetDummyLeftGuid = creature->GetGUID(); + else if (creature->GetExactDist2d(MassiveCrashTargetPositionRight) < 1.0f) + _roomStalkerTargetDummyRightGuid = creature->GetGUID(); default: break; } @@ -83,6 +101,30 @@ class instance_blackwing_descent : public InstanceMapScript if (!InstanceScript::SetBossState(type, state)) return false; + switch (type) + { + case DATA_MAGMAW: + if (state == FAIL || state == DONE) + { + if (Creature* dummy = instance->GetCreature(_massiveCrashRightDummyGUID)) + dummy->DespawnOrUnsummon(0s, 30s); + + if (Creature* dummy = instance->GetCreature(_massiveCrashLeftDummyGUID)) + dummy->DespawnOrUnsummon(0s, 30s); + + for (ObjectGuid guid : _roomStalkerGUIDs) + { + if (Creature* stalker = instance->GetCreature(guid)) + stalker->DespawnOrUnsummon(0s, 30s); + } + + _roomStalkerGUIDs.clear(); + } + break; + default: + break; + } + return true; } @@ -97,16 +139,66 @@ class instance_blackwing_descent : public InstanceMapScript } */ - /* uint32 GetData(uint32 type) const override + { + return 0; + } + + ObjectGuid GetGuidData(uint32 type) const override { switch (type) { + case DATA_PREPARE_MASSIVE_CRASH_AND_GET_TARGET_GUID: + { + Creature* massiveCrashStalker = nullptr; + uint8 sideIndex = MASSIVE_CRASH_SIDE_LEFT; + switch (urand(MASSIVE_CRASH_SIDE_LEFT, MASSIVE_CRASH_SIDE_RIGHT)) + { + case MASSIVE_CRASH_SIDE_LEFT: + massiveCrashStalker = instance->GetCreature(_massiveCrashLeftDummyGUID); + break; + case MASSIVE_CRASH_SIDE_RIGHT: + massiveCrashStalker = instance->GetCreature(_massiveCrashRightDummyGUID); + sideIndex = MASSIVE_CRASH_SIDE_RIGHT; + break; + default: + break; + } + + if (!massiveCrashStalker) + return ObjectGuid::Empty; + + for (ObjectGuid guid : _roomStalkerGUIDs) + { + if (Creature* stalker = instance->GetCreature(guid)) + { + if (massiveCrashStalker->HasInArc(float(M_PI / 4.0f), stalker)) + { + stalker->CastSpell(stalker, SPELL_LIGHT_SHOW); + stalker->m_Events.AddEventAtOffset([stalker]() + { + stalker->RemoveAurasDueToSpell(SPELL_LIGHT_SHOW); + }, 7s); + } + } + } + + massiveCrashStalker->m_Events.AddEventAtOffset([massiveCrashStalker]() + { + massiveCrashStalker->CastSpell(massiveCrashStalker, SPELL_MASSIVE_CRASH_DAMAGE); + }, 6s); + + if (sideIndex == MASSIVE_CRASH_SIDE_LEFT) + return _roomStalkerTargetDummyLeftGuid; + else + return _roomStalkerTargetDummyRightGuid; + + break; + } } - return 0; + return ObjectGuid::Empty; } - */ /* void WriteSaveDataMore(std::ostringstream& data) override @@ -119,6 +211,12 @@ class instance_blackwing_descent : public InstanceMapScript { } */ + private: + ObjectGuid _massiveCrashLeftDummyGUID; + ObjectGuid _massiveCrashRightDummyGUID; + ObjectGuid _roomStalkerTargetDummyLeftGuid; + ObjectGuid _roomStalkerTargetDummyRightGuid; + GuidSet _roomStalkerGUIDs; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 25cb637c389..8abe7df73ff 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -3836,6 +3836,45 @@ class spell_gen_eject_passenger : public SpellScriptLoader } }; + +class spell_gen_eject_passenger_1 : public SpellScript +{ + PrepareSpellScript(spell_gen_eject_passenger_1); + + void EjectPassenger(SpellEffIndex /*effIndex*/) + { + if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit()) + { + if (Unit* passenger = vehicle->GetPassenger(0)) + passenger->ExitVehicle(); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_eject_passenger_1::EjectPassenger, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + +class spell_gen_eject_passenger_3 : public SpellScript +{ + PrepareSpellScript(spell_gen_eject_passenger_3); + + void EjectPassenger(SpellEffIndex /*effIndex*/) + { + if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit()) + { + if (Unit* passenger = vehicle->GetPassenger(2)) + passenger->ExitVehicle(); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_eject_passenger_3::EjectPassenger, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; + enum GMFreeze { SPELL_GM_FREEZE = 9454 @@ -4983,6 +5022,8 @@ void AddSC_generic_spell_scripts() new spell_gen_whisper_gulch_yogg_saron_whisper(); new spell_gen_eject_all_passengers(); new spell_gen_eject_passenger(); + RegisterSpellScript(spell_gen_eject_passenger_1); + RegisterSpellScript(spell_gen_eject_passenger_3); new spell_gen_gm_freeze(); new spell_gen_stand(); new spell_gen_mixology_bonus();