using HPJ.Simulation.Enums; using HPJ.Simulation.Map; using HPJ.Simulation.Utilities; using System; using System.Collections; using System.Collections.Generic; namespace HPJ.Simulation.Pathing { /// /// The Base class for any pathfinding algorithms /// public abstract class PathingCalculation { /// /// The Navigation Type this pathing is. Will need to add yours to the enum /// public NavigationTypes NavigationType { get; protected set; } /// /// The Dictionary of all the pathing algorithms /// public static Dictionary PathingTypes = new Dictionary(); public PathingCalculation() { Initialize(); } /// /// Initializes the Algorithm, You will need to call this or add this for your algorithm /// public virtual void Initialize() { NavigationType = NavigationTypes.None; if (!PathingTypes.ContainsKey(NavigationType)) { PathingTypes.Add(NavigationType, this); } } /// /// Calculates the Path for a Navigation Job Request on a specific Map /// /// /// /// /// public abstract void CalculatePath(NavigationPath Path, Map.Map OccuringMap, out string Status, out bool Succeeded); } /// /// A Navigation Job Request /// [Serializable] public class NavigationJob { #region Navigation Info /// /// Infomation on this Job /// public PathingInfo Info; /// /// Current Step on the Pathfinding Calculation /// public PathfindingCalculationStep CurrentStep; /// /// The Number of tiles away from the start to the end /// public int TilesAway; /// /// Point A of the Path /// public IntVector3 WorldPointA; /// /// Point B of the Path /// public IntVector3 WorldPointB; /// /// If this Job was compatable or not /// public bool Compatable; /// /// Next time this path is pathed, repath it /// public bool RepathSavedPath; /// /// List of Traversable Tiles /// public List TraverableTileTypes; /// /// List of Prefferred Tiles /// public List PrefferedTileTypes; #endregion #region Navigation Results /// /// The Resulting Path for this Job Request /// public NavigationPath CurrentPath { get; protected set; } public ushort AgentID { get; set; } /// /// The Callback to the presentation side /// public Action OnCompleteCallback; #endregion public NavigationJob(Action onCompleteCallback) { Info = new PathingInfo(); CurrentPath = null; CurrentStep = PathfindingCalculationStep.Incomplete; OnCompleteCallback = onCompleteCallback; AgentID = 0; } /// /// Clears the Job and reverts it back to default /// public void Clear() { Info = new PathingInfo(); CurrentPath = null; CurrentStep = PathfindingCalculationStep.Incomplete; } /// /// Initializes the Job with the neccessary pathing information /// /// /// /// /// /// /// /// public void SetDestinationInfo(IntVector3 Start, IntVector3 End, List TraverableTiles, List PrefferedTiles, NavigationTypes Navigation, MapSet ForMap, bool RepathAnyway = false) { if (Start.x < End.x) { WorldPointA = Start; WorldPointB = End; } else if (Start.x > End.x) { WorldPointA = End; WorldPointB = Start; } else { if (Start.z < End.z) { WorldPointA = Start; WorldPointB = End; } else if (Start.z > End.z) { WorldPointA = End; WorldPointB = Start; } else { WorldPointA = Start; WorldPointB = End; } } TraverableTileTypes = TraverableTiles; PrefferedTileTypes = PrefferedTiles; RepathSavedPath = RepathAnyway; Info = new PathingInfo(ForMap.GetMapTileIndex(WorldPointA), ForMap.GetMapTileIndex(WorldPointB), Navigation, TraverableTiles.TilesToString(), PrefferedTiles.TilesToString()); TilesAway = JumpPointSearch.Instance.CalculateDistanceCost(Start.x, Start.z, End.x, End.z); Compatable = ForMap.JobCompatible(this); } /// /// Sets the resulting path to the request /// /// internal void SetNewCurrentPath(NavigationPath path) { CurrentPath = path; } /// /// The callback from the simulation when the job request is finished /// internal void PathfindingComplete() { CurrentStep = PathfindingCalculationStep.Complete; OnCompleteCallback?.Invoke(); } } /// /// The Calculated Path on a specific Map /// [System.Serializable] public class NavigationPath { /// /// The map the path was calculated on /// public Map.Map HostMap; /// /// The Information on this Path /// public PathingInfo Info; /// /// The Resulting Path /// public List Path; /// /// If this Path resulting in a valid path /// public bool ValidPath; /// /// Previous status on the path /// public string PreviousStatus { get; set; } /// /// Asking For Path from specific agent /// public ushort AgentID; public NavigationPath() { Info = new PathingInfo(); Path = new List(); ValidPath = false; PreviousStatus = ""; AgentID = 0; } public NavigationPath(PathingInfo PathInfo, Map.Map hostMap, ushort ID = 0) { Info = PathInfo; Path = new List(); ValidPath = false; HostMap = hostMap; PreviousStatus = ""; AgentID = 0; } /// /// Checks to see if your starting point is the first index of the path or the last /// /// /// public bool NeedToReverse(IntVector3 startPoint) { if (!ValidPath) { return false; } if (Path.Count <= 0) { return false; } return Path[0] != HostMap.GetTileIndexPosition(startPoint); } } /// /// The information on a given path /// [System.Serializable] public struct PathingInfo { /// /// Point A of a Path /// public IntVector2 PointA; /// /// Point B of a Path /// public IntVector2 PointB; /// /// Navigation type used for this Path /// public NavigationTypes NavigationType; /// /// Traversable Tiles Key /// public string TraversableTilesKey; /// /// Preffered Tile Kep /// public string PrefferedTilesKey; public PathingInfo(IntVector2 A, IntVector2 B, NavigationTypes Type, string Traverable, string Preffered) { // Sort tiles by bottom left so there is no repeats in the saved path Dictionary if (A.x < B.x) { PointA = A; PointB = B; } else if (A.x > B.x) { PointA = B; PointB = A; } else { if (A.y < B.y) { PointA = A; PointB = B; } else if (A.y > B.y) { PointA = B; PointB = A; } else { PointA = A; PointB = B; } } NavigationType = Type; TraversableTilesKey = Traverable; PrefferedTilesKey = Preffered; } } }