diff --git a/sql/updates/world/4.3.4/2020_11_24_00_world.sql b/sql/updates/world/4.3.4/2020_11_24_00_world.sql
new file mode 100644
index 00000000000..818b57a52fb
--- /dev/null
+++ b/sql/updates/world/4.3.4/2020_11_24_00_world.sql
@@ -0,0 +1,70 @@
+UPDATE `creature_template` SET `ScriptName`= 'boss_majordomo_staghelm' WHERE `entry`= 52571;
+UPDATE `creature_template` SET `mingold`= 2500000, `maxgold`= 2500000 WHERE `entry` IN (52571, 53857);
+UPDATE `creature_template` SET `mingold`= 6250000, `maxgold`= 6250000 WHERE `entry` IN (53856, 53858);
+UPDATE `creature_template` SET `mechanic_immune_mask`= 650854271, `lootid`= `entry` WHERE `entry` IN (52571, 53857, 53856, 53858);
+UPDATE `creature_template` SET `DamageModifier`= 240, `BaseVariance`= 0.665 WHERE `entry` IN (53857, 53858);
+UPDATE `creature_template` SET `DamageModifier`= 200, `BaseVariance`= 0.665 WHERE `entry` IN (52571, 53856);
+UPDATE `creature_template` SET `mechanic_immune_mask`= 650854271 WHERE `entry` IN (52593, 53859, 53860, 53861);
+UPDATE `creature_template` SET `DamageModifier`= 240, `BaseVariance`= 0.665 WHERE `entry` IN (53859, 53861);
+UPDATE `creature_template` SET `DamageModifier`= 200, `BaseVariance`= 0.665 WHERE `entry` IN (52593, 53860);
+UPDATE `creature_template` SET `AIName`= 'NullCreatureAI', `RegenHealth`= 0, `mechanic_immune_mask`= 650854271, `flags_extra`= 0x100 | 0x40000000 WHERE `entry`= 53216;
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN
+('spell_majordomo_staghelm_form_controller',
+'spell_majordomo_staghelm_clump_check',
+'spell_majordomo_staghelm_leaping_flames_targeting',
+'spell_majordomo_staghelm_leaping_flames',
+'spell_majordomo_staghelm_searing_seeds',
+'spell_majordomo_staghelm_concentration',
+'spell_majordomo_staghelm_burning_orbs');
+
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(98386, 'spell_majordomo_staghelm_form_controller'),
+(98399, 'spell_majordomo_staghelm_clump_check'),
+(100943, 'spell_majordomo_staghelm_clump_check'),
+(101165, 'spell_majordomo_staghelm_leaping_flames_targeting'),
+(98476, 'spell_majordomo_staghelm_leaping_flames'),
+(98450, 'spell_majordomo_staghelm_searing_seeds'),
+(98229, 'spell_majordomo_staghelm_concentration'),
+(98451, 'spell_majordomo_staghelm_burning_orbs');
+
+DELETE FROM `spell_proc` WHERE `SpellId`= 98229;
+INSERT INTO `spell_proc` (`SpellId`, `SpellTypeMask`, `AttributesMask`) VALUES
+(98229, 1 | 4, 0x2);
+
+DELETE FROM `creature_text` WHERE `CreatureID`= 52571;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `comment`) VALUES
+(52571, 0, 0, 'Very well. Witness the raw power of my new Lord!', 14, 0, 100, 0, 0, 24464, 52195, 'Majordomo Staghelm - Intro'),
+(52571, 1, 0, 'The master\'s power takes on many forms...', 14, 0, 100, 0, 0, 24483, 52430, 'Majordomo Staghelm - Scorpion Form'),
+(52571, 2, 0, '|TInterface\\Icons\\inv_mount_hordescorpiong.blp:20|t%s transforms into a |c0087CEFA|Hspell:98379|h[Scorpion]|h|r!', 41, 0, 100, 0, 0, 0, 52646, 'Majordomo Staghelm - Announce Scorpion Form'),
+(52571, 3, 0, 'Behold the rage of the Firelands!', 14, 0, 100, 0, 0, 24485, 52431, 'Majordomo Staghelm - Cat Form'),
+(52571, 4, 0, '|TInterface\\Icons\\ability_druid_tigersroar.blp:20|t%s transforms into a |c0087CEFA|Hspell:98374|h[Cat]|h|r!', 41, 0, 100, 0, 0, 0, 52645, 'Majordomo Staghelm - Announce Cat Form'),
+(52571, 5, 0, 'Blaze of Glory!', 14, 0, 100, 0, 0, 24472, 52427, 'Majordomo Staghelm - Searing Seeds'),
+(52571, 6, 0, '|c00FF0000Searing Seeds begin to grow!|r', 41, 0, 100, 0, 0, 0, 52491, 'Majordomo Staghelm - Announce Searing Seeds'),
+(52571, 7, 0, 'Nothing but ash!', 14, 0, 100, 0, 0, 24478, 52422, 'Majordomo Staghelm - Burning Orbs'),
+(52571, 8, 0, '|c00FF0000%s summons Burning Orbs!|r', 41, 0, 100, 0, 0, 0, 52484, 'Majordomo Staghelm - Announce Burning Orbs'),
+(52571, 9, 0, 'Burn.', 14, 0, 100, 0, 0, 24477, 52418, 'Majordomo Staghelm - Slay'),
+(52571, 9, 1, 'Soon ALL of Azeroth will burn!', 14, 0, 100, 0, 0, 24479, 52419, 'Majordomo Staghelm - Slay'),
+(52571, 9, 2, 'So much power!', 14, 0, 100, 0, 0, 24480, 52420, 'Majordomo Staghelm - Slay'),
+(52571, 9, 3, 'You stood in the fire!', 14, 0, 100, 0, 0, 24481, 52421, 'Majordomo Staghelm - Slay'),
+(52571, 10, 0, 'My studies... had only just begun...', 14, 0, 100, 0, 0, 24471, 52432, 'Majordomo Staghelm to Player'),
+(52571, 11, 0, 'Well, well. I admire your tenacity. Baleroc stood guard over this keep for a thousand mortal lifetimes.', 14, 0, 100, 0, 0, 24473, 52415, 'Majordomo Staghelm - Baleroc Outro 1'),
+(52571, 12, 0, 'But none may enter the Firelord\'s abode!', 14, 0, 100, 0, 0, 24474, 52416, 'Majordomo Staghelm - Baleroc Outro'),
+(52571, 13, 0, 'Beg for mercy now, and I may yet allow you to live. Well, \"heroes?\" What is your answer?', 14, 0, 100, 0, 0, 24475, 52417, 'Majordomo Staghelm - Baleroc Outro');
+
+UPDATE `creature_text` SET `TextRange`= 3 WHERE `CreatureID`= 52571 AND `GroupID` IN (0, 11, 12, 13);
+
+UPDATE `creature_model_info` SET `BoundingRadius`= 1.75, `CombatReach`= 7 WHERE `DisplayID`= 38208;
+UPDATE `creature_model_info` SET `BoundingRadius`= 2, `CombatReach`= 4 WHERE `DisplayID`= 38174;
+UPDATE `creature_model_info` SET `BoundingRadius`= 1.75, `CombatReach`= 7 WHERE `DisplayID`= 38747;
+
+UPDATE `creature_template_addon` SET `auras`= '98583' WHERE `entry`= 53216;
+DELETE FROM `creature` WHERE `guid`= 338806;
+DELETE FROM `creature_addon` WHERE `guid`= 338806;
+
+DELETE FROM `spell_custom_attr` WHERE `entry` IN (98474, 100212, 100213, 100214);
+INSERT INTO `spell_custom_attr` (`entry`, `attributes`) VALUES
+(98474, 0x8),
+(100212, 0x8),
+(100213, 0x8),
+(100214, 0x8);
diff --git a/src/server/scripts/Kalimdor/Firelands/boss_majordomo_staghelm.cpp b/src/server/scripts/Kalimdor/Firelands/boss_majordomo_staghelm.cpp
new file mode 100644
index 00000000000..ab005a7cbce
--- /dev/null
+++ b/src/server/scripts/Kalimdor/Firelands/boss_majordomo_staghelm.cpp
@@ -0,0 +1,578 @@
+/*
+ * This file is part of the TrinityCore 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 General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 "firelands.h"
+#include "InstanceScript.h"
+#include "Map.h"
+#include "MotionMaster.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+
+enum Spells
+{
+ // Majordomo Staghelm
+ SPELL_ZERO_ENERGY_ZERO_REGEN = 72242,
+ SPELL_FORM_CONTROLLER = 98386,
+ SPELL_CONCENTRATION = 98256,
+ SPELL_CLUMP_CHECK = 98399,
+ SPELL_SCORPION_FORM = 98379,
+ SPELL_CAT_FORM = 98374,
+ SPELL_FURY = 97235,
+ SPELL_ADRENALINE = 97238,
+ SPELL_FLAME_SCYTHE = 98474,
+ SPELL_LEAPING_FLAMES_TARGETING = 101165,
+ SPELL_LEAPING_FLAMES_SUMMON = 101222,
+ SPELL_FIERY_CYCLONE = 98443,
+ SPELL_SEARING_SEEDS = 98450,
+ SPELL_BURNING_ORBS = 98451,
+ SPELL_BURNING_ORBS_SUMMON = 98565,
+
+ // Spirit of the Flame
+ SPELL_STUN_AND_HATE = 101224,
+
+ // Player
+ SPELL_SEARING_SEED = 98620,
+ SPELL_UNCOMMON_CONCENTRTATION = 98254,
+ SPELL_RARE_CONCENTRTATION = 98253,
+ SPELL_EPIC_CONCENTRTATION = 98252,
+ SPELL_LEGENDARY_CONCENTRATION = 98245
+};
+
+enum Events
+{
+ // Majordomo Staghelm
+ EVENT_ALLOW_COMBAT = 1,
+ EVENT_FORM_ABILITY,
+ EVENT_BALEROC_DIED_1,
+ EVENT_BALEROC_DIED_2,
+ EVENT_BALEROC_DIED_3
+};
+
+enum Actions
+{
+ ACTION_PLAYERS_CLUSTERED = 0,
+ ACTION_PLAYERS_SPLIT = 1,
+ ACTION_BALEROC_DIED = 2,
+ ACTION_DRUID_OF_THE_FLAME_DIED = 3
+};
+
+enum Phases
+{
+ PHASE_INTRO = 1,
+ PHASE_COMBAT = 2
+};
+
+enum Texts
+{
+ // Majordomo Staghelm
+ SAY_INTRO = 0,
+ SAY_SCORPION_FORM = 1,
+ SAY_ANNOUNCE_SCORPION_FORM = 2,
+ SAY_CAT_FORM = 3,
+ SAY_ANNOUNCE_CAT_FORM = 4,
+ SAY_SEARING_SEEDS = 5,
+ SAY_ANNOUNCE_SEARING_SEEDS = 6,
+ SAY_BURNING_ORBS = 7,
+ SAY_ANNOUNCE_BURNING_ORBS = 8,
+ SAY_SLAY = 9,
+ SAY_DEATH = 10,
+ SAY_BALEROC_DIED_1 = 11,
+ SAY_BALEROC_DIED_2 = 12,
+ SAY_BALEROC_DIED_3 = 13
+};
+
+enum Points
+{
+ // Majordomo Staghelm
+ POINT_INTRO = 0
+};
+
+enum class Forms
+{
+ Druid = 0,
+ Cat = 1,
+ Scorpion = 2
+};
+
+Position const MajordomoStaghelmMovePosition = { 523.4965f, -61.987846f, 83.94701f };
+
+struct boss_majordomo_staghelm : public BossAI
+{
+ boss_majordomo_staghelm(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_STAGHELM),
+ _firstTransformation(true), _splitPlayersTicks(0), _clusteredPlayersTicks(0), _currentForm(Forms::Druid), _appliedSeeds(0), _formSwitchCount(0), _killedDruidsOfTheFlameCount(0) { }
+
+ void InitializeAI() override
+ {
+ if (instance->GetBossState(DATA_MAJORDOMO_STAGHELM) == FAIL)
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ me->SetPowerType(POWER_ENERGY);
+ DoCastSelf(SPELL_ZERO_ENERGY_ZERO_REGEN);
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ BossAI::JustEngagedWith(who);
+
+ DoCastSelf(SPELL_ZERO_ENERGY_ZERO_REGEN);
+ DoCastSelf(SPELL_FORM_CONTROLLER);
+ if (IsHeroic())
+ DoCastSelf(SPELL_CONCENTRATION);
+
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+ events.SetPhase(PHASE_COMBAT);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ BossAI::EnterEvadeMode(why);
+ summons.DespawnAll();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ instance->SetBossState(DATA_MAJORDOMO_STAGHELM, FAIL);
+ me->DespawnOrUnsummon();
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ BossAI::JustDied(killer);
+ me->RemoveAllDynObjects();
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SEARING_SEEDS);
+ Talk(SAY_DEATH);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->IsPlayer())
+ Talk(SAY_SLAY, victim);
+ }
+
+ void MovementInform(uint32 motionType, uint32 pointId) override
+ {
+ if (motionType != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == POINT_INTRO)
+ events.ScheduleEvent(EVENT_ALLOW_COMBAT, 1s);
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+
+ switch (summon->GetEntry())
+ {
+ case NPC_SPIRIT_OF_THE_FLAME:
+ summon->CastSpell(summon, SPELL_STUN_AND_HATE);
+ summon->SetCorpseDelay(0);
+ summon->m_Events.AddEventAtOffset([summon]()
+ {
+ if (summon->IsAIEnabled)
+ summon->AI()->DoZoneInCombat();
+ }, 1s);
+ break;
+ case NPC_BURNING_ORB:
+ summon->SetCorpseDelay(0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_PLAYERS_CLUSTERED:
+ ++_clusteredPlayersTicks;
+ _splitPlayersTicks = 0;
+ break;
+ case ACTION_PLAYERS_SPLIT:
+ ++_splitPlayersTicks;
+ _clusteredPlayersTicks = 0;
+ break;
+ case ACTION_BALEROC_DIED:
+ me->setActive(true);
+ events.SetPhase(PHASE_INTRO);
+ events.ScheduleEvent(EVENT_BALEROC_DIED_1, 10s);
+ break;
+ case ACTION_DRUID_OF_THE_FLAME_DIED:
+ ++_killedDruidsOfTheFlameCount;
+ if (_killedDruidsOfTheFlameCount >= (Is25ManRaid() ? 6 : 3))
+ {
+ events.SetPhase(PHASE_INTRO);
+ Talk(SAY_INTRO);
+ me->GetMotionMaster()->MovePoint(POINT_INTRO, MajordomoStaghelmMovePosition, true, 5.f);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (action != ACTION_PLAYERS_CLUSTERED && action != ACTION_PLAYERS_SPLIT)
+ return;
+
+ if ((_clusteredPlayersTicks >= 3 && _currentForm != Forms::Scorpion)
+ || (_splitPlayersTicks >= 3 && _currentForm != Forms::Cat))
+ {
+ if (_formSwitchCount >= 2)
+ {
+ me->RemoveAurasDueToSpell(SPELL_SCORPION_FORM);
+ me->RemoveAurasDueToSpell(SPELL_CAT_FORM);
+ me->RemoveAurasDueToSpell(SPELL_ADRENALINE);
+ DoCastAOE(SPELL_FIERY_CYCLONE);
+
+ if (_currentForm == Forms::Cat)
+ {
+ _appliedSeeds = 0;
+ DoCastAOE(SPELL_SEARING_SEEDS);
+ Talk(SAY_SEARING_SEEDS);
+ Talk(SAY_ANNOUNCE_SEARING_SEEDS);
+ }
+ else
+ {
+ DoCastAOE(SPELL_BURNING_ORBS);
+ Talk(SAY_BURNING_ORBS);
+ Talk(SAY_ANNOUNCE_BURNING_ORBS);
+ }
+
+ _currentForm = Forms::Druid;
+ _formSwitchCount = 0;
+ return;
+ }
+
+ bool useScorpionForm = _clusteredPlayersTicks > _splitPlayersTicks;
+ Talk(useScorpionForm ? SAY_SCORPION_FORM : SAY_CAT_FORM);
+ Talk(useScorpionForm ? SAY_ANNOUNCE_SCORPION_FORM : SAY_ANNOUNCE_CAT_FORM);
+ DoCastSelf(useScorpionForm ? SPELL_SCORPION_FORM : SPELL_CAT_FORM);
+
+ if (!_firstTransformation)
+ DoCastSelf(SPELL_FURY);
+ else
+ _firstTransformation = false;
+
+ me->RemoveAurasDueToSpell(SPELL_ADRENALINE);
+ events.RescheduleEvent(EVENT_FORM_ABILITY, 400ms, 0, PHASE_COMBAT);
+ _currentForm = useScorpionForm ? Forms::Scorpion : Forms::Cat;
+ ++_formSwitchCount;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ALLOW_COMBAT:
+ DoCastSelf(SPELL_ZERO_ENERGY_ZERO_REGEN);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ break;
+ case EVENT_FORM_ABILITY:
+ if (me->GetPower(POWER_ENERGY) == me->GetMaxPower(POWER_ENERGY))
+ {
+ if (_currentForm == Forms::Scorpion)
+ DoCastVictim(SPELL_FLAME_SCYTHE);
+ else if (_currentForm == Forms::Cat)
+ DoCastAOE(SPELL_LEAPING_FLAMES_TARGETING, CastSpellExtraArgs(false).AddSpellMod(SPELLVALUE_MAX_TARGETS, 1));
+ }
+ events.Repeat(400ms);
+ break;
+ case EVENT_BALEROC_DIED_1:
+ Talk(SAY_BALEROC_DIED_1);
+ events.ScheduleEvent(EVENT_BALEROC_DIED_2, 11s);
+ break;
+ case EVENT_BALEROC_DIED_2:
+ Talk(SAY_BALEROC_DIED_2);
+ events.ScheduleEvent(EVENT_BALEROC_DIED_3, 11s);
+ break;
+ case EVENT_BALEROC_DIED_3:
+ Talk(SAY_BALEROC_DIED_3);
+ if (!me->IsEngaged())
+ me->setActive(false);
+ break;
+ default:
+ break;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ bool _firstTransformation;
+ uint32 _splitPlayersTicks;
+ uint32 _clusteredPlayersTicks;
+ Forms _currentForm;
+ uint8 _appliedSeeds;
+ uint8 _formSwitchCount;
+ uint8 _killedDruidsOfTheFlameCount;
+};
+
+class spell_majordomo_staghelm_form_controller : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_CLUMP_CHECK });
+ }
+
+ void HandlePeriodicDummy(AuraEffect const* /*aurEff*/)
+ {
+ GetTarget()->CastSpell(nullptr, SPELL_CLUMP_CHECK, true);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic.Register(&spell_majordomo_staghelm_form_controller::HandlePeriodicDummy, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+class spell_majordomo_staghelm_clump_check : public SpellScript
+{
+ bool Load() override
+ {
+ _targetThreshold = GetCaster()->GetMap()->Is25ManRaid() ? 18 : 7;
+ return GetCaster()->IsCreature();
+ }
+
+ void FilterTargets(std::list& targets)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (caster->IsAIEnabled)
+ caster->AI()->DoAction(targets.size() >= _targetThreshold ? ACTION_PLAYERS_CLUSTERED : ACTION_PLAYERS_SPLIT);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect.Register(&spell_majordomo_staghelm_clump_check::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY_2);
+ }
+private:
+ uint8 _targetThreshold = 0;
+};
+
+class spell_majordomo_staghelm_leaping_flames_targeting : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_LEAPING_FLAMES_SUMMON });
+ }
+
+ void HandleDummyEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ {
+ caster->CastSpell(nullptr, SPELL_LEAPING_FLAMES_SUMMON);
+ caster->CastSpell(GetHitUnit(), GetEffectValue());
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget.Register(&spell_majordomo_staghelm_leaping_flames_targeting::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+class spell_majordomo_staghelm_leaping_flames : public SpellScript
+{
+ void HandleJumpEffect(SpellEffIndex effIndex)
+ {
+ if (Unit* caster = GetCaster())
+ if (caster->IsAlive())
+ caster->CastSpell(caster->GetPosition(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHit.Register(&spell_majordomo_staghelm_leaping_flames::HandleJumpEffect, EFFECT_0, SPELL_EFFECT_JUMP_DEST);
+ }
+};
+
+class spell_majordomo_staghelm_searing_seeds : public SpellScript
+{
+ void CalculateDuration(std::list& targets)
+ {
+ uint32 baseValue = 10 * IN_MILLISECONDS;
+ uint32 offsetValue = (GetCaster()->GetMap()->Is25ManRaid() ? 2 : 5) * IN_MILLISECONDS;
+ uint8 targetCount = 0;
+
+ for (WorldObject* target : targets)
+ {
+ ++targetCount;
+ _durationForTarget[target->GetGUID()] = baseValue + offsetValue * targetCount;
+ }
+ }
+
+ void HandleAuraDuration(SpellEffIndex /*effIndex*/)
+ {
+ if (Aura* aura = GetHitAura())
+ {
+ aura->SetMaxDuration(_durationForTarget[GetHitUnit()->GetGUID()]);
+ aura->SetDuration(_durationForTarget[GetHitUnit()->GetGUID()]);
+ }
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect.Register(&spell_majordomo_staghelm_searing_seeds::CalculateDuration, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget.Register(&spell_majordomo_staghelm_searing_seeds::HandleAuraDuration, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+
+private:
+ std::unordered_map _durationForTarget;
+};
+
+class spell_majordomo_staghelm_searing_seeds_AuraScript : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SEARING_SEED });
+ }
+
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode().HasFlag(AuraRemoveFlags::Expired))
+ GetTarget()->CastSpell(nullptr, SPELL_SEARING_SEED, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove.Register(&spell_majordomo_staghelm_searing_seeds_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+class spell_majordomo_staghelm_concentration : public AuraScript
+{
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(
+ {
+ SPELL_UNCOMMON_CONCENTRTATION,
+ SPELL_RARE_CONCENTRTATION,
+ SPELL_EPIC_CONCENTRTATION,
+ SPELL_LEGENDARY_CONCENTRATION
+ });
+ }
+
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ RemoveConcentration(GetTarget());
+ }
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Unit* target = GetTarget();
+ uint8 power = GetTarget()->GetPower(POWER_ALTERNATE_POWER);
+
+ if (_oldPower != power)
+ {
+ uint32 oldConcentration = _currentConcentrationSpellId;
+ if (power == 100)
+ _currentConcentrationSpellId = SPELL_LEGENDARY_CONCENTRATION;
+ else if (power >= 75)
+ _currentConcentrationSpellId = SPELL_EPIC_CONCENTRTATION;
+ else if (power >= 50)
+ _currentConcentrationSpellId = SPELL_RARE_CONCENTRTATION;
+ else if (power >= 25)
+ _currentConcentrationSpellId = SPELL_UNCOMMON_CONCENTRTATION;
+
+ if (oldConcentration != _currentConcentrationSpellId)
+ {
+ target->RemoveAurasDueToSpell(oldConcentration);
+ target->CastSpell(target, _currentConcentrationSpellId, true);
+ }
+
+ _oldPower = power;
+ }
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ RemoveConcentration(GetTarget());
+ GetTarget()->SetPower(POWER_ALTERNATE_POWER, 0);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove.Register(&spell_majordomo_staghelm_concentration::HandleRemove, EFFECT_0, SPELL_AURA_ENABLE_ALT_POWER, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic.Register(&spell_majordomo_staghelm_concentration::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectProc.Register(&spell_majordomo_staghelm_concentration::HandleProc, EFFECT_0, SPELL_AURA_ENABLE_ALT_POWER);
+ }
+private:
+ void RemoveConcentration(Unit* target)
+ {
+ target->RemoveAurasDueToSpell(SPELL_UNCOMMON_CONCENTRTATION);
+ target->RemoveAurasDueToSpell(SPELL_RARE_CONCENTRTATION);
+ target->RemoveAurasDueToSpell(SPELL_EPIC_CONCENTRTATION);
+ target->RemoveAurasDueToSpell(SPELL_LEGENDARY_CONCENTRATION);
+ _currentConcentrationSpellId = 0;
+ _oldPower = 0;
+ }
+
+ uint8 _oldPower = 0;
+ uint32 _currentConcentrationSpellId = 0;
+};
+
+class spell_majordomo_staghelm_burning_orbs : public SpellScript
+{
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BURNING_ORBS_SUMMON });
+ }
+
+ void HandleDummyEffect(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ for (uint8 i = 0; i < 5; ++i)
+ caster->CastSpell(nullptr, SPELL_BURNING_ORBS_SUMMON);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget.Register(&spell_majordomo_staghelm_burning_orbs::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+void AddSC_boss_majordomo_staghelm()
+{
+ RegisterFirelandsCreatureAI(boss_majordomo_staghelm);
+ RegisterSpellScript(spell_majordomo_staghelm_form_controller);
+ RegisterSpellScript(spell_majordomo_staghelm_clump_check);
+ RegisterSpellScript(spell_majordomo_staghelm_leaping_flames_targeting);
+ RegisterSpellScript(spell_majordomo_staghelm_leaping_flames);
+ RegisterSpellAndAuraScriptPair(spell_majordomo_staghelm_searing_seeds, spell_majordomo_staghelm_searing_seeds_AuraScript);
+ RegisterSpellScript(spell_majordomo_staghelm_concentration);
+ RegisterSpellScript(spell_majordomo_staghelm_burning_orbs);
+}
diff --git a/src/server/scripts/Kalimdor/Firelands/firelands.h b/src/server/scripts/Kalimdor/Firelands/firelands.h
index f989e443286..9bd326edb79 100644
--- a/src/server/scripts/Kalimdor/Firelands/firelands.h
+++ b/src/server/scripts/Kalimdor/Firelands/firelands.h
@@ -55,6 +55,11 @@ enum FLCreatureIds
NPC_HARBINGER_OF_FLAME = 53793,
NPC_MOLTEN_EGG_TRASH = 53914,
NPC_SMOULDERING_HATCHLING = 53794,
+
+ // Majordomo Staghelm
+ NPC_SPIRIT_OF_THE_FLAME = 52593,
+ NPC_BURNING_ORB = 53216,
+ NPC_DRUID_OF_THE_FLAME = 53619
};
enum GameobjectIds
@@ -72,4 +77,6 @@ inline AI* GetFirelandsAI(T* obj)
return GetInstanceAI(obj, FirelandsScriptName);
}
+#define RegisterFirelandsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetFirelandsAI)
+
#endif // FIRELANDS_H_
diff --git a/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp b/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
index d0d856044e8..f5fb01b260d 100644
--- a/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
@@ -60,6 +60,19 @@ private:
Creature* _owner;
};
+enum MajordomoStaghelmActions
+{
+ ACTION_BALEROC_DIED = 2, // Action 0 and 1 used by encounter
+ ACTION_DRUID_OF_THE_FLAME_DIED = 3
+};
+
+enum Events
+{
+ EVENT_RESPAWN_MAJORDOMO_STAGHELM = 1
+};
+
+Position const MajordomoStaghelmSpawnPosition = { 570.2274f, -61.82986f, 90.42272f, 3.1415927f };
+Position const MajordomoStaghelmRespawnPosition = { 523.4965f, -61.987846f, 83.94701f, 3.1415927f };
class instance_firelands : public InstanceMapScript
{
@@ -76,8 +89,23 @@ class instance_firelands : public InstanceMapScript
LoadObjectData(creatureData, nullptr);
}
+ void Create() override
+ {
+ InstanceScript::Create();
+ instance->SummonCreature(BOSS_MAJORDOMO_STAGHELM, MajordomoStaghelmSpawnPosition);
+ }
+
+ void Load(char const* data) override
+ {
+ InstanceScript::Load(data);
+ if (GetBossState(DATA_MAJORDOMO_STAGHELM) != DONE)
+ instance->SummonCreature(BOSS_MAJORDOMO_STAGHELM, MajordomoStaghelmSpawnPosition);
+ }
+
void OnCreatureCreate(Creature* creature) override
{
+ InstanceScript::OnCreatureCreate(creature);
+
switch (creature->GetEntry())
{
case NPC_SMOULDERING_HATCHLING:
@@ -88,6 +116,67 @@ class instance_firelands : public InstanceMapScript
break;
}
}
+
+ void OnUnitDeath(Unit* unit) override
+ {
+ if (!unit->IsCreature())
+ return;
+
+ switch (unit->GetEntry())
+ {
+ case NPC_DRUID_OF_THE_FLAME:
+ if (Creature* majordomo = GetCreature(DATA_MAJORDOMO_STAGHELM))
+ if (majordomo->IsAIEnabled)
+ majordomo->AI()->DoAction(ACTION_DRUID_OF_THE_FLAME_DIED);
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool SetBossState(uint32 type, EncounterState state) override
+ {
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ switch (type)
+ {
+ case DATA_BALEROC:
+ if (state == DONE)
+ if (Creature* majordomo = GetCreature(DATA_MAJORDOMO_STAGHELM))
+ if (majordomo->IsAIEnabled)
+ majordomo->AI()->DoAction(ACTION_BALEROC_DIED);
+ break;
+ case DATA_MAJORDOMO_STAGHELM:
+ if (state == FAIL)
+ _events.ScheduleEvent(EVENT_RESPAWN_MAJORDOMO_STAGHELM, 30s);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ void Update(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RESPAWN_MAJORDOMO_STAGHELM:
+ instance->SummonCreature(BOSS_MAJORDOMO_STAGHELM, MajordomoStaghelmRespawnPosition);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
index 8dc472552cb..e47016ba981 100644
--- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
+++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
@@ -128,6 +128,7 @@ void AddSC_boss_alakir();
void AddSC_instance_firelands(); //Firelands
void AddSC_boss_alysrazor();
void AddSC_boss_baleroc();
+void AddSC_boss_majordomo_staghelm();
void AddSC_ashenvale();
void AddSC_azuremyst_isle();
@@ -262,6 +263,7 @@ void AddKalimdorScripts()
AddSC_instance_firelands(); //Firelands
AddSC_boss_alysrazor();
AddSC_boss_baleroc();
+ AddSC_boss_majordomo_staghelm();
AddSC_ashenvale();
AddSC_azuremyst_isle();