diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 618178822..09d231017 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -180,6 +180,7 @@ enum PriestSpells SPELL_PRIEST_PENANCE_DAMAGE = 47666, SPELL_PRIEST_PENANCE_HEALING = 47750, SPELL_PRIEST_PHANTOM_REACH = 459559, + SPELL_PRIEST_PSYCHIC_LINK = 199484, SPELL_PRIEST_POWER_LEECH_MINDBENDER_MANA = 123051, SPELL_PRIEST_POWER_LEECH_MINDBENDER_INSANITY = 200010, SPELL_PRIEST_POWER_LEECH_SHADOWFIEND_MANA = 343727, @@ -5304,6 +5305,101 @@ class spell_pri_tentacle_slam : public SpellScript } }; +// 199484 - Psychic Link +// Direct damage spells also inflict $s1% of that damage on every other target that is affected by +// the caster's Vampiric Touch. The talent itself is a dummy aura, so the copy is driven by its proc. +class spell_pri_psychic_link : public AuraScript +{ + // The radius is read by the client from 199486 ($199486A2) which exposes no radius field here, + // so the retail value is used instead + static constexpr float PSYCHIC_LINK_RADIUS = 10.0f; + + // Copied damage is dealt with the triggering spell, which runs procs again. Without this the + // passive would keep copying the copy, so nested calls are rejected while a copy is in flight + bool _processing = false; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo + ({ + SPELL_PRIEST_VAMPIRIC_TOUCH, + SPELL_PRIEST_SHADOW_WORD_PAIN, + SPELL_PRIEST_SHADOWY_APPARITION_MISSILE + }); + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (_processing) + return false; + + SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); + if (!spellInfo) + return false; + + // Only direct damage is copied, never the periodic ticks + if (eventInfo.GetDamageInfo()->GetDamageType() != DIRECT_DAMAGE) + return false; + + // The talent explicitly does not copy damage from these spells + switch (spellInfo->Id) + { + case SPELL_PRIEST_SHADOW_WORD_PAIN: + case SPELL_PRIEST_VAMPIRIC_TOUCH: + case SPELL_PRIEST_SHADOWY_APPARITION_MISSILE: + return false; + default: + break; + } + + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + DamageInfo* damageInfo = eventInfo.GetDamageInfo(); + SpellInfo const* spellInfo = eventInfo.GetSpellInfo(); + if (!damageInfo || !spellInfo || !damageInfo->GetDamage()) + return; + + SpellEffectValue const damage = CalculatePct(damageInfo->GetDamage(), aurEff->GetAmount()); + if (damage <= 0) + return; + + Unit* triggerTarget = damageInfo->GetVictim(); + SpellSchoolMask const schoolMask = damageInfo->GetSchoolMask(); + + // Every other enemy around the caster that carries the caster's own Vampiric Touch + std::list targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck check(caster, caster, PSYCHIC_LINK_RADIUS); + Trinity::UnitListSearcher searcher(caster, targets, check); + Cell::VisitAllObjects(caster, searcher, PSYCHIC_LINK_RADIUS); + + for (Unit* target : targets) + { + if (target == triggerTarget) + continue; + + if (!target->HasAura(SPELL_PRIEST_VAMPIRIC_TOUCH, caster->GetGUID())) + continue; + + _processing = true; + caster->DealDamage(caster, target, uint32(damage), nullptr, DIRECT_DAMAGE, schoolMask, spellInfo); + _processing = false; + } + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_pri_psychic_link::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_psychic_link::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } +}; + //WowCommunity // 1253590 - Master the Darkness class spell_pri_master_the_darkness : public AuraScript @@ -5633,6 +5729,7 @@ void AddSC_priest_spell_scripts() //WowCommunity RegisterSpellScript(spell_pri_master_the_darkness); RegisterSpellScript(spell_pri_tentacle_slam); + RegisterSpellScript(spell_pri_psychic_link); RegisterSpellScript(spell_pri_idol_of_cthun); RegisterSpellScript(spell_pri_idol_of_cthun_trigger); RegisterSpellScript(spell_pri_idol_of_cthun_periodic_aura);