From 7df43c36a5238edf252e7bec209fda0e08ede052 Mon Sep 17 00:00:00 2001 From: Nefertumm Date: Fri, 3 Dec 2021 00:18:40 -0800 Subject: [PATCH] fix(Scripts/BlackrockSpire): rewrite Mor Grayhoof fight (#9374) --- .../rev_1637946798791977700.sql | 10 + .../BlackrockSpire/blackrock_spire.h | 3 +- .../BlackrockSpire/boss_mor_grayhoof.cpp | 232 ++++++++++++++++++ .../eastern_kingdoms_script_loader.cpp | 2 + 4 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 data/sql/updates/pending_db_world/rev_1637946798791977700.sql create mode 100644 src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mor_grayhoof.cpp diff --git a/data/sql/updates/pending_db_world/rev_1637946798791977700.sql b/data/sql/updates/pending_db_world/rev_1637946798791977700.sql new file mode 100644 index 000000000..46e3125ea --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1637946798791977700.sql @@ -0,0 +1,10 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1637946798791977700'); + +DELETE FROM `creature_text` WHERE `CreatureID` = 16080; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(16080, 0, 0, 'All of Nature\'s might is at my disposal, puny mortals. Let us see which of my many forms it will be that ends your suffering!', 14, 0, 100, 0, 0, 0, 11966, 0, 'Mor Grayhoof - ON AGGRO'), +(16080, 1, 0, 'Though I move on in peace, you all have my undying gratitude. Thank you for freeing me of the curse of my folly and greed.', 14, 0, 100, 0, 0, 0, 11861, 0, 'Mor Grayhoof - ON DEATH'); + +UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'boss_mor_grayhoof' WHERE `entry` = 16080; + +DELETE FROM `smart_scripts` WHERE `entryorguid` = 16080 AND `source_type` = 0; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h index 88f36015c..dbe855aea 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h @@ -50,7 +50,8 @@ enum DataTypes DATA_HALL_RUNE_5 = 20, DATA_HALL_RUNE_6 = 21, DATA_HALL_RUNE_7 = 22, - DATA_SOLAKAR_FLAMEWREATH = 23 + DATA_SOLAKAR_FLAMEWREATH = 23, + DATA_MOR_GRAYHOOF = 24 }; enum CreaturesIds diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mor_grayhoof.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mor_grayhoof.cpp new file mode 100644 index 000000000..5651e276b --- /dev/null +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mor_grayhoof.cpp @@ -0,0 +1,232 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "blackrock_spire.h" +#include "TaskScheduler.h" + +enum Texts +{ + SAY_AGGRO = 0, + SAY_DEATH, +}; + +enum Spells +{ + // Druid spell + SPELL_HURRICANE = 27530, + SPELL_MOONFIRE = 27737, + SPELL_SHOCK = 15605, + + // Healing spell + SPELL_HEALING_TOUCH = 27527, + SPELL_REJUVENATION = 27532, + + // Bear spell + SPELL_BEAR_FORM = 27543, + SPELL_DEMORALIZING_ROAR = 27551, + SPELL_MAUL = 27553, + SPELL_SWIPE = 27554, + + // Cat spell + SPELL_CAT_FORM = 27545, + SPELL_SHRED = 27555, + SPELL_RAKE = 27556, + SPELL_FEROCIOUS_BITE = 27557, + + // Dragon form + SPELL_FAERIE_DRAGON_FORM = 27546, + SPELL_ARCANE_EXPLOSION = 22271, + SPELL_REFLECTION = 27564, + SPELL_CHAIN_LIGHTING = 27567, + SPELL_SLEEP = 20663 // Guessed +}; + +enum Phases +{ + PHASE_HUMAN = 0, + PHASE_CAT, + PHASE_BEAR, + PHASE_FAERIE +}; + +std::vector catSpells = { SPELL_SHRED, SPELL_RAKE, SPELL_FEROCIOUS_BITE }; +std::vector humanSpells = { SPELL_HURRICANE, SPELL_MOONFIRE, SPELL_SHOCK, SPELL_HEALING_TOUCH, SPELL_REJUVENATION }; +std::vector bearSpells = { SPELL_DEMORALIZING_ROAR, SPELL_MAUL, SPELL_SWIPE }; +std::vector faerieSpells = { SPELL_ARCANE_EXPLOSION, SPELL_REFLECTION, SPELL_CHAIN_LIGHTING, SPELL_SLEEP }; + +struct boss_mor_grayhoof : public BossAI +{ + boss_mor_grayhoof(Creature* creature) : BossAI(creature, DATA_MOR_GRAYHOOF) + { + _scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); + + _sleepTargetThreat = 0.f; + } + + void Reset() override + { + _scheduler.CancelAll(); + _phase = PHASE_HUMAN; + } + + void CastRandomSpell(uint8 phase) + { + uint32 spell; + switch (phase) + { + case PHASE_HUMAN: + spell = Acore::Containers::SelectRandomContainerElement(humanSpells); + if (spell == SPELL_REJUVENATION || spell == SPELL_HEALING_TOUCH) + { + DoCastSelf(spell); + } + else + { + DoCastAOE(spell); + } + break; + case PHASE_BEAR: + spell = Acore::Containers::SelectRandomContainerElement(bearSpells); + DoCastVictim(spell); + break; + case PHASE_CAT: + spell = Acore::Containers::SelectRandomContainerElement(catSpells); + DoCastVictim(spell); + break; + case PHASE_FAERIE: + spell = Acore::Containers::SelectRandomContainerElement(faerieSpells); + if (spell == SPELL_SLEEP) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.f, true)) + { + me->CastSpell(target, SPELL_SLEEP); + + // Sleep can target tank, we need to drop threat temporarily on the target. + _sleepTargetGUID = target->GetGUID(); + _sleepTargetThreat = me->getThreatMgr().getThreat(target); + me->getThreatMgr().modifyThreatPercent(target, -100); + _scheduler.Schedule(10s, [this](TaskContext /*context*/) + { + if (Unit* sleepTarget = ObjectAccessor::GetUnit(*me, _sleepTargetGUID)) + { + me->getThreatMgr().addThreat(sleepTarget, _sleepTargetThreat); + } + }); + } + } + else + { + DoCastVictim(spell); + } + break; + default: + break; + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override + { + if (_phase == PHASE_HUMAN && me->HealthBelowPct(75.f)) + { + _phase = PHASE_BEAR; + me->CastStop(); + _scheduler.DelayGroup(PHASE_HUMAN, 10s); + DoCastSelf(SPELL_BEAR_FORM); + _scheduler.Schedule(3s, PHASE_BEAR, [this](TaskContext context) + { + CastRandomSpell(PHASE_BEAR); + if (context.GetRepeatCounter() <= 3) + { + context.Repeat(); + } + }); + } + else if (_phase == PHASE_BEAR && me->HealthBelowPct(50.f)) + { + _phase = PHASE_CAT; + _scheduler.DelayGroup(PHASE_HUMAN, 10s); + me->CastStop(); + DoCastSelf(SPELL_CAT_FORM); + _scheduler.Schedule(3s, PHASE_CAT, [this](TaskContext context) + { + CastRandomSpell(PHASE_CAT); + if (context.GetRepeatCounter() <= 3) + { + context.Repeat(); + } + }); + } + else if (_phase == PHASE_CAT && me->HealthBelowPct(25.f)) + { + _phase = PHASE_FAERIE; + _scheduler.CancelGroup(PHASE_HUMAN); + me->CastStop(); + DoCastSelf(SPELL_FAERIE_DRAGON_FORM); + _scheduler.Schedule(5s, 10s, PHASE_FAERIE, [this](TaskContext context) + { + CastRandomSpell(PHASE_FAERIE); + context.Repeat(5s, 10s); + }); + } + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + _scheduler.Schedule(5s, 10s, PHASE_HUMAN, [this](TaskContext context) + { + CastRandomSpell(PHASE_HUMAN); + context.Repeat(); + }); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + { + return; + } + + _scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + +protected: + TaskScheduler _scheduler; + uint8 _phase; + ObjectGuid _sleepTargetGUID; + float _sleepTargetThreat; +}; + +void AddSC_boss_mor_grayhoof() +{ + RegisterBlackrockSpireCreatureAI(boss_mor_grayhoof); +} diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index 0b1017341..40ab731a0 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -46,6 +46,7 @@ void AddSC_boss_rend_blackhand(); void AddSC_boss_urok_doomhowl(); void AddSC_boss_solakar_flamewreath(); void AddSC_boss_quartermasterzigris(); +void AddSC_boss_mor_grayhoof(); void AddSC_instance_blackrock_spire(); void AddSC_boss_razorgore(); //Blackwing lair void AddSC_boss_vaelastrasz(); @@ -187,6 +188,7 @@ void AddEasternKingdomsScripts() AddSC_boss_rend_blackhand(); AddSC_boss_urok_doomhowl(); AddSC_boss_quartermasterzigris(); + AddSC_boss_mor_grayhoof(); AddSC_instance_blackrock_spire(); AddSC_boss_razorgore(); //Blackwing lair AddSC_boss_vaelastrasz();