From a604bbd7f9741cbb756a86d38af5834a9002355b Mon Sep 17 00:00:00 2001 From: hondacrx Date: Fri, 18 Feb 2022 12:51:16 -0500 Subject: [PATCH] Core/Gameobjects: Improve stealth detection Port From (https://github.com/TrinityCore/TrinityCore/commit/60e66621dae44cb832ebb0bdb5e168f9ab114ecb) --- Source/Game/Entities/GameObject/GameObject.cs | 2 +- Source/Game/Entities/Object/WorldObject.cs | 25 ++++++++++++------- Source/Game/Maps/GridNotifiers.cs | 6 ++--- Source/Game/Spells/Spell.cs | 4 ++- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index c03240d68..05720f5b6 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -663,7 +663,7 @@ namespace Game.Entities if (owner) { // Hunter trap: Search units which are unfriendly to the trap's owner - var checker = new NearestAttackableNoTotemUnitInObjectRangeCheck(this, owner, radius); + var checker = new NearestAttackableNoTotemUnitInObjectRangeCheck(this, radius); var searcher = new UnitLastSearcher(this, checker); Cell.VisitAllObjects(this, searcher, radius); target = searcher.GetTarget(); diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 5be5613da..408b988e4 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1248,10 +1248,17 @@ namespace Game.Entities if (distance < combatReach) return true; - if (!HasInArc(MathFunctions.PI, obj)) + // Only check back for units, it does not make sense for gameobjects + if (unit && !HasInArc(MathF.PI, obj)) return false; - GameObject go = obj.ToGameObject(); + // Traps should detect stealth always + GameObject go = ToGameObject(); + if (go != null) + if (go.GetGoType() == GameObjectTypes.Trap) + return true; + + go = obj.ToGameObject(); for (int i = 0; i < (int)StealthType.Max; ++i) { if (!Convert.ToBoolean(obj.m_stealth.GetFlags() & (1 << i))) @@ -2056,8 +2063,8 @@ namespace Game.Entities } } - Unit unit = ToUnit(); - Unit targetUnit = target.ToUnit(); + Unit unit = ToUnit() ?? selfPlayerOwner; + Unit targetUnit = target.ToUnit() ?? targetPlayerOwner; if (unit && unit.HasUnitFlag(UnitFlags.PlayerControlled)) { if (targetUnit && targetUnit.HasUnitFlag(UnitFlags.PlayerControlled)) @@ -2452,7 +2459,7 @@ namespace Game.Entities if (IsFriendlyTo(target) || target.IsFriendlyTo(this)) return false; - Player playerAffectingAttacker = unit != null && unit.HasUnitFlag(UnitFlags.PlayerControlled) ? GetAffectingPlayer() : null; + Player playerAffectingAttacker = unit != null && unit.HasUnitFlag(UnitFlags.PlayerControlled) ? GetAffectingPlayer() : IsGameObject() ? GetAffectingPlayer() : null; Player playerAffectingTarget = unitTarget != null && unitTarget.HasUnitFlag(UnitFlags.PlayerControlled) ? target.GetAffectingPlayer() : null; // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar) @@ -2500,14 +2507,14 @@ namespace Game.Entities // additional checks - only PvP case if (playerAffectingAttacker && playerAffectingTarget) { - if (unitTarget.IsPvP()) + if (playerAffectingTarget.IsPvP()) return true; - if (unit.IsFFAPvP() && unitTarget.IsFFAPvP()) + if (playerAffectingAttacker.IsFFAPvP() && playerAffectingTarget.IsFFAPvP()) return true; - return unit.HasPvpFlag(UnitPVPStateFlags.Unk1) || - unitTarget.HasPvpFlag(UnitPVPStateFlags.Unk1); + return playerAffectingAttacker.HasPvpFlag(UnitPVPStateFlags.Unk1) || + playerAffectingTarget.HasPvpFlag(UnitPVPStateFlags.Unk1); } return true; diff --git a/Source/Game/Maps/GridNotifiers.cs b/Source/Game/Maps/GridNotifiers.cs index 860287db9..5706841cb 100644 --- a/Source/Game/Maps/GridNotifiers.cs +++ b/Source/Game/Maps/GridNotifiers.cs @@ -1962,10 +1962,9 @@ namespace Game.Maps public class NearestAttackableNoTotemUnitInObjectRangeCheck : ICheck { - public NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject obj, Unit funit, float range) + public NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject obj, float range) { i_obj = obj; - i_funit = funit; i_range = range; } @@ -1983,7 +1982,7 @@ namespace Game.Maps if (!u.IsTargetableForAttack(false)) return false; - if (!i_obj.IsWithinDistInMap(u, i_range) || i_funit.IsValidAttackTarget(u)) + if (!i_obj.IsWithinDistInMap(u, i_range) || i_obj.IsValidAttackTarget(u)) return false; i_range = i_obj.GetDistance(u); @@ -1991,7 +1990,6 @@ namespace Game.Maps } WorldObject i_obj; - Unit i_funit; float i_range; } diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 089a8dd02..a17837c95 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -4639,7 +4639,9 @@ namespace Game.Spells { // Check explicit target for m_originalCaster - todo: get rid of such workarounds WorldObject caster = m_caster; - if (m_originalCaster != null) + // in case of gameobjects like traps, we need the gameobject itself to check target validity + // otherwise, if originalCaster is far away and cannot detect the target, the trap would not hit the target + if (m_originalCaster != null && !caster.IsGameObject()) caster = m_originalCaster; castResult = m_spellInfo.CheckExplicitTarget(caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());