private static List <ICommonSession> PasInRange(IEnumerable <ICommonSession> players, MapCoordinates position, float range) { return(players.Where(x => x.AttachedEntity != null && position.InRange(x.AttachedEntity.Transform.MapPosition, range)) .ToList()); }
/// <summary> /// Checks that these coordinates are within a certain distance without any /// entity that matches the collision mask obstructing them. /// If the <paramref name="range"/> is zero or negative, /// this method will only check if nothing obstructs the two sets /// of coordinates. /// </summary> /// <param name="origin">Set of coordinates to use.</param> /// <param name="other">Other set of coordinates to use.</param> /// <param name="range"> /// Maximum distance between the two sets of coordinates. /// </param> /// <param name="collisionMask">The mask to check for collisions.</param> /// <param name="predicate"> /// A predicate to check whether to ignore an entity or not. /// If it returns true, it will be ignored. /// </param> /// <param name="ignoreInsideBlocker"> /// If true and <see cref="origin"/> or <see cref="other"/> are inside /// the obstruction, ignores the obstruction and considers the interaction /// unobstructed. /// Therefore, setting this to true makes this check more permissive, /// such as allowing an interaction to occur inside something impassable /// (like a wall). The default, false, makes the check more restrictive. /// </param> /// <returns> /// True if the two points are within a given range without being obstructed. /// </returns> public bool InRangeUnobstructed( MapCoordinates origin, MapCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored?predicate = null, bool ignoreInsideBlocker = false) { 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 CollisionRay(origin.Position, dir.Normalized, (int)collisionMask); var rayResults = _sharedBroadphaseSystem.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) { return(true); } // TODO: Wot? This should just be in the predicate. if (!ignoreInsideBlocker) { return(false); } foreach (var result in rayResults) { if (!result.HitEntity.TryGetComponent(out IPhysBody? p)) { continue; } var bBox = p.GetWorldAABB(); if (bBox.Contains(origin.Position) || bBox.Contains(other.Position)) { continue; } return(false); } return(true); }
public static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored?predicate, bool ignoreInsideBlocker = true) { var occluderSystem = Get <OccluderSystem>(); 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(); if (rayResults.Count == 0) { return(true); } if (!ignoreInsideBlocker) { return(false); } foreach (var result in rayResults) { if (!result.HitEntity.TryGetComponent(out OccluderComponent? o)) { continue; } var bBox = o.BoundingBox.Translated(o.Owner.Transform.WorldPosition); if (bBox.Contains(origin.Position) || bBox.Contains(other.Position)) { continue; } return(false); } return(true); }
/// <summary> /// Gets all players inside of a circle. /// </summary> /// <param name="worldPos">Position of the circle in world-space.</param> /// <param name="range">Radius of the circle in world units.</param> /// <returns></returns> public List <IPlayerSession> GetPlayersInRange(MapCoordinates worldPos, int range) { _sessionsLock.EnterReadLock(); //TODO: This needs to be moved to the PVS system. try { return (_sessions.Values.Where(x => x.AttachedEntity != null && worldPos.InRange(x.AttachedEntity.Transform.MapPosition, range)) .Cast <IPlayerSession>() .ToList()); } finally { _sessionsLock.ExitReadLock(); } }
/// <summary> /// Checks that these coordinates are within a certain distance without any /// entity that matches the collision mask obstructing them. /// If the <paramref name="range"/> is zero or negative, /// this method will only check if nothing obstructs the two sets /// of coordinates. /// </summary> /// <param name="origin">Set of coordinates to use.</param> /// <param name="other">Other set of coordinates to use.</param> /// <param name="range"> /// Maximum distance between the two sets of coordinates. /// </param> /// <param name="collisionMask">The mask to check for collisions.</param> /// <param name="predicate"> /// A predicate to check whether to ignore an entity or not. /// If it returns true, it will be ignored. /// </param> /// <param name="ignoreInsideBlocker"> /// If true and <see cref="origin"/> or <see cref="other"/> are inside /// the obstruction, ignores the obstruction and considers the interaction /// unobstructed. /// Therefore, setting this to true makes this check more permissive, /// such as allowing an interaction to occur inside something impassable /// (like a wall). The default, false, makes the check more restrictive. /// </param> /// <returns> /// True if the two points are within a given range without being obstructed. /// </returns> public bool InRangeUnobstructed( MapCoordinates origin, MapCoordinates other, float range = InteractionRange, CollisionGroup collisionMask = CollisionGroup.Impassable, Ignored predicate = null, bool ignoreInsideBlocker = false) { 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 CollisionRay(origin.Position, dir.Normalized, (int)collisionMask); var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) { return(true); } if (!ignoreInsideBlocker) { return(false); } if (rayResults.Count <= 0) { return(false); } return((rayResults[0].HitPos - other.Position).Length < 1f); }
public static bool InRangeUnOccluded(MapCoordinates origin, MapCoordinates other, float range, Ignored predicate, bool ignoreInsideBlocker = true) { var occluderSystem = Get <OccluderSystem>(); 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(); if (rayResults.Count == 0) { return(true); } if (!ignoreInsideBlocker) { return(false); } if (rayResults.Count <= 0) { return(false); } return((rayResults[0].HitPos - other.Position).Length < 1f); }
/// <summary> /// Checks that these coordinates are within a certain distance without any /// entity that matches the collision mask obstructing them. /// If the <paramref name="range"/> is zero or negative, /// this method will only check if nothing obstructs the two sets of coordinates.. /// </summary> /// <param name="coords">Set of coordinates to use.</param> /// <param name="otherCoords">Other set of coordinates to use.</param> /// <param name="range">maximum distance between the two sets of coordinates.</param> /// <param name="collisionMask">the mask to check for collisions</param> /// <param name="predicate">A predicate to check whether to ignore an entity or not. If it returns true, it will be ignored.</param> /// <param name="ignoreInsideBlocker">if true and the coordinates are inside the obstruction, ignores the obstruction and /// considers the interaction unobstructed. Therefore, setting this to true makes this check more permissive, such /// as allowing an interaction to occur inside something impassable (like a wall). The default, false, /// makes the check more restrictive.</param> /// <returns>True if the two points are within a given range without being obstructed.</returns> public bool InRangeUnobstructed(MapCoordinates coords, MapCoordinates otherCoords, float range = InteractionRange, int collisionMask = (int)CollisionGroup.Impassable, Func <IEntity, bool> predicate = null, bool ignoreInsideBlocker = false) { if (!coords.InRange(otherCoords, range)) { return(false); } var dir = otherCoords.Position - coords.Position; if (dir.LengthSquared.Equals(0f)) { return(true); } if (range > 0f && !(dir.LengthSquared <= range * range)) { return(false); } var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask); var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, returnOnFirstHit: false).ToList(); return(rayResults.Count == 0 || (ignoreInsideBlocker && rayResults.Count > 0 && (rayResults[0].HitPos - otherCoords.Position).Length < 1f)); }