Files

3550 lines
120 KiB
C#

// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the Gnu General Public License. See License file in the project root for full license information.
using Framework.Constants;
using Framework.Dynamic;
using Game.AI;
using Game.Entities;
using Game.Movement;
using Game.Scripting;
using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Scripts.Spells.Priest;
struct SpellIds
{
public const uint AbyssalReverie = 373054;
public const uint AngelicFeatherAreatrigger = 158624;
public const uint AngelicFeatherAura = 121557;
public const uint AnsweredPrayers = 394289;
public const uint Apotheosis = 200183;
public const uint ArmorOfFaith = 28810;
public const uint AssuredSafety = 440766;
public const uint Atonement = 81749;
public const uint AtonementEffect = 194384;
public const uint AtonementHeal = 81751;
public const uint Benediction = 193157;
public const uint Benevolence = 415416;
public const uint BlazeOfLight = 215768;
public const uint BlazeOfLightIncrease = 355851;
public const uint BlazeOfLightDecrease = 356084;
public const uint BlessedHealing = 70772;
public const uint BlessedLight = 196813;
public const uint BodyAndSoul = 64129;
public const uint BodyAndSoulSpeed = 65081;
public const uint CircleOfHealing = 204883;
public const uint CrystallineReflection = 373457;
public const uint CrystallineReflectionHeal = 373462;
public const uint CrystallineReflectionReflect = 373464;
public const uint DarkIndulgence = 372972;
public const uint DarkReprimand = 400169;
public const uint DarkReprimandChannelDamage = 373129;
public const uint DarkReprimandChannelHealing = 400171;
public const uint DarkReprimandDamage = 373130;
public const uint DarkReprimandHealing = 400187;
public const uint DazzlingLight = 196810;
public const uint DivineAegis = 47515;
public const uint DivineAegisAbsorb = 47753;
public const uint DivineBlessing = 40440;
public const uint DivineHymnHeal = 64844;
public const uint DivineImageSummon = 392990;
public const uint DivineImageEmpower = 409387;
public const uint DivineImageEmpowerStack = 405963;
public const uint DivineService = 391233;
public const uint DivineStarHoly = 110744;
public const uint DivineStarShadow = 122121;
public const uint DivineStarHolyDamage = 122128;
public const uint DivineStarHolyHeal = 110745;
public const uint DivineStarShadowDamage = 390845;
public const uint DivineStarShadowHeal = 390981;
public const uint DivineWrath = 40441;
public const uint EmpoweredRenewHeal = 391359;
public const uint Epiphany = 414553;
public const uint EpiphanyHighlight = 414556;
public const uint EssenceDevourer = 415479;
public const uint EssenceDevourerShadowfiendHeal = 415673;
public const uint EssenceDevourerMindbenderHeal = 415676;
public const uint FlashHeal = 2061;
public const uint FromDarknessComesLightAura = 390617;
public const uint GreaterHeal = 289666;
public const uint FocusedMending = 372354;
public const uint GuardianSpiritHeal = 48153;
public const uint HaloHoly = 120517;
public const uint HaloShadow = 120644;
public const uint HaloHolyDamage = 120696;
public const uint HaloHolyHeal = 120692;
public const uint HaloShadowDamage = 390964;
public const uint HaloShadowHeal = 390971;
public const uint Heal = 2060;
public const uint HealingLight = 196809;
public const uint HeavensWrath = 421558;
public const uint HolyFire = 14914;
public const uint HolyMendingHeal = 391156;
public const uint HolyNova = 132157;
public const uint HolyWordChastise = 88625;
public const uint HolyWordSalvation = 265202;
public const uint HolyWordSanctify = 34861;
public const uint HolyWordSerenity = 2050;
public const uint Holy10_1_ClassSet2PChooser = 411097;
public const uint Holy10_1_ClassSet4P = 405556;
public const uint Holy10_1_ClassSet4PEffect = 409479;
public const uint Indemnity = 373049;
public const uint ItemEfficiency = 37595;
public const uint LeapOfFaithEffect = 92832;
public const uint LevitateEffect = 111759;
public const uint LightEruption = 196812;
public const uint LightsWrathVisual = 215795;
public const uint MasochismTalent = 193063;
public const uint MasochismPeriodicHeal = 193065;
public const uint MasteryGrace = 271534;
public const uint MindDevourer = 373202;
public const uint MindDevourerAura = 373204;
public const uint MindbenderDisc = 123040;
public const uint MindbenderShadow = 200174;
public const uint Mindgames = 375901;
public const uint MindgamesVenthyr = 323673;
public const uint MindBombStun = 226943;
public const uint Misery = 238558;
public const uint OracularHeal = 26170;
public const uint PainTransformation = 372991;
public const uint PainTransformationHeal = 372994;
public const uint Penance = 47540;
public const uint PenanceChannelDamage = 47758;
public const uint PenanceChannelHealing = 47757;
public const uint PenanceDamage = 47666;
public const uint PenanceHealing = 47750;
public const uint PowerLeechMindbenderMana = 123051;
public const uint PowerLeechMindbenderInsanity = 200010;
public const uint PowerLeechShadowfiendMana = 343727;
public const uint PowerLeechShadowfiendInsanity = 262485;
public const uint PowerOfTheDarkSide = 198069;
public const uint PowerOfTheDarkSideTint = 225795;
public const uint PowerWordLife = 373481;
public const uint PowerWordRadiance = 194509;
public const uint PowerWordShield = 17;
public const uint PowerWordSolaceEnergize = 129253;
public const uint PrayerOfHealing = 596;
public const uint PrayerOfMending = 33076;
public const uint PrayerOfMendingAura = 41635;
public const uint PrayerOfMendingHeal = 33110;
public const uint PrayerOfMendingJump = 155793;
public const uint ProtectiveLightAura = 193065;
public const uint PurgeTheWicked = 204197;
public const uint PurgeTheWickedDummy = 204215;
public const uint PurgeTheWickedPeriodic = 204213;
public const uint Rapture = 47536;
public const uint Renew = 139;
public const uint RenewedHope = 197469;
public const uint RenewedHopeEffect = 197470;
public const uint RevelInPurity = 373003;
public const uint Sanctuary = 231682;
public const uint SanctuaryAbsorb = 208771;
public const uint SanctuaryAura = 208772;
public const uint ShadowCovenant = 314867;
public const uint ShadowCovenantEffect = 322105;
public const uint RhapsodyProc = 390636;
public const uint SayYourPrayers = 391186;
public const uint Schism = 424509;
public const uint SchismAura = 214621;
public const uint SearingLight = 196811;
public const uint ShadowMendDamage = 186439;
public const uint ShadowWordDeath = 32379;
public const uint ShadowWordDeathDamage = 32409;
public const uint ShadowMendPeriodicDummy = 187464;
public const uint ShadowWordPain = 589;
public const uint ShieldDiscipline = 197045;
public const uint ShieldDisciplineEffect = 47755;
public const uint SinAndPunishment = 87204;
public const uint SinsOfTheMany = 280398;
public const uint Smite = 585;
public const uint SpiritOfRedemption = 27827;
public const uint StrengthOfSoul = 197535;
public const uint StrengthOfSoulEffect = 197548;
public const uint SurgeOfLight = 109186;
public const uint SurgeOfLightEffect = 114255;
public const uint TranquilLight = 196816;
public const uint ThePenitentAura = 200347;
public const uint TrailOfLightHeal = 234946;
public const uint Trinity = 214205;
public const uint TrinityEffect = 214206;
public const uint UltimatePenitence = 421453;
public const uint UltimatePenitenceDamage = 421543;
public const uint UltimatePenitenceHeal = 421544;
public const uint UnfurlingDarkness = 341273;
public const uint UnfurlingDarknessAura = 341282;
public const uint UnfurlingDarknessDebuff = 341291;
public const uint VampiricEmbraceHeal = 15290;
public const uint VampiricTouch = 34914;
public const uint VoidShield = 199144;
public const uint VoidShieldEffect = 199145;
public const uint WeakenedSoul = 6788;
public const uint WhisperingShadows = 406777;
public const uint WhisperingShadowsDummy = 391286;
public const uint PvpRulesEnabledHardcoded = 134735;
public const uint VisualPriestPowerWordRadiance = 52872;
public const uint VisualPriestPrayerOfMending = 38945;
}
struct CreatureIds
{
public const uint DivineImage = 198236;
public const uint Mindbender = 62982;
public const uint Shadowfiend = 19668;
}
class RaidCheck(Unit caster)
{
public bool Invoke(WorldObject obj)
{
Unit target = obj.ToUnit();
if (target != null)
return !caster.IsInRaidWith(target);
return true;
}
}
[Script] // 121536 - Angelic Feather talent
class spell_pri_angelic_feather_trigger : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.AngelicFeatherAreatrigger);
}
void HandleEffectDummy(uint effIndex)
{
Position destPos = GetHitDest().GetPosition();
float radius = GetEffectInfo().CalcRadius();
// Caster is prioritary
if (GetCaster().IsWithinDist2d(destPos, radius))
{
GetCaster().CastSpell(GetCaster(), SpellIds.AngelicFeatherAura, true);
}
else
{
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
args.CastDifficulty = GetCastDifficulty();
GetCaster().CastSpell(destPos, SpellIds.AngelicFeatherAreatrigger, args);
}
}
public override void Register()
{
OnEffectHit.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // Angelic Feather areatrigger - created by SpellIds.AngelicFeatherAreatrigger
class areatrigger_pri_angelic_feather(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger)
{
// Called when the AreaTrigger has just been initialized, just before added to map
public override void OnInitialize()
{
Unit caster = at.GetCaster();
if (caster != null)
{
List<AreaTrigger> areaTriggers = caster.GetAreaTriggers(SpellIds.AngelicFeatherAreatrigger);
if (areaTriggers.Count >= 3)
areaTriggers.First().SetDuration(0);
}
}
public override void OnUnitEnter(Unit unit)
{
Unit caster = at.GetCaster();
if (caster != null)
{
if (caster.IsFriendlyTo(unit))
{
// If target already has aura, increase duration to max 130% of initial duration
caster.CastSpell(unit, SpellIds.AngelicFeatherAura, true);
at.SetDuration(0);
}
}
}
}
[Script] // 391387 - Answered Prayers
class spell_pri_answered_prayers : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.AnsweredPrayers, SpellIds.Apotheosis)
&& ValidateSpellEffect((spellInfo.Id, 1));
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
TimeSpan extraDuration = TimeSpan.Zero;
AuraEffect durationEffect = GetEffect(1);
if (durationEffect != null)
extraDuration = TimeSpan.FromSeconds(durationEffect.GetAmount());
Unit target = eventInfo.GetActor();
Aura answeredPrayers = target.GetAura(SpellIds.AnsweredPrayers);
// Note: if caster has no aura, we must cast it first.
if (answeredPrayers == null)
target.CastSpell(target, SpellIds.AnsweredPrayers, TriggerCastFlags.IgnoreCastInProgress);
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();
Aura apotheosis = GetTarget().GetAura(SpellIds.Apotheosis);
if (apotheosis != null)
{
apotheosis.SetDuration(apotheosis.GetDuration() + (int)extraDuration.TotalSeconds);
apotheosis.SetMaxDuration(apotheosis.GetMaxDuration() + (int)extraDuration.TotalSeconds);
}
else
target.CastSpell(target, SpellIds.Apotheosis,
new CastSpellExtraArgs(TriggerCastFlags.FullMask & ~TriggerCastFlags.CastDirectly)
.AddSpellMod(SpellValueMod.Duration, (int)extraDuration.TotalSeconds));
}
}
public override void Register()
{
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.AddFlatModifierBySpellLabel));
}
}
[Script] // 26169 - Oracle Healing Bonus
class spell_pri_aq_3p_bonus : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.OracularHeal);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
Unit caster = eventInfo.GetActor();
if (caster == eventInfo.GetProcTarget())
return;
HealInfo healInfo = eventInfo.GetHealInfo();
if (healInfo == null || healInfo.GetHeal() == 0)
return;
CastSpellExtraArgs args = new(aurEff);
args.AddSpellMod(SpellValueMod.BasePoint0, MathFunctions.CalculatePct((int)(healInfo.GetHeal()), 10));
caster.CastSpell(caster, SpellIds.OracularHeal, args);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 81749 - Atonement
class spell_pri_atonement : AuraScript
{
List<ObjectGuid> _appliedAtonements = new();
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.AtonementHeal, SpellIds.SinsOfTheMany)
&& ValidateSpellEffect((spellInfo.Id, 1), (SpellIds.SinsOfTheMany, 2));
}
bool CheckProc(ProcEventInfo eventInfo)
{
return eventInfo.GetDamageInfo() != null;
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
TriggerAtonementHealOnTargets(aurEff, eventInfo);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy));
}
public void AddAtonementTarget(ObjectGuid target)
{
_appliedAtonements.Add(target);
UpdateSinsOfTheManyValue();
}
public void RemoveAtonementTarget(ObjectGuid target)
{
_appliedAtonements.Remove(target);
UpdateSinsOfTheManyValue();
}
public List<ObjectGuid> GetAtonementTargets()
{
return _appliedAtonements;
}
public class TriggerArgs
{
public SpellInfo TriggeredBy;
public SpellSchoolMask DamageSchoolMask;
}
public void TriggerAtonementHealOnTargets(AuraEffect atonementEffect, ProcEventInfo eventInfo)
{
Unit priest = GetUnitOwner();
DamageInfo damageInfo = eventInfo.GetDamageInfo();
CastSpellExtraArgs args = new(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError);
// Note: atonementEffect holds the correct amount since we passed the effect in the AuraScript that calls this method.
args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), atonementEffect.GetAmount()));
args.SetCustomArg(new TriggerArgs()
{
TriggeredBy = eventInfo.GetSpellInfo(),
DamageSchoolMask = eventInfo.GetDamageInfo().GetSchoolMask()
});
float distanceLimit = GetEffectInfo(1).CalcValue();
_appliedAtonements.RemoveAll(targetGuid =>
{
Unit target = Global.ObjAccessor.GetUnit(priest, targetGuid);
if (target != null)
{
if (target.IsInDist2d(priest, distanceLimit))
priest.CastSpell(target, SpellIds.AtonementHeal, args);
return false;
}
return true;
});
}
void UpdateSinsOfTheManyValue()
{
// Note: the damage dimish starts at the 6th application as of 10.0.5.
float[] 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];
foreach (uint effectIndex in new uint[] { 0, 1, 2 })
{
AuraEffect sinOfTheMany = GetUnitOwner().GetAuraEffect(SpellIds.SinsOfTheMany, effectIndex);
if (sinOfTheMany != null)
sinOfTheMany.ChangeAmount((int)damageByStack[Math.Min(_appliedAtonements.Count, (byte)(damageByStack.Length - 1))]);
}
}
}
[Script] // 81751 - Atonement (Heal)
class spell_pri_abyssal_reverie : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.AbyssalReverie, 0));
}
void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod)
{
spell_pri_atonement.TriggerArgs args = (spell_pri_atonement.TriggerArgs)GetSpell().m_customArg;
if (args == null || (args.DamageSchoolMask & SpellSchoolMask.Shadow) == 0)
return;
AuraEffect abyssalReverieEffect = GetCaster().GetAuraEffect(SpellIds.AbyssalReverie, 0);
if (abyssalReverieEffect != null)
MathFunctions.AddPct(ref pctMod, abyssalReverieEffect.GetAmount());
}
public override void Register()
{
CalcHealing.Add(new(CalculateHealingBonus));
}
}
// 17 - Power Word: Shield
// 139 - Renew
// 2061 - Flash Heal
[Script] // 194509 - Power Word: Radiance
class spell_pri_atonement_effect : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.TrinityEffect, SpellIds.PowerWordRadiance, SpellIds.PowerWordShield)
&& ValidateSpellEffect((SpellIds.PowerWordRadiance, 3), (SpellIds.Indemnity, 0));
}
public override bool Load()
{
Unit caster = GetCaster();
if (!caster.HasAura(SpellIds.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(SpellIds.Trinity))
{
if (GetSpellInfo().Id != SpellIds.PowerWordShield)
return false;
_effectSpellId = SpellIds.TrinityEffect;
}
return true;
}
void HandleOnHitTarget()
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
args.SetTriggeringSpell(GetSpell());
switch (GetSpellInfo().Id)
{
case SpellIds.PowerWordShield:
AuraEffect indemnity = caster.GetAuraEffect(SpellIds.Indemnity, 0);
if (indemnity != null)
args.AddSpellMod(SpellValueMod.Duration,
(int)(TimeSpan.FromSeconds(indemnity.GetAmount())
+ TimeSpan.FromSeconds(Aura.CalcMaxDuration(Global.SpellMgr.GetSpellInfo(_effectSpellId, GetCastDifficulty()),
caster, GetSpell().GetPowerCost()))).TotalSeconds);
break;
case SpellIds.PowerWordRadiance:
// Power Word: Radiance applies Atonement at 60 % (without modifiers) of its total duration.
args.AddSpellMod(SpellValueModFloat.DurationPct, GetEffectInfo(3).CalcValue(caster));
break;
default:
break;
}
caster.CastSpell(target, _effectSpellId, args);
}
public override void Register()
{
AfterHit.Add(new(HandleOnHitTarget));
}
uint _effectSpellId = SpellIds.AtonementEffect;
}
[Script] // 194384 - Atonement (Buff), 214206 - Atonement [Trinity] (Buff)
class spell_pri_atonement_effect_aura : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Atonement);
}
void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
{
Aura atonement = caster.GetAura(SpellIds.Atonement);
if (atonement != null)
{
spell_pri_atonement script = atonement.GetScript<spell_pri_atonement>();
if (script != null)
script.AddAtonementTarget(GetTarget().GetGUID());
}
}
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
{
Aura atonement = caster.GetAura(SpellIds.Atonement);
if (atonement != null)
{
spell_pri_atonement script = atonement.GetScript<spell_pri_atonement>();
if (script != null)
script.RemoveAtonementTarget(GetTarget().GetGUID());
}
}
}
public override void Register()
{
OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
[Script] // 195178 - Atonement (Passive)
class spell_pri_atonement_passive : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.Atonement, 0));
}
bool CheckProc(ProcEventInfo eventInfo)
{
return eventInfo.GetDamageInfo() != null;
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit target = GetTarget();
Unit summoner = target.GetOwner();
if (summoner == null)
return;
AuraEffect atonementEffect = summoner.GetAuraEffect(SpellIds.Atonement, 0);
if (atonementEffect != null)
{
spell_pri_atonement script = atonementEffect.GetBase().GetScript<spell_pri_atonement>();
if (script != null)
script.TriggerAtonementHealOnTargets(atonementEffect, eventInfo);
}
}
public override void Register()
{
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy));
}
}
[Script] // 33110 - Prayer of Mending (Heal)
class spell_pri_benediction : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Renew)
&& ValidateSpellEffect((SpellIds.Benediction, 0));
}
void HandleEffectHitTarget(uint effIndex)
{
AuraEffect benediction = GetCaster().GetAuraEffect(SpellIds.Benediction, 0);
if (benediction != null)
if (RandomHelper.randChance(benediction.GetAmount()))
GetCaster().CastSpell(GetHitUnit(), SpellIds.Renew, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Heal));
}
}
[Script] // 215768 - Blaze of Light
class spell_pri_blaze_of_light : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.BlazeOfLightDecrease, SpellIds.BlazeOfLightIncrease);
}
void HandleProc(ProcEventInfo eventInfo)
{
Unit procTarget = eventInfo.GetProcTarget();
if (procTarget == null)
return;
if (GetTarget().IsValidAttackTarget(procTarget))
GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightDecrease, (TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress));
else
GetTarget().CastSpell(procTarget, SpellIds.BlazeOfLightIncrease, (TriggerCastFlags.CastDirectly | TriggerCastFlags.IgnoreCastInProgress));
}
public override void Register()
{
OnProc.Add(new(HandleProc));
}
}
[Script] // 204883 - Circle of Healing
class spell_pri_circle_of_healing : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((spellInfo.Id, 1));
}
void FilterTargets(List<WorldObject> targets)
{
// Note: we must remove one since target is always chosen.
uint maxTargets = (uint)(GetSpellInfo().GetEffect(1).CalcValue(GetCaster()) - 1);
SelectRandomInjuredTargets(targets, maxTargets, true);
Unit explicitTarget = GetExplTargetUnit();
if (explicitTarget != null)
targets.Insert(0, explicitTarget);
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly));
}
}
[Script] // 17 - Power Word: Shield
class spell_pri_crystalline_reflection : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.CrystallineReflection, SpellIds.CrystallineReflectionHeal, SpellIds.CrystallineReflectionReflect) && ValidateSpellEffect((SpellIds.CrystallineReflection, 0));
}
void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster == null)
return;
// Crystalline Reflection Heal
if (caster.HasAura(SpellIds.CrystallineReflection))
caster.CastSpell(GetTarget(), SpellIds.CrystallineReflectionHeal, new CastSpellExtraArgs(aurEff)
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError));
}
void HandleAfterAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
{
Unit caster = GetCaster();
if (caster == null)
return;
AuraEffect auraEff = caster.GetAuraEffect(SpellIds.CrystallineReflection, 0);
if (auraEff == null)
return;
Unit attacker = dmgInfo.GetAttacker();
if (attacker == null)
return;
CastSpellExtraArgs args = new(TriggerCastFlags.DontReportCastError);
args.AddSpellMod(SpellValueMod.BasePoint0, (int)MathFunctions.CalculatePct(absorbAmount, auraEff.GetAmount()));
caster.CastSpell(attacker, SpellIds.CrystallineReflectionReflect, args);
}
public override void Register()
{
AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask));
AfterEffectAbsorb.Add(new(HandleAfterAbsorb, 0));
}
}
[Script] // 8092 - Mind Blast
class spell_pri_dark_indulgence : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.DarkIndulgence, 0));
}
void HandleEffectHit(uint effIndex)
{
AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.DarkIndulgence, 0);
if (aurEff == null)
return;
if (RandomHelper.randChance(aurEff.GetAmount()))
GetCaster().CastSpell(GetCaster(), SpellIds.PowerOfTheDarkSide, true);
}
public override void Register()
{
OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage));
}
}
struct DivineImageHelpers
{
public static Unit GetSummon(Unit owner)
{
foreach (Unit summon in owner.m_Controlled)
if (summon.GetEntry() == CreatureIds.DivineImage)
return summon;
return null;
}
public static uint? GetSpellToCast(uint spellId)
{
switch (spellId)
{
case SpellIds.Renew:
return SpellIds.TranquilLight;
case SpellIds.PowerWordShield:
case SpellIds.PowerWordLife:
case SpellIds.FlashHeal:
case SpellIds.Heal:
case SpellIds.GreaterHeal:
case SpellIds.HolyWordSerenity:
return SpellIds.HealingLight;
case SpellIds.PrayerOfMending:
case SpellIds.PrayerOfMendingHeal:
return SpellIds.BlessedLight;
case SpellIds.PrayerOfHealing:
case SpellIds.CircleOfHealing:
case SpellIds.HaloHoly:
case SpellIds.DivineStarHolyHeal:
case SpellIds.DivineHymnHeal:
case SpellIds.HolyWordSanctify:
case SpellIds.HolyWordSalvation:
return SpellIds.DazzlingLight;
case SpellIds.ShadowWordPain:
case SpellIds.Smite:
case SpellIds.HolyFire:
case SpellIds.ShadowWordDeath:
case SpellIds.HolyWordChastise:
case SpellIds.Mindgames:
case SpellIds.MindgamesVenthyr:
return SpellIds.SearingLight;
case SpellIds.HolyNova:
return SpellIds.LightEruption;
default:
break;
}
return null;
}
public static void Trigger(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit target = eventInfo.GetActor();
if (target == null)
return;
Unit divineImage = GetSummon(target);
if (divineImage == null)
return;
uint? spellId = GetSpellToCast(eventInfo.GetSpellInfo().Id);
if (!spellId.HasValue)
return;
divineImage.CastSpell(new CastSpellTargetArg(eventInfo.GetProcSpell().m_targets), spellId.Value, aurEff);
}
}
[Script] // 392988 - Divine Image
class spell_pri_divine_image : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.DivineImageSummon, SpellIds.DivineImageEmpower, SpellIds.DivineImageEmpowerStack);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit target = eventInfo.GetActor();
if (target == null)
return;
// Note: if target has an active Divine Image, we should empower it rather than summoning a new one.
Unit divineImage = DivineImageHelpers.GetSummon(target);
if (divineImage != null)
{
// 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));
TempSummon tempSummon = divineImage.ToTempSummon();
if (tempSummon != null)
tempSummon.RefreshTimer();
divineImage.CastSpell(divineImage, SpellIds.DivineImageEmpower, eventInfo.GetProcSpell());
}
else
{
target.CastSpell(target, SpellIds.DivineImageSummon, new CastSpellExtraArgs()
.SetTriggeringAura(aurEff)
.SetTriggeringSpell(eventInfo.GetProcSpell())
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DisallowProcEvents | TriggerCastFlags.DontReportCastError));
// Note: Divine Image triggers a cast immediately based on the Holy Word cast.
DivineImageHelpers.Trigger(aurEff, eventInfo);
}
target.CastSpell(target, SpellIds.DivineImageEmpowerStack, new CastSpellExtraArgs()
.SetTriggeringAura(aurEff)
.SetTriggeringSpell(eventInfo.GetProcSpell())
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DisallowProcEvents | TriggerCastFlags.DontReportCastError));
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 405216 - Divine Image (Spell Cast Check)
class spell_pri_divine_image_spell_triggered : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo
(
SpellIds.Renew,
SpellIds.PowerWordShield,
SpellIds.PowerWordLife,
SpellIds.FlashHeal,
SpellIds.HolyWordSerenity,
SpellIds.PrayerOfMending,
SpellIds.PrayerOfMendingHeal,
SpellIds.PrayerOfHealing,
SpellIds.CircleOfHealing,
SpellIds.HaloHoly,
SpellIds.DivineStarHolyHeal,
SpellIds.DivineHymnHeal,
SpellIds.HolyWordSanctify,
SpellIds.HolyWordSalvation,
SpellIds.Smite,
SpellIds.HolyFire,
SpellIds.ShadowWordDeath,
SpellIds.ShadowWordPain,
SpellIds.Mindgames,
SpellIds.MindgamesVenthyr,
SpellIds.HolyWordChastise,
SpellIds.HolyNova,
SpellIds.TranquilLight,
SpellIds.HealingLight,
SpellIds.BlessedLight,
SpellIds.DazzlingLight,
SpellIds.SearingLight,
SpellIds.LightEruption,
SpellIds.DivineImageEmpowerStack
);
}
bool CheckProc(ProcEventInfo eventInfo)
{
return DivineImageHelpers.GetSummon(eventInfo.GetActor()) != null;
}
void HandleAfterRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
GetTarget().RemoveAurasDueToSpell(SpellIds.DivineImageEmpowerStack);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(DivineImageHelpers.Trigger, 0, AuraType.Dummy));
AfterEffectRemove.Add(new(HandleAfterRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
// 405963 Divine Image
[Script] // 409387 Divine Image
class spell_pri_divine_image_stack_timer : AuraScript
{
void TrackStackApplicationTime(AuraEffect aurEff, AuraEffectHandleModes mode)
{
var spelId = GetId();
var owner = GetUnitOwner();
GetUnitOwner().m_Events.AddEventAtOffset(() => owner.RemoveAuraFromStack(spelId), TimeSpan.FromSeconds(GetMaxDuration()));
}
public override void Register()
{
AfterEffectApply.Add(new(TrackStackApplicationTime, 0, AuraType.Any, AuraEffectHandleModes.RealOrReapplyMask));
}
}
[Script] // 33110 - Prayer of Mending (Heal)
class spell_pri_divine_service : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingAura)
&& ValidateSpellEffect((SpellIds.DivineService, 0));
}
void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod)
{
AuraEffect divineServiceEffect = GetCaster().GetAuraEffect(SpellIds.DivineService, 0);
if (divineServiceEffect != null)
{
Aura prayerOfMending = victim.GetAura(SpellIds.PrayerOfMendingAura, GetCaster().GetGUID());
if (prayerOfMending != null)
MathFunctions.AddPct(ref pctMod, (int)divineServiceEffect.GetAmount() * prayerOfMending.GetStackAmount());
}
}
public override void Register()
{
CalcHealing.Add(new(CalculateHealingBonus));
}
}
[Script] // 122121 - Divine Star (Shadow)
class spell_pri_divine_star_shadow : SpellScript
{
void HandleHitTarget(uint effIndex)
{
Unit caster = GetCaster();
if ((int)caster.GetPowerType() != GetEffectInfo().MiscValue)
PreventHitDefaultEffect(effIndex);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleHitTarget, 2, SpellEffectName.Energize));
}
}
// 110744 - Divine Star (Holy)
[Script] // 122121 - Divine Star (Shadow)
class areatrigger_pri_divine_star(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger)
{
TaskScheduler _scheduler = new();
Position _casterCurrentPosition;
List<ObjectGuid> _affectedUnits = new();
public override void OnInitialize()
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(at.GetSpellId(), Difficulty.None);
if (spellInfo == null)
return;
if (spellInfo.GetEffects().Count <= 1)
return;
Unit caster = at.GetCaster();
if (caster == null)
return;
_casterCurrentPosition = caster.GetPosition();
// Note: max. distance at which the Divine Star can travel to is 1's BasePoints yards.
float maxTravelDistance = (float)spellInfo.GetEffect(1).CalcValue(caster);
Position destPos = _casterCurrentPosition;
at.MovePositionToFirstCollision(destPos, maxTravelDistance, 0.0f);
PathGenerator firstPath = new(at);
firstPath.CalculatePath(destPos.GetPositionX(), destPos.GetPositionY(), destPos.GetPositionZ(), false);
at.InitSplines(firstPath.GetPath());
}
public override void OnUpdate(uint diff)
{
_scheduler.Update(diff);
}
public override void OnUnitEnter(Unit unit)
{
HandleUnitEnterExit(unit);
}
public override void OnUnitExit(Unit unit, AreaTriggerExitReason reason)
{
// 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 == null)
return;
if (_affectedUnits.Contains(unit.GetGUID()))
return;
TriggerCastFlags triggerFlags = TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress;
if (caster.IsValidAttackTarget(unit))
caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowDamage : SpellIds.DivineStarHolyDamage,
triggerFlags);
else if (caster.IsValidAssistTarget(unit))
caster.CastSpell(unit, at.GetSpellId() == SpellIds.DivineStarShadow ? SpellIds.DivineStarShadowHeal : SpellIds.DivineStarHolyHeal,
triggerFlags);
_affectedUnits.Add(unit.GetGUID());
}
public override void OnDestinationReached()
{
Unit caster = at.GetCaster();
if (caster == null)
return;
if (at.GetDistance(_casterCurrentPosition) > 0.05f)
{
_affectedUnits.Clear();
ReturnToCaster();
}
else
at.Remove();
}
void ReturnToCaster()
{
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
{
Unit caster = at.GetCaster();
if (caster == null)
return;
_casterCurrentPosition = caster.GetPosition();
at.InitSplines([at, caster]);
task.Repeat(TimeSpan.FromSeconds(250));
});
}
}
[Script] // 391339 - Empowered Renew
class spell_pri_empowered_renew : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Renew, SpellIds.EmpoweredRenewHeal)
&& ValidateSpellEffect((SpellIds.Renew, 0))
&& Global.SpellMgr.GetSpellInfo(SpellIds.Renew, Difficulty.None).GetEffect(0).IsAura(AuraType.PeriodicHeal);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit caster = eventInfo.GetActor();
Unit target = eventInfo.GetProcTarget();
SpellInfo renewSpellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.Renew, GetCastDifficulty());
SpellEffectInfo renewEffect = renewSpellInfo.GetEffect(0);
int estimatedTotalHeal = (int)AuraEffect.CalculateEstimatedfTotalPeriodicAmount(caster, target, renewSpellInfo, renewEffect, renewEffect.CalcValue(caster), 1);
int healAmount = MathFunctions.CalculatePct(estimatedTotalHeal, aurEff.GetAmount());
caster.CastSpell(target, SpellIds.EmpoweredRenewHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, healAmount));
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 414553 - Epiphany
class spell_pri_epiphany : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMending, SpellIds.EpiphanyHighlight);
}
bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
return RandomHelper.randChance(aurEff.GetAmount());
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit target = GetTarget();
target.GetSpellHistory().ResetCooldown(SpellIds.PrayerOfMending, true);
target.CastSpell(target, SpellIds.EpiphanyHighlight, aurEff);
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy));
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy));
}
}
// 415673 - Essence Devourer (Heal)
[Script] // 415676 - Essence Devourer (Heal)
class spell_pri_essence_devourer_heal : SpellScript
{
void FilterTargets(List<WorldObject> targets)
{
SelectRandomInjuredTargets(targets, 1, true);
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaAlly));
}
}
[Script] // 246287 - Evangelism
class spell_pri_evangelism : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Trinity, SpellIds.AtonementEffect, SpellIds.TrinityEffect);
}
void HandleScriptEffect(uint effIndex)
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
Aura atonementAura = caster.HasAura(SpellIds.Trinity)
? target.GetAura(SpellIds.TrinityEffect, caster.GetGUID())
: target.GetAura(SpellIds.AtonementEffect, caster.GetGUID());
if (atonementAura == null)
return;
TimeSpan extraDuration = TimeSpan.FromSeconds(GetEffectValue());
atonementAura.SetDuration(atonementAura.GetDuration() + (int)extraDuration.TotalMilliseconds);
atonementAura.SetMaxDuration(atonementAura.GetDuration() + (int)extraDuration.TotalMilliseconds);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleScriptEffect, 0, SpellEffectName.ScriptEffect));
}
}
[Script] // 33110 - Prayer of Mending (Heal)
class spell_pri_focused_mending : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.FocusedMending, 0));
}
void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod)
{
AuraEffect focusedMendingEffect = GetCaster().GetAuraEffect(SpellIds.FocusedMending, 0);
if (focusedMendingEffect != null)
{
if (GetSpell().m_customArg is bool isEmpoweredByFocusedMending && isEmpoweredByFocusedMending)
MathFunctions.AddPct(ref pctMod, focusedMendingEffect.GetAmount());
}
}
public override void Register()
{
CalcHealing.Add(new(CalculateHealingBonus));
}
}
[Script] // 390615 - From Darkness Comes Light (Talent)
class spell_pri_from_darkness_comes_light : AuraScript
{
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
GetTarget().CastSpell(GetTarget(), SpellIds.FromDarknessComesLightAura, aurEff);
}
public override void Register()
{
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
[Script] // 47788 - Guardian Spirit
class spell_pri_guardian_spirit : AuraScript
{
uint healPct = 0;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.GuardianSpiritHeal) && ValidateSpellEffect((spellInfo.Id, 1));
}
public override bool Load()
{
healPct = (uint)GetEffectInfo(1).CalcValue();
return true;
}
void CalculateAmount(AuraEffect aurEff, ref int amount, ref bool canBeRecalculated)
{
// Set absorbtion amount to unlimited
amount = -1;
}
void Absorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
{
Unit target = GetTarget();
if (dmgInfo.GetDamage() < target.GetHealth())
return;
int healAmount = (int)target.CountPctFromMaxHealth((int)healPct);
// remove the aura now, we don't want 40% healing bonus
Remove(AuraRemoveMode.EnemySpell);
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
args.AddSpellMod(SpellValueMod.BasePoint0, healAmount);
target.CastSpell(target, SpellIds.GuardianSpiritHeal, args);
absorbAmount = dmgInfo.GetDamage();
}
public override void Register()
{
DoEffectCalcAmount.Add(new(CalculateAmount, 1, AuraType.SchoolAbsorb));
OnEffectAbsorb.Add(new(Absorb, 1));
}
}
[Script] // 421558 - Heaven's Wrath
class spell_pri_heavens_wrath : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.UltimatePenitence);
}
bool CheckProc(ProcEventInfo eventInfo)
{
return !(eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceDamage || eventInfo.GetSpellInfo().Id == SpellIds.UltimatePenitenceHeal);
}
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit caster = eventInfo.GetActor();
if (caster == null)
return;
int cdReduction = aurEff.GetAmount();
caster.GetSpellHistory().ModifyCooldown(SpellIds.UltimatePenitence, TimeSpan.FromSeconds(-cdReduction), true);
}
public override void Register()
{
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
[Script] // 120644 - Halo (Shadow)
class spell_pri_halo_shadow : SpellScript
{
void HandleHitTarget(uint effIndex)
{
Unit caster = GetCaster();
if ((int)caster.GetPowerType() != GetEffectInfo().MiscValue)
PreventHitDefaultEffect(effIndex);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleHitTarget, 1, SpellEffectName.Energize));
}
}
// 120517 - Halo (Holy)
[Script] // 120644 - Halo (Shadow)
class areatrigger_pri_halo(AreaTrigger areaTrigger) : AreaTriggerAI(areaTrigger)
{
public override void OnUnitEnter(Unit unit)
{
Unit caster = at.GetCaster();
if (caster != null)
{
if (caster.IsValidAttackTarget(unit))
caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowDamage : SpellIds.HaloHolyDamage,
TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress);
else if (caster.IsValidAssistTarget(unit))
caster.CastSpell(unit, at.GetSpellId() == SpellIds.HaloShadow ? SpellIds.HaloShadowHeal : SpellIds.HaloHolyHeal,
TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress);
}
}
}
[Script] // 391154 - Holy Mending
class spell_pri_holy_mending : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Renew, SpellIds.HolyMendingHeal);
}
bool CheckProc(AuraEffect aurEff, ProcEventInfo procInfo)
{
return procInfo.GetProcTarget().HasAura(SpellIds.Renew, procInfo.GetActor().GetGUID());
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.HolyMendingHeal, new CastSpellExtraArgs(aurEff));
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell));
OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell));
}
}
[Script] // 63733 - Holy Words
class spell_pri_holy_words : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(
SpellIds.Heal,
SpellIds.FlashHeal,
SpellIds.PrayerOfHealing,
SpellIds.Renew,
SpellIds.Smite,
SpellIds.HolyWordChastise,
SpellIds.HolyWordSanctify,
SpellIds.HolyWordSerenity
) && ValidateSpellEffect((SpellIds.HolyWordSerenity, 1), (SpellIds.HolyWordSanctify, 3), (SpellIds.HolyWordChastise, 1));
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
SpellInfo spellInfo = eventInfo.GetSpellInfo();
if (spellInfo == null)
return;
uint targetSpellId;
uint cdReductionEffIndex;
switch (spellInfo.Id)
{
case SpellIds.Heal:
case SpellIds.FlashHeal: // reduce Holy Word: Serenity cd by 6 seconds
targetSpellId = SpellIds.HolyWordSerenity;
cdReductionEffIndex = 1;
// cdReduction = Global.SpellMgr.GetSpellInfo(SpellIds.HolyWordSerenity, GetCastDifficulty()).GetEffect(1).CalcValue(player);
break;
case SpellIds.PrayerOfHealing: // reduce Holy Word: Sanctify cd by 6 seconds
targetSpellId = SpellIds.HolyWordSanctify;
cdReductionEffIndex = 2;
break;
case SpellIds.Renew: // reuce Holy Word: Sanctify cd by 2 seconds
targetSpellId = SpellIds.HolyWordSanctify;
cdReductionEffIndex = 3;
break;
case SpellIds.Smite: // reduce Holy Word: Chastise cd by 4 seconds
targetSpellId = SpellIds.HolyWordChastise;
cdReductionEffIndex = 1;
break;
default:
Log.outWarn(LogFilter.Spells, $"HolyWords aura has been proced by an unknown spell: {GetSpellInfo().Id}");
return;
}
SpellInfo targetSpellInfo = Global.SpellMgr.GetSpellInfo(targetSpellId, GetCastDifficulty());
int cdReduction = targetSpellInfo.GetEffect(cdReductionEffIndex).CalcValue(GetTarget());
GetTarget().GetSpellHistory().ModifyCooldown(targetSpellInfo, TimeSpan.FromSeconds(-cdReduction), true);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 265202 - Holy Word: Salvation
class spell_pri_holy_word_salvation : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingAura, SpellIds.Renew) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0), (spellInfo.Id, 1))
&& spellInfo.GetEffect(1).TargetB.GetTarget() == Targets.UnitSrcAreaAlly;
}
public override bool Load()
{
_spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None);
_healEffectDummy = _spellInfoHeal.GetEffect(0);
return true;
}
void HandleApplyBuffs(uint effIndex)
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
// amount of Prayer of Mending is SpellIds.HolyWordSalvation's 1.
args.AddSpellMod(SpellValueMod.AuraStack, GetEffectValue());
int basePoints = caster.SpellHealingBonusDone(target, _spellInfoHeal, _healEffectDummy.CalcValue(caster), DamageEffectType.Heal, _healEffectDummy);
args.AddSpellMod(SpellValueMod.BasePoint0, basePoints);
caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args);
// a full duration Renew is triggered.
caster.CastSpell(target, SpellIds.Renew, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetTriggeringSpell(GetSpell()));
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleApplyBuffs, 1, SpellEffectName.Dummy));
}
SpellInfo _spellInfoHeal = null;
SpellEffectInfo _healEffectDummy = null;
}
// 2050 - Holy Word: Serenity
[Script] // 34861 - Holy Word: Sanctify
class spell_pri_holy_word_salvation_cooldown_reduction : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.HolyWordSalvation)
&& ValidateSpellEffect((SpellIds.HolyWordSalvation, 2));
}
public override bool Load()
{
return GetCaster().HasSpell(SpellIds.HolyWordSalvation);
}
void ReduceCooldown()
{
// cooldown reduced by SpellIds.HolyWordSalvation's TimeSpan.FromSeconds(2).
int cooldownReduction = Global.SpellMgr.GetSpellInfo(SpellIds.HolyWordSalvation, GetCastDifficulty()).GetEffect(2).CalcValue(GetCaster());
GetCaster().GetSpellHistory().ModifyCooldown(SpellIds.HolyWordSalvation, TimeSpan.FromSeconds(-cooldownReduction), true);
}
public override void Register()
{
AfterCast.Add(new(ReduceCooldown));
}
}
[Script] // 40438 - Priest Tier 6 Trinket
class spell_pri_item_t6_trinket : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.DivineBlessing, SpellIds.DivineWrath);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
Unit caster = eventInfo.GetActor();
if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Heal) != 0)
caster.CastSpell(null, SpellIds.DivineBlessing, true);
if ((eventInfo.GetSpellTypeMask() & ProcFlagsSpellType.Damage) != 0)
caster.CastSpell(null, SpellIds.DivineWrath, true);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 92833 - Leap of Faith
class spell_pri_leap_of_faith_effect_trigger : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.LeapOfFaithEffect);
}
void HandleEffectDummy(uint effIndex)
{
Position destPos = GetHitDest().GetPosition();
SpellCastTargets targets = new();
targets.SetDst(destPos);
targets.SetUnitTarget(GetCaster());
GetHitUnit().CastSpell(targets, (uint)GetEffectValue(), GetCastDifficulty());
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 1706 - Levitate
class spell_pri_levitate : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.LevitateEffect);
}
void HandleDummy(uint effIndex)
{
GetCaster().CastSpell(GetHitUnit(), SpellIds.LevitateEffect, true);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 373178 - Light's Wrath
class spell_pri_lights_wrath : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((spellInfo.Id, 1));
}
public override void OnPrecast()
{
Aura atonement = GetCaster().GetAura(SpellIds.Atonement);
if (atonement == null)
return;
spell_pri_atonement script = atonement.GetScript<spell_pri_atonement>();
if (script == null)
return;
foreach (ObjectGuid atonementTarget in script.GetAtonementTargets())
{
Unit target = Global.ObjAccessor.GetUnit(GetCaster(), atonementTarget);
if (target != null)
{
target.CancelSpellMissiles(SpellIds.LightsWrathVisual, false, false);
target.CastSpell(GetCaster(), SpellIds.LightsWrathVisual, TriggerCastFlags.IgnoreCastInProgress);
}
}
}
void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod)
{
Aura atonement = GetCaster().GetAura(SpellIds.Atonement);
if (atonement == null)
return;
// Atonement size may have changed when missile hits, we need to take an updated count of Atonement applications.
spell_pri_atonement script = atonement.GetScript<spell_pri_atonement>();
if (script != null)
MathFunctions.AddPct(ref pctMod, GetEffectInfo(1).CalcValue(GetCaster()) * script.GetAtonementTargets().Count);
}
public override void Register()
{
CalcDamage.Add(new(CalculateDamageBonus));
}
}
[Script] // 205369 - Mind Bomb
class spell_pri_mind_bomb : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.MindBombStun);
}
void RemoveEffect(AuraEffect aurEff, AuraEffectHandleModes mode)
{
if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Death || GetTargetApplication().GetRemoveMode() == AuraRemoveMode.Expire)
{
Unit caster = GetCaster();
if (caster != null)
caster.CastSpell(GetTarget().GetPosition(), SpellIds.MindBombStun, true);
}
}
public override void Register()
{
AfterEffectRemove.Add(new(RemoveEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
// 373202 - Mind Devourer
[Script] // Triggered by 8092 - Mind Blast
class spell_pri_mind_devourer : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.MindDevourerAura)
&& ValidateSpellEffect((SpellIds.MindDevourer, 0));
}
public override bool Load()
{
return GetCaster().HasAura(SpellIds.MindDevourer);
}
void HandleEffectHitTarget(uint effIndex)
{
AuraEffect aurEff = GetCaster().GetAuraEffect(SpellIds.MindDevourer, 0);
if (aurEff != null && RandomHelper.randChance(aurEff.GetAmount()))
GetCaster().CastSpell(GetCaster(), SpellIds.MindDevourerAura, GetSpell());
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage));
}
}
// 373204 - Mind Devourer (Aura)
[Script] // Attached to 335467 - Devouring Plague
class spell_pri_mind_devourer_buff_aura : AuraScript
{
public float DamageIncrease = 0.0f;
void CalculateDamage(AuraEffect aurEff, Unit victim, ref int damage, ref int flatMod, ref float pctMod)
{
MathFunctions.AddPct(ref pctMod, DamageIncrease);
}
public override void Register()
{
DoEffectCalcDamageAndHealing.Add(new(CalculateDamage, 1, AuraType.PeriodicLeech));
}
}
[Script]
class spell_pri_mind_devourer_buff : SpellScript
{
float _damageIncrease = 0.0f;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.MindDevourerAura, 1));
}
public override void OnPrecast()
{
AuraEffect mindDevourer = GetCaster().GetAuraEffect(SpellIds.MindDevourerAura, 1);
if (mindDevourer == null || !GetSpell().m_appliedMods.Contains(mindDevourer.GetBase()))
return;
_damageIncrease = (int)mindDevourer.GetAmount();
}
void CalculateDamage(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod)
{
MathFunctions.AddPct(ref pctMod, _damageIncrease);
}
void ModifyAuraValueAndRemoveBuff(uint effIndex)
{
if (_damageIncrease == 0)
return;
Aura devouringPlague = GetHitAura();
if (devouringPlague != null)
{
spell_pri_mind_devourer_buff_aura script = devouringPlague.GetScript<spell_pri_mind_devourer_buff_aura>();
if (script != null)
script.DamageIncrease = _damageIncrease;
}
GetCaster().RemoveAurasDueToSpell(SpellIds.MindDevourerAura);
}
public override void Register()
{
CalcDamage.Add(new(CalculateDamage));
OnEffectHitTarget.Add(new(ModifyAuraValueAndRemoveBuff, 1, SpellEffectName.ApplyAura));
}
}
[Script] // 390686 - Painful Punishment
class spell_pri_painful_punishment : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ShadowWordPain, SpellIds.PurgeTheWickedPeriodic);
}
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit caster = eventInfo.GetActor();
Unit target = eventInfo.GetActionTarget();
if (caster == null || target == null)
return;
int additionalDuration = aurEff.GetAmount();
Aura shadowWordPain = target.GetOwnedAura(SpellIds.ShadowWordPain, caster.GetGUID());
if (shadowWordPain != null)
shadowWordPain.SetDuration(shadowWordPain.GetDuration() + additionalDuration);
Aura purgeTheWicked = target.GetOwnedAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID());
if (purgeTheWicked != null)
purgeTheWicked.SetDuration(purgeTheWicked.GetDuration() + additionalDuration);
}
public override void Register()
{
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
// 372991 - Pain Transformation
[Script] // Triggered by 33206 - Pain Suppression
class spell_pri_pain_transformation : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.PainTransformation, SpellIds.PainTransformationHeal);
}
public override bool Load()
{
return GetCaster().HasAura(SpellIds.PainTransformation) && !GetCaster().HasAura(SpellIds.Trinity);
}
void HandleHit(uint effIndex)
{
CastSpellExtraArgs args = new(GetSpell());
args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError);
GetCaster().CastSpell(GetHitUnit(), SpellIds.PainTransformationHeal, args);
GetCaster().CastSpell(GetHitUnit(), SpellIds.AtonementEffect, args);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleHit, 0, SpellEffectName.ApplyAura));
}
}
// 47540 - Penance
// 400169 - Dark Reprimand
[Script("spell_pri_penance", SpellIds.PenanceChannelDamage, SpellIds.PenanceChannelHealing)]
[Script("spell_pri_dark_reprimand", SpellIds.DarkReprimandChannelDamage, SpellIds.DarkReprimandChannelHealing)]
class spell_pri_penance(uint damageSpellId, uint healingSpellId) : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(damageSpellId, healingSpellId);
}
SpellCastResult CheckCast()
{
Unit caster = GetCaster();
Unit target = GetExplTargetUnit();
if (target != null)
{
if (!caster.IsFriendlyTo(target))
{
if (!caster.IsValidAttackTarget(target))
return SpellCastResult.BadTargets;
if (!caster.IsInFront(target))
return SpellCastResult.UnitNotInfront;
}
}
return SpellCastResult.SpellCastOk;
}
void HandleDummy(uint effIndex)
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
if (target != null)
{
if (caster.IsFriendlyTo(target))
caster.CastSpell(target, healingSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD)
.SetTriggeringSpell(GetSpell()));
else
caster.CastSpell(target, damageSpellId, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD)
.SetTriggeringSpell(GetSpell()));
}
}
public override void Register()
{
OnCheckCast.Add(new(CheckCast));
OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy));
}
}
// 47758 - Penance (Channel Damage), 47757 - Penance (Channel Healing)
[Script] // 373129 - Dark Reprimand (Channel Damage), 400171 - Dark Reprimand (Channel Healing)
class spell_pri_penance_or_dark_reprimand_channeled : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide);
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
caster.RemoveAura(SpellIds.PowerOfTheDarkSide);
}
public override void Register()
{
OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
[Script] // 114239 - Phantasm
class spell_pri_phantasm : SpellScript
{
void HandleEffectHit(uint effIndex)
{
GetCaster().RemoveMovementImpairingAuras(false);
}
public override void Register()
{
OnEffectHit.Add(new(HandleEffectHit, 0, SpellEffectName.Dummy));
}
}
// 262484 - Power Leech (Passive for Shadowfiend)
[Script] // 284621 - Power Leech (Passive for Mindbender)
class spell_pri_power_leech_passive : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerLeechShadowfiendInsanity, SpellIds.PowerLeechShadowfiendMana, SpellIds.PowerLeechMindbenderInsanity, SpellIds.PowerLeechMindbenderMana, SpellIds.EssenceDevourer, SpellIds.EssenceDevourerShadowfiendHeal, SpellIds.EssenceDevourerMindbenderHeal)
&& ValidateSpellEffect((SpellIds.PowerLeechShadowfiendInsanity, 0), (SpellIds.PowerLeechShadowfiendMana, 0), (SpellIds.PowerLeechMindbenderInsanity, 0), (SpellIds.PowerLeechMindbenderMana, 0));
}
bool CheckProc(ProcEventInfo eventInfo)
{
return eventInfo.GetDamageInfo() != null;
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit target = GetTarget();
Player summoner = target.GetOwner()?.ToPlayer();
if (summoner == null)
return;
SpellInfo spellInfo = null;
int divisor = 1;
if (summoner.GetPrimarySpecialization() != ChrSpecialization.PriestShadow)
{
if (target.GetEntry() == CreatureIds.Shadowfiend)
{
// Note: divisor is 100 because effect value is 5 and its supposed to restore 0.5%
spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PowerLeechShadowfiendMana, GetCastDifficulty());
divisor = 10;
}
else
{
// Note: divisor is 100 because effect value is 20 and its supposed to restore 0.2%
spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.PowerLeechMindbenderMana, GetCastDifficulty());
divisor = 100;
}
}
else
spellInfo = Global.SpellMgr.GetSpellInfo(target.GetEntry() == CreatureIds.Shadowfiend
? SpellIds.PowerLeechShadowfiendInsanity
: SpellIds.PowerLeechMindbenderInsanity, GetCastDifficulty());
target.CastSpell(summoner, spellInfo.Id, new CastSpellExtraArgs(aurEff)
.AddSpellMod(SpellValueMod.BasePoint0, spellInfo.GetEffect(0).CalcValue() / divisor));
// Note: Essence Devourer talent.
if (summoner.HasAura(SpellIds.EssenceDevourer))
summoner.CastSpell(null, target.GetEntry() == CreatureIds.Shadowfiend ? SpellIds.EssenceDevourerShadowfiendHeal : SpellIds.EssenceDevourerMindbenderHeal, aurEff);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy));
}
}
[Script] // 198069 - Power of the Dark Side
class spell_pri_power_of_the_dark_side : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerOfTheDarkSideTint);
}
void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
caster.CastSpell(caster, SpellIds.PowerOfTheDarkSideTint, true);
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
caster.RemoveAura(SpellIds.PowerOfTheDarkSideTint);
}
public override void Register()
{
OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
// 47666 - Penance (Damage)
[Script] // 373130 - Dark Reprimand (Damage)
class spell_pri_power_of_the_dark_side_damage_bonus : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide);
}
void CalculateDamageBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod)
{
AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0);
if (powerOfTheDarkSide != null)
MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount());
}
public override void Register()
{
CalcDamage.Add(new(CalculateDamageBonus));
}
}
// 47750 - Penance (Healing)
[Script] // 400187 - Dark Reprimand (Healing)
class spell_pri_power_of_the_dark_side_healing_bonus : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerOfTheDarkSide);
}
void CalculateHealingBonus(SpellEffectInfo spellEffectInfo, Unit victim, ref int healing, ref int flatMod, ref float pctMod)
{
AuraEffect powerOfTheDarkSide = GetCaster().GetAuraEffect(SpellIds.PowerOfTheDarkSide, 0);
if (powerOfTheDarkSide != null)
MathFunctions.AddPct(ref pctMod, powerOfTheDarkSide.GetAmount());
}
public override void Register()
{
CalcHealing.Add(new(CalculateHealingBonus));
}
}
[Script] // 194509 - Power Word: Radiance
class spell_pri_power_word_radiance : SpellScript
{
List<ObjectGuid> _visualTargets = new();
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.AtonementEffect);
}
void FilterTargets(List<WorldObject> targets)
{
Unit caster = GetCaster();
Unit explTarget = GetExplTargetUnit();
// we must add one since explicit target is always chosen.
int maxTargets = GetEffectInfo(2).CalcValue(caster) + 1;
SortTargetsWithPriorityRules(targets, maxTargets, GetRadianceRules(caster, explTarget));
foreach (WorldObject target in targets)
{
if (target == explTarget)
continue;
_visualTargets.Add(target.GetGUID());
}
}
void HandleEffectHitTarget(uint effIndex)
{
foreach (ObjectGuid guid in _visualTargets)
{
Unit target = Global.ObjAccessor.GetUnit(GetHitUnit(), guid);
if (target != null)
GetHitUnit().SendPlaySpellVisual(target, SpellIds.VisualPriestPowerWordRadiance, 0, 0, 70.0f);
}
}
List<TargetPriorityRule> GetRadianceRules(Unit caster, Unit explTarget)
{
return new List<TargetPriorityRule>()
{
new TargetPriorityRule((WorldObject target) => target == explTarget),
new TargetPriorityRule((Unit target) => !target.HasAura(SpellIds.AtonementEffect, caster.GetGUID())),
new TargetPriorityRule((Unit target) => !target.ToUnit().IsFullHealth()),
new TargetPriorityRule((WorldObject target) => target.IsPlayer() || (target.IsCreature() && target.ToCreature().IsTreatedAsRaidUnit())),
new TargetPriorityRule((Unit target) => target.ToUnit().IsInRaidWith(caster))
};
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaAlly));
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy));
}
}
[Script] // 17 - Power Word: Shield
class spell_pri_power_word_shield : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.StrengthOfSoul, SpellIds.StrengthOfSoulEffect, SpellIds.AtonementEffect, SpellIds.TrinityEffect, SpellIds.ShieldDiscipline, SpellIds.ShieldDisciplineEffect, SpellIds.PvpRulesEnabledHardcoded)
&& ValidateSpellEffect((SpellIds.MasteryGrace, 0), (SpellIds.Rapture, 1), (SpellIds.Benevolence, 0), (SpellIds.DivineAegis, 1));
}
void CalculateAmount(AuraEffect auraEffect, ref int amount, ref bool canBeRecalculated)
{
canBeRecalculated = false;
Unit caster = GetCaster();
if (caster != null)
{
float modifiedAmount = caster.SpellBaseDamageBonusDone(GetSpellInfo().GetSchoolMask()) * 3.36f;
Player player = caster.ToPlayer();
if (player != null)
{
MathFunctions.AddPct(ref modifiedAmount, player.GetRatingBonusValue(CombatRating.VersatilityDamageDone));
// Mastery: Grace (Tbd: move into DoEffectCalcDamageAndHealing hook with a new SpellScript and AuraScript).
AuraEffect masteryGraceEffect = caster.GetAuraEffect(SpellIds.MasteryGrace, 0);
if (masteryGraceEffect != null)
if (GetUnitOwner().HasAura(SpellIds.AtonementEffect) || GetUnitOwner().HasAura(SpellIds.TrinityEffect))
MathFunctions.AddPct(ref modifiedAmount, masteryGraceEffect.GetAmount());
switch (player.GetPrimarySpecialization())
{
case ChrSpecialization.PriestDiscipline:
modifiedAmount *= 1.37f;
break;
case ChrSpecialization.PriestShadow:
modifiedAmount *= 1.25f;
if (caster.HasAura(SpellIds.PvpRulesEnabledHardcoded))
modifiedAmount *= 0.8f;
break;
default:
break;
}
}
float critChanceDone = caster.SpellCritChanceDone(null, auraEffect, GetSpellInfo().GetSchoolMask(), GetSpellInfo().GetAttackType());
float critChanceTaken = GetUnitOwner().SpellCritChanceTaken(caster, null, auraEffect, GetSpellInfo().GetSchoolMask(), critChanceDone, GetSpellInfo().GetAttackType());
if (RandomHelper.randChance(critChanceTaken))
{
modifiedAmount *= 2;
// Divine Aegis
AuraEffect divineEff = caster.GetAuraEffect(SpellIds.DivineAegis, 1);
if (divineEff != null)
MathFunctions.AddPct(ref modifiedAmount, divineEff.GetAmount());
}
// Rapture talent (Tbd: move into DoEffectCalcDamageAndHealing hook).
AuraEffect raptureEffect = caster.GetAuraEffect(SpellIds.Rapture, 1);
if (raptureEffect != null)
MathFunctions.AddPct(ref modifiedAmount, raptureEffect.GetAmount());
// Benevolence talent
AuraEffect benevolenceEffect = caster.GetAuraEffect(SpellIds.Benevolence, 0);
if (benevolenceEffect != null)
MathFunctions.AddPct(ref modifiedAmount, benevolenceEffect.GetAmount());
amount = (int)modifiedAmount;
}
}
void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster == null)
return;
// Note: Strength of Soul PvP talent.
if (caster.HasAura(SpellIds.StrengthOfSoul))
caster.CastSpell(GetTarget(), SpellIds.StrengthOfSoulEffect, aurEff);
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
GetTarget().RemoveAura(SpellIds.StrengthOfSoulEffect);
// Note: Shield Discipline talent.
Unit caster = GetCaster();
if (caster != null)
if (GetTargetApplication().GetRemoveMode() == AuraRemoveMode.EnemySpell && caster.HasAura(SpellIds.ShieldDiscipline))
caster.CastSpell(caster, SpellIds.ShieldDisciplineEffect, aurEff);
}
public override void Register()
{
DoEffectCalcAmount.Add(new(CalculateAmount, 0, AuraType.SchoolAbsorb));
AfterEffectApply.Add(new(HandleOnApply, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.RealOrReapplyMask));
AfterEffectRemove.Add(new(HandleOnRemove, 0, AuraType.SchoolAbsorb, AuraEffectHandleModes.Real));
}
}
[Script] // 47515 - Divine Aegis
class spell_pri_divine_aegis : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellEffect((SpellIds.DivineAegisAbsorb, 0));
}
bool CheckProc(ProcEventInfo eventInfo)
{
return eventInfo.GetHealInfo() != null;
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit caster = eventInfo.GetActor();
if (caster == null)
return;
int aegisAmount = (int)MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount());
CastSpellExtraArgs args = new(aurEff);
args.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError);
args.AddSpellMod(SpellValueMod.BasePoint0, aegisAmount);
caster.CastSpell(eventInfo.GetProcTarget(), SpellIds.DivineAegisAbsorb, args);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 129250 - Power Word: Solace
class spell_pri_power_word_solace : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerWordSolaceEnergize);
}
void RestoreMana(uint effIndex)
{
GetCaster().CastSpell(GetCaster(), SpellIds.PowerWordSolaceEnergize,
new CastSpellExtraArgs(TriggerCastFlags.IgnoreCastInProgress).SetTriggeringSpell(GetSpell())
.AddSpellMod(SpellValueMod.BasePoint0, GetEffectValue() / 100));
}
public override void Register()
{
OnEffectLaunch.Add(new(RestoreMana, 1, SpellEffectName.Dummy));
}
}
[Script] // 33076 - Prayer of Mending (Dummy)
class spell_pri_prayer_of_mending_dummy : SpellScript
{
SpellInfo _spellInfoHeal = null;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura, SpellIds.Epiphany, SpellIds.EpiphanyHighlight) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0));
}
public override bool Load()
{
_spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None);
return true;
}
void HandleEffectDummy(uint effIndex)
{
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.
byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1);
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
args.AddSpellMod(SpellValueMod.AuraStack, stackAmount);
// Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate.
SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0);
uint basePoints = (uint)caster.SpellHealingBonusDone(target, _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy);
args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints);
// Note: Focused Mending talent.
args.SetCustomArg(true);
caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args);
// Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers.
caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f);
// Note: Epiphany talent.
if (caster.HasAura(SpellIds.Epiphany))
caster.RemoveAurasDueToSpell(SpellIds.EpiphanyHighlight);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 41635 - Prayer of Mending (Aura)
class spell_pri_prayer_of_mending_aura : AuraScript
{
bool _isEmpoweredByFocusedMending;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingJump)
&& ValidateSpellEffect((SpellIds.SayYourPrayers, 0));
}
void HandleHeal(AuraEffect aurEff, ProcEventInfo eventInfo)
{
// Note: caster is the priest who cast the spell and target is current holder of the aura.
Unit target = GetTarget();
Unit caster = GetCaster();
if (caster != null)
{
CastSpellExtraArgs args = new(aurEff);
args.SetCustomArg(_isEmpoweredByFocusedMending);
caster.CastSpell(target, SpellIds.PrayerOfMendingHeal, args);
// Note: jump is only executed if higher than 1 stack.
int stackAmount = GetStackAmount();
if (stackAmount > 1)
{
args.OriginalCaster = caster.GetGUID();
int newStackAmount = stackAmount - 1;
AuraEffect sayYourPrayers = caster.GetAuraEffect(SpellIds.SayYourPrayers, 0);
if (sayYourPrayers != null)
if (RandomHelper.randChance(sayYourPrayers.GetAmount()))
++newStackAmount;
args.AddSpellMod(SpellValueMod.BasePoint0, newStackAmount);
target.CastSpell(target, SpellIds.PrayerOfMendingJump, args);
}
Remove();
}
}
public override void Register()
{
OnEffectProc.Add(new(HandleHeal, 0, AuraType.Dummy));
}
public void SetEmpoweredByFocusedMending(bool isEmpowered)
{
_isEmpoweredByFocusedMending = isEmpowered;
}
}
[Script]
class spell_pri_prayer_of_mending : SpellScript
{
void HandleEffectDummy(uint effIndex)
{
Aura aura = GetHitAura();
if (aura == null)
return;
spell_pri_prayer_of_mending_aura script = aura.GetScript<spell_pri_prayer_of_mending_aura>();
if (script == null)
return;
if (GetSpell().m_customArg is bool isEmpoweredByFocusedMending)
script.SetEmpoweredByFocusedMending(isEmpoweredByFocusedMending);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.ApplyAura));
}
}
[Script] // 155793 - Prayer of Mending (Jump)
class spell_pri_prayer_of_mending_jump : SpellScript
{
SpellInfo _spellInfoHeal = null;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura)
&& ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0));
}
public override bool Load()
{
_spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None);
return true;
}
void FilterTargets(List<WorldObject> targets)
{
SelectRandomInjuredTargets(targets, 1, true);
}
void HandleJump(uint effIndex)
{
Unit origCaster = GetOriginalCaster();
if (origCaster != null)
{
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
args.AddSpellMod(SpellValueMod.AuraStack, (byte)GetEffectValue());
// Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate.
SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0);
uint basePoints = (uint)origCaster.SpellHealingBonusDone(GetHitUnit(), _spellInfoHeal, healEffectDummy.CalcValue(origCaster), DamageEffectType.Heal, healEffectDummy);
args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints);
// Note: Focused Mending talent.
args.SetCustomArg(false);
origCaster.CastSpell(GetHitUnit(), SpellIds.PrayerOfMendingAura, args);
// Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers.
GetCaster().SendPlaySpellVisual(GetHitUnit(), SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f);
}
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitSrcAreaAlly));
OnEffectHitTarget.Add(new(HandleJump, 0, SpellEffectName.Dummy));
}
}
[Script] // 193063 - Protective Light (Aura)
class spell_pri_protective_light : AuraScript
{
bool CheckEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
return eventInfo.GetProcTarget() == GetCaster();
}
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
GetCaster().CastSpell(GetCaster(), SpellIds.ProtectiveLightAura, aurEff);
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckEffectProc, 0, AuraType.Dummy));
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
[Script] // 405554 - Priest Holy 10.1 Class Set 2pc
class spell_pri_holy_10_1_class_set_2pc : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet2PChooser)
&& ValidateSpellEffect((SpellIds.PrayerOfMending, 0));
}
bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
return RandomHelper.randChance(aurEff.GetAmount());
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
CastSpellExtraArgs args = new(aurEff);
args.SetTriggeringSpell(eventInfo.GetProcSpell());
args.AddSpellMod(SpellValueMod.BasePoint0, Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMending, GetCastDifficulty()).GetEffect(0).CalcValue(GetCaster()));
GetTarget().CastSpell(GetTarget(), SpellIds.Holy10_1_ClassSet2PChooser, args);
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.Dummy));
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 411097 - Priest Holy 10.1 Class Set 2pc (Chooser)
class spell_pri_holy_10_1_class_set_2pc_chooser : SpellScript
{
SpellInfo _spellInfoHeal = null;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0));
}
public override bool Load()
{
_spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None);
return true;
}
void FilterTargets(List<WorldObject> targets)
{
SelectRandomInjuredTargets(targets, 1, true);
}
void HandleEffectDummy(uint effIndex)
{
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.
byte stackAmount = (byte)(target.HasAura(SpellIds.PrayerOfMendingAura, caster.GetGUID()) ? GetEffectValue() : GetEffectValue() + 1);
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
args.AddSpellMod(SpellValueMod.AuraStack, stackAmount);
// Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate.
SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0);
uint basePoints = (uint)caster.SpellHealingBonusDone(target, _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy);
args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints);
// Note: Focused Mending talent.
args.SetCustomArg(true);
caster.CastSpell(target, SpellIds.PrayerOfMendingAura, args);
// Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers.
caster.SendPlaySpellVisual(target, SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f);
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEntry));
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 155793 - Prayer of Mending (Jump)
class spell_pri_holy_10_1_class_set_4pc : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet4P, SpellIds.Holy10_1_ClassSet4PEffect);
}
void HandleEffectDummy(uint effIndex)
{
if (GetOriginalCaster().HasAura(SpellIds.Holy10_1_ClassSet4P))
GetOriginalCaster().CastSpell(GetOriginalCaster(), SpellIds.Holy10_1_ClassSet4PEffect, TriggerCastFlags.IgnoreGCD);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 41635 - Prayer of Mending (Aura)
class spell_pri_holy_10_1_class_set_4pc_aura : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Holy10_1_ClassSet4P, SpellIds.Holy10_1_ClassSet4PEffect);
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire)
return;
if (GetCaster().HasAura(SpellIds.Holy10_1_ClassSet4P))
GetCaster().CastSpell(GetCaster(), SpellIds.Holy10_1_ClassSet4PEffect, new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD).SetTriggeringAura(aurEff));
}
public override void Register()
{
OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
[Script] // 17 - Power Word: Shield
class spell_pri_assured_safety : SpellScript
{
SpellInfo _spellInfoHeal = null;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PrayerOfMendingHeal, SpellIds.PrayerOfMendingAura) && ValidateSpellEffect((SpellIds.PrayerOfMendingHeal, 0), (SpellIds.AssuredSafety, 0));
}
public override bool Load()
{
_spellInfoHeal = Global.SpellMgr.GetSpellInfo(SpellIds.PrayerOfMendingHeal, Difficulty.None);
return GetCaster().HasAura(SpellIds.AssuredSafety);
}
void HandleEffectHitTarget(uint effIndex)
{
Unit caster = GetCaster();
AuraEffect effect = caster.GetAuraEffect(SpellIds.AssuredSafety, 0);
if (effect != null)
{
CastSpellExtraArgs args = new();
args.TriggerFlags = TriggerCastFlags.FullMask;
args.AddSpellMod(SpellValueMod.AuraStack, (byte)effect.GetAmount());
// Note: this line's purpose is to show the correct amount in Points field in SmsgAuraUpdate.
SpellEffectInfo healEffectDummy = _spellInfoHeal.GetEffect(0);
uint basePoints = (uint)caster.SpellHealingBonusDone(GetHitUnit(), _spellInfoHeal, healEffectDummy.CalcValue(caster), DamageEffectType.Heal, healEffectDummy);
args.AddSpellMod(SpellValueMod.BasePoint0, (int)basePoints);
// Note: Focused Mending talent.
args.SetCustomArg(false);
caster.CastSpell(GetHitUnit(), SpellIds.PrayerOfMendingAura, args);
// Note: the visualSender is the priest if it is first cast or the aura holder when the aura triggers.
caster.SendPlaySpellVisual(GetHitUnit(), SpellIds.VisualPriestPrayerOfMending, 0, 0, 40.0f);
}
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.ApplyAura));
}
}
// 204197 - Purge the Wicked
[Script] // Called by Penance - 47540, Dark Reprimand - 400169
class spell_pri_purge_the_wicked : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.PurgeTheWickedDummy);
}
void HandleDummy(uint effIndex)
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
if (target.HasAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID()))
caster.CastSpell(target, SpellIds.PurgeTheWickedDummy, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleDummy, 0, SpellEffectName.Dummy));
}
}
[Script] // 204215 - Purge the Wicked
class spell_pri_purge_the_wicked_dummy : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PurgeTheWickedPeriodic, SpellIds.RevelInPurity)
&& ValidateSpellEffect((SpellIds.RevelInPurity, 1));
}
void FilterTargets(List<WorldObject> targets)
{
Unit caster = GetCaster();
Unit explTarget = GetExplTargetUnit();
targets.RemoveAll(obj =>
{
// 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 = obj.ToUnit();
return target == null || target == explTarget || target.HasBreakableByDamageCrowdControlAura();
});
if (targets.Empty())
return;
// Note: there's no SpellEffectName.Dummy with BasePoints 1 in any of the spells related to use as reference so we hardcode the value.
uint spreadCount = 1;
// Note: we must sort our list of targets whose priority is 1) aura, 2) distance, and 3) duration.
targets.Sort((WorldObject lhs, WorldObject rhs) =>
{
Unit targetA = lhs.ToUnit();
Unit targetB = rhs.ToUnit();
Aura auraA = targetA.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID());
Aura auraB = targetB.GetAura(SpellIds.PurgeTheWickedPeriodic, caster.GetGUID());
if (auraA == null)
{
if (auraB != null)
return 1;
return explTarget.GetExactDist(targetA).CompareTo(explTarget.GetExactDist(targetB));
}
if (auraB == null)
return -1;
return auraA.GetDuration().CompareTo(auraB.GetDuration());
});
// Note: Revel in Purity talent.
if (caster.HasAura(SpellIds.RevelInPurity))
spreadCount += (uint)Global.SpellMgr.GetSpellInfo(SpellIds.RevelInPurity, Difficulty.None).GetEffect(1).CalcValue(GetCaster());
if (targets.Count > spreadCount)
targets.Resize(spreadCount);
}
void HandleDummy(uint effIndex)
{
Unit caster = GetCaster();
Unit target = GetHitUnit();
caster.CastSpell(target, SpellIds.PurgeTheWickedPeriodic, TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress);
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 1, Targets.UnitDestAreaEnemy));
OnEffectHitTarget.Add(new(HandleDummy, 1, SpellEffectName.Dummy));
}
}
[Script] // 390622 - Rhapsody
class spell_pri_rhapsody : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.RhapsodyProc);
}
void HandlePeriodic(AuraEffect aurEff)
{
Unit target = GetTarget();
Aura rhapsodyStack = target.GetAura(SpellIds.RhapsodyProc, GetCasterGUID());
if (rhapsodyStack != null)
rhapsodyStack.ModStackAmount(1);
else
target.CastSpell(target, SpellIds.RhapsodyProc,
new CastSpellExtraArgs(aurEff).SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError));
}
public override void Register()
{
OnEffectPeriodic.Add(new(HandlePeriodic, 0, AuraType.PeriodicDummy));
}
}
[Script] // 390636 - Rhapsody
class spell_pri_rhapsody_proc : AuraScript
{
void PreventChargeDrop(ProcEventInfo eventInfo)
{
PreventDefaultAction();
}
void RemoveAura(ProcEventInfo eventInfo)
{
// delay charge drop to allow spellmod to be applied to both damaging and healing spells
GetAura().DropChargeDelayed(1);
}
public override void Register()
{
DoPrepareProc.Add(new(PreventChargeDrop));
AfterProc.Add(new(RemoveAura));
}
}
[Script] // 47536 - Rapture
class spell_pri_rapture : SpellScript
{
ObjectGuid _raptureTarget;
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerWordShield);
}
void HandleEffectDummy(uint effIndex)
{
_raptureTarget = GetHitUnit().GetGUID();
}
void HandleAfterCast()
{
Unit caster = GetCaster();
Unit target = Global.ObjAccessor.GetUnit(caster, _raptureTarget);
if (target != null)
caster.CastSpell(target, SpellIds.PowerWordShield,
new CastSpellExtraArgs(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress)
.SetTriggeringSpell(GetSpell()));
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectDummy, 0, SpellEffectName.Dummy));
AfterCast.Add(new(HandleAfterCast));
}
}
[Script] // 8092 - Mind Blast
class spell_pri_schism : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Schism, SpellIds.SchismAura);
}
void HandleEffectHitTarget(uint effIndex)
{
if (GetCaster().HasAura(SpellIds.Schism))
GetCaster().CastSpell(GetHitUnit(), SpellIds.SchismAura, true);
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.SchoolDamage));
}
}
[Script] // 208771 - Sanctuary (Absorb)
class spell_pri_sanctuary_absorb : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.SanctuaryAura);
}
void CalcAbsorbAmount(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
{
PreventDefaultAction();
Unit attacker = dmgInfo.GetAttacker();
if (attacker == null)
return;
AuraEffect amountHolderEffect = attacker.GetAuraEffect(SpellIds.SanctuaryAura, 0, GetCasterGUID());
if (amountHolderEffect == null)
return;
if (dmgInfo.GetDamage() >= amountHolderEffect.GetAmount())
{
amountHolderEffect.GetBase().Remove(AuraRemoveMode.EnemySpell);
dmgInfo.AbsorbDamage((uint)amountHolderEffect.GetAmount());
}
else
{
amountHolderEffect.ChangeAmount(amountHolderEffect.GetAmount() - (int)dmgInfo.GetDamage());
dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
}
}
public override void Register()
{
OnEffectAbsorb.Add(new(CalcAbsorbAmount, 0));
}
}
[Script] // Smite - 585
class spell_pri_sanctuary_trigger : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Sanctuary, SpellIds.SanctuaryAura, SpellIds.SanctuaryAbsorb);
}
void HandleEffectHit(uint effIndex)
{
Player caster = GetCaster()?.ToPlayer();
if (caster == null)
return;
AuraEffect sanctuaryEffect = caster.GetAuraEffect(SpellIds.Sanctuary, 0);
if (sanctuaryEffect != null)
{
Unit target = GetHitUnit();
if (target != null)
{
float absorbAmount = MathFunctions.CalculatePct(caster.SpellBaseDamageBonusDone(SpellSchoolMask.Shadow), sanctuaryEffect.GetAmount());
MathFunctions.AddPct(ref absorbAmount, caster.GetRatingBonusValue(CombatRating.VersatilityDamageDone));
caster.CastSpell(caster, SpellIds.SanctuaryAbsorb, new CastSpellExtraArgs()
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)
.SetTriggeringSpell(GetSpell()));
caster.CastSpell(target, SpellIds.SanctuaryAura, new CastSpellExtraArgs()
.AddSpellMod(SpellValueMod.BasePoint0, (int)absorbAmount)
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)
.SetTriggeringSpell(GetSpell()));
}
}
}
public override void Register()
{
OnEffectHitTarget.Add(new(HandleEffectHit, 0, SpellEffectName.SchoolDamage));
}
}
[Script] // 280391 - Sins of the Many
class spell_pri_sins_of_the_many : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.SinsOfTheMany);
}
void HandleOnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
{
GetTarget().CastSpell(GetTarget(), SpellIds.SinsOfTheMany, true);
}
void HandleOnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
{
GetTarget().RemoveAura(SpellIds.SinsOfTheMany);
}
public override void Register()
{
OnEffectApply.Add(new(HandleOnApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
OnEffectRemove.Add(new(HandleOnRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
}
}
[Script] // 20711 - Spirit of Redemption
class spell_pri_spirit_of_redemption : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.SpiritOfRedemption);
}
void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
{
Unit target = GetTarget();
target.CastSpell(target, SpellIds.SpiritOfRedemption, aurEff);
target.SetFullHealth();
}
public override void Register()
{
OnEffectAbsorb.Add(new(HandleAbsorb, 0));
}
}
// 34433 - Shadowfiend
// 123040 - Mindbender (Discipline)
[Script] // 451235 - Voidwrath
class spell_pri_shadow_covenant : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ShadowCovenant, SpellIds.ShadowCovenantEffect);
}
public override bool Load()
{
return GetCaster().HasAura(SpellIds.ShadowCovenant);
}
void HandleAfterCast()
{
GetCaster().CastSpell(GetCaster(), SpellIds.ShadowCovenantEffect, new CastSpellExtraArgs()
{
TriggerFlags = TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError,
TriggeringSpell = GetSpell()
});
}
public override void Register()
{
AfterCast.Add(new(HandleAfterCast));
}
}
[Script] // 186263 - Shadow Mend
class spell_pri_shadow_mend : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Atonement, SpellIds.AtonementEffect, SpellIds.Trinity, SpellIds.MasochismTalent, SpellIds.MasochismPeriodicHeal, SpellIds.ShadowMendPeriodicDummy);
}
void HandleEffectHit()
{
Unit target = GetHitUnit();
if (target != null)
{
Unit caster = GetCaster();
int periodicAmount = GetHitHeal() / 20;
int damageForAuraRemoveAmount = periodicAmount * 10;
// Handle Masochism talent
if (caster.HasAura(SpellIds.MasochismTalent) && caster.GetGUID() == target.GetGUID())
caster.CastSpell(caster, SpellIds.MasochismPeriodicHeal, new CastSpellExtraArgs(GetSpell()).AddSpellMod(SpellValueMod.BasePoint0, periodicAmount));
else if (target.IsInCombat() && periodicAmount != 0)
{
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
args.SetTriggeringSpell(GetSpell());
args.AddSpellMod(SpellValueMod.BasePoint0, periodicAmount);
args.AddSpellMod(SpellValueMod.BasePoint1, damageForAuraRemoveAmount);
caster.CastSpell(target, SpellIds.ShadowMendPeriodicDummy, args);
}
}
}
public override void Register()
{
AfterHit.Add(new(HandleEffectHit));
}
}
[Script] // 187464 - Shadow Mend (Damage)
class spell_pri_shadow_mend_periodic_damage : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ShadowMendDamage);
}
void HandleDummyTick(AuraEffect aurEff)
{
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
args.SetOriginalCaster(GetCasterGUID());
args.SetTriggeringAura(aurEff);
args.AddSpellMod(SpellValueMod.BasePoint0, aurEff.GetAmount());
GetTarget().CastSpell(GetTarget(), SpellIds.ShadowMendDamage, args);
}
bool CheckProc(ProcEventInfo eventInfo)
{
return eventInfo.GetDamageInfo() != null;
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
int newAmount = aurEff.GetAmount() - (int)eventInfo.GetDamageInfo().GetDamage();
aurEff.ChangeAmount(newAmount);
if (newAmount < 0)
Remove();
}
public override void Register()
{
OnEffectPeriodic.Add(new(HandleDummyTick, 0, AuraType.PeriodicDummy));
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleProc, 1, AuraType.Dummy));
}
}
[Script] // 32379 - Shadow Word: Death
class spell_pri_shadow_word_death : SpellScript
{
static TimeSpan BacklashDelay = TimeSpan.FromSeconds(1);
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ShadowWordDeathDamage)
&& ValidateSpellEffect((spellInfo.Id, 5))
&& spellInfo.GetEffect(2).IsEffect(SpellEffectName.Dummy)
&& spellInfo.GetEffect(3).IsEffect(SpellEffectName.ScriptEffect)
&& spellInfo.GetEffect(5).IsEffect(SpellEffectName.Dummy);
}
void HandleDamageCalculation(SpellEffectInfo spellEffectInfo, Unit victim, ref int damage, ref int flatMod, ref float pctMod)
{
if (victim.HealthBelowPct(GetEffectInfo(2).CalcValue(GetCaster())))
MathFunctions.AddPct(ref pctMod, GetEffectInfo(3).CalcValue(GetCaster()));
}
void DetermineKillStatus(DamageInfo damageInfo, ref uint resistAmount, ref int absorbAmount)
{
bool killed = damageInfo.GetDamage() >= damageInfo.GetVictim().GetHealth();
if (!killed)
{
Unit caster = GetCaster();
int backlashDamage = (int)caster.CountPctFromMaxHealth(GetEffectInfo(5).CalcValue(caster));
var originalCastId = GetSpell().m_castId;
caster.m_Events.AddEventAtOffset(() =>
{
caster.CastSpell(caster, SpellIds.ShadowWordDeathDamage, new CastSpellExtraArgs()
.SetTriggerFlags(TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.DontReportCastError)
.SetOriginalCastId(originalCastId)
.AddSpellMod(SpellValueMod.BasePoint0, backlashDamage));
}, BacklashDelay);
}
}
public override void Register()
{
CalcDamage.Add(new(HandleDamageCalculation));
// abuse OnCalculateResistAbsorb to determine if this spell will kill target or not (its still not perfect - happens before absorbs are applied)
OnCalculateResistAbsorb.Add(new(DetermineKillStatus));
}
}
[Script] // 109186 - Surge of Light
class spell_pri_surge_of_light : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.Smite, SpellIds.SurgeOfLightEffect);
}
bool CheckProc(ProcEventInfo eventInfo)
{
if (eventInfo.GetSpellInfo().Id == SpellIds.Smite)
return true;
if (eventInfo.GetSpellInfo().SpellFamilyName == SpellFamilyNames.Priest)
return eventInfo.GetHealInfo() != null;
return false;
}
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
if (RandomHelper.randChance(aurEff.GetAmount()))
GetTarget().CastSpell(GetTarget(), SpellIds.SurgeOfLightEffect, aurEff);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
[Script] // 28809 - Greater Heal
class spell_pri_t3_4p_bonus : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ArmorOfFaith);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
eventInfo.GetActor().CastSpell(eventInfo.GetProcTarget(), SpellIds.ArmorOfFaith, aurEff);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 37594 - Greater Heal Refund
class spell_pri_t5_heal_2p_bonus : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ItemEfficiency);
}
bool CheckProc(ProcEventInfo eventInfo)
{
HealInfo healInfo = eventInfo.GetHealInfo();
if (healInfo != null)
{
Unit healTarget = healInfo.GetTarget();
if (healTarget != null && healInfo.GetEffectiveHeal() != 0)
if (healTarget.GetHealth() >= healTarget.GetMaxHealth())
return true;
}
return false;
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
GetTarget().CastSpell(GetTarget(), SpellIds.ItemEfficiency, aurEff);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleProc, 0, AuraType.ProcTriggerSpell));
}
}
[Script] // 70770 - Item - Priest T10 Healer 2P Bonus
class spell_pri_t10_heal_2p_bonus : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.BlessedHealing);
}
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
HealInfo healInfo = eventInfo.GetHealInfo();
if (healInfo == null || healInfo.GetHeal() == 0)
return;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.BlessedHealing, GetCastDifficulty());
int amount = MathFunctions.CalculatePct((int)(healInfo.GetHeal()), aurEff.GetAmount());
Cypher.Assert(spellInfo.GetMaxTicks() > 0);
amount /= (int)spellInfo.GetMaxTicks();
Unit caster = eventInfo.GetActor();
Unit target = eventInfo.GetProcTarget();
CastSpellExtraArgs args = new(aurEff);
args.AddSpellMod(SpellValueMod.BasePoint0, amount);
caster.CastSpell(target, SpellIds.BlessedHealing, args);
}
public override void Register()
{
OnEffectProc.Add(new(HandleProc, 0, AuraType.Dummy));
}
}
[Script] // 200128 - Trail of Light
class spell_pri_trail_of_light : AuraScript
{
Queue<ObjectGuid> _healQueue = new();
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.TrailOfLightHeal);
}
bool CheckProc(ProcEventInfo eventInfo)
{
if (_healQueue.Count == 0 || _healQueue.Last() != eventInfo.GetActionTarget().GetGUID())
_healQueue.Enqueue(eventInfo.GetActionTarget().GetGUID());
if (_healQueue.Count > 2)
_healQueue.Dequeue();
if (_healQueue.Count == 2)
return true;
return false;
}
void HandleOnProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
Unit caster = GetTarget();
Unit oldTarget = Global.ObjAccessor.GetUnit(caster, _healQueue.Peek());
if (oldTarget == null)
return;
// Note: old target may not be friendly anymore due to charm and faction change effects.
if (!caster.IsValidAssistTarget(oldTarget))
return;
SpellInfo healSpellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.TrailOfLightHeal, Difficulty.None);
if (healSpellInfo == null)
return;
// Note: distance may be greater than the heal's spell range.
if (!caster.IsWithinDist(oldTarget, healSpellInfo.GetMaxRange(true, caster)))
return;
uint healAmount = MathFunctions.CalculatePct(eventInfo.GetHealInfo().GetHeal(), aurEff.GetAmount());
caster.CastSpell(oldTarget, SpellIds.TrailOfLightHeal, new CastSpellExtraArgs(aurEff).AddSpellMod(SpellValueMod.BasePoint0, (int)healAmount));
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleOnProc, 0, AuraType.Dummy));
}
}
// 390693 - Train of Thought
[Script] // Called by Flash Heal, Renew, Smite
class spell_pri_train_of_thought : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.PowerWordShield, SpellIds.Penance);
}
bool CheckEffect0(AuraEffect aurEff, ProcEventInfo eventInfo)
{
// Renew & Flash Heal
return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x840));
}
bool Check1(AuraEffect aurEff, ProcEventInfo eventInfo)
{
// Smite
return eventInfo.GetSpellInfo().IsAffected(SpellFamilyNames.Priest, new FlagArray128(0x80));
}
void ReducePowerWordShieldCooldown(AuraEffect aurEff, ProcEventInfo eventInfo)
{
GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.PowerWordShield, TimeSpan.FromSeconds(aurEff.GetAmount()));
}
void ReducePenanceCooldown(AuraEffect aurEff, ProcEventInfo eventInfo)
{
GetTarget().GetSpellHistory().ModifyCooldown(SpellIds.Penance, TimeSpan.FromSeconds(aurEff.GetAmount()));
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckEffect0, 0, AuraType.Dummy));
OnEffectProc.Add(new(ReducePowerWordShieldCooldown, 0, AuraType.Dummy));
DoCheckEffectProc.Add(new(Check1, 1, AuraType.Dummy));
OnEffectProc.Add(new(ReducePenanceCooldown, 1, AuraType.Dummy));
}
}
// 109142 - Twist of Fate (Shadow)
[Script] // 265259 - Twist of Fate (Discipline)
class spell_pri_twist_of_fate : AuraScript
{
bool CheckProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
return eventInfo.GetProcTarget().GetHealthPct() < aurEff.GetAmount();
}
public override void Register()
{
DoCheckEffectProc.Add(new(CheckProc, 0, AuraType.ProcTriggerSpell));
}
}
// 341273 - Unfurling Darkness
[Script] // Triggered by 34914 - Vampiric Touch
class spell_pri_unfurling_darkness : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.UnfurlingDarkness, SpellIds.UnfurlingDarknessDebuff)
&& ValidateSpellEffect((SpellIds.UnfurlingDarknessAura, 0));
}
void PreventDirectDamage(ref WorldObject target)
{
bool canTriggerDirectDamage()
{
if (!GetSpell().m_originalCastId.IsEmpty())
return false; // not when triggered by Shadow Crash (Whispering Shadows talent)
AuraEffect unfurlingDarkness = GetCaster().GetAuraEffect(SpellIds.UnfurlingDarknessAura, 0);
if (unfurlingDarkness != null)
if (GetSpell().m_appliedMods.Contains(unfurlingDarkness.GetBase()))
return true;
return false;
}
;
if (!canTriggerDirectDamage())
target = null;
}
void TriggerUnfurlingDarkness()
{
if (!GetSpell().m_originalCastId.IsEmpty())
return; // not when triggered by Shadow Crash (Whispering Shadows talent)
Unit caster = GetCaster();
AuraEffect unfurlingDarkness = GetCaster().GetAuraEffect(SpellIds.UnfurlingDarknessAura, 0);
if (unfurlingDarkness != null)
{
if (GetSpell().m_appliedMods.Contains(unfurlingDarkness.GetBase()))
{
unfurlingDarkness.GetBase().Remove();
return;
}
}
if (!caster.HasAura(SpellIds.UnfurlingDarknessDebuff))
caster.CastSpell(caster, SpellIds.UnfurlingDarknessAura, true);
}
public override void Register()
{
OnObjectTargetSelect.Add(new(PreventDirectDamage, 3, Targets.UnitTargetEnemy));
AfterCast.Add(new(TriggerUnfurlingDarkness));
}
}
[Script] // 15286 - Vampiric Embrace
class spell_pri_vampiric_embrace : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.VampiricEmbraceHeal);
}
bool CheckProc(ProcEventInfo eventInfo)
{
// Not proc from Mind Sear
return (eventInfo.GetDamageInfo().GetSpellInfo().SpellFamilyFlags[1] & 0x80000) == 0;
}
void HandleEffectProc(AuraEffect aurEff, ProcEventInfo eventInfo)
{
PreventDefaultAction();
DamageInfo damageInfo = eventInfo.GetDamageInfo();
if (damageInfo == null || damageInfo.GetDamage() == 0)
return;
int selfHeal = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), aurEff.GetAmount());
int teamHeal = selfHeal / 2;
CastSpellExtraArgs args = new(aurEff);
args.AddSpellMod(SpellValueMod.BasePoint0, teamHeal);
args.AddSpellMod(SpellValueMod.BasePoint1, selfHeal);
GetTarget().CastSpell(null, SpellIds.VampiricEmbraceHeal, args);
}
public override void Register()
{
DoCheckProc.Add(new(CheckProc));
OnEffectProc.Add(new(HandleEffectProc, 0, AuraType.Dummy));
}
}
[Script] // 15290 - Vampiric Embrace (heal)
class spell_pri_vampiric_embrace_target : SpellScript
{
void FilterTargets(List<WorldObject> unitList)
{
unitList.Remove(GetCaster());
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitCasterAreaParty));
}
}
[Script] // 34914 - Vampiric Touch
class spell_pri_vampiric_touch : AuraScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.SinAndPunishment, SpellIds.ShadowWordPain);
}
void HandleDispel(DispelInfo dispelInfo)
{
Unit caster = GetCaster();
if (caster != null)
caster.CastSpell(dispelInfo.GetDispeller(), SpellIds.SinAndPunishment, true);
}
void HandleApplyEffect(AuraEffect aurEff, AuraEffectHandleModes mode)
{
Unit caster = GetCaster();
if (caster != null)
if (caster.HasAura(SpellIds.Misery))
caster.CastSpell(GetTarget(), SpellIds.ShadowWordPain, true);
}
public override void Register()
{
AfterDispel.Add(new(HandleDispel));
OnEffectApply.Add(new(HandleApplyEffect, 0, AuraType.Dummy, AuraEffectHandleModes.RealOrReapplyMask));
}
}
[Script] // 205385 - Shadow Crash
class spell_pri_whispering_shadows : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.WhisperingShadows);
}
void HandleEffectHitTarget(uint effIndex)
{
if (!GetCaster().HasAura(SpellIds.WhisperingShadows))
PreventHitDefaultEffect(effIndex);
}
public override void Register()
{
OnEffectHit.Add(new(HandleEffectHitTarget, 2, SpellEffectName.TriggerMissile));
}
}
[Script] // 391286 - Whispering Shadows (Dot Application)
class spell_pri_whispering_shadows_effect : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.VampiricTouch);
}
void FilterTargets(List<WorldObject> targets)
{
if (targets.Count <= GetSpellValue().MaxAffectedTargets)
return;
Aura getVampiricTouch(WorldObject target)
{
return target.ToUnit().GetAura(SpellIds.VampiricTouch, GetCaster().GetGUID());
}
// prioritize targets without Vampiric Touch
targets.Sort((target1, target2) =>
{
int duration1 = 0;
Aura aura1 = getVampiricTouch(target1);
if (aura1 != null)
duration1 = aura1.GetDuration();
int duration2 = 0;
Aura aura2 = getVampiricTouch(target2);
if (aura2 != null)
duration2 = aura2.GetDuration();
return duration1.CompareTo(duration2);
});
// remove targets that definitely will not get Vampiric Touch applied (excess targets with longest remaining duration)
while (targets.Count > GetSpellValue().MaxAffectedTargets && getVampiricTouch(targets.Last()) != null)
targets.RemoveAt(targets.Count - 1);
targets.RandomResize(GetSpellValue().MaxAffectedTargets);
}
void HandleEffectHitTarget(uint effIndex)
{
GetCaster().CastSpell(GetHitUnit(), SpellIds.VampiricTouch, new CastSpellExtraArgs()
.SetTriggeringSpell(GetSpell())
.SetTriggerFlags(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreSpellAndCategoryCD | TriggerCastFlags.IgnorePowerCost | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.IgnoreCastTime | TriggerCastFlags.DontReportCastError));
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new(FilterTargets, 0, Targets.UnitDestAreaEnemy));
OnEffectHitTarget.Add(new(HandleEffectHitTarget, 0, SpellEffectName.Dummy));
}
}