/*
* 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 .
*/
/*
* Scripts for spells with SPELLFAMILY_DEMONHUNTER and SPELLFAMILY_GENERIC spells used by demon hunter players.
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "spell_dh_".
*/
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "DB2Stores.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "Unit.h"
enum DemonHunterSpells
{
AREATRIGGER_DH_SHATTERED_SOULS_HAVOC = 8352,
AREATRIGGER_DH_SHATTERED_SOULS_HAVOC_DEMON = 11231,
AREATRIGGER_DH_SHATTERED_SOULS_VENGEANCE = 11266,
AREATRIGGER_DH_SHATTERED_SOULS_VENGEANCE_DEMON = 10693,
AREATRIGGER_DH_SOUL_FRAGMENT_HAVOC = 12929,
AREATRIGGER_DH_SOUL_FRAGMENT_VENGEANCE = 10665,
SPELL_DH_ABYSSAL_STRIKE = 207550,
SPELL_DH_ANNIHILATION = 201427,
SPELL_DH_ANNIHILATION_MH = 227518,
SPELL_DH_ANNIHILATION_OH = 201428,
SPELL_DH_AWAKEN_THE_DEMON_WITHIN_CD = 207128,
SPELL_DH_BLUR = 212800,
SPELL_DH_BLUR_TRIGGER = 198589,
SPELL_DH_BURNING_ALIVE = 207739,
SPELL_DH_BURNING_ALIVE_TARGET_SELECTOR = 207760,
SPELL_DH_CHAOS_NOVA = 179057,
SPELL_DH_CHAOS_STRIKE = 162794,
SPELL_DH_CHAOS_STRIKE_ENERGIZE = 193840,
SPELL_DH_CHAOS_STRIKE_MH = 222031,
SPELL_DH_CHAOS_STRIKE_OH = 199547,
SPELL_DH_CHAOTIC_TRANSFORMATION = 388112,
SPELL_DH_CHARRED_WARBLADES_HEAL = 213011,
SPELL_DH_COLLECTIVE_ANGUISH = 390152,
SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM = 391057,
SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM_DAMAGE = 391058,
SPELL_DH_COLLECTIVE_ANGUISH_FEL_DEVASTATION = 393831,
SPELL_DH_CONSUME_SOUL_HAVOC = 228542,
SPELL_DH_CONSUME_SOUL_HAVOC_DEMON = 228556,
SPELL_DH_CONSUME_SOUL_HAVOC_SHATTERED = 228540,
SPELL_DH_CONSUME_SOUL_HEAL = 203794,
SPELL_DH_CONSUME_SOUL_VENGEANCE = 208014,
SPELL_DH_CONSUME_SOUL_VENGEANCE_DEMON = 210050,
SPELL_DH_CONSUME_SOUL_VENGEANCE_SHATTERED = 210047,
SPELL_DH_CYCLE_OF_HATRED = 258887,
SPELL_DH_DARKGLARE_BOON = 389708,
SPELL_DH_DARKGLARE_BOON_ENERGIZE = 391345,
SPELL_DH_DARKNESS_ABSORB = 209426,
SPELL_DH_DEMON_BLADES_DMG = 203796,
SPELL_DH_DEMON_SPIKES = 203819,
SPELL_DH_DEMON_SPIKES_TRIGGER = 203720,
SPELL_DH_DEMONIC = 213410,
SPELL_DH_DEMONIC_ORIGINS = 235893,
SPELL_DH_DEMONIC_ORIGINS_BUFF = 235894,
SPELL_DH_DEMONIC_TRAMPLE_DMG = 208645,
SPELL_DH_DEMONIC_TRAMPLE_STUN = 213491,
SPELL_DH_DEMONS_BITE = 162243,
SPELL_DH_EYE_BEAM = 198013,
SPELL_DH_EYE_BEAM_DAMAGE = 198030,
SPELL_DH_EYE_OF_LEOTHERAS_DMG = 206650,
SPELL_DH_FEAST_OF_SOULS = 207697,
SPELL_DH_FEAST_OF_SOULS_PERIODIC_HEAL = 207693,
SPELL_DH_FEED_THE_DEMON = 218612,
SPELL_DH_FEL_BARRAGE = 211053,
SPELL_DH_FEL_BARRAGE_DMG = 211052,
SPELL_DH_FEL_BARRAGE_PROC = 222703,
SPELL_DH_FEL_DEVASTATION = 212084,
SPELL_DH_FEL_DEVASTATION_DMG = 212105,
SPELL_DH_FEL_DEVASTATION_HEAL = 212106,
SPELL_DH_FEL_FLAME_FORTIFICATION_TALENT = 389705,
SPELL_DH_FEL_FLAME_FORTIFICATION_MOD_DAMAGE = 393009,
SPELL_DH_FEL_RUSH = 195072,
SPELL_DH_FEL_RUSH_DMG = 192611,
SPELL_DH_FEL_RUSH_GROUND = 197922,
SPELL_DH_FEL_RUSH_WATER_AIR = 197923,
SPELL_DH_FELBLADE = 232893,
SPELL_DH_FELBLADE_CHARGE = 213241,
SPELL_DH_FELBLADE_COOLDOWN_RESET_PROC_HAVOC = 236167,
SPELL_DH_FELBLADE_COOLDOWN_RESET_PROC_VENGEANCE= 203557,
SPELL_DH_FELBLADE_COOLDOWN_RESET_PROC_VISUAL = 204497,
SPELL_DH_FELBLADE_DAMAGE = 213243,
SPELL_DH_FIERY_BRAND = 204021,
SPELL_DH_FIERY_BRAND_DMG_REDUCTION_DEBUFF = 207744,
SPELL_DH_FIERY_BRAND_DOT = 207771,
SPELL_DH_FIRST_BLOOD = 206416,
SPELL_DH_FLAME_CRASH = 227322,
SPELL_DH_FRAILTY = 224509,
SPELL_DH_FURIOUS_GAZE = 343311,
SPELL_DH_FURIOUS_GAZE_BUFF = 343312,
SPELL_DH_GLIDE = 131347,
SPELL_DH_GLIDE_DURATION = 197154,
SPELL_DH_GLIDE_KNOCKBACK = 196353,
SPELL_DH_HAVOC_MASTERY = 185164,
SPELL_DH_ILLIDANS_GRASP = 205630,
SPELL_DH_ILLIDANS_GRASP_DAMAGE = 208618,
SPELL_DH_ILLIDANS_GRASP_JUMP_DEST = 208175,
SPELL_DH_INFERNAL_STRIKE_CAST = 189110,
SPELL_DH_INFERNAL_STRIKE_IMPACT_DAMAGE = 189112,
SPELL_DH_INFERNAL_STRIKE_JUMP = 189111,
SPELL_DH_JAGGED_SPIKES = 205627,
SPELL_DH_JAGGED_SPIKES_DMG = 208790,
SPELL_DH_JAGGED_SPIKES_PROC = 208796,
SPELL_DH_MANA_RIFT_DMG_POWER_BURN = 235904,
SPELL_DH_METAMORPHOSIS = 191428,
SPELL_DH_METAMORPHOSIS_DUMMY = 191427,
SPELL_DH_METAMORPHOSIS_IMPACT_DAMAGE = 200166,
SPELL_DH_METAMORPHOSIS_RESET = 320645,
SPELL_DH_METAMORPHOSIS_TRANSFORM = 162264,
SPELL_DH_METAMORPHOSIS_VENGEANCE_TRANSFORM = 187827,
SPELL_DH_MOMENTUM = 208628,
SPELL_DH_NEMESIS_ABERRATIONS = 208607,
SPELL_DH_NEMESIS_BEASTS = 208608,
SPELL_DH_NEMESIS_CRITTERS = 208609,
SPELL_DH_NEMESIS_DEMONS = 208608,
SPELL_DH_NEMESIS_DRAGONKIN = 208610,
SPELL_DH_NEMESIS_ELEMENTALS = 208611,
SPELL_DH_NEMESIS_GIANTS = 208612,
SPELL_DH_NEMESIS_HUMANOIDS = 208605,
SPELL_DH_NEMESIS_MECHANICALS = 208613,
SPELL_DH_NEMESIS_UNDEAD = 208614,
SPELL_DH_RAIN_FROM_ABOVE = 206803,
SPELL_DH_RAIN_OF_CHAOS = 205628,
SPELL_DH_RAIN_OF_CHAOS_IMPACT = 232538,
SPELL_DH_RAZOR_SPIKES = 210003,
SPELL_DH_SEVER = 235964,
SPELL_DH_SHATTER_SOUL = 209980,
SPELL_DH_SHATTER_SOUL_1 = 209981,
SPELL_DH_SHATTER_SOUL_2 = 210038,
SPELL_DH_SHATTERED_SOUL = 226258,
SPELL_DH_SHATTERED_SOUL_LESSER_SOUL_FRAGMENT_1 = 228533,
SPELL_DH_SHATTERED_SOUL_LESSER_SOUL_FRAGMENT_2 = 237867,
SPELL_DH_SHEAR = 203782,
SPELL_DH_SIGIL_OF_CHAINS_AREA_SELECTOR = 204834,
SPELL_DH_SIGIL_OF_CHAINS_GRIP = 208674,
SPELL_DH_SIGIL_OF_CHAINS_JUMP = 208674,
SPELL_DH_SIGIL_OF_CHAINS_SLOW = 204843,
SPELL_DH_SIGIL_OF_CHAINS_SNARE = 204843,
SPELL_DH_SIGIL_OF_CHAINS_TARGET_SELECT = 204834,
SPELL_DH_SIGIL_OF_CHAINS_VISUAL = 208673,
SPELL_DH_SIGIL_OF_FLAME_AOE = 204598,
SPELL_DH_SIGIL_OF_FLAME_DAMAGE = 204598,
SPELL_DH_SIGIL_OF_FLAME_FLAME_CRASH = 228973,
SPELL_DH_SIGIL_OF_MISERY = 207685,
SPELL_DH_SIGIL_OF_MISERY_AOE = 207685,
SPELL_DH_SIGIL_OF_SILENCE = 204490,
SPELL_DH_SIGIL_OF_SILENCE_AOE = 204490,
SPELL_DH_SOUL_BARRIER = 227225,
SPELL_DH_SOUL_CLEAVE = 228477,
SPELL_DH_SOUL_CLEAVE_DMG = 228478,
SPELL_DH_SOUL_FRAGMENT_COUNTER = 203981,
SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF = 391172,
SPELL_DH_SOUL_RENDING = 204909,
SPELL_DH_SPIRIT_BOMB_DAMAGE = 218677,
SPELL_DH_SPIRIT_BOMB_HEAL = 227255,
SPELL_DH_SPIRIT_BOMB_VISUAL = 218678,
SPELL_DH_TACTICAL_RETREAT_ENERGIZE = 389890,
SPELL_DH_TACTICAL_RETREAT_TALENT = 389688,
SPELL_DH_THROW_GLAIVE = 185123,
SPELL_DH_UNCONTAINED_FEL = 209261,
SPELL_DH_VENGEFUL_BONDS = 320635,
SPELL_DH_VENGEFUL_RETREAT = 198813,
SPELL_DH_VENGEFUL_RETREAT_TRIGGER = 198793,
};
enum DemonHunterSpellCategories
{
SPELL_CATEGORY_DH_EYE_BEAM = 1582,
SPELL_CATEGORY_DH_BLADE_DANCE = 1640
};
// 197125 - Chaos Strike
class spell_dh_chaos_strike : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_CHAOS_STRIKE_ENERGIZE });
}
void HandleEffectProc(AuraEffect* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
args.SetTriggeringAura(aurEff);
GetTarget()->CastSpell(GetTarget(), SPELL_DH_CHAOS_STRIKE_ENERGIZE, args);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_dh_chaos_strike::HandleEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// Called by 191427 - Metamorphosis
class spell_dh_chaotic_transformation : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_CHAOTIC_TRANSFORMATION })
&& sSpellCategoryStore.LookupEntry(SPELL_CATEGORY_DH_EYE_BEAM)
&& sSpellCategoryStore.LookupEntry(SPELL_CATEGORY_DH_BLADE_DANCE);
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_DH_CHAOTIC_TRANSFORMATION);
}
void HandleCooldown() const
{
GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr)
{
uint32 category = sSpellMgr->AssertSpellInfo(itr->first, DIFFICULTY_NONE)->CategoryId;
return category == SPELL_CATEGORY_DH_EYE_BEAM || category == SPELL_CATEGORY_DH_BLADE_DANCE;
}, true);
}
void Register() override
{
AfterCast += SpellCastFn(spell_dh_chaotic_transformation::HandleCooldown);
}
};
// 213010 - Charred Warblades
class spell_dh_charred_warblades : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_CHARRED_WARBLADES_HEAL });
}
bool CheckProc(ProcEventInfo& eventInfo)
{
return eventInfo.GetDamageInfo() && eventInfo.GetDamageInfo()->GetSchoolMask() & SPELL_SCHOOL_MASK_FIRE;
}
void HandleAfterProc(ProcEventInfo& eventInfo)
{
_healAmount += CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), GetEffect(EFFECT_0)->GetAmount());
}
void HandleDummyTick(AuraEffect const* aurEff)
{
if (_healAmount == 0)
return;
GetTarget()->CastSpell(GetTarget(), SPELL_DH_CHARRED_WARBLADES_HEAL,
CastSpellExtraArgs(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR)
.SetTriggeringAura(aurEff)
.AddSpellBP0(_healAmount));
_healAmount = 0;
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_dh_charred_warblades::CheckProc);
AfterProc += AuraProcFn(spell_dh_charred_warblades::HandleAfterProc);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dh_charred_warblades::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
private:
uint32 _healAmount = 0;
};
// Called by 212084 - Fel Devastation and 198013 - Eye Beam
class spell_dh_collective_anguish : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_COLLECTIVE_ANGUISH, SPELL_DH_FEL_DEVASTATION, SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM, SPELL_DH_COLLECTIVE_ANGUISH_FEL_DEVASTATION });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_DH_COLLECTIVE_ANGUISH);
}
void HandleEyeBeam() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void HandleFelDevastation() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_DH_COLLECTIVE_ANGUISH_FEL_DEVASTATION, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
if (m_scriptSpellId == SPELL_DH_FEL_DEVASTATION)
AfterCast += SpellCastFn(spell_dh_collective_anguish::HandleEyeBeam);
else
AfterCast += SpellCastFn(spell_dh_collective_anguish::HandleFelDevastation);
}
};
// 391057 - Eye Beam
class spell_dh_collective_anguish_eye_beam : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM_DAMAGE });
}
void HandleEffectPeriodic(AuraEffect const* aurEff) const
{
if (Unit* caster = GetCaster())
caster->CastSpell(nullptr, SPELL_DH_COLLECTIVE_ANGUISH_EYE_BEAM_DAMAGE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dh_collective_anguish_eye_beam::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
// Called by 188499 - Blade Dance, 162794 - Chaos Strike and 342817 - Glaive Tempest
class spell_dh_cycle_of_hatred : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_CYCLE_OF_HATRED });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_DH_CYCLE_OF_HATRED);
}
void ReduceEyeBeamCooldown() const
{
if (AuraEffect const* aurEff = GetCaster()->GetAuraEffect(SPELL_DH_CYCLE_OF_HATRED, EFFECT_0))
GetCaster()->GetSpellHistory()->ModifyCooldown(SPELL_DH_EYE_BEAM, Milliseconds(-aurEff->GetAmount()));
}
void Register() override
{
AfterCast += SpellCastFn(spell_dh_cycle_of_hatred::ReduceEyeBeamCooldown);
}
};
// Called by 212084 - Fel Devastation
class spell_dh_darkglare_boon : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (!ValidateSpellInfo({ SPELL_DH_DARKGLARE_BOON_ENERGIZE, SPELL_DH_FEL_DEVASTATION })
|| !ValidateSpellEffect({ { SPELL_DH_DARKGLARE_BOON, EFFECT_3 } }))
return false;
SpellInfo const* darkglareBoon = sSpellMgr->GetSpellInfo(SPELL_DH_DARKGLARE_BOON, DIFFICULTY_NONE);
return darkglareBoon->GetEffect(EFFECT_0).CalcValue() < darkglareBoon->GetEffect(EFFECT_1).CalcValue()
&& darkglareBoon->GetEffect(EFFECT_2).CalcValue() < darkglareBoon->GetEffect(EFFECT_3).CalcValue();
}
bool Load() override
{
return GetUnitOwner()->HasAura(SPELL_DH_DARKGLARE_BOON);
}
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
// Tooltip mentions "fully channelled" being a requirement but ingame it always reduces cooldown and energizes, even when manually cancelled
//if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
// return;
Unit* target = GetTarget();
Aura const* darkglareBoon = target->GetAura(SPELL_DH_DARKGLARE_BOON);
SpellHistory::Duration cooldown, categoryCooldown;
SpellHistory::GetCooldownDurations(GetSpellInfo(), 0, &cooldown, nullptr, &categoryCooldown);
int32 reductionPct = irand(darkglareBoon->GetEffect(EFFECT_0)->GetAmount(), darkglareBoon->GetEffect(EFFECT_1)->GetAmount());
SpellHistory::Duration cooldownReduction(CalculatePct(std::max(cooldown, categoryCooldown).count(), reductionPct));
int32 energizeValue = irand(darkglareBoon->GetEffect(EFFECT_2)->GetAmount(), darkglareBoon->GetEffect(EFFECT_3)->GetAmount());
target->GetSpellHistory()->ModifyCooldown(SPELL_DH_FEL_DEVASTATION, -cooldownReduction);
target->CastSpell(target, SPELL_DH_DARKGLARE_BOON_ENERGIZE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.SpellValueOverrides = { { SPELLVALUE_BASE_POINT0, energizeValue } }
});
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_dh_darkglare_boon::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// 209426 - Darkness
class spell_dh_darkness : public AuraScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
// Set absorbtion amount to unlimited
amount = -1;
}
void Absorb(AuraEffect const* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) const
{
if (AuraEffect const* chanceEffect = GetEffect(EFFECT_1))
if (roll_chance_i(chanceEffect->GetAmount()))
absorbAmount = dmgInfo.GetDamage();
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dh_darkness::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
OnEffectAbsorb += AuraEffectAbsorbFn(spell_dh_darkness::Absorb, EFFECT_0);
}
};
// 196718 - Darkness
// Id: 6615
struct areatrigger_dh_darkness : AreaTriggerAI
{
areatrigger_dh_darkness(AreaTrigger* areaTrigger) : AreaTriggerAI(areaTrigger),
_absorbAuraInfo(sSpellMgr->GetSpellInfo(SPELL_DH_DARKNESS_ABSORB, DIFFICULTY_NONE)) { }
void OnUnitEnter(Unit* unit) override
{
Unit* caster = at->GetCaster();
if (!caster || !caster->IsValidAssistTarget(unit, _absorbAuraInfo))
return;
caster->CastSpell(unit, SPELL_DH_DARKNESS_ABSORB, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.SpellValueOverrides = { { SPELLVALUE_DURATION, at->GetDuration() } }
});
}
void OnUnitExit(Unit* unit) override
{
unit->RemoveAura(SPELL_DH_DARKNESS_ABSORB, at->GetCasterGuid());
}
private:
SpellInfo const* _absorbAuraInfo;
};
// 198013 - Eye Beam
class spell_dh_eye_beam : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_EYE_BEAM_DAMAGE });
}
void HandleEffectPeriodic(AuraEffect const* aurEff) const
{
if (Unit* caster = GetCaster())
caster->CastSpell(nullptr, SPELL_DH_EYE_BEAM_DAMAGE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dh_eye_beam::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
// 212084 - Fel Devastation
class spell_dh_fel_devastation : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FEL_DEVASTATION_HEAL });
}
void HandlePeriodicEffect(AuraEffect const* aurEff) const
{
if (Unit* caster = GetCaster())
caster->CastSpell(caster, SPELL_DH_FEL_DEVASTATION_HEAL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dh_fel_devastation::HandlePeriodicEffect, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
// Called by 258920 - Immolation Aura
class spell_dh_fel_flame_fortification : public AuraScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_DH_FEL_FLAME_FORTIFICATION_TALENT, SPELL_DH_FEL_FLAME_FORTIFICATION_MOD_DAMAGE });
}
bool Load() override
{
return GetUnitOwner()->HasAura(SPELL_DH_FEL_FLAME_FORTIFICATION_TALENT);
}
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
Unit* target = GetTarget();
target->CastSpell(target, SPELL_DH_FEL_FLAME_FORTIFICATION_MOD_DAMAGE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff,
.OriginalCastId = aurEff->GetBase()->GetCastId()
});
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DH_FEL_FLAME_FORTIFICATION_MOD_DAMAGE);
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_dh_fel_flame_fortification::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_fel_flame_fortification::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// 232893 - Felblade
class spell_dh_felblade : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FELBLADE_CHARGE });
}
void HandleCharge(SpellEffIndex /*effIndex*/) const
{
uint32 spellToCast = GetCaster()->IsWithinMeleeRange(GetHitUnit()) ? SPELL_DH_FELBLADE_DAMAGE : SPELL_DH_FELBLADE_CHARGE;
GetCaster()->CastSpell(GetHitUnit(), spellToCast, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_dh_felblade::HandleCharge, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 213241 - Felblade Charge
class spell_dh_felblade_charge : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FELBLADE_DAMAGE });
}
void HandleDamage(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_DH_FELBLADE_DAMAGE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_dh_felblade_charge::HandleDamage, EFFECT_0, SPELL_EFFECT_CHARGE);
}
};
// 203557 - Felblade (Vengeance cooldow reset proc aura)
// 236167 - Felblade (Havoc cooldow reset proc aura)
class spell_dh_felblade_cooldown_reset_proc : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FELBLADE });
}
void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo const& /*eventInfo*/) const
{
GetTarget()->GetSpellHistory()->ResetCooldown(SPELL_DH_FELBLADE, true);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_dh_felblade_cooldown_reset_proc::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 206416 - First Blood
class spell_dh_first_blood : public AuraScript
{
public:
ObjectGuid const& GetFirstTarget() const { return _firstTargetGUID; }
void SetFirstTarget(ObjectGuid const& targetGuid) { _firstTargetGUID = targetGuid; }
private:
void Register() override
{
}
private:
ObjectGuid _firstTargetGUID;
};
// Called by 198013 - Eye Beam
class spell_dh_furious_gaze : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FURIOUS_GAZE, SPELL_DH_FURIOUS_GAZE_BUFF });
}
bool Load() override
{
return GetUnitOwner()->HasAura(SPELL_DH_FURIOUS_GAZE);
}
void HandleAfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
return;
Unit* target = GetTarget();
target->CastSpell(target, SPELL_DH_FURIOUS_GAZE_BUFF, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringAura = aurEff
});
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_furious_gaze::HandleAfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
// 188499 - Blade Dance
// 210152 - Death Sweep
class spell_dh_blade_dance : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FIRST_BLOOD });
}
void DecideFirstTarget(std::list& targetList)
{
if (targetList.empty())
return;
Aura* aura = GetCaster()->GetAura(SPELL_DH_FIRST_BLOOD);
if (!aura)
return;
ObjectGuid firstTargetGUID = ObjectGuid::Empty;
ObjectGuid selectedTarget = GetCaster()->GetTarget();
// Prefer the selected target if he is one of the enemies
if (targetList.size() > 1 && !selectedTarget.IsEmpty())
{
auto it = std::find_if(targetList.begin(), targetList.end(), [selectedTarget](WorldObject* object)
{
return object->GetGUID() == selectedTarget;
});
if (it != targetList.end())
firstTargetGUID = (*it)->GetGUID();
}
if (firstTargetGUID.IsEmpty())
firstTargetGUID = targetList.front()->GetGUID();
if (spell_dh_first_blood* script = aura->GetScript())
script->SetFirstTarget(firstTargetGUID);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dh_blade_dance::DecideFirstTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
// 199552 - Blade Dance
// 200685 - Blade Dance
// 210153 - Death Sweep
// 210155 - Death Sweep
class spell_dh_blade_dance_damage : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_FIRST_BLOOD });
}
void HandleHitTarget()
{
int32 damage = GetHitDamage();
if (AuraEffect* aurEff = GetCaster()->GetAuraEffect(SPELL_DH_FIRST_BLOOD, EFFECT_0))
if (spell_dh_first_blood* script = aurEff->GetBase()->GetScript())
if (GetHitUnit()->GetGUID() == script->GetFirstTarget())
AddPct(damage, aurEff->GetAmount());
SetHitDamage(damage);
}
void Register() override
{
OnHit += SpellHitFn(spell_dh_blade_dance_damage::HandleHitTarget);
}
};
// 131347 - Glide
class spell_dh_glide : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_GLIDE_KNOCKBACK, SPELL_DH_GLIDE_DURATION, SPELL_DH_VENGEFUL_RETREAT_TRIGGER, SPELL_DH_FEL_RUSH });
}
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
if (caster->IsMounted() || caster->GetVehicleBase())
return SPELL_FAILED_DONT_REPORT;
if (!caster->IsFalling())
return SPELL_FAILED_NOT_ON_GROUND;
return SPELL_CAST_OK;
}
void HandleCast()
{
Player* caster = GetCaster()->ToPlayer();
if (!caster)
return;
caster->CastSpell(caster, SPELL_DH_GLIDE_KNOCKBACK, true);
caster->CastSpell(caster, SPELL_DH_GLIDE_DURATION, true);
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_DH_VENGEFUL_RETREAT_TRIGGER, GetCastDifficulty()), 0, nullptr, false, 250ms);
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_DH_FEL_RUSH, GetCastDifficulty()), 0, nullptr, false, 250ms);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_dh_glide::CheckCast);
BeforeCast += SpellCastFn(spell_dh_glide::HandleCast);
}
};
// 131347 - Glide
class spell_dh_glide_AuraScript : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_GLIDE_DURATION });
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAura(SPELL_DH_GLIDE_DURATION);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_glide_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_FEATHER_FALL, AURA_EFFECT_HANDLE_REAL);
}
};
// 197154 - Glide
class spell_dh_glide_timer : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_GLIDE });
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAura(SPELL_DH_GLIDE);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_dh_glide_timer::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 391166 - Soul Furnace
class spell_dh_soul_furnace : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF });
}
void CalculateSpellMod(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetStackAmount() == GetAura()->CalcMaxStackAmount())
{
GetTarget()->CastSpell(GetTarget(), SPELL_DH_SOUL_FURNACE_DAMAGE_BUFF, true);
Remove();
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_dh_soul_furnace::CalculateSpellMod, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
// 339424 - Soul Furnace
class spell_dh_soul_furnace_conduit : public AuraScript
{
void CalculateSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod)
{
if (aurEff->GetAmount() == 10)
{
if (!spellMod)
{
spellMod = new SpellModifierByClassMask(GetAura());
spellMod->op = SpellModOp::HealingAndDamage;
spellMod->type = SPELLMOD_PCT;
spellMod->spellId = GetId();
static_cast(spellMod)->mask = flag128(0x80000000);
static_cast(spellMod)->value = GetEffect(EFFECT_1)->GetAmount() + 1;
}
}
}
void Register() override
{
DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_dh_soul_furnace_conduit::CalculateSpellMod, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 204596 - Sigil of Flame
// 207684 - Sigil of Misery
// 202137 - Sigil of Silence
template
class areatrigger_dh_generic_sigil : public AreaTriggerEntityScript
{
public:
areatrigger_dh_generic_sigil(char const* script) : AreaTriggerEntityScript(script) { }
template
struct areatrigger_dh_generic_sigilAI : AreaTriggerAI
{
areatrigger_dh_generic_sigilAI(AreaTrigger* at) : AreaTriggerAI(at) { }
void OnRemove() override
{
if (Unit* caster = at->GetCaster())
caster->CastSpell(at->GetPosition(), Trigger);
}
};
AreaTriggerAI* GetAI(AreaTrigger* at) const override
{
return new areatrigger_dh_generic_sigilAI(at);
}
};
// 208673 - Sigil of Chains
class spell_dh_sigil_of_chains : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_SIGIL_OF_CHAINS_SLOW, SPELL_DH_SIGIL_OF_CHAINS_GRIP });
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/)
{
if (WorldLocation const* loc = GetExplTargetDest())
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_DH_SIGIL_OF_CHAINS_SLOW, true);
GetHitUnit()->CastSpell(loc->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_GRIP, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_dh_sigil_of_chains::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 202138 - Sigil of Chains
struct areatrigger_dh_sigil_of_chains : AreaTriggerAI
{
areatrigger_dh_sigil_of_chains(AreaTrigger* at) : AreaTriggerAI(at) { }
void OnRemove() override
{
if (Unit* caster = at->GetCaster())
{
caster->CastSpell(at->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_VISUAL);
caster->CastSpell(at->GetPosition(), SPELL_DH_SIGIL_OF_CHAINS_TARGET_SELECT);
}
}
};
// Called by 198793 - Vengeful Retreat
class spell_dh_tactical_retreat : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_TACTICAL_RETREAT_TALENT, SPELL_DH_TACTICAL_RETREAT_ENERGIZE });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_DH_TACTICAL_RETREAT_TALENT);
}
void Energize() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_DH_TACTICAL_RETREAT_ENERGIZE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_dh_tactical_retreat::Energize);
}
};
// 198813 - Vengeful Retreat
class spell_dh_vengeful_retreat_damage : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DH_VENGEFUL_BONDS });
}
void HandleVengefulBonds(std::list& targets)
{
if (!GetCaster()->HasAura(SPELL_DH_VENGEFUL_BONDS))
targets.clear();
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dh_vengeful_retreat_damage::HandleVengefulBonds, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
void AddSC_demon_hunter_spell_scripts()
{
RegisterSpellScript(spell_dh_chaos_strike);
RegisterSpellScript(spell_dh_chaotic_transformation);
RegisterSpellScript(spell_dh_charred_warblades);
RegisterSpellScript(spell_dh_collective_anguish);
RegisterSpellScript(spell_dh_collective_anguish_eye_beam);
RegisterSpellScript(spell_dh_cycle_of_hatred);
RegisterSpellScript(spell_dh_darkglare_boon);
RegisterSpellScript(spell_dh_darkness);
RegisterSpellScript(spell_dh_eye_beam);
RegisterSpellScript(spell_dh_fel_devastation);
RegisterSpellScript(spell_dh_fel_flame_fortification);
RegisterSpellScript(spell_dh_felblade);
RegisterSpellScript(spell_dh_felblade_charge);
RegisterSpellScript(spell_dh_felblade_cooldown_reset_proc);
RegisterSpellScript(spell_dh_furious_gaze);
RegisterSpellScript(spell_dh_sigil_of_chains);
RegisterSpellScript(spell_dh_tactical_retreat);
RegisterSpellScript(spell_dh_vengeful_retreat_damage);
RegisterAreaTriggerAI(areatrigger_dh_darkness);
new areatrigger_dh_generic_sigil("areatrigger_dh_sigil_of_silence");
new areatrigger_dh_generic_sigil("areatrigger_dh_sigil_of_misery");
new areatrigger_dh_generic_sigil("areatrigger_dh_sigil_of_flame");
RegisterAreaTriggerAI(areatrigger_dh_sigil_of_chains);
// Havoc
/* Spells & Auras */
/* Auras */
RegisterSpellScript(spell_dh_first_blood);
/* AreaTrigger */
/* Spells */
RegisterSpellScript(spell_dh_blade_dance);
RegisterSpellScript(spell_dh_blade_dance_damage);
// Vengeance
RegisterSpellScript(spell_dh_soul_furnace);
// Vengeance & Havoc
RegisterSpellAndAuraScriptPair(spell_dh_glide, spell_dh_glide_AuraScript);
RegisterSpellScript(spell_dh_glide_timer);
// Soulbind conduits
RegisterSpellScript(spell_dh_soul_furnace_conduit);
}