Files
firestorm/Gameleap/code/mw4/Code/MW4/gridmove.cpp
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

1048 lines
23 KiB
C++

#include "MW4Headers.hpp"
#include "server\comline.hpp"
#include "adept\application.hpp"
#include "rail_move.hpp"
#include "ai.hpp"
#pragma warning (push)
#include <vector>
#include <map>
#pragma warning (pop)
namespace MW4AI
{
extern Stuff::Scalar MinZ, MaxZ, MinX, MaxX;
extern __int64 tPathTime,tGridPathTime;
};
namespace MechWarrior4
{
extern DWORD Path_Calcs_Count;
extern DWORD GridPath_Calcs_Count;
extern DWORD QuickPath_Calcs_Count;
extern DWORD QuickRail_Calcs_Count;
extern DWORD FailedPath_Calcs_Count;
}
using namespace MW4AI;
using namespace MechWarrior4;
unsigned int CGridPath::m_BlockGrid[BLOCK_GRID_SIZE][BLOCK_GRID_SIZE][2];
int CGridPath::m_BlockOriginX,CGridPath::m_BlockOriginY;
CGridPath *CGridPath::m_WorkingPath=NULL;
CGridPath::CGridPath (CRailGraph *graph,unsigned short mask,Stuff::Scalar sx,Stuff::Scalar sy,Stuff::Scalar dx,Stuff::Scalar dy,bool tenmeter)
{
m_Working = false;
m_WorkCount = 0;
m_TenMeterAllowed = tenmeter;
m_StartX = (int) (sx);
m_StartY = (int) (sy);
m_EndX = (int) (dx);
m_EndY = (int) (dy);
m_Calced = false;
m_DirList.clear ();
m_InDirPath = m_DirList.begin ();
m_Graph = graph;
m_QuickValid = false;
m_Mask = mask;
}
CGridPath::CGridPath (CRailGraph *graph)
{
m_Working = false;
m_WorkCount = 0;
m_TenMeterAllowed = false;
m_StartX = 0;
m_StartY = 0;
m_EndX = 0;
m_EndY = 0;
m_Calced = false;
m_DirList.clear ();
m_InDirPath = m_DirList.begin ();
m_Graph = graph;
m_QuickValid = false;
m_Mask = 0;
}
CGridPath::CGridPath (CRailGraph *graph,unsigned short mask,int sx,int sy,int dx,int dy,bool tenmeter)
{
m_Working = false;
m_WorkCount = 0;
m_TenMeterAllowed = tenmeter;
m_StartX = sx;
m_StartY = sy;
m_EndX = dx;
m_EndY = dy;
m_Calced = false;
m_DirList.clear ();
m_InDirPath = m_DirList.begin ();
m_Graph = graph;
m_QuickValid = false;
m_Mask = mask;
}
CGridPath::~CGridPath (void)
{
if (m_WorkingPath == this)
m_WorkingPath = NULL;
calc.clear ();
m_DirList.clear ();
}
void CGridPath::UpdateSrcDest (int sx,int sy,int dx,int dy)
{
if (m_Working)
return;
m_StartX = sx;
m_StartY = sy;
m_EndX = dx;
m_EndY = dy;
}
void CGridPath::UpdateSrcDest (Scalar sx,Scalar sy,Scalar dx,Scalar dy)
{
if (m_Working)
return;
m_StartX = (int) (sx);
m_StartY = (int) (sy);
m_EndX = (int) (dx);
m_EndY = (int) (dy);
}
void CGridPath::Save (MemoryStream *stream)
{
int count;
stlport::vector<DirElement>::iterator iter;
*stream << m_TenMeterAllowed;
*stream << m_StartX;
*stream << m_StartY;
*stream << m_EndX;
*stream << m_EndY;
*stream << m_Calced;
*stream << m_QuickValid;
*stream << m_Mask;
*stream << m_DirList.size ();
for (count = 0,iter = m_DirList.begin ();(iter != m_DirList.end ()) && (m_InDirPath != iter);iter++,count++);
*stream << count;
for (iter = m_DirList.begin ();iter != m_DirList.end ();iter++)
{
stream->WriteBytes (&(*iter),sizeof (*iter));
}
}
void CGridPath::Load (MemoryStream *stream)
{
int count,size,i;
*stream >> m_TenMeterAllowed;
*stream >> m_StartX;
*stream >> m_StartY;
*stream >> m_EndX;
*stream >> m_EndY;
*stream >> m_Calced;
*stream >> m_QuickValid;
*stream >> m_Mask;
*stream >> size;
*stream >> count;
m_DirList.assign (size,DirElement ());
for (i=0;i<size;i++)
{
stream->ReadBytes (&(m_DirList[i]),sizeof (DirElement));
}
m_InDirPath = m_DirList.begin ();
m_InDirPath += count;
}
void CGridPath::PointList (stlport::vector<Point3D>& dest)
{
stlport::vector<DirElement>::iterator iter;
AutoHeap local_heap (g_RailHeap);
for (iter = m_InDirPath;iter != m_DirList.end ();iter++)
{
Scalar x,y;
if (iter->locX < 0)
{
x = (iter->locX*BLOCK_GRID_RES) - (BLOCK_GRID_RES/2.0f);
}
else
{
x = (iter->locX*BLOCK_GRID_RES) + (BLOCK_GRID_RES/2.0f);
}
if (iter->locY < 0)
{
y = (iter->locY*BLOCK_GRID_RES) - (BLOCK_GRID_RES/2.0f);
}
else
{
y = (iter->locY*BLOCK_GRID_RES) + (BLOCK_GRID_RES/2.0f);
}
dest.push_back (Point3D (x,0,y));
}
}
void CGridPath::ConstructQuickPath (void)
{
m_DirList.clear ();
Stuff::Point3D extra;
float sx,sy,dx,dy;
int ix,iy,ex,ey;
int count,distcount;
int startx,starty,endx,endy;
AutoHeap local_heap (g_RailHeap);
startx = m_StartX/BLOCK_GRID_RES;
starty = m_StartY/BLOCK_GRID_RES;
endx = m_EndX/BLOCK_GRID_RES;
endy = m_EndY/BLOCK_GRID_RES;
Verify ((startx != endx) || (starty != endy));
dx = (float) endx - startx;
dy = (float) endy - starty;
sx = dx < 0 ? dx*-1.0f : dx;
sy = dy < 0 ? dy*-1.0f : dy;
if (sx > sy)
{
dy = dy / sx;
count = (int) ( (dx<0.0 ? dx*-1.0f : dx));
dx = dx<0 ? -1.0f : 1.0f;
}
else
{
dx = dx / sy;
count = (int) ( (dy<0.0 ? dy*-1.0f : dy));
dy = dy<0 ? -1.0f : 1.0f;
}
sx = (float) startx;
sy = (float) starty;
ex = endx;
ey = endy;
ix = (int) (sx);
iy = (int) (sy);
distcount = 0;
m_DirList.push_back (DirElement (ix,iy));
bool flag = false;
while (count)
{
count--;
sx += dx;
sy += dy;
ix = (int) (sx);
iy = (int) (sy);
distcount += BLOCK_GRID_RES;
flag = false;
m_DirList.push_back (DirElement (ix,iy));
flag = true;
}
if (!flag)
{
m_DirList.push_back (DirElement (ix,iy));
}
m_InDirPath = m_DirList.begin ();
m_Calced = true;
}
void CGridPath::DumpPath (void)
{
stlport::vector<DirElement>::iterator iter;
char text[100];
iter = m_DirList.begin ();
while (iter != m_DirList.end ())
{
sprintf (text,"Move Point %d,%d",iter->locX,iter->locY);
COMSPEW (text);
iter++;
}
COMSPEW ("");
}
void CGridPath::Calc30Path (void)
{
Verify (m_Graph);
int i;
GridPathElement temp;
bool done,hackflag=false;
bool allow10early=false;
bool did10early=false;
int startx,starty,endx,endy;
const int SIZEDELTA = 8;
static int delta[SIZEDELTA][5] = { // first, second, cost
{0,-1,7,1,10},
{1,-1,0,2,15},
{1,0,1,3,10},
{1,1,2,4,15},
{0,1,5,3,10},
{-1,1,6,4,15},
{-1,0,7,5,10},
{-1,-1,6,0,15}
};
AutoHeap local_heap (g_RailHeap);
PATH_LOGIC("Calc30Path");
#if !defined(NO_TIMERS)
my_AutoTimer fred ((void *) &tGridPathTime);
#endif
Set_Statistic(GridPath_Calcs_Count, GridPath_Calcs_Count+1);
m_QuickValid = false;
startx = m_StartX/BLOCK_GRID_RES;
starty = m_StartY/BLOCK_GRID_RES;
endx = m_EndX/BLOCK_GRID_RES;
endy = m_EndY/BLOCK_GRID_RES;
#if 0
Point3D srcpt,destpt,extra;
destpt.x = (float) m_EndX;
destpt.z = (float) m_EndY;
srcpt.x = (float) m_StartX;
srcpt.z = (float) m_StartY;
destpt.y = 0;
srcpt.y = 0;
extra = m_Graph->PullPointElementMask (srcpt,destpt,m_Mask);
Verify (extra != Point3D (-1,-1,-1));
endx = (int) (extra.x / BLOCK_GRID_RES);
endy = (int) (extra.z / BLOCK_GRID_RES);
memset (m_BlockGrid,0,sizeof (unsigned int) * BLOCK_GRID_SIZE * BLOCK_GRID_SIZE * 2);
int dx,dy;
dx = startx>endx ? startx - endx : endx - startx;
dy = starty>endy ? starty - endy : endy - starty;
Verify (dx < BLOCK_GRID_SIZE);
Verify (dy < BLOCK_GRID_SIZE);
m_BlockOriginX = startx - ((BLOCK_GRID_SIZE - dx) >> 1);
m_BlockOriginY = starty - ((BLOCK_GRID_SIZE - dy) >> 1);
if (m_BlockOriginX < MinX)
m_BlockOriginX = (int) MinX;
if (m_BlockOriginY < MinZ)
m_BlockOriginY = (int) MinZ;
if (m_BlockOriginX >= (MaxX - BLOCK_GRID_SIZE))
m_BlockOriginX = (int) ( MaxX - BLOCK_GRID_SIZE - 1);
if (m_BlockOriginY >= (MaxZ - BLOCK_GRID_SIZE))
m_BlockOriginY = (int) ( MaxZ - BLOCK_GRID_SIZE-1 - 1);
Cost (startx,starty,1,(unsigned short) CostGuess (startx,starty));
calc.Insert (GridPathElement (startx,starty));
#endif
GridPathElement end (endx,endy);
done = false;
m_Calced = false;
{
hackflag = false;
top:
int count = 0;
while (!done)
{
count++;
if (count > GRIDMOVE_FAIL_THRESHOLD)
break;
if (!calc.size ())
break;
temp = calc.ExtractMin ();
if (temp == end)
{
done = true;
break;
}
int cost;
cost = Cost (temp);
if (cost > 1)
allow10early = false;
for (i=0;i<SIZEDELTA;i++)
{
int newcost;
int newx,newy;
newx = temp.locX+delta[i][0];
newy = temp.locY+delta[i][1];
if (!m_Graph->MoveTo (newx,newy,i,m_Mask))
continue;
if (!allow10early)
{
int newx,newy;
{
newx = temp.locX+delta[delta[i][2]][0];
newy = temp.locY+delta[delta[i][2]][1];
if (!m_Graph->MoveTo (newx,newy,delta[i][2],m_Mask))
continue;
}
{
newx = temp.locX+delta[delta[i][3]][0];
newy = temp.locY+delta[delta[i][3]][1];
if (!m_Graph->MoveTo (newx,newy,delta[i][3],m_Mask))
continue;
}
}
int updown = m_Graph->UpDownTo (newx,newy,delta[i][3],m_Mask);
if (updown == 0)
{
newcost = delta[i][4];
}
else if (updown == 1)
{
if (delta[i][4] == 10)
newcost = 14;
else
newcost = 21;
}
else
{
if (delta[i][4] == 10)
newcost = 13;
else
newcost = 19;
}
newcost += cost;
newcost += AdjustCost (newx,newy);
if (Cost (newx,newy,(unsigned int) newcost,(unsigned int) CostGuess (newx,newy)))
{
GridPathElement newelement(newx,newy);
if (calc.Member (newelement))
{
calc.DecreaseKey (newelement);
}
else
{
calc.Insert (newelement);
}
}
}
}
if ((!hackflag) && (count <= 2) && (!done)) // all cells around itself are blocked
{
Cost (startx,starty,1,(unsigned short) CostGuess (startx,starty));
calc.clear ();
calc.Insert (GridPathElement (startx,starty));
allow10early = true;
did10early = true;
hackflag = true;
goto top;
}
if (!done && (count > GRIDMOVE_FAIL_THRESHOLD)) // check for can continue work later
{
m_WorkCount += count;
if (m_WorkCount > GRIDMOVE_MAX_CHECK_THRESHOLD)
{
calc.clear ();
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Working = false;
}
return;
}
else if (!done) // visited all possible cells
{
calc.clear ();
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Working = false;
return;
}
done = false;
GridPathElement cur;
int min;
unsigned int mincost;
int newx,newy;
int lastdir = -1;
GridPathElement start(startx,starty);
int t;
Stuff::Scalar dirdist = 0;
cur.locX = endx;
cur.locY = endy;
m_DirList.push_back (DirElement (cur.locX,cur.locY));
calc.clear ();
min = NULL;
count=0;
while (!done)
{
#if 1
count++;
if (count > (GRIDMOVE_MAX_CHECK_THRESHOLD/2))
{
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
break;
}
#endif
min = 0;
newx = cur.locX + delta[min][0];
newy = cur.locY + delta[min][1];
mincost = Cost (newx,newy);
for (i=1;i<SIZEDELTA;i++)
{
if ((newx == startx) && (newy == starty))
{
min = i-1;
mincost = 1;
break;
}
newx = cur.locX + delta[i][0];
newy = cur.locY + delta[i][1];
t= Cost (newx,newy);
if (t && !hackflag && (t <= 16))
{
int newx,newy;
{
{
newx = cur.locX+delta[delta[i][2]][0];
newy = cur.locY+delta[delta[i][2]][1];
if (!m_Graph->MoveTo (newx,newy,delta[i][2]+4,m_Mask))
t = 0;
}
{
newx = cur.locX+delta[delta[i][3]][0];
newy = cur.locY+delta[delta[i][3]][1];
if (!m_Graph->MoveTo (newx,newy,delta[i][3]+4,m_Mask))
t = 0;
}
}
}
if (((t < mincost) && (t != 0)) || (mincost == 0))
{
mincost = t;
min = i;
}
}
if (mincost == 0)
{
min = 0;
newx = cur.locX + delta[min][0];
newy = cur.locY + delta[min][1];
mincost = Cost (newx,newy);
for (i=1;i<SIZEDELTA;i++)
{
newx = cur.locX + delta[i][0];
newy = cur.locY + delta[i][1];
t= Cost (newx,newy);
if (((t < mincost) && (t != 0)) || (mincost == 0))
{
mincost = t;
min = i;
}
}
}
Verify (mincost != 0);
cur.locX+=delta[min][0];
cur.locY+=delta[min][1];
dirdist += BLOCK_GRID_RES;
bool dirflag = false;
if (lastdir != min)
{
dirdist = 0;
m_DirList.push_back (DirElement (cur.locX,cur.locY));
dirflag = true;
lastdir = min;
}
if (cur == start)
{
if (!dirflag)
m_DirList.push_back (DirElement (cur.locX,cur.locY));
done = true;
m_Calced = true;
continue;
}
}
}
if (!m_Calced)
{
// STOP (("should not get here. We have already weighted cells from start to finish"));
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
g_PathManager->m_FailedCalcFrame = true;
m_Working = false;
return;
}
ReverseList ();
Verify (m_DirList.size () >= 2);
// SmoothList ();
m_InDirPath = m_DirList.begin ();
if (m_InDirPath != m_DirList.end ())
{
m_InDirPath++;
}
m_Calced = true;
m_Working = false;
}
void CGridPath::Calc10Path (void)
{
Verify (m_Graph);
int i;
GridPathElement temp;
bool done,hackflag=false;
int startx,starty,endx,endy;
const int SIZEDELTA = 8;
static int delta[SIZEDELTA][5] = { // first, second, cost
{0,-1,7,1,10},
{1,-1,0,2,15},
{1,0,1,3,10},
{1,1,2,4,15},
{0,1,5,3,10},
{-1,1,6,4,15},
{-1,0,7,5,10},
{-1,-1,6,0,15}
};
AutoHeap local_heap (g_RailHeap);
PATH_LOGIC("Calc10Path");
#if !defined(NO_TIMERS)
my_AutoTimer fred ((void *) &tGridPathTime);
#endif
Set_Statistic(GridPath_Calcs_Count, GridPath_Calcs_Count+1);
m_QuickValid = false;
startx = m_StartX/BLOCK_GRID_RES;
starty = m_StartY/BLOCK_GRID_RES;
endx = m_EndX/BLOCK_GRID_RES;
endy = m_EndY/BLOCK_GRID_RES;
Point3D srcpt,destpt,extra;
#if 0
memset (m_BlockGrid,0,sizeof (unsigned int) * BLOCK_GRID_SIZE * BLOCK_GRID_SIZE * 2);
int dx,dy;
dx = startx>endx ? startx - endx : endx - startx;
dy = starty>endy ? starty - endy : endy - starty;
Verify (dx < BLOCK_GRID_SIZE);
Verify (dy < BLOCK_GRID_SIZE);
m_BlockOriginX = startx - ((BLOCK_GRID_SIZE - dx) >> 1);
m_BlockOriginY = starty - ((BLOCK_GRID_SIZE - dy) >> 1);
if (m_BlockOriginX < MinX)
m_BlockOriginX = (int) MinX;
if (m_BlockOriginY < MinZ)
m_BlockOriginY = (int) MinZ;
if (m_BlockOriginX >= (MaxX - BLOCK_GRID_SIZE))
m_BlockOriginX = (int) ( MaxX - BLOCK_GRID_SIZE - 1);
if (m_BlockOriginY >= (MaxZ - BLOCK_GRID_SIZE))
m_BlockOriginY = (int) ( MaxZ - BLOCK_GRID_SIZE-1 - 1);
Cost (startx,starty,1,(unsigned short) CostGuess (startx,starty));
calc.Insert (GridPathElement (startx,starty));
#endif
GridPathElement end (endx,endy);
done = false;
m_Calced = false;
{
hackflag = false;
top:
int count = 0;
while (!done)
{
count++;
if (count > GRIDMOVE_FAIL_THRESHOLD)
break;
if (!calc.size ())
break;
temp = calc.ExtractMin ();
if (temp == end)
{
done = true;
break;
}
int cost;
cost = Cost (temp);
for (i=0;i<SIZEDELTA;i++)
{
int newcost;
int newx,newy;
newx = temp.locX+delta[i][0];
newy = temp.locY+delta[i][1];
if (!m_Graph->MoveTo (newx,newy,i,m_Mask))
continue;
int updown = m_Graph->UpDownTo (newx,newy,delta[i][3],m_Mask);
if (updown == 0)
{
newcost = delta[i][4];
}
else if (updown == 1)
{
if (delta[i][4] == 10)
newcost = 14;
else
newcost = 21;
}
else
{
if (delta[i][4] == 10)
newcost = 13;
else
newcost = 19;
}
newcost += cost;
newcost += AdjustCost (newx,newy);
if (Cost (newx,newy,(unsigned int) newcost,(unsigned int) CostGuess (newx,newy)))
{
GridPathElement newelement(newx,newy);
if (calc.Member (newelement))
calc.DecreaseKey (newelement);
else
calc.Insert (newelement);
}
}
}
if (!done && (count > GRIDMOVE_FAIL_THRESHOLD)) // check for can continue work later
{
m_WorkCount += count;
if (m_WorkCount > GRIDMOVE_MAX_CHECK_THRESHOLD)
{
calc.clear ();
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Working = false;
}
return;
}
else if (!done) // visited all possible cells
{
calc.clear ();
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Working = false;
return;
}
calc.clear ();
done = false;
GridPathElement cur;
int min;
unsigned int mincost;
int newx,newy;
int lastdir = -1;
GridPathElement start(startx,starty);
int t;
Stuff::Scalar dirdist = 0;
cur.locX = endx;
cur.locY = endy;
m_DirList.push_back (DirElement (cur.locX,cur.locY));
min = NULL;
count=0;
while (!done)
{
#if 1
count++;
if (count > (GRIDMOVE_MAX_CHECK_THRESHOLD/2))
{
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
break;
}
#endif
min = 0;
newx = cur.locX + delta[min][0];
newy = cur.locY + delta[min][1];
mincost = Cost (newx,newy);
for (i=1;i<SIZEDELTA;i++)
{
if ((newx == startx) && (newy == starty))
{
min = i-1;
mincost = 1;
break;
}
newx = cur.locX + delta[i][0];
newy = cur.locY + delta[i][1];
t= Cost (newx,newy);
if (((t < mincost) && (t != 0)) || (mincost == 0))
{
mincost = t;
min = i;
}
}
if (mincost == 0)
{
min = 0;
newx = cur.locX + delta[min][0];
newy = cur.locY + delta[min][1];
mincost = Cost (newx,newy);
for (i=1;i<SIZEDELTA;i++)
{
newx = cur.locX + delta[i][0];
newy = cur.locY + delta[i][1];
t= Cost (newx,newy);
if (((t < mincost) && (t != 0)) || (mincost == 0))
{
mincost = t;
min = i;
}
}
}
Verify (mincost != 0);
cur.locX+=delta[min][0];
cur.locY+=delta[min][1];
dirdist += BLOCK_GRID_RES;
bool dirflag = false;
if (lastdir != min)
{
dirdist = 0;
m_DirList.push_back (DirElement (cur.locX,cur.locY));
dirflag = true;
lastdir = min;
}
if (cur == start)
{
if (!dirflag)
m_DirList.push_back (DirElement (cur.locX,cur.locY));
done = true;
m_Calced = true;
continue;
}
}
}
if (!m_Calced)
{
STOP (("should not get here. have already created costs from start to end"));
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
g_PathManager->m_FailedCalcFrame = true;
m_Working = false;
return;
}
ReverseList ();
// SmoothList ();
Verify (m_DirList.size () >= 2);
m_InDirPath = m_DirList.begin ();
if (m_InDirPath != m_DirList.end ())
{
m_InDirPath++;
}
m_Calced = true;
m_Working = false;
}
void CGridPath::ContinueCalcPath (void)
{
Verify (m_Working);
Verify (m_WorkingPath == this);
if (m_TenMeterAllowed)
{
Calc10Path ();
}
else
{
Calc30Path ();
}
}
void CGridPath::DoCalcPath (void)
{
if (m_Working)
{
Verify (m_WorkingPath == this);
ContinueCalcPath ();
}
else
{
StartCalcPath ();
}
if (!m_Working)
m_WorkingPath = NULL;
}
void CGridPath::StartCalcPath (void)
{
Verify (m_Graph);
GridPathElement temp;
int startx,starty,endx,endy;
AutoHeap local_heap (g_RailHeap);
Verify (!m_Working);
Verify (m_WorkingPath == NULL);
PATH_LOGIC("CalcPath");
#if !defined(NO_TIMERS)
my_AutoTimer fred ((void *) &tGridPathTime);
#endif
Set_Statistic(GridPath_Calcs_Count, GridPath_Calcs_Count+1);
m_QuickValid = false;
startx = m_StartX/BLOCK_GRID_RES;
starty = m_StartY/BLOCK_GRID_RES;
endx = m_EndX/BLOCK_GRID_RES;
endy = m_EndY/BLOCK_GRID_RES;
if ((startx == endx) && (starty == endy))
{
m_Calced = true;
m_QuickValid = true;
return;
}
Point3D srcpt,destpt,extra;
destpt.x = (float) m_EndX;
destpt.z = (float) m_EndY;
srcpt.x = (float) m_StartX;
srcpt.z = (float) m_StartY;
destpt.y = 0;
srcpt.y = 0;
extra = m_Graph->PullPointElementMask (srcpt,destpt,m_Mask);
if (extra == Point3D (-1,-1,-1))
{
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
return;
}
m_EndX = (int) extra.x;
m_EndY = (int) extra.z;
endx = (int) (m_EndX / BLOCK_GRID_RES);
endy = (int) (m_EndY / BLOCK_GRID_RES);
if ((startx == endx) && (starty == endy))
{
m_Calced = true;
m_QuickValid = true;
return;
}
if (m_Graph->QuickCheck (m_StartX,m_StartY,m_EndX,m_EndY,m_Mask,!m_TenMeterAllowed))
{
Set_Statistic(QuickPath_Calcs_Count, QuickPath_Calcs_Count+1);
m_QuickValid = true;
m_Calced = true;
return;
}
memset (m_BlockGrid,0,sizeof (unsigned int) * BLOCK_GRID_SIZE * BLOCK_GRID_SIZE * 2);
int dx,dy;
dx = startx>endx ? startx - endx : endx - startx;
dy = starty>endy ? starty - endy : endy - starty;
if (dx >= BLOCK_GRID_SIZE)
{
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
return;
}
if (dy >= BLOCK_GRID_SIZE)
{
Set_Statistic(FailedPath_Calcs_Count, FailedPath_Calcs_Count+1);
m_Calced = false;
g_PathManager->m_FailedCalcFrame = true;
return;
}
m_BlockOriginX = startx - ((BLOCK_GRID_SIZE - dx) >> 1);
m_BlockOriginY = starty - ((BLOCK_GRID_SIZE - dy) >> 1);
if (m_BlockOriginX < MinX)
m_BlockOriginX = (int) MinX;
if (m_BlockOriginY < MinZ)
m_BlockOriginY = (int) MinZ;
if (m_BlockOriginX >= (MaxX - BLOCK_GRID_SIZE))
m_BlockOriginX = (int) ( MaxX - BLOCK_GRID_SIZE - 1);
if (m_BlockOriginY >= (MaxZ - BLOCK_GRID_SIZE))
m_BlockOriginY = (int) ( MaxZ - BLOCK_GRID_SIZE-1 - 1);
Cost (startx,starty,1,(unsigned short) CostGuess (startx,starty));
calc.Insert (GridPathElement (startx,starty));
m_WorkingPath = this;
m_WorkCount = 0;
m_Working = true;
ContinueCalcPath ();
}
void CGridPath::SmoothListHelper (stlport::vector<DirElement>& vec,int s,int e)
{
int x1,x2,y1,y2,middle;
AutoHeap local_heap (g_RailHeap);
x1 = m_DirList[s].locX;
y1 = m_DirList[s].locY;
x2 = m_DirList[e].locX;
y2 = m_DirList[e].locY;
if (s >= e)
{
vec.push_back (DirElement (x1,y1));
vec.push_back (DirElement (x2,y2));
return;
}
Verify (e<m_DirList.size ());
if (m_Graph->QuickCheck (x1,y1,x2,y2,m_Mask,!m_TenMeterAllowed))
{
vec.push_back (DirElement (x2,y2));
return;
}
middle = s+e;
middle >>= 1;
SmoothListHelper (vec,s,middle);
SmoothListHelper (vec,middle+1,e);
}
void CGridPath::SmoothList (void)
{
stlport::vector<DirElement> newlist;
int middle;
AutoHeap local_heap (g_RailHeap);
if (m_DirList.size () <=2 )
return;
newlist.clear ();
middle = m_DirList.size ();
middle >>= 1;
newlist.push_back (m_DirList[0]);
SmoothListHelper (newlist,0,middle-1);
SmoothListHelper (newlist,middle,m_DirList.size ()-1);
m_DirList = newlist;
}
void CGridPath::ReverseList (void)
{
stlport::vector<DirElement>::iterator s,e;
AutoHeap local_heap (g_RailHeap);
s = m_DirList.begin ();
e = m_DirList.end ();
stlport::reverse (s,e);
}