Core/Spells: Only check spell immunity against effects that will apply to each target

This commit is contained in:
Shauren
2025-12-25 16:48:32 +01:00
parent 42ebe3b0dc
commit 6cff1622e5
7 changed files with 36 additions and 23 deletions

View File

@@ -2434,7 +2434,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
// Calculate hit result
WorldObject* caster = m_originalCaster ? m_originalCaster : m_caster;
targetInfo.MissCondition = caster->SpellHitResult(target, m_spellInfo, m_canReflect && !(IsPositive() && m_caster->IsFriendlyTo(target)));
targetInfo.MissCondition = caster->SpellHitResult(target, m_spellInfo,
m_canReflect && !(IsPositive() && m_caster->IsFriendlyTo(target)),
false /*immunity will be checked after complete EffectMask is known*/);
// Spell have speed - need calculate incoming time
// Incoming time is zero for self casts. At least I think so.
@@ -2479,7 +2481,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
{
// Calculate reflected spell result on caster (shouldn't be able to reflect gameobject spells)
Unit* unitCaster = ASSERT_NOTNULL(m_caster->ToUnit());
targetInfo.ReflectResult = unitCaster->SpellHitResult(unitCaster, m_spellInfo, false); // can't reflect twice
targetInfo.ReflectResult = unitCaster->SpellHitResult(unitCaster, m_spellInfo,
false /*can't reflect twice*/,
false /*immunity will be checked after complete EffectMask is known*/);
// Proc spell reflect aura when missile hits the original target
target->m_Events.AddEvent(new ProcReflectDelayed(target, m_originalCasterGUID), target->m_Events.CalculateTime(Milliseconds(targetInfo.TimeDelay)));
@@ -3099,7 +3103,7 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo)
return SPELL_MISS_EVADE;
// For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
if (hitInfo.TimeDelay && unit->IsImmunedToSpell(m_spellInfo, m_caster))
if (hitInfo.TimeDelay && unit->IsImmunedToSpell(m_spellInfo, hitInfo.EffectMask, m_caster))
return SPELL_MISS_IMMUNE;
CallScriptBeforeHitHandlers(hitInfo.MissCondition);
@@ -8612,6 +8616,10 @@ void Spell::PreprocessSpellLaunch(TargetInfo& targetInfo)
if (!targetUnit)
return;
// Check immunity now that EffectMask is known
if (targetUnit->IsImmunedToSpell(GetSpellInfo(), targetInfo.EffectMask, m_caster))
targetInfo.MissCondition = SPELL_MISS_IMMUNE;
// This will only cause combat - the target will engage once the projectile hits (in Spell::TargetInfo::PreprocessTarget)
if (m_originalCaster && targetInfo.MissCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(targetUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || targetUnit->IsEngaged()))
m_originalCaster->SetInCombatWith(targetUnit, true);
@@ -8622,7 +8630,11 @@ void Spell::PreprocessSpellLaunch(TargetInfo& targetInfo)
unit = targetUnit;
// In case spell reflect from target, do all effect on caster (if hit)
else if (targetInfo.MissCondition == SPELL_MISS_REFLECT && targetInfo.ReflectResult == SPELL_MISS_NONE)
{
unit = m_caster->ToUnit();
if (unit && unit->IsImmunedToSpell(GetSpellInfo(), targetInfo.EffectMask, unit))
targetInfo.ReflectResult = SPELL_MISS_IMMUNE;
}
if (!unit)
return;