mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-25 11:21:58 +01:00
874
src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
Normal file
874
src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
Normal file
@@ -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();
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user