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.
986 lines
21 KiB
C++
986 lines
21 KiB
C++
#include "MW4Headers.hpp"
|
|
#include "server\comline.hpp"
|
|
#include "adept\application.hpp"
|
|
#include "rail_move.hpp"
|
|
#include "move_rect.hpp"
|
|
#include "ai.hpp"
|
|
|
|
#pragma warning (push)
|
|
#include <vector>
|
|
#include <map>
|
|
#pragma warning (pop)
|
|
|
|
namespace MechWarrior4
|
|
{
|
|
extern DWORD Path_Calcs_Count;
|
|
extern DWORD GridPath_Calcs_Count;
|
|
extern DWORD QuickPath_Calcs_Count;
|
|
extern DWORD QuickRail_Calcs_Count;
|
|
}
|
|
|
|
namespace MW4AI
|
|
{
|
|
extern __int64 tCalcPathTime;
|
|
extern __int64 tQuickCheckTime;
|
|
extern __int64 tCreatePathRequestsTime;
|
|
extern __int64 tPathCalc1Time;
|
|
extern __int64 tPathCalc2Time;
|
|
extern __int64 tNodeToPathTime;
|
|
};
|
|
|
|
using namespace MW4AI;
|
|
using namespace MechWarrior4;
|
|
|
|
CRailPath::CRailPath (CRailGraph *graph,MoverAI *ai)
|
|
: m_Start(-1,-1,-1)
|
|
, m_End(-1,-1,-1)
|
|
{
|
|
m_SubPathRequest = NULL;
|
|
|
|
m_NearLastFrame = false;
|
|
m_TenMeterAllowed = false;
|
|
m_AI = ai;
|
|
m_SubPath = NULL;
|
|
m_Graph = graph;
|
|
m_Strict = false;
|
|
m_StartNode = NULL;
|
|
m_EndNode = NULL;
|
|
m_Calced = false;
|
|
m_InNodePath = 0;
|
|
m_Path.clear ();
|
|
m_NodePath.clear ();
|
|
m_InPath = m_Path.begin ();;
|
|
}
|
|
CRailPath::CRailPath (CRailGraph *graph,const Stuff::Point3D& start,const Stuff::Point3D& end,bool strict,MoverAI *ai,bool tenmeter)
|
|
: m_Start(start)
|
|
, m_End(end)
|
|
{
|
|
m_NearLastFrame = false;
|
|
m_TenMeterAllowed = tenmeter;
|
|
m_AI = ai;
|
|
m_SubPathRequest = NULL;
|
|
m_SubPath = NULL;
|
|
m_Graph = graph;
|
|
m_Strict = strict;
|
|
m_Graph->FindBestNode (m_Start,m_End,false,m_StartNode,m_EndNode);
|
|
m_Calced = false;
|
|
m_InNodePath = 0;
|
|
m_Path.clear ();
|
|
m_NodePath.clear ();
|
|
m_InPath = m_Path.begin ();;
|
|
}
|
|
|
|
CRailPath::CRailPath (CRailGraph *graph,CRailNode *start,CRailNode *end,MoverAI *ai,bool tenmeter)
|
|
{
|
|
m_NearLastFrame = false;
|
|
m_TenMeterAllowed = tenmeter;
|
|
m_AI = ai;
|
|
m_SubPathRequest = NULL;
|
|
m_SubPath = NULL;
|
|
m_Graph = graph;
|
|
m_StartNode = start;
|
|
m_EndNode = end;
|
|
m_Strict = true;
|
|
m_Start = m_StartNode->Location ();
|
|
m_End = m_EndNode->Location ();
|
|
m_Calced = false;
|
|
m_InNodePath = 0;
|
|
m_Path.clear ();
|
|
m_NodePath.clear ();
|
|
m_InPath = m_Path.begin ();
|
|
// m_GridRequests.clear ();
|
|
}
|
|
|
|
CRailPath::~CRailPath (void)
|
|
{
|
|
m_NodePath.clear ();
|
|
m_Path.clear ();
|
|
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
delete m_SubPathRequest;
|
|
m_SubPathRequest = NULL;
|
|
}
|
|
|
|
void CRailPath::UpdateSrcDest (CRailNode *src,CRailNode *dest)
|
|
{
|
|
Verify (dest);
|
|
m_StartNode = src;
|
|
m_EndNode = dest;
|
|
m_End = m_EndNode->Location ();
|
|
m_Start = m_StartNode->Location ();
|
|
}
|
|
|
|
void CRailPath::UpdateSrcDest (const Stuff::Point3D& src,const Stuff::Point3D& dest)
|
|
{
|
|
m_Start = src;
|
|
m_End = dest;
|
|
m_Graph->FindBestNode (m_Start,m_End,false,m_StartNode,m_EndNode);
|
|
}
|
|
|
|
void CRailPath::Save (MemoryStream *stream)
|
|
{
|
|
|
|
stlport::vector<NodePathElement>::iterator iter1;
|
|
stlport::vector<PathElement>::iterator iter2;
|
|
|
|
*stream << m_TenMeterAllowed;
|
|
*stream << m_Start;
|
|
*stream << m_End;
|
|
*stream << m_HeadPoint;
|
|
*stream << m_UsageAllowed;
|
|
*stream << m_Calced;
|
|
*stream << m_Strict;
|
|
if (m_StartNode)
|
|
{
|
|
*stream << true;
|
|
*stream << m_StartNode->ID ();
|
|
}
|
|
else
|
|
*stream << false;
|
|
if (m_EndNode)
|
|
{
|
|
*stream << true;
|
|
*stream << m_EndNode->ID ();
|
|
}
|
|
else
|
|
*stream << false;
|
|
*stream << m_InNodePath;
|
|
*stream << ((int) m_State);
|
|
*stream << m_NodePath.size ();
|
|
*stream << m_Path.size ();
|
|
int count;
|
|
|
|
|
|
for (iter2 = m_Path.begin (),count = 0;(iter2 != m_Path.end ()) && (m_InPath != iter2);iter2++,count++);
|
|
*stream << count;
|
|
|
|
for (iter1 = m_NodePath.begin ();iter1 != m_NodePath.end ();iter1++)
|
|
{
|
|
iter1->Save (stream);
|
|
}
|
|
for (iter2 = m_Path.begin ();iter2 != m_Path.end ();iter2++)
|
|
{
|
|
iter2->Save (stream);
|
|
}
|
|
}
|
|
|
|
void CRailPath::Load (MemoryStream *stream)
|
|
{
|
|
bool flag;
|
|
int temp;
|
|
int size1,size2;
|
|
|
|
*stream >> m_TenMeterAllowed;
|
|
*stream >> m_Start;
|
|
*stream >> m_End;
|
|
*stream >> m_HeadPoint;
|
|
*stream >> m_UsageAllowed;
|
|
*stream >> m_Calced;
|
|
*stream >> m_Strict;
|
|
*stream >> flag;
|
|
m_StartNode = NULL;
|
|
if (flag)
|
|
{
|
|
int id;
|
|
*stream >> id;
|
|
m_StartNode = m_Graph->Node (id);
|
|
}
|
|
*stream >> flag;
|
|
m_EndNode = NULL;
|
|
if (flag)
|
|
{
|
|
int id;
|
|
*stream >> id;
|
|
m_EndNode = m_Graph->Node (id);
|
|
}
|
|
|
|
*stream >> m_InNodePath;
|
|
*stream >> temp;
|
|
m_State = (PATHSTATES) temp;
|
|
*stream >> size1;
|
|
*stream >> size2;
|
|
int count,i;
|
|
|
|
*stream >> count;
|
|
|
|
m_NodePath.assign (size1,NodePathElement ());
|
|
for (i=0;i<size1;i++)
|
|
{
|
|
m_NodePath[i].Load (stream);
|
|
}
|
|
m_Path.assign (size2,PathElement());
|
|
for (i=0;i<size2;i++)
|
|
{
|
|
m_Path[i].Load (stream);
|
|
}
|
|
m_InPath = m_Path.begin ();
|
|
m_InPath += count;
|
|
}
|
|
|
|
void CRailPath::PathElement::Save (MemoryStream *stream)
|
|
{
|
|
*stream << loc;
|
|
*stream << usage;
|
|
*stream << onrail;
|
|
*stream << linkid;
|
|
}
|
|
void CRailPath::PathElement::Load (MemoryStream *stream)
|
|
{
|
|
*stream >> loc;
|
|
*stream >> usage;
|
|
*stream >> onrail;
|
|
*stream >> linkid;
|
|
}
|
|
void CRailPath::NodePathElement::Save (MemoryStream *stream)
|
|
{
|
|
*stream << usage;
|
|
if (link)
|
|
{
|
|
*stream << true;
|
|
*stream << link->ID ();
|
|
}
|
|
else
|
|
*stream << false;
|
|
if (destnode)
|
|
{
|
|
*stream << true;
|
|
*stream << destnode->ID ();
|
|
}
|
|
else
|
|
*stream << false;
|
|
}
|
|
|
|
void CRailPath::NodePathElement::Load (MemoryStream *stream)
|
|
{
|
|
bool flag;
|
|
int id;
|
|
*stream >> usage;
|
|
destnode = NULL;
|
|
link = NULL;
|
|
*stream >> flag;
|
|
if (flag)
|
|
{
|
|
*stream >> id;
|
|
link = g_MissionGraph->Link (id);
|
|
}
|
|
*stream >> flag;
|
|
if (flag)
|
|
{
|
|
*stream >> id;
|
|
destnode = g_MissionGraph->Node (id);
|
|
}
|
|
}
|
|
|
|
float CRailPath::CostGuess (CRailNode *src)
|
|
{
|
|
Stuff::Point3D start;
|
|
Stuff::Point3D end;
|
|
|
|
start = src->Location ();
|
|
end = m_End;
|
|
|
|
float t1,t2;
|
|
|
|
t1 = end.x - start.x;
|
|
t2 = end.z - start.z;
|
|
|
|
t1 = t1<0 ? t1*-1.0f : t1;
|
|
t2 = t2<0 ? t2*-1.0f : t2;
|
|
|
|
return 0;
|
|
// return t2 < t1 ? (t1+(t2/2.0f)) : (t2+(t1/2.0f));
|
|
}
|
|
|
|
void CRailPath::CalcOutVec (Stuff::Point3D& outvec)
|
|
{
|
|
outvec = NextPoint ();
|
|
// outvec = Stuff::Point3D (-1,-1,-1);
|
|
}
|
|
|
|
|
|
bool CRailPath::NewSubPath (const Stuff::Point3D& loc)
|
|
{
|
|
if (m_InPath == m_Path.end ())
|
|
return false;
|
|
int mask=0;
|
|
|
|
if (m_InPath->usage & JUMPFLAG)
|
|
{
|
|
Verify (!m_SubPathRequest);
|
|
return true;
|
|
}
|
|
if (m_InPath->onrail)
|
|
{
|
|
Verify (!m_SubPathRequest);
|
|
return true;
|
|
}
|
|
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
if (m_SubPathRequest)
|
|
{
|
|
m_SubPath = m_SubPathRequest->GridPath ();
|
|
if (!m_SubPathRequest->Done ())
|
|
{
|
|
return true;
|
|
}
|
|
m_SubPathRequest->DetachGridPath ();
|
|
delete m_SubPathRequest;
|
|
m_SubPathRequest = NULL;
|
|
if (!m_SubPath->Calced ())
|
|
{
|
|
if (m_InPath->linkid != -1)
|
|
m_Graph->DeleteLink (m_InPath->linkid);
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
m_Calced = false;
|
|
return false;
|
|
}
|
|
if (m_SubPath->QuickValid ())
|
|
{
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mask = ConvertUsagetoMovePass (m_InPath->usage);
|
|
|
|
m_SubPathRequest = g_PathManager->AddRequest (gos_GetElapsedTime (),m_Graph,(unsigned short) mask,loc.x,loc.z,m_InPath->loc.x,m_InPath->loc.z,m_AI,m_TenMeterAllowed);
|
|
return true;
|
|
#if 0
|
|
gos_PushCurrentHeap (g_RailHeap);
|
|
m_SubPath = new CGridPath (m_Graph,(unsigned short) mask,loc.x,loc.z,m_InPath->loc.x,m_InPath->loc.z,m_TenMeterAllowed);
|
|
gos_PopCurrentHeap ();
|
|
Verify (m_SubPath);
|
|
m_SubPath->CalcPath();
|
|
#endif
|
|
}
|
|
#if 0
|
|
if (!m_SubPath->Calced ())
|
|
{
|
|
if (m_InPath->linkid != -1)
|
|
m_Graph->DeleteLink (m_InPath->linkid);
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
m_Calced = false;
|
|
return false;
|
|
}
|
|
if (m_SubPath->QuickValid ())
|
|
{
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
bool CRailPath::Next (const Stuff::Point3D& loc)
|
|
{
|
|
if (m_SubPath)
|
|
{
|
|
if (m_SubPath->Next ())
|
|
{
|
|
return true;
|
|
}
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
if (m_InPath != m_Path.end ())
|
|
{
|
|
m_InPath++;
|
|
return NewSubPath (loc);
|
|
}
|
|
}
|
|
if (m_InPath != m_Path.end ())
|
|
{
|
|
m_InPath++;
|
|
return NewSubPath (loc);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Stuff::Point3D CRailPath::CurrentPoint (void) const
|
|
{
|
|
if (!m_Calced)
|
|
return Stuff::Point3D (-1,-1,-1);
|
|
if (m_State == RAIL_FINISH)
|
|
return Stuff::Point3D (-1,-1,-1);
|
|
|
|
if (m_InPath == m_Path.end () && (m_SubPath == NULL))
|
|
return Stuff::Point3D (-1,-1,-1);
|
|
|
|
if (m_SubPath)
|
|
return m_SubPath->CurrentPoint ();
|
|
else
|
|
return m_InPath->loc;
|
|
}
|
|
|
|
bool CRailPath::PointBehind (const Stuff::Point3D& loc,const Stuff::Point3D& dest)
|
|
{
|
|
Stuff::Point3D nextdest,destextra,nextdestextra;
|
|
Scalar dist1,dist2,dot;
|
|
|
|
nextdest = NextPoint ();
|
|
if (nextdest == Point3D (-1,-1,-1))
|
|
return false;
|
|
|
|
int x,y,mask;
|
|
x = (int) (loc.x/10);
|
|
y = (int) (loc.z/10);
|
|
mask = ConvertUsagetoMovePass (m_UsageAllowed&(~JUMPFLAG));
|
|
if ((!m_Graph->MoveTo (x+1,y,0,mask)) || (!m_Graph->MoveTo (x-1,y,0,mask)) || (!m_Graph->MoveTo (x,y-1,0,mask)) || (!m_Graph->MoveTo (x,y+1,0,mask)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
destextra.Subtract (dest,loc);
|
|
dist1 = destextra.GetLengthSquared ();
|
|
nextdestextra.Subtract (nextdest,loc);
|
|
dist2 = nextdestextra.GetLengthSquared ();
|
|
if (dist2 < dist1)
|
|
return true;
|
|
|
|
dot = (nextdestextra.x*destextra.x) + (nextdestextra.z*destextra.z);
|
|
dot /= (nextdestextra.GetLength () * destextra.GetLength ());
|
|
|
|
if ((m_Graph->Passable (loc.x,loc.z) & BRIDGE_FLAG) && (dot <= 0.0f))
|
|
return true;
|
|
|
|
if ((dot <= 0.0f) && (dist1 < 400))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void CRailPath::PointList (stlport::vector<Point3D>& dest)
|
|
{
|
|
dest.clear ();
|
|
if (!m_Calced)
|
|
return;
|
|
if (m_InPath == m_Path.end () && (m_SubPath == NULL))
|
|
return;
|
|
gos_PushCurrentHeap (g_RailHeap);
|
|
|
|
if (m_SubPath)
|
|
{
|
|
m_SubPath->PointList (dest);
|
|
}
|
|
stlport::vector<PathElement>::iterator iter;
|
|
|
|
for (iter = m_InPath;iter != m_Path.end ();iter++)
|
|
{
|
|
dest.push_back (iter->loc);
|
|
}
|
|
gos_PopCurrentHeap ();
|
|
}
|
|
|
|
void CRailPath::Tick (const Stuff::Point3D& loc,Stuff::Time till,Stuff::Scalar speed,Stuff::Point3D& outvec,bool& jump,bool& prejump)
|
|
{
|
|
m_HeadPoint = Stuff::Point3D (-1,-1,-1);
|
|
|
|
Verify (m_Calced);
|
|
jump = false;
|
|
prejump = false;
|
|
if (m_State == RAIL_FINISH)
|
|
return;
|
|
if (m_SubPathRequest)
|
|
{
|
|
if (m_SubPathRequest->Done ())
|
|
{
|
|
m_SubPath = m_SubPathRequest->DetachGridPath ();
|
|
delete m_SubPathRequest;
|
|
m_SubPathRequest = NULL;
|
|
if (!m_SubPath->Calced ())
|
|
{
|
|
if (m_InPath->linkid != -1)
|
|
m_Graph->DeleteLink (m_InPath->linkid);
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
m_Calced = false;
|
|
m_State = RAIL_FINISH;
|
|
return;
|
|
}
|
|
if (m_SubPath->QuickValid ())
|
|
{
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_State = RAIL_MOVE_WAITING;
|
|
return;
|
|
}
|
|
}
|
|
m_State = RAIL_MOVE_ENDPOINT;
|
|
CalcOutVec (outvec);
|
|
|
|
Stuff::Point3D destloc,extra,fakeloc;
|
|
Stuff::Scalar dist,move;
|
|
|
|
destloc = CurrentPoint ();
|
|
|
|
destloc.y = 0;
|
|
fakeloc = loc;
|
|
fakeloc.y = 0;
|
|
extra.Subtract (destloc,fakeloc);
|
|
dist = extra.GetLengthSquared ();
|
|
|
|
if (speed < 0)
|
|
move = (float) (speed * till * 6); // use 6 frame buffer
|
|
else
|
|
move = (float) (speed * till * 6); // use 6 frame buffer
|
|
move *= move;
|
|
|
|
// if ((dist<49.0) || (dist < move) || PointBehind (loc,destloc))
|
|
if (m_NearLastFrame)
|
|
{
|
|
m_NearLastFrame = false;
|
|
if (!Next (loc))
|
|
{
|
|
m_State = RAIL_FINISH;
|
|
return;
|
|
}
|
|
if (!m_Calced)
|
|
return;
|
|
Tick (loc,till,speed,outvec,jump,prejump);
|
|
return;
|
|
}
|
|
#if 1
|
|
if ((dist<16.0) || (dist < move) || PointBehind (loc,destloc))
|
|
{
|
|
m_NearLastFrame = true;
|
|
}
|
|
#endif
|
|
|
|
m_HeadPoint = CurrentPoint ();
|
|
destloc = CurrentPoint ();
|
|
|
|
destloc.y = 0;
|
|
fakeloc = loc;
|
|
fakeloc.y = 0;
|
|
extra.Subtract (destloc,fakeloc);
|
|
dist = extra.GetLengthSquared ();
|
|
|
|
CalcOutVec (outvec);
|
|
|
|
stlport::vector<PathElement>::iterator iter;
|
|
iter = m_InPath;
|
|
if (m_InPath != m_Path.end ())
|
|
iter++;
|
|
|
|
if (m_InPath->usage & JUMPFLAG)
|
|
jump = true;
|
|
else
|
|
jump = false;
|
|
if ((iter != m_Path.end ()) && (iter->usage & JUMPFLAG))
|
|
prejump = true;
|
|
|
|
bool flag = false;
|
|
if ((!m_SubPath) && (iter == m_Path.end () && (m_State != RAIL_FINISH)))
|
|
flag = true;
|
|
if ((m_SubPath) && (iter == m_Path.end () && (m_State != RAIL_FINISH)))
|
|
{
|
|
if (m_SubPath->OneFromEnd ())
|
|
flag = true;
|
|
}
|
|
}
|
|
|
|
bool CRailGraph::PointOpen (Scalar x,Scalar y,int movepass)
|
|
{
|
|
|
|
const int SIZEDELTA = 8;
|
|
int delta[SIZEDELTA][2] = {
|
|
{-1*BLOCK_GRID_RES,0*BLOCK_GRID_RES},
|
|
{0*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
|
|
{1*BLOCK_GRID_RES,0*BLOCK_GRID_RES},
|
|
{0*BLOCK_GRID_RES,1*BLOCK_GRID_RES},
|
|
#if 1
|
|
{-1*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
|
|
{-1*BLOCK_GRID_RES,1*BLOCK_GRID_RES},
|
|
{1*BLOCK_GRID_RES,-1*BLOCK_GRID_RES},
|
|
{1*BLOCK_GRID_RES,1*BLOCK_GRID_RES}
|
|
#endif
|
|
};
|
|
int i;
|
|
|
|
if (CheckCanPass (Passable (x,y),movepass))
|
|
return false;
|
|
for (i=0;i<SIZEDELTA;i++)
|
|
{
|
|
if (CheckCanPass (Passable (x+delta[i][0],y+delta[i][1]),movepass))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Stuff::Point3D CRailGraph::PullPointElementMask (Stuff::Point3D& start,Stuff::Point3D& end,int movepass)
|
|
{
|
|
end.y = 0;
|
|
start.y = 0;
|
|
if (!PointOpen (end.x,end.z , movepass))
|
|
{
|
|
Stuff::Point3D vec,tempvec,third;
|
|
Stuff::Scalar len,curlen;
|
|
|
|
third.Subtract (start,end);
|
|
len = third.GetLengthSquared ();
|
|
if (len < 5.0f)
|
|
return Point3D (-1,-1,-1);
|
|
vec.Normalize (third);
|
|
curlen = 0;
|
|
while ((curlen*curlen) < len)
|
|
{
|
|
curlen+=BLOCK_GRID_RES;
|
|
third.Multiply (vec,curlen);
|
|
tempvec.Add (third,end);
|
|
if (PointOpen (tempvec.x,tempvec.z , movepass))
|
|
return tempvec;
|
|
}
|
|
return Stuff::Point3D (-1,-1,-1);
|
|
}
|
|
else
|
|
return end;
|
|
|
|
}
|
|
|
|
Stuff::Point3D CRailGraph::PullPointElement (Stuff::Point3D& start,Stuff::Point3D& end,int usage)
|
|
{
|
|
int movepass;
|
|
|
|
movepass = ConvertUsagetoMovePass (usage);
|
|
return PullPointElementMask (start,end,movepass);
|
|
}
|
|
|
|
void CRailPath::DumpPath (void)
|
|
{
|
|
stlport::vector<PathElement>::iterator iter;
|
|
char text[100];
|
|
|
|
iter = m_Path.begin ();
|
|
while (iter != m_Path.end ())
|
|
{
|
|
sprintf (text,"Move Point %f,%f",iter->loc.x,iter->loc.z);
|
|
COMSPEW (text);
|
|
iter++;
|
|
}
|
|
COMSPEW ("");
|
|
}
|
|
|
|
void CRailPath::ReverseList (void)
|
|
{
|
|
stlport::vector<NodePathElement>::iterator start,end;
|
|
|
|
// COMSPEW ("reversing path list");
|
|
start = m_NodePath.begin ();
|
|
end = m_NodePath.end ();
|
|
stlport::reverse (start,end);
|
|
}
|
|
|
|
void CRailPath::Reverify (int usage)
|
|
{
|
|
return;
|
|
#if 0
|
|
if (!m_QuickPath)
|
|
return;
|
|
|
|
unsigned short usa = (unsigned short) (m_UsageAllowed&(~JUMPFLAG));
|
|
if (m_Graph->QuickCheck ((int) m_Start.x,(int) m_Start.z,(int) m_End.x,(int) m_End.z,(unsigned short) ConvertUsagetoMovePass (usa)))
|
|
return;
|
|
|
|
m_Calced = false;
|
|
|
|
m_NodePath.clear ();
|
|
m_Path.clear ();
|
|
CalcPath (usage);
|
|
#endif
|
|
}
|
|
|
|
void CRailPath::CalcPath (int usage)
|
|
{
|
|
PATH_LOGIC("Calc");
|
|
TIME_FUNCTION(tCalcPathTime);
|
|
|
|
Verify (m_Graph);
|
|
int i;
|
|
int type;
|
|
my_heap<CRailNode *,true,railnodecmp> calc;
|
|
CRailNode *temp;
|
|
bool done;
|
|
Scalar dist;
|
|
Point3D extra;
|
|
|
|
m_NearLastFrame = false;
|
|
m_SubPathRequest = NULL;
|
|
|
|
Set_Statistic(Path_Calcs_Count, Path_Calcs_Count+1);
|
|
// usage &= ~JUMPFLAG;
|
|
Verify (m_Graph->CountNodes ());
|
|
Verify (m_Graph->CountLinks ());
|
|
Verify (usage >0);
|
|
m_UsageAllowed = usage & (~JUMPFLAG);
|
|
|
|
AutoHeap local_heap (g_RailHeap);
|
|
|
|
unsigned short usa = (unsigned short) (m_UsageAllowed&(~JUMPFLAG));
|
|
|
|
extra = m_Graph->PullPointElement (m_Start,m_End,usa);
|
|
if (extra == Point3D (-1,-1,-1))
|
|
{
|
|
m_Calced = false;
|
|
return;
|
|
}
|
|
m_End = extra;
|
|
|
|
m_QuickPath = false;
|
|
if (m_Graph->QuickCheck ((int) m_Start.x,(int) m_Start.z,(int) m_End.x,(int) m_End.z,(unsigned short) ConvertUsagetoMovePass (usa)))
|
|
{
|
|
Set_Statistic(QuickRail_Calcs_Count, QuickRail_Calcs_Count+1);
|
|
m_Calced = true;
|
|
m_Path.push_back (PathElement (m_Start,usa,false,-1));
|
|
m_Path.push_back (PathElement (m_End,usa,true,-1));
|
|
m_InPath = m_Path.begin ();
|
|
m_QuickPath = true;
|
|
return;
|
|
}
|
|
|
|
if ((m_StartNode == NULL) || (m_EndNode == NULL))
|
|
{
|
|
m_Calced = false;
|
|
m_State = RAIL_START_PATH;
|
|
return;
|
|
}
|
|
|
|
m_Start.y = m_End.y = 0;
|
|
extra.Subtract (m_Start,m_End);
|
|
dist = extra.GetLengthSquared ();
|
|
if ((m_StartNode == m_EndNode) || ((dist < (250.0f*250.0f)) && (!m_Graph->BridgeNear (m_Start,m_End))))
|
|
{
|
|
m_Calced = true;
|
|
m_Path.push_back (PathElement (m_Start,usa,false,-1));
|
|
|
|
Point3D temp;
|
|
temp = m_Graph->PullPointElement (m_Start,m_End,usa);
|
|
if (temp != Point3D (-1,-1,-1))
|
|
{
|
|
m_Path.push_back (PathElement (temp,usa,false,-1));
|
|
m_InPath = m_Path.begin ();
|
|
|
|
m_InPath++;
|
|
|
|
gos_PushCurrentHeap (g_RailHeap);
|
|
unsigned short mask = (unsigned short) ConvertUsagetoMovePass (m_InPath->usage);
|
|
m_SubPath = new CGridPath (m_Graph,mask,m_Start.x,m_Start.z,m_End.x,m_End.z,m_TenMeterAllowed);
|
|
gos_PopCurrentHeap ();
|
|
Verify (m_SubPath);
|
|
m_SubPath->DoCalcPath();
|
|
if (m_SubPath->Calced ())
|
|
{
|
|
if (m_SubPath->QuickValid ())
|
|
{
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
m_Calced = true;
|
|
m_Path.clear ();
|
|
m_Path.push_back (PathElement (m_Start,usa,false,-1));
|
|
m_Path.push_back (PathElement (m_End,usa,false,-1));
|
|
m_InPath = m_Path.begin ();
|
|
m_QuickPath = true;
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
else if (m_StartNode == m_EndNode)
|
|
{
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
CreatePathRequests ();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
m_Calced = false;
|
|
delete m_SubPath;
|
|
m_SubPath = NULL;
|
|
}
|
|
#if 0
|
|
if ((m_Calced) || (m_StartNode == m_EndNode))
|
|
{
|
|
Set_Statistic(QuickRail_Calcs_Count, QuickRail_Calcs_Count+1);
|
|
m_QuickPath = true;
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
m_Calced = false;
|
|
|
|
if (m_StartNode == m_EndNode)
|
|
{
|
|
m_QuickPath = true;
|
|
m_State = RAIL_FINISH;
|
|
m_Calced = true;
|
|
m_Path.push_back (PathElement (m_End,usa,false,-1));
|
|
m_InPath = m_Path.end ();
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_Graph->ClearPathFlags ();
|
|
|
|
m_StartNode->PathWeight (1,CostGuess (m_EndNode),usa);
|
|
calc.Insert (m_StartNode);
|
|
|
|
done = false;
|
|
m_Calced = false;
|
|
int count = 0;
|
|
|
|
{
|
|
PATH_LOGIC("RailPath phase 1");
|
|
TIME_FUNCTION(tPathCalc1Time);
|
|
{
|
|
while (!done)
|
|
{
|
|
count++;
|
|
if (count > (m_Graph->NumNodes ()*2))
|
|
{
|
|
break;
|
|
}
|
|
if (!calc.size ())
|
|
break;
|
|
temp = calc.ExtractMin ();
|
|
if (temp == NULL)
|
|
break;
|
|
if (temp == m_EndNode)
|
|
{
|
|
done = true;
|
|
break;
|
|
}
|
|
int size;
|
|
float cost;
|
|
|
|
cost = temp->PathWeight ();
|
|
size = temp->NumLinks ();
|
|
for (i=0;i<size;i++)
|
|
{
|
|
CRailNode *dest;
|
|
CRailLink *curlink;
|
|
float newcost;
|
|
|
|
curlink = temp->Link (i);
|
|
dest = curlink->OtherLocation (temp);
|
|
newcost = curlink->LowestWeight (usage,type,temp);
|
|
if (newcost == -1)
|
|
continue;
|
|
if (type == 0)
|
|
continue;
|
|
newcost += cost;
|
|
if (dest->PathWeight (newcost,CostGuess (dest),type))
|
|
{
|
|
if (calc.Member (dest))
|
|
calc.DecreaseKey (dest);
|
|
else
|
|
calc.Insert (dest);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!done)
|
|
return;
|
|
|
|
done = false;
|
|
CRailNode *cur;
|
|
int min;
|
|
float mincost;
|
|
|
|
cur = m_EndNode;
|
|
|
|
min = NULL;
|
|
count =0;
|
|
|
|
{
|
|
PATH_LOGIC("RailPath phase 2");
|
|
TIME_FUNCTION(tPathCalc2Time);
|
|
{
|
|
while (!done)
|
|
{
|
|
count++;
|
|
if (count > (m_Graph->NumNodes ()*2))
|
|
{
|
|
m_Calced = false;
|
|
return;
|
|
}
|
|
min = 0;
|
|
mincost = cur->Link (min)->OtherLocation (cur)->PathWeight ();
|
|
if (cur->Link (min)->LowestWeight (usage,type,cur->Link (min)->OtherLocation (cur)) == -1.0f)
|
|
mincost = 0;
|
|
for (i=1;i<cur->NumLinks ();i++)
|
|
{
|
|
float t;
|
|
|
|
t= cur->Link (i)->OtherLocation (cur)->PathWeight ();
|
|
if (cur->Link (i)->LowestWeight (usage,type,cur->Link (i)->OtherLocation (cur)) == -1.0f)
|
|
t = 0;
|
|
if (((t < mincost) && (t != 0)) || (mincost == 0))
|
|
{
|
|
mincost = t;
|
|
min = i;
|
|
}
|
|
}
|
|
m_NodePath.push_back (NodePathElement (cur->Link (min),cur,cur->PathType ()));
|
|
cur = cur->Link (min)->OtherLocation (cur);
|
|
if (cur == m_StartNode)
|
|
{
|
|
int fred = 0;
|
|
if (usage & LEGFLAG)
|
|
fred = LEGFLAG;
|
|
else if (usage & JUMPFLAG)
|
|
fred = JUMPFLAG;
|
|
else if (usage & TRACKFLAG)
|
|
fred = TRACKFLAG;
|
|
else if (usage & WHEELFLAG)
|
|
fred = WHEELFLAG;
|
|
else if (usage & FLYFLAG)
|
|
fred = FLYFLAG;
|
|
else if (usage & HOVERFLAG)
|
|
fred = HOVERFLAG;
|
|
else if (usage & HELIFLAG)
|
|
fred = HELIFLAG;
|
|
else if (usage & WATERFLAG)
|
|
fred = WATERFLAG;
|
|
#if defined(LAB_ONLY)
|
|
else
|
|
PAUSE (("unknown movetype in calcpath"));
|
|
#endif
|
|
|
|
m_NodePath.push_back (NodePathElement (NULL,cur,fred));
|
|
ReverseList ();
|
|
done = true;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_Calced = true;
|
|
m_State = RAIL_START_PATH;
|
|
m_HeadPoint = Stuff::Point3D (-1,-1,-1);
|
|
m_InNodePath = 0;
|
|
ConvertNodeToPath ();
|
|
if (m_Calced)
|
|
CreatePathRequests ();
|
|
}
|
|
}
|
|
|
|
void CRailPath::CreatePathRequests (void)
|
|
{
|
|
TIME_FUNCTION(tCreatePathRequestsTime);
|
|
|
|
if (m_Calced)
|
|
NewSubPath (m_Start);
|
|
}
|
|
|
|
|