/*
* 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_PRIEST and SPELLFAMILY_GENERIC spells used by priest players.
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "spell_pri_".
*/
#include "ScriptMgr.h"
#include "AreaTriggerAI.h"
#include "Containers.h"
#include "G3DPosition.hpp"
#include "GridNotifiers.h"
#include "ListUtils.h"
#include "Log.h"
#include "MoveSplineInitArgs.h"
#include "ObjectAccessor.h"
#include "PathGenerator.h"
#include "Player.h"
#include "SpellAuraEffects.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TaskScheduler.h"
#include "TemporarySummon.h"
enum PriestSpells
{
SPELL_PRIEST_ABYSSAL_REVERIE = 373054,
SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER = 158624,
SPELL_PRIEST_ANGELIC_FEATHER_AURA = 121557,
SPELL_PRIEST_ANSWERED_PRAYERS = 394289,
SPELL_PRIEST_APOTHEOSIS = 200183,
SPELL_PRIEST_ARMOR_OF_FAITH = 28810,
SPELL_PRIEST_ASSURED_SAFETY = 440766,
SPELL_PRIEST_ATONEMENT = 81749,
SPELL_PRIEST_ATONEMENT_EFFECT = 194384,
SPELL_PRIEST_ATONEMENT_HEAL = 81751,
SPELL_PRIEST_BENEDICTION = 193157,
SPELL_PRIEST_BENEVOLENCE = 415416,
SPELL_PRIEST_BLAZE_OF_LIGHT = 215768,
SPELL_PRIEST_BLAZE_OF_LIGHT_INCREASE = 355851,
SPELL_PRIEST_BLAZE_OF_LIGHT_DECREASE = 356084,
SPELL_PRIEST_BLESSED_HEALING = 70772,
SPELL_PRIEST_BLESSED_LIGHT = 196813,
SPELL_PRIEST_BODY_AND_SOUL = 64129,
SPELL_PRIEST_BODY_AND_SOUL_SPEED = 65081,
SPELL_PRIEST_CIRCLE_OF_HEALING = 204883,
SPELL_PRIEST_CRYSTALLINE_REFLECTION = 373457,
SPELL_PRIEST_CRYSTALLINE_REFLECTION_HEAL = 373462,
SPELL_PRIEST_CRYSTALLINE_REFLECTION_REFLECT = 373464,
SPELL_PRIEST_DARK_INDULGENCE = 372972,
SPELL_PRIEST_DARK_REPRIMAND = 400169,
SPELL_PRIEST_DARK_REPRIMAND_CHANNEL_DAMAGE = 373129,
SPELL_PRIEST_DARK_REPRIMAND_CHANNEL_HEALING = 400171,
SPELL_PRIEST_DARK_REPRIMAND_DAMAGE = 373130,
SPELL_PRIEST_DARK_REPRIMAND_HEALING = 400187,
SPELL_PRIEST_DAZZLING_LIGHT = 196810,
SPELL_PRIEST_DIVINE_AEGIS = 47515,
SPELL_PRIEST_DIVINE_AEGIS_ABSORB = 47753,
SPELL_PRIEST_DIVINE_BLESSING = 40440,
SPELL_PRIEST_DIVINE_HYMN_HEAL = 64844,
SPELL_PRIEST_DIVINE_IMAGE_SUMMON = 392990,
SPELL_PRIEST_DIVINE_IMAGE_EMPOWER = 409387,
SPELL_PRIEST_DIVINE_IMAGE_EMPOWER_STACK = 405963,
SPELL_PRIEST_DIVINE_SERVICE = 391233,
SPELL_PRIEST_DIVINE_STAR_HOLY = 110744,
SPELL_PRIEST_DIVINE_STAR_SHADOW = 122121,
SPELL_PRIEST_DIVINE_STAR_HOLY_DAMAGE = 122128,
SPELL_PRIEST_DIVINE_STAR_HOLY_HEAL = 110745,
SPELL_PRIEST_DIVINE_STAR_SHADOW_DAMAGE = 390845,
SPELL_PRIEST_DIVINE_STAR_SHADOW_HEAL = 390981,
SPELL_PRIEST_DIVINE_WRATH = 40441,
SPELL_PRIEST_EMPOWERED_RENEW_HEAL = 391359,
SPELL_PRIEST_EPIPHANY = 414553,
SPELL_PRIEST_EPIPHANY_HIGHLIGHT = 414556,
SPELL_PRIEST_ESSENCE_DEVOURER = 415479,
SPELL_PRIEST_ESSENCE_DEVOURER_SHADOWFIEND_HEAL = 415673,
SPELL_PRIEST_ESSENCE_DEVOURER_MINDBENDER_HEAL = 415676,
SPELL_PRIEST_FLASH_HEAL = 2061,
SPELL_PRIEST_FROM_DARKNESS_COMES_LIGHT_AURA = 390617,
SPELL_PRIEST_GREATER_HEAL = 289666,
SPELL_PRIEST_FOCUSED_MENDING = 372354,
SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153,
SPELL_PRIEST_HALO_HOLY = 120517,
SPELL_PRIEST_HALO_SHADOW = 120644,
SPELL_PRIEST_HALO_HOLY_DAMAGE = 120696,
SPELL_PRIEST_HALO_HOLY_HEAL = 120692,
SPELL_PRIEST_HALO_SHADOW_DAMAGE = 390964,
SPELL_PRIEST_HALO_SHADOW_HEAL = 390971,
SPELL_PRIEST_HEAL = 2060,
SPELL_PRIEST_HEALING_LIGHT = 196809,
SPELL_PRIEST_HEAVENS_WRATH = 421558,
SPELL_PRIEST_HOLY_FIRE = 14914,
SPELL_PRIEST_HOLY_MENDING_HEAL = 391156,
SPELL_PRIEST_HOLY_NOVA = 132157,
SPELL_PRIEST_HOLY_WORD_CHASTISE = 88625,
SPELL_PRIEST_HOLY_WORD_SALVATION = 265202,
SPELL_PRIEST_HOLY_WORD_SANCTIFY = 34861,
SPELL_PRIEST_HOLY_WORD_SERENITY = 2050,
SPELL_PRIEST_HOLY_10_1_CLASS_SET_2P_CHOOSER = 411097,
SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P = 405556,
SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P_EFFECT = 409479,
SPELL_PRIEST_INDEMNITY = 373049,
SPELL_PRIEST_ITEM_EFFICIENCY = 37595,
SPELL_PRIEST_LEAP_OF_FAITH_EFFECT = 92832,
SPELL_PRIEST_LEVITATE_EFFECT = 111759,
SPELL_PRIEST_LIGHT_ERUPTION = 196812,
SPELL_PRIEST_LIGHTS_WRATH_VISUAL = 215795,
SPELL_PRIEST_MASOCHISM_TALENT = 193063,
SPELL_PRIEST_MASOCHISM_PERIODIC_HEAL = 193065,
SPELL_PRIEST_MASTERY_GRACE = 271534,
SPELL_PRIEST_MIND_DEVOURER = 373202,
SPELL_PRIEST_MIND_DEVOURER_AURA = 373204,
SPELL_PRIEST_MINDBENDER_DISC = 123040,
SPELL_PRIEST_MINDBENDER_SHADOW = 200174,
SPELL_PRIEST_MINDGAMES = 375901,
SPELL_PRIEST_MINDGAMES_VENTHYR = 323673,
SPELL_PRIEST_MIND_BOMB_STUN = 226943,
SPELL_PRIEST_MISERY = 238558,
SPELL_PRIEST_ORACULAR_HEAL = 26170,
SPELL_PRIEST_PAIN_TRANSFORMATION = 372991,
SPELL_PRIEST_PAIN_TRANSFORMATION_HEAL = 372994,
SPELL_PRIEST_PENANCE = 47540,
SPELL_PRIEST_PENANCE_CHANNEL_DAMAGE = 47758,
SPELL_PRIEST_PENANCE_CHANNEL_HEALING = 47757,
SPELL_PRIEST_PENANCE_DAMAGE = 47666,
SPELL_PRIEST_PENANCE_HEALING = 47750,
SPELL_PRIEST_POWER_LEECH_MINDBENDER_MANA = 123051,
SPELL_PRIEST_POWER_LEECH_MINDBENDER_INSANITY = 200010,
SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_MANA = 343727,
SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_INSANITY = 262485,
SPELL_PRIEST_POWER_OF_THE_DARK_SIDE = 198069,
SPELL_PRIEST_POWER_OF_THE_DARK_SIDE_TINT = 225795,
SPELL_PRIEST_POWER_WORD_LIFE = 373481,
SPELL_PRIEST_POWER_WORD_RADIANCE = 194509,
SPELL_PRIEST_POWER_WORD_SHIELD = 17,
SPELL_PRIEST_POWER_WORD_SOLACE_ENERGIZE = 129253,
SPELL_PRIEST_PRAYER_OF_HEALING = 596,
SPELL_PRIEST_PRAYER_OF_MENDING = 33076,
SPELL_PRIEST_PRAYER_OF_MENDING_AURA = 41635,
SPELL_PRIEST_PRAYER_OF_MENDING_HEAL = 33110,
SPELL_PRIEST_PRAYER_OF_MENDING_JUMP = 155793,
SPELL_PRIEST_PROTECTIVE_LIGHT_AURA = 193065,
SPELL_PRIEST_PURGE_THE_WICKED = 204197,
SPELL_PRIEST_PURGE_THE_WICKED_DUMMY = 204215,
SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC = 204213,
SPELL_PRIEST_RAPTURE = 47536,
SPELL_PRIEST_RENEW = 139,
SPELL_PRIEST_RENEWED_HOPE = 197469,
SPELL_PRIEST_RENEWED_HOPE_EFFECT = 197470,
SPELL_PRIEST_REVEL_IN_PURITY = 373003,
SPELL_PRIEST_SANCTUARY = 231682,
SPELL_PRIEST_SANCTUARY_ABSORB = 208771,
SPELL_PRIEST_SANCTUARY_AURA = 208772,
SPELL_PRIEST_SHADOW_COVENANT = 314867,
SPELL_PRIEST_SHADOW_COVENANT_EFFECT = 322105,
SPELL_PRIEST_RHAPSODY_PROC = 390636,
SPELL_PRIEST_SAY_YOUR_PRAYERS = 391186,
SPELL_PRIEST_SCHISM = 424509,
SPELL_PRIEST_SCHISM_AURA = 214621,
SPELL_PRIEST_SEARING_LIGHT = 196811,
SPELL_PRIEST_SHADOW_MEND_DAMAGE = 186439,
SPELL_PRIEST_SHADOW_WORD_DEATH = 32379,
SPELL_PRIEST_SHADOW_WORD_DEATH_DAMAGE = 32409,
SPELL_PRIEST_SHADOW_MEND_PERIODIC_DUMMY = 187464,
SPELL_PRIEST_SHADOW_WORD_PAIN = 589,
SPELL_PRIEST_SHIELD_DISCIPLINE = 197045,
SPELL_PRIEST_SHIELD_DISCIPLINE_EFFECT = 47755,
SPELL_PRIEST_SIN_AND_PUNISHMENT = 87204,
SPELL_PRIEST_SINS_OF_THE_MANY = 280398,
SPELL_PRIEST_SMITE = 585,
SPELL_PRIEST_SPIRIT_OF_REDEMPTION = 27827,
SPELL_PRIEST_STRENGTH_OF_SOUL = 197535,
SPELL_PRIEST_STRENGTH_OF_SOUL_EFFECT = 197548,
SPELL_PRIEST_SURGE_OF_LIGHT = 109186,
SPELL_PRIEST_SURGE_OF_LIGHT_EFFECT = 114255,
SPELL_PRIEST_TRANQUIL_LIGHT = 196816,
SPELL_PRIEST_THE_PENITENT_AURA = 200347,
SPELL_PRIEST_TRAIL_OF_LIGHT_HEAL = 234946,
SPELL_PRIEST_TRINITY = 214205,
SPELL_PRIEST_TRINITY_EFFECT = 214206,
SPELL_PRIEST_ULTIMATE_PENITENCE = 421453,
SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE = 421543,
SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL = 421544,
SPELL_PRIEST_UNFURLING_DARKNESS = 341273,
SPELL_PRIEST_UNFURLING_DARKNESS_AURA = 341282,
SPELL_PRIEST_UNFURLING_DARKNESS_DEBUFF = 341291,
SPELL_PRIEST_VAMPIRIC_EMBRACE_HEAL = 15290,
SPELL_PRIEST_VAMPIRIC_TOUCH = 34914,
SPELL_PRIEST_VOID_SHIELD = 199144,
SPELL_PRIEST_VOID_SHIELD_EFFECT = 199145,
SPELL_PRIEST_WEAKENED_SOUL = 6788,
SPELL_PRIEST_WHISPERING_SHADOWS = 406777,
SPELL_PRIEST_WHISPERING_SHADOWS_DUMMY = 391286,
SPELL_PVP_RULES_ENABLED_HARDCODED = 134735
};
enum PriestSpellVisuals
{
SPELL_VISUAL_PRIEST_POWER_WORD_RADIANCE = 52872,
SPELL_VISUAL_PRIEST_PRAYER_OF_MENDING = 38945
};
enum PriestSummons
{
NPC_PRIEST_DIVINE_IMAGE = 198236,
NPC_PRIEST_MINDBENDER = 62982,
NPC_PRIEST_SHADOWFIEND = 19668
};
class RaidCheck
{
public:
explicit RaidCheck(Unit const* caster) : _caster(caster) { }
bool operator()(WorldObject* obj) const
{
if (Unit* target = obj->ToUnit())
return !_caster->IsInRaidWith(target);
return true;
}
private:
Unit const* _caster;
};
// 121536 - Angelic Feather talent
class spell_pri_angelic_feather_trigger : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER });
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
Position destPos = GetHitDest()->GetPosition();
float radius = GetEffectInfo().CalcRadius();
// Caster is prioritary
if (GetCaster()->IsWithinDist2d(&destPos, radius))
{
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_ANGELIC_FEATHER_AURA, true);
}
else
{
CastSpellExtraArgs args;
args.TriggerFlags = TRIGGERED_FULL_MASK;
args.CastDifficulty = GetCastDifficulty();
GetCaster()->CastSpell(destPos, SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER, args);
}
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_pri_angelic_feather_trigger::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// Angelic Feather areatrigger - created by SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER
struct areatrigger_pri_angelic_feather : AreaTriggerAI
{
areatrigger_pri_angelic_feather(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { }
// Called when the AreaTrigger has just been initialized, just before added to map
void OnInitialize() override
{
if (Unit* caster = at->GetCaster())
{
std::vector areaTriggers = caster->GetAreaTriggers(SPELL_PRIEST_ANGELIC_FEATHER_AREATRIGGER);
if (areaTriggers.size() >= 3)
areaTriggers.front()->SetDuration(0);
}
}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsFriendlyTo(unit))
{
// If target already has aura, increase duration to max 130% of initial duration
caster->CastSpell(unit, SPELL_PRIEST_ANGELIC_FEATHER_AURA, true);
at->SetDuration(0);
}
}
}
};
// 391387 - Answered Prayers
class spell_pri_answered_prayers : public AuraScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ANSWERED_PRAYERS, SPELL_PRIEST_APOTHEOSIS })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
void HandleOnProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const
{
Milliseconds extraDuration = 0ms;
if (AuraEffect const* durationEffect = GetEffect(EFFECT_1))
extraDuration = Seconds(durationEffect->GetAmount());
Unit* target = eventInfo.GetActor();
Aura* answeredPrayers = target->GetAura(SPELL_PRIEST_ANSWERED_PRAYERS);
// Note: if caster has no aura, we must cast it first.
if (!answeredPrayers)
target->CastSpell(target, SPELL_PRIEST_ANSWERED_PRAYERS, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
else
{
// Note: there's no BaseValue dummy that we can use as reference, so we hardcode the increasing stack value.
answeredPrayers->ModStackAmount(1);
// Note: if current stacks match max. stacks, trigger Apotheosis.
if (answeredPrayers->GetStackAmount() != aurEff->GetAmount())
return;
answeredPrayers->Remove();
if (Aura* apotheosis = GetTarget()->GetAura(SPELL_PRIEST_APOTHEOSIS))
{
apotheosis->SetDuration(apotheosis->GetDuration() + extraDuration.count());
apotheosis->SetMaxDuration(apotheosis->GetMaxDuration() + extraDuration.count());
}
else
target->CastSpell(target, SPELL_PRIEST_APOTHEOSIS,
CastSpellExtraArgs(TRIGGERED_FULL_MASK & ~TRIGGERED_CAST_DIRECTLY)
.AddSpellMod(SPELLVALUE_DURATION, extraDuration.count()));
}
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_answered_prayers::HandleOnProc, EFFECT_0, SPELL_AURA_ADD_FLAT_MODIFIER_BY_SPELL_LABEL);
}
};
// 26169 - Oracle Healing Bonus
class spell_pri_aq_3p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ORACULAR_HEAL });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
if (caster == eventInfo.GetProcTarget())
return;
HealInfo* healInfo = eventInfo.GetHealInfo();
if (!healInfo || !healInfo->GetHeal())
return;
CastSpellExtraArgs args(aurEff);
args.AddSpellBP0(CalculatePct(static_cast(healInfo->GetHeal()), 10));
caster->CastSpell(caster, SPELL_PRIEST_ORACULAR_HEAL, args);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_aq_3p_bonus::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 81749 - Atonement
class spell_pri_atonement : public AuraScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT_HEAL, SPELL_PRIEST_SINS_OF_THE_MANY })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 }, { SPELL_PRIEST_SINS_OF_THE_MANY, EFFECT_2 } });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return eventInfo.GetDamageInfo() != nullptr;
}
void HandleOnProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
TriggerAtonementHealOnTargets(aurEff, eventInfo);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_atonement::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_atonement::HandleOnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
std::vector _appliedAtonements;
public:
void AddAtonementTarget(ObjectGuid const& target)
{
_appliedAtonements.push_back(target);
UpdateSinsOfTheManyValue();
}
void RemoveAtonementTarget(ObjectGuid const& target)
{
std::erase(_appliedAtonements, target);
UpdateSinsOfTheManyValue();
}
std::vector const& GetAtonementTargets() const
{
return _appliedAtonements;
}
struct TriggerArgs
{
SpellInfo const* TriggeredBy = nullptr;
SpellSchoolMask DamageSchoolMask = SPELL_SCHOOL_MASK_NONE;
};
void TriggerAtonementHealOnTargets(AuraEffect const* atonementEffect, ProcEventInfo const& eventInfo)
{
Unit* priest = GetUnitOwner();
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
CastSpellExtraArgs args(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
// Note: atonementEffect holds the correct amount since we passed the effect in the AuraScript that calls this method.
args.AddSpellMod(SPELLVALUE_BASE_POINT0, CalculatePct(damageInfo->GetDamage(), atonementEffect->GetAmount()));
args.SetCustomArg(TriggerArgs{
.TriggeredBy = eventInfo.GetSpellInfo(),
.DamageSchoolMask = eventInfo.GetDamageInfo()->GetSchoolMask() });
float distanceLimit = GetEffectInfo(EFFECT_1).CalcValue();
std::erase_if(_appliedAtonements, [priest, distanceLimit, &args](ObjectGuid const& targetGuid)
{
if (Unit* target = ObjectAccessor::GetUnit(*priest, targetGuid))
{
if (target->IsInDist2d(priest, distanceLimit))
priest->CastSpell(target, SPELL_PRIEST_ATONEMENT_HEAL, args);
return false;
}
return true;
});
}
void UpdateSinsOfTheManyValue() const
{
// Note: the damage dimish starts at the 6th application as of 10.0.5.
constexpr std::array damageByStack = { 20.0f, 20.0f, 20.0f, 20.0f, 20.0f, 17.5f, 15.0f, 12.5f, 10.0f, 7.5f, 5.5f, 4.0f, 2.5f, 2.0f, 1.5f, 1.25f, 1.0f, 0.75f, 0.63f, 0.5f };
for (SpellEffIndex effectIndex : { EFFECT_0, EFFECT_1, EFFECT_2 })
if (AuraEffect* sinOfTheMany = GetUnitOwner()->GetAuraEffect(SPELL_PRIEST_SINS_OF_THE_MANY, effectIndex))
sinOfTheMany->ChangeAmount(damageByStack[std::min(_appliedAtonements.size(), damageByStack.size() - 1)]);
}
};
// 81751 - Atonement (Heal)
class spell_pri_abyssal_reverie : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_ABYSSAL_REVERIE, EFFECT_0 } });
}
void CalculateHealingBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32 const& /*healing*/, int32 const& /*flatMod*/, float& pctMod) const
{
spell_pri_atonement::TriggerArgs const* args = std::any_cast(&GetSpell()->m_customArg);
if (!args || !(args->DamageSchoolMask & SPELL_SCHOOL_MASK_SHADOW))
return;
if (AuraEffect* const abyssalReverieEffect = GetCaster()->GetAuraEffect(SPELL_PRIEST_ABYSSAL_REVERIE, EFFECT_0))
AddPct(pctMod, abyssalReverieEffect->GetAmount());
}
void Register() override
{
CalcHealing += SpellCalcHealingFn(spell_pri_abyssal_reverie::CalculateHealingBonus);
}
};
// 17 - Power Word: Shield
// 139 - Renew
// 2061 - Flash Heal
// 194509 - Power Word: Radiance
class spell_pri_atonement_effect : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_ATONEMENT,
SPELL_PRIEST_ATONEMENT_EFFECT,
SPELL_PRIEST_TRINITY,
SPELL_PRIEST_TRINITY_EFFECT,
SPELL_PRIEST_POWER_WORD_RADIANCE,
SPELL_PRIEST_POWER_WORD_SHIELD
}) && ValidateSpellEffect({
{ SPELL_PRIEST_POWER_WORD_RADIANCE, EFFECT_3 },
{ SPELL_PRIEST_INDEMNITY, EFFECT_0 }
});
}
bool Load() override
{
Unit* caster = GetCaster();
if (!caster->HasAura(SPELL_PRIEST_ATONEMENT))
return false;
// only apply Trinity if the Priest has both Trinity and Atonement and the triggering spell is Power Word: Shield.
if (caster->HasAura(SPELL_PRIEST_TRINITY))
{
if (GetSpellInfo()->Id != SPELL_PRIEST_POWER_WORD_SHIELD)
return false;
_effectSpellId = SPELL_PRIEST_TRINITY_EFFECT;
}
return true;
}
void HandleOnHitTarget() const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.SetTriggeringSpell(GetSpell());
switch (GetSpellInfo()->Id)
{
case SPELL_PRIEST_POWER_WORD_SHIELD:
if (AuraEffect const* indemnity = caster->GetAuraEffect(SPELL_PRIEST_INDEMNITY, EFFECT_0))
args.AddSpellMod(SPELLVALUE_DURATION,
(Seconds(indemnity->GetAmount())
+ Milliseconds(Aura::CalcMaxDuration(sSpellMgr->AssertSpellInfo(_effectSpellId, GetCastDifficulty()),
caster, &GetSpell()->GetPowerCost()))).count());
break;
case SPELL_PRIEST_POWER_WORD_RADIANCE:
// Power Word: Radiance applies Atonement at 60 % (without modifiers) of its total duration.
args.AddSpellMod(SPELLVALUE_DURATION_PCT, GetEffectInfo(EFFECT_3).CalcValue(caster));
break;
default:
break;
}
caster->CastSpell(target, _effectSpellId, args);
}
void Register() override
{
AfterHit += SpellHitFn(spell_pri_atonement_effect::HandleOnHitTarget);
}
uint32 _effectSpellId = SPELL_PRIEST_ATONEMENT_EFFECT;
};
// 194384 - Atonement (Buff), 214206 - Atonement [Trinity] (Buff)
class spell_pri_atonement_effect_aura : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT });
}
void HandleOnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
RegisterHelper<&spell_pri_atonement::AddAtonementTarget>();
}
void HandleOnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
RegisterHelper<&spell_pri_atonement::RemoveAtonementTarget>();
}
template
void RegisterHelper() const
{
if (Unit* caster = GetCaster())
if (Aura* atonement = caster->GetAura(SPELL_PRIEST_ATONEMENT))
if (spell_pri_atonement* script = atonement->GetScript())
(script->*func)(GetTarget()->GetGUID());
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_pri_atonement_effect_aura::HandleOnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_pri_atonement_effect_aura::HandleOnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 195178 - Atonement (Passive)
class spell_pri_atonement_passive : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_ATONEMENT, EFFECT_0 } });
}
static bool CheckProc(ProcEventInfo const& eventInfo)
{
return eventInfo.GetDamageInfo() != nullptr;
}
void HandleOnProc(AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo) const
{
Unit* target = GetTarget();
Unit* summoner = target->GetOwner();
if (!summoner)
return;
if (AuraEffect const* atonementEffect = summoner->GetAuraEffect(SPELL_PRIEST_ATONEMENT, EFFECT_0))
if (spell_pri_atonement* script = atonementEffect->GetBase()->GetScript())
script->TriggerAtonementHealOnTargets(atonementEffect, eventInfo);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_atonement_passive::HandleOnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 33110 - Prayer of Mending (Heal)
class spell_pri_benediction : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_RENEW })
&& ValidateSpellEffect({ { SPELL_PRIEST_BENEDICTION, EFFECT_0 } });
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
if (AuraEffect const* benediction = GetCaster()->GetAuraEffect(SPELL_PRIEST_BENEDICTION, EFFECT_0))
if (roll_chance_i(benediction->GetAmount()))
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_RENEW, TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_benediction::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_HEAL);
}
};
// 215768 - Blaze of Light
class spell_pri_blaze_of_light : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_PRIEST_BLAZE_OF_LIGHT_DECREASE,
SPELL_PRIEST_BLAZE_OF_LIGHT_INCREASE
});
}
void HandleProc(ProcEventInfo const& eventInfo) const
{
Unit* procTarget = eventInfo.GetProcTarget();
if (!procTarget)
return;
if (GetTarget()->IsValidAttackTarget(procTarget))
GetTarget()->CastSpell(procTarget, SPELL_PRIEST_BLAZE_OF_LIGHT_DECREASE, TriggerCastFlags(TRIGGERED_CAST_DIRECTLY | TRIGGERED_IGNORE_CAST_IN_PROGRESS));
else
GetTarget()->CastSpell(procTarget, SPELL_PRIEST_BLAZE_OF_LIGHT_INCREASE, TriggerCastFlags(TRIGGERED_CAST_DIRECTLY | TRIGGERED_IGNORE_CAST_IN_PROGRESS));
}
void Register() override
{
OnProc += AuraProcFn(spell_pri_blaze_of_light::HandleProc);
}
};
// 204883 - Circle of Healing
class spell_pri_circle_of_healing : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
void FilterTargets(std::list& targets) const
{
// Note: we must remove one since target is always chosen.
uint32 const maxTargets = uint32(GetSpellInfo()->GetEffect(EFFECT_1).CalcValue(GetCaster()) - 1);
Trinity::SelectRandomInjuredTargets(targets, maxTargets, true);
if (Unit* explicitTarget = GetExplTargetUnit())
targets.push_front(explicitTarget);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_circle_of_healing::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
};
// 17 - Power Word: Shield
class spell_pri_crystalline_reflection : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_CRYSTALLINE_REFLECTION,
SPELL_PRIEST_CRYSTALLINE_REFLECTION_HEAL,
SPELL_PRIEST_CRYSTALLINE_REFLECTION_REFLECT,
}) && ValidateSpellEffect({ { SPELL_PRIEST_CRYSTALLINE_REFLECTION, EFFECT_0 } });
}
void HandleOnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
Unit* caster = GetCaster();
if (!caster)
return;
// Crystalline Reflection Heal
if (caster->HasAura(SPELL_PRIEST_CRYSTALLINE_REFLECTION))
caster->CastSpell(GetTarget(), SPELL_PRIEST_CRYSTALLINE_REFLECTION_HEAL, CastSpellExtraArgs(aurEff)
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR));
}
void HandleAfterAbsorb(AuraEffect const* /*aurEff*/, DamageInfo const& dmgInfo, uint32 const& absorbAmount) const
{
Unit* caster = GetCaster();
if (!caster)
return;
AuraEffect const* auraEff = caster->GetAuraEffect(SPELL_PRIEST_CRYSTALLINE_REFLECTION, EFFECT_0);
if (!auraEff)
return;
Unit* attacker = dmgInfo.GetAttacker();
if (!attacker)
return;
CastSpellExtraArgs args(TRIGGERED_DONT_REPORT_CAST_ERROR);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, CalculatePct(absorbAmount, auraEff->GetAmount()));
caster->CastSpell(attacker, SPELL_PRIEST_CRYSTALLINE_REFLECTION_REFLECT, args);
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_pri_crystalline_reflection::HandleOnApply, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_crystalline_reflection::HandleAfterAbsorb, EFFECT_0);
}
};
// 8092 - Mind Blast
class spell_pri_dark_indulgence : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_DARK_INDULGENCE, EFFECT_0 } });
}
void HandleEffectHit(SpellEffIndex /*effIndex*/) const
{
AuraEffect const* aurEff = GetCaster()->GetAuraEffect(SPELL_PRIEST_DARK_INDULGENCE, EFFECT_0);
if (!aurEff)
return;
if (roll_chance_i(aurEff->GetAmount()))
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_POWER_OF_THE_DARK_SIDE, true);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_pri_dark_indulgence::HandleEffectHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
namespace DivineImageHelpers
{
Unit* GetSummon(Unit const* owner)
{
for (Unit* summon : owner->m_Controlled)
if (summon->GetEntry() == NPC_PRIEST_DIVINE_IMAGE)
return summon;
return nullptr;
}
Optional GetSpellToCast(uint32 spellId)
{
switch (spellId)
{
case SPELL_PRIEST_RENEW:
return SPELL_PRIEST_TRANQUIL_LIGHT;
case SPELL_PRIEST_POWER_WORD_SHIELD:
case SPELL_PRIEST_POWER_WORD_LIFE:
case SPELL_PRIEST_FLASH_HEAL:
case SPELL_PRIEST_HEAL:
case SPELL_PRIEST_GREATER_HEAL:
case SPELL_PRIEST_HOLY_WORD_SERENITY:
return SPELL_PRIEST_HEALING_LIGHT;
case SPELL_PRIEST_PRAYER_OF_MENDING:
case SPELL_PRIEST_PRAYER_OF_MENDING_HEAL:
return SPELL_PRIEST_BLESSED_LIGHT;
case SPELL_PRIEST_PRAYER_OF_HEALING:
case SPELL_PRIEST_CIRCLE_OF_HEALING:
case SPELL_PRIEST_HALO_HOLY:
case SPELL_PRIEST_DIVINE_STAR_HOLY_HEAL:
case SPELL_PRIEST_DIVINE_HYMN_HEAL:
case SPELL_PRIEST_HOLY_WORD_SANCTIFY:
case SPELL_PRIEST_HOLY_WORD_SALVATION:
return SPELL_PRIEST_DAZZLING_LIGHT;
case SPELL_PRIEST_SHADOW_WORD_PAIN:
case SPELL_PRIEST_SMITE:
case SPELL_PRIEST_HOLY_FIRE:
case SPELL_PRIEST_SHADOW_WORD_DEATH:
case SPELL_PRIEST_HOLY_WORD_CHASTISE:
case SPELL_PRIEST_MINDGAMES:
case SPELL_PRIEST_MINDGAMES_VENTHYR:
return SPELL_PRIEST_SEARING_LIGHT;
case SPELL_PRIEST_HOLY_NOVA:
return SPELL_PRIEST_LIGHT_ERUPTION;
default:
break;
}
return {};
}
void Trigger(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
Unit* target = eventInfo.GetActor();
if (!target)
return;
Unit* divineImage = GetSummon(target);
if (!divineImage)
return;
Optional spellId = GetSpellToCast(eventInfo.GetSpellInfo()->Id);
if (!spellId)
return;
divineImage->CastSpell(SpellCastTargets(eventInfo.GetProcSpell()->m_targets), *spellId, aurEff);
}
}
// 392988 - Divine Image
class spell_pri_divine_image : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_DIVINE_IMAGE_SUMMON,
SPELL_PRIEST_DIVINE_IMAGE_EMPOWER,
SPELL_PRIEST_DIVINE_IMAGE_EMPOWER_STACK
});
}
static void HandleProc(AuraScript const& script, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
Unit* target = eventInfo.GetActor();
if (!target)
return;
// Note: if target has an active Divine Image, we should empower it rather than summoning a new one.
if (Unit* divineImage = DivineImageHelpers::GetSummon(target))
{
// Note: Divine Image now teleports near the target when they cast a Holy Word spell if the Divine Image is further than 15 yards away (Patch 10.1.0).
if (target->GetDistance(divineImage) > 15.0f)
divineImage->NearTeleportTo(target->GetRandomNearPosition(3.0f));
if (TempSummon* tempSummon = divineImage->ToTempSummon())
tempSummon->RefreshTimer();
divineImage->CastSpell(divineImage, SPELL_PRIEST_DIVINE_IMAGE_EMPOWER, eventInfo.GetProcSpell());
}
else
{
target->CastSpell(target, SPELL_PRIEST_DIVINE_IMAGE_SUMMON, CastSpellExtraArgs()
.SetTriggeringAura(aurEff)
.SetTriggeringSpell(eventInfo.GetProcSpell())
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DISALLOW_PROC_EVENTS | TRIGGERED_DONT_REPORT_CAST_ERROR));
// Note: Divine Image triggers a cast immediately based on the Holy Word cast.
DivineImageHelpers::Trigger(script, aurEff, eventInfo);
}
target->CastSpell(target, SPELL_PRIEST_DIVINE_IMAGE_EMPOWER_STACK, CastSpellExtraArgs()
.SetTriggeringAura(aurEff)
.SetTriggeringSpell(eventInfo.GetProcSpell())
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DISALLOW_PROC_EVENTS | TRIGGERED_DONT_REPORT_CAST_ERROR));
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_divine_image::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 405216 - Divine Image (Spell Cast Check)
class spell_pri_divine_image_spell_triggered : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_RENEW,
SPELL_PRIEST_POWER_WORD_SHIELD,
SPELL_PRIEST_POWER_WORD_LIFE,
SPELL_PRIEST_FLASH_HEAL,
SPELL_PRIEST_HOLY_WORD_SERENITY,
SPELL_PRIEST_PRAYER_OF_MENDING,
SPELL_PRIEST_PRAYER_OF_MENDING_HEAL,
SPELL_PRIEST_PRAYER_OF_HEALING,
SPELL_PRIEST_CIRCLE_OF_HEALING,
SPELL_PRIEST_HALO_HOLY,
SPELL_PRIEST_DIVINE_STAR_HOLY_HEAL,
SPELL_PRIEST_DIVINE_HYMN_HEAL,
SPELL_PRIEST_HOLY_WORD_SANCTIFY,
SPELL_PRIEST_HOLY_WORD_SALVATION,
SPELL_PRIEST_SMITE,
SPELL_PRIEST_HOLY_FIRE,
SPELL_PRIEST_SHADOW_WORD_DEATH,
SPELL_PRIEST_SHADOW_WORD_PAIN,
SPELL_PRIEST_MINDGAMES,
SPELL_PRIEST_MINDGAMES_VENTHYR,
SPELL_PRIEST_HOLY_WORD_CHASTISE,
SPELL_PRIEST_HOLY_NOVA,
SPELL_PRIEST_TRANQUIL_LIGHT,
SPELL_PRIEST_HEALING_LIGHT,
SPELL_PRIEST_BLESSED_LIGHT,
SPELL_PRIEST_DAZZLING_LIGHT,
SPELL_PRIEST_SEARING_LIGHT,
SPELL_PRIEST_LIGHT_ERUPTION,
SPELL_PRIEST_DIVINE_IMAGE_EMPOWER_STACK
});
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return DivineImageHelpers::GetSummon(eventInfo.GetActor()) != nullptr;
}
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
GetTarget()->RemoveAurasDueToSpell(SPELL_PRIEST_DIVINE_IMAGE_EMPOWER_STACK);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_divine_image_spell_triggered::CheckProc);
OnEffectProc += AuraEffectProcFn(DivineImageHelpers::Trigger, EFFECT_0, SPELL_AURA_DUMMY);
AfterEffectRemove += AuraEffectRemoveFn(spell_pri_divine_image_spell_triggered::HandleAfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 405963 Divine Image
// 409387 Divine Image
class spell_pri_divine_image_stack_timer : public AuraScript
{
void TrackStackApplicationTime(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
GetUnitOwner()->m_Events.AddEventAtOffset([spelId = GetId(), owner = GetUnitOwner()]
{
owner->RemoveAuraFromStack(spelId);
}, Milliseconds(GetMaxDuration()));
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_pri_divine_image_stack_timer::TrackStackApplicationTime, EFFECT_0, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
// 33110 - Prayer of Mending (Heal)
class spell_pri_divine_service : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING_AURA })
&& ValidateSpellEffect({ { SPELL_PRIEST_DIVINE_SERVICE, EFFECT_0 } });
}
void CalculateHealingBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* victim, int32& /*healing*/, int32& /*flatMod*/, float& pctMod) const
{
if (AuraEffect const* divineServiceEffect = GetCaster()->GetAuraEffect(SPELL_PRIEST_DIVINE_SERVICE, EFFECT_0))
if (Aura const* prayerOfMending = victim->GetAura(SPELL_PRIEST_PRAYER_OF_MENDING_AURA, GetCaster()->GetGUID()))
AddPct(pctMod, int32(divineServiceEffect->GetAmount() * prayerOfMending->GetStackAmount()));
}
void Register() override
{
CalcHealing += SpellCalcHealingFn(spell_pri_divine_service::CalculateHealingBonus);
}
};
// 122121 - Divine Star (Shadow)
class spell_pri_divine_star_shadow : public SpellScript
{
void HandleHitTarget(SpellEffIndex effIndex)
{
Unit* caster = GetCaster();
if (caster->GetPowerType() != GetEffectInfo().MiscValue)
PreventHitDefaultEffect(effIndex);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_divine_star_shadow::HandleHitTarget, EFFECT_2, SPELL_EFFECT_ENERGIZE);
}
};
// 110744 - Divine Star (Holy)
// 122121 - Divine Star (Shadow)
struct areatrigger_pri_divine_star : AreaTriggerAI
{
using AreaTriggerAI::AreaTriggerAI;
void OnInitialize() override
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(at->GetSpellId(), DIFFICULTY_NONE);
if (!spellInfo)
return;
if (spellInfo->GetEffects().size() <= EFFECT_1)
return;
Unit* caster = at->GetCaster();
if (!caster)
return;
_casterCurrentPosition = caster->GetPosition();
// Note: max. distance at which the Divine Star can travel to is EFFECT_1's BasePoints yards.
float maxTravelDistance = float(spellInfo->GetEffect(EFFECT_1).CalcValue(caster));
Position destPos = _casterCurrentPosition;
at->MovePositionToFirstCollision(destPos, maxTravelDistance, 0.0f);
PathGenerator firstPath(at);
firstPath.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false);
at->InitSplines(firstPath.GetPath());
}
void OnUpdate(uint32 diff) override
{
_scheduler.Update(diff);
}
void OnUnitEnter(Unit* unit) override
{
HandleUnitEnterExit(unit);
}
void OnUnitExit(Unit* unit, AreaTriggerExitReason /*reason*/) override
{
// Note: this ensures any unit receives a second hit if they happen to be inside the AT when Divine Star starts its return path.
HandleUnitEnterExit(unit);
}
void HandleUnitEnterExit(Unit* unit)
{
Unit* caster = at->GetCaster();
if (!caster)
return;
if (advstd::ranges::contains(_affectedUnits, unit->GetGUID()))
return;
constexpr TriggerCastFlags TriggerFlags = TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS;
if (caster->IsValidAttackTarget(unit))
caster->CastSpell(unit, at->GetSpellId() == SPELL_PRIEST_DIVINE_STAR_SHADOW ? SPELL_PRIEST_DIVINE_STAR_SHADOW_DAMAGE : SPELL_PRIEST_DIVINE_STAR_HOLY_DAMAGE,
TriggerFlags);
else if (caster->IsValidAssistTarget(unit))
caster->CastSpell(unit, at->GetSpellId() == SPELL_PRIEST_DIVINE_STAR_SHADOW ? SPELL_PRIEST_DIVINE_STAR_SHADOW_HEAL : SPELL_PRIEST_DIVINE_STAR_HOLY_HEAL,
TriggerFlags);
_affectedUnits.push_back(unit->GetGUID());
}
void OnDestinationReached() override
{
Unit* caster = at->GetCaster();
if (!caster)
return;
if (at->GetDistance(_casterCurrentPosition) > 0.05f)
{
_affectedUnits.clear();
ReturnToCaster();
}
else
at->Remove();
}
void ReturnToCaster()
{
_scheduler.Schedule(0ms, [this](TaskContext task)
{
Unit* caster = at->GetCaster();
if (!caster)
return;
_casterCurrentPosition = caster->GetPosition();
Movement::PointsArray returnSplinePoints;
returnSplinePoints.push_back(PositionToVector3(at));
returnSplinePoints.push_back(PositionToVector3(caster));
at->InitSplines(returnSplinePoints);
task.Repeat(250ms);
});
}
private:
TaskScheduler _scheduler;
Position _casterCurrentPosition;
std::vector _affectedUnits;
};
// 391339 - Empowered Renew
class spell_pri_empowered_renew : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_RENEW, SPELL_PRIEST_EMPOWERED_RENEW_HEAL })
&& ValidateSpellEffect({ { SPELL_PRIEST_RENEW, EFFECT_0 } })
&& sSpellMgr->AssertSpellInfo(SPELL_PRIEST_RENEW, DIFFICULTY_NONE)->GetEffect(EFFECT_0).IsAura(SPELL_AURA_PERIODIC_HEAL);
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo const& eventInfo) const
{
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
SpellInfo const* renewSpellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_RENEW, GetCastDifficulty());
SpellEffectInfo const& renewEffect = renewSpellInfo->GetEffect(EFFECT_0);
int32 estimatedTotalHeal = AuraEffect::CalculateEstimatedfTotalPeriodicAmount(caster, target, renewSpellInfo, renewEffect, renewEffect.CalcValue(caster), 1);
int32 healAmount = CalculatePct(estimatedTotalHeal, aurEff->GetAmount());
caster->CastSpell(target, SPELL_PRIEST_EMPOWERED_RENEW_HEAL, CastSpellExtraArgs(aurEff).AddSpellBP0(healAmount));
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_empowered_renew::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 414553 - Epiphany
class spell_pri_epiphany : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING, SPELL_PRIEST_EPIPHANY_HIGHLIGHT });
}
static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
return roll_chance_i(aurEff->GetAmount());
}
void HandleOnProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) const
{
Unit* target = GetTarget();
target->GetSpellHistory()->ResetCooldown(SPELL_PRIEST_PRAYER_OF_MENDING, true);
target->CastSpell(target, SPELL_PRIEST_EPIPHANY_HIGHLIGHT, aurEff);
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_epiphany::CheckProc, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_pri_epiphany::HandleOnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 415673 - Essence Devourer (Heal)
// 415676 - Essence Devourer (Heal)
class spell_pri_essence_devourer_heal : public SpellScript
{
static void FilterTargets(SpellScript const&, std::list& targets)
{
Trinity::SelectRandomInjuredTargets(targets, 1, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_essence_devourer_heal::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
};
// 246287 - Evangelism
class spell_pri_evangelism : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_TRINITY,
SPELL_PRIEST_ATONEMENT_EFFECT,
SPELL_PRIEST_TRINITY_EFFECT
});
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
Aura* atonementAura = caster->HasAura(SPELL_PRIEST_TRINITY)
? target->GetAura(SPELL_PRIEST_TRINITY_EFFECT, caster->GetGUID())
: target->GetAura(SPELL_PRIEST_ATONEMENT_EFFECT, caster->GetGUID());
if (!atonementAura)
return;
Milliseconds extraDuration = Seconds(GetEffectValue());
atonementAura->SetDuration(atonementAura->GetDuration() + extraDuration.count());
atonementAura->SetMaxDuration(atonementAura->GetDuration() + extraDuration.count());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_evangelism::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 33110 - Prayer of Mending (Heal)
class spell_pri_focused_mending : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_FOCUSED_MENDING, EFFECT_0 } });
}
void CalculateHealingBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit* /*victim*/, int32& /*healing*/, int32& /*flatMod*/, float& pctMod) const
{
if (AuraEffect const* focusedMendingEffect = GetCaster()->GetAuraEffect(SPELL_PRIEST_FOCUSED_MENDING, EFFECT_0))
{
bool const* isEmpoweredByFocusedMending = std::any_cast(&GetSpell()->m_customArg);
if (isEmpoweredByFocusedMending && *isEmpoweredByFocusedMending)
AddPct(pctMod, focusedMendingEffect->GetAmount());
}
}
void Register() override
{
CalcHealing += SpellCalcHealingFn(spell_pri_focused_mending::CalculateHealingBonus);
}
};
// 390615 - From Darkness Comes Light (Talent)
class spell_pri_from_darkness_comes_light : public AuraScript
{
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) const
{
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_FROM_DARKNESS_COMES_LIGHT_AURA, aurEff);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_from_darkness_comes_light::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 47788 - Guardian Spirit
class spell_pri_guardian_spirit : public AuraScript
{
uint32 healPct = 0;
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL }) && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
bool Load() override
{
healPct = GetEffectInfo(EFFECT_1).CalcValue();
return true;
}
static void CalculateAmount(AuraScript const&, AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
{
// Set absorbtion amount to unlimited
amount = -1;
}
void Absorb(AuraEffect* /*aurEff*/, DamageInfo const& dmgInfo, uint32 & absorbAmount)
{
Unit* target = GetTarget();
if (dmgInfo.GetDamage() < target->GetHealth())
return;
int32 healAmount = int32(target->CountPctFromMaxHealth(healPct));
// remove the aura now, we don't want 40% healing bonus
Remove(AURA_REMOVE_BY_ENEMY_SPELL);
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.AddSpellBP0(healAmount);
target->CastSpell(target, SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL, args);
absorbAmount = dmgInfo.GetDamage();
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_guardian_spirit::CalculateAmount, EFFECT_1, SPELL_AURA_SCHOOL_ABSORB);
OnEffectAbsorb += AuraEffectAbsorbFn(spell_pri_guardian_spirit::Absorb, EFFECT_1);
}
};
// 421558 - Heaven's Wrath
class spell_pri_heavens_wrath : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ULTIMATE_PENITENCE });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return !(eventInfo.GetSpellInfo()->Id == SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE || eventInfo.GetSpellInfo()->Id == SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL);
}
static void HandleEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
Unit* caster = eventInfo.GetActor();
if (!caster)
return;
int32 cdReduction = aurEff->GetAmount();
caster->GetSpellHistory()->ModifyCooldown(SPELL_PRIEST_ULTIMATE_PENITENCE, Seconds(-cdReduction), true);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_heavens_wrath::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 120644 - Halo (Shadow)
class spell_pri_halo_shadow : public SpellScript
{
void HandleHitTarget(SpellEffIndex effIndex)
{
Unit* caster = GetCaster();
if (caster->GetPowerType() != GetEffectInfo().MiscValue)
PreventHitDefaultEffect(effIndex);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_halo_shadow::HandleHitTarget, EFFECT_1, SPELL_EFFECT_ENERGIZE);
}
};
// 120517 - Halo (Holy)
// 120644 - Halo (Shadow)
struct areatrigger_pri_halo : AreaTriggerAI
{
areatrigger_pri_halo(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) {}
void OnUnitEnter(Unit* unit) override
{
if (Unit* caster = at->GetCaster())
{
if (caster->IsValidAttackTarget(unit))
caster->CastSpell(unit, at->GetSpellId() == SPELL_PRIEST_HALO_SHADOW ? SPELL_PRIEST_HALO_SHADOW_DAMAGE : SPELL_PRIEST_HALO_HOLY_DAMAGE,
TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS);
else if (caster->IsValidAssistTarget(unit))
caster->CastSpell(unit, at->GetSpellId() == SPELL_PRIEST_HALO_SHADOW ? SPELL_PRIEST_HALO_SHADOW_HEAL : SPELL_PRIEST_HALO_HOLY_HEAL,
TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS);
}
}
};
// 391154 - Holy Mending
class spell_pri_holy_mending : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_RENEW, SPELL_PRIEST_HOLY_MENDING_HEAL });
}
static bool CheckProc(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& procInfo)
{
return procInfo.GetProcTarget()->HasAura(SPELL_PRIEST_RENEW, procInfo.GetActor()->GetGUID());
}
static void HandleProc(AuraScript const&, AuraEffect* aurEff, ProcEventInfo const& eventInfo)
{
eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_PRIEST_HOLY_MENDING_HEAL, CastSpellExtraArgs(aurEff));
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_holy_mending::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
OnEffectProc += AuraEffectProcFn(spell_pri_holy_mending::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 63733 - Holy Words
class spell_pri_holy_words : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_PRIEST_HEAL,
SPELL_PRIEST_FLASH_HEAL,
SPELL_PRIEST_PRAYER_OF_HEALING,
SPELL_PRIEST_RENEW,
SPELL_PRIEST_SMITE,
SPELL_PRIEST_HOLY_WORD_CHASTISE,
SPELL_PRIEST_HOLY_WORD_SANCTIFY,
SPELL_PRIEST_HOLY_WORD_SERENITY
}) && ValidateSpellEffect(
{
{ SPELL_PRIEST_HOLY_WORD_SERENITY, EFFECT_1 },
{ SPELL_PRIEST_HOLY_WORD_SANCTIFY, EFFECT_3 },
{ SPELL_PRIEST_HOLY_WORD_CHASTISE, EFFECT_1 }
});
}
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo const& eventInfo) const
{
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
if (!spellInfo)
return;
uint32 targetSpellId;
SpellEffIndex cdReductionEffIndex;
switch (spellInfo->Id)
{
case SPELL_PRIEST_HEAL:
case SPELL_PRIEST_FLASH_HEAL: // reduce Holy Word: Serenity cd by 6 seconds
targetSpellId = SPELL_PRIEST_HOLY_WORD_SERENITY;
cdReductionEffIndex = EFFECT_1;
// cdReduction = sSpellMgr->GetSpellInfo(SPELL_PRIEST_HOLY_WORD_SERENITY, GetCastDifficulty())->GetEffect(EFFECT_1)->CalcValue(player);
break;
case SPELL_PRIEST_PRAYER_OF_HEALING: // reduce Holy Word: Sanctify cd by 6 seconds
targetSpellId = SPELL_PRIEST_HOLY_WORD_SANCTIFY;
cdReductionEffIndex = EFFECT_2;
break;
case SPELL_PRIEST_RENEW: // reuce Holy Word: Sanctify cd by 2 seconds
targetSpellId = SPELL_PRIEST_HOLY_WORD_SANCTIFY;
cdReductionEffIndex = EFFECT_3;
break;
case SPELL_PRIEST_SMITE: // reduce Holy Word: Chastise cd by 4 seconds
targetSpellId = SPELL_PRIEST_HOLY_WORD_CHASTISE;
cdReductionEffIndex = EFFECT_1;
break;
default:
TC_LOG_WARN("spells.priest", "HolyWords aura has been proced by an unknown spell: {}", GetSpellInfo()->Id);
return;
}
SpellInfo const* targetSpellInfo = sSpellMgr->AssertSpellInfo(targetSpellId, GetCastDifficulty());
int32 cdReduction = targetSpellInfo->GetEffect(cdReductionEffIndex).CalcValue(GetTarget());
GetTarget()->GetSpellHistory()->ModifyCooldown(targetSpellInfo, Seconds(-cdReduction), true);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_holy_words::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 265202 - Holy Word: Salvation
class spell_pri_holy_word_salvation : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_PRAYER_OF_MENDING_AURA,
SPELL_PRIEST_RENEW
}) && ValidateSpellEffect({
{ SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, EFFECT_0 },
{ spellInfo->Id, EFFECT_1 }
}) && spellInfo->GetEffect(EFFECT_1).TargetB.GetTarget() == TARGET_UNIT_SRC_AREA_ALLY;
}
bool Load() override
{
_spellInfoHeal = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, DIFFICULTY_NONE);
_healEffectDummy = &_spellInfoHeal->GetEffect(EFFECT_0);
return true;
}
void HandleApplyBuffs(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
CastSpellExtraArgs args;
args.TriggerFlags = TRIGGERED_FULL_MASK;
// amount of Prayer of Mending is SPELL_PRIEST_HOLY_WORD_SALVATION's EFFECT_1.
args.AddSpellMod(SPELLVALUE_AURA_STACK, GetEffectValue());
int32 basePoints = caster->SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy->CalcValue(caster), HEAL, *_healEffectDummy);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, basePoints);
caster->CastSpell(target, SPELL_PRIEST_PRAYER_OF_MENDING_AURA, args);
// a full duration Renew is triggered.
caster->CastSpell(target, SPELL_PRIEST_RENEW, CastSpellExtraArgs(TRIGGERED_FULL_MASK).SetTriggeringSpell(GetSpell()));
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_holy_word_salvation::HandleApplyBuffs, EFFECT_1, SPELL_EFFECT_DUMMY);
}
SpellInfo const* _spellInfoHeal = nullptr;
SpellEffectInfo const* _healEffectDummy = nullptr;
};
// 2050 - Holy Word: Serenity
// 34861 - Holy Word: Sanctify
class spell_pri_holy_word_salvation_cooldown_reduction : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_HOLY_WORD_SALVATION })
&& ValidateSpellEffect({ { SPELL_PRIEST_HOLY_WORD_SALVATION, EFFECT_2 } });
}
bool Load() override
{
return GetCaster()->HasSpell(SPELL_PRIEST_HOLY_WORD_SALVATION);
}
void ReduceCooldown() const
{
// cooldown reduced by SPELL_PRIEST_HOLY_WORD_SALVATION's Seconds(EFFECT_2).
int32 cooldownReduction = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_HOLY_WORD_SALVATION, GetCastDifficulty())->GetEffect(EFFECT_2).CalcValue(GetCaster());
GetCaster()->GetSpellHistory()->ModifyCooldown(SPELL_PRIEST_HOLY_WORD_SALVATION, Seconds(-cooldownReduction), true);
}
void Register() override
{
AfterCast += SpellCastFn(spell_pri_holy_word_salvation_cooldown_reduction::ReduceCooldown);
}
};
// 40438 - Priest Tier 6 Trinket
class spell_pri_item_t6_trinket : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_DIVINE_BLESSING, SPELL_PRIEST_DIVINE_WRATH });
}
void HandleProc(AuraEffect* /*aurEff*/, ProcEventInfo const& eventInfo)
{
PreventDefaultAction();
Unit* caster = eventInfo.GetActor();
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_HEAL)
caster->CastSpell(nullptr, SPELL_PRIEST_DIVINE_BLESSING, true);
if (eventInfo.GetSpellTypeMask() & PROC_SPELL_TYPE_DAMAGE)
caster->CastSpell(nullptr, SPELL_PRIEST_DIVINE_WRATH, true);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_item_t6_trinket::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 92833 - Leap of Faith
class spell_pri_leap_of_faith_effect_trigger : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_LEAP_OF_FAITH_EFFECT });
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
Position destPos = GetHitDest()->GetPosition();
SpellCastTargets targets;
targets.SetDst(destPos);
targets.SetUnitTarget(GetCaster());
GetHitUnit()->CastSpell(std::move(targets), GetEffectValue(), GetCastDifficulty());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_leap_of_faith_effect_trigger::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 1706 - Levitate
class spell_pri_levitate : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_LEVITATE_EFFECT });
}
void HandleDummy(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_LEVITATE_EFFECT, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_levitate::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 373178 - Light's Wrath
class spell_pri_lights_wrath : public SpellScript
{
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } });
}
void OnPrecast() override
{
Aura const* atonement = GetCaster()->GetAura(SPELL_PRIEST_ATONEMENT);
if (!atonement)
return;
spell_pri_atonement const* script = atonement->GetScript();
if (!script)
return;
for (ObjectGuid const& atonementTarget : script->GetAtonementTargets())
{
if (Unit* target = ObjectAccessor::GetUnit(*GetCaster(), atonementTarget))
{
target->CancelSpellMissiles(SPELL_PRIEST_LIGHTS_WRATH_VISUAL, false, false);
target->CastSpell(GetCaster(), SPELL_PRIEST_LIGHTS_WRATH_VISUAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS);
}
}
}
void CalculateDamageBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* /*victim*/, int32 const& /*damage*/, int32 const& /*flatMod*/, float& pctMod) const
{
Aura const* atonement = GetCaster()->GetAura(SPELL_PRIEST_ATONEMENT);
if (!atonement)
return;
// Atonement size may have changed when missile hits, we need to take an updated count of Atonement applications.
if (spell_pri_atonement const* script = atonement->GetScript())
AddPct(pctMod, GetEffectInfo(EFFECT_1).CalcValue(GetCaster()) * script->GetAtonementTargets().size());
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_pri_lights_wrath::CalculateDamageBonus);
}
};
// 205369 - Mind Bomb
class spell_pri_mind_bomb : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_MIND_BOMB_STUN });
}
void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH || GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
if (Unit* caster = GetCaster())
caster->CastSpell(GetTarget()->GetPosition(), SPELL_PRIEST_MIND_BOMB_STUN, true);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_pri_mind_bomb::RemoveEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 373202 - Mind Devourer
// Triggered by 8092 - Mind Blast
class spell_pri_mind_devourer : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_MIND_DEVOURER_AURA })
&& ValidateSpellEffect({ { SPELL_PRIEST_MIND_DEVOURER, EFFECT_0 } });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_PRIEST_MIND_DEVOURER);
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
AuraEffect const* aurEff = GetCaster()->GetAuraEffect(SPELL_PRIEST_MIND_DEVOURER, EFFECT_0);
if (aurEff && roll_chance_i(aurEff->GetAmount()))
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_MIND_DEVOURER_AURA, GetSpell());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_mind_devourer::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 373204 - Mind Devourer (Aura)
// Attached to 335467 - Devouring Plague
class spell_pri_mind_devourer_buff_aura : public AuraScript
{
void CalculateDamage(AuraEffect const* /*aurEff*/, Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const
{
AddPct(pctMod, DamageIncrease);
}
void Register() override
{
DoEffectCalcDamageAndHealing += AuraEffectCalcDamageFn(spell_pri_mind_devourer_buff_aura::CalculateDamage, EFFECT_1, SPELL_AURA_PERIODIC_LEECH);
}
public:
float DamageIncrease = 0.0f;
};
class spell_pri_mind_devourer_buff : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_MIND_DEVOURER_AURA, EFFECT_1 } });
}
void OnPrecast() override
{
AuraEffect const* mindDevourer = GetCaster()->GetAuraEffect(SPELL_PRIEST_MIND_DEVOURER_AURA, EFFECT_1);
if (!mindDevourer || !GetSpell()->m_appliedMods.contains(mindDevourer->GetBase()))
return;
_damageIncrease = mindDevourer->GetAmount();
}
void CalculateDamage(SpellEffectInfo const& /*spellEffectInfo*/, Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const
{
AddPct(pctMod, _damageIncrease);
}
void ModifyAuraValueAndRemoveBuff(SpellEffIndex /*effIndex*/) const
{
if (!_damageIncrease)
return;
if (Aura* devouringPlague = GetHitAura())
if (spell_pri_mind_devourer_buff_aura* script = devouringPlague->GetScript())
script->DamageIncrease = _damageIncrease;
GetCaster()->RemoveAurasDueToSpell(SPELL_PRIEST_MIND_DEVOURER_AURA);
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_pri_mind_devourer_buff::CalculateDamage);
OnEffectHitTarget += SpellEffectFn(spell_pri_mind_devourer_buff::ModifyAuraValueAndRemoveBuff, EFFECT_1, SPELL_EFFECT_APPLY_AURA);
}
float _damageIncrease = 0.0f;
};
// 390686 - Painful Punishment
class spell_pri_painful_punishment : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_SHADOW_WORD_PAIN,
SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC
});
}
static void HandleEffectProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetActionTarget();
if (!caster || !target)
return;
int32 additionalDuration = aurEff->GetAmount();
if (Aura* shadowWordPain = target->GetOwnedAura(SPELL_PRIEST_SHADOW_WORD_PAIN, caster->GetGUID()))
shadowWordPain->SetDuration(shadowWordPain->GetDuration() + additionalDuration);
if (Aura* purgeTheWicked = target->GetOwnedAura(SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, caster->GetGUID()))
purgeTheWicked->SetDuration(purgeTheWicked->GetDuration() + additionalDuration);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_painful_punishment::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 372991 - Pain Transformation
// Triggered by 33206 - Pain Suppression
class spell_pri_pain_transformation : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_ATONEMENT_EFFECT,
SPELL_PRIEST_TRINITY,
SPELL_PRIEST_PAIN_TRANSFORMATION,
SPELL_PRIEST_PAIN_TRANSFORMATION_HEAL
});
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_PRIEST_PAIN_TRANSFORMATION) && !GetCaster()->HasAura(SPELL_PRIEST_TRINITY);
}
void HandleHit(SpellEffIndex /*effIndex*/) const
{
CastSpellExtraArgs args(GetSpell());
args.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_PAIN_TRANSFORMATION_HEAL, args);
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_ATONEMENT_EFFECT, args);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_pain_transformation::HandleHit, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
// 47540 - Penance
// 400169 - Dark Reprimand
class spell_pri_penance : public SpellScript
{
public:
spell_pri_penance(uint32 damageSpellId, uint32 healingSpellId) : _damageSpellId(damageSpellId), _healingSpellId(healingSpellId)
{
}
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ _damageSpellId, _healingSpellId });
}
SpellCastResult CheckCast() const
{
Unit* caster = GetCaster();
if (Unit* target = GetExplTargetUnit())
{
if (!caster->IsFriendlyTo(target))
{
if (!caster->IsValidAttackTarget(target))
return SPELL_FAILED_BAD_TARGETS;
if (!caster->isInFront(target))
return SPELL_FAILED_UNIT_NOT_INFRONT;
}
}
return SPELL_CAST_OK;
}
void HandleDummy(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
{
if (caster->IsFriendlyTo(target))
caster->CastSpell(target, _healingSpellId, CastSpellExtraArgs(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD)
.SetTriggeringSpell(GetSpell()));
else
caster->CastSpell(target, _damageSpellId, CastSpellExtraArgs(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD)
.SetTriggeringSpell(GetSpell()));
}
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_pri_penance::CheckCast);
OnEffectHitTarget += SpellEffectFn(spell_pri_penance::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
private:
uint32 _damageSpellId;
uint32 _healingSpellId;
};
// 47758 - Penance (Channel Damage), 47757 - Penance (Channel Healing)
// 373129 - Dark Reprimand (Channel Damage), 400171 - Dark Reprimand (Channel Healing)
class spell_pri_penance_or_dark_reprimand_channeled : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_OF_THE_DARK_SIDE });
}
void HandleOnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
if (Unit* caster = GetCaster())
caster->RemoveAura(SPELL_PRIEST_POWER_OF_THE_DARK_SIDE);
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_pri_penance_or_dark_reprimand_channeled::HandleOnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 114239 - Phantasm
class spell_pri_phantasm : public SpellScript
{
void HandleEffectHit(SpellEffIndex /*effIndex*/) const
{
GetCaster()->RemoveMovementImpairingAuras(false);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_pri_phantasm::HandleEffectHit, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 262484 - Power Leech (Passive for Shadowfiend)
// 284621 - Power Leech (Passive for Mindbender)
class spell_pri_power_leech_passive : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_INSANITY,
SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_MANA,
SPELL_PRIEST_POWER_LEECH_MINDBENDER_INSANITY,
SPELL_PRIEST_POWER_LEECH_MINDBENDER_MANA,
SPELL_PRIEST_ESSENCE_DEVOURER,
SPELL_PRIEST_ESSENCE_DEVOURER_SHADOWFIEND_HEAL,
SPELL_PRIEST_ESSENCE_DEVOURER_MINDBENDER_HEAL
})
&& ValidateSpellEffect
({
{ SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_INSANITY, EFFECT_0 },
{ SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_MANA, EFFECT_0 },
{ SPELL_PRIEST_POWER_LEECH_MINDBENDER_INSANITY, EFFECT_0 },
{ SPELL_PRIEST_POWER_LEECH_MINDBENDER_MANA, EFFECT_0 }
});
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return eventInfo.GetDamageInfo() != nullptr;
}
void HandleOnProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) const
{
Unit* target = GetTarget();
Player* summoner = Object::ToPlayer(target->GetOwner());
if (!summoner)
return;
SpellInfo const* spellInfo = nullptr;
int32 divisor = 1;
if (summoner->GetPrimarySpecialization() != ChrSpecialization::PriestShadow)
{
if (target->GetEntry() == NPC_PRIEST_SHADOWFIEND)
{
// Note: divisor is 100 because effect value is 5 and its supposed to restore 0.5%
spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_MANA, GetCastDifficulty());
divisor = 10;
}
else
{
// Note: divisor is 100 because effect value is 20 and its supposed to restore 0.2%
spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_POWER_LEECH_MINDBENDER_MANA, GetCastDifficulty());
divisor = 100;
}
}
else
spellInfo = sSpellMgr->AssertSpellInfo(target->GetEntry() == NPC_PRIEST_SHADOWFIEND
? SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_INSANITY
: SPELL_PRIEST_POWER_LEECH_MINDBENDER_INSANITY, GetCastDifficulty());
target->CastSpell(summoner, spellInfo->Id, CastSpellExtraArgs(aurEff)
.AddSpellMod(SPELLVALUE_BASE_POINT0, spellInfo->GetEffect(EFFECT_0).CalcValue() / divisor));
// Note: Essence Devourer talent.
if (summoner->HasAura(SPELL_PRIEST_ESSENCE_DEVOURER))
summoner->CastSpell(nullptr, target->GetEntry() == NPC_PRIEST_SHADOWFIEND ? SPELL_PRIEST_ESSENCE_DEVOURER_SHADOWFIEND_HEAL : SPELL_PRIEST_ESSENCE_DEVOURER_MINDBENDER_HEAL, aurEff);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_power_leech_passive::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_power_leech_passive::HandleOnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 198069 - Power of the Dark Side
class spell_pri_power_of_the_dark_side : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_OF_THE_DARK_SIDE_TINT });
}
void HandleOnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
if (Unit* caster = GetCaster())
caster->CastSpell(caster, SPELL_PRIEST_POWER_OF_THE_DARK_SIDE_TINT, true);
}
void HandleOnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
if (Unit* caster = GetCaster())
caster->RemoveAura(SPELL_PRIEST_POWER_OF_THE_DARK_SIDE_TINT);
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_pri_power_of_the_dark_side::HandleOnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_pri_power_of_the_dark_side::HandleOnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 47666 - Penance (Damage)
// 373130 - Dark Reprimand (Damage)
class spell_pri_power_of_the_dark_side_damage_bonus : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_OF_THE_DARK_SIDE });
}
void CalculateDamageBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) const
{
if (AuraEffect* powerOfTheDarkSide = GetCaster()->GetAuraEffect(SPELL_PRIEST_POWER_OF_THE_DARK_SIDE, EFFECT_0))
AddPct(pctMod, powerOfTheDarkSide->GetAmount());
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_pri_power_of_the_dark_side_damage_bonus::CalculateDamageBonus);
}
};
// 47750 - Penance (Healing)
// 400187 - Dark Reprimand (Healing)
class spell_pri_power_of_the_dark_side_healing_bonus : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_OF_THE_DARK_SIDE });
}
void CalculateHealingBonus(SpellEffectInfo const& /*spellEffectInfo*/, Unit* /*victim*/, int32& /*healing*/, int32& /*flatMod*/, float& pctMod) const
{
if (AuraEffect* powerOfTheDarkSide = GetCaster()->GetAuraEffect(SPELL_PRIEST_POWER_OF_THE_DARK_SIDE, EFFECT_0))
AddPct(pctMod, powerOfTheDarkSide->GetAmount());
}
void Register() override
{
CalcHealing += SpellCalcHealingFn(spell_pri_power_of_the_dark_side_healing_bonus::CalculateHealingBonus);
}
};
// 194509 - Power Word: Radiance
class spell_pri_power_word_radiance : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ATONEMENT_EFFECT });
}
void FilterTargets(std::list& targets)
{
Unit* caster = GetCaster();
Unit* explTarget = GetExplTargetUnit();
// we must add one since explicit target is always chosen.
uint32 maxTargets = GetEffectInfo(EFFECT_2).CalcValue(caster) + 1;
Trinity::SortTargetsWithPriorityRules(targets, maxTargets, GetRadianceRules(caster, explTarget));
for (WorldObject const* target : targets)
{
if (target == explTarget)
continue;
_visualTargets.push_back(target->GetGUID());
}
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
for (ObjectGuid const& guid : _visualTargets)
if (Unit* target = ObjectAccessor::GetUnit(*GetHitUnit(), guid))
GetHitUnit()->SendPlaySpellVisual(target, SPELL_VISUAL_PRIEST_POWER_WORD_RADIANCE, 0, 0, 70.0f);
}
static std::array GetRadianceRules(Unit const* caster, Unit const* explTarget)
{
return
{
[explTarget](WorldObject const* target) { return target == explTarget; },
[caster](Unit const* target) { return !target->HasAura(SPELL_PRIEST_ATONEMENT_EFFECT, caster->GetGUID()); },
[](Unit const* target) { return !target->IsFullHealth(); },
[](WorldObject const* target) { return target->IsPlayer() || (target->IsCreature() && target->ToCreature()->IsTreatedAsRaidUnit()); },
[caster](Unit const* target) { return target->IsInRaidWith(caster); }
};
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_power_word_radiance::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ALLY);
OnEffectHitTarget += SpellEffectFn(spell_pri_power_word_radiance::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
std::vector _visualTargets;
};
// 17 - Power Word: Shield
class spell_pri_power_word_shield : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_STRENGTH_OF_SOUL,
SPELL_PRIEST_STRENGTH_OF_SOUL_EFFECT,
SPELL_PRIEST_ATONEMENT_EFFECT,
SPELL_PRIEST_TRINITY_EFFECT,
SPELL_PRIEST_SHIELD_DISCIPLINE,
SPELL_PRIEST_SHIELD_DISCIPLINE_EFFECT,
SPELL_PVP_RULES_ENABLED_HARDCODED
}) && ValidateSpellEffect({
{ SPELL_PRIEST_MASTERY_GRACE, EFFECT_0 },
{ SPELL_PRIEST_RAPTURE, EFFECT_1 },
{ SPELL_PRIEST_BENEVOLENCE, EFFECT_0 },
{ SPELL_PRIEST_DIVINE_AEGIS, EFFECT_1 }
});
}
void CalculateAmount(AuraEffect const* auraEffect, int32& amount, bool& canBeRecalculated) const
{
canBeRecalculated = false;
if (Unit* caster = GetCaster())
{
float modifiedAmount = caster->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()) * 3.36f;
if (Player* player = caster->ToPlayer())
{
AddPct(modifiedAmount, player->GetRatingBonusValue(CR_VERSATILITY_DAMAGE_DONE));
// Mastery: Grace (TBD: move into DoEffectCalcDamageAndHealing hook with a new SpellScript and AuraScript).
if (AuraEffect const* masteryGraceEffect = caster->GetAuraEffect(SPELL_PRIEST_MASTERY_GRACE, EFFECT_0))
if (GetUnitOwner()->HasAura(SPELL_PRIEST_ATONEMENT_EFFECT) || GetUnitOwner()->HasAura(SPELL_PRIEST_TRINITY_EFFECT))
AddPct(modifiedAmount, masteryGraceEffect->GetAmount());
switch (player->GetPrimarySpecialization())
{
case ChrSpecialization::PriestDiscipline:
modifiedAmount *= 1.37f;
break;
case ChrSpecialization::PriestShadow:
modifiedAmount *= 1.25f;
if (caster->HasAura(SPELL_PVP_RULES_ENABLED_HARDCODED))
modifiedAmount *= 0.8f;
break;
default:
break;
}
}
float critChanceDone = caster->SpellCritChanceDone(nullptr, auraEffect, GetSpellInfo()->GetSchoolMask(), GetSpellInfo()->GetAttackType());
float critChanceTaken = GetUnitOwner()->SpellCritChanceTaken(caster, nullptr, auraEffect, GetSpellInfo()->GetSchoolMask(), critChanceDone, GetSpellInfo()->GetAttackType());
if (roll_chance_f(critChanceTaken))
{
modifiedAmount *= 2;
// Divine Aegis
if (AuraEffect const* divineEff = caster->GetAuraEffect(SPELL_PRIEST_DIVINE_AEGIS, EFFECT_1))
AddPct(modifiedAmount, divineEff->GetAmount());
}
// Rapture talent (TBD: move into DoEffectCalcDamageAndHealing hook).
if (AuraEffect const* raptureEffect = caster->GetAuraEffect(SPELL_PRIEST_RAPTURE, EFFECT_1))
AddPct(modifiedAmount, raptureEffect->GetAmount());
// Benevolence talent
if (AuraEffect const* benevolenceEffect = caster->GetAuraEffect(SPELL_PRIEST_BENEVOLENCE, EFFECT_0))
AddPct(modifiedAmount, benevolenceEffect->GetAmount());
amount = modifiedAmount;
}
}
void HandleOnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
Unit* caster = GetCaster();
if (!caster)
return;
// Note: Strength of Soul PvP talent.
if (caster->HasAura(SPELL_PRIEST_STRENGTH_OF_SOUL))
caster->CastSpell(GetTarget(), SPELL_PRIEST_STRENGTH_OF_SOUL_EFFECT, aurEff);
}
void HandleOnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
GetTarget()->RemoveAura(SPELL_PRIEST_STRENGTH_OF_SOUL_EFFECT);
// Note: Shield Discipline talent.
if (Unit* caster = GetCaster())
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && caster->HasAura(SPELL_PRIEST_SHIELD_DISCIPLINE))
caster->CastSpell(caster, SPELL_PRIEST_SHIELD_DISCIPLINE_EFFECT, aurEff);
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_power_word_shield::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
AfterEffectApply += AuraEffectApplyFn(spell_pri_power_word_shield::HandleOnApply, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
AfterEffectRemove += AuraEffectRemoveFn(spell_pri_power_word_shield::HandleOnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
}
};
// 47515 - Divine Aegis
class spell_pri_divine_aegis : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_DIVINE_AEGIS_ABSORB, EFFECT_0 } });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return eventInfo.GetHealInfo() != nullptr;
}
static void HandleProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
Unit* caster = eventInfo.GetActor();
if (!caster)
return;
int32 aegisAmount = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount());
CastSpellExtraArgs args(aurEff);
args.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aegisAmount);
caster->CastSpell(eventInfo.GetProcTarget(), SPELL_PRIEST_DIVINE_AEGIS_ABSORB, args);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_divine_aegis::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 129250 - Power Word: Solace
class spell_pri_power_word_solace : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_WORD_SOLACE_ENERGIZE });
}
void RestoreMana(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_POWER_WORD_SOLACE_ENERGIZE,
CastSpellExtraArgs(TRIGGERED_IGNORE_CAST_IN_PROGRESS).SetTriggeringSpell(GetSpell())
.AddSpellMod(SPELLVALUE_BASE_POINT0, GetEffectValue() / 100));
}
void Register() override
{
OnEffectLaunch += SpellEffectFn(spell_pri_power_word_solace::RestoreMana, EFFECT_1, SPELL_EFFECT_DUMMY);
}
};
// Base class used by various Prayer of Mending spells
class spell_pri_prayer_of_mending_SpellScriptBase : public SpellScript
{
public:
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, SPELL_PRIEST_PRAYER_OF_MENDING_AURA })
&& ValidateSpellEffect({ { SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, EFFECT_0 } });
}
bool Load() override
{
_spellInfoHeal = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, DIFFICULTY_NONE);
return true;
}
void CastPrayerOfMendingAura(Unit* caster, Unit* target, Unit* visualSender, uint8 stack, bool firstCast) const
{
CastSpellExtraArgs args;
args.TriggerFlags = TRIGGERED_FULL_MASK;
args.AddSpellMod(SPELLVALUE_AURA_STACK, stack);
// Note: this line's purpose is to show the correct amount in Points field in SMSG_AURA_UPDATE.
SpellEffectInfo const* healEffectDummy = &_spellInfoHeal->GetEffect(EFFECT_0);
uint32 basePoints = caster->SpellHealingBonusDone(target, _spellInfoHeal, healEffectDummy->CalcValue(caster), HEAL, *healEffectDummy);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, basePoints);
// Note: Focused Mending talent.
args.SetCustomArg(firstCast);
caster->CastSpell(target, SPELL_PRIEST_PRAYER_OF_MENDING_AURA, args);
// Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers.
visualSender->SendPlaySpellVisual(target, SPELL_VISUAL_PRIEST_PRAYER_OF_MENDING, 0, 0, 40.0f);
}
protected:
SpellInfo const* _spellInfoHeal = nullptr;
};
// 33076 - Prayer of Mending (Dummy)
class spell_pri_prayer_of_mending_dummy : public spell_pri_prayer_of_mending_SpellScriptBase
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_PRAYER_OF_MENDING_AURA,
SPELL_PRIEST_EPIPHANY,
SPELL_PRIEST_EPIPHANY_HIGHLIGHT
});
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
// Note: we need to increase BasePoints by 1 since it's 4 as default. Also HACKFIX, we shouldn't reduce it by 1 if the target has the aura already.
uint8 stackAmount = target->HasAura(SPELL_PRIEST_PRAYER_OF_MENDING_AURA, caster->GetGUID()) ? GetEffectValue() : GetEffectValue() + 1;
CastPrayerOfMendingAura(caster, target, caster, stackAmount, true);
// Note: Epiphany talent.
if (caster->HasAura(SPELL_PRIEST_EPIPHANY))
caster->RemoveAurasDueToSpell(SPELL_PRIEST_EPIPHANY_HIGHLIGHT);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_dummy::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 41635 - Prayer of Mending (Aura)
class spell_pri_prayer_of_mending_aura : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, SPELL_PRIEST_PRAYER_OF_MENDING_JUMP })
&& ValidateSpellEffect({ { SPELL_PRIEST_SAY_YOUR_PRAYERS, EFFECT_0 } });
}
void HandleHeal(AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/)
{
// Note: caster is the priest who cast the spell and target is current holder of the aura.
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
{
CastSpellExtraArgs args(aurEff);
args.SetCustomArg(_isEmpoweredByFocusedMending);
caster->CastSpell(target, SPELL_PRIEST_PRAYER_OF_MENDING_HEAL, args);
// Note: jump is only executed if higher than 1 stack.
int32 stackAmount = GetStackAmount();
if (stackAmount > 1)
{
args.OriginalCaster = caster->GetGUID();
int32 newStackAmount = stackAmount - 1;
if (AuraEffect* sayYourPrayers = caster->GetAuraEffect(SPELL_PRIEST_SAY_YOUR_PRAYERS, EFFECT_0))
if (roll_chance_i(sayYourPrayers->GetAmount()))
++newStackAmount;
args.AddSpellMod(SPELLVALUE_BASE_POINT0, newStackAmount);
target->CastSpell(target, SPELL_PRIEST_PRAYER_OF_MENDING_JUMP, args);
}
Remove();
}
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_prayer_of_mending_aura::HandleHeal, EFFECT_0, SPELL_AURA_DUMMY);
}
public:
void SetEmpoweredByFocusedMending(bool isEmpowered)
{
_isEmpoweredByFocusedMending = isEmpowered;
}
private:
bool _isEmpoweredByFocusedMending = false;
};
class spell_pri_prayer_of_mending : public SpellScript
{
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
Aura* aura = GetHitAura();
if (!aura)
return;
spell_pri_prayer_of_mending_aura* script = aura->GetScript();
if (!script)
return;
if (bool const* isEmpoweredByFocusedMending = std::any_cast(&GetSpell()->m_customArg))
script->SetEmpoweredByFocusedMending(isEmpoweredByFocusedMending);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
// 155793 - Prayer of Mending (Jump)
class spell_pri_prayer_of_mending_jump : public spell_pri_prayer_of_mending_SpellScriptBase
{
static void FilterTargets(SpellScript const&, std::list& targets)
{
Trinity::SelectRandomInjuredTargets(targets, 1, true);
}
void HandleJump(SpellEffIndex /*effIndex*/) const
{
if (Unit* origCaster = GetOriginalCaster())
CastPrayerOfMendingAura(origCaster, GetHitUnit(), GetCaster(), GetEffectValue(), false);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_prayer_of_mending_jump::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_jump::HandleJump, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 193063 - Protective Light (Aura)
class spell_pri_protective_light : public AuraScript
{
bool CheckEffectProc(AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo) const
{
return eventInfo.GetProcTarget() == GetCaster();
}
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) const
{
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_PROTECTIVE_LIGHT_AURA, aurEff);
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_protective_light::CheckEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_pri_protective_light::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 405554 - Priest Holy 10.1 Class Set 2pc
class spell_pri_holy_10_1_class_set_2pc : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_HOLY_10_1_CLASS_SET_2P_CHOOSER })
&& ValidateSpellEffect({ { SPELL_PRIEST_PRAYER_OF_MENDING, EFFECT_0 } });
}
static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
return roll_chance_i(aurEff->GetAmount());
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const
{
CastSpellExtraArgs args(aurEff);
args.SetTriggeringSpell(eventInfo.GetProcSpell());
args.AddSpellMod(SPELLVALUE_BASE_POINT0, sSpellMgr->AssertSpellInfo(SPELL_PRIEST_PRAYER_OF_MENDING, GetCastDifficulty())->GetEffect(EFFECT_0).CalcValue(GetCaster()));
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_HOLY_10_1_CLASS_SET_2P_CHOOSER, args);
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_holy_10_1_class_set_2pc::CheckProc, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_pri_holy_10_1_class_set_2pc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 411097 - Priest Holy 10.1 Class Set 2pc (Chooser)
class spell_pri_holy_10_1_class_set_2pc_chooser : public spell_pri_prayer_of_mending_SpellScriptBase
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PRAYER_OF_MENDING_AURA });
}
static void FilterTargets(SpellScript const&, std::list& targets)
{
Trinity::SelectRandomInjuredTargets(targets, 1, true);
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
// Note: we need to increase BasePoints by 1 since it's 4 as default. Also HACKFIX, we shouldn't reduce it by 1 if the target has the aura already.
uint8 stackAmount = target->HasAura(SPELL_PRIEST_PRAYER_OF_MENDING_AURA, caster->GetGUID()) ? GetEffectValue() : GetEffectValue() + 1;
CastPrayerOfMendingAura(caster, target, caster, stackAmount, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_holy_10_1_class_set_2pc_chooser::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_pri_holy_10_1_class_set_2pc_chooser::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 155793 - Prayer of Mending (Jump)
class spell_pri_holy_10_1_class_set_4pc : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P, SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P_EFFECT });
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/) const
{
if (GetOriginalCaster()->HasAura(SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P))
GetOriginalCaster()->CastSpell(GetOriginalCaster(), SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P_EFFECT, TRIGGERED_IGNORE_GCD);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_holy_10_1_class_set_4pc::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 41635 - Prayer of Mending (Aura)
class spell_pri_holy_10_1_class_set_4pc_aura : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P, SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P_EFFECT });
}
void HandleOnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) const
{
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
return;
if (GetCaster()->HasAura(SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P))
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_HOLY_10_1_CLASS_SET_4P_EFFECT, CastSpellExtraArgs(TRIGGERED_IGNORE_GCD).SetTriggeringAura(aurEff));
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_pri_holy_10_1_class_set_4pc_aura::HandleOnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 17 - Power Word: Shield
class spell_pri_assured_safety : public spell_pri_prayer_of_mending_SpellScriptBase
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellEffect({ { SPELL_PRIEST_ASSURED_SAFETY, EFFECT_0 } });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_PRIEST_ASSURED_SAFETY);
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
if (AuraEffect const* effect = caster->GetAuraEffect(SPELL_PRIEST_ASSURED_SAFETY, EFFECT_0))
CastPrayerOfMendingAura(caster, GetHitUnit(), caster, effect->GetAmount(), false);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_assured_safety::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
// 204197 - Purge the Wicked
// Called by Penance - 47540, Dark Reprimand - 400169
class spell_pri_purge_the_wicked : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC,
SPELL_PRIEST_PURGE_THE_WICKED_DUMMY
});
}
void HandleDummy(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
if (target->HasAura(SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, caster->GetGUID()))
caster->CastSpell(target, SPELL_PRIEST_PURGE_THE_WICKED_DUMMY, TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_purge_the_wicked::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 204215 - Purge the Wicked
class spell_pri_purge_the_wicked_dummy : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, SPELL_PRIEST_REVEL_IN_PURITY })
&& ValidateSpellEffect({ { SPELL_PRIEST_REVEL_IN_PURITY, EFFECT_1 } });
}
void FilterTargets(std::list& targets) const
{
Unit* caster = GetCaster();
Unit* explTarget = GetExplTargetUnit();
targets.remove_if([&](WorldObject* object) -> bool
{
// Note: we must remove any non-unit target, the explicit target and any other target that may be under any crowd control aura.
Unit* target = object->ToUnit();
return !target || target == explTarget || target->HasBreakableByDamageCrowdControlAura();
});
if (targets.empty())
return;
// Note: there's no SPELL_EFFECT_DUMMY with BasePoints 1 in any of the spells related to use as reference so we hardcode the value.
uint32 spreadCount = 1;
// Note: we must sort our list of targets whose priority is 1) aura, 2) distance, and 3) duration.
targets.sort([&](WorldObject const* lhs, WorldObject const* rhs) -> bool
{
Unit const* targetA = lhs->ToUnit();
Unit const* targetB = rhs->ToUnit();
Aura* auraA = targetA->GetAura(SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, caster->GetGUID());
Aura* auraB = targetB->GetAura(SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, caster->GetGUID());
if (!auraA)
{
if (auraB)
return true;
return explTarget->GetExactDist(targetA) < explTarget->GetExactDist(targetB);
}
if (!auraB)
return false;
return auraA->GetDuration() < auraB->GetDuration();
});
// Note: Revel in Purity talent.
if (caster->HasAura(SPELL_PRIEST_REVEL_IN_PURITY))
spreadCount += sSpellMgr->AssertSpellInfo(SPELL_PRIEST_REVEL_IN_PURITY, DIFFICULTY_NONE)->GetEffect(EFFECT_1).CalcValue(GetCaster());
if (targets.size() > spreadCount)
targets.resize(spreadCount);
}
void HandleDummy(SpellEffIndex /*effIndex*/) const
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
caster->CastSpell(target, SPELL_PRIEST_PURGE_THE_WICKED_PERIODIC, TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_purge_the_wicked_dummy::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_pri_purge_the_wicked_dummy::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY);
}
};
// 390622 - Rhapsody
class spell_pri_rhapsody : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_RHAPSODY_PROC });
}
void HandlePeriodic(AuraEffect const* aurEff) const
{
Unit* target = GetTarget();
if (Aura* rhapsodyStack = target->GetAura(SPELL_PRIEST_RHAPSODY_PROC, GetCasterGUID()))
rhapsodyStack->ModStackAmount(1);
else
target->CastSpell(target, SPELL_PRIEST_RHAPSODY_PROC,
CastSpellExtraArgs(aurEff).SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR));
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_pri_rhapsody::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 390636 - Rhapsody
class spell_pri_rhapsody_proc : public AuraScript
{
void PreventChargeDrop(ProcEventInfo const& /*eventInfo*/)
{
PreventDefaultAction();
}
void RemoveAura(ProcEventInfo const& /*eventInfo*/) const
{
// delay charge drop to allow spellmod to be applied to both damaging and healing spells
GetAura()->DropChargeDelayed(1);
}
void Register() override
{
DoPrepareProc += AuraProcFn(spell_pri_rhapsody_proc::PreventChargeDrop);
AfterProc += AuraProcFn(spell_pri_rhapsody_proc::RemoveAura);
}
};
// 47536 - Rapture
class spell_pri_rapture : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_POWER_WORD_SHIELD });
}
void HandleEffectDummy(SpellEffIndex /*effIndex*/)
{
_raptureTarget = GetHitUnit()->GetGUID();
}
void HandleAfterCast() const
{
Unit* caster = GetCaster();
if (Unit* target = ObjectAccessor::GetUnit(*caster, _raptureTarget))
caster->CastSpell(target, SPELL_PRIEST_POWER_WORD_SHIELD,
CastSpellExtraArgs(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_CAST_IN_PROGRESS)
.SetTriggeringSpell(GetSpell()));
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_rapture::HandleEffectDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
AfterCast += SpellCastFn(spell_pri_rapture::HandleAfterCast);
}
private:
ObjectGuid _raptureTarget;
};
// 8092 - Mind Blast
class spell_pri_schism : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_SCHISM,
SPELL_PRIEST_SCHISM_AURA
});
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
if (GetCaster()->HasAura(SPELL_PRIEST_SCHISM))
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_SCHISM_AURA, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_schism::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 208771 - Sanctuary (Absorb)
class spell_pri_sanctuary_absorb : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SANCTUARY_AURA });
}
void CalcAbsorbAmount(AuraEffect const* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
{
PreventDefaultAction();
Unit const* attacker = dmgInfo.GetAttacker();
if (!attacker)
return;
AuraEffect* amountHolderEffect = attacker->GetAuraEffect(SPELL_PRIEST_SANCTUARY_AURA, EFFECT_0, GetCasterGUID());
if (!amountHolderEffect)
return;
if (dmgInfo.GetDamage() >= uint32(amountHolderEffect->GetAmount()))
{
amountHolderEffect->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
dmgInfo.AbsorbDamage(amountHolderEffect->GetAmount());
}
else
{
amountHolderEffect->ChangeAmount(amountHolderEffect->GetAmount() - int32(dmgInfo.GetDamage()));
dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
}
}
void Register() override
{
OnEffectAbsorb += AuraEffectAbsorbFn(spell_pri_sanctuary_absorb::CalcAbsorbAmount, EFFECT_0);
}
};
// Smite - 585
class spell_pri_sanctuary_trigger : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SANCTUARY, SPELL_PRIEST_SANCTUARY_AURA, SPELL_PRIEST_SANCTUARY_ABSORB });
}
void HandleEffectHit(SpellEffIndex /*effIndex*/) const
{
Player* caster = Object::ToPlayer(GetCaster());
if (!caster)
return;
if (AuraEffect const* sanctuaryEffect = caster->GetAuraEffect(SPELL_PRIEST_SANCTUARY, EFFECT_0))
{
if (Unit* target = GetHitUnit())
{
float absorbAmount = CalculatePct(caster->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW), sanctuaryEffect->GetAmount());
AddPct(absorbAmount, caster->GetRatingBonusValue(CR_VERSATILITY_DAMAGE_DONE));
caster->CastSpell(caster, SPELL_PRIEST_SANCTUARY_ABSORB, CastSpellExtraArgs()
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR)
.SetTriggeringSpell(GetSpell()));
caster->CastSpell(target, SPELL_PRIEST_SANCTUARY_AURA, CastSpellExtraArgs()
.AddSpellMod(SPELLVALUE_BASE_POINT0, absorbAmount)
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR)
.SetTriggeringSpell(GetSpell()));
}
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_pri_sanctuary_trigger::HandleEffectHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// 280391 - Sins of the Many
class spell_pri_sins_of_the_many : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SINS_OF_THE_MANY });
}
void HandleOnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_SINS_OF_THE_MANY, true);
}
void HandleOnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
GetTarget()->RemoveAura(SPELL_PRIEST_SINS_OF_THE_MANY);
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_pri_sins_of_the_many::HandleOnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_pri_sins_of_the_many::HandleOnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 20711 - Spirit of Redemption
class spell_pri_spirit_of_redemption : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SPIRIT_OF_REDEMPTION });
}
void HandleAbsorb(AuraEffect const* aurEff, DamageInfo const& /*dmgInfo*/, uint32 const& /*absorbAmount*/) const
{
Unit* target = GetTarget();
target->CastSpell(target, SPELL_PRIEST_SPIRIT_OF_REDEMPTION, aurEff);
target->SetFullHealth();
}
void Register() override
{
OnEffectAbsorb += AuraEffectAbsorbOverkillFn(spell_pri_spirit_of_redemption::HandleAbsorb, EFFECT_0);
}
};
// 34433 - Shadowfiend
// 123040 - Mindbender (Discipline)
// 451235 - Voidwrath
class spell_pri_shadow_covenant : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SHADOW_COVENANT, SPELL_PRIEST_SHADOW_COVENANT_EFFECT });
}
bool Load() override
{
return GetCaster()->HasAura(SPELL_PRIEST_SHADOW_COVENANT);
}
void HandleAfterCast() const
{
GetCaster()->CastSpell(GetCaster(), SPELL_PRIEST_SHADOW_COVENANT_EFFECT, CastSpellExtraArgsInit{
.TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR,
.TriggeringSpell = GetSpell()
});
}
void Register() override
{
AfterCast += SpellCastFn(spell_pri_shadow_covenant::HandleAfterCast);
}
};
// 186263 - Shadow Mend
class spell_pri_shadow_mend : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_ATONEMENT,
SPELL_PRIEST_ATONEMENT_EFFECT,
SPELL_PRIEST_TRINITY,
SPELL_PRIEST_MASOCHISM_TALENT,
SPELL_PRIEST_MASOCHISM_PERIODIC_HEAL,
SPELL_PRIEST_SHADOW_MEND_PERIODIC_DUMMY
});
}
void HandleEffectHit() const
{
if (Unit* target = GetHitUnit())
{
Unit* caster = GetCaster();
int32 periodicAmount = GetHitHeal() / 20;
int32 damageForAuraRemoveAmount = periodicAmount * 10;
// Handle Masochism talent
if (caster->HasAura(SPELL_PRIEST_MASOCHISM_TALENT) && caster->GetGUID() == target->GetGUID())
caster->CastSpell(caster, SPELL_PRIEST_MASOCHISM_PERIODIC_HEAL, CastSpellExtraArgs(GetSpell()).AddSpellMod(SPELLVALUE_BASE_POINT0, periodicAmount));
else if (target->IsInCombat() && periodicAmount)
{
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.SetTriggeringSpell(GetSpell());
args.AddSpellMod(SPELLVALUE_BASE_POINT0, periodicAmount);
args.AddSpellMod(SPELLVALUE_BASE_POINT1, damageForAuraRemoveAmount);
caster->CastSpell(target, SPELL_PRIEST_SHADOW_MEND_PERIODIC_DUMMY, args);
}
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_pri_shadow_mend::HandleEffectHit);
}
};
// 187464 - Shadow Mend (Damage)
class spell_pri_shadow_mend_periodic_damage : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SHADOW_MEND_DAMAGE });
}
void HandleDummyTick(AuraEffect const* aurEff) const
{
CastSpellExtraArgs args(TRIGGERED_FULL_MASK);
args.SetOriginalCaster(GetCasterGUID());
args.SetTriggeringAura(aurEff);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount());
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_SHADOW_MEND_DAMAGE, args);
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
return eventInfo.GetDamageInfo() != nullptr;
}
void HandleProc(AuraEffect* aurEff, ProcEventInfo const& eventInfo)
{
int32 newAmount = aurEff->GetAmount() - eventInfo.GetDamageInfo()->GetDamage();
aurEff->ChangeAmount(newAmount);
if (newAmount < 0)
Remove();
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_pri_shadow_mend_periodic_damage::HandleDummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
DoCheckProc += AuraCheckProcFn(spell_pri_shadow_mend_periodic_damage::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_shadow_mend_periodic_damage::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// 32379 - Shadow Word: Death
class spell_pri_shadow_word_death : public SpellScript
{
static constexpr Seconds BACKLASH_DELAY = 1s;
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SHADOW_WORD_DEATH_DAMAGE })
&& ValidateSpellEffect({ { spellInfo->Id, EFFECT_5 } })
&& spellInfo->GetEffect(EFFECT_2).IsEffect(SPELL_EFFECT_DUMMY)
&& spellInfo->GetEffect(EFFECT_3).IsEffect(SPELL_EFFECT_SCRIPT_EFFECT)
&& spellInfo->GetEffect(EFFECT_5).IsEffect(SPELL_EFFECT_DUMMY);
}
void HandleDamageCalculation(SpellEffectInfo const& /*spellEffectInfo*/, Unit const* victim, int32 const& /*damage*/, int32 const& /*flatMod*/, float& pctMod) const
{
if (victim->HealthBelowPct(GetEffectInfo(EFFECT_2).CalcValue(GetCaster())))
AddPct(pctMod, GetEffectInfo(EFFECT_3).CalcValue(GetCaster()));
}
void DetermineKillStatus(DamageInfo const& damageInfo, uint32& /*resistAmount*/, int32& /*absorbAmount*/) const
{
bool killed = damageInfo.GetDamage() >= damageInfo.GetVictim()->GetHealth();
if (!killed)
{
Unit* caster = GetCaster();
int32 backlashDamage = caster->CountPctFromMaxHealth(GetEffectInfo(EFFECT_5).CalcValue(caster));
caster->m_Events.AddEventAtOffset([caster, originalCastId = GetSpell()->m_castId, backlashDamage]
{
caster->CastSpell(caster, SPELL_PRIEST_SHADOW_WORD_DEATH_DAMAGE, CastSpellExtraArgs()
.SetTriggerFlags(TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR)
.SetOriginalCastId(originalCastId)
.AddSpellMod(SPELLVALUE_BASE_POINT0, backlashDamage));
}, BACKLASH_DELAY);
}
}
void Register() override
{
CalcDamage += SpellCalcDamageFn(spell_pri_shadow_word_death::HandleDamageCalculation);
// abuse OnCalculateResistAbsorb to determine if this spell will kill target or not (its still not perfect - happens before absorbs are applied)
OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(spell_pri_shadow_word_death::DetermineKillStatus);
}
};
// 109186 - Surge of Light
class spell_pri_surge_of_light : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_SMITE,
SPELL_PRIEST_SURGE_OF_LIGHT_EFFECT
});
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
if (eventInfo.GetSpellInfo()->Id == SPELL_PRIEST_SMITE)
return true;
if (eventInfo.GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST)
return eventInfo.GetHealInfo();
return false;
}
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) const
{
if (roll_chance_i(aurEff->GetAmount()))
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_SURGE_OF_LIGHT_EFFECT, aurEff);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_surge_of_light::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_surge_of_light::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 28809 - Greater Heal
class spell_pri_t3_4p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ARMOR_OF_FAITH });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
PreventDefaultAction();
eventInfo.GetActor()->CastSpell(eventInfo.GetProcTarget(), SPELL_PRIEST_ARMOR_OF_FAITH, aurEff);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_t3_4p_bonus::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 37594 - Greater Heal Refund
class spell_pri_t5_heal_2p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_ITEM_EFFICIENCY });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
if (HealInfo* healInfo = eventInfo.GetHealInfo())
if (Unit* healTarget = healInfo->GetTarget())
if (healInfo->GetEffectiveHeal())
if (healTarget->GetHealth() >= healTarget->GetMaxHealth())
return true;
return false;
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetTarget()->CastSpell(GetTarget(), SPELL_PRIEST_ITEM_EFFICIENCY, aurEff);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_t5_heal_2p_bonus::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_t5_heal_2p_bonus::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 70770 - Item - Priest T10 Healer 2P Bonus
class spell_pri_t10_heal_2p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_BLESSED_HEALING });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
PreventDefaultAction();
HealInfo* healInfo = eventInfo.GetHealInfo();
if (!healInfo || !healInfo->GetHeal())
return;
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_BLESSED_HEALING, GetCastDifficulty());
int32 amount = CalculatePct(static_cast(healInfo->GetHeal()), aurEff->GetAmount());
ASSERT(spellInfo->GetMaxTicks() > 0);
amount /= spellInfo->GetMaxTicks();
Unit* caster = eventInfo.GetActor();
Unit* target = eventInfo.GetProcTarget();
CastSpellExtraArgs args(aurEff);
args.AddSpellBP0(amount);
caster->CastSpell(target, SPELL_PRIEST_BLESSED_HEALING, args);
}
void Register() override
{
OnEffectProc += AuraEffectProcFn(spell_pri_t10_heal_2p_bonus::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 200128 - Trail of Light
class spell_pri_trail_of_light : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_TRAIL_OF_LIGHT_HEAL });
}
bool CheckProc(ProcEventInfo const& eventInfo)
{
if (_healQueue.empty() || _healQueue.back() != eventInfo.GetActionTarget()->GetGUID())
_healQueue.push(eventInfo.GetActionTarget()->GetGUID());
if (_healQueue.size() > 2)
_healQueue.pop();
if (_healQueue.size() == 2)
return true;
return false;
}
void HandleOnProc(AuraEffect* aurEff, ProcEventInfo const& eventInfo) const
{
Unit* caster = GetTarget();
Unit* oldTarget = ObjectAccessor::GetUnit(*caster, _healQueue.front());
if (!oldTarget)
return;
// Note: old target may not be friendly anymore due to charm and faction change effects.
if (!caster->IsValidAssistTarget(oldTarget))
return;
SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_TRAIL_OF_LIGHT_HEAL, DIFFICULTY_NONE);
if (!healSpellInfo)
return;
// Note: distance may be greater than the heal's spell range.
if (!caster->IsWithinDist(oldTarget, healSpellInfo->GetMaxRange(true, caster)))
return;
uint32 healAmount = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount());
caster->CastSpell(oldTarget, SPELL_PRIEST_TRAIL_OF_LIGHT_HEAL, CastSpellExtraArgs(aurEff).AddSpellBP0(healAmount));
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_trail_of_light::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_trail_of_light::HandleOnProc, EFFECT_0, SPELL_AURA_DUMMY);
}
private:
std::queue _healQueue;
};
// 390693 - Train of Thought
// Called by Flash Heal, Renew, Smite
class spell_pri_train_of_thought : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo
({
SPELL_PRIEST_POWER_WORD_SHIELD,
SPELL_PRIEST_PENANCE
});
}
static bool CheckEffect0(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo)
{
// Renew & Flash Heal
return eventInfo.GetSpellInfo()->IsAffected(SPELLFAMILY_PRIEST, { 0x840 });
}
static bool CheckEffect1(AuraScript const&, AuraEffect const* /*aurEff*/, ProcEventInfo const& eventInfo)
{
// Smite
return eventInfo.GetSpellInfo()->IsAffected(SPELLFAMILY_PRIEST, { 0x80 });
}
void ReducePowerWordShieldCooldown(AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/) const
{
GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PRIEST_POWER_WORD_SHIELD, Milliseconds(aurEff->GetAmount()));
}
void ReducePenanceCooldown(AuraEffect const* aurEff, ProcEventInfo const& /*eventInfo*/) const
{
GetTarget()->GetSpellHistory()->ModifyCooldown(SPELL_PRIEST_PENANCE, Milliseconds(aurEff->GetAmount()));
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_train_of_thought::CheckEffect0, EFFECT_0, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_pri_train_of_thought::ReducePowerWordShieldCooldown, EFFECT_0, SPELL_AURA_DUMMY);
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_train_of_thought::CheckEffect1, EFFECT_1, SPELL_AURA_DUMMY);
OnEffectProc += AuraEffectProcFn(spell_pri_train_of_thought::ReducePenanceCooldown, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// 109142 - Twist of Fate (Shadow)
// 265259 - Twist of Fate (Discipline)
class spell_pri_twist_of_fate : public AuraScript
{
static bool CheckProc(AuraScript const&, AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
return eventInfo.GetProcTarget()->GetHealthPct() < aurEff->GetAmount();
}
void Register() override
{
DoCheckEffectProc += AuraCheckEffectProcFn(spell_pri_twist_of_fate::CheckProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 341273 - Unfurling Darkness
// Triggered by 34914 - Vampiric Touch
class spell_pri_unfurling_darkness : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_UNFURLING_DARKNESS, SPELL_PRIEST_UNFURLING_DARKNESS_DEBUFF })
&& ValidateSpellEffect({ { SPELL_PRIEST_UNFURLING_DARKNESS_AURA, EFFECT_0 } });
}
void PreventDirectDamage(WorldObject*& target) const
{
bool canTriggerDirectDamage = [&]
{
if (!GetSpell()->m_originalCastId.IsEmpty())
return false; // not when triggered by Shadow Crash (Whispering Shadows talent)
if (AuraEffect const* unfurlingDarkness = GetCaster()->GetAuraEffect(SPELL_PRIEST_UNFURLING_DARKNESS_AURA, EFFECT_0))
if (GetSpell()->m_appliedMods.contains(unfurlingDarkness->GetBase()))
return true;
return false;
}();
if (!canTriggerDirectDamage)
target = nullptr;
}
void TriggerUnfurlingDarkness() const
{
if (!GetSpell()->m_originalCastId.IsEmpty())
return; // not when triggered by Shadow Crash (Whispering Shadows talent)
Unit* caster = GetCaster();
if (AuraEffect const* unfurlingDarkness = GetCaster()->GetAuraEffect(SPELL_PRIEST_UNFURLING_DARKNESS_AURA, EFFECT_0))
{
if (GetSpell()->m_appliedMods.contains(unfurlingDarkness->GetBase()))
{
unfurlingDarkness->GetBase()->Remove();
return;
}
}
if (!caster->HasAura(SPELL_PRIEST_UNFURLING_DARKNESS_DEBUFF))
caster->CastSpell(caster, SPELL_PRIEST_UNFURLING_DARKNESS_AURA, true);
}
void Register() override
{
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_pri_unfurling_darkness::PreventDirectDamage, EFFECT_3, TARGET_UNIT_TARGET_ENEMY);
AfterCast += SpellCastFn(spell_pri_unfurling_darkness::TriggerUnfurlingDarkness);
}
};
// 15286 - Vampiric Embrace
class spell_pri_vampiric_embrace : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_VAMPIRIC_EMBRACE_HEAL });
}
static bool CheckProc(AuraScript const&, ProcEventInfo const& eventInfo)
{
// Not proc from Mind Sear
return !(eventInfo.GetDamageInfo()->GetSpellInfo()->SpellFamilyFlags[1] & 0x80000);
}
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo)
{
PreventDefaultAction();
DamageInfo* damageInfo = eventInfo.GetDamageInfo();
if (!damageInfo || !damageInfo->GetDamage())
return;
int32 selfHeal = int32(CalculatePct(damageInfo->GetDamage(), aurEff->GetAmount()));
int32 teamHeal = selfHeal / 2;
CastSpellExtraArgs args(aurEff);
args.AddSpellMod(SPELLVALUE_BASE_POINT0, teamHeal);
args.AddSpellMod(SPELLVALUE_BASE_POINT1, selfHeal);
GetTarget()->CastSpell(nullptr, SPELL_PRIEST_VAMPIRIC_EMBRACE_HEAL, args);
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_pri_vampiric_embrace::CheckProc);
OnEffectProc += AuraEffectProcFn(spell_pri_vampiric_embrace::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 15290 - Vampiric Embrace (heal)
class spell_pri_vampiric_embrace_target : public SpellScript
{
void FilterTargets(std::list& unitList) const
{
unitList.remove(GetCaster());
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_vampiric_embrace_target::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY);
}
};
// 34914 - Vampiric Touch
class spell_pri_vampiric_touch : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_SIN_AND_PUNISHMENT, SPELL_PRIEST_SHADOW_WORD_PAIN });
}
void HandleDispel(DispelInfo const* dispelInfo) const
{
if (Unit* caster = GetCaster())
caster->CastSpell(dispelInfo->GetDispeller(), SPELL_PRIEST_SIN_AND_PUNISHMENT, true);
}
void HandleApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
if (Unit* caster = GetCaster())
if (caster->HasAura(SPELL_PRIEST_MISERY))
caster->CastSpell(GetTarget(), SPELL_PRIEST_SHADOW_WORD_PAIN, true);
}
void Register() override
{
AfterDispel += AuraDispelFn(spell_pri_vampiric_touch::HandleDispel);
OnEffectApply += AuraEffectApplyFn(spell_pri_vampiric_touch::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
// 205385 - Shadow Crash
class spell_pri_whispering_shadows : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_WHISPERING_SHADOWS });
}
void HandleEffectHitTarget(SpellEffIndex effIndex)
{
if (!GetCaster()->HasAura(SPELL_PRIEST_WHISPERING_SHADOWS))
PreventHitDefaultEffect(effIndex);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_pri_whispering_shadows::HandleEffectHitTarget, EFFECT_2, SPELL_EFFECT_TRIGGER_MISSILE);
}
};
// 391286 - Whispering Shadows (Dot Application)
class spell_pri_whispering_shadows_effect : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_PRIEST_VAMPIRIC_TOUCH });
}
void FilterTargets(std::list& targets) const
{
if (targets.size() <= GetSpellValue()->MaxAffectedTargets)
return;
auto getVampiricTouch = [&](WorldObject const* target)
{
return target->ToUnit()->GetAura(SPELL_PRIEST_VAMPIRIC_TOUCH, GetCaster()->GetGUID());
};
// prioritize targets without Vampiric Touch
targets.sort([&](WorldObject const* target1, WorldObject const* target2)
{
int32 duration1 = 0;
if (Aura const* aura1 = getVampiricTouch(target1))
duration1 = aura1->GetDuration();
int32 duration2 = 0;
if (Aura const* aura2 = getVampiricTouch(target2))
duration2 = aura2->GetDuration();
return duration1 < duration2;
});
// remove targets that definitely will not get Vampiric Touch applied (excess targets with longest remaining duration)
while (targets.size() > GetSpellValue()->MaxAffectedTargets && getVampiricTouch(targets.back()) != nullptr)
targets.pop_back();
Trinity::Containers::RandomResize(targets, GetSpellValue()->MaxAffectedTargets);
}
void HandleEffectHitTarget(SpellEffIndex /*effIndex*/) const
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_PRIEST_VAMPIRIC_TOUCH, CastSpellExtraArgs()
.SetTriggeringSpell(GetSpell())
.SetTriggerFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD | TRIGGERED_IGNORE_POWER_COST | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_IGNORE_CAST_TIME | TRIGGERED_DONT_REPORT_CAST_ERROR));
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_whispering_shadows_effect::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_pri_whispering_shadows_effect::HandleEffectHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
void AddSC_priest_spell_scripts()
{
RegisterSpellScript(spell_pri_angelic_feather_trigger);
RegisterAreaTriggerAI(areatrigger_pri_angelic_feather);
RegisterSpellScript(spell_pri_abyssal_reverie);
RegisterSpellScript(spell_pri_answered_prayers);
RegisterSpellScript(spell_pri_aq_3p_bonus);
RegisterSpellScript(spell_pri_assured_safety);
RegisterSpellScript(spell_pri_atonement);
RegisterSpellScript(spell_pri_atonement_effect);
RegisterSpellScript(spell_pri_atonement_effect_aura);
RegisterSpellScript(spell_pri_atonement_passive);
RegisterSpellScript(spell_pri_benediction);
RegisterSpellScript(spell_pri_blaze_of_light);
RegisterSpellScript(spell_pri_circle_of_healing);
RegisterSpellScript(spell_pri_crystalline_reflection);
RegisterSpellScript(spell_pri_dark_indulgence);
RegisterSpellScript(spell_pri_divine_aegis);
RegisterSpellScript(spell_pri_divine_image);
RegisterSpellScript(spell_pri_divine_image_spell_triggered);
RegisterSpellScript(spell_pri_divine_image_stack_timer);
RegisterSpellScript(spell_pri_divine_service);
RegisterSpellScript(spell_pri_divine_star_shadow);
RegisterAreaTriggerAI(areatrigger_pri_divine_star);
RegisterSpellScript(spell_pri_empowered_renew);
RegisterSpellScript(spell_pri_epiphany);
RegisterSpellScript(spell_pri_essence_devourer_heal);
RegisterSpellScript(spell_pri_evangelism);
RegisterSpellScript(spell_pri_focused_mending);
RegisterSpellScript(spell_pri_from_darkness_comes_light);
RegisterSpellScript(spell_pri_guardian_spirit);
RegisterSpellScript(spell_pri_halo_shadow);
RegisterAreaTriggerAI(areatrigger_pri_halo);
RegisterSpellScript(spell_pri_heavens_wrath);
RegisterSpellScript(spell_pri_holy_mending);
RegisterSpellScript(spell_pri_holy_words);
RegisterSpellScript(spell_pri_holy_word_salvation);
RegisterSpellScript(spell_pri_holy_word_salvation_cooldown_reduction);
RegisterSpellScript(spell_pri_item_t6_trinket);
RegisterSpellScript(spell_pri_leap_of_faith_effect_trigger);
RegisterSpellScript(spell_pri_levitate);
RegisterSpellScript(spell_pri_lights_wrath);
RegisterSpellScript(spell_pri_mind_bomb);
RegisterSpellScript(spell_pri_mind_devourer);
RegisterSpellAndAuraScriptPair(spell_pri_mind_devourer_buff, spell_pri_mind_devourer_buff_aura);
RegisterSpellScript(spell_pri_painful_punishment);
RegisterSpellScript(spell_pri_pain_transformation);
RegisterSpellScriptWithArgs(spell_pri_penance, "spell_pri_penance", SPELL_PRIEST_PENANCE_CHANNEL_DAMAGE, SPELL_PRIEST_PENANCE_CHANNEL_HEALING);
RegisterSpellScriptWithArgs(spell_pri_penance, "spell_pri_dark_reprimand", SPELL_PRIEST_DARK_REPRIMAND_CHANNEL_DAMAGE, SPELL_PRIEST_DARK_REPRIMAND_CHANNEL_HEALING);
RegisterSpellScript(spell_pri_penance_or_dark_reprimand_channeled);
RegisterSpellScript(spell_pri_phantasm);
RegisterSpellScript(spell_pri_power_leech_passive);
RegisterSpellScript(spell_pri_power_of_the_dark_side);
RegisterSpellScript(spell_pri_power_of_the_dark_side_damage_bonus);
RegisterSpellScript(spell_pri_power_of_the_dark_side_healing_bonus);
RegisterSpellScript(spell_pri_power_word_radiance);
RegisterSpellScript(spell_pri_power_word_shield);
RegisterSpellScript(spell_pri_power_word_solace);
RegisterSpellScript(spell_pri_prayer_of_mending_dummy);
RegisterSpellAndAuraScriptPair(spell_pri_prayer_of_mending, spell_pri_prayer_of_mending_aura);
RegisterSpellScript(spell_pri_prayer_of_mending_jump);
RegisterSpellScript(spell_pri_protective_light);
RegisterSpellScript(spell_pri_holy_10_1_class_set_2pc);
RegisterSpellScript(spell_pri_holy_10_1_class_set_2pc_chooser);
RegisterSpellScript(spell_pri_holy_10_1_class_set_4pc);
RegisterSpellScript(spell_pri_holy_10_1_class_set_4pc_aura);
RegisterSpellScript(spell_pri_purge_the_wicked);
RegisterSpellScript(spell_pri_purge_the_wicked_dummy);
RegisterSpellScript(spell_pri_rapture);
RegisterSpellScript(spell_pri_sanctuary_absorb);
RegisterSpellScript(spell_pri_sanctuary_trigger);
RegisterSpellScript(spell_pri_rhapsody);
RegisterSpellScript(spell_pri_rhapsody_proc);
RegisterSpellScript(spell_pri_schism);
RegisterSpellScript(spell_pri_sins_of_the_many);
RegisterSpellScript(spell_pri_spirit_of_redemption);
RegisterSpellScript(spell_pri_shadow_covenant);
RegisterSpellScript(spell_pri_shadow_mend);
RegisterSpellScript(spell_pri_shadow_mend_periodic_damage);
RegisterSpellScript(spell_pri_shadow_word_death);
RegisterSpellScript(spell_pri_surge_of_light);
RegisterSpellScript(spell_pri_trail_of_light);
RegisterSpellScript(spell_pri_train_of_thought);
RegisterSpellScript(spell_pri_t3_4p_bonus);
RegisterSpellScript(spell_pri_t5_heal_2p_bonus);
RegisterSpellScript(spell_pri_t10_heal_2p_bonus);
RegisterSpellScript(spell_pri_twist_of_fate);
RegisterSpellScript(spell_pri_unfurling_darkness);
RegisterSpellScript(spell_pri_vampiric_embrace);
RegisterSpellScript(spell_pri_vampiric_embrace_target);
RegisterSpellScript(spell_pri_vampiric_touch);
RegisterSpellScript(spell_pri_whispering_shadows);
RegisterSpellScript(spell_pri_whispering_shadows_effect);
}