Files
firestorm/Gameleap/code/mw4/Code/MW4/rail_move.hpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1013 lines
33 KiB
C++

#pragma once
#ifndef __RAILMOVEHPP__
#define __RAILMOVEHPP__
#include "mw4.hpp"
#include "adept\applicationtask.hpp"
#include "aiutils.hpp"
#include "vehicle.hpp"
#include <gameos\gameos.hpp>
#include "quadtree.hpp"
#pragma warning(push)
#include <vector>
#include <stack>
#pragma warning (pop)
// Editor specific code
//#ifdef GAMEEDITOR
#include <ElementRenderer\LineCloudElement.hpp>
//#endif
//#include "utils\utils.h"
//--------------------------------------------------------------------
Stuff::Scalar GetMapY(Stuff::Scalar x, Stuff::Scalar z);
namespace MW4AI
{
extern HGOSHEAP g_AIHeap,g_MoverAIHeap,g_CombatAIHeap,g_RailHeap;
typedef void (*WorkCallBack) (float);
extern Stuff::Scalar MinZ, MaxZ, MinX, MaxX;
extern bool twofalse[2],twotrue[2];
extern int twomax[2];
class CRailNode;
class CRailLink;
class CRailGraph;
class CMoveGrid;
class CAirMoveGrid;
class CPathRequest;
class CGridPath;
class CRailPath;
class CMoveRectList;
struct OBRect;
const int MAXLINKS=10000;
const int MAXNODES=2000;
const int MINLINKCALC = 10;
const int MAXLINKCALC = 15;
const int LINKDIST = 300;
const int BLOCK_GRID_SIZE = 128;
const int BLOCK_GRID_RES = 10; // meters per cell
const int MACROBLOCK_GRID_RES = 80; // meters per cell
const int MACROBLOCK_GRID_SIZE = 1280 / MACROBLOCK_GRID_RES;
const int BLOCK_TO_MACROBLOCK = (MACROBLOCK_GRID_RES / BLOCK_GRID_RES);
const int AIR_BLOCK_GRID_SIZE = 64;
const int AIR_BLOCK_GRID_RES = 20; // meters per cell
const int GRIDMOVE_FAIL_THRESHOLD = 250; // number of cells to visit before failure to find path
const int GRIDMOVE_MAX_CHECK_THRESHOLD = 5000;
// mapquery project has a copy of these also.
const unsigned char AIRPASS_FLAG = 0x01; // true if air units cannot pass
const unsigned short LEGPASS_FLAG = 0x0001; // true if legged units cannot use
const unsigned short HOVERPASS_FLAG = 0x0002; // true if hover units cannot use
const unsigned short TRACKPASS_FLAG = 0x0004; // true if track units cannot use
const unsigned short WHEELPASS_FLAG = 0x0008; // true if wheel units cannot use
const unsigned short WATERPASS_FLAG = 0x0010; // true if water units cannot use
const unsigned short JUMPPASS_FLAG = 0x0020; // true if cannot jump through
const unsigned short MOVEPASSNOW_FLAG = 0x0040; // if a vehicle has this cell blocked now
const unsigned short BRIDGE_FLAG = 0x0080; // true if this cell is a bridge cell
const unsigned short WATER1_FLAG = 0x0100; // with water 2 for four levels of water
const unsigned short WATER2_FLAG = 0x0200; // no, shallow, medium, deep
const unsigned short STEEP1_FLAG = 0x0400; // with steep 2 for steepness of slope for descending, going up uses blocked flags
const unsigned short STEEP2_FLAG = 0x0800; // mech down, track down, wheel down, hover down
const unsigned short SLOPEDIR1_FLAG = 0x1000; // quanta of slope direction
const unsigned short SLOPEDIR2_FLAG = 0x2000;
const unsigned short SLOPEDIR3_FLAG = 0x4000;
const int HOVERDOWN_SLOPE = 0;
const int WHEELDOWN_SLOPE = 1;
const int TRACKDOWN_SLOPE = 2;
const int LEGDOWN_SLOPE = 3;
const int STEEP_MASK = 0x0c00;
const int STEEP_SHIFT = 10;
const int NO_WATER = 0;
const int SHALLOW_WATER = 1;
const int MEDIUM_WATER = 2;
const int DEEP_WATER = 3;
const int WATER_MASK = 0x0300;
const int WATER_SHIFT = 8;
const int SLOPEDIR_MASK = 0x7000;
const int SLOPEDIR_SHIFT = 12;
const int UPSLOPE_STRAIGHT_COST = 14;
const int UPSLOPE_DIAG_COST = 21;
const int STRAIGHT_COST = 10;
const int DIAG_COST = 15;
const int DOWNSLOPE_STRAIGHT_COST = 13;
const int DOWNSLOPE_DIAG_COST = 19;
// const float LEGUP_SLOPE_THRESHOLD = 0.707f; //cos (45 deg)
// const float LEGDOWN_SLOPE_THRESHOLD = 0.5f; //cos (60 deg)
// const float TRACKUP_SLOPE_THRESHOLD = 0.819f; //cos (35 deg)
// const float TRACKDOWN_SLOPE_THRESHOLD = 0.707f; //cos (45 deg)
// const float WHEELUP_SLOPE_THRESHOLD = 0.906f; //cos (25 deg)
// const float WHEELDOWN_SLOPE_THRESHOLD = 0.819f; //cos (35 deg)
// const float HOVERUP_SLOPE_THRESHOLD = 0.965f; //cos (15 deg)
// const float HOVERDOWN_SLOPE_THRESHOLD = 0.906f; //cos (25 deg)
const unsigned short BLOCKED_FLAGS = 0x003f; // for all blocked flags
//--------------------------------------------------------------------
// note: these two areas of const's must match
const int JUMPFLAG = 0x0001;
const int TRACKFLAG = 0x0002;
const int FLYFLAG = 0x0004;
const int WHEELFLAG = 0x0008;
const int LEGFLAG = 0x0010;
const int HOVERFLAG = 0x0020;
const int HELIFLAG = 0x0040;
const int WATERFLAG = 0x0100;
const int BRIDGEFLAG = 0x0080; // implied from data so not listed as index
const int JUMPINDEX = 0;
const int TRACKINDEX = 1;
const int FLYINDEX = 2;
const int WHEELINDEX = 3;
const int LEGINDEX = 4;
const int HOVERINDEX = 5;
const int HELIINDEX = 6;
const int BRIDGEINDEX = 7;
const int WATERINDEX = 8;
const int NUM_MOVE_TYPES = 9;
struct gridpoint
{
int x,y;
gridpoint (int p1,int p2);
gridpoint (float p1,float p2);
};
void FillCircle (stlport::vector<gridpoint>& points,Stuff::Point3D center,Stuff::Scalar rad);
//--------------------------------------------------------------------
typedef CRailNode *CRailNodePtr;
typedef CRailLink *CRailLinkPtr;
class CRailLink
{
friend class CRailGraph;
private:
unsigned int m_ID;
CRailNode *m_Loc[2];
unsigned int m_LocID[2];
float m_Weight[NUM_MOVE_TYPES][2];
float m_CalcedWeight[NUM_MOVE_TYPES][2];
int m_Bridge; // id of bridge object
int m_UsageFlags[2];
void ID (unsigned int id)
{ m_ID = id; }
~CRailLink();
public:
// would you believe that all this is to just draw a single line?
static void ConstructLinkObjectStream(int id,Stuff::MemoryStream *stream,Stuff::NotationFile *model_file);
void DumpNotationFile (Stuff::NotationFile *file);
CRailLink (Stuff::MemoryStream *stream,CRailGraph *parent);
CRailLink (void);
CRailLink (CRailNode *loc1,CRailNode *loc2,float weight[NUM_MOVE_TYPES][2],bool jump[2] = twofalse,bool track[2]=twofalse,bool fly[2]=twofalse,bool wheel[2]=twofalse,bool leg[2]=twotrue,bool hover[2] =twofalse,bool heli[2] = twofalse);
CRailLink (CRailNode *loc1,CRailNode *loc2,float weight[NUM_MOVE_TYPES][2],int moveflags[2] = twomax);
int Bridge (void) const
{ return m_Bridge; }
void Bridge (int id)
{ m_Bridge = id; }
void DestroyBridge (void);
float Weight (int type,CRailNode *src) const;
float LowestWeight (int usage,int &type,CRailNode *src) const;
bool Jump (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & JUMPFLAG;
else
return m_UsageFlags[1] & JUMPFLAG;
#pragma warning (default:4800)
}
bool Tracked (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & TRACKFLAG;
else
return m_UsageFlags[1] & TRACKFLAG;
#pragma warning (default:4800)
}
bool Flyer (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & FLYFLAG;
else
return m_UsageFlags[1] & FLYFLAG;
#pragma warning (default:4800)
}
bool Wheeled (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & WHEELFLAG;
else
return m_UsageFlags[1] & WHEELFLAG;
#pragma warning (default:4800)
}
bool Legged (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & LEGFLAG;
else
return m_UsageFlags[1] & LEGFLAG;
#pragma warning (default:4800)
}
bool Hover (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & TRACKFLAG;
else
return m_UsageFlags[1] & HOVERFLAG;
#pragma warning (default:4800)
}
bool Heli (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & HELIFLAG;
else
return m_UsageFlags[1] & HELIFLAG;
#pragma warning (default:4800)
}
bool Water (CRailNode *src) const
{
#pragma warning (disable :4800)
if (m_Loc[0] == src)
return m_UsageFlags[0] & WATERFLAG;
else
return m_UsageFlags[1] & WATERFLAG;
#pragma warning (default:4800)
}
void Weight (float amount,int which,CRailNode *src,bool calc=false);
void Jump (bool p1,CRailNode *src);
void Tracked (bool p1,CRailNode *src);
void Flyer (bool p1,CRailNode *src);
void Wheeled (bool p1,CRailNode *src);
void Legged (bool p1,CRailNode *src);
void Hover (bool p1,CRailNode *src);
void Heli (bool p1,CRailNode *src);
unsigned int ID (void) const
{ return m_ID; }
const CRailNode *Location (unsigned int id) const;
unsigned int LocID (unsigned int id) const;
CRailNode *OtherLocation (const CRailNode *temp);
CRailNode *Location (int id);
void TestInstance (void) const
{}
};
class CRailNode
{
friend class CRailGraph;
private:
struct RailSubNode
{
Stuff::Point3D location;
RailSubNode (void)
{ location = Stuff::Point3D (0,0,0); }
RailSubNode (const Stuff::Point3D& loc)
{ location = loc; }
RailSubNode (Stuff::Scalar p1,Stuff::Scalar p2,Stuff::Scalar p3);
RailSubNode (const RailSubNode& p1)
{ location = p1.location; }
RailSubNode& operator= (const RailSubNode& p1);
};
unsigned int m_ID;
bool m_Dirty;
bool m_DistanceValid;
Stuff::Point3D m_Location;
stlport::vector<CRailLink *> m_Links;
stlport::vector<RailSubNode> m_SubNodes;
stlport::vector<float> m_EditorDistance; // only allocated in the editor
float m_PathWeight; // used in the path finding code weight to get to this node
float m_PathEstimate; // used in the path finding code weight from this node to the dest
int m_PathType; // used in the path finding code type of movement to get to this node
Stuff::Scalar m_Radius,m_RadiusSquared,m_MaxRadius,m_SubNodeRadiusMult;
void SubNodeRadiusMult(Stuff::Scalar mult)
{ m_SubNodeRadiusMult = mult;}
void ID (unsigned int id)
{ m_ID = id; }
~CRailNode (void);
public:
// Draw a circle for the radius
static void ConstructNodeObjectStream(int id,Stuff::MemoryStream *stream,Stuff::NotationFile *model_file);
void DumpNotationFile (Stuff::NotationFile *file);
CRailNode (const Stuff::Point3D& loc,Stuff::Scalar rad);
CRailNode (Stuff::MemoryStream *stream,CRailGraph *parent);
CRailLink *LinkTo (CRailNode *dest);
float LinkLength (CRailLink *link); // only length for non intersecting parts, negative if overlap with abs = to dist center to center
bool PtInNode (const Stuff::Point3D& pt);
Stuff::Point3D Location (void) const
{ return m_Location; }
void Location (const Stuff::Point3D& newloc);
unsigned int ID (void) const
{ return m_ID; }
Stuff::Scalar Radius (void) const
{ return m_Radius; }
Stuff::Scalar RadiusSquared (void) const
{ return m_RadiusSquared; }
void Radius (Stuff::Scalar newrad);
void SetRadiusToMax (void);
void CheckRadius();
int NumLinks (void) const
{ return m_Links.size (); }
CRailLink *Link (unsigned int id) const;
void ClearLinks (void);
RailSubNode SubNode (unsigned int id);
RailSubNode SubNode (CRailLink *link);
unsigned int LinkID (unsigned int index);
void AddLink (CRailLink *link);
void DeleteLink (CRailLink *link);
float EditorDistance (CRailNode *dest) const;
float EditorDistance (unsigned int id) const;
// Path finding support
float PathWeight (void) const
{ return m_PathWeight; }
float PathEstimate (void) const
{ return m_PathEstimate; }
int PathType (void) const
{ return m_PathType; }
bool PathWeight (float newvalue,float estimate,int type); // true if changed
void ClearPathWeight (float newvalue,float newestimate,int type);
void TestInstance (void) const
{}
};
struct NodeDist
{
CRailNode *src;
CRailNode *dest;
NodeDist (void)
{
src = dest = NULL;
}
NodeDist (const NodeDist& p1)
{
src = p1.src;
dest = p1.dest;
}
NodeDist (CRailNode *p1,CRailNode *p2)
{
src = p1;
dest = p2;
}
};
struct raildistcmp : binary_function<NodeDist,NodeDist, bool>
{
bool operator()(const NodeDist& _X, const NodeDist& _Y) const
{return _X.src->EditorDistance (_X.dest) < _Y.src->EditorDistance (_Y.dest); }
};
class CRailSquare
{
public:
Stuff::Scalar height;
BYTE material;
Stuff::Normal3D normal;
int waterlevel;
int objectid;
int bridge; // id of bridge object
bool walkthruflag;
Stuff::Scalar objectheight;
CRailSquare (void);
void Construct (Stuff::Scalar x,Stuff::Scalar z);
};
class CRailWorkGrid
{
protected:
QuadTree<int> m_QuadTree;
bool workarray[2048][2048];
stlport::vector<stlport::vector <CRailSquare> > m_Grid;
float CheckSquare (int cx,int cy,int movetype);
void MarkBuilding (Stuff::ExtentBox& box,int id,bool bridge,CMoveGrid *movegrid,CAirMoveGrid *airmovegrid,bool walkthruflag);
public:
CRailWorkGrid (void);
void Construct (WorkCallBack callback,float maxpercent,CMoveGrid *movegrid,CAirMoveGrid *airmovegrid);
Stuff::Scalar CalcWeight (Stuff::Point3D src, Stuff::Point3D dest,int movetype);
Stuff::Scalar MaterialMode (int x,int y,int movetype);
Stuff::Scalar CalcRadius (const Stuff::Point3D& center,Stuff::Scalar maxrad);
bool BuildingAt (const Stuff::Point3D&);
Stuff::Scalar Slope (const Stuff::Point3D& loc);
Stuff::Scalar Slope (int x,int y);
int CalcBridgeLink (Stuff::Point3D src, Stuff::Point3D dest);
bool AnalyzeNode (QuadTreeNode<int> *node);
};
class CAirMoveGrid
{
private:
DWORD m_Width,m_Height; // in meters
unsigned char **m_Data; // two dimensional array for width and height. AIR_PASS_FLAG flags at top
DWORD m_AllocWidth,m_AllocHeight;
public:
CAirMoveGrid (Stuff::MemoryStream *stream);
CAirMoveGrid (void);
~CAirMoveGrid (void)
{ Destroy (); }
void Destroy (void);
void SaveData (const char *filename);
static void ConstructStream (Stuff::MemoryStream *stream,const char *filename);
void Construct (int width,int height);
void Clear (void);
void Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned char canpass,bool override = false); // in meters
void PassableLocal (int x,int z,unsigned char canpass,bool override=false); // in local
unsigned char Passable (Stuff::Scalar x,Stuff::Scalar z) const; // in meters
unsigned char PassableLocal (int x,int z) const; // in local
};
class CMoveGrid
{
private:
DWORD m_Width,m_Height; // in meters
unsigned short *m_Data; // two dimensional array for width and height. PASS_FLAG flags at top
// unsigned short **m_Data; // two dimensional array for width and height. PASS_FLAG flags at top
unsigned char **m_MacroData; // 40 meter grid for whether a cell is open, same size in width and height at m_Data
// 0 is totatlly open 1 is some form of blocking
DWORD m_AllocWidth,m_AllocHeight;
DWORD m_MacroAllocWidth,m_MacroAllocHeight;
static void ConvertOldStyle (Stuff::MemoryStream *stream,DWORD *data,DWORD filesize);
static void ConvertOldStyle2 (Stuff::MemoryStream *stream,DWORD *data,DWORD filesize);
void CreateMacroData (void);
void DeleteMacroData (void);
public:
CMoveGrid (Stuff::MemoryStream *stream);
CMoveGrid (void);
~CMoveGrid (void)
{ Destroy (); }
void Destroy (void);
void SaveData (const char *filename);
static bool ConstructStream (Stuff::MemoryStream *stream,const char *filename);
void Construct (int width,int height);
void Clear (void);
void Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass); // in meters
void PassableLocal (int x,int z,unsigned short canpass); // in local
void PassableOverride (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass); // in meters
void PassableLocalOverride (int x,int z,unsigned short canpass); // in local
unsigned short Passable (Stuff::Scalar x,Stuff::Scalar z) const; // in meters
unsigned short PassableLocal (int x,int z) const; // in local
unsigned char MacroPassable (Stuff::Scalar x,Stuff::Scalar z) const; // in meters
unsigned char MacroPassableLocal (int x,int z) const; // in local
};
typedef CRailNode *CRailNodePtr;
typedef Adept::Receiver__ClassData CRailGraph__ClassData;
typedef Adept::Receiver__Message CRailGraph__Message;
class CRailGraph : public Adept::Receiver
{
private:
stlport::vector<CRailLink *> m_Links;
stlport::vector<CRailNode *> m_Nodes;
stlport::vector<Stuff::Point3D> m_BlockedLinks;
bool m_Dirty;
CRailWorkGrid *m_WorkGrid;
CMoveGrid *m_MoveGrid;
CAirMoveGrid *m_AirMoveGrid;
int m_WorkGridRefCount;
CMoveRectList *m_RectList;
void CalcEditorDistances (void);
void AnalyzePaths (void);
void AddBridgeLinks (void);
int CalcBridgeLink (Stuff::Point3D src, Stuff::Point3D dest);
bool TestBridge (int id,int node1,int node2);
bool LinkWeight (CRailLink *link);
public:
typedef CRailGraph__ClassData ClassData;
typedef CRailGraph__Message Message;
bool BridgeNear (Stuff::Point3D& start,Stuff::Point3D& end);
bool m_SaveLineElementMemory;
Stuff::Point3D PullPointElement (Stuff::Point3D& start,Stuff::Point3D& end,int usage);
Stuff::Point3D PullPointElementMask (Stuff::Point3D& start,Stuff::Point3D& end,int mask);
bool PointOpen (Stuff::Scalar x,Stuff::Scalar y,int pass);
unsigned short Passable (Stuff::Scalar x,Stuff::Scalar z) const;
unsigned short PassableLocal (int x,int z) const; // in local
void Passable (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass); // in meters
void PassableLocal (int x,int z,unsigned short canpass); // in local
void PassableOverride (Stuff::Scalar x,Stuff::Scalar z,unsigned short canpass); // in meters
void PassableLocalOverride (int x,int z,unsigned short canpass); // in local
unsigned char MacroPassable (Stuff::Scalar x,Stuff::Scalar z) const; // in meters
unsigned char MacroPassableLocal (int x,int z) const; // in local
unsigned char AirPassable (Stuff::Scalar x,Stuff::Scalar z) const;
unsigned char AirPassableLocal (int x,int z) const; // in local
void AirPassable (Stuff::Scalar x,Stuff::Scalar z,unsigned char canpass,bool override = false); // in meters
void AirPassableLocal (int x,int z,unsigned char canpass,bool override=false); // in local
CRailGraph (ClassData *class_data);
CRailGraph (ClassData *class_data,Stuff::MemoryStream *stream);
~CRailGraph (void);
void CreateGrid (WorkCallBack callback,float maxpercent);
void KillGrid (void);
void ClearLinks (int *start,int numnodes);
void ClearLinks (void);
static ClassData *DefaultData;
static void ConstructGraphObjectStream(Stuff::MemoryStream *stream,Stuff::NotationFile *model_file);
bool QuickCheck (int x1,int y1,int x2,int y2,unsigned short mask,bool widthvalid=true);
bool AirQuickCheck (int x1,int y1,int x2,int y2);
bool MoveTo (int x,int y,int dir,int mask); // in local coordinates dir is from mask list
int UpDownTo (int x,int y,int dir,int mask); // in local coordinates dir is from mask list
static void InitializeClass();
static void TerminateClass();
void BlockLink (int node1,int node2);
void RemoveBlock (int node);
int AddNode (CRailNode *node);
int AddLink (CRailLink *link);
int AddLink (unsigned int n1,unsigned int n2,float weight[NUM_MOVE_TYPES][2],int moveflags[2] = twomax);
int AddLink (CRailNode *n1,CRailNode *n2,float weight[NUM_MOVE_TYPES][2],int moveflags[2] = twomax);
void ClearPathFlags (void);
CRailNode *FindClosestNode (const Stuff::Point3D& loc,bool strict=true,CRailNode *firstcheck = NULL);
void FindBestNode (const Stuff::Point3D& start,const Stuff::Point3D& end,bool strict,CRailNodePtr& startnode,CRailNodePtr& endnode);
float Connect (CRailNode *src,CRailNode *dest,int usagetype) const;
int Connect (CRailNode *src,CRailNode *dest) const;
int NumNodes(void) const
{ return m_Nodes.size(); }
int NumLinks(void) const
{ return m_Links.size(); }
int CountNodes(void) const;
int CountLinks(void) const;
CRailLink *Link (unsigned int id);
CRailNode *Node (unsigned int id);
void DeleteNode (unsigned int id);
void DeleteLink (unsigned int id);
void DeleteLink (unsigned int node1,unsigned int node2);
void TestInstance (void) const;
const CMoveRectList *RectList (void) const
{ return m_RectList; }
// editor support
void DumpNotationFile (Stuff::NotationFile *file,const char *passfile,const char *rectfile,const char *airpassfile);
void CalcLinks (int min = MINLINKCALC,int max = MAXLINKCALC,int range = LINKDIST,WorkCallBack callback = NULL);
void CalcLinks (int *start,int numnodes,int min = MINLINKCALC,int max = MAXLINKCALC,int range = LINKDIST,WorkCallBack callback= NULL);
void UpdateNodes (WorkCallBack callback,float percentstart);
void CreateBasicNodes (int number,WorkCallBack callback);
void CreateRectData (WorkCallBack callback);
Stuff::Scalar m_SubNodeRadiusMult;
};
struct railnodecmp : binary_function<CRailNode *,CRailNode *, bool>
{
bool operator()(const CRailNode *_X, const CRailNode *_Y) const
{
float c1,c2;
c1 = _X->PathWeight () + _X->PathEstimate ();
c2 = _Y->PathWeight () + _Y->PathEstimate ();
return c1 < c2;
}
};
class CRailPath
{
public:
struct NodePathElement
{
CRailLink *link;
CRailNode *destnode;
int usage;
NodePathElement (void)
{ link = NULL; destnode = NULL; usage = 0; }
NodePathElement (CRailLink *p1,CRailNode *p2,int p3)
{ link = p1; destnode = p2; usage = p3; }
void Save (MemoryStream *stream);
void Load (MemoryStream *stream);
};
struct PathElement
{
Stuff::Point3D loc;
int usage;
bool onrail;
int linkid;
PathElement (void);
PathElement (const Stuff::Point3D& p1,int p2,bool p3,int p4);
bool operator== (const PathElement& p1);
void Save (MemoryStream *stream);
void Load (MemoryStream *stream);
};
private:
Stuff::Point3D m_Start;
Stuff::Point3D m_End;
Stuff::Point3D m_HeadPoint;
MechWarrior4::MoverAI *m_AI;
int m_UsageAllowed;
CRailNode *m_StartNode,*m_EndNode;
CRailGraph *m_Graph;
CPathRequest *m_SubPathRequest;
bool m_Calced;
bool m_Strict;
bool m_TenMeterAllowed;
bool m_QuickPath;
bool m_NearLastFrame;
stlport::vector<NodePathElement> m_NodePath;
stlport::vector<PathElement> m_Path;
int m_InNodePath;
stlport::vector<PathElement>::iterator m_InPath;
CGridPath *m_SubPath;
bool NewSubPath (const Stuff::Point3D& loc);
float CostGuess (CRailNode *src);
//-------------------
// following support
public:
enum PATHSTATES
{
RAIL_START_PATH,
RAIL_MOVE_NO_RAIL,
RAIL_NEXT_STEP,
RAIL_HEAD_EXIT_SUB,
RAIL_MOVE_RAIL,
RAIL_MOVE_ENDPOINT,
RAIL_MOVE_WAITING, // waiting for a subpath calc to end
RAIL_FINISH
};
private:
PATHSTATES m_State;
void CalcOutVec (Stuff::Point3D& outvec);
void ConvertNodeToPath (void);
void ReverseList (void);
void DumpPath (void);
void CreatePathRequests (void);
bool PointBehind (const Stuff::Point3D& loc,const Stuff::Point3D& dest);
void AddStartPoint (Stuff::Point3D& loc,bool& startbrid,stlport::vector<NodePathElement>::iterator& iter);
void AddBridgeToPath (stlport::vector<NodePathElement>::iterator iter,Stuff::Point3D& loc,const OBRect *bridge,bool startbrid);
void AddPointToPath (stlport::vector<NodePathElement>::iterator iter,Stuff::Point3D& loc);
void AddJumpPoint (stlport::vector<NodePathElement>::iterator iter,Stuff::Point3D& loc);
void AddEndPoint (Stuff::Point3D& loc);
void HandleOneNodePath (void);
public:
CRailPath (CRailGraph *graph,const Stuff::Point3D& start,const Stuff::Point3D& end,bool strict,MechWarrior4::MoverAI *ai,bool tenmeter);
CRailPath (CRailGraph *graph,CRailNode *start,CRailNode *end,MechWarrior4::MoverAI *ai,bool tenmeter);
CRailPath (CRailGraph *graph,MechWarrior4::MoverAI *ai);
~CRailPath (void);
void Save (MemoryStream *stream);
void Load (MemoryStream *stream);
bool Calced (void) const
{ return m_Calced; }
bool QuickPath (void) const
{ return m_QuickPath; }
void Reverify (int usage);
bool JumpSoon (void) const;
void CalcPath (int usage);
int CurLink (void) const;
Stuff::Point3D CurrentPoint (void) const; // next link in path
Stuff::Point3D NextPoint (void) const; // next link in path
bool Next (const Stuff::Point3D& loc);
Stuff::Point3D Heading (void) const
{ return CurrentPoint (); }
PATHSTATES State (void) const
{ return m_State; }
void Tick (const Stuff::Point3D& loc,Stuff::Time till,Stuff::Scalar speed,Stuff::Point3D& outvec,bool& jump,bool& prejump);
void TestInstance (void) const {Verify (m_State>=RAIL_START_PATH); Verify (m_State <=RAIL_FINISH);}
Stuff::Point3D Start (void) const
{ return m_Start; }
Stuff::Point3D End (void) const
{ return m_End; }
void UpdateSrcDest (CRailNode *src,CRailNode *dest);
void UpdateSrcDest (const Stuff::Point3D& src,const Stuff::Point3D& dest);
void PointList (stlport::vector<Stuff::Point3D>& dest);
};
class CGridPath
{
friend struct gridpathcmp;
public:
struct GridPathElement
{
int locX,locY;
GridPathElement (void)
{ locX = 0; locY = 0;}
GridPathElement (int p1,int p2)
{
locX = p1;
locY = p2;
}
bool operator== (const GridPathElement& p1)
{ return (p1.locX == locX) && (p1.locY == locY); }
};
struct DirElement
{
int locX,locY;
DirElement (void)
{ locX = -1; locY = -1;}
DirElement (int p1,int p2)
{
locX = p1;
locY = p2;
}
};
bool DirPathValid() const
{
return (m_InDirPath != m_DirList.end());
}
private:
stlport::vector<DirElement>::iterator m_InDirPath;
stlport::vector<DirElement> m_DirList;
int m_StartX,m_StartY,m_EndX,m_EndY;
bool m_Calced;
bool m_Working;
bool m_QuickValid;
bool m_TenMeterAllowed;
int m_WorkCount;
unsigned short m_Mask;
CRailGraph *m_Graph;
my_heap<GridPathElement,true,gridpathcmp> calc;
static CGridPath *m_WorkingPath;
static int m_BlockOriginX,m_BlockOriginY;
static unsigned int m_BlockGrid[BLOCK_GRID_SIZE][BLOCK_GRID_SIZE][2]; // lower number is current cost, upper is estimate
static unsigned int Cost (int sx,int sy);
static unsigned int Estimate (int sx,int sy);
static bool Cost (int sx,int sy,unsigned int cost,unsigned int estimate);
static unsigned int Cost (const GridPathElement& p1)
{ return Cost (p1.locX,p1.locY); }
static unsigned int Estimate (const GridPathElement& p1)
{ return Estimate (p1.locX,p1.locY); }
static bool Cost (const GridPathElement& p1,unsigned int cost,unsigned int estimate)
{ return Cost (p1.locX,p1.locY,cost,estimate); }
int CostGuess (int sx,int sy);
int AdjustCost (int cx,int cy); // will adjust the cost based on locality to blocked terrain
void ReverseList (void);
// bool QuickCheck (int x1,int y1,int x2,int y2);
void ConstructQuickPath (void);
void DumpPath (void);
void SmoothList (void);
void SmoothListHelper (stlport::vector<DirElement>& vec,int s,int e);
void Calc30Path (void);
void Calc10Path (void);
void StartCalcPath (void);
void ContinueCalcPath (void);
public:
virtual void Save (MemoryStream *stream);
virtual void Load (MemoryStream *stream);
CGridPath (CRailGraph *graph);
CGridPath (CRailGraph *graph,unsigned short mask,int sx,int sy,int dx,int dy,bool tenmeter);
CGridPath (CRailGraph *graph,unsigned short mask,Stuff::Scalar sx,Stuff::Scalar sy,Stuff::Scalar dx,Stuff::Scalar dy,bool tenmeter);
~CGridPath (void);
void DoCalcPath (void);
bool Working (void)
{ return m_Working; }
bool Calced (void) const
{ return m_Calced; }
bool QuickValid (void) const
{ return m_QuickValid; }
bool Next (void); // true if path still exists
Stuff::Point3D NextPoint (void) const; // next link in path
bool OneFromEnd (void) const; // at end is also good
Stuff::Point3D CurrentPoint (void) const;
// int size (void)
// { return m_Path.size (); }
DirElement direlement (int index);
int dirsize (void)
{ return m_DirList.size (); }
void UpdateSrcDest (int sx,int sy,int dx,int dy);
void UpdateSrcDest (Stuff::Scalar sx,Stuff::Scalar sy,Stuff::Scalar dx,Stuff::Scalar dy);
void PointList (stlport::vector<Stuff::Point3D>& dest);
Stuff::Point3D End (void)
{ return Point3D ((Scalar) m_EndX,0.0f,(Scalar) m_EndY); }
};
struct gridpathcmp : binary_function<CGridPath::GridPathElement *,CGridPath::GridPathElement *, bool>
{
bool operator()(const CGridPath::GridPathElement& _X, const CGridPath::GridPathElement& _Y) const
{
int c1,c2;
c1 = CGridPath::Cost (_X) + CGridPath::Estimate (_X);
c2 = CGridPath::Cost (_Y) + CGridPath::Estimate (_Y);
return c1<c2;
}
};
class CPathRequest
{
friend class CPathManager;
private:
Stuff::Time m_NeedBy;
bool m_Done;
CRailPath *m_NodePath;
CGridPath *m_GridPath;
int m_UsageAllowed;
bool m_Strict;
bool m_Working;
CPathRequest *m_Next,*m_Prev;
MechWarrior4::MoverAI *m_Who;
void Done (bool done)
{ m_Done = done; }
public:
virtual void Save (MemoryStream *stream);
virtual void Load (MemoryStream *stream);
CPathRequest (CRailGraph *graph);
CPathRequest (Stuff::Time needby,CRailGraph *graph,CRailNode *start,CRailNode *end,int usageallowed,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest (Stuff::Time needby,CRailGraph *graph,Stuff::Point3D start,Stuff::Point3D end,int usageallowed,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest (Stuff::Time needby,CRailGraph *graph,unsigned short mask,int sx,int sy,int dx,int dy,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest (Stuff::Time needby,CRailGraph *graph,unsigned short mask,Stuff::Scalar sx,Stuff::Scalar sy,Stuff::Scalar dx,Stuff::Scalar dy,MechWarrior4::MoverAI *who,bool tenmeter);
~CPathRequest (void);
bool Working (void) const
{ return m_Working; }
bool Done (void) const
{ return m_Done; }
CRailPath *NodePath (void)
{ return m_NodePath; }
CGridPath *GridPath (void)
{ return m_GridPath; }
int UsageAllowed (void) const
{ return m_UsageAllowed; }
bool PathTypeIsNode (void)
{ return (m_NodePath != NULL); }
CRailPath *DetachNodePath (void);
CGridPath *DetachGridPath (void);
bool UpdateSrcDest (CRailNode *src,CRailNode *end);
bool UpdateSrcDest (const Stuff::Point3D& src,const Stuff::Point3D& end);
bool UpdateSrcDest (int sx,int sy,int dx,int dy);
Stuff::Point3D GetEndPoint (void);
void Unlock (void);
void Lock (void);
};
class CPathManager : public Adept::ApplicationTask
{
private:
CPathRequest *m_Root;
void InsertRequest (CPathRequest *req);
protected:
public:
bool m_FailedCalcFrame;
void Save (MemoryStream *stream);
void Load (MemoryStream *stream);
static void InitializeClass();
static void TerminateClass();
CPathManager (void);
~CPathManager (void);
CPathRequest *AddRequest (Stuff::Time needby,CRailGraph *graph,CRailNode *start,CRailNode *end,int usageallowed,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest *AddRequest (Stuff::Time needby,CRailGraph *graph,Stuff::Point3D start,Stuff::Point3D end,int usageallowed,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest *AddRequest (Stuff::Time needby,CRailGraph *graph,unsigned short mask,int sx,int sy,int dx,int dy,MechWarrior4::MoverAI *who,bool tenmeter);
CPathRequest *AddRequest (Stuff::Time needby,CRailGraph *graph,unsigned short mask,Stuff::Scalar sx,Stuff::Scalar sy,Stuff::Scalar dx,Stuff::Scalar dy,MechWarrior4::MoverAI *who,bool tenmeter);
void RemoveRequest (CPathRequest *req);
void CleanRequests (void);
unsigned int GetNumPathRequests() const;
virtual bool Execute();
};
extern CPathManager *g_PathManager;
extern CRailGraph *g_MissionGraph;
/*
inline void CRailLink::UpdateLinkPointData()
{
m_RailLinkPointData[0] = m_Loc[0]->Location();
m_RailLinkPointData[0].y += 0.5f;
m_RailLinkPointData[1] = m_Loc[1]->Location();
m_RailLinkPointData[1].y += 0.5f;
}
*/
}
#include "rail_move.inl"
#endif