From 52277581da44e8c4b26731bdbec12e9c977c1434 Mon Sep 17 00:00:00 2001 From: _daanieL Date: Wed, 3 Jul 2024 12:33:35 +0200 Subject: [PATCH] Magtheridon: Rework Magtheridon Fight (#683) * Use broadcast_text insteat of script_texts for all texts * put hellfire channeler into spell_list * remove spell mental interference script from magtheridon script and put it into netherstorm file Used for an Quest in Netherstorm * Add correct BossFail behavior all npcs should now despawn for 30 seconds before respawning fail should happen instantly on evade mode not when channeler reaches home add leashing for channelers * add back visual * remove double code * Instantly free magtheridon when all channelers are dead * Add delay before magtheridon starts the fight * remove not needed break and add a safty check * correct rnd texts * remove quake knockback spellscript, players should get hit from while jumping * Add leash also to magtheridon * Add Magtheridon spell into spell_list * update script, fix p2 intro * despawn blaze objects on wipe --- sql/scriptdev2/scriptdev2.sql | 18 -- sql/scriptdev2/spell.sql | 1 - .../magtheridons_lair/boss_magtheridon.cpp | 227 ++++++------------ .../magtheridons_lair/magtheridons_lair.cpp | 145 +++++------ .../magtheridons_lair/magtheridons_lair.h | 14 +- .../scripts/outland/netherstorm.cpp | 14 ++ 6 files changed, 181 insertions(+), 238 deletions(-) diff --git a/sql/scriptdev2/scriptdev2.sql b/sql/scriptdev2/scriptdev2.sql index cc2b93be975..378d2335859 100644 --- a/sql/scriptdev2/scriptdev2.sql +++ b/sql/scriptdev2/scriptdev2.sql @@ -3905,24 +3905,6 @@ INSERT INTO script_texts (entry,content_default,sound,type,language,emote,broadc -- -1 543 000 HELLFIRE RAMPARTS -- -1 544 000 MAGTHERIDON'S LAIR -INSERT INTO script_texts (entry,content_default,sound,type,language,emote,broadcast_text_id,comment) VALUES -('-1544000','Wretched, meddling insects! Release me, and perhaps I will grant you a merciful death!','10247','6','0','0','17339','magtheridon SAY_TAUNT1'), -('-1544001','Vermin! Leeches! Take my blood and choke on it!','10248','6','0','0','17340','magtheridon SAY_TAUNT2'), -('-1544002','Illidan is an arrogant fool! I will crush him and reclaim Outland as my own!','10249','6','0','0','17341','magtheridon SAY_TAUNT3'), -('-1544003','Away, you mindless parasites! My blood is my own!','10250','6','0','0','17342','magtheridon SAY_TAUNT4'), -('-1544004','How long do you believe your pathetic sorcery can hold me?','10251','6','0','0','17343','magtheridon SAY_TAUNT5'), -('-1544005','My blood will be the end of you!','10252','6','0','0','17344','magtheridon SAY_TAUNT6'), -('-1544006','I... am... unleashed!','10253','1','0','0','17346','magtheridon SAY_FREED'), -('-1544007','Thank you for releasing me. Now...die!','10254','1','0','0','0','magtheridon SAY_AGGRO'), -('-1544008','Not again! Not again...','10256','1','0','0','17348','magtheridon SAY_BANISH'), -('-1544009','I will not be taken so easily! Let the walls of this prison tremble... and fall!','10257','1','0','0','17336','magtheridon SAY_CHAMBER_DESTROY'), -('-1544010','Did you think me weak? Soft? Who is the weak one now?','10255','1','0','0','17349','magtheridon SAY_PLAYER_KILLED'), -('-1544011','The Legion will consume you all!','10258','1','0','0','17347','magtheridon SAY_DEATH'), -('-1544012','REUSE_ME','0','0','0','0','0','REUSE_ME'), -('-1544013','%s begins to cast Blast Nova!','0','3','0','0','18739','magtheridon EMOTE_BLASTNOVA'), -('-1544014','%s''s bonds begin to weaken!','0','2','0','0','13689','magtheridon EMOTE_BEGIN'), -('-1544015','%s breaks free!','0','2','0','0','13691','magtheridon EMOTE_FREED'), -('-1544016','%s is nearly free of his bonds!','0','2','0','0','13690','magtheridon EMOTE_NEARLY_FREE'); -- -1 545 000 THE STEAMVAULT INSERT INTO script_texts (entry,content_default,sound,type,language,emote,broadcast_text_id,comment) VALUES diff --git a/sql/scriptdev2/spell.sql b/sql/scriptdev2/spell.sql index 879aa3e3b93..68ab18a750c 100644 --- a/sql/scriptdev2/spell.sql +++ b/sql/scriptdev2/spell.sql @@ -260,7 +260,6 @@ INSERT INTO spell_scripts(Id, ScriptName) VALUES (30166,'spell_shadow_grasp_magtheridon'), (30410,'spell_shadow_grasp_cube'), (30658,'spell_quake_magtheridon'), -(30571,'spell_quake_magtheridon_knockback'), (30425,'spell_portal_attunement'), (30469,'spell_nether_beam'), (38546,'spell_face_random_target'), diff --git a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp index 8d1c344e614..67fa2e76112 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp @@ -30,16 +30,17 @@ EndScriptData */ enum { // yells - SAY_AGGRO = -1544006, - SAY_UNUSED = -1544007, - SAY_BANISH = -1544008, - SAY_CHAMBER_DESTROY = -1544009, - SAY_PLAYER_KILLED = -1544010, - SAY_DEATH = -1544011, - - EMOTE_GENERIC_ENRAGED = -1000003, - EMOTE_BLASTNOVA = -1544013, - EMOTE_FREED = -1544015, + SAY_AGGRO = 17346, + SAY_BANISH = 17348, + SAY_CHAMBER_DESTROY = 17336, + SAY_PLAYER_KILLED = 17349, + SAY_DEATH = 17347, + + EMOTE_GENERIC_ENRAGED = 2384, + EMOTE_BLASTNOVA = 18739, + EMOTE_FREED = 13691, + EMOTE_EVENT_BEGIN = 13689, + EMOTE_NEARLY_FREE = 13690, // Maghteridon spells SPELL_SHADOW_CAGE_DUMMY = 30205, // dummy aura - in creature_template_addon @@ -81,6 +82,9 @@ enum NPC_RAID_TRIGGER = 17376, MAX_QUAKE_COUNT = 7, + + SPELL_LIST_PHASE_1 = 1725701, + SPELL_LIST_PHASE_2 = 1725702, }; /*###### @@ -91,14 +95,11 @@ enum MagtheridonActions { MAGTHERIDON_PHASE_3, MAGTHERIDON_BERSERK, - MAGTHERIDON_BLAST_NOVA, MAGTHERIDON_DEBRIS, - MAGTHERIDON_QUAKE, - MAGTHERIDON_CLEAVE, - MAGTHERIDON_BLAZE, MAGTHERIDON_ACTION_MAX, MAGTHERIDON_QUAKE_TIMER, MAGTHERIDON_TRANSITION_TIMER, + MAGTHERIDON_ATTACK_DELAY }; struct boss_magtheridonAI : public CombatAI @@ -107,11 +108,6 @@ struct boss_magtheridonAI : public CombatAI { AddTimerlessCombatAction(MAGTHERIDON_PHASE_3, true); AddCombatAction(MAGTHERIDON_DEBRIS, true); - AddCombatAction(MAGTHERIDON_BERSERK, true); - AddCombatAction(MAGTHERIDON_BLAZE, true); - AddCombatAction(MAGTHERIDON_QUAKE, true); - AddCombatAction(MAGTHERIDON_BLAST_NOVA, true); - AddCombatAction(MAGTHERIDON_CLEAVE, true); AddCustomAction(MAGTHERIDON_QUAKE_TIMER, true, [&]() { m_creature->SetStunned(false); @@ -119,7 +115,16 @@ struct boss_magtheridonAI : public CombatAI DoStartMovement(m_creature->GetVictim()); }); AddCustomAction(MAGTHERIDON_TRANSITION_TIMER, true, [&]() { HandlePhaseTransition(); }); + AddCustomAction(MAGTHERIDON_ATTACK_DELAY, true, [&]() { HandleStartAttack(); }); Reset(); + + // Magtheridon gets respawned after a wipe + DoCastSpellIfCan(nullptr, SPELL_SHADOW_CAGE_DUMMY, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); + + m_creature->GetCombatManager().SetLeashingCheck([&](Unit* /*unit*/, float /*x*/, float /*y*/, float /*z*/)->bool + { + return m_creature->GetDistance2d(-16.683f, 2.34519f) > 55.0f; + }); } ScriptedInstance* m_instance; @@ -152,33 +157,30 @@ struct boss_magtheridonAI : public CombatAI m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNINTERACTIBLE); m_creature->SetInCombatWithZone(); - DoScriptText(EMOTE_FREED, m_creature); - DoScriptText(SAY_AGGRO, m_creature); - - SetCombatScriptStatus(false); + DoBroadcastText(EMOTE_FREED, m_creature); + m_creature->HandleEmote(EMOTE_ONESHOT_ROAR); + DoBroadcastText(SAY_AGGRO, m_creature); + ResetTimer(MAGTHERIDON_ATTACK_DELAY, 3000); + m_creature->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_DUMMY); - - SetReactState(REACT_AGGRESSIVE); - + DoResetThreat(); // clear threat at start - - // timers here so they dont start at combat initiate - ResetCombatAction(MAGTHERIDON_BERSERK, uint32(20 * MINUTE * IN_MILLISECONDS)); - ResetCombatAction(MAGTHERIDON_BLAZE, urand(10000, 15000)); - ResetCombatAction(MAGTHERIDON_QUAKE, 40000); - ResetCombatAction(MAGTHERIDON_BLAST_NOVA, 55000); - ResetCombatAction(MAGTHERIDON_CLEAVE, urand(8000, 12000)); + } else if (eventType == AI_EVENT_CUSTOM_B) { - DoScriptText(EMOTE_EVENT_BEGIN, m_creature); + DoBroadcastText(EMOTE_EVENT_BEGIN, m_creature); + } + else if (eventType == AI_EVENT_CUSTOM_C) + { + DoBroadcastText(EMOTE_NEARLY_FREE, m_creature); } } void KilledUnit(Unit* victim) override { if (victim->GetTypeId() == TYPEID_PLAYER) - DoScriptText(SAY_PLAYER_KILLED, m_creature); + DoBroadcastText(SAY_PLAYER_KILLED, m_creature); } void JustDied(Unit* /*killer*/) override @@ -186,30 +188,31 @@ struct boss_magtheridonAI : public CombatAI if (m_instance) m_instance->SetData(TYPE_MAGTHERIDON_EVENT, DONE); - DoScriptText(SAY_DEATH, m_creature); + DoBroadcastText(SAY_DEATH, m_creature); m_creature->CastSpell(nullptr, SPELL_QUAKE_REMOVAL, TRIGGERED_OLD_TRIGGERED); } void EnterEvadeMode() override - { - m_creature->SetStunned(false); - CombatAI::EnterEvadeMode(); - } - - void JustReachedHome() override { if (m_instance) m_instance->SetData(TYPE_MAGTHERIDON_EVENT, FAIL); - DoCastSpellIfCan(nullptr, SPELL_SHADOW_CAGE_DUMMY, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); + m_creature->SetStunned(false); + CombatAI::EnterEvadeMode(); } void SpellHit(Unit* /*caster*/, const SpellEntry* spellInfo) override { // When banished by the cubes if (spellInfo->Id == SPELL_SHADOW_CAGE) - DoScriptText(SAY_BANISH, m_creature); + DoBroadcastText(SAY_BANISH, m_creature); + } + + void HandleStartAttack() + { + SetReactState(REACT_AGGRESSIVE); + SetCombatScriptStatus(false); } void HandlePhaseTransition() @@ -231,6 +234,12 @@ struct boss_magtheridonAI : public CombatAI SetCombatScriptStatus(false); SetMeleeEnabled(true); SetCombatMovement(true, true); + m_creature->SetSpellList(SPELL_LIST_PHASE_2); + if (Unit* victim = m_creature->GetVictim()) + { + m_creature->SetTarget(victim); + DoStartMovement(victim); + } break; } @@ -239,6 +248,23 @@ struct boss_magtheridonAI : public CombatAI ResetTimer(MAGTHERIDON_TRANSITION_TIMER, timer); } + void OnSpellCast(SpellEntry const* spellInfo, Unit* /*target*/) override + { + switch (spellInfo->Id) + { + case SPELL_BLASTNOVA: + DoBroadcastText(EMOTE_BLASTNOVA, m_creature); + break; + case SPELL_QUAKE: + m_creature->SetStunned(true); + ResetTimer(MAGTHERIDON_QUAKE_TIMER, 7000); + break; + case SPELL_BERSERK: + DoBroadcastText(EMOTE_GENERIC_ENRAGED, m_creature); + break; + } + } + void ExecuteAction(uint32 action) override { switch (action) @@ -248,63 +274,17 @@ struct boss_magtheridonAI : public CombatAI if (m_creature->GetHealthPercent() < 30.0f) { // ToDo: maybe there is a spell here - requires additional research - DoScriptText(SAY_CHAMBER_DESTROY, m_creature); + DoBroadcastText(SAY_CHAMBER_DESTROY, m_creature); m_creature->HandleEmote(EMOTE_STATE_TALK); ResetTimer(MAGTHERIDON_TRANSITION_TIMER, 5000); + m_creature->SetTarget(nullptr); SetCombatScriptStatus(true); SetMeleeEnabled(false); SetCombatMovement(false); SetActionReadyStatus(action, false); - ResetCombatAction(MAGTHERIDON_DEBRIS, urand(20000, 30000)); - } - break; - } - case MAGTHERIDON_BERSERK: - { - if (DoCastSpellIfCan(nullptr, SPELL_BERSERK) == CAST_OK) - { - DoScriptText(EMOTE_GENERIC_ENRAGED, m_creature); - DisableCombatAction(action); - } - break; - } - case MAGTHERIDON_BLAST_NOVA: - { - if (DoCastSpellIfCan(nullptr, SPELL_BLASTNOVA) == CAST_OK) - { - DoScriptText(EMOTE_BLASTNOVA, m_creature); - ResetCombatAction(action, 55000); } break; } - case MAGTHERIDON_DEBRIS: - { - if (DoCastSpellIfCan(nullptr, SPELL_DEBRIS_1) == CAST_OK) - ResetCombatAction(action, urand(10000, 15000)); - break; - } - case MAGTHERIDON_QUAKE: - { - if (DoCastSpellIfCan(m_creature->GetVictim(), SPELL_QUAKE) == CAST_OK) - { - m_creature->SetStunned(true); - ResetTimer(MAGTHERIDON_QUAKE_TIMER, 7000); - ResetCombatAction(action, 50000); - } - break; - } - case MAGTHERIDON_CLEAVE: - { - if (DoCastSpellIfCan(m_creature->GetVictim(), SPELL_CLEAVE) == CAST_OK) - ResetCombatAction(action, urand(8000, 16000)); - break; - } - case MAGTHERIDON_BLAZE: - { - if (DoCastSpellIfCan(nullptr, SPELL_BLAZE) == CAST_OK) - ResetCombatAction(action, urand(10000, 15000)); - break; - } } } }; @@ -315,10 +295,6 @@ struct boss_magtheridonAI : public CombatAI enum ChannelerActions { - CHANNELER_INFERNAL, - CHANNELER_DARK_MENDING, - CHANNELER_FEAR, - CHANNELER_SHADOW_BOLT, CHANNELER_ACTION_MAX, CHANNELER_SHADOW_GRASP, }; @@ -327,12 +303,13 @@ struct mob_hellfire_channelerAI : public CombatAI { mob_hellfire_channelerAI(Creature* creature) : CombatAI(creature, CHANNELER_ACTION_MAX), m_instance(static_cast(creature->GetInstanceData())) { - AddCombatAction(CHANNELER_INFERNAL, 10000, 50000); - AddCombatAction(CHANNELER_DARK_MENDING, 10000u); - AddCombatAction(CHANNELER_FEAR, 15000, 20000); - AddCombatAction(CHANNELER_SHADOW_BOLT, 8000, 10000); - AddCustomAction(CHANNELER_SHADOW_GRASP, 10000u, [&]() { DoCastSpellIfCan(m_creature, SPELL_SHADOW_GRASP_DUMMY); }); SetReactState(REACT_DEFENSIVE); + AddCustomAction(CHANNELER_SHADOW_GRASP, 5000u, [&]() { DoCastSpellIfCan(m_creature, SPELL_SHADOW_GRASP_DUMMY); }, TIMER_COMBAT_OOC); + + m_creature->GetCombatManager().SetLeashingCheck([&](Unit* /*unit*/, float /*x*/, float /*y*/, float /*z*/)->bool + { + return m_creature->GetDistance2d(-16.683f, 2.34519f) > 55.0f; + }); } ScriptedInstance* m_instance; @@ -350,44 +327,11 @@ struct mob_hellfire_channelerAI : public CombatAI m_creature->CastSpell(m_creature, SPELL_SOUL_TRANSFER, TRIGGERED_OLD_TRIGGERED); } - void JustReachedHome() override + void EnterEvadeMode() override { if (m_instance) m_instance->SetData(TYPE_CHANNELER_EVENT, FAIL); - } - - void ExecuteAction(uint32 action) override - { - switch (action) - { - case CHANNELER_INFERNAL: - { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_BURNING_ABYSSAL, SELECT_FLAG_PLAYER)) - if (DoCastSpellIfCan(target, SPELL_BURNING_ABYSSAL) == CAST_OK) - ResetCombatAction(action, 45000); - break; - } - case CHANNELER_DARK_MENDING: - { - if (Unit* target = DoSelectLowestHpFriendly(30.0f)) - if (DoCastSpellIfCan(target, SPELL_DARK_MENDING) == CAST_OK) - ResetCombatAction(action, urand(10000, 20000)); - break; - } - case CHANNELER_FEAR: - { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_FEAR, (SELECT_FLAG_PLAYER | SELECT_FLAG_NOT_AURA))) - if (DoCastSpellIfCan(target, SPELL_FEAR) == CAST_OK) - ResetCombatAction(action, urand(25000, 40000)); - break; - } - case CHANNELER_SHADOW_BOLT: - { - if (DoCastSpellIfCan(nullptr, SPELL_SHADOW_BOLT_VOLLEY) == CAST_OK) - ResetCombatAction(action, urand(10000, 20000)); - break; - } - } + CombatAI::EnterEvadeMode(); } }; @@ -482,16 +426,6 @@ struct QuakeMagth : public SpellScript } }; -struct QuakeMagthKnockback : public SpellScript -{ - bool OnCheckTarget(const Spell* /*spell*/, Unit* target, SpellEffectIndex /*eff*/) const override - { - if (target->IsJumping() || target->IsFalling()) - return false; - return true; - } -}; - struct DebrisMagtheridon : public AuraScript { void OnPersistentAreaAuraEnd(DynamicObject* dynGo) const override @@ -522,6 +456,5 @@ void AddSC_boss_magtheridon() RegisterSpellScript("spell_shadow_grasp_cube"); RegisterSpellScript("spell_shadow_grasp_magtheridon"); RegisterSpellScript("spell_quake_magtheridon"); - RegisterSpellScript("spell_quake_magtheridon_knockback"); RegisterSpellScript("spell_magtheridon_debris"); } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.cpp b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.cpp index 2c805372fdd..9280729b3bf 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.cpp @@ -57,14 +57,27 @@ void instance_magtheridons_lair::OnCreatureCreate(Creature* pCreature) m_npcEntryGuidStore[NPC_MAGTHERIDON] = pCreature->GetObjectGuid(); break; case NPC_CHANNELER: - m_lChannelerGuidList.push_back(pCreature->GetObjectGuid()); + m_lChannelerGuidList.push_back(pCreature->GetDbGuid()); break; case NPC_BURNING_ABYSSAL: - m_npcEntryGuidCollection[pCreature->GetEntry()].push_back(pCreature->GetObjectGuid()); + m_abyssalTemporaryGuids.push_back(pCreature->GetObjectGuid()); break; } } +void instance_magtheridons_lair::OnCreatureGroupDespawn(CreatureGroup* pGroup, Creature* /*pCreature*/) +{ + // Confirmed on TBC Classic: instantly free magtheridon when all channelers are dead + if (pGroup->GetGroupId() == SPAWN_GROUP_CHANNELER) + { + if (GetData(TYPE_CHANNELER_EVENT) == IN_PROGRESS) + { + SetData(TYPE_MAGTHERIDON_EVENT, IN_PROGRESS); + m_uiCageBreakTimer = 0; + } + } +} + void instance_magtheridons_lair::OnObjectCreate(GameObject* pGo) { switch (pGo->GetEntry()) @@ -84,6 +97,10 @@ void instance_magtheridons_lair::OnObjectCreate(GameObject* pGo) case GO_MANTICRON_CUBE: m_lCubeGuidList.push_back(pGo->GetObjectGuid()); break; + case GO_MAGHERIDON_BLAZE: + m_lBlazeGuidList.push_back(pGo->GetObjectGuid()); + break; + } } @@ -94,40 +111,9 @@ void instance_magtheridons_lair::SetData(uint32 uiType, uint32 uiData) case TYPE_MAGTHERIDON_EVENT: switch (uiData) { - case FAIL: - // Reset channelers - for (GuidList::const_iterator itr = m_lChannelerGuidList.begin(); itr != m_lChannelerGuidList.end(); ++itr) - { - if (Creature* pChanneler = instance->GetCreature(*itr)) - { - if (!pChanneler->IsAlive()) - pChanneler->Respawn(); - } - } - - // Reset columns - for (GuidList::const_iterator itr = m_lColumnGuidList.begin(); itr != m_lColumnGuidList.end(); ++itr) - { - if (GameObject* pColumn = instance->GetGameObject(*itr)) - pColumn->ResetDoorOrButton(); - } - - { - GuidVector abyssals; - GetCreatureGuidVectorFromStorage(NPC_BURNING_ABYSSAL, abyssals); - DespawnGuids(abyssals); - } - - // Reset cubes - for (GuidList::const_iterator itr = m_lCubeGuidList.begin(); itr != m_lCubeGuidList.end(); ++itr) - DoToggleGameObjectFlags(*itr, GO_FLAG_NO_INTERACT, true); - - // Reset timers and doors - SetData(TYPE_CHANNELER_EVENT, NOT_STARTED); - m_uiCageBreakTimer = 0; - m_uiCageBreakStage = 0; - - [[fallthrough]]; + case FAIL: + FailBoss(); + break; case DONE: // Reset door on Fail or Done DoUseOpenableObject(GO_DOODAD_HF_MAG_DOOR01, true); @@ -157,21 +143,8 @@ void instance_magtheridons_lair::SetData(uint32 uiType, uint32 uiData) if (m_auiEncounter[1] == uiData) break; // stop the event timer on fail - if (uiData == FAIL) - { - m_uiCageBreakTimer = 0; - m_uiCageBreakStage = 0; - - // Reset door on Fail - DoUseOpenableObject(GO_DOODAD_HF_MAG_DOOR01, true); - - // Reset Magtheridon - if (Creature* pMagtheridon = GetSingleCreatureFromStorage(NPC_MAGTHERIDON)) - { - if (pMagtheridon->IsAlive()) - pMagtheridon->AI()->EnterEvadeMode(); - } - } + if (uiData == FAIL) + FailBoss(); // prepare Magtheridon for release if (uiData == IN_PROGRESS) { @@ -202,6 +175,49 @@ uint32 instance_magtheridons_lair::GetData(uint32 uiType) const return 0; } +void instance_magtheridons_lair::FailBoss() +{ + // Reset Timers and stages + m_uiCageBreakTimer = 0; + m_uiCageBreakStage = 0; + SetData(TYPE_CHANNELER_EVENT, NOT_STARTED); + + // Reset door on Fail + DoUseOpenableObject(GO_DOODAD_HF_MAG_DOOR01, true); + + for (GuidList::const_iterator itr = m_lColumnGuidList.begin(); itr != m_lColumnGuidList.end(); ++itr) + { + if (GameObject* pColumn = instance->GetGameObject(*itr)) + pColumn->ResetDoorOrButton(); + } + + // Reset cubes + for (GuidList::const_iterator itr = m_lCubeGuidList.begin(); itr != m_lCubeGuidList.end(); ++itr) + DoToggleGameObjectFlags(*itr, GO_FLAG_NO_INTERACT, true); + + // Despawn all Blaze objects + for (GuidList::const_iterator itr = m_lBlazeGuidList.begin(); itr != m_lBlazeGuidList.end(); ++itr) + { + if (GameObject* pBlaze = instance->GetGameObject(*itr)) + pBlaze->AddObjectToRemoveList(); + } + + // Despawn all abyssals + for (ObjectGuid& guid : m_abyssalTemporaryGuids) + if (Creature* creature = instance->GetCreature(guid)) + creature->ForcedDespawn(); + + // Despawn and Respawn all Channelers for 30 seconds + RespawnDbGuids(m_lChannelerGuidList, 30); + m_lChannelerGuidList.clear(); + + if (Creature* pMagtheridon = GetSingleCreatureFromStorage(NPC_MAGTHERIDON)) + { + pMagtheridon->SetRespawnDelay(30, true); + pMagtheridon->ForcedDespawn(); + } +} + void instance_magtheridons_lair::Update(uint32 uiDiff) { // Prepare to release Magtheridon @@ -216,7 +232,7 @@ void instance_magtheridons_lair::Update(uint32 uiDiff) { if (pMagtheridon->IsAlive()) { - DoScriptText(EMOTE_NEARLY_FREE, pMagtheridon); + pMagtheridon->AI()->SendAIEvent(AI_EVENT_CUSTOM_C, pMagtheridon, pMagtheridon); m_uiCageBreakTimer = MINUTE * IN_MILLISECONDS; } } @@ -239,25 +255,20 @@ void instance_magtheridons_lair::Update(uint32 uiDiff) if (m_uiRandYellTimer < uiDiff) { - DoOrSimulateScriptTextForThisInstance(aRandomTaunt[urand(0, 5)], NPC_MAGTHERIDON); + if (Creature* pMagtheridon = GetSingleCreatureFromStorage(NPC_MAGTHERIDON)) + { + if (pMagtheridon->IsAlive()) + { + DoBroadcastText(aRandomTaunt[urand(0, 5)], pMagtheridon); + m_uiCageBreakTimer = MINUTE * IN_MILLISECONDS; + } + } m_uiRandYellTimer = 90000; } else m_uiRandYellTimer -= uiDiff; } -struct MentalInterferenceSpellScript : public SpellScript -{ - SpellCastResult OnCheckCast(Spell* spell, bool /*strict*/) const override - { - if (ObjectGuid target = spell->m_targets.getUnitTargetGuid()) - if (target.GetEntry() != 16943 && target.GetEntry() != 20928) // Mental Interference can be cast only on these two targets - return SPELL_FAILED_BAD_TARGETS; - - return SPELL_CAST_OK; - } -}; - InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) { return new instance_magtheridons_lair(pMap); @@ -268,7 +279,5 @@ void AddSC_instance_magtheridons_lair() Script* pNewScript = new Script; pNewScript->Name = "instance_magtheridons_lair"; pNewScript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; - pNewScript->RegisterSelf(); - - RegisterSpellScript("spell_mental_interference"); + pNewScript->RegisterSelf(); } diff --git a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h index b56e1429f79..300bc818a68 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h +++ b/src/game/AI/ScriptDevAI/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h @@ -25,12 +25,12 @@ enum GO_MAGTHERIDON_COLUMN_005 = 184637, GO_MAGTHERIDON_COLUMN_000 = 184638, GO_MAGTHERIDON_COLUMN_001 = 184639, + GO_MAGHERIDON_BLAZE = 181832, - EMOTE_EVENT_BEGIN = -1544014, - EMOTE_NEARLY_FREE = -1544016, + SPAWN_GROUP_CHANNELER = 5440005, }; -static const int32 aRandomTaunt[] = { -1544000, -1544001, -1544002, -1544003, -1544004, -1544005}; +static const int32 aRandomTaunt[] = { 17339, 17340, 17341, 17342, 17343, 17344 }; class instance_magtheridons_lair : public ScriptedInstance { @@ -41,8 +41,11 @@ class instance_magtheridons_lair : public ScriptedInstance bool IsEncounterInProgress() const override; + void FailBoss(); + void OnCreatureCreate(Creature* pCreature) override; void OnObjectCreate(GameObject* pGo) override; + void OnCreatureGroupDespawn(CreatureGroup* pGroup, Creature* pCreature) override; void SetData(uint32 uiType, uint32 uiData) override; uint32 GetData(uint32 uiType) const override; @@ -52,9 +55,12 @@ class instance_magtheridons_lair : public ScriptedInstance private: uint32 m_auiEncounter[MAX_ENCOUNTER]; - GuidList m_lChannelerGuidList; + std::vector m_lChannelerGuidList; + GuidVector m_abyssalTemporaryGuids; + GuidList m_lColumnGuidList; GuidList m_lCubeGuidList; + GuidList m_lBlazeGuidList; uint32 m_uiRandYellTimer; uint32 m_uiCageBreakTimer; diff --git a/src/game/AI/ScriptDevAI/scripts/outland/netherstorm.cpp b/src/game/AI/ScriptDevAI/scripts/outland/netherstorm.cpp index 02f9de5f8fe..3cde7f353a6 100644 --- a/src/game/AI/ScriptDevAI/scripts/outland/netherstorm.cpp +++ b/src/game/AI/ScriptDevAI/scripts/outland/netherstorm.cpp @@ -4040,6 +4040,19 @@ struct RingOfFlame : public AuraScript } }; + +struct MentalInterferenceSpellScript : public SpellScript +{ + SpellCastResult OnCheckCast(Spell* spell, bool /*strict*/) const override + { + if (ObjectGuid target = spell->m_targets.getUnitTargetGuid()) + if (target.GetEntry() != 16943 && target.GetEntry() != 20928) // Mental Interference can be cast only on these two targets + return SPELL_FAILED_BAD_TARGETS; + + return SPELL_CAST_OK; + } +}; + void AddSC_netherstorm() { Script* pNewScript = new Script; @@ -4160,4 +4173,5 @@ void AddSC_netherstorm() RegisterSpellScript("spell_ultra_deconsolodation_zapper"); RegisterSpellScript("spell_throw_booms_doom"); RegisterSpellScript("spell_scrap_reaver_spell"); + RegisterSpellScript("spell_mental_interference"); }