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.
1013 lines
33 KiB
C++
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
|