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;
}
}
}