fix(Core/Unit): partial immunity for mixed spells (#25219)

Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
sogladev 2026-03-25 12:42:25 +01:00 committed by GitHub
parent 9d9f9bdc58
commit aac930864a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 3 deletions

View file

@ -910,15 +910,34 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, Unit
if (!spellInfo)
return false;
bool immuneToAllEffects = true;
bool hasCheckedEffect = false;
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
{
if (!(effectMask & (1u << i)))
continue;
if (!spellInfo->Effects[i].IsEffect())
continue;
hasCheckedEffect = true;
if (IsImmunedToSpellEffect(spellInfo, i, caster))
return true;
{
if (spellInfo->HasAttribute(SPELL_ATTR4_NO_PARTIAL_IMMUNITY))
return true;
continue;
}
immuneToAllEffects = false;
break;
}
if (hasCheckedEffect && immuneToAllEffects)
return true;
if (!spellInfo->HasAttribute(SPELL_ATTR2_NO_SCHOOL_IMMUNITIES))
{
if (IsImmunedToSchool(spellInfo))

View file

@ -105,6 +105,31 @@ namespace
return false;
}
bool IsEffectBlockedByStunImmunity(EffectDesc const& effect, bool immuneToStun)
{
if (!immuneToStun)
return false;
return effect.effect == EFFECT_APPLY_AURA && effect.aura == AURA_MOD_STUN;
}
bool IsFullyImmunedByStunImmunity(SpellDesc const& spell, bool immuneToStun)
{
bool hasAnyEffect = false;
for (EffectDesc const& effect : spell.effects)
{
if (effect.effect == EFFECT_NONE)
continue;
hasAnyEffect = true;
if (!IsEffectBlockedByStunImmunity(effect, immuneToStun))
return false;
}
return hasAnyEffect;
}
// The last parameter defaults to false to avoid updating existing tests
// that don't care about mechanic immunities. Bladestorm grants a
// specific mechanic immunity (including stun) that should block
@ -114,12 +139,12 @@ namespace
{
// Mirrors current core ordering:
// 1) full spell immunity check
// 2) mechanic immunity check (e.g. bladestorm vs stun)
// 2) full immunity from mechanic immunity (all effects blocked)
// 3) damage immunity only for damage-only spells
if (isImmunedToSpell)
return SPELL_MISS_IMMUNE;
if (immuneToStun && IsStunSpell(spell))
if (IsFullyImmunedByStunImmunity(spell, immuneToStun))
return SPELL_MISS_IMMUNE;
if (HasOnlyDamageEffects(spell) && isImmunedToDamage)
@ -328,3 +353,14 @@ TEST(SpellImmunityTest, Bladestorm_ImmuneToStun)
// with a bladestormstyle stun immunity it is blocked
EXPECT_EQ(ComputeSpellHitResult(false, false, stunSpell, true), SPELL_MISS_IMMUNE);
}
TEST(SpellImmunityTest, StunImmunity_DoesNotFullyBlockMixedSpell)
{
SpellDesc mixedSpell;
mixedSpell.effects[0] = { EFFECT_SCHOOL_DAMAGE, AURA_NONE };
mixedSpell.effects[1] = { EFFECT_APPLY_AURA, AURA_MOD_STUN };
// This models partial immunity: stun effect is blocked, damage still hits.
EXPECT_TRUE(IsStunSpell(mixedSpell));
EXPECT_EQ(ComputeSpellHitResult(false, false, mixedSpell, true), SPELL_MISS_NONE);
}