/*
* 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_EVOKER and SPELLFAMILY_GENERIC spells used by evoker players.
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "spell_evo_".
*/
#include "AreaTrigger.h"
#include "AreaTriggerAI.h"
#include "Containers.h"
#include "DB2Stores.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
enum EvokerSpells
{
SPELL_EVOKER_AZURE_ESSENCE_BURST = 375721,
SPELL_EVOKER_BLAST_FURNACE = 375510,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DK = 381732,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DH = 381741,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DRUID = 381746,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_EVOKER = 381748,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_HUNTER = 381749,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_MAGE = 381750,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_MONK = 381751,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_PALADIN = 381752,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_PRIEST = 381753,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_ROGUE = 381754,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_SHAMAN = 381756,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_WARLOCK = 381757,
SPELL_EVOKER_BLESSING_OF_THE_BRONZE_WARRIOR = 381758,
SPELL_EVOKER_BURNOUT = 375802,
SPELL_EVOKER_CALL_OF_YSERA_TALENT = 373834,
SPELL_EVOKER_CALL_OF_YSERA = 373835,
SPELL_EVOKER_CAUSALITY = 375777,
SPELL_EVOKER_DISINTEGRATE = 356995,
SPELL_EVOKER_EMERALD_BLOSSOM_HEAL = 355916,
SPELL_EVOKER_ENERGIZING_FLAME = 400006,
SPELL_EVOKER_ESSENCE_BURST = 359618,
SPELL_EVOKER_FIRESTORM_DAMAGE = 369374,
SPELL_EVOKER_ETERNITY_SURGE = 359073,
SPELL_EVOKER_FIRE_BREATH = 357208,
SPELL_EVOKER_FIRE_BREATH_DAMAGE = 357209,
SPELL_EVOKER_GLIDE_KNOCKBACK = 358736,
SPELL_EVOKER_HOVER = 358267,
SPELL_EVOKER_LIVING_FLAME = 361469,
SPELL_EVOKER_LIVING_FLAME_DAMAGE = 361500,
SPELL_EVOKER_LIVING_FLAME_HEAL = 361509,
SPELL_EVOKER_PANACEA_HEAL = 387763,
SPELL_EVOKER_PANACEA_TALENT = 387761,
SPELL_EVOKER_PERMEATING_CHILL_TALENT = 370897,
SPELL_EVOKER_PYRE_DAMAGE = 357212,
SPELL_EVOKER_RUBY_EMBERS = 365937,
SPELL_EVOKER_RUBY_ESSENCE_BURST = 376872,
SPELL_EVOKER_SCOURING_FLAME = 378438,
SPELL_EVOKER_SNAPFIRE = 370818,
SPELL_EVOKER_SOAR_RACIAL = 369536,
SPELL_EVOKER_VERDANT_EMBRACE_HEAL = 361195,
SPELL_EVOKER_VERDANT_EMBRACE_JUMP = 373514
};
enum EvokerSpellLabels
{
SPELL_LABEL_EVOKER_BLUE = 1465,
};
enum EvokerSpellVisuals
{
SPELL_VISUAL_KIT_EVOKER_VERDANT_EMBRACE_JUMP = 152557,
};
// 362969 - Azure Strike (blue)
class spell_evo_azure_strike : public SpellScript
{
void FilterTargets(std::list& targets)
{
targets.remove(GetExplTargetUnit());
Trinity::Containers::RandomResize(targets, GetEffectInfo(EFFECT_0).CalcValue(GetCaster()) - 1);
targets.push_back(GetExplTargetUnit());
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_azure_strike::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
}
};
// 381732 - Blessing of the Bronze (Bronze)
// 381741 - Blessing of the Bronze (Bronze)
// 381746 - Blessing of the Bronze (Bronze)
// 381748 - Blessing of the Bronze (Bronze)
// 381749 - Blessing of the Bronze (Bronze)
// 381750 - Blessing of the Bronze (Bronze)
// 381751 - Blessing of the Bronze (Bronze)
// 381752 - Blessing of the Bronze (Bronze)
// 381753 - Blessing of the Bronze (Bronze)
// 381754 - Blessing of the Bronze (Bronze)
// 381756 - Blessing of the Bronze (Bronze)
// 381757 - Blessing of the Bronze (Bronze)
// 381758 - Blessing of the Bronze (Bronze)
class spell_evo_blessing_of_the_bronze : public SpellScript
{
void RemoveInvalidTargets(std::list& targets) const
{
targets.remove_if([&](WorldObject const* target)
{
Unit const* unitTarget = target->ToUnit();
if (!unitTarget)
return true;
switch (GetSpellInfo()->Id)
{
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DK: return unitTarget->GetClass() != CLASS_DEATH_KNIGHT;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DH: return unitTarget->GetClass() != CLASS_DEMON_HUNTER;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_DRUID: return unitTarget->GetClass() != CLASS_DRUID;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_EVOKER: return unitTarget->GetClass() != CLASS_EVOKER;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_HUNTER: return unitTarget->GetClass() != CLASS_HUNTER;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_MAGE: return unitTarget->GetClass() != CLASS_MAGE;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_MONK: return unitTarget->GetClass() != CLASS_MONK;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_PALADIN: return unitTarget->GetClass() != CLASS_PALADIN;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_PRIEST: return unitTarget->GetClass() != CLASS_PRIEST;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_ROGUE: return unitTarget->GetClass() != CLASS_ROGUE;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_SHAMAN: return unitTarget->GetClass() != CLASS_SHAMAN;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_WARLOCK: return unitTarget->GetClass() != CLASS_WARLOCK;
case SPELL_EVOKER_BLESSING_OF_THE_BRONZE_WARRIOR: return unitTarget->GetClass() != CLASS_WARRIOR;
default:
break;
}
return true;
});
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_blessing_of_the_bronze::RemoveInvalidTargets, EFFECT_ALL, TARGET_UNIT_CASTER_AREA_RAID);
}
};
// 375801 - Burnout
class spell_evo_burnout : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_BURNOUT });
}
static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/)
{
return roll_chance_i(aurEff->GetAmount());
}
static void HandleProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo)
{
eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_EVOKER_BURNOUT, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_evo_burnout::CheckProc, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_evo_burnout::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 373834 - Call of Ysera (attached to 361195 - Verdant Embrace (Green))
class spell_evo_call_of_ysera : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_CALL_OF_YSERA_TALENT, SPELL_EVOKER_CALL_OF_YSERA });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_EVOKER_CALL_OF_YSERA_TALENT);
}
void HandleCallOfYsera() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_EVOKER_CALL_OF_YSERA, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_evo_call_of_ysera::HandleCallOfYsera);
}
};
static constexpr std::array CausalityAffectedEmpowerSpells = { SPELL_EVOKER_ETERNITY_SURGE, SPELL_EVOKER_FIRE_BREATH };
// Called by 356995 - Disintegrate (Blue)
class spell_evo_causality_disintegrate : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_EVOKER_CAUSALITY, EFFECT_1 } });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_EVOKER_CAUSALITY);
}
void OnTick(AuraEffect const* /*aurEff*/) const
{
if (AuraEffect const* causality = GetCaster()->GetAuraEffect(SPELL_EVOKER_CAUSALITY, EFFECT_0))
for (uint32 spell : CausalityAffectedEmpowerSpells)
GetCaster()->GetSpellHistory()->ModifyCooldown(spell, Milliseconds(causality->GetAmount()));
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_evo_causality_disintegrate::OnTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
// Called by 357212 - Pyre (Red)
class spell_evo_causality_pyre : public SpellScript
{
static constexpr int64 TargetLimit = 5;
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_EVOKER_CAUSALITY, EFFECT_1 } });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_EVOKER_CAUSALITY);
}
void HandleCooldown() const
{
AuraEffect const* causality = GetCaster()->GetAuraEffect(SPELL_EVOKER_CAUSALITY, EFFECT_1);
if (!causality)
return;
Milliseconds cooldownReduction = Milliseconds(std::min(GetUnitTargetCountForEffect(EFFECT_0), TargetLimit) * causality->GetAmount());
for (uint32 spell : CausalityAffectedEmpowerSpells)
GetCaster()->GetSpellHistory()->ModifyCooldown(spell, cooldownReduction);
}
void Register() override
{
AfterCast += SpellCastFn(spell_evo_causality_pyre::HandleCooldown);
}
};
// 370455 - Charged Blast
class spell_evo_charged_blast : public AuraScript
{
bool CheckProc(ProcEventInfo& procInfo)
{
return procInfo.GetSpellInfo() && procInfo.GetSpellInfo()->HasLabel(SPELL_LABEL_EVOKER_BLUE);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_evo_charged_blast::CheckProc);
}
};
// 355913 - Emerald Blossom (Green)
// ID - 23318
struct at_evo_emerald_blossom : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnRemove() override
{
if (Unit* caster = at->GetCaster())
caster->CastSpell(at->GetPosition(), SPELL_EVOKER_EMERALD_BLOSSOM_HEAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
}
};
// 355916 - Emerald Blossom (Green)
class spell_evo_emerald_blossom_heal : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
void FilterTargets(std::list& targets) const
{
uint32 const maxTargets = uint32(GetSpellInfo()->GetEffect(EFFECT_1).CalcValue(GetCaster()));
Trinity::SelectRandomInjuredTargets(targets, maxTargets, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_emerald_blossom_heal::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
};
// Called by 362969 - Azure Strike
// Called by 361469 - Living Flame (Red)
class spell_evo_essence_burst_trigger : public SpellScript
{
public:
explicit spell_evo_essence_burst_trigger(uint32 talentAuraId) : _talentAuraId(talentAuraId) { }
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ _talentAuraId, SPELL_EVOKER_ESSENCE_BURST });
}
bool Load() override
{
AuraEffect const* aurEff = GetCaster()->GetAuraEffect(_talentAuraId, EFFECT_0);
return aurEff && roll_chance_i(aurEff->GetAmount());
}
void HandleEssenceBurst() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_EVOKER_ESSENCE_BURST, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_evo_essence_burst_trigger::HandleEssenceBurst);
}
uint32 _talentAuraId;
};
// 357208 Fire Breath (Red)
// 382266 Fire Breath (Red)
class spell_evo_fire_breath : public SpellScript
{
public:
struct data
{
int32 EmpowerLevel;
};
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_FIRE_BREATH_DAMAGE, SPELL_EVOKER_BLAST_FURNACE });
}
void OnComplete(int32 completedStageCount) const
{
int32 dotTicks = 10 - (completedStageCount - 1) * 3;
if (AuraEffect const* blastFurnace = GetCaster()->GetAuraEffect(SPELL_EVOKER_BLAST_FURNACE, EFFECT_0))
dotTicks += blastFurnace->GetAmount() / 2;
GetCaster()->CastSpell(GetCaster(), SPELL_EVOKER_FIRE_BREATH_DAMAGE, CastSpellExtraArgs()
.SetTriggeringSpell(GetSpell())
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR)
.AddSpellMod(SPELLVALUE_DURATION_PCT, 100 * dotTicks)
.SetCustomArg(data{ .EmpowerLevel = completedStageCount }));
}
void Register() override
{
OnEmpowerCompleted += SpellOnEmpowerStageCompletedFn(spell_evo_fire_breath::OnComplete);
}
};
// 357209 Fire Breath (Red)
class spell_evo_fire_breath_damage : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 } })
&& spellInfo->GetEffect(EFFECT_2).IsAura(SPELL_AURA_MOD_SILENCE); // validate we are removing the correct effect
}
void AddBonusUpfrontDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* victim, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) const
{
spell_evo_fire_breath::data const* params = std::any_cast(&GetSpell()->m_customArg);
if (!params)
return;
// damage is done after aura is applied, grab periodic amount
if (AuraEffect const* fireBreath = victim->GetAuraEffect(GetSpellInfo()->Id, EFFECT_1, GetCaster()->GetGUID()))
flatMod += fireBreath->GetEstimatedAmount().value_or(fireBreath->GetAmount()) * (params->EmpowerLevel - 1) * 3;
}
void RemoveUnusedEffect(std::list& targets) const
{
targets.clear();
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_evo_fire_breath_damage::AddBonusUpfrontDamage);
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_fire_breath_damage::RemoveUnusedEffect, EFFECT_2, TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY);
}
};
// 369372 - Firestorm (Red)
struct at_evo_firestorm : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
struct extra_create_data
{
float SnapshotDamageMultipliers = 1.0f;
};
static extra_create_data& GetOrCreateExtraData(Spell* firestorm)
{
if (firestorm->m_customArg.type() != typeid(extra_create_data))
return firestorm->m_customArg.emplace();
return *std::any_cast(&firestorm->m_customArg);
}
void OnCreate(Spell const* creatingSpell) override
{
_damageSpellCustomArg = creatingSpell->m_customArg;
_scheduler.Schedule(0ms, [this](TaskContext task)
{
FloatMilliseconds period = 2s; // 2s, affected by haste
if (Unit* caster = at->GetCaster())
{
period *= *caster->m_unitData->ModCastingSpeed;
caster->CastSpell(at->GetPosition(), SPELL_EVOKER_FIRESTORM_DAMAGE, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.CustomArg = _damageSpellCustomArg
});
}
task.Repeat(duration_cast(period));
});
}
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
private:
TaskScheduler _scheduler;
std::any _damageSpellCustomArg;
};
// 358733 - Glide (Racial)
class spell_evo_glide : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_GLIDE_KNOCKBACK, SPELL_EVOKER_HOVER, SPELL_EVOKER_SOAR_RACIAL });
}
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
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_EVOKER_GLIDE_KNOCKBACK, true);
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_EVOKER_HOVER, GetCastDifficulty()), 0, nullptr, false, 250ms);
caster->GetSpellHistory()->StartCooldown(sSpellMgr->AssertSpellInfo(SPELL_EVOKER_SOAR_RACIAL, GetCastDifficulty()), 0, nullptr, false, 250ms);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_evo_glide::CheckCast);
OnCast += SpellCastFn(spell_evo_glide::HandleCast);
}
};
// 361469 - Living Flame (Red)
class spell_evo_living_flame : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo ({ SPELL_EVOKER_LIVING_FLAME_DAMAGE, SPELL_EVOKER_LIVING_FLAME_HEAL, SPELL_EVOKER_ENERGIZING_FLAME });
}
void HandleHitTarget(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
Unit* hitUnit = GetHitUnit();
if (caster->IsValidAssistTarget(hitUnit))
caster->CastSpell(hitUnit, SPELL_EVOKER_LIVING_FLAME_HEAL, true);
else
caster->CastSpell(hitUnit, SPELL_EVOKER_LIVING_FLAME_DAMAGE, true);
}
void HandleLaunchTarget(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (caster->IsValidAssistTarget(GetHitUnit()))
return;
if (AuraEffect* auraEffect = caster->GetAuraEffect(SPELL_EVOKER_ENERGIZING_FLAME, EFFECT_0))
{
int32 manaCost = GetSpell()->GetPowerTypeCostAmount(POWER_MANA).value_or(0);
if (manaCost != 0)
GetCaster()->ModifyPower(POWER_MANA, CalculatePct(manaCost, auraEffect->GetAmount()));
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_evo_living_flame::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
OnEffectLaunchTarget += SpellEffectFn(spell_evo_living_flame::HandleLaunchTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 387761 Panacea (Green) (attached to 355913 - Emerald Blossom (Green) and 360995 - Verdant Embrace (Green))
class spell_evo_panacea : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_PANACEA_TALENT, SPELL_EVOKER_PANACEA_HEAL });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_EVOKER_PANACEA_TALENT);
}
void HandlePanacea() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_EVOKER_PANACEA_HEAL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_evo_panacea::HandlePanacea);
}
};
// 381773 - Permeating Chill
class spell_evo_permeating_chill : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_PERMEATING_CHILL_TALENT });
}
bool CheckProc(ProcEventInfo& procInfo)
{
SpellInfo const* spellInfo = procInfo.GetSpellInfo();
if (!spellInfo)
return false;
if (!spellInfo->HasLabel(SPELL_LABEL_EVOKER_BLUE))
return false;
if (!procInfo.GetActor()->HasAura(SPELL_EVOKER_PERMEATING_CHILL_TALENT))
if (!spellInfo->IsAffected(SPELLFAMILY_EVOKER, { 0x40, 0, 0, 0 })) // disintegrate
return false;
return true;
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_evo_permeating_chill::CheckProc);
}
};
// 393568 - Pyre
class spell_evo_pyre : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo ({ SPELL_EVOKER_PYRE_DAMAGE });
}
void HandleDamage(SpellEffIndex /*effIndex*/)
{
GetCaster()->CastSpell(GetHitUnit()->GetPosition(), SPELL_EVOKER_PYRE_DAMAGE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_evo_pyre::HandleDamage, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 361500 Living Flame (Red)
// 361509 Living Flame (Red)
class spell_evo_ruby_embers : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_EVOKER_RUBY_EMBERS })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
&& spellInfo->GetEffect(EFFECT_1).IsEffect(SPELL_EFFECT_APPLY_AURA)
&& spellInfo->GetEffect(EFFECT_1).ApplyAuraPeriod != 0;
}
bool Load() override
{
return !GetCaster()->HasAura(SPELL_EVOKER_RUBY_EMBERS);
}
static void PreventPeriodic(SpellScript const&, WorldObject*& target)
{
target = nullptr;
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_evo_ruby_embers::PreventPeriodic, EFFECT_1,
m_scriptSpellId == SPELL_EVOKER_LIVING_FLAME_DAMAGE ? TARGET_UNIT_TARGET_ENEMY : TARGET_UNIT_TARGET_ALLY);
}
};
// 357209 Fire Breath (Red)
class spell_evo_scouring_flame : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_SCOURING_FLAME });
}
void HandleScouringFlame(std::list& targets) const
{
if (!GetCaster()->HasAura(SPELL_EVOKER_SCOURING_FLAME))
targets.clear();
}
void CalcDispelCount(SpellEffIndex /*effIndex*/)
{
if (spell_evo_fire_breath::data const* params = std::any_cast(&GetSpell()->m_customArg))
SetEffectValue(params->EmpowerLevel);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_evo_scouring_flame::HandleScouringFlame, EFFECT_3, TARGET_UNIT_CONE_CASTER_TO_DEST_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_evo_scouring_flame::CalcDispelCount, EFFECT_3, SPELL_EFFECT_DISPEL);
}
};
// Called by 368847 - Firestorm (Red)
class spell_evo_snapfire : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_EVOKER_SNAPFIRE, EFFECT_1 } });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_EVOKER_SNAPFIRE);
}
void OnPrecast() override
{
if (AuraEffect const* snapfire = GetCaster()->GetAuraEffect(SPELL_EVOKER_SNAPFIRE, EFFECT_1))
if (GetSpell()->m_appliedMods.contains(snapfire->GetBase()))
AddPct(at_evo_firestorm::GetOrCreateExtraData(GetSpell()).SnapshotDamageMultipliers, snapfire->GetAmount());
}
void Register() override { }
};
// Called by 369374 - Firestorm (Red)
class spell_evo_snapfire_bonus_damage : public SpellScript
{
void CalculateDamageBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const
{
if (at_evo_firestorm::extra_create_data const* bonus = std::any_cast(&GetSpell()->m_customArg))
pctMod *= bonus->SnapshotDamageMultipliers;
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_evo_snapfire_bonus_damage::CalculateDamageBonus);
}
};
// 360995 - Verdant Embrace (Green)
class spell_evo_verdant_embrace : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_VERDANT_EMBRACE_HEAL, SPELL_EVOKER_VERDANT_EMBRACE_JUMP })
&& sSpellVisualKitStore.HasRecord(SPELL_VISUAL_KIT_EVOKER_VERDANT_EMBRACE_JUMP);
}
void HandleLaunchTarget(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
CastSpellExtraArgs args;
args.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
args.SetTriggeringSpell(GetSpell());
if (target != caster)
{
caster->CastSpell(target, SPELL_EVOKER_VERDANT_EMBRACE_JUMP, args);
caster->SendPlaySpellVisualKit(SPELL_VISUAL_KIT_EVOKER_VERDANT_EMBRACE_JUMP, 0, 0);
}
else
caster->CastSpell(caster, SPELL_EVOKER_VERDANT_EMBRACE_HEAL, args);
}
void Register() override
{
OnEffectLaunchTarget += SpellEffectFn(spell_evo_verdant_embrace::HandleLaunchTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 396557 - Verdant Embrace
class spell_evo_verdant_embrace_trigger_heal : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_EVOKER_VERDANT_EMBRACE_HEAL });
}
void HandleHitTarget(SpellEffIndex /*effIndex*/) const
{
GetHitUnit()->CastSpell(GetExplTargetUnit(), SPELL_EVOKER_VERDANT_EMBRACE_HEAL, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_evo_verdant_embrace_trigger_heal::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_evoker_spell_scripts()
{
RegisterSpellScript(spell_evo_azure_strike);
RegisterSpellScript(spell_evo_blessing_of_the_bronze);
RegisterSpellScript(spell_evo_burnout);
RegisterSpellScript(spell_evo_call_of_ysera);
RegisterSpellScript(spell_evo_causality_disintegrate);
RegisterSpellScript(spell_evo_causality_pyre);
RegisterSpellScript(spell_evo_charged_blast);
RegisterAreaTriggerAI(at_evo_emerald_blossom);
RegisterSpellScript(spell_evo_emerald_blossom_heal);
RegisterSpellScriptWithArgs(spell_evo_essence_burst_trigger, "spell_evo_azure_essence_burst", SPELL_EVOKER_AZURE_ESSENCE_BURST);
RegisterSpellScriptWithArgs(spell_evo_essence_burst_trigger, "spell_evo_ruby_essence_burst", SPELL_EVOKER_RUBY_ESSENCE_BURST);
RegisterAreaTriggerAI(at_evo_firestorm);
RegisterSpellScript(spell_evo_fire_breath);
RegisterSpellScript(spell_evo_fire_breath_damage);
RegisterSpellScript(spell_evo_glide);
RegisterSpellScript(spell_evo_living_flame);
RegisterSpellScript(spell_evo_panacea);
RegisterSpellScript(spell_evo_permeating_chill);
RegisterSpellScript(spell_evo_pyre);
RegisterSpellScript(spell_evo_ruby_embers);
RegisterSpellScript(spell_evo_scouring_flame);
RegisterSpellScript(spell_evo_snapfire);
RegisterSpellScript(spell_evo_snapfire_bonus_damage);
RegisterSpellScript(spell_evo_verdant_embrace);
RegisterSpellScript(spell_evo_verdant_embrace_trigger_heal);
}