From 17368d7443f84fb1c40ecd2d9630add53c53ffe8 Mon Sep 17 00:00:00 2001 From: cala Date: Tue, 3 Oct 2017 14:55:43 +0200 Subject: [PATCH] Razorgore: fix exploit and event breaking case * Give NPC Orb Controller more control over things during the event. Sniffs show it is source and target for many spells in the encounter. Thanks @Tobschinski the Almighty Fish for his precious data. Many visuals and two cases of event reset/failure are now working properly * Use proper healing spell for Razorgore in transition before the last phase * Fix an exploit where players were able to kill Razorgore while bypassing most of the event and not even registering it, making it farmable at will --- sql/scriptdev2/scriptdev2.sql | 3 +- .../blackwing_lair/blackwing_lair.h | 5 + .../blackwing_lair/boss_razorgore.cpp | 121 ++++++++++++------ .../instance_blackwing_lair.cpp | 31 ++++- 4 files changed, 117 insertions(+), 43 deletions(-) diff --git a/sql/scriptdev2/scriptdev2.sql b/sql/scriptdev2/scriptdev2.sql index e7c944ca008..2a5fd3632d4 100644 --- a/sql/scriptdev2/scriptdev2.sql +++ b/sql/scriptdev2/scriptdev2.sql @@ -347,6 +347,7 @@ UPDATE gameobject_template SET ScriptName='go_father_flame' WHERE entry=175245; /* BLACKWING LAIR */ UPDATE instance_template SET ScriptName='instance_blackwing_lair' WHERE map=469; UPDATE creature_template SET ScriptName='boss_razorgore' WHERE entry=12435; +UPDATE creature_template SET ScriptName='npc_blackwing_orb' WHERE entry=14449; UPDATE gameobject_template SET ScriptName='go_black_dragon_egg' WHERE entry=177807; UPDATE creature_template SET ScriptName='boss_vaelastrasz' WHERE entry=13020; UPDATE creature_template SET ScriptName='boss_broodlord' WHERE entry=12017; @@ -3478,7 +3479,7 @@ INSERT INTO script_texts (entry,content_default,sound,type,language,emote,commen (-1469022,'You\'ll pay for forcing me to do this.',8275,1,0,0,'razorgore SAY_EGGS_BROKEN1'), (-1469023,'Fools! These eggs are more precious than you know!',8276,1,0,0,'razorgore SAY_EGGS_BROKEN2'), (-1469024,'No - not another one! I\'ll have your heads for this atrocity!',8277,1,0,0,'razorgore SAY_EGGS_BROKEN3'), -(-1469025,'If I fall into the abyss I\'ll take all of you mortals with me...',8278,1,0,0,'razorgore SAY_DEATH'), +(-1469025,'If I fall into the abyss I\'ll take all of you mortals with me...',8278,1,0,0,'razorgore SAY_RAZORGORE_DEATH'), (-1469026,'Too late, friends! Nefarius\' corruption has taken hold...I cannot...control myself.',8281,1,0,1,'vaelastrasz SAY_LINE1'), (-1469027,'I beg you, mortals - FLEE! Flee before I lose all sense of control! The black fire rages within my heart! I MUST- release it!',8282,1,0,1,'vaelastrasz SAY_LINE2'), diff --git a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h index 2bb56af259b..7980ba4d4d7 100644 --- a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h +++ b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h @@ -53,12 +53,17 @@ enum EMOTE_ORB_SHUT_OFF = -1469035, EMOTE_TROOPS_FLEE = -1469033, // emote by Nefarian's Troops npc + SAY_RAZORGORE_DEATH = -1469025, // Spells used by the monster generator in Razorgore encounter // SPELL_SUMMON_LEGIONNAIRES = 19824, // Periodically triggers 19826 SPELL_SUMMON_LEGIONNAIRE = 19826, SPELL_SUMMON_MAGE = 19827, SPELL_SUMMON_DRAGONSPAWN = 19828, + SPELL_WARMING_FLAMES = 23040, // Used by Razorgore to fully heal in in phase 1 to 2 transition + SPELL_CONTROL_ORB = 23018, // Visual used by Grethok the Controller + SPELL_FIREBALL = 23024, // Used by Razorgore to reset the event (and kill everyone like a badass) + SPELL_EXPLODE_ORB = 20037, // used if attacked without destroying the eggs - triggers 20038 MAX_EGGS_DEFENDERS = 4, MAX_DRAGONSPAWN = 12, diff --git a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp index c535deddd91..7a47d5b8e62 100644 --- a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp +++ b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Boss_Razorgore SD%Complete: 95 -SDComment: When casting spell Explode Orb all triggers are killed by the triggered spell 20038 casted by trigger NPCs 16604 (including some of those): this breaks the event. Triggers should survive/not be targeted. Possibly a core issue. +SDComment: Threat management after Mind Control is released needs core support (boss should have aggro on its previous controller and its previous victim should have threat transfered from boss to controlling player) SDCategory: Blackwing Lair EndScriptData */ @@ -29,11 +29,9 @@ enum SAY_EGGS_BROKEN_1 = -1469022, SAY_EGGS_BROKEN_2 = -1469023, SAY_EGGS_BROKEN_3 = -1469024, - SAY_DEATH = -1469025, - SPELL_POSSESS = 23014, // visual effect and increase the damage taken + SPELL_POSSESS_VISUAL = 23014, // visual effect and increase the damage taken SPELL_DESTROY_EGG = 19873, - SPELL_EXPLODE_ORB = 20037, // used if attacked without destroying the eggs - triggers 20038 SPELL_CLEAVE = 19632, SPELL_WARSTOMP = 24375, @@ -51,7 +49,6 @@ struct boss_razorgoreAI : public ScriptedAI instance_blackwing_lair* m_pInstance; - uint32 m_uiIntroVisualTimer; uint32 m_uiCleaveTimer; uint32 m_uiWarStompTimer; uint32 m_uiFireballVolleyTimer; @@ -61,7 +58,6 @@ struct boss_razorgoreAI : public ScriptedAI void Reset() override { - m_uiIntroVisualTimer = 5000; m_bEggsExploded = false; m_uiCleaveTimer = urand(4000, 8000); @@ -70,18 +66,6 @@ struct boss_razorgoreAI : public ScriptedAI m_uiFireballVolleyTimer = urand(15000, 20000); } - void JustDied(Unit* /*pKiller*/) override - { - if (m_pInstance) - { - // Don't set instance data unless all eggs are destroyed - if (m_pInstance->GetData(TYPE_RAZORGORE) != SPECIAL) - return; - - m_pInstance->SetData(TYPE_RAZORGORE, DONE); - } - } - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage, DamageEffectType /*damagetype*/) override { if (uiDamage < m_creature->GetHealth()) @@ -103,8 +87,8 @@ struct boss_razorgoreAI : public ScriptedAI uiDamage = 0; m_bEggsExploded = true; m_pInstance->SetData(TYPE_RAZORGORE, FAIL); - DoScriptText(SAY_DEATH, m_creature); - DoCastSpellIfCan(m_creature, SPELL_EXPLODE_ORB, CAST_TRIGGERED); + DoScriptText(SAY_RAZORGORE_DEATH, m_creature); + m_creature->CastSpell(m_creature, SPELL_FIREBALL, TRIGGERED_OLD_TRIGGERED); m_creature->ForcedDespawn(5000); } } @@ -118,28 +102,7 @@ struct boss_razorgoreAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - { - // Set visual only on OOC timer - if (m_uiIntroVisualTimer) - { - if (m_uiIntroVisualTimer <= uiDiff) - { - if (!m_pInstance) - { - script_error_log("Instance Blackwing Lair: ERROR Failed to load instance data for this instace."); - return; - } - - if (Creature* pOrbTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER)) - pOrbTrigger->CastSpell(m_creature, SPELL_POSSESS, TRIGGERED_NONE); - m_uiIntroVisualTimer = 0; - } - else - m_uiIntroVisualTimer -= uiDiff; - } - return; - } // Cleave if (m_uiCleaveTimer < uiDiff) @@ -203,6 +166,77 @@ CreatureAI* GetAI_boss_razorgore(Creature* pCreature) return new boss_razorgoreAI(pCreature); } +struct npc_blackwing_orbAI : public ScriptedAI +{ + npc_blackwing_orbAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_blackwing_lair*)pCreature->GetInstanceData(); + Reset(); + } + + instance_blackwing_lair* m_pInstance; + + uint32 m_uiIntroVisualTimer; + + void Reset() override + { + m_uiIntroVisualTimer = 4000; + } + + void SpellHit(Unit* /* pCaster */, const SpellEntry* pSpell) override + { + // If hit by Razorgore's fireball: explodes everything in the room + if (pSpell->Id == SPELL_FIREBALL) + m_creature->CastSpell(m_creature, SPELL_EXPLODE_ORB, TRIGGERED_IGNORE_UNATTACKABLE_FLAG); + } + + void UpdateAI(const uint32 uiDiff) override + { + // Set visual only on OOC timer + if (m_uiIntroVisualTimer) + { + if (m_uiIntroVisualTimer <= uiDiff) + { + if (!m_pInstance) + { + script_error_log("Instance Blackwing Lair: ERROR Failed to load instance data for this instace."); + return; + } + + // If Razorgore is not respawned yet: wait + if (Creature* pRazorgore = m_pInstance->GetSingleCreatureFromStorage(NPC_RAZORGORE)) + { + if (!(pRazorgore->isAlive())) + { + m_uiIntroVisualTimer = 2000; + return; + } + } + + // If Grethok the Controller is here and spawned, start the visual, else wait for him + if (Creature* pGrethok = GetClosestCreatureWithEntry(m_creature, NPC_GRETHOK_CONTROLLER, 2.0f)) + { + if (pGrethok->isAlive()) + { + m_creature->CastSpell(m_creature, SPELL_POSSESS_VISUAL, TRIGGERED_OLD_TRIGGERED); + pGrethok->CastSpell(pGrethok, SPELL_CONTROL_ORB, TRIGGERED_OLD_TRIGGERED); + m_uiIntroVisualTimer = 0; + } + } + else + m_uiIntroVisualTimer = 2000; + } + else + m_uiIntroVisualTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_blackwing_orb(Creature* pCreature) +{ + return new npc_blackwing_orbAI(pCreature); +} + bool EffectDummyGameObj_go_black_dragon_egg(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, GameObject* pGOTarget, ObjectGuid /*originalCasterGuid*/) { if (uiSpellId == SPELL_DESTROY_EGG && uiEffIndex == EFFECT_INDEX_1) @@ -241,6 +275,11 @@ void AddSC_boss_razorgore() pNewScript->GetAI = &GetAI_boss_razorgore; pNewScript->RegisterSelf(); + pNewScript = new Script; + pNewScript->Name = "npc_blackwing_orb"; + pNewScript->GetAI = &GetAI_npc_blackwing_orb; + pNewScript->RegisterSelf(); + pNewScript = new Script; pNewScript->Name = "go_black_dragon_egg"; pNewScript->pEffectDummyGO = &EffectDummyGameObj_go_black_dragon_egg; diff --git a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp index 697a0513d1c..89f319ab86f 100644 --- a/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp +++ b/src/game/AI/ScriptDevAI/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp @@ -130,6 +130,11 @@ void instance_blackwing_lair::SetData(uint32 uiType, uint32 uiData) // Reset the Orb of Domination and the eggs DoToggleGameObjectFlags(GO_ORB_OF_DOMINATION, GO_FLAG_NO_INTERACT, true); + if (Creature* pOrb = GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER)) + { + if (pOrb->isAlive()) + pOrb->AI()->EnterEvadeMode(); + } // Reset defenders for (GuidList::const_iterator itr = m_lDefendersGuids.begin(); itr != m_lDefendersGuids.end(); ++itr) @@ -274,7 +279,7 @@ void instance_blackwing_lair::SetData64(uint32 uiData, uint64 uiGuid) if (Creature* pRazorgore = GetSingleCreatureFromStorage(NPC_RAZORGORE)) { pRazorgore->RemoveAllAuras(); - pRazorgore->SetHealth(pRazorgore->GetMaxHealth()); + pRazorgore->CastSpell(pRazorgore, SPELL_WARMING_FLAMES, TRIGGERED_OLD_TRIGGERED); } // All defenders evade and despawn @@ -312,6 +317,30 @@ void instance_blackwing_lair::OnCreatureDeath(Creature* pCreature) if (Creature* pOrbTrigger = GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER)) pOrbTrigger->InterruptNonMeleeSpells(false); break; + case NPC_RAZORGORE: + // Only set the event as done if Razorgore dies in last phase + if (GetData(TYPE_RAZORGORE) == SPECIAL) + { + SetData(TYPE_RAZORGORE, DONE); + break; + } + + // If the event is not already failed in Razorgore script, then force group wipe by making the boss trigger an AoE + // this is basically a duplicate of what is in Razorgore script because when the boss is Mind Controlled the AI is overriden + // So we have to handle it in the instance script instead to prevent the event to be stucked or exploited + if (GetData(TYPE_RAZORGORE) != FAIL) + { + if (Creature* pRazorgore = GetSingleCreatureFromStorage(NPC_RAZORGORE)) + { + pRazorgore->CastSpell(pRazorgore, SPELL_FIREBALL, TRIGGERED_OLD_TRIGGERED); + SetData(TYPE_RAZORGORE, FAIL); + DoScriptText(SAY_RAZORGORE_DEATH, pRazorgore); + pRazorgore->ForcedDespawn(); + } + if (Creature* pOrbTrigger = GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER)) + pOrbTrigger->CastSpell(pOrbTrigger, SPELL_EXPLODE_ORB, TRIGGERED_IGNORE_UNATTACKABLE_FLAG); + } + break; case NPC_BLACKWING_LEGIONNAIRE: case NPC_BLACKWING_MAGE: m_uiBlackwingDefCount--;