/// <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);
        }
Exemple #3
0
        /// <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));
        }