diff --git a/Content.Shared/Examine/ExamineSystemShared.cs b/Content.Shared/Examine/ExamineSystemShared.cs index 1172875d23..832d2c1f8b 100644 --- a/Content.Shared/Examine/ExamineSystemShared.cs +++ b/Content.Shared/Examine/ExamineSystemShared.cs @@ -9,6 +9,7 @@ using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.IoC; +using Robust.Shared.Log; using Robust.Shared.Map; using Robust.Shared.Maths; using Robust.Shared.Physics; @@ -33,6 +34,8 @@ namespace Content.Shared.Examine [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + public const float MaxRaycastRange = 100; + /// /// Examine range to use when the examiner is in critical condition. /// @@ -114,23 +117,31 @@ namespace Content.Shared.Examine public static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored? predicate, bool ignoreInsideBlocker = true) { - if (origin.MapId == MapId.Nullspace || + if (other.MapId != origin.MapId || other.MapId == MapId.Nullspace) return false; + var dir = other.Position - origin.Position; + var length = dir.Length; + + // If range specified also check it + if (range > 0f && length > range) return false; + + if (MathHelper.CloseTo(length, 0)) return true; + + if (length > MaxRaycastRange) + { + Logger.Warning("InRangeUnOccluded check performed over extreme range. Limiting CollisionRay size."); + length = MaxRaycastRange; + } + var occluderSystem = Get(); var entMan = IoCManager.Resolve(); - if (!origin.InRange(other, range)) return false; - - var dir = other.Position - origin.Position; - - if (dir.LengthSquared.Equals(0f)) return true; - if (range > 0f && !(dir.LengthSquared <= range * range)) return false; predicate ??= _ => false; var ray = new Ray(origin.Position, dir.Normalized); var rayResults = occluderSystem - .IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); + .IntersectRayWithPredicate(origin.MapId, ray, length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) return true; diff --git a/Content.Shared/Interaction/SharedInteractionSystem.cs b/Content.Shared/Interaction/SharedInteractionSystem.cs index 783d7a7c03..e219effae8 100644 --- a/Content.Shared/Interaction/SharedInteractionSystem.cs +++ b/Content.Shared/Interaction/SharedInteractionSystem.cs @@ -49,6 +49,8 @@ namespace Content.Shared.Interaction public const float InteractionRange = 2; public const float InteractionRangeSquared = InteractionRange * InteractionRange; + public const float MaxRaycastRange = 100; + public delegate bool Ignored(EntityUid entity); public override void Initialize() @@ -322,19 +324,24 @@ namespace Content.Shared.Interaction // Have to be on same map regardless. if (other.MapId != origin.MapId) return false; - // Uhh this does mean we could raycast infinity distance so may need to limit it. var dir = other.Position - origin.Position; - var lengthSquared = dir.LengthSquared; - - if (lengthSquared.Equals(0f)) return true; + var length = dir.Length; // If range specified also check it - if (range > 0f && lengthSquared > range * range) return false; + if (range > 0f && length > range) return false; + + if (MathHelper.CloseTo(length, 0)) return true; predicate ??= _ => false; + if (length > MaxRaycastRange) + { + Logger.Warning("InRangeUnobstructed check performed over extreme range. Limiting CollisionRay size."); + length = MaxRaycastRange; + } + var ray = new CollisionRay(origin.Position, dir.Normalized, (int) collisionMask); - var rayResults = _sharedBroadphaseSystem.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); + var rayResults = _sharedBroadphaseSystem.IntersectRayWithPredicate(origin.MapId, ray, length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) return true;