/// <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">.</param> /// <param name="mapManager">Map manager containing the two GridIds.</param> /// <param name="insideBlockerValid">if coordinates inside obstructions count as obstructed or not</param> /// <returns>True if the two points are within a given range without being obstructed.</returns> public bool InRangeUnobstructed(MapCoordinates coords, Vector2 otherCoords, float range = InteractionRange, int collisionMask = (int)CollisionGroup.Impassable, Func <IEntity, bool> predicate = null, bool insideBlockerValid = false) { var dir = otherCoords - 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, true); if (!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && (rayResults.HitPos - otherCoords).Length < 1f)) { if (_mapManager.TryFindGridAt(coords, out var mapGrid) && mapGrid != null) { var srcPos = mapGrid.MapToGrid(coords); var destPos = new GridCoordinates(otherCoords, mapGrid); if (srcPos.InRange(_mapManager, destPos, range)) { return(true); } } } return(false); }
/// <summary> /// Traces a ray from coords to otherCoords and returns the length /// of the vector between coords and the ray's first hit. /// </summary> /// <param name="coords">Set of coordinates to use.</param> /// <param name="otherCoords">Other set of coordinates to use.</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> /// <returns>Length of resulting ray.</returns> public float UnobstructedRayLength(MapCoordinates coords, MapCoordinates otherCoords, int collisionMask = (int)CollisionGroup.Impassable, Func <IEntity, bool> predicate = null) { var dir = otherCoords.Position - coords.Position; if (dir.LengthSquared.Equals(0f)) { return(0f); } var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask); var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, returnOnFirstHit: false).ToList(); if (rayResults.Count == 0) { return(dir.Length); } return((rayResults[0].HitPos - coords.Position).Length); }
/// <summary> /// Traces a ray from coords to otherCoords and returns the length /// of the vector between coords and the ray's first hit. /// </summary> /// <param name="origin">Set of coordinates to use.</param> /// <param name="other">Other set of coordinates to use.</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> /// <returns>Length of resulting ray.</returns> public float UnobstructedDistance( MapCoordinates origin, MapCoordinates other, int collisionMask = (int)CollisionGroup.Impassable, Ignored predicate = null) { var dir = other.Position - origin.Position; if (dir.LengthSquared.Equals(0f)) { return(0f); } predicate ??= _ => false; var ray = new CollisionRay(origin.Position, dir.Normalized, collisionMask); var rayResults = _physicsManager.IntersectRayWithPredicate(origin.MapId, ray, dir.Length, predicate.Invoke, false).ToList(); if (rayResults.Count == 0) { return(dir.Length); } return((rayResults[0].HitPos - origin.Position).Length); }
/// <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">.</param> /// <param name="insideBlockerValid">if coordinates inside obstructions count as obstructed or not</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 insideBlockerValid = 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).ToList(); return(rayResults.Count == 0 || (insideBlockerValid && rayResults.Count > 0 && (rayResults[0].HitPos - otherCoords.Position).Length < 1f)); }