From 7fadeb1141c48d552afd7c3bb40ef4b527272fa3 Mon Sep 17 00:00:00 2001 From: blinkysc <37940565+blinkysc@users.noreply.github.com> Date: Sun, 22 Feb 2026 11:06:47 -0600 Subject: [PATCH] fix(Core/Spells): Beacon of Light no longer copies target healing modifiers (#24796) Co-authored-by: blinkysc --- src/server/game/Entities/Unit/Unit.h | 9 ++++++++- src/server/game/Spells/Spell.cpp | 15 +++++++++++++++ src/server/game/Spells/Spell.h | 2 ++ src/server/game/Spells/SpellEffects.cpp | 4 ++++ src/server/scripts/Spells/spell_paladin.cpp | 5 ++++- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 96e99ab98..6be903f8b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -386,6 +386,7 @@ private: Unit* const m_healer; Unit* const m_target; uint32 m_heal; + uint32 m_healBeforeTakenMods; uint32 m_effectiveHeal; uint32 m_absorb; SpellInfo const* const m_spellInfo; @@ -393,7 +394,7 @@ private: uint32 m_hitMask; public: explicit HealInfo(Unit* _healer, Unit* _target, uint32 _heal, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask) - : m_healer(_healer), m_target(_target), m_heal(_heal), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask), m_hitMask(0) + : m_healer(_healer), m_target(_target), m_heal(_heal), m_healBeforeTakenMods(0), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask), m_hitMask(0) { m_absorb = 0; m_effectiveHeal = 0; @@ -414,6 +415,11 @@ public: m_heal = amount; } + void SetHealBeforeTakenMods(uint32 amount) + { + m_healBeforeTakenMods = amount; + } + void SetEffectiveHeal(uint32 amount) { m_effectiveHeal = amount; @@ -422,6 +428,7 @@ public: [[nodiscard]] Unit* GetHealer() const { return m_healer; } [[nodiscard]] Unit* GetTarget() const { return m_target; } [[nodiscard]] uint32 GetHeal() const { return m_heal; } + [[nodiscard]] uint32 GetHealBeforeTakenMods() const { return m_healBeforeTakenMods; } [[nodiscard]] uint32 GetEffectiveHeal() const { return m_effectiveHeal; } [[nodiscard]] uint32 GetAbsorb() const { return m_absorb; } [[nodiscard]] SpellInfo const* GetSpellInfo() const { return m_spellInfo; }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e8fe0a346..fb9b33958 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -649,6 +649,7 @@ Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, m_diminishGroup = DIMINISHING_NONE; m_damage = 0; m_healing = 0; + m_damageBeforeTakenMods = 0; m_procAttacker = 0; m_procVictim = 0; m_procEx = 0; @@ -2337,6 +2338,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= targetInfo.processed = false; // Effects not apply on target targetInfo.alive = target->IsAlive(); targetInfo.damage = 0; + targetInfo.damageBeforeTakenMods = 0; targetInfo.crit = false; targetInfo.scaleAura = false; if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask && m_caster != target) @@ -2712,6 +2714,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask()); + // Heal amount before SpellHealingBonusTaken, used by Beacon of Light + if (target->damageBeforeTakenMods != 0) + { + uint32 healBeforeTakenMods = uint32(-target->damageBeforeTakenMods); + if (crit) + healBeforeTakenMods = Unit::SpellCriticalHealingBonus(caster, m_spellInfo, healBeforeTakenMods, nullptr); + healInfo.SetHealBeforeTakenMods(healBeforeTakenMods); + } + else + healInfo.SetHealBeforeTakenMods(addhealth); + // Set hitMask based on crit if (crit) healInfo.AddHitMask(PROC_HIT_CRITICAL); @@ -8297,6 +8310,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) { m_damage = 0; m_healing = 0; + m_damageBeforeTakenMods = 0; HandleEffects(unit, nullptr, nullptr, i, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); @@ -8322,6 +8336,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) m_damageMultipliers[i] *= multiplier[i]; } targetInfo.damage += m_damage; + targetInfo.damageBeforeTakenMods += m_damageBeforeTakenMods; } } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index ea9fe3630..cb3f89540 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -273,6 +273,7 @@ struct TargetInfo bool crit:1; bool scaleAura:1; int32 damage; + int32 damageBeforeTakenMods; }; static const uint32 SPELL_INTERRUPT_NONPLAYER = 32747; @@ -683,6 +684,7 @@ public: // Damage and healing in effects need just calculate int32 m_damage; // Damge in effects count here int32 m_healing; // Healing in effects count here + int32 m_damageBeforeTakenMods; // ****************************************** // Spell trigger system diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5aff04864..730dc9859 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1557,11 +1557,13 @@ void Spell::EffectHeal(SpellEffIndex effIndex) else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000) { addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, int32(caster->CountPctFromMaxHealth(damage)), HEAL, effIndex); + m_damageBeforeTakenMods -= addhealth; addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL); } else if (m_spellInfo->Id != 33778) // not lifebloom { addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL, effIndex); + m_damageBeforeTakenMods -= addhealth; addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL); } @@ -1593,6 +1595,7 @@ void Spell::EffectHealPct(SpellEffIndex effIndex) return; uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL, effIndex); + m_damageBeforeTakenMods -= heal; heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL); m_damage -= heal; @@ -1611,6 +1614,7 @@ void Spell::EffectHealMechanical(SpellEffIndex effIndex) return; uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL, effIndex); + m_damageBeforeTakenMods -= heal; m_damage -= unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 163899a46..0e5f3b48a 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -2148,7 +2148,10 @@ class spell_pal_light_s_beacon : public AuraScript // Holy Light heals for 100%, Flash of Light heals for 50% uint32 healSpellId = procSpell->IsRankOf(sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_LIGHT_R1)) ? SPELL_PALADIN_BEACON_OF_LIGHT_FLASH : SPELL_PALADIN_BEACON_OF_LIGHT_HOLY; - int32 heal = CalculatePct(healInfo->GetHeal(), aurEff->GetAmount()); + + // Use heal amount before target-specific modifiers to avoid copying them + uint32 healAmount = healInfo->GetHealBeforeTakenMods(); + int32 heal = CalculatePct(healAmount, aurEff->GetAmount()); Unit* beaconTarget = GetCaster(); if (!beaconTarget || !beaconTarget->HasAura(SPELL_PALADIN_BEACON_OF_LIGHT_AURA, eventInfo.GetActor()->GetGUID()))