From f908481bce6a220969f4127fa9a1bcacb73bcfd8 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Mon, 26 Aug 2024 16:15:18 -0400 Subject: [PATCH] Core/Spells: Fixed implementation of SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS and removed banish special cases that were neccessary because that attribute wasn't correctly supported Port From (https://github.com/TrinityCore/TrinityCore/commit/c968dedfee59db53fc912ac166309f3d87470821) --- .../Framework/Constants/Spells/SpellConst.cs | 4 +- Source/Framework/Constants/UnitConst.cs | 4 +- Source/Game/Entities/Object/WorldObject.cs | 2 +- Source/Game/Entities/Unit/Unit.Spells.cs | 143 ++++++++++++------ Source/Game/Entities/Unit/Unit.cs | 2 +- Source/Game/Spells/Auras/Aura.cs | 4 +- Source/Game/Spells/Auras/AuraEffect.cs | 40 ++--- Source/Game/Spells/Spell.cs | 2 +- Source/Game/Spells/SpellInfo.cs | 57 +++---- 9 files changed, 131 insertions(+), 127 deletions(-) diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 62a9f05cd..6bd3a6aa7 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -1702,7 +1702,7 @@ namespace Framework.Constants ToggleFarSight = 0x2000, // Toggle Far Sight (Client Only) TrackTargetInChannel = 0x4000, // Track Target In Channel Description While Channeling, Adjust Facing To Face Target ImmunityPurgesEffect = 0x8000, // Immunity Purges Effect Description For Immunity Spells, Cancel All Auras That This Spell Would Make You Immune To When The Spell Is Applied - ImmunityToHostileAndFriendlyEffects = 0x10000, /*Wrong Impl*/ // Immunity To Hostile & Friendly Effects Description Will Not Pierce Divine Shield, Ice Block And Other Full Invulnerabilities + ImmunityToHostileAndFriendlyEffects = 0x10000, // Immunity applied by this aura will also be checked for friendly spells (school immunity only) - used by Cyclone for example to cause friendly spells and healing over time to be immuned NoAutocastAi = 0x20000, // No Autocast (Ai) PreventsAnim = 0x40000, /*Nyi*/ // Prevents Anim Description Auras Apply UnitFlagPreventEmotesFromChatText ExcludeCaster = 0x80000, // Exclude Caster @@ -2683,7 +2683,7 @@ namespace Framework.Constants Marked = 5, // C T| Nyi Wounded25Percent = 6, // T | Defensive2 = 7, // Cc | Nyi - Banished = 8, // C | Nyi + Banished = 8, // C | Dazed = 9, // T| Victorious = 10, // C | Rampage = 11, // | Nyi diff --git a/Source/Framework/Constants/UnitConst.cs b/Source/Framework/Constants/UnitConst.cs index 0707f1401..d7df14be9 100644 --- a/Source/Framework/Constants/UnitConst.cs +++ b/Source/Framework/Constants/UnitConst.cs @@ -474,7 +474,7 @@ namespace Framework.Constants Root = 0x400, Confused = 0x800, Distracted = 0x1000, - Isolated = 0x2000, // Area Auras Do Not Affect Other Players + Isolated_Deprecated = 0x2000, // REUSE AttackPlayer = 0x4000, Casting = 0x8000, Possessed = 0x10000, // being possessed by another unit @@ -494,7 +494,7 @@ namespace Framework.Constants AllStateSupported = Died | MeleeAttacking | Charmed | Stunned | Roaming | Chase | Focusing | Fleeing | InFlight | Follow | Root | Confused - | Distracted | Isolated | AttackPlayer | Casting + | Distracted | AttackPlayer | Casting | Possessed | Charging | Jumping | Move | Rotating | Evade | RoamingMove | ConfusedMove | FleeingMove | ChaseMove | FollowMove | IgnorePathfinding | FollowFormationMove, diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index d45a70c03..011466ddc 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -2189,7 +2189,7 @@ namespace Game.Entities // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit - if (spellInfo.HasOnlyDamageEffects() && victim.IsImmunedToDamage(spellInfo)) + if (spellInfo.HasOnlyDamageEffects() && victim.IsImmunedToDamage(this, spellInfo)) return SpellMissInfo.Immune; // All positive spells can`t miss diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index 1a080846a..50d2d39b0 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -1339,11 +1339,13 @@ namespace Game.Entities if (immuneSpellInfo == null || !immuneSpellInfo.HasAttribute(SpellAttr1.ImmunityPurgesEffect)) continue; - // Consider the school immune if any of these conditions are not satisfied. - // In case of no immuneSpellInfo, ignore that condition and check only the other conditions - if ((immuneSpellInfo != null && !immuneSpellInfo.IsPositive()) || !spellInfo.IsPositive() || caster == null || !IsFriendlyTo(caster)) - if (!spellInfo.CanPierceImmuneAura(immuneSpellInfo)) - schoolImmunityMask |= pair.Key; + if (immuneSpellInfo != null && !immuneSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && caster != null && !caster.IsFriendlyTo(this)) + continue; + + if (spellInfo.CanPierceImmuneAura(immuneSpellInfo)) + continue; + + schoolImmunityMask |= pair.Key; } if ((schoolImmunityMask & schoolMask) == schoolMask) @@ -1392,6 +1394,69 @@ namespace Game.Entities return mask; } + public bool IsImmunedToDamage(SpellSchoolMask schoolMask) + { + if (schoolMask == SpellSchoolMask.None) + return false; + + // If m_immuneToSchool type contain this school type, IMMUNE damage. + uint schoolImmunityMask = GetSchoolImmunityMask(); + if (((SpellSchoolMask)schoolImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types + return true; + + // If m_immuneToDamage type contain magic, IMMUNE damage. + uint damageImmunityMask = GetDamageImmunityMask(); + if (((SpellSchoolMask)damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types + return true; + + return false; + } + + public bool IsImmunedToDamage(WorldObject caster, SpellInfo spellInfo, SpellEffectInfo spellEffectInfo = null) + { + if (spellInfo == null) + return false; + + if (spellInfo.HasAttribute(SpellAttr0.NoImmunities) && spellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) + return false; + + if (spellEffectInfo != null && spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes.NoImmunity)) + return false; + + uint schoolMask = (uint)spellInfo.GetSchoolMask(); + if (schoolMask != 0) + { + bool hasImmunity(MultiMap container) + { + uint schoolImmunityMask = 0; + foreach (var (immunitySchoolMask, immunityAuraId) in container) + { + SpellInfo immuneAuraInfo = Global.SpellMgr.GetSpellInfo(immunityAuraId, GetMap().GetDifficultyID()); + if (immuneAuraInfo != null && !immuneAuraInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && caster != null && caster.IsFriendlyTo(this)) + continue; + + if (immuneAuraInfo != null && spellInfo.CanPierceImmuneAura(immuneAuraInfo)) + continue; + + schoolImmunityMask |= immunitySchoolMask; + } + + // // We need to be immune to all types + return (schoolImmunityMask & schoolMask) == schoolMask; + }; + + // If m_immuneToSchool type contain this school type, IMMUNE damage. + if (hasImmunity(m_spellImmune[(int)SpellImmunity.School])) + return true; + + // If m_immuneToDamage type contain magic, IMMUNE damage. + if (hasImmunity(m_spellImmune[(int)SpellImmunity.Damage])) + return true; + } + + return false; + } + public virtual bool IsImmunedToSpellEffect(SpellInfo spellInfo, SpellEffectInfo spellEffectInfo, WorldObject caster, bool requireImmunityPurgesEffectAttribute = false) { if (spellInfo == null) @@ -1445,46 +1510,26 @@ namespace Game.Entities if (!spellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) { - // Check for immune to application of harmful magical effects - var immuneAuraApply = GetAuraEffectsByType(AuraType.ModImmuneAuraApplySchool); - foreach (var auraEffect in immuneAuraApply) - if (Convert.ToBoolean(auraEffect.GetMiscValue() & (int)spellInfo.GetSchoolMask()) && // Check school - ((caster != null && !IsFriendlyTo(caster)) || !spellInfo.IsPositiveEffect(spellEffectInfo.EffectIndex))) // Harmful + foreach (AuraEffect immuneAuraApply in GetAuraEffectsByType(AuraType.ModImmuneAuraApplySchool)) + { + if ((immuneAuraApply.GetMiscValue() & (int)spellInfo.GetSchoolMask()) == 0) // Check school + continue; + + if (spellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) || (caster != null && !IsFriendlyTo(caster))) // Harmful return true; + } } } return false; } - public bool IsImmunedToDamage(SpellSchoolMask schoolMask) - { - if (schoolMask == SpellSchoolMask.None) - return false; - - // If m_immuneToSchool type contain this school type, IMMUNE damage. - uint schoolImmunityMask = GetSchoolImmunityMask(); - if (((SpellSchoolMask)schoolImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types - return true; - - // If m_immuneToDamage type contain magic, IMMUNE damage. - uint damageImmunityMask = GetDamageImmunityMask(); - if (((SpellSchoolMask)damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types - return true; - - return false; - } - - public bool IsImmunedToDamage(SpellInfo spellInfo, SpellEffectInfo spellEffectInfo = null) + public bool IsImmunedToAuraPeriodicTick(WorldObject caster, SpellInfo spellInfo, SpellEffectInfo spellEffectInfo = null) { if (spellInfo == null) return false; - // for example 40175 - if (spellInfo.HasAttribute(SpellAttr0.NoImmunities) && spellInfo.HasAttribute(SpellAttr3.AlwaysHit)) - return false; - - if (spellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) || spellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) + if (spellInfo.HasAttribute(SpellAttr0.NoImmunities) || spellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities) /*only school immunities are checked in this function*/) return false; if (spellEffectInfo != null && spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes.NoImmunity)) @@ -1493,20 +1538,24 @@ namespace Game.Entities uint schoolMask = (uint)spellInfo.GetSchoolMask(); if (schoolMask != 0) { + bool hasImmunity(MultiMap container) + { + uint schoolImmunityMask = 0; + foreach (var (immunitySchoolMask, immunityAuraId) in container) + { + SpellInfo immuneAuraInfo = Global.SpellMgr.GetSpellInfo(immunityAuraId, GetMap().GetDifficultyID()); + if (immuneAuraInfo != null && !immuneAuraInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && caster != null && caster.IsFriendlyTo(this)) + continue; + + schoolImmunityMask |= immunitySchoolMask; + } + + // // We need to be immune to all types + return (schoolImmunityMask & schoolMask) == schoolMask; + } + // If m_immuneToSchool type contain this school type, IMMUNE damage. - uint schoolImmunityMask = 0; - var schoolList = m_spellImmune[(int)SpellImmunity.School]; - foreach (var pair in schoolList) - if (Convert.ToBoolean(pair.Key & schoolMask) && !spellInfo.CanPierceImmuneAura(Global.SpellMgr.GetSpellInfo(pair.Value, GetMap().GetDifficultyID()))) - schoolImmunityMask |= pair.Key; - - // // We need to be immune to all types - if ((schoolImmunityMask & schoolMask) == schoolMask) - return true; - - // If m_immuneToDamage type contain magic, IMMUNE damage. - uint damageImmunityMask = GetDamageImmunityMask(); - if ((damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types + if (hasImmunity(m_spellImmune[(int)SpellImmunity.School])) return true; } diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 8d1a7b658..cb051914b 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -3100,7 +3100,7 @@ namespace Game.Entities } // ...or immuned - if (IsImmunedToDamage(spellInfo)) + if (IsImmunedToDamage(this, spellInfo)) { victim.SendSpellDamageImmune(this, spellInfo.Id, false); continue; diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 9cfbd18a3..4cc85005a 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -410,7 +410,7 @@ namespace Game.Spells return Global.ObjAccessor.GetUnit(m_owner, m_casterGuid); } - WorldObject GetWorldObjectCaster() + public WorldObject GetWorldObjectCaster() { if (GetCasterGUID().IsUnit()) return GetCaster(); @@ -2785,7 +2785,7 @@ namespace Game.Spells if (!GetUnitOwner().IsInWorld) continue; - if (GetUnitOwner().HasUnitState(UnitState.Isolated)) + if (GetUnitOwner().HasAuraState(AuraStateType.Banished, GetSpellInfo(), caster)) continue; List units = new(); diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index c6478c608..e38c59260 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -2933,28 +2933,6 @@ namespace Game.Spells Unit target = aurApp.GetTarget(); m_spellInfo.ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), apply); - if (GetSpellInfo().Mechanic == Mechanics.Banish) - { - if (apply) - target.AddUnitState(UnitState.Isolated); - else - { - bool banishFound = false; - var banishAuras = target.GetAuraEffectsByType(GetAuraType()); - foreach (var aurEff in banishAuras) - { - if (aurEff.GetSpellInfo().Mechanic == Mechanics.Banish) - { - banishFound = true; - break; - } - } - - if (!banishFound) - target.ClearUnitState(UnitState.Isolated); - } - } - // TODO: should be changed to a proc script on flag spell (they have "Taken positive" proc flags in db2) { if (apply && GetMiscValue() == (int)SpellSchoolMask.Normal) @@ -5091,7 +5069,7 @@ namespace Game.Spells if (!target.IsAlive()) return; - if (target.HasUnitState(UnitState.Isolated) || target.IsImmunedToDamage(GetSpellInfo(), GetSpellEffectInfo())) + if (target.IsImmunedToDamage(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5219,7 +5197,7 @@ namespace Game.Spells if (!target.IsAlive()) return; - if (target.HasUnitState(UnitState.Isolated) || target.IsImmunedToDamage(GetSpellInfo(), GetSpellEffectInfo())) + if (target.IsImmunedToDamage(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5319,7 +5297,7 @@ namespace Game.Spells if (caster == null || !caster.IsAlive() || !target.IsAlive()) return; - if (target.HasUnitState(UnitState.Isolated)) + if (target.IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5349,7 +5327,7 @@ namespace Game.Spells if (!target.IsAlive()) return; - if (target.HasUnitState(UnitState.Isolated)) + if (target.IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5409,7 +5387,7 @@ namespace Game.Spells if (caster == null || !caster.IsAlive() || !target.IsAlive() || target.GetPowerType() != powerType) return; - if (target.HasUnitState(UnitState.Isolated) || target.IsImmunedToDamage(GetSpellInfo(), GetSpellEffectInfo())) + if (target.IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5469,7 +5447,7 @@ namespace Game.Spells if (!target.IsAlive() || target.GetMaxPower(powerType) == 0) return; - if (target.HasUnitState(UnitState.Isolated)) + if (target.IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5498,7 +5476,7 @@ namespace Game.Spells if (!target.IsAlive() || target.GetMaxPower(powerType) == 0) return; - if (target.HasUnitState(UnitState.Isolated)) + if (target.IsImmunedToAuraPeriodicTick(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5527,7 +5505,7 @@ namespace Game.Spells if (caster == null || !target.IsAlive() || target.GetPowerType() != powerType) return; - if (target.HasUnitState(UnitState.Isolated) || target.IsImmunedToDamage(GetSpellInfo(), GetSpellEffectInfo())) + if (target.IsImmunedToDamage(caster, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(target, caster); return; @@ -5657,7 +5635,7 @@ namespace Game.Spells { Unit target = aurApp.GetTarget(); Unit triggerTarget = eventInfo.GetProcTarget(); - if (triggerTarget.HasUnitState(UnitState.Isolated) || triggerTarget.IsImmunedToDamage(GetSpellInfo(), GetSpellEffectInfo())) + if (triggerTarget.IsImmunedToDamage(target, GetSpellInfo(), GetSpellEffectInfo())) { SendTickImmune(triggerTarget, target); return; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 3a5f3a953..54fd321e6 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -9002,7 +9002,7 @@ namespace Game.Spells // Fill base damage struct (unitTarget - is real spell target) SpellNonMeleeDamage damageInfo = new(caster, spell.unitTarget, spell.m_spellInfo, spell.m_SpellVisual, spell.m_spellSchoolMask, spell.m_castId); // Check damage immunity - if (spell.unitTarget.IsImmunedToDamage(spell.m_spellInfo)) + if (spell.unitTarget.IsImmunedToDamage(caster, spell.m_spellInfo)) { hitMask = ProcFlagsHit.Immune; spell.m_damage = 0; diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index 3eefadecd..4333e7c2a 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -673,24 +673,6 @@ namespace Game.Spells public bool CanPierceImmuneAura(SpellInfo auraSpellInfo) { - // aura can't be pierced - if (auraSpellInfo == null || auraSpellInfo.HasAttribute(SpellAttr0.NoImmunities)) - return false; - - // these spells pierce all avalible spells (Resurrection Sickness for example) - if (HasAttribute(SpellAttr0.NoImmunities)) - return true; - - // these spells (Cyclone for example) can pierce all... - if (HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) || HasAttribute(SpellAttr2.NoSchoolImmunities)) - { - // ...but not these (Divine shield, Ice block, Cyclone and Banish for example) - if (auraSpellInfo.Mechanic != Mechanics.ImmuneShield && - auraSpellInfo.Mechanic != Mechanics.Invulnerability && - (auraSpellInfo.Mechanic != Mechanics.Banish || (IsRankOf(auraSpellInfo) && auraSpellInfo.Dispel != DispelType.None))) // Banish shouldn't be immune to itself, but Cyclone should - return true; - } - // Dispels other auras on immunity, check if this spell makes the unit immune to aura if (HasAttribute(SpellAttr1.ImmunityPurgesEffect) && CanSpellProvideImmunityAgainstAura(auraSpellInfo)) return true; @@ -704,15 +686,6 @@ namespace Game.Spells if (auraSpellInfo.HasAttribute(SpellAttr0.NoImmunities)) return false; - // These spells (like Mass Dispel) can dispel all auras - if (HasAttribute(SpellAttr0.NoImmunities)) - return true; - - // These auras (Cyclone for example) are not dispelable - if ((auraSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && auraSpellInfo.Mechanic != Mechanics.None) - || auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) - return false; - return true; } @@ -2331,11 +2304,21 @@ namespace Game.Spells target.RemoveAppliedAuras(aurApp => { SpellInfo auraSpellInfo = aurApp.GetBase().GetSpellInfo(); - return (((uint)auraSpellInfo.GetSchoolMask() & schoolImmunity) != 0 && // Check for school mask - CanDispelAura(auraSpellInfo) && - (IsPositive() != aurApp.IsPositive()) && // Check spell vs aura possitivity - !auraSpellInfo.IsPassive() && // Don't remove passive auras - auraSpellInfo.Id != Id); // Don't remove self + if (auraSpellInfo.Id == Id) // Don't remove self + return false; + if (auraSpellInfo.IsPassive()) // Don't remove passive auras + return false; + if (((uint)auraSpellInfo.GetSchoolMask() & schoolImmunity) == 0) // Check for school mask + return false; + if (!CanDispelAura(auraSpellInfo)) + return false; + if (!HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects)) + { + WorldObject existingAuraCaster = aurApp.GetBase().GetWorldObjectCaster(); + if (existingAuraCaster != null && existingAuraCaster.IsFriendlyTo(target)) // Check spell vs aura possitivity + return false; + } + return true; }); } @@ -2408,13 +2391,7 @@ namespace Game.Spells { target.ApplySpellImmune(Id, SpellImmunity.State, auraType, apply); if (apply && HasAttribute(SpellAttr1.ImmunityPurgesEffect)) - { - target.RemoveAurasByType(auraType, aurApp => - { - // if the aura has SPELL_ATTR0_NO_IMMUNITIES, then it cannot be removed by immunity - return !aurApp.GetBase().GetSpellInfo().HasAttribute(SpellAttr0.NoImmunities); - }); - } + target.RemoveAurasByType(auraType, aurApp => CanDispelAura(aurApp.GetBase().GetSpellInfo())); } foreach (SpellEffectName effectType in immuneInfo.SpellEffectImmune) @@ -2437,7 +2414,7 @@ namespace Game.Spells ImmunityInfo immuneInfo = effectInfo.GetImmunityInfo(); - if (!auraSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && !auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) + if (!auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities)) { uint schoolImmunity = immuneInfo.SchoolImmuneMask; if (schoolImmunity != 0)