aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKrudor <erikstrandberg93@hotmail.com>2017-08-22 18:28:07 +0200
committerShauren <shauren.trinity@gmail.com>2017-08-22 18:28:07 +0200
commit28ec50b0534c721e613d68b7b1daa73d573fbc17 (patch)
tree8bfdfc604ce6d0201fbfe8b2d2464717ba378b53 /src
parentcc6ca733d8064e12c7b11590250a99f696bbf9c5 (diff)
Scripts/Firelands: Baleroc
Closes #17527
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Spells/SpellMgr.cpp22
-rw-r--r--src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp874
-rw-r--r--src/server/scripts/Kalimdor/Firelands/firelands.cpp318
-rw-r--r--src/server/scripts/Kalimdor/Firelands/firelands.h66
-rw-r--r--src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp53
-rw-r--r--src/server/scripts/Kalimdor/kalimdor_script_loader.cpp4
6 files changed, 1335 insertions, 2 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 28534345dad..0a2ae57ffd1 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3676,6 +3676,28 @@ void SpellMgr::LoadSpellInfoCorrections()
});
// ENDOF ISLE OF CONQUEST SPELLS
+ //
+ // FIRELANDS SPELLS
+ //
+ // Torment Searcher
+ ApplySpellFix({ 99253 }, [](SpellInfo* spellInfo)
+ {
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_15_YARDS);
+ });
+
+ // Torment Damage
+ ApplySpellFix({ 99256 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
+ });
+
+ // Blaze of Glory
+ ApplySpellFix({ 99252 }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CHANGE_MAP;
+ });
+ // ENDOF FIRELANDS SPELLS
+
// Summon Master Li Fei
ApplySpellFix({ 102445 }, [](SpellInfo* spellInfo)
{
diff --git a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
new file mode 100644
index 00000000000..4f012d7f2d1
--- /dev/null
+++ b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
@@ -0,0 +1,874 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "Containers.h"
+#include "firelands.h"
+#include "GridNotifiers.h"
+#include "PassiveAI.h"
+#include "Spell.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+#include "SpellMgr.h"
+
+enum Spells
+{
+ // Baleroc
+ //SPELL_LEASH = 101514, // Server-side, used to keep him in his encounter area? TrinityCore does not need a spell to handle this
+ SPELL_BLADES_OF_BALEROC = 99342,
+ SPELL_INFERNO_BLADE = 99350,
+ SPELL_INFERNO_STRIKE = 99351,
+ SPELL_DECIMATION_BLADE = 99352,
+ SPELL_DECIMATION_BLADE_2 = 99405,
+ SPELL_DECIMATING_STRIKE = 99353,
+ SPELL_BLAZE_OF_GLORY = 99252,
+ SPELL_INCENDIARY_SOUL = 99369,
+ SPELL_SHARDS_OF_TORMENT = 99259,
+ SPELL_SHARDS_OF_TORMENT_SUMMON = 99260,
+ SPELL_TORMENT_PRE_VISUAL = 99258,
+ SPELL_TORMENT_ACTIVE = 99254,
+ SPELL_TORMENT_PERIODIC = 99255,
+ SPELL_WAVE_OF_TORMENT = 99261,
+ SPELL_TORMENTED = 99257,
+ SPELL_TORMENT = 99256,
+ SPELL_COUNTDOWN = 99515,
+ SPELL_COUNTDOWN_AURA = 99516,
+ SPELL_COUNTDOWN_3 = 99517,
+ SPELL_COUNTDOWN_AOE_EXPLOSION = 99518,
+ SPELL_COUNTDOWN_VISUAL_LINK = 99519,
+ SPELL_VITAL_SPARK = 99262,
+ SPELL_VITAL_FLAME = 99263,
+ SPELL_BERSERK = 26662,
+};
+
+enum Emotes
+{
+ SAY_AGGRO = 0,
+ SAY_SHARDS_OF_TORMENT = 1,
+ SAY_INFERNO_BLADE = 2,
+ SAY_DECIMATION_BLADE = 3,
+ SAY_KILL = 4,
+ SAY_DEATH = 5,
+ SAY_ENRAGE = 6,
+ EMOTE_ENRAGE = 7,
+ EMOTE_DECIMATION_BLADE = 8,
+ EMOTE_INFERNO_BLADE = 9,
+};
+
+enum Guids
+{
+ GUID_TORMENTED = 1,
+};
+
+enum Actions
+{
+ ACTION_EQUIP_DEFAULT = 1,
+ ACTION_EQUIP_INFERNO_BLADE = 2,
+ ACTION_EQUIP_DECIMATION_BLADE = 3,
+};
+
+
+enum Misc
+{
+ EQUIP_DEFAULT = 1,
+ EQUIP_INFERNO_BLADE = 2,
+ EQUIP_DECIMATION_BLADE = 3,
+};
+
+enum Phases
+{
+ PHASE_NONE = 0,
+ PHASE_ONE = 1
+};
+
+// http://www.wowhead.com/npc=53494/baleroc
+struct boss_baleroc : public firelands_bossAI
+{
+ boss_baleroc(Creature* creature) : firelands_bossAI(creature, DATA_BALEROC), _canYellKilledPlayer(true)
+ {
+ scheduler.SetValidator([this]
+ {
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ });
+ }
+
+ void Reset() override
+ {
+ firelands_bossAI::Reset();
+ _canYellKilledPlayer = true;
+ EquipWeapon(EQUIP_DEFAULT);
+ }
+
+ void EnterCombat(Unit* target) override
+ {
+ firelands_bossAI::EnterCombat(target);
+
+ Talk(SAY_AGGRO);
+ PreparePhase(PHASE_ONE);
+
+ _sharedThePain.clear();
+ }
+
+ void PreparePhase(Phases phase)
+ {
+ //events.SetPhase(phase);
+
+ switch (phase)
+ {
+ case PHASE_ONE:
+ scheduler.Schedule(Milliseconds(8500), [this](TaskContext context)
+ {
+ me->AddAura(SPELL_INCENDIARY_SOUL, me); // No cast
+ DoCastVictim(SPELL_BLAZE_OF_GLORY);
+ context.Repeat(Milliseconds(11500));
+ });
+ scheduler.Schedule(Seconds(5), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_SHARDS_OF_TORMENT);
+ context.Repeat(Seconds(34));
+ });
+ if (me->GetMap()->IsHeroic())
+ {
+ scheduler.Schedule(Seconds(26), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_COUNTDOWN);
+ context.Repeat(Seconds(48));
+ });
+ }
+ scheduler.Schedule(Milliseconds(30500), [this](TaskContext context)
+ {
+ DoCastSelf(SPELL_BLADES_OF_BALEROC);
+ context.Repeat(Seconds(47));
+ });
+ scheduler.Schedule(Minutes(6), [this](TaskContext)
+ {
+ Talk(SAY_ENRAGE);
+ Talk(EMOTE_ENRAGE);
+ DoCastSelf(SPELL_BERSERK);
+ });
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_EQUIP_DEFAULT:
+ case ACTION_EQUIP_INFERNO_BLADE:
+ case ACTION_EQUIP_DECIMATION_BLADE:
+ EquipWeapon(action);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER && _canYellKilledPlayer)
+ {
+ _canYellKilledPlayer = false;
+ Talk(SAY_KILL);
+
+ separateScheduler.Schedule(Seconds(8), [this](TaskContext)
+ {
+ _canYellKilledPlayer = true;
+ });
+ }
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ Talk(SAY_DEATH);
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLAZE_OF_GLORY);
+ firelands_bossAI::JustDied(killer);
+ }
+
+ void EnterEvadeMode(EvadeReason reason) override
+ {
+ summons.DespawnAll();
+ instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLAZE_OF_GLORY);
+ firelands_bossAI::EnterEvadeMode(reason);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ scheduler.Update(diff);
+ separateScheduler.Update(diff);
+ firelands_bossAI::UpdateAI(diff);
+ }
+
+ void SetGUID(ObjectGuid guid, int32 type = 0) override
+ {
+ switch (type)
+ {
+ case GUID_TORMENTED:
+ ++_sharedThePain[guid];
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case GUID_TORMENTED:
+ for (auto const& entry : _sharedThePain)
+ if (entry.second > 3)
+ return 1;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+private:
+ void EquipWeapon(uint8 equipment) const
+ {
+ switch (equipment)
+ {
+ case EQUIP_DEFAULT:
+ me->LoadEquipment(equipment);
+ me->SetCanDualWield(true);
+ break;
+ case EQUIP_INFERNO_BLADE:
+ case EQUIP_DECIMATION_BLADE:
+ me->LoadEquipment(equipment);
+ me->SetCanDualWield(false);
+ break;
+ default:
+ break;
+ }
+ }
+ // Our default TaskScheduler has a UNIT_STATE_CASTING validator that would get in the way of certain tasks, run them on a separate track.
+ TaskScheduler separateScheduler;
+ bool _canYellKilledPlayer;
+ std::unordered_map<ObjectGuid, uint32> _sharedThePain;
+};
+
+// http://www.wowhead.com/npc=53495/shard-of-torment
+struct npc_shard_of_torment : public NullCreatureAI
+{
+ npc_shard_of_torment(Creature* creature) : NullCreatureAI(creature) { }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ DoCastAOE(SPELL_TORMENT_PRE_VISUAL);
+ scheduler.Schedule(Milliseconds(4400), [this](TaskContext)
+ {
+ me->RemoveAurasDueToSpell(SPELL_TORMENT_PRE_VISUAL);
+ DoCastAOE(SPELL_TORMENT_ACTIVE);
+ scheduler.Schedule(Milliseconds(1100), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_WAVE_OF_TORMENT);
+ context.Repeat(Seconds(1));
+ });
+ });
+ }
+
+ void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) override
+ {
+ if (spell->Id != SPELL_TORMENT)
+ return;
+
+ scheduler.CancelAll();
+ scheduler.Schedule(Milliseconds(1100), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_WAVE_OF_TORMENT);
+ context.Repeat(Seconds(1));
+ });
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler scheduler;
+};
+
+// http://www.wowhead.com/spell=99342/blades-of-baloroc
+class spell_baleroc_blades_of_baleroc : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_blades_of_baleroc);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_INFERNO_BLADE, SPELL_DECIMATION_BLADE });
+ }
+
+ void ChooseBlade(SpellEffIndex /*effIndex*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster || !caster->IsAIEnabled)
+ return;
+
+ switch (urand(1, 2))
+ {
+ case 1:
+ caster->AI()->DoCast(SPELL_INFERNO_BLADE);
+ caster->AI()->Talk(SAY_INFERNO_BLADE);
+ caster->AI()->Talk(EMOTE_INFERNO_BLADE);
+ break;
+ case 2:
+ caster->AI()->DoCast(SPELL_DECIMATION_BLADE);
+ caster->AI()->Talk(SAY_DECIMATION_BLADE);
+ caster->AI()->Talk(EMOTE_DECIMATION_BLADE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_baleroc_blades_of_baleroc::ChooseBlade, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+// http://www.wowhead.com/spell=99350/inferno-blade
+class spell_baleroc_inferno_blade : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_inferno_blade);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTarget()->IsAIEnabled)
+ GetTarget()->GetAI()->DoAction(ACTION_EQUIP_INFERNO_BLADE);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTarget()->IsAIEnabled)
+ GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DEFAULT);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_baleroc_inferno_blade::OnApply, EFFECT_0, SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_baleroc_inferno_blade::OnRemove, EFFECT_0, SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// http://www.wowhead.com/spell=99352/decimation-blade
+class spell_baleroc_decimation_blade : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_decimation_blade);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTarget()->IsAIEnabled)
+ GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DECIMATION_BLADE);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTarget()->IsAIEnabled)
+ GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DEFAULT);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_baleroc_decimation_blade::OnApply, EFFECT_1, SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_baleroc_decimation_blade::OnRemove, EFFECT_1, SPELL_AURA_OVERRIDE_AUTOATTACK_WITH_MELEE_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// http://www.wowhead.com/spell=99353/decimating-strike
+class spell_baleroc_decimating_strike : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_decimating_strike);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ if (!spellInfo->GetEffect(EFFECT_0))
+ return false;
+ SpellEffectInfo const* spellEffectInfo = spellInfo->GetEffect(EFFECT_2);
+ return spellEffectInfo && ValidateSpellInfo({ uint32(spellEffectInfo->BasePoints) });
+ }
+
+ void ChangeDamage()
+ {
+ int32 healthPctDmg = GetHitUnit()->CountPctFromMaxHealth(GetSpellInfo()->GetEffect(EFFECT_0)->BasePoints);
+ int32 flatDmg = GetSpellInfo()->GetEffect(EFFECT_2)->BasePoints;
+
+ SetHitDamage(healthPctDmg < flatDmg ? flatDmg : healthPctDmg);
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_baleroc_decimating_strike::ChangeDamage);
+ }
+};
+
+// http://www.wowhead.com/spell=99515/countdown
+class spell_baleroc_countdown_aoe_dummy : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_countdown_aoe_dummy);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_COUNTDOWN_VISUAL_LINK, SPELL_COUNTDOWN_AURA });
+ }
+
+ void CastSpellLink()
+ {
+ Unit* firstTarget = ObjectAccessor::GetUnit(*GetCaster(), _targets.front());
+ Unit* secondTarget = ObjectAccessor::GetUnit(*GetCaster(), _targets.back());
+ if (!firstTarget || !secondTarget)
+ return;
+
+ firstTarget->CastSpell(secondTarget, SPELL_COUNTDOWN_VISUAL_LINK, true);
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_COUNTDOWN_AURA);
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster)
+ return;
+
+ if (WorldObject* tank = caster->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO))
+ targets.remove(tank);
+
+ if (targets.size() < 2)
+ {
+ FinishCast(SPELL_FAILED_NO_VALID_TARGETS);
+ return;
+ }
+
+ Trinity::Containers::RandomResize(targets, 2);
+
+ _targets.push_back(targets.front()->GetGUID());
+ _targets.push_back(targets.back()->GetGUID());
+ }
+
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_baleroc_countdown_aoe_dummy::CastSpellLink);
+ OnEffectHitTarget += SpellEffectFn(spell_baleroc_countdown_aoe_dummy::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_baleroc_countdown_aoe_dummy::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+
+ GuidList _targets;
+};
+
+// http://www.wowhead.com/spell=99516/countdown
+class spell_baleroc_countdown : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_countdown);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_COUNTDOWN_VISUAL_LINK, SPELL_COUNTDOWN_AOE_EXPLOSION });
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_VISUAL_LINK);
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ GetTarget()->CastSpell(static_cast<Unit*>(nullptr), SPELL_COUNTDOWN_AOE_EXPLOSION, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_baleroc_countdown::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// http://www.wowhead.com/spell=99517/countdown
+class spell_baleroc_countdown_proximity_check : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_countdown_proximity_check);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_COUNTDOWN_AURA });
+ }
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_AURA);
+ GetHitUnit()->RemoveAurasDueToSpell(SPELL_COUNTDOWN_AURA);
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove(GetCaster());
+ targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_COUNTDOWN_AURA));
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_baleroc_countdown_proximity_check::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_baleroc_countdown_proximity_check::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ }
+};
+
+// http://www.wowhead.com/spell=99259/shards-of-torment
+class spell_baleroc_shards_of_torment_target_search : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_shards_of_torment_target_search);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SHARDS_OF_TORMENT_SUMMON });
+ }
+
+ bool Load() override
+ {
+ _hasTarget = false;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void OnSpellCast()
+ {
+ if (_hasTarget)
+ ENSURE_AI(boss_baleroc, GetCaster()->GetAI())->Talk(SAY_SHARDS_OF_TORMENT);
+ }
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_SHARDS_OF_TORMENT_SUMMON, true);
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ // Shards of torment seems to target tanks if no other targets are available as of Warlords of Draenor
+ if (targets.size() <= 1)
+ {
+ _hasTarget = !targets.empty();
+ return;
+ }
+
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster || !caster->IsAIEnabled)
+ return;
+
+ if (WorldObject* tank = caster->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO))
+ targets.remove(tank);
+
+ std::list<WorldObject*> melee, ranged;
+ for (WorldObject* target : targets)
+ {
+ if (caster->IsWithinMeleeRange(target->ToUnit()))
+ melee.push_back(target);
+ else
+ ranged.push_back(target);
+ }
+
+ targets.clear();
+
+ if (caster->GetMap()->Is25ManRaid())
+ if (WorldObject* target = GetRandomContainerElement(ranged, melee))
+ targets.push_back(target);
+
+ if (WorldObject* target = GetRandomContainerElement(melee, ranged))
+ targets.push_back(target);
+
+ _hasTarget = !targets.empty();
+ }
+
+ WorldObject* GetRandomContainerElement(std::list<WorldObject*>& priority1, std::list<WorldObject*>& priority2) const
+ {
+ WorldObject* target = nullptr;
+ target = GetRandomContainerElement(&priority1);
+ if (target)
+ priority1.remove(target);
+ else
+ {
+ target = GetRandomContainerElement(&priority2);
+ priority2.remove(target);
+ }
+
+ return target;
+ }
+
+ static WorldObject* GetRandomContainerElement(std::list<WorldObject*> const* list)
+ {
+ if (!list->empty())
+ return Trinity::Containers::SelectRandomContainerElement(*list);
+
+ return nullptr;
+ }
+
+ void Register() override
+ {
+ OnCast += SpellCastFn(spell_baleroc_shards_of_torment_target_search::OnSpellCast);
+ OnEffectHitTarget += SpellEffectFn(spell_baleroc_shards_of_torment_target_search::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_baleroc_shards_of_torment_target_search::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+
+ bool _hasTarget;
+};
+
+// http://www.wowhead.com/spell=99253/torment
+class spell_baleroc_torment_target_search : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_torment_target_search);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_TORMENT_PERIODIC });
+ }
+
+ void OnHit(SpellEffIndex /*effIndex*/)
+ {
+ Spell* spell = GetCaster()->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
+ if (spell && spell->m_targets.GetUnitTargetGUID() == _target)
+ return;
+
+ if (GetHitUnit()->GetGUID() == _target)
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_TORMENT_PERIODIC);
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(PlayerCheck());
+ if (targets.empty())
+ return;
+
+ targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster()));
+ _target = targets.front()->GetGUID();
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_baleroc_torment_target_search::OnHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_baleroc_torment_target_search::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+
+ ObjectGuid _target;
+};
+
+// http://www.wowhead.com/spell=99256/torment
+class spell_baleroc_torment : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_torment);
+
+ void ModifyDamage()
+ {
+ SetHitDamage(GetHitDamage() * GetHitUnit()->GetAuraCount(GetSpellInfo()->Id));
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_baleroc_torment::ModifyDamage);
+ }
+};
+
+class spell_baleroc_torment_AuraScript : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_torment_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_VITAL_FLAME, SPELL_VITAL_SPARK, SPELL_TORMENTED });
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ Unit* healer = eventInfo.GetProcTarget();
+ if (healer->HasAura(SPELL_VITAL_FLAME))
+ return;
+
+ bool Is25ManHeroic = healer->GetMap()->IsHeroic() && healer->GetMap()->Is25ManRaid();
+ uint32 stacks = healer->GetAuraCount(SPELL_VITAL_SPARK) + std::min(uint8(ceil(GetStackAmount() / (Is25ManHeroic ? 5 : 3))), uint8(255));
+
+ healer->SetAuraStack(SPELL_VITAL_SPARK, healer, stacks);
+ healer->GetAura(SPELL_VITAL_SPARK)->RefreshDuration();
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
+ GetTarget()->CastSpell(GetTarget(), SPELL_TORMENTED, true);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_baleroc_torment_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
+ OnEffectRemove += AuraEffectRemoveFn(spell_baleroc_torment_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// http://www.wowhead.com/spell=99257/tormented
+class spell_baleroc_tormented : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_tormented);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (InstanceScript* instance = GetTarget()->GetInstanceScript())
+ if (Creature* baleroc = ObjectAccessor::GetCreature(*GetTarget(), instance->GetGuidData(DATA_BALEROC)))
+ baleroc->AI()->SetGUID(GetTarget()->GetGUID(), GUID_TORMENTED);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_baleroc_tormented::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ }
+};
+
+// http://www.wowhead.com/spell=99489/tormented
+class spell_baleroc_tormented_spread : public SpellScript
+{
+ PrepareSpellScript(spell_baleroc_tormented_spread);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_TORMENTED });
+ }
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_TORMENTED, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_baleroc_tormented_spread::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// http://www.wowhead.com/spell=99262/vital-spark
+class spell_baleroc_vital_spark : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_vital_spark);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BLAZE_OF_GLORY, SPELL_VITAL_FLAME });
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ if (Unit* target = eventInfo.GetProcTarget())
+ if (target->HasAura(SPELL_BLAZE_OF_GLORY))
+ GetCaster()->CastSpell(GetCaster(), SPELL_VITAL_FLAME, true);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_baleroc_vital_spark::HandleProc, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
+// http://www.wowhead.com/spell=99263/vital-flame
+class spell_baleroc_vital_flame : public AuraScript
+{
+ PrepareAuraScript(spell_baleroc_vital_flame);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_VITAL_SPARK });
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (!GetCaster()->HasAura(SPELL_VITAL_SPARK))
+ {
+ stacks = 0;
+ return;
+ }
+
+ stacks = GetCaster()->GetAuraCount(SPELL_VITAL_SPARK);
+ int32 healingPct = sSpellMgr->AssertSpellInfo(SPELL_VITAL_SPARK)->GetEffect(EFFECT_0)->BasePoints * stacks;
+
+ if (GetAura()->GetEffect(EFFECT_0)->GetAmount() < healingPct)
+ GetAura()->GetEffect(EFFECT_0)->SetAmount(healingPct);
+
+ GetCaster()->RemoveAura(SPELL_VITAL_SPARK);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ GetCaster()->SetAuraStack(SPELL_VITAL_SPARK, GetCaster(), stacks);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_baleroc_vital_flame::OnApply, EFFECT_0, SPELL_AURA_359, AURA_EFFECT_HANDLE_REAL);
+ OnEffectRemove += AuraEffectRemoveFn(spell_baleroc_vital_flame::OnRemove, EFFECT_0, SPELL_AURA_359, AURA_EFFECT_HANDLE_REAL);
+ }
+
+ uint32 stacks;
+};
+
+// http://www.wowhead.com/achievement=5830/share-the-pain //17577
+class achievement_share_the_pain : public AchievementCriteriaScript
+{
+ public:
+ achievement_share_the_pain() : AchievementCriteriaScript("achievement_share_the_pain") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target) override
+ {
+ if (!target)
+ return false;
+
+ return target->GetAI()->GetData(GUID_TORMENTED) == 0;
+ }
+};
+
+void AddSC_boss_baleroc()
+{
+ RegisterFirelandsAI(boss_baleroc);
+ RegisterFirelandsAI(npc_shard_of_torment);
+ RegisterSpellScript(spell_baleroc_blades_of_baleroc);
+ RegisterAuraScript(spell_baleroc_inferno_blade);
+ RegisterAuraScript(spell_baleroc_decimation_blade);
+ RegisterSpellScript(spell_baleroc_decimating_strike);
+ RegisterSpellScript(spell_baleroc_countdown_aoe_dummy);
+ RegisterAuraScript(spell_baleroc_countdown);
+ RegisterSpellScript(spell_baleroc_countdown_proximity_check);
+ RegisterSpellScript(spell_baleroc_shards_of_torment_target_search);
+ RegisterSpellScript(spell_baleroc_torment_target_search);
+ RegisterSpellAndAuraScriptPair(spell_baleroc_torment, spell_baleroc_torment_AuraScript);
+ RegisterAuraScript(spell_baleroc_tormented);
+ RegisterSpellScript(spell_baleroc_tormented_spread);
+ RegisterAuraScript(spell_baleroc_vital_spark);
+ RegisterAuraScript(spell_baleroc_vital_flame);
+ new achievement_share_the_pain();
+};
diff --git a/src/server/scripts/Kalimdor/Firelands/firelands.cpp b/src/server/scripts/Kalimdor/Firelands/firelands.cpp
index 092ff5c3b2a..9ed7ce1ebe0 100644
--- a/src/server/scripts/Kalimdor/Firelands/firelands.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/firelands.cpp
@@ -15,12 +15,326 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "firelands.h"
+#include "ScriptMgr.h"
#include "Creature.h"
-#include "CreatureAI.h"
+#include "firelands.h"
+#include "GridNotifiers.h"
+#include "Vehicle.h"
+
+enum Spells
+{
+ // Baleroc Trash
+ SPELL_FLAME_TORRENT = 100795,
+ SPELL_FIERY_TORMENT = 100797,
+ SPELL_FIERY_TORMENT_DAMAGE = 100802,
+ SPELL_EARTHQUAKE = 100724,
+ SPELL_MAGMA_CONDUIT = 100728,
+ SPELL_ERUPTION = 100755,
+ SPELL_SUMMON_MAGMAKIN = 100746,
+
+ // Legendary questline
+ SPELL_SMOULDERING_QUEST_CHECK_A = 101089, // Alliance - Unverified
+ SPELL_SMOULDERING_QUEST_CHECK_H = 101092 // Horde - Unverified
+};
bool DelayedAttackStartEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
_owner->AI()->DoZoneInCombat(_owner, 200.0f);
return true;
}
+
+bool DelayedSpellCastEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
+{
+ _owner->CastSpell(_target, _spellId, _triggered);
+ return true;
+}
+
+void firelands_bossAI::EnterCombat(Unit* target)
+{
+ BossAI::EnterCombat(target);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
+}
+
+void firelands_bossAI::JustDied(Unit* killer)
+{
+ BossAI::JustDied(killer);
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+ me->m_Events.AddEvent(new DelayedSpellCastEvent(me, static_cast<Unit*>(nullptr), SPELL_SMOULDERING_1, false), me->m_Events.CalculateTime(2 * IN_MILLISECONDS));
+ me->m_Events.AddEvent(new DelayedSpellCastEvent(me, static_cast<Unit*>(nullptr), SPELL_SMOULDERING_2, false), me->m_Events.CalculateTime(2 * IN_MILLISECONDS));
+}
+
+void firelands_bossAI::EnterEvadeMode(EvadeReason why)
+{
+ instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
+
+ // Copy paste ScriptedAI::EnterEvadeMode functionality to exclude Reset function call
+ if (!_EnterEvadeMode(why))
+ return;
+
+ if (!me->GetVehicle()) // otherwise me will be in evade mode forever
+ {
+ if (Unit* owner = me->GetCharmerOrOwner())
+ {
+ me->GetMotionMaster()->Clear(false);
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle(), MOTION_SLOT_ACTIVE);
+ }
+ else
+ {
+ // Required to prevent attacking creatures that are evading and cause them to reenter combat
+ // Does not apply to MoveFollow
+ me->AddUnitState(UNIT_STATE_EVADE);
+ me->GetMotionMaster()->MoveTargetedHome();
+ }
+ }
+
+ // Copy paste reason
+ //Reset();
+
+ if (me->IsVehicle()) // use the same sequence of addtoworld, aireset may remove all summons!
+ me->GetVehicleKit()->Reset(true);
+
+ _DespawnAtEvade();
+}
+
+// http://www.wowhead.com/npc=54161/flame-archon
+struct npc_firelands_flame_archon : public ScriptedAI
+{
+ npc_firelands_flame_archon(Creature* creature) : ScriptedAI(creature)
+ {
+ scheduler.SetValidator([this]
+ {
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ });
+ }
+
+ void EnterCombat(Unit* /*attacker*/) override
+ {
+ scheduler.Schedule(Seconds(10), Seconds(12), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_FLAME_TORRENT);
+ context.Repeat(Seconds(15), Seconds(17));
+ });
+ scheduler.Schedule(Seconds(25), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_FIERY_TORMENT);
+ context.Repeat(Seconds(45));
+ });
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ scheduler.CancelAll();
+ ScriptedAI::JustDied(killer);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ scheduler.CancelAll();
+ ScriptedAI::EnterEvadeMode(why);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ scheduler.Update(diff);
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ TaskScheduler scheduler;
+};
+
+// http://www.wowhead.com/npc=54143/molten-flamefather
+struct npc_firelands_molten_flamefather : public ScriptedAI
+{
+ npc_firelands_molten_flamefather(Creature* creature) : ScriptedAI(creature)
+ {
+ scheduler.SetValidator([this]
+ {
+ return !me->HasUnitState(UNIT_STATE_CASTING);
+ });
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() != NPC_MAGMA_CONDUIT)
+ return;
+
+ summon->CastSpell(summon, SPELL_SUMMON_MAGMAKIN);
+ }
+
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ if (summon->GetEntry() != NPC_MAGMA_CONDUIT)
+ return;
+
+ summon->DespawnOrUnsummon();
+ }
+
+ void EnterCombat(Unit* /*attacker*/) override
+ {
+ scheduler.Schedule(Seconds(5), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_MAGMA_CONDUIT);
+ if (Is25ManRaid())
+ DoCastAOE(SPELL_MAGMA_CONDUIT);
+ context.Repeat(Seconds(25));
+ });
+ scheduler.Schedule(Milliseconds(12800), [this](TaskContext context)
+ {
+ DoCastAOE(SPELL_EARTHQUAKE);
+ context.Repeat(Milliseconds(32500));
+ });
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ scheduler.CancelAll();
+ ScriptedAI::JustDied(killer);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ scheduler.CancelAll();
+ ScriptedAI::EnterEvadeMode(why);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ scheduler.Update(diff);
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ TaskScheduler scheduler;
+};
+
+// http://www.wowhead.com/npc=54144/magmakin
+struct npc_firelands_magmakin : public ScriptedAI
+{
+ npc_firelands_magmakin(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ //Not actually sniffed behavior
+ Unit* target = me->SelectNearestTarget(50.0f, true);
+ if (!target)
+ return;
+
+ me->AddThreat(target, 50000000.0f);
+ me->TauntApply(target);
+ }
+
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ DoSpellAttackIfReady(SPELL_ERUPTION);
+ }
+};
+
+// http://www.wowhead.com/spell=100799/fiery-torment
+class spell_firelands_fiery_torment : public SpellScript
+{
+ PrepareSpellScript(spell_firelands_fiery_torment);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FIERY_TORMENT_DAMAGE });
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_FIERY_TORMENT_DAMAGE, true);
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ if (targets.empty())
+ return;
+
+ targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), true));
+ targets.resize(1);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_firelands_fiery_torment::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_firelands_fiery_torment::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+};
+
+// http://www.wowhead.com/spell=101089/smouldering
+// http://www.wowhead.com/spell=101092/smouldering
+class spell_firelands_smouldering : public SpellScript
+{
+ PrepareSpellScript(spell_firelands_smouldering);
+
+ void CheckQuestStatus(std::list<WorldObject*>& targets)
+ {
+ uint32 questId = 0;
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_SMOULDERING_QUEST_CHECK_A:
+ questId = QUEST_HEART_OF_FLAME_A;
+ break;
+ case SPELL_SMOULDERING_QUEST_CHECK_H:
+ questId = QUEST_HEART_OF_FLAME_H;
+ break;
+ default:
+ break;
+ }
+
+ bool raidHasQuest = targets.end() != std::find_if(targets.begin(), targets.end(), [questId](WorldObject* worldObject)
+ {
+ if (Player* player = worldObject->ToPlayer())
+ if (player->GetQuestStatus(questId) == QUEST_STATUS_INCOMPLETE)
+ return true;
+
+ return false;
+ });
+
+ targets.clear();
+ if (raidHasQuest)
+ targets.push_back(GetCaster());
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_firelands_smouldering::CheckQuestStatus, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ }
+};
+
+// http://www.wowhead.com/spell=101093/smouldering
+class spell_firelands_smouldering_aura : public SpellScript
+{
+ PrepareSpellScript(spell_firelands_smouldering_aura);
+
+ void SetTarget(WorldObject*& target)
+ {
+ target = GetCaster();
+ }
+
+ void Register() override
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_firelands_smouldering_aura::SetTarget, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY);
+ }
+};
+
+void AddSC_firelands()
+{
+ RegisterFirelandsAI(npc_firelands_flame_archon);
+ RegisterFirelandsAI(npc_firelands_molten_flamefather);
+ RegisterFirelandsAI(npc_firelands_magmakin);
+ RegisterSpellScript(spell_firelands_fiery_torment);
+ RegisterSpellScript(spell_firelands_smouldering);
+ RegisterSpellScript(spell_firelands_smouldering_aura);
+}
diff --git a/src/server/scripts/Kalimdor/Firelands/firelands.h b/src/server/scripts/Kalimdor/Firelands/firelands.h
index 59fa43baeec..e2dc5aedec4 100644
--- a/src/server/scripts/Kalimdor/Firelands/firelands.h
+++ b/src/server/scripts/Kalimdor/Firelands/firelands.h
@@ -20,6 +20,7 @@
#include "CreatureAIImpl.h"
#include "EventProcessor.h"
+#include "ScriptedCreature.h"
class Creature;
@@ -41,12 +42,43 @@ enum FLDataTypes
enum FLCreatureIds
{
+ // Bosses
+ NPC_SHANNOX = 53691,
+ NPC_LORD_RHYOLITH = 52558,
+ NPC_BETH_TILAC = 52498,
+ NPC_ALYSRAZOR = 52530,
+ NPC_BALEROC = 53494,
+ NPC_MAJORDOMO_STAGHELM = 52571,
+ NPC_RAGNAROS = 52409,
+
+ // Alysrazor
NPC_BLAZING_MONSTROSITY_LEFT = 53786,
NPC_BLAZING_MONSTROSITY_RIGHT = 53791,
NPC_EGG_PILE = 53795,
NPC_HARBINGER_OF_FLAME = 53793,
NPC_MOLTEN_EGG_TRASH = 53914,
NPC_SMOULDERING_HATCHLING = 53794,
+
+ // Baleroc
+ NPC_MAGMA_CONDUIT = 54145,
+ NPC_MAGMAKIN = 54144
+};
+
+enum GameobjectIds
+{
+ GO_BALEROC_FIREWALL = 209066
+};
+
+enum FirelandsSpells
+{
+ SPELL_SMOULDERING_1 = 101089,
+ SPELL_SMOULDERING_2 = 101092,
+};
+
+enum FirelandsQuests
+{
+ QUEST_HEART_OF_FLAME_A = 29307,
+ QUEST_HEART_OF_FLAME_H = 29308
};
class DelayedAttackStartEvent : public BasicEvent
@@ -60,10 +92,44 @@ class DelayedAttackStartEvent : public BasicEvent
Creature* _owner;
};
+class DelayedSpellCastEvent : public BasicEvent
+{
+ public:
+ DelayedSpellCastEvent(Creature* owner, Unit* target, uint32 spellId, bool triggered) : _owner(owner), _target(target), _spellId(spellId), _triggered(triggered) { }
+
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override;
+
+ private:
+ Creature* _owner;
+ Unit* _target;
+ uint32 _spellId;
+ bool _triggered;
+};
+
+class PlayerCheck
+{
+ public:
+ bool operator()(WorldObject* object) const
+ {
+ return object->GetTypeId() != TYPEID_PLAYER;
+ }
+};
+
+struct firelands_bossAI : public BossAI
+{
+ firelands_bossAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId) { }
+
+ void EnterCombat(Unit* target) override;
+ void JustDied(Unit* killer) override;
+ void EnterEvadeMode(EvadeReason why) override;
+};
+
template<typename AI>
inline AI* GetFirelandsAI(Creature* creature)
{
return GetInstanceAI<AI>(creature, FirelandsScriptName);
}
+#define RegisterFirelandsAI(AI) RegisterCreatureAIWithFactory(AI, 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 da1fe55d2a5..c2bc3aa1263 100644
--- a/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/instance_firelands.cpp
@@ -18,6 +18,7 @@
#include "ScriptMgr.h"
#include "Creature.h"
#include "firelands.h"
+#include "GameObject.h"
#include "InstanceScript.h"
#include "Map.h"
@@ -42,8 +43,60 @@ class instance_firelands : public InstanceMapScript
// Cannot directly start attacking here as the creature is not yet on map
creature->m_Events.AddEvent(new DelayedAttackStartEvent(creature), creature->m_Events.CalculateTime(500));
break;
+ case NPC_BALEROC:
+ BalerocGUID = creature->GetGUID();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void OnGameObjectCreate(GameObject* go) override
+ {
+ switch (go->GetEntry())
+ {
+ case GO_BALEROC_FIREWALL:
+ BalerocDoorGUID = go->GetGUID();
+ if (GetBossState(DATA_SHANNOX) == DONE || GetBossState(DATA_BALEROC) == DONE)
+ go->SetGoState(GO_STATE_ACTIVE);
+ break;
+ default:
+ break;
}
}
+
+ bool SetBossState(uint32 type, EncounterState state) override
+ {
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ if ((type == DATA_SHANNOX && state == DONE) || (type == DATA_BALEROC && state != IN_PROGRESS))
+ {
+ if (GameObject* door = instance->GetGameObject(BalerocDoorGUID))
+ door->SetGoState(GO_STATE_ACTIVE);
+ }
+ else if (type == DATA_BALEROC && state == IN_PROGRESS)
+ if (GameObject* door = instance->GetGameObject(BalerocDoorGUID))
+ door->SetGoState(GO_STATE_READY);
+
+ return true;
+ }
+
+ ObjectGuid GetGuidData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_BALEROC:
+ return BalerocGUID;
+ default:
+ break;
+ }
+ return ObjectGuid::Empty;
+ }
+
+ protected:
+ ObjectGuid BalerocDoorGUID;
+ ObjectGuid BalerocGUID;
};
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 cdca725290d..2fdd22e9be0 100644
--- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
+++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
@@ -91,7 +91,9 @@ void AddSC_boss_temple_guardian_anhuur();
void AddSC_boss_earthrager_ptah();
void AddSC_boss_anraphet();
void AddSC_instance_firelands();
+void AddSC_firelands();
void AddSC_boss_alysrazor();
+void AddSC_boss_baleroc();
void AddSC_ashenvale();
void AddSC_azshara();
@@ -220,5 +222,7 @@ void AddKalimdorScripts()
AddSC_boss_anraphet();
AddSC_instance_firelands();
+ AddSC_firelands();
AddSC_boss_alysrazor();
+ AddSC_boss_baleroc();
}