2019-05-15 14:52:37 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Treadable.h"
|
|
|
|
|
2019-08-11 17:11:54 +00:00
|
|
|
class CVehicle;
|
2020-04-14 10:45:47 +00:00
|
|
|
class CPtrList;
|
2019-10-13 21:33:18 +00:00
|
|
|
|
2020-05-30 17:08:31 +00:00
|
|
|
#define LANE_WIDTH 5.0f
|
2020-09-29 19:53:12 +00:00
|
|
|
#define WIDTH_TO_PED_NODE_WIDTH (31.f/(500.f * 8.f))
|
2020-05-30 17:08:31 +00:00
|
|
|
|
2020-03-25 14:13:06 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
NodeTypeExtern = 1,
|
|
|
|
NodeTypeIntern = 2,
|
|
|
|
};
|
|
|
|
|
2019-08-09 17:42:18 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PATH_CAR = 0,
|
|
|
|
PATH_PED = 1,
|
|
|
|
};
|
|
|
|
|
2019-10-14 18:13:23 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
SWITCH_OFF = 0,
|
|
|
|
SWITCH_ON = 1,
|
|
|
|
};
|
|
|
|
|
2020-04-14 10:45:47 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
ROUTE_ADD_BLOCKADE = 0,
|
|
|
|
ROUTE_NO_BLOCKADE = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CPedPathNode
|
|
|
|
{
|
|
|
|
bool bBlockade;
|
|
|
|
uint8 nodeIdX;
|
|
|
|
uint8 nodeIdY;
|
|
|
|
int16 id;
|
|
|
|
CPedPathNode* prev;
|
|
|
|
CPedPathNode* next;
|
|
|
|
};
|
2020-05-10 13:54:37 +00:00
|
|
|
|
2020-05-10 15:49:33 +00:00
|
|
|
VALIDATE_SIZE(CPedPathNode, 0x10);
|
2020-04-14 10:45:47 +00:00
|
|
|
|
|
|
|
class CPedPath {
|
|
|
|
public:
|
|
|
|
static bool CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints);
|
|
|
|
static void AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList);
|
|
|
|
static void RemoveNodeFromList(CPedPathNode *pNode);
|
|
|
|
static void AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList);
|
|
|
|
static void AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition);
|
|
|
|
static void AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition);
|
|
|
|
};
|
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
struct CPathNode
|
|
|
|
{
|
2020-05-05 15:04:43 +00:00
|
|
|
int16 prevIndex;
|
|
|
|
int16 nextIndex;
|
|
|
|
int16 x;
|
|
|
|
int16 y;
|
|
|
|
int16 z;
|
|
|
|
int16 distance; // in path search
|
|
|
|
int16 firstLink;
|
2020-06-03 13:16:31 +00:00
|
|
|
uint8 width;
|
2020-05-05 15:04:43 +00:00
|
|
|
int8 group;
|
|
|
|
|
|
|
|
uint8 numLinks : 4;
|
|
|
|
uint8 bDeadEnd : 1;
|
|
|
|
uint8 bDisabled : 1;
|
|
|
|
uint8 bBetweenLevels : 1;
|
|
|
|
uint8 bUseInRoadBlock : 1;
|
|
|
|
|
|
|
|
uint8 bWaterPath : 1;
|
2020-05-08 20:29:43 +00:00
|
|
|
uint8 bOnlySmallBoats : 1;
|
2020-05-05 15:04:43 +00:00
|
|
|
uint8 flagB4 : 1; // where is this set?
|
|
|
|
uint8 speedLimit : 2;
|
|
|
|
//uint8 flagB20 : 1;
|
|
|
|
//uint8 flagB40 : 1;
|
|
|
|
//uint8 flagB80 : 1;
|
|
|
|
|
|
|
|
uint8 spawnRate : 4;
|
|
|
|
uint8 flagsC : 4;
|
|
|
|
|
|
|
|
CVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); }
|
|
|
|
void SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; }
|
|
|
|
float GetX(void) { return x/8.0f; }
|
|
|
|
float GetY(void) { return y/8.0f; }
|
|
|
|
float GetZ(void) { return z/8.0f; }
|
2020-05-30 17:08:31 +00:00
|
|
|
bool HasDivider(void) { return width != 0; }
|
2020-05-30 17:09:58 +00:00
|
|
|
float GetDividerWidth(void) { return width/(2*8.0f); }
|
2020-09-29 19:53:12 +00:00
|
|
|
float GetPedNodeWidth(void) { return width*WIDTH_TO_PED_NODE_WIDTH; }
|
2020-05-05 15:04:43 +00:00
|
|
|
CPathNode *GetPrev(void);
|
|
|
|
CPathNode *GetNext(void);
|
|
|
|
void SetPrev(CPathNode *node);
|
|
|
|
void SetNext(CPathNode *node);
|
2019-05-15 14:52:37 +00:00
|
|
|
};
|
|
|
|
|
2019-08-09 17:42:18 +00:00
|
|
|
union CConnectionFlags
|
|
|
|
{
|
|
|
|
uint8 flags;
|
|
|
|
struct {
|
|
|
|
uint8 bCrossesRoad : 1;
|
|
|
|
uint8 bTrafficLight : 1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2019-05-15 20:15:49 +00:00
|
|
|
struct CCarPathLink
|
2019-05-15 14:52:37 +00:00
|
|
|
{
|
2020-05-05 15:04:43 +00:00
|
|
|
int16 x;
|
|
|
|
int16 y;
|
|
|
|
int16 pathNodeIndex;
|
|
|
|
int8 dirX;
|
|
|
|
int8 dirY;
|
|
|
|
int8 numLeftLanes : 3;
|
|
|
|
int8 numRightLanes : 3;
|
|
|
|
uint8 flag1 : 1;
|
|
|
|
uint8 trafficLightType : 2;
|
|
|
|
uint8 bBridgeLights : 1; // at least in LCS...
|
|
|
|
int8 width;
|
|
|
|
|
|
|
|
CVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }
|
|
|
|
CVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }
|
|
|
|
float GetX(void) { return x/8.0f; }
|
|
|
|
float GetY(void) { return y/8.0f; }
|
|
|
|
float GetDirX(void) { return dirX/100.0f; }
|
|
|
|
float GetDirY(void) { return dirY/100.0f; }
|
2020-05-30 17:08:31 +00:00
|
|
|
float GetLaneOffset(void) { return width/(2*8.0f*LANE_WIDTH); }
|
2020-05-03 13:57:57 +00:00
|
|
|
|
2019-09-14 17:53:04 +00:00
|
|
|
float OneWayLaneOffset()
|
|
|
|
{
|
|
|
|
if (numLeftLanes == 0)
|
|
|
|
return 0.5f - 0.5f * numRightLanes;
|
|
|
|
if (numRightLanes == 0)
|
|
|
|
return 0.5f - 0.5f * numLeftLanes;
|
2020-05-06 21:27:10 +00:00
|
|
|
return 0.5f + GetLaneOffset();
|
2019-09-14 17:53:04 +00:00
|
|
|
}
|
2019-05-15 14:52:37 +00:00
|
|
|
};
|
|
|
|
|
2020-05-03 13:57:57 +00:00
|
|
|
// This is what we're reading from the files, only temporary
|
2019-05-15 14:52:37 +00:00
|
|
|
struct CPathInfoForObject
|
|
|
|
{
|
2020-05-05 15:04:43 +00:00
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
float z;
|
|
|
|
int8 type;
|
|
|
|
int8 next;
|
|
|
|
int8 numLeftLanes;
|
|
|
|
int8 numRightLanes;
|
|
|
|
int8 speedLimit;
|
|
|
|
int8 width;
|
|
|
|
|
|
|
|
uint8 crossing : 1;
|
2020-05-08 20:29:43 +00:00
|
|
|
uint8 onlySmallBoats : 1;
|
2020-05-05 15:04:43 +00:00
|
|
|
uint8 roadBlock : 1;
|
|
|
|
uint8 disabled : 1;
|
|
|
|
uint8 waterPath : 1;
|
|
|
|
uint8 betweenLevels : 1;
|
|
|
|
|
|
|
|
uint8 spawnRate : 4;
|
|
|
|
|
|
|
|
void SwapConnectionsToBeRightWayRound(void);
|
2019-05-15 14:52:37 +00:00
|
|
|
};
|
2020-04-17 05:54:14 +00:00
|
|
|
extern CPathInfoForObject *InfoForTileCars;
|
|
|
|
extern CPathInfoForObject *InfoForTilePeds;
|
2019-05-15 14:52:37 +00:00
|
|
|
|
|
|
|
struct CTempNode
|
|
|
|
{
|
|
|
|
CVector pos;
|
2020-05-05 15:04:43 +00:00
|
|
|
int8 dirX; // *100
|
|
|
|
int8 dirY;
|
|
|
|
int16 link1;
|
|
|
|
int16 link2;
|
|
|
|
int8 numLeftLanes;
|
|
|
|
int8 numRightLanes;
|
|
|
|
int8 width;
|
|
|
|
bool isCross;
|
|
|
|
int8 linkState;
|
2019-05-15 14:52:37 +00:00
|
|
|
};
|
|
|
|
|
2020-05-05 15:04:43 +00:00
|
|
|
struct CTempNodeExternal // made up name
|
|
|
|
{
|
|
|
|
CVector pos;
|
|
|
|
int16 next;
|
|
|
|
int8 numLeftLanes;
|
|
|
|
int8 numRightLanes;
|
|
|
|
int8 width;
|
|
|
|
bool isCross;
|
|
|
|
};
|
2019-05-15 14:52:37 +00:00
|
|
|
|
|
|
|
class CPathFind
|
|
|
|
{
|
|
|
|
public:
|
2019-08-09 17:42:18 +00:00
|
|
|
CPathNode m_pathNodes[NUM_PATHNODES];
|
|
|
|
CCarPathLink m_carPathLinks[NUM_CARPATHLINKS];
|
|
|
|
CTreadable *m_mapObjects[NUM_MAPOBJECTS];
|
2020-05-05 15:04:43 +00:00
|
|
|
uint16 m_connections[NUM_PATHCONNECTIONS]; // and flags
|
|
|
|
uint8 m_distances[NUM_PATHCONNECTIONS];
|
2019-08-09 17:42:18 +00:00
|
|
|
int16 m_carPathConnections[NUM_PATHCONNECTIONS];
|
2020-05-03 13:57:57 +00:00
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
int32 m_numPathNodes;
|
|
|
|
int32 m_numCarPathNodes;
|
|
|
|
int32 m_numPedPathNodes;
|
|
|
|
int16 m_numMapObjects;
|
2019-05-15 20:15:49 +00:00
|
|
|
int16 m_numConnections;
|
|
|
|
int32 m_numCarPathLinks;
|
2019-08-09 17:42:18 +00:00
|
|
|
int32 unk;
|
2019-05-15 14:52:37 +00:00
|
|
|
uint8 m_numGroups[2];
|
2019-08-09 17:42:18 +00:00
|
|
|
CPathNode m_searchNodes[512];
|
2019-05-15 14:52:37 +00:00
|
|
|
|
2019-08-09 17:42:18 +00:00
|
|
|
void Init(void);
|
|
|
|
void AllocatePathFindInfoMem(int16 numPathGroups);
|
|
|
|
void RegisterMapObject(CTreadable *mapObject);
|
2020-05-05 21:27:43 +00:00
|
|
|
void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate);
|
|
|
|
void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,
|
|
|
|
bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate);
|
|
|
|
void StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,
|
|
|
|
bool disabled, bool betweenLevels, uint8 spawnRate);
|
|
|
|
void StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,
|
|
|
|
bool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk);
|
2020-05-05 15:04:43 +00:00
|
|
|
void CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);
|
2019-08-09 17:42:18 +00:00
|
|
|
bool LoadPathFindData(void);
|
2019-05-15 14:52:37 +00:00
|
|
|
void PreparePathData(void);
|
|
|
|
void CountFloodFillGroups(uint8 type);
|
|
|
|
void PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,
|
2020-05-05 15:04:43 +00:00
|
|
|
float maxdist, CPathInfoForObject *detachednodes, int32 numDetached);
|
2019-06-18 07:50:26 +00:00
|
|
|
|
|
|
|
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
|
2019-07-04 11:04:34 +00:00
|
|
|
|
2019-08-09 17:42:18 +00:00
|
|
|
float CalcRoadDensity(float x, float y);
|
|
|
|
bool TestForPedTrafficLight(CPathNode *n1, CPathNode *n2);
|
|
|
|
bool TestCrossesRoad(CPathNode *n1, CPathNode *n2);
|
|
|
|
void AddNodeToList(CPathNode *node, int32 listId);
|
|
|
|
void RemoveNodeFromList(CPathNode *node);
|
|
|
|
void RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n);
|
2019-07-04 11:04:34 +00:00
|
|
|
void SetLinksBridgeLights(float, float, float, float, bool);
|
2019-08-09 17:42:18 +00:00
|
|
|
void SwitchOffNodeAndNeighbours(int32 nodeId, bool disable);
|
|
|
|
void SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable);
|
|
|
|
void SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable);
|
|
|
|
void SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 enable);
|
|
|
|
void MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);
|
|
|
|
void MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
|
2020-02-16 20:08:54 +00:00
|
|
|
void PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);
|
2020-05-05 16:06:38 +00:00
|
|
|
// TODO(MIAMI): check callers for new arguments
|
2020-05-05 15:04:43 +00:00
|
|
|
int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreFlagB4 = false, bool bWaterPath = false);
|
2019-08-09 17:42:18 +00:00
|
|
|
int32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);
|
|
|
|
float FindNodeOrientationForCarPlacement(int32 nodeId);
|
|
|
|
float FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards);
|
|
|
|
bool NewGenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false);
|
|
|
|
bool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix);
|
|
|
|
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);
|
|
|
|
void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);
|
|
|
|
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
|
2019-10-08 20:07:11 +00:00
|
|
|
void Save(uint8 *buf, uint32 *size);
|
|
|
|
void Load(uint8 *buf, uint32 size);
|
2020-05-05 15:04:43 +00:00
|
|
|
|
2020-06-03 13:16:31 +00:00
|
|
|
static CVector TakeWidthIntoAccountForWandering(CPathNode*, uint16);
|
2020-09-26 23:36:49 +00:00
|
|
|
static void TakeWidthIntoAccountForCoors(CPathNode*, CPathNode*, uint16, float*, float*);
|
2020-06-03 13:16:31 +00:00
|
|
|
|
2020-05-05 15:04:43 +00:00
|
|
|
CPathNode *GetNode(int16 index);
|
|
|
|
int16 GetIndex(CPathNode *node);
|
|
|
|
|
|
|
|
uint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; }
|
|
|
|
bool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); }
|
|
|
|
bool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); }
|
|
|
|
void ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; }
|
2020-05-03 13:57:57 +00:00
|
|
|
|
2020-04-10 16:36:39 +00:00
|
|
|
void DisplayPathData(void);
|
2019-05-15 14:52:37 +00:00
|
|
|
};
|
|
|
|
|
2020-04-17 05:54:14 +00:00
|
|
|
extern CPathFind ThePaths;
|
2020-04-10 16:36:39 +00:00
|
|
|
|
2020-05-05 15:04:43 +00:00
|
|
|
inline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); }
|
|
|
|
inline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); }
|
|
|
|
inline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); }
|
|
|
|
inline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); }
|
|
|
|
|
2020-04-10 16:36:39 +00:00
|
|
|
extern bool gbShowPedPaths;
|
|
|
|
extern bool gbShowCarPaths;
|
|
|
|
extern bool gbShowCarPathsLinks;
|