Files
source/Tactical/PATHAI.H
T
Shadooow 43dfa982a5 Bright future is here, introduced turning AP costs into pathing AP prediction. Full changelog:
- fixed camera action AP cost shown and made soldier to turn towards target
- fixed handcuffs, jar and can actions AP cost shown calculating pathing cost twice and not calculating stance change at all
- fixed refueling and repairing pathing leading to inside vehicle
- fixed endless clock issue when trying to refuel from spot next to vehicle
- fixed endless clock issue when trying to repair vehicle/SAM site during combat
- fixed refuel, repair and jar actions not costing any AP in turn based mode
- fixed multiple actions not calculating and substracting AP cost for turning
- fixed using toolkit asking whether player wants to attack ally
- fixed issue where the required AP cost for melee attack was not recalculated when changing movement mode
- allowed to start repairs on robot manually from tactical mode
still a problem:
- repairing during combat still does nothing as soldiers cannot go into assignment while there are enemies on map
- we need new function to return action gridno for actions on vehicles, FindAdjacentGridEx is not working very well
- soldiers doesn't turn during interactive actions

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9033 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2021-05-20 11:42:57 +00:00

328 lines
11 KiB
C++

/*
Filename : pathai.h
Author : Ray E. Bornert II
Date : 1992-MAR-15
Copyright (C) 1993 HixoxiH Software
*/
#ifndef _PATHAI_H
#define _PATHAI_H
#include "isometric utils.h"
// WANNE: Please do not use ASTAR pathing,
// because it is a HUGH PERFORMANCE KILLER on big maps!!
//#define USE_ASTAR_PATHS
#ifdef USE_ASTAR_PATHS
namespace ASTAR {
#include "BinaryHeap.hpp"
#include <vector>
enum eAStar
{
AStar_Init,
AStar_Open,
AStar_Closed
};
class AStar_Data
{
public:
AStar_Data()
{
cost = directionFromPrev = 0;
extraGCoverCost = -1;//-1 means we have not stopped at this node
wasBackwards = false;
status = AStar_Init;
parent = -1;
};
// h is calculated on the fly
INT16 cost;//G
//int f;//F is also calculated on the fly
//int APCost;//the APs spent to get here // Isn't this the same as "cost"?
int extraGCoverCost;//an extra cost that makes stopping in midpath at a node with little cover worse
INT32 parent;
eAStar status;
//int prevCost;
bool wasBackwards;
UINT8 directionFromPrev;
int numSteps;
};
class AStarPathfinder
{
public:
AStarPathfinder ();
static AStarPathfinder& GetInstance();
int GetPath (SOLDIERTYPE *s ,
INT32 dest,
INT8 ubLevel,
INT16 usMovementMode,
INT8 bCopy,
UINT8 fFlags );
private:
static AStarPathfinder* pThis;
CBinaryHeap<int, INT32> OpenHeap;
// The "closed list" is the AStarData array below which is also the path backtrace when a path is found.
// For PythSpacesAway, we do not really need the distance, but rather something to compare against.
// So I will eliminate the sqrt function from the result for the sake of speed. This means that when comparing against
// input distances, we should square them. This is one of the variables that needs to hold the squared value.
int gubNPCDistLimitSq;
UINT8 direction;//current direction
UINT8 startDir;
UINT8 endDir;
UINT8 lastDir;
bool startingLoop;
SOLDIERTYPE* pSoldier;
INT8 onRooftop;//aka ubLevel, not sure if this bool is logically reversed yet
bool fNonFenceJumper;
bool fNonSwimmer;
bool fPathingForPlayer;
bool fPathAroundPeople;
bool fGoingThroughDoor;
INT16 bOKToAddStructID;
int bLoopState;
bool bWaterToWater;
bool fVisitSpotsOnlyOnce;
bool fCheckedBehind;
bool fTurnBased;
bool fCloseGoodEnough;
bool fContinuousTurnNeeded;
bool fConsiderPersonAtDestAsObstacle;
bool fCopyReachable;
bool fCopyPathCosts;
bool fFindClimbPoints;
int maxAPBudget;//the gubNPCAPBudget
int mercsMaxAPs;//the merc only has so many points to move with
UINT16 movementMode;
int sClosePathLimitSq;
int travelcostDiag;
int travelcostOrth;
INT16 PATHAI_VISIBLE_DEBUG_Counter;
//vehicle defined in cpp
//#ifdef VEHICLE
BOOLEAN fMultiTile;
STRUCTURE_FILE_REF * pStructureFileRef;
//#endif
// member variables to prevent passing them around
INT32 StartNode;
INT32 DestNode;
INT32 CurrentNode;
INT32 ParentNode;
// WANNE - BMP: DONE!
//AStar_Data AStarData[WORLD_MAX];
AStar_Data AStarData[MAX_ALLOWED_WORLD_MAX];
INT16 AStar ();
void ExecuteAStarLogic();
void ResetAStarList ();
int TerrainCostToAStarG(int const terrainCost);
int CalcG (int* pPrevCost);
INT16 CalcAP (int const terrainCost, UINT8 const direction);
int CalcH ();
int CalcGCover (int const NodeIndex,
int const APCost);
INT16 CalcStartingAP ();
//including THREATTYPE was a pain, so pass by value
int CalcCoverValue (INT32 sMyGridNo, INT32 iMyThreat, INT32 iMyAPsLeft,
INT32 myThreatsiOrigRange, INT32 myThreatssGridNo, SOLDIERTYPE* myThreatspOpponent,
INT32 myThreatsiValue, INT32 myThreatsiAPs, INT32 myThreatsiCertainty);
eAStar GetAStarStatus (const INT32 node) const {return AStarData[node].status;};
INT32 GetAStarParent (const INT32 node) const {return AStarData[node].parent;};
INT16 GetAStarG (INT32 node) const {return AStarData[node].cost;};
int GetExtraGCover (const INT32 node) const {return AStarData[node].extraGCoverCost;};
//int GetAStarF (const INT16 node) const {return AStarData[node].f;};
//int GetActionPoints (const INT16 node) const {return AStarData[node].APCost;};
bool GetLoopState (const INT32 node) const {return AStarData[node].wasBackwards;};
//int GetPrevCost (const INT16 node) const {return AStarData[node].prevCost;};
UINT8 GetDirection (const INT32 node) const {return AStarData[node].directionFromPrev;};
int GetNumSteps (const INT32 node) const {return AStarData[node].numSteps;};
void SetAStarStatus (const INT32 node, const eAStar status) {AStarData[node].status = status;};
void SetAStarParent (const INT32 node, const INT32 parent) {AStarData[node].parent = parent;};
void SetAStarG (const INT32 node, const INT16 cost) {AStarData[node].cost = cost;};
void SetExtraGCover (const INT32 node, const int extraGCoverCost) {AStarData[node].extraGCoverCost = extraGCoverCost;};
//void SetAStarF (const INT16 node, const int f) {AStarData[node].f = f;};
//void SetActionPoints (const INT16 node, const int APCost) {AStarData[node].APCost = APCost;};
void SetLoopState (const INT32 node, const int loopState);
//void SetPrevCost (const INT16 node, const int prevCost) {AStarData[node].prevCost = prevCost;};
void SetDirection (const INT32 node, const UINT8 direction) {AStarData[node].directionFromPrev = direction;};
void SetNumSteps (const INT32 node, const int steps) {AStarData[node].numSteps = steps;};
int PythSpacesAway (const INT32 node1,
const INT32 node2);
INT16 SpacesAway (const INT32 node1,
const INT32 node2);
//bool IsDiagonal (const INT16 node1,
// const INT16 node2) {return (abs(node1.x - node2.x) && abs(node1.y - node2.y));};
bool IsDiagonal (int const direction) {return (direction & 1);};
void InitVehicle ();
int VehicleObstacleCheck();
bool WantToTraverse (); // Renamed this because it doesn't mean "can we traverse" but rather, if it is profitable to.
bool IsSomeoneInTheWay();
void IncrementLoop ();
void InitLoop ();
bool ContinueLoop ();
};
};//end namespace ASTAR
#endif// USE_ASTAR_PATHS
BOOLEAN InitPathAI( void );
void ShutDownPathAI( void );
INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
INT32 UIPlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
INT32 EstimatePlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
void ErasePath(char bEraseOldOne);
INT32 FindBestPath(SOLDIERTYPE *s , INT32 sDestination, INT8 ubLevel, INT16 usMovementMode, INT8 bCopy, UINT8 fFlags );
void GlobalReachableTest( INT32 sStartGridNo );
void GlobalItemsReachableTest( INT32 sStartGridNo1, INT32 sStartGridNo2 );
void RoofReachableTest( INT32 sStartGridNo, UINT8 ubBuildingID );
void LocalReachableTest( INT32 sStartGridNo, INT8 bRadius );
UINT8 DoorTravelCost( SOLDIERTYPE * pSoldier, INT32 iGridNo, UINT8 ubMovementCost, BOOLEAN fReturnPerceivedValue, INT32 * piDoorGridNo );
UINT8 InternalDoorTravelCost( SOLDIERTYPE * pSoldier, INT32 iGridNo, UINT8 ubMovementCost, BOOLEAN fReturnPerceivedValue, INT32 * piDoorGridNo, BOOLEAN fReturnDoorCost );
INT16 RecalculatePathCost( SOLDIERTYPE *pSoldier, UINT16 usMovementMode );
//dnl ch50 071009
// ABSOLUTE maximums
#define ABSMAX_SKIPLIST_LEVEL 10 // was 5
#define ABSMAX_TRAIL_TREE (WORLD_MAX) // was 16384
#define ABSMAX_PATHQ (ABSMAX_TRAIL_TREE/16) // was 512
// STANDARD maximums... configurable!
#define MAX_SKIPLIST_LEVEL ABSMAX_SKIPLIST_LEVEL// was 5
#define MAX_TRAIL_TREE ABSMAX_TRAIL_TREE // was 16384
#define MAX_PATHQ ABSMAX_PATHQ // was 512
// Lesh: setup max length of path
#define MAX_PATH_DATA_LENGTH MAX_PATHQ // was 512
#define TRAILCELLTYPE UINT16 //Lalien: moved form pathai.cpp
// Exporting these global variables
extern UINT32* guiPathingData;
extern INT16 gubNPCAPBudget;
extern UINT16 gusNPCMovementMode;
extern UINT8 gubNPCDistLimit;
extern UINT8 gubNPCPathCount;
extern BOOLEAN gfPlotPathToExitGrid;
extern BOOLEAN gfNPCCircularDistLimit;
extern BOOLEAN gfEstimatePath;
extern BOOLEAN gfPathAroundObstacles;
extern UINT8 gubGlobalPathFlags;
extern UINT8 gfPlotPathEndDirection;
// Ian's terrain values for travelling speed/pathing purposes
// Fixed by CJC March 4, 1998. Please do not change these unless familiar
// with how this will affect the path code!
#define TRAVELCOST_NONE 0
#define TRAVELCOST_FLAT 10
#define TRAVELCOST_BUMPY 12
#define TRAVELCOST_GRASS 12
#define TRAVELCOST_THICK 16
#define TRAVELCOST_DEBRIS 20
#define TRAVELCOST_SHORE 30
#define TRAVELCOST_KNEEDEEP 36
#define TRAVELCOST_DEEPWATER 50
#define TRAVELCOST_FENCE 40
// these values are used to indicate "this is an obstacle
// if there is a door (perceived) open/closed in this tile
#define TRAVELCOST_DOOR_CLOSED_HERE 220
#define TRAVELCOST_DOOR_CLOSED_N 221
#define TRAVELCOST_DOOR_CLOSED_W 222
#define TRAVELCOST_DOOR_OPEN_HERE 223
#define TRAVELCOST_DOOR_OPEN_N 224
#define TRAVELCOST_DOOR_OPEN_NE 225
#define TRAVELCOST_DOOR_OPEN_E 226
#define TRAVELCOST_DOOR_OPEN_SE 227
#define TRAVELCOST_DOOR_OPEN_S 228
#define TRAVELCOST_DOOR_OPEN_SW 229
#define TRAVELCOST_DOOR_OPEN_W 230
#define TRAVELCOST_DOOR_OPEN_NW 231
#define TRAVELCOST_DOOR_OPEN_N_N 232
#define TRAVELCOST_DOOR_OPEN_NW_N 233
#define TRAVELCOST_DOOR_OPEN_NE_N 234
#define TRAVELCOST_DOOR_OPEN_W_W 235
#define TRAVELCOST_DOOR_OPEN_SW_W 236
#define TRAVELCOST_DOOR_OPEN_NW_W 237
#define TRAVELCOST_NOT_STANDING 248
#define TRAVELCOST_OFF_MAP 249
#define TRAVELCOST_CAVEWALL 250
#define TRAVELCOST_HIDDENOBSTACLE 251
#define TRAVELCOST_DOOR 252
#define TRAVELCOST_OBSTACLE 253
#define TRAVELCOST_WALL 254
#define TRAVELCOST_EXITGRID 255
///ddd { window
#define TRAVELCOST_JUMPABLEWINDOW 46
#define TRAVELCOST_JUMPABLEWINDOW_N 47
#define TRAVELCOST_JUMPABLEWINDOW_W 48
///ddd window }
#define TRAVELCOST_TRAINTRACKS 30
#define TRAVELCOST_DIRTROAD 9
#define TRAVELCOST_PAVEDROAD 9
#define TRAVELCOST_FLATFLOOR 10
#define TRAVELCOST_BLOCKED (TRAVELCOST_OFF_MAP)
#define IS_TRAVELCOST_DOOR( x ) (x >= TRAVELCOST_DOOR_CLOSED_HERE && x <= TRAVELCOST_DOOR_OPEN_NW_W)
#define IS_TRAVELCOST_CLOSED_DOOR( x ) (x >= TRAVELCOST_DOOR_CLOSED_HERE && x << TRAVELCOST_DOOR_CLOSED_W)
// ------------------------------------------
// PLOT PATH defines
#define NOT_STEALTH 0
#define STEALTH 1
#define NO_PLOT 0
#define PLOT 1
#define TEMPORARY 0
#define PERMANENT 1
#define FORWARD 0
#define REVERSE 1
#define NO_COPYROUTE 0
#define COPYROUTE 1
#define COPYREACHABLE 2
#define COPYREACHABLE_AND_APS 3
#define FINDCLIMBPOINTS 4
#define PATH_THROUGH_PEOPLE 0x01
#define PATH_IGNORE_PERSON_AT_DEST 0x02
#define PATH_CLOSE_GOOD_ENOUGH 0x04
#define PATH_CLOSE_RADIUS 5
#define PATH_CLOSE_RADIUS_SQ 25
// ------------------------------------------
#endif