diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 5003375f0..dc7702235 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -2988,4 +2988,12 @@ namespace Framework.Constants Area, Chain } + + [Flags] + public enum SpellOtherImmunity + { + None = 0x0, + AoETarget = 0x1, + ChainTarget = 0x2 + } } diff --git a/Source/Framework/Constants/UnitConst.cs b/Source/Framework/Constants/UnitConst.cs index 64d269e16..0707f1401 100644 --- a/Source/Framework/Constants/UnitConst.cs +++ b/Source/Framework/Constants/UnitConst.cs @@ -98,7 +98,8 @@ namespace Framework.Constants Dispel = 4, // enum DispelType Mechanic = 5, // enum Mechanics Id = 6, - Max = 7 + Other = 7, //enum SpellOtherImmunity + Max } diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index d2bab92e7..202383916 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -2218,6 +2218,9 @@ namespace Game.Entities foreach (AuraType aura in immunities.Aura) ApplySpellImmune(placeholderSpellId, SpellImmunity.State, aura, apply); + + if (immunities.Other != SpellOtherImmunity.None) + ApplySpellImmune(placeholderSpellId, SpellImmunity.Other, (byte)immunities.Other, apply); } // unapply template immunities (in case we're updating entry) diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index 0fa68e088..037732aa0 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -1384,6 +1384,16 @@ namespace Game.Entities return mask; } + public SpellOtherImmunity GetSpellOtherImmunityMask() + { + SpellOtherImmunity mask = 0; + var damageList = m_spellImmune[(int)SpellImmunity.Other]; + foreach (var pair in damageList) + mask |= (SpellOtherImmunity)pair.Key; + + return mask; + } + public virtual bool IsImmunedToSpellEffect(SpellInfo spellInfo, SpellEffectInfo spellEffectInfo, WorldObject caster, bool requireImmunityPurgesEffectAttribute = false) { if (spellInfo == null) diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index a47a6d6a2..9e79c84d5 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -9185,26 +9185,21 @@ namespace Game.Spells if (!isInsideCylinder) return false; - Creature creatureTarget = target.ToCreature(); - if (creatureTarget != null) + Unit unitTarget = target.ToUnit(); + if (unitTarget != null) { - CreatureImmunities immunities = Global.SpellMgr.GetCreatureImmunities(creatureTarget.GetCreatureTemplate().CreatureImmunitiesId); - if (immunities != null) + switch (_searchReason) { - switch (_searchReason) - { - case WorldObjectSpellAreaTargetSearchReason.Area: - if (immunities.ImmuneAoE) - return false; - break; - case WorldObjectSpellAreaTargetSearchReason.Chain: - if (immunities.ImmuneChain) - return false; - break; - default: - break; - } - + case WorldObjectSpellAreaTargetSearchReason.Area: + if (unitTarget.GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity.AoETarget)) + return false; + break; + case WorldObjectSpellAreaTargetSearchReason.Chain: + if (unitTarget.GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity.ChainTarget)) + return false; + break; + default: + break; } } } diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index d5cf0b765..83beaea4e 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -1078,6 +1078,10 @@ namespace Game.Spells if (HasAttribute(SpellAttr8.OnlyTargetOwnSummons)) if (!unitTarget.IsSummon() || unitTarget.ToTempSummon().GetSummonerGUID() != caster.GetGUID()) return SpellCastResult.BadTargets; + + if (HasAttribute(SpellAttr3.NotOnAoeImmune)) + if (unitTarget.GetSpellOtherImmunityMask().HasFlag(SpellOtherImmunity.AoETarget)) + return SpellCastResult.BadTargets; } // corpse specific target checks else if (target.IsTypeId(TypeId.Corpse)) @@ -1106,13 +1110,6 @@ namespace Game.Spells if (HasAttribute(SpellAttr5.NotOnPlayerControlledNpc) && unitTarget.IsControlledByPlayer()) return SpellCastResult.TargetIsPlayerControlled; - - if (HasAttribute(SpellAttr3.NotOnAoeImmune)) - { - CreatureImmunities immunities = Global.SpellMgr.GetCreatureImmunities(unitTarget.ToCreature().GetCreatureTemplate().CreatureImmunitiesId); - if (immunities != null && immunities.ImmuneAoE) - return SpellCastResult.BadTargets; - } } else if (HasAttribute(SpellAttr5.NotOnPlayer)) return SpellCastResult.TargetIsPlayer; @@ -2144,6 +2141,7 @@ namespace Game.Spells ulong mechanicImmunityMask = 0; uint dispelImmunityMask = 0; uint damageImmunityMask = 0; + byte otherImmunityMask = 0; int miscVal = effect.MiscValue; @@ -2159,6 +2157,7 @@ namespace Game.Spells schoolImmunityMask |= creatureImmunities.School.ToUInt(); dispelImmunityMask |= creatureImmunities.DispelType.ToUInt(); mechanicImmunityMask |= creatureImmunities.Mechanic.ToUInt(); + otherImmunityMask |= (byte)creatureImmunities.Other; foreach (SpellEffectName effectType in creatureImmunities.Effect) immuneInfo.SpellEffectImmune.Add(effectType); foreach (AuraType aura in creatureImmunities.Aura) @@ -2237,6 +2236,7 @@ namespace Game.Spells immuneInfo.MechanicImmuneMask = mechanicImmunityMask; immuneInfo.DispelImmuneMask = dispelImmunityMask; immuneInfo.DamageSchoolMask = damageImmunityMask; + immuneInfo.OtherImmuneMask = otherImmunityMask; _allowedMechanicMask |= immuneInfo.MechanicImmuneMask; } @@ -2413,6 +2413,10 @@ namespace Game.Spells foreach (SpellEffectName effectType in immuneInfo.SpellEffectImmune) target.ApplySpellImmune(Id, SpellImmunity.Effect, effectType, apply); + + byte otherImmuneMask = immuneInfo.OtherImmuneMask; + if (otherImmuneMask != 0) + target.ApplySpellImmune(Id, SpellImmunity.Other, otherImmuneMask, apply); } bool CanSpellProvideImmunityAgainstAura(SpellInfo auraSpellInfo) @@ -5154,6 +5158,7 @@ namespace Game.Spells public ulong MechanicImmuneMask; public uint DispelImmuneMask; public uint DamageSchoolMask; + public byte OtherImmuneMask; public List AuraTypeImmune = new(); public List SpellEffectImmune = new(); diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index eb6e41978..3145026ea 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -4513,8 +4513,10 @@ namespace Game.Entities immunities.School = new BitSet(new uint[] { school }); immunities.DispelType = new BitSet(new uint[] { dispelType }); immunities.Mechanic = new BitSet(mechanics); - immunities.ImmuneAoE = result.Read(6); - immunities.ImmuneChain = result.Read(7); + if (result.Read(6)) + immunities.Other |= SpellOtherImmunity.AoETarget; + if (result.Read(7)) + immunities.Other |= SpellOtherImmunity.ChainTarget; if (immunities.School.ToUInt() != school) Log.outError(LogFilter.Sql, $"Invalid value in `SchoolMask` {school} for creature immunities {id}, truncated"); @@ -5147,7 +5149,6 @@ namespace Game.Entities public BitSet Mechanic = new((int)Mechanics.Max); public List Effect = new(); public List Aura = new(); - public bool ImmuneAoE; // NYI - public bool ImmuneChain; // NYI + public SpellOtherImmunity Other; } }