public static Vector3 GetValidCastSpot(this Vector3 castPosition) { // If the position is not a wall then return the input position var flags = castPosition.ToNavMeshCell().CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { return(castPosition); } const int maxRange = 20; const double step = 2 * Math.PI / 20; var start = new Vector2(castPosition.ToNavMeshCell().GridX, castPosition.ToNavMeshCell().GridY); var checkedCells = new HashSet <Vector2>(); // Get all directions var directions = new List <Vector2>(); for (var theta = 0d; theta <= 2 * Math.PI + step; theta += step) { directions.Add((new Vector2((short)(start.X + Math.Cos(theta)), (short)(start.Y - Math.Sin(theta))) - start).Normalized()); } var validPositions = new HashSet <Vector3>(); for (var range = 1; range < maxRange; range++) { // ReSharper disable once LoopCanBePartlyConvertedToQuery foreach (var direction in directions) { // Get the position to check var end = start + range * direction; var testPoint = new Vector2((short)end.X, (short)end.Y); if (checkedCells.Contains(testPoint)) { continue; } checkedCells.Add(testPoint); // Check the position for wall flags flags = new NavMeshCell((short)testPoint.X, (short)testPoint.Y).CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { // Add the position to the valid positions set validPositions.Add(NavMesh.GridToWorld((short)testPoint.X, (short)testPoint.Y)); } } if (validPositions.Count > 0) { // Return the closest position to the initial wall position return(validPositions.OrderBy(o => o.Distance(start, true)).First()); } } // Nothing found return input return(castPosition); }
public static Vector3 GetClosestWardSpot(this Vector3 wallPosition) { // If the position is not a wall then return the input position var flags = wallPosition.ToNavMeshCell().CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { return wallPosition; } const int maxRange = 10; const double step = 2 * Math.PI / 20; var start = new Vector2(wallPosition.ToNavMeshCell().GridX, wallPosition.ToNavMeshCell().GridY); var checkedCells = new HashSet<Vector2>(); // Get all directions var directions = new List<Vector2>(); for (var theta = 0d; theta <= 2 * Math.PI + step; theta += step) { directions.Add((new Vector2((short) (start.X + Math.Cos(theta)), (short) (start.Y - Math.Sin(theta))) - start).Normalized()); } var validPositions = new HashSet<Vector3>(); for (var range = 1; range < maxRange; range++) { foreach (var direction in directions) { // Get the position to check var end = start + range * direction; var testPoint = new Vector2((short) end.X, (short) end.Y); if (checkedCells.Contains(testPoint)) { continue; } checkedCells.Add(testPoint); // Check the position for wall flags flags = new NavMeshCell((short) testPoint.X, (short) testPoint.Y).CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { // Add the position to the valid positions set validPositions.Add(NavMesh.GridToWorld((short) testPoint.X, (short) testPoint.Y)); } } if (validPositions.Count > 0) { // Return the closest position to the initial wall position return validPositions.OrderBy(o => o.Distance(start, true)).First(); } } // Nothing found return input return wallPosition; }
public static Vector3 GetValidCastSpot(Vector3 castPosition) { var flags = castPosition.ToNavMeshCell().CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { return(castPosition); } const int maxRange = 20; const double step = 2 * Math.PI / 20; var start = new Vector2(castPosition.ToNavMeshCell().GridX, castPosition.ToNavMeshCell().GridY); var checkedCells = new HashSet <Vector2>(); var directions = new List <Vector2>(); for (var theta = 0d; theta <= 2 * Math.PI + step; theta += step) { directions.Add((new Vector2((short)(start.X + Math.Cos(theta)), (short)(start.Y - Math.Sin(theta))) - start).Normalized()); } var validPositions = new HashSet <Vector3>(); for (var range = 1; range < maxRange; range++) { foreach (var direction in directions) { var end = start + range * direction; var testPoint = new Vector2((short)end.X, (short)end.Y); if (checkedCells.Contains(testPoint)) { continue; } checkedCells.Add(testPoint); flags = new NavMeshCell((short)testPoint.X, (short)testPoint.Y).CollFlags; if (!flags.HasFlag(CollisionFlags.Wall) && !flags.HasFlag(CollisionFlags.Building)) { validPositions.Add(NavMesh.GridToWorld((short)testPoint.X, (short)testPoint.Y)); } } if (validPositions.Count > 0) { return(validPositions.OrderBy(o => o.Distance(start, true)).First()); } } return(castPosition); }