PC-20230316NUNE\Administrator 2b467e56ad no message
2024-02-20 18:39:12 +08:00

341 lines
10 KiB
C#

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