diff --git a/Source/Framework/Constants/CreatureConst.cs b/Source/Framework/Constants/CreatureConst.cs index 827eb93da..52a41854d 100644 --- a/Source/Framework/Constants/CreatureConst.cs +++ b/Source/Framework/Constants/CreatureConst.cs @@ -79,7 +79,7 @@ namespace Framework.Constants Unk28 = 0x10000000, Unk29 = 0x20000000, Sheathe = 0x40000000, - Unk31 = 0x80000000 + Immune = 0x80000000 } public enum UnitFlags2 : uint diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 6e5cf9e8c..07eb67b57 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -1448,6 +1448,9 @@ namespace Game.Entities Player playerUser = user.ToPlayer(); if (playerUser != null) { + if (m_goInfo.GetNoDamageImmune() != 0 && playerUser.HasUnitFlag(UnitFlags.Immune)) + return; + if (!m_goInfo.IsUsableMounted()) playerUser.RemoveAurasByType(AuraType.Mounted); diff --git a/Source/Game/Entities/GameObject/GameObjectData.cs b/Source/Game/Entities/GameObject/GameObjectData.cs index bb6918116..30550f846 100644 --- a/Source/Game/Entities/GameObject/GameObjectData.cs +++ b/Source/Game/Entities/GameObject/GameObjectData.cs @@ -352,7 +352,37 @@ namespace Game.Entities } } - // despawn at uses amount + /// + /// Cannot be used/activated/looted by players under immunity effects (example: Divine Shield) + /// + /// + public uint GetNoDamageImmune() + { + switch (type) + { + case GameObjectTypes.Door: + return Door.noDamageImmune; + case GameObjectTypes.Button: + return Button.noDamageImmune; + case GameObjectTypes.QuestGiver: + return QuestGiver.noDamageImmune; + case GameObjectTypes.Chest: + return 1; + case GameObjectTypes.Goober: + return Goober.noDamageImmune; + case GameObjectTypes.FlagStand: + return FlagStand.noDamageImmune; + case GameObjectTypes.FlagDrop: + return FlagDrop.noDamageImmune; + default: + return 0; + } + } + + /// + /// despawn at uses amount + /// + /// public uint GetCharges() { switch (type) diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 02a6764ec..22bdd65bc 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -2799,7 +2799,18 @@ namespace Game.Spells } if (apply) + { + target.AddUnitFlag(UnitFlags.Immune); target.GetThreatManager().EvaluateSuppressed(); + } + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit + if (target.HasAuraType(GetAuraType())) + return; + + target.RemoveUnitFlag(UnitFlags.Immune); + } } [AuraEffectHandler(AuraType.DamageImmunity)] diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 162eee1e7..a7dd199a0 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -4365,6 +4365,13 @@ namespace Game.Spells if (m_caster.ToUnit() && !m_caster.ToUnit().IsAlive() && !m_spellInfo.IsPassive() && !(m_spellInfo.HasAttribute(SpellAttr0.CastableWhileDead) || (IsTriggered() && m_triggeredByAuraSpell == null))) return SpellCastResult.CasterDead; + // Prevent cheating in case the player has an immunity effect and tries to interact with a non-allowed gameobject. The error message is handled by the client so we don't report anything here + if (m_caster.IsPlayer() && m_targets.GetGOTarget() != null) + { + if (m_targets.GetGOTarget().GetGoInfo().GetNoDamageImmune() != 0 && m_caster.ToUnit().HasUnitFlag(UnitFlags.Immune)) + return SpellCastResult.DontReport; + } + // check cooldowns to prevent cheating if (!m_spellInfo.IsPassive()) { diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index b9a347709..a3c83e829 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -1324,6 +1324,10 @@ namespace Game.Spells if (gameObjTarget != null) { GameObjectTemplate goInfo = gameObjTarget.GetGoInfo(); + + if (goInfo.GetNoDamageImmune() != 0 && player.HasUnitFlag(UnitFlags.Immune)) + return; + // Arathi Basin banner opening. // @todo Verify correctness of this check if ((goInfo.type == GameObjectTypes.Button && goInfo.Button.noDamageImmune != 0) || (goInfo.type == GameObjectTypes.Goober && goInfo.Goober.requireLOS != 0))