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

1981 lines
45 KiB
C++

#include "MW4Headers.hpp"
#include "adept\application.hpp"
#include "rail_move.hpp"
//#include "quadedge.h"
#include <MW4\MWMission.hpp>
#include <Adept\Map.hpp>
#include <Adept\CollisionGrid.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <adept\collisionvolume.hpp>
#include "path.hpp"
#include "bridge.hpp"
#include "cultural.hpp"
#include "mwplayer.hpp"
#include "move_rect.hpp"
#include "windows.h"
#include "shooterai.hpp"
#pragma warning (push)
#include <vector>
#include <map>
#pragma warning (pop)
using namespace MW4AI;
using namespace MechWarrior4;
using namespace ElementRenderer;
#define BADSLOPE 0.707f
namespace MW4AI
{
void GetMapData(Stuff::Scalar x, Stuff::Scalar z,CRailSquare *who)
// void GetMapData(Stuff::Scalar x, Stuff::Scalar z,Stuff::Scalar &y,Normal3D& normal,BYTE& material,int& objectid)
{
Stuff::Scalar i,j;
Stuff::Line3D line;
Point3D point;
Stuff::Scalar water_depth=0.0f;
who->normal.x = FLT_MAX;
who->normal.y = FLT_MAX;
who->normal.z = FLT_MAX;
for (i=-5.0f;i<=5.0f;i+=1.0f)
{
for (j=-5.0f;j<=5.0f;j+=1.0f)
{
point.x = x+i;
point.z = z+j;
point.y = 800.0f;
line.m_length = 1000.0f;
line.m_direction = Vector3D::Down;
line.SetOrigin(point);
//
// Prepare query
//
Stuff::Normal3D inormal;
Stuff::Line3D iline;
Stuff::Normal3D fred;
Entity::CollisionQuery *query;
//
// Cast ray for map surface
//
query = new Entity::CollisionQuery (&line, &fred, Entity::CanBeWalkedOnFlag, NULL);
Adept::Entity *entity_hit;
Check_Object(CollisionGrid::Instance);
entity_hit = CollisionGrid::Instance->ProjectLine(query);
if (entity_hit != NULL)
{
line.FindEnd(&point);
who->height = point.y;
Check_Object (Map::GetInstance());
Check_Object (Map::GetInstance()->GetGameModel ());
if ((Map::GetInstance()->GetGameModel ()->m_waterLevel - point.y) > water_depth)
water_depth = (Map::GetInstance()->GetGameModel ()->m_waterLevel - point.y);
who->material = query->m_material;
if (query->m_normal->y < who->normal.y)
{
who->normal.x = query->m_normal->x;
who->normal.y = query->m_normal->y;
who->normal.z = query->m_normal->z;
}
Check_Object (&who->normal);
}
delete query;
}
}
if ((water_depth >= ShallowWaterDepth) && (water_depth < MidWaterDepth))
{
who->material = FakeShallowWaterMaterial;
}
else if ((water_depth >= MidWaterDepth) && (water_depth < DeepWaterDepth))
{
who->material = FakeMidWaterMaterial;
}
else if (water_depth >= DeepWaterDepth)
{
who->material = FakeOceanicWaterMaterial;
}
who->objectid = -1;
}
Stuff::Scalar MinZ, MaxZ, MinX, MaxX;
}
void CRailNode::CheckRadius()
{
if (m_Radius < 1.0f)
m_Radius = 1.0f;
if (m_Location.x < MinX + 5.0f)
m_Location.x = MinX + 5.0f;
if (m_Location.z < MinZ + 5.0f)
m_Location.z = MinZ + 5.0f;
if (m_Location.x > MaxX - 5.0f)
m_Location.x = MaxX - 5.0f;
if (m_Location.z > MaxZ - 5.0f)
m_Location.z = MaxZ - 5.0f;
if (m_Location.x - m_Radius < MinX)
m_Radius = m_Location.x - MinX - 1.0f;
if (m_Location.z - m_Radius < MinZ)
m_Radius = m_Location.z - MinZ - 1.0f;
if (m_Location.x + m_Radius > MaxX)
m_Radius = MaxX - m_Location.x - 1.0f;
if (m_Location.z + m_Radius > MaxZ)
m_Radius = MaxZ - m_Location.z - 1.0f;
Verify(m_Radius > 0);
}
void CRailGraph::CalcEditorDistances (void)
{
int i,j,size;
gos_PushCurrentHeap (g_RailHeap);
size = m_Nodes.size ();
for (i=0;i<size;i++)
{
if (m_Nodes[i])
{
m_Nodes[i]->m_DistanceValid = true;
m_Nodes[i]->m_EditorDistance.reserve (size);
for (j=0;j<size;j++)
m_Nodes[i]->m_EditorDistance.push_back (FLT_MAX);
}
}
for (i=0;i<(size-1);i++)
{
for (j=i+1;j<size;j++)
{
Stuff::Point3D loc1,loc2,extra;
float dist;
if ((!m_Nodes[i]) && (!m_Nodes[j]))
{
continue;
}
if (!m_Nodes[i])
{
m_Nodes[j]->m_EditorDistance[i] = FLT_MAX;
continue;
}
if (!m_Nodes[j])
{
m_Nodes[i]->m_EditorDistance[j] = FLT_MAX;
continue;
}
loc1 = m_Nodes[i]->Location ();
loc2 = m_Nodes[j]->Location ();
loc1.y = 0;
loc2.y = 0;
extra.Subtract (loc1,loc2);
dist = extra.GetLength ();
m_Nodes[i]->m_EditorDistance[j] = dist;
m_Nodes[j]->m_EditorDistance[i] = dist;
}
}
gos_PopCurrentHeap ();
}
CRailSquare::CRailSquare (void)
{
height = 0;
material = 0;
objectid = -1;
objectheight = 1.0f;
waterlevel = 0;
normal = Normal3D (0,0,1);
bridge = -1;
}
void CRailSquare::Construct (Stuff::Scalar x,Stuff::Scalar z)
{
// GetMapData (x+5.0f,z+5.0f,height,normal,material,objectid);
GetMapData (x+5.0f,z+5.0f,this);
#if defined(LAB_ONLY)
switch (material)
{
case WaterMaterial:
PAUSE (("ran into a water material, should be a water depth based material"));
break;
case NoMaterial:
case LavaMaterial:
case GreyDirtMaterial:
case BrownDirtMaterial:
case DarkGreyDirtMaterial:
case DarkBrownDirtMaterial:
case RockMaterial:
case DarkRockMaterial:
case SteelMaterial:
case BlacktopMaterial:
case UsMaterial:
case ThemMaterial:
case GlassMaterial:
case GrassMaterial:
case WoodMaterial:
case ConcreteMaterial:
case DarkConcreteMaterial:
case SnowMaterial:
case FakeShallowWaterMaterial:
case FakeMidWaterMaterial:
case FakeOceanicWaterMaterial:
// MSL 5.03 Lava
case LightMineralMaterial:
case DarkMineralMaterial:
case AshMaterial:
case CrackedLavaMaterial:
case OpenLavaMaterial:
break;
default:
PAUSE (("ran into an unknown material"));
break;
}
#endif
}
CRailWorkGrid::CRailWorkGrid (void)
{
m_Grid.clear ();
}
void CRailWorkGrid::MarkBuilding (ExtentBox& box,int id,bool bridge,CMoveGrid *movegrid,CAirMoveGrid *airmovegrid,bool walkthruflag)
{
int x,z;
int minx,maxx,minz,maxz;
int offx,offz;
minx = (int) box.minX;
maxx = (int) box.maxX;
minz = (int) box.minZ;
maxz = (int) box.maxZ;
if (minx < MinX)
minx = (int) MinX;
if (minz < MinZ)
minz = (int) MinZ;
if (maxx >= (MaxX))
maxx = (int) (MaxX)-1;
if (maxz >= (MaxZ))
maxz = (int) (MaxZ)-1;
minx /= BLOCK_GRID_RES;
maxx /= BLOCK_GRID_RES;
minz /= BLOCK_GRID_RES;
maxz /= BLOCK_GRID_RES;
offx = (int) MinX/BLOCK_GRID_RES;
offz = (int) MinZ/BLOCK_GRID_RES;
if (bridge)
{
for (x=minx;x<=maxx;x++)
{
for (z=minz;z<=maxz;z++)
{
m_Grid[x-offx][z-offz].objectid = id;
if (bridge)
m_Grid[x-offx][z-offz].bridge = id;
m_Grid[x-offx][z-offz].objectheight = box.maxY;
movegrid->PassableLocalOverride (x,z,0);
}
}
if ((maxx-minx) > (maxz-minz))
{
for (z=minz;z<=maxz;z++)
{
movegrid->PassableLocalOverride (minx-3,z,0);
movegrid->PassableLocalOverride (maxx+3,z,0);
movegrid->PassableLocalOverride (minx-2,z,0);
movegrid->PassableLocalOverride (maxx+2,z,0);
movegrid->PassableLocalOverride (minx-1,z,0);
movegrid->PassableLocalOverride (maxx+1,z,0);
}
for (x=minx;x<=maxx;x++)
{
movegrid->PassableLocalOverride (x,minz-2,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,maxz+2,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,minz-3,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,maxz+3,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,minz-1,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,maxz+1,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,minz,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (x,maxz,BLOCKED_FLAGS);
}
}
else
{
for (x=minx;x<=maxx;x++)
{
movegrid->PassableLocalOverride (x,minz-2,0);
movegrid->PassableLocalOverride (x,maxz+2,0);
movegrid->PassableLocalOverride (x,minz-3,0);
movegrid->PassableLocalOverride (x,maxz+3,0);
movegrid->PassableLocalOverride (x,minz-1,0);
movegrid->PassableLocalOverride (x,maxz+1,0);
}
for (z=minz;z<=maxz;z++)
{
movegrid->PassableLocalOverride (minx-3,z,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (maxx+3,z,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (minx-2,z,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (maxx+2,z,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (minx-1,z,BLOCKED_FLAGS);
movegrid->PassableLocalOverride (maxx+1,z,BLOCKED_FLAGS);
}
}
}
else
{
for (x=minx;x<=maxx;x++)
{
for (z=minz;z<=maxz;z++)
{
m_Grid[x-offx][z-offz].walkthruflag = walkthruflag;
m_Grid[x-offx][z-offz].objectid = id;
m_Grid[x-offx][z-offz].objectheight = box.maxY - box.minY;
}
}
}
}
bool CRailWorkGrid::AnalyzeNode (QuadTreeNode<int> *node)
{
int sx,ex,sy,ey,cx,cy;
bool flag;
sx = node->Left ();
ex = node->Right ();
sy = node->Top ();
ey = node->Bottom ();
flag = false;
if (m_Grid[sx][sy].objectid != -1)
flag = true;
for (cx = sx;cx<=ex;cx++)
{
for (cy = sy;cy<=ey;cy++)
{
if (flag)
{
if (m_Grid[cx][cy].objectid == -1)
return true;
}
else
{
if (m_Grid[cx][cy].objectid != -1)
return true;
}
}
}
return false;
}
bool QuadTree<int>::TraverseFunction (QuadTreeNode<int> *node,int level,DWORD param)
{
CRailWorkGrid *grid;
if (param)
{
grid = (CRailWorkGrid *) param;
if (grid->AnalyzeNode (node))
{
node->Subdivide ();
}
}
return true;
}
void CRailWorkGrid::Construct (WorkCallBack callback,float maxpercent,CMoveGrid *movegrid,CAirMoveGrid *airmovegrid)
{
int i,j,sizex,sizey;
Stuff::Scalar x,z;
stlport::vector<CRailSquare> fred;
float curpercent;
float dpercent;
x = MaxX - MinX;
x /= 10.0f;
z = MaxZ - MinZ;
z /= 10.0f;
m_Grid.assign ((int) x,fred);
for (i=0;i<x;i++)
{
m_Grid[i].assign ((int) z,CRailSquare ());
}
curpercent = 0;
sizex = m_Grid.size ();
dpercent = maxpercent / sizex;
movegrid->Clear ();
airmovegrid->Clear ();
for (i=0;i<sizex;i++)
{
curpercent += dpercent;
if (callback)
callback (curpercent);
sizey = m_Grid[i].size ();
for (j=0;j<sizey;j++)
{
x = i*10.0f;
x += MinX;
z = j*10.0f;
z += MinZ;
m_Grid[i][j].Construct (x,z);
}
}
int offx = (int) (MinX / BLOCK_GRID_RES);
int offz = (int) (MinZ / BLOCK_GRID_RES);
for (i=0;i<sizex;i++)
{
sizey = m_Grid[i].size ();
for (j=0;j<sizey;j++)
{
switch (m_Grid[i][j].material)
{
case FakeShallowWaterMaterial:
movegrid->PassableLocalOverride (i+offx,j+offz,SHALLOW_WATER<<WATER_SHIFT);
movegrid->PassableLocal (i+offx,j+offz,TRACKPASS_FLAG+WHEELPASS_FLAG+WATERPASS_FLAG);
break;
case FakeMidWaterMaterial:
movegrid->PassableLocalOverride (i+offx,j+offz,MEDIUM_WATER<<WATER_SHIFT);
movegrid->PassableLocal (i+offx,j+offz,TRACKPASS_FLAG+WHEELPASS_FLAG);
break;
// MSL 5.03 Lava
case CrackedLavaMaterial:
case OpenLavaMaterial:
case FakeOceanicWaterMaterial:
movegrid->PassableLocalOverride (i+offx,j+offz,DEEP_WATER<<WATER_SHIFT);
movegrid->PassableLocal (i+offx,j+offz,LEGPASS_FLAG+TRACKPASS_FLAG+WHEELPASS_FLAG);
break;
default:
movegrid->PassableLocalOverride (i+offx,j+offz,WATERPASS_FLAG);
break;
}
}
}
UserConstants *constants;
constants = UserConstants::Instance ();
Check_Pointer (constants);
for (i=0;i<sizex;i++)
{
sizey = m_Grid[i].size ();
for (j=0;j<sizey;j++)
{
float nx,nz,ny;
nx = m_Grid[i][j].normal.x;
nz = m_Grid[i][j].normal.z;
ny = m_Grid[i][j].normal.y;
if ((nz <= 0) && (nx >= -Pi_Over_8) && (nx <= Pi_Over_8))
{
movegrid->PassableLocal (i+offx,j+offz,0 << SLOPEDIR_SHIFT);
}
else if ((nz <= 0) && (nx >= Pi_Over_8) && (nx <= (Pi_Over_2-Pi_Over_8)))
{
movegrid->PassableLocal (i+offx,j+offz,1 << SLOPEDIR_SHIFT);
}
else if ((nx >= 0) && (nz>=-Pi_Over_8) && (nz <= Pi_Over_8))
{
movegrid->PassableLocal (i+offx,j+offz,2 << SLOPEDIR_SHIFT);
}
else if ((nz >= 0) && (nx >= Pi_Over_8) && (nx <= (Pi_Over_2-Pi_Over_8)))
{
movegrid->PassableLocal (i+offx,j+offz,3 << SLOPEDIR_SHIFT);
}
else if ((nz >= 0) && (nx >= -Pi_Over_8) && (nx <= Pi_Over_8))
{
movegrid->PassableLocal (i+offx,j+offz,4 << SLOPEDIR_SHIFT);
}
else if ((nz >= 0) && (nx <= -Pi_Over_8) && (nx >= (-Pi_Over_2+Pi_Over_8)))
{
movegrid->PassableLocal (i+offx,j+offz,5 << SLOPEDIR_SHIFT);
}
else if ((nx <= 0) && (nz>=-Pi_Over_8) && (nz <= Pi_Over_8))
{
movegrid->PassableLocal (i+offx,j+offz,6 << SLOPEDIR_SHIFT);
}
else if ((nz <= 0) && (nx <= -Pi_Over_8) && (nx >= (-Pi_Over_2+Pi_Over_8)))
{
movegrid->PassableLocal (i+offx,j+offz,7 << SLOPEDIR_SHIFT);
}
else
{
STOP (("unknown slope direction value"));
}
if (ny < constants->Get (UserConstants::leg_down_slope))
{
movegrid->PassableLocal (i+offx,j+offz,LEGPASS_FLAG);
}
if (ny < constants->Get (UserConstants::track_down_slope))
{
movegrid->PassableLocal (i+offx,j+offz,TRACKPASS_FLAG);
}
if (ny < constants->Get (UserConstants::wheel_down_slope))
{
movegrid->PassableLocal (i+offx,j+offz,WHEELPASS_FLAG);
}
if (ny < constants->Get (UserConstants::hover_down_slope))
{
if (((movegrid->PassableLocal (i+offx,j+offz) & WATER_MASK) >> WATER_SHIFT) == NO_WATER)
{
movegrid->PassableLocal (i+offx,j+offz,HOVERPASS_FLAG);
}
}
if ((ny < constants->Get (UserConstants::leg_up_slope)) && (ny > constants->Get (UserConstants::leg_down_slope)))
{
movegrid->PassableLocal (i+offx,j+offz,LEGDOWN_SLOPE<<STEEP_SHIFT);
}
if ((ny < constants->Get (UserConstants::track_up_slope)) && (ny > constants->Get (UserConstants::track_down_slope)))
{
movegrid->PassableLocal (i+offx,j+offz,TRACKDOWN_SLOPE<<STEEP_SHIFT);
}
if ((ny < constants->Get (UserConstants::wheel_up_slope)) && (ny > constants->Get (UserConstants::wheel_down_slope)))
{
movegrid->PassableLocal (i+offx,j+offz,WHEELDOWN_SLOPE<<STEEP_SHIFT);
}
if ((ny < constants->Get (UserConstants::hover_up_slope)) && (ny > constants->Get (UserConstants::hover_down_slope)))
{
if (((movegrid->PassableLocal (i+offx,j+offz) & WATER_MASK) >> WATER_SHIFT) == NO_WATER)
{
movegrid->PassableLocal (i+offx,j+offz,HOVERPASS_FLAG);
}
}
}
}
int tablescan[] =
{
NameTable::CulturalArray,
NameTable::BuildingArray,
NameTable::TurretArray,
NameTable::VehicleArray
};
int size;
Scalar maxheight=0;
NameTable *table = NameTable::GetInstance();
Check_Object (table);
for (i=0;i<sizeof (tablescan)/sizeof (int);i++)
{
size = table->nameTableArray[tablescan[i]].GetLength ();
for (j=0;j<size;j++)
{
NameTableEntry *data;
Entity *who;
data = &table->nameTableArray [tablescan[i]][j];
if (!strnicmp (data->objectName,"water",5))
{
continue;
}
who = data->dataPointer->GetCurrent ();
if (!who)
continue;
if ((!who->GetSolidVolume ()) && (!who->GetHierarchicalVolume ()))
continue;
OBB *obb;
CollisionVolume *col;
col = who->GetHierarchicalVolume ();
if (!col)
col = who->GetSolidVolume ();
OBB world_bounds;
world_bounds.Multiply(col->m_localSpaceBounds, who->GetLocalToWorld());
obb = &(world_bounds);
ExtentBox box (*obb);
if (who->IsDerivedFrom (Vehicle::DefaultData))
{
if (maxheight < (box.maxY - box.minY))
{
maxheight = (box.maxY - box.minY);
}
}
bool walkthruflag = false;
{
MWObject *obj;
obj = Cast_Object (MWObject *,who);
if (obj->GetWalkThruType () == Entity::AnythingCanWalkThruType)
continue;
if ((obj->GetAI ()) && (tablescan[i] == NameTable::VehicleArray))
{
if (!obj->GetAI ()->IsDerivedFrom (ShooterAI::DefaultData))
continue;
}
if (!obj->CanOBBCollide ())
continue;
}
Point3D loc = (Point3D) obb->localToParent;
if (who->IsDerivedFrom (Bridge::DefaultData))
MarkBuilding (box,data->GetObjectID (),true,movegrid,airmovegrid,walkthruflag);
else
MarkBuilding (box,data->GetObjectID (),false,movegrid,airmovegrid,walkthruflag);
}
}
maxheight += 5.0f;
offx = (int) (MinX / BLOCK_GRID_RES);
offz = (int) (MinZ / BLOCK_GRID_RES);
for (i=0;i<sizex;i++)
{
curpercent += dpercent;
if (callback)
callback (curpercent);
sizey = m_Grid[i].size ();
for (j=0;j<sizey;j++)
{
x = i*10.0f;
x += MinX;
z = j*10.0f;
z += MinZ;
x += 5.0f;
z += 5.0f;
if (m_Grid[i][j].bridge != -1)
{
// movegrid->PassableLocal (i+offx,j+offx,BRIDGE_FLAG);
}
else if (m_Grid[i][j].objectid != -1)
{
// if (!m_Grid[i][j].walkthruflag)
movegrid->PassableLocal (i+offx,j+offx,BLOCKED_FLAGS);
// else
// movegrid->PassableLocal (i+offx,j+offx,0x3e); //mechs can move through
if (m_Grid[i][j].objectheight >= maxheight)
{
airmovegrid->Passable (x,z,AIRPASS_FLAG);
}
}
}
}
}
void CRailGraph::UpdateNodes (WorkCallBack callback,float percentstart)
{
stlport::vector<CRailNode *>::iterator iter;
int i,size,min;
Stuff::Scalar max;
float curpercent,dpercent;
CreateGrid (callback,80.0f);
Check_Pointer (m_WorkGrid);
CalcEditorDistances ();
curpercent = percentstart;
dpercent = 10.0f / m_Nodes.size ();
iter = m_Nodes.begin ();
while (iter != m_Nodes.end ())
{
if (!(*iter))
{
iter++;
continue;
}
curpercent += dpercent;
if (callback)
callback (curpercent);
size = (*iter)->m_EditorDistance.size ();
min = 0;
for (i=1;i<size;i++)
{
if ((*iter)->m_EditorDistance[i] < (*iter)->m_EditorDistance[min])
min = i;
}
max = (*iter)->m_EditorDistance[min];
if (((*iter)->Location ().x - MinX) < max)
max = (*iter)->Location ().x - MinX;
if (((*iter)->Location ().z - MinZ) < max)
max = (*iter)->Location ().z - MinZ;
if ((MaxX - (*iter)->Location ().x) < max)
max = MaxX - (*iter)->Location ().x;
if ((MaxZ - (*iter)->Location ().z) < max)
max = MaxZ - (*iter)->Location ().z;
max -= 1.0f;
(*iter)->m_Radius = m_WorkGrid->CalcRadius ((*iter)->Location (),max);
if ((*iter)->m_Radius < 20.0)
{
DeleteNode ((*iter)->ID ());
}
else
{
(*iter)->m_MaxRadius = (*iter)->m_Radius;
(*iter)->m_RadiusSquared = (*iter)->m_Radius * (*iter)->m_Radius;
}
iter++;
}
KillGrid ();
}
void CRailGraph::CreateRectData (WorkCallBack callback)
{
delete m_RectList;
gos_PushCurrentHeap (g_RailHeap);
m_RectList = new CMoveRectList ();
gos_PopCurrentHeap ();
m_RectList->Create (callback);
}
void CRailGraph::CreateBasicNodes (int num,WorkCallBack callback)
{
float curx,cury;
float offx,offy;
float dx,dy;
float temp;
int x,y;
float width,height;
int i,size;
float maxx,maxy;
float curpercent,dpercent;
if (num >= MAXNODES)
num = (MAXNODES-1);
maxx = MaxX - MinX - 10.0f;
maxy = MaxZ - MinZ - 10.0f;
size = m_Nodes.size ();
for (i=0;i<size;i++)
DeleteNode (i);
m_Nodes.clear ();
CreateGrid (callback,80.0f);
Check_Pointer (m_WorkGrid);
temp = (float) sqrt (num);
width = temp;
height = ((float) num)/temp;
dx = maxx / (width+1);
dy = maxy / (height+1);
if (dx < 100.0f)
{
dx = 100.0f;
width = maxx / dx;
}
if (dy < 100.0f)
{
dy = 100.0f;
height = maxy / dy;
}
width-=1;
height -=1;
curx = MinX + dx + 5.0f;
cury = MinZ + dy + 5.0f;
curpercent = 80.0f;
dpercent = 10.0f / height;
offx = MinX;
offy = MinZ;
gos_PushCurrentHeap (g_RailHeap);
for (y=0;y<=height;y++)
{
curx = MinX + dx + 5.0f;
curpercent += dpercent;
if (callback)
callback (curpercent);
for (x=0;x<=width;x++)
{
CRailNode *node;
if (!m_WorkGrid->BuildingAt (Stuff::Point3D (curx-offx,0,cury-offy)))
{
node = new CRailNode (Stuff::Point3D (curx,0,cury),50);
AddNode (node);
}
curx += dx;
}
cury += dy;
}
gos_PopCurrentHeap ();
UpdateNodes (callback,90);
KillGrid ();
}
bool CRailWorkGrid::BuildingAt (const Stuff::Point3D& pt)
{
float cx,cy;
int ix,iy;
cx = pt.x;
cy = pt.z;
cx /= 10.0f;
cy /= 10.0f;
ix = (int) cx;
iy = (int) cy;
return m_Grid[ix][iy].objectid != -1;
}
Stuff::Scalar CRailWorkGrid::Slope (int ix,int iy)
{
Stuff::Scalar toret;
toret = m_Grid[ix][iy].normal.y; // since straight up line is 0,1,0 and length 1
return (toret);
}
Stuff::Scalar CRailWorkGrid::Slope (const Stuff::Point3D& loc)
{
float cx,cy;
int ix,iy;
Stuff::Scalar toret;
cx = loc.x;
cy = loc.z;
cx /= 10.0f;
cy /= 10.0f;
ix = (int) cx;
iy = (int) cy;
toret = m_Grid[ix][iy].normal.y; // since straight up line is 0,1,0 and length 1
return (toret);
}
void MW4AI::FillCircle (stlport::vector<gridpoint>& points,Stuff::Point3D center,Stuff::Scalar radcomp)
{
float cx,cy;
float curx,cury,maxx,maxy;
gos_PushCurrentHeap (g_RailHeap);
cx = center.x/10.0f;
cy = center.z/10.0f;
maxx = radcomp/10.0f;
maxy = radcomp/10.0f;
radcomp /=10.0f;
radcomp *= radcomp;
for (curx = 0;curx<=maxx;curx++)
{
for (cury = 0;cury<=maxy;cury++)
{
if (((curx*curx) + (cury*cury)) <= radcomp)
{
points.push_back (gridpoint((cx-curx),(cy-cury)));
points.push_back (gridpoint((cx-curx),(cy+cury)));
points.push_back (gridpoint((cx+curx),(cy-cury)));
points.push_back (gridpoint((cx+curx),(cy+cury)));
}
}
}
gos_PopCurrentHeap ();
}
Stuff::Scalar CRailWorkGrid::CalcRadius (const Stuff::Point3D& center, Stuff::Scalar maxrad)
{
float radcomp;
float currad;
int cellcount,filledcount;
bool flag;
bool bridgeflag;
// int minx,miny,maxx,maxy;
int offx = (int) MinX/BLOCK_GRID_RES;
int offz = (int) MinZ/BLOCK_GRID_RES;
gos_PushCurrentHeap (g_RailHeap);
stlport::vector<gridpoint> points;
stlport::map<int,bool> objects;
stlport::stack<gridpoint> fillstack;
if (maxrad > 500.0f)
maxrad = 500.0f;
for (currad = maxrad;currad >= 10;currad-=5)
{
cellcount = filledcount = 0;
radcomp = currad;
points.clear ();
objects.clear ();
// FillCircle (points,center,radcomp,minx,miny,maxx,maxy);
FillCircle (points,center,radcomp);
int x,y;
for (x=0;x<2048;x++)
{
for (y=0;y<2048;y++)
{
workarray[x][y] = true;
}
}
stlport::vector<gridpoint>::iterator iter;
iter = points.begin ();
while (iter != points.end ())
{
workarray[iter->x-offx][iter->y-offz] = false;
iter++;
}
bridgeflag = false;
iter = points.begin ();
while (iter != points.end ())
{
cellcount++;
int obj;
// if (m_Grid[iter->x-offx][iter->y-offz].bridge != -1)
// bridgeflag = true;
obj = m_Grid[iter->x-offx][iter->y-offz].objectid;
if (obj != -1)
{
objects[obj] = true;
filledcount++;
workarray[iter->x-offx][iter->y-offz] = true;
}
else if (Slope (iter->x-offx,iter->y-offz) < BADSLOPE)
{
filledcount++;
workarray[iter->x-offx][iter->y-offz] = true;
}
iter++;
}
if (bridgeflag)
continue;
flag = false;
float t;
float step;
step = 2.0f*(currad/10.0f)*Pi;
step = 1.0f/step;
step /= 1.5f;
for (t=0;t<1.0f;t+=step)
{
float x,y;
x = currad * (float) cos (2.0f*Pi*t);
y = currad * (float) sin (2.0f*Pi*t);
x += center.x;
y += center.z;
x /= 10.0f;
y /= 10.0f;
Verify (x>=(MinX/10));
Verify (y>=(MinZ/10));
Verify (x<(float) m_Grid.size ());
Verify (y<(float) m_Grid[(unsigned int) (x-offx)].size ());
// if (m_Grid[(unsigned int) (x-offx)][(unsigned int) (y-offz)].bridge>=0)
// flag = true;
// if (m_Grid[(unsigned int) x][(unsigned int) y].objectid>=0)
// flag = true;
if (Slope ((int) x-offx,(int) y-offz) < BADSLOPE)
flag = true;
if (flag)
break;
}
if (flag)
{
continue;
}
while (!fillstack.empty ())
fillstack.pop ();
fillstack.push(gridpoint (center.x/10,center.z/10));
while (!fillstack.empty ())
{
gridpoint t = fillstack.top ();
fillstack.pop ();
if (workarray[t.x-offx][t.y-offz])
continue;
workarray[t.x-offx][t.y-offz] = true;
if (t.x-1>=MinX/10)
fillstack.push (gridpoint (t.x-1,t.y));
if (t.y-1>=MinZ/10)
fillstack.push (gridpoint (t.x,t.y-1));
if (t.x+1<(MaxX/10))
fillstack.push (gridpoint (t.x+1,t.y));
if (t.y+1<(MaxZ/10))
fillstack.push (gridpoint (t.x,t.y+1));
}
while (!fillstack.empty ())
fillstack.pop ();
iter = points.begin ();
while (iter != points.end ())
{
if (!workarray[iter->x-offx][iter->y-offz])
flag = true;
iter++;
}
float ratio;
ratio = (float) filledcount / (float) cellcount;
if ((ratio <= 0.5f) && !flag)
break;
}
gos_PopCurrentHeap ();
return currad;
}
float CRailWorkGrid::CheckSquare (int cx,int cy,int movetype)
{
int sqrindex[8][2] = {
{-1,-1},
{0,-1},
{1,-1},
{-1,0},
{1,0},
{-1,1},
{0,1},
{1,1}
};
int i;
for (i=0;i<8;i++)
{
int ix,iy;
ix = cx+sqrindex[i][0];
iy = cy+sqrindex[i][1];
if (MaterialMode (ix,iy,movetype) == FLT_MAX)
return -1.0f;
if (m_Grid[ix][iy].objectid != -1)
{
switch (movetype)
{
case JUMPINDEX:
break;
case TRACKINDEX:
case WHEELINDEX:
case LEGINDEX:
case HOVERINDEX:
case WATERINDEX:
if (m_Grid[ix][iy].objectheight > 0)
return -1.0f;
break;
case HELIINDEX:
case FLYINDEX:
if (m_Grid[ix][iy].objectheight > 50.0)
return -1.0f;
break;
case BRIDGEINDEX:
break;
default:
Verify (false);
break;
}
}
}
return 0;
}
Stuff::Scalar CRailWorkGrid::CalcWeight (Stuff::Point3D src, Stuff::Point3D dest,int movetype)
{
Stuff::Point3D extra;
Stuff::Scalar sx,sy,dx,dy;
int ix,iy,ex,ey;
Stuff::Scalar curweight,tempweight;
Stuff::Scalar lastheight,curheight,dh;
int dir;
int count,mask;
if (movetype == FLYINDEX)
return -1.0f;
if (movetype == HELIINDEX)
return -1.0f;
int offx = (int) MinX;
int offz = (int) MinZ;
src.x -= offx;
src.z -= offz;
dest.x -= offx;
dest.z -= offz;
dx = (float) dest.x - src.x;
dy = (float) dest.z - src.z;
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;
if (dx == 1.0f)
{
if (dy < -0.25f)
dir = 1;
else if (dy > 0.25f)
dir = 3;
else
dir = 2;
}
else
{
if (dy < -0.25f)
dir = 7;
else if (dy > 0.25f)
dir = 5;
else
dir = 6;
}
}
else
{
dx = dx / sy;
count = (int) (dy<0.0 ? dy*-1.0f : dy);
dy = dy<0 ? -1.0f : 1.0f;
if (dy == 1.0f)
{
if (dx < -0.25f)
dir = 5;
else if (dx > 0.25f)
dir = 3;
else
dir = 4;
}
else
{
if (dx < -0.25f)
dir = 7;
else if (dx > 0.25f)
dir = 1;
else
dir = 0;
}
}
extra.Subtract (dest,src);
dest.x /= 10.0f;
dest.z /= 10.0f;
src.x /= 10.0f;
src.z /= 10.0f;
Verify (dest.x >= 0);
Verify (dest.z >= 0);
Verify (src.x >= 0);
Verify (src.z >= 0);
dx = dest.x - src.x;
dy = dest.z - src.z;
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;
}
mask = BLOCKED_FLAGS;
switch (movetype)
{
case JUMPINDEX:
mask = JUMPPASS_FLAG;
break;
case TRACKINDEX:
mask = TRACKPASS_FLAG;
break;
case WHEELINDEX:
mask = WHEELPASS_FLAG;
break;
case LEGINDEX:
mask = LEGPASS_FLAG;
break;
case HOVERINDEX:
mask = HOVERPASS_FLAG;
break;
case WATERINDEX:
mask = WATERPASS_FLAG;
break;
}
sx = src.x;
sy = src.z;
ex = (int) dest.x;
ey = (int) dest.z;
ix = (int) sx;
iy = (int) sy;
lastheight = m_Grid[ix][iy].height;
curweight = 0;
while (count)
{
count--;
sx += dx;
sy += dy;
ix = (int) sx;
iy = (int) sy;
Verify (ix >= 0);
Verify (iy >= 0);
if (!g_MissionGraph->MoveTo (ix+(offx/BLOCK_GRID_RES),iy+(offz/BLOCK_GRID_RES),dir,mask))
return -1.0f;
// if (m_Grid[ix][iy].bridge != -1)
// return -1.0f;
if (m_Grid[ix][iy].objectid != -1)
{
switch (movetype)
{
case JUMPINDEX:
if (m_Grid[ix][iy].objectheight > 12.0)
return -1.0f;
break;
case BRIDGEINDEX:
break;
case TRACKINDEX:
case WHEELINDEX:
case LEGINDEX:
case HOVERINDEX:
if (m_Grid[ix][iy].objectheight > 0)
return -1.0f;
break;
case HELIINDEX:
case FLYINDEX:
if (m_Grid[ix][iy].objectheight > 50.0)
return -1.0f;
break;
case WATERINDEX:
if (m_Grid[ix][iy].objectheight > 0)
return -1.0f;
break;
default:
Verify (false);
break;
}
}
if (movetype != JUMPINDEX)
{
curheight = m_Grid[ix][iy].height;
dh = lastheight - curheight;
dh = dh < 0 ? dh*-1.0f : dh;
dh /= 10.0f;
curweight += (1.0f + dh);
}
tempweight = MaterialMode (ix,iy,movetype);
if (tempweight == FLT_MAX)
{
return -1.0f;
}
if (CheckSquare (ix,iy,movetype) == -1)
return -1.0f;
curweight += tempweight;
}
if (movetype == JUMPINDEX)
curweight *= 1.25f;
return curweight*10.0f;
}
Stuff::Scalar CRailWorkGrid::MaterialMode (int ix,int iy,int movetype)
{
BYTE mat;
UserConstants *data;
data = UserConstants::Instance ();
Check_Pointer (data);
Verify (ix >= 0);
Verify (iy >= 0);
mat = m_Grid[ix][iy].material;
if (movetype == WATERINDEX)
{
switch (mat)
{
case FakeShallowWaterMaterial:
return FLT_MAX;
case FakeMidWaterMaterial:
return 0.25;
case FakeOceanicWaterMaterial:
return 0;
default:
return FLT_MAX;
}
}
if (movetype == JUMPINDEX)
return 0;
if ((movetype == FLYINDEX) || (movetype == HELIINDEX))
return 0;
if (movetype == BRIDGEINDEX)
return 0;
Verify ((movetype == TRACKINDEX) || (movetype == WHEELINDEX) || (movetype == LEGINDEX) || (movetype == HOVERINDEX));
switch (mat)
{
case WaterMaterial:
gosREPORT (false,"ran into a water material");
return 0;
case NoMaterial:
case GreyDirtMaterial:
case BrownDirtMaterial:
case DarkGreyDirtMaterial:
case DarkBrownDirtMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_dirt_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_dirt_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_dirt_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_dirt_cost);
}
// MSL 5.03 Lava
case CrackedLavaMaterial:
switch (movetype)
{
case TRACKINDEX:
return FLT_MAX;
case WHEELINDEX:
return FLT_MAX;
case LEGINDEX:
return data->Get (UserConstants::leg_crackedlava_cost);
case HOVERINDEX:
return FLT_MAX;
}
break;
case OpenLavaMaterial:
switch (movetype)
{
case TRACKINDEX:
return FLT_MAX;
case WHEELINDEX:
return FLT_MAX;
case LEGINDEX:
return data->Get (UserConstants::leg_openlava_cost);
case HOVERINDEX:
return FLT_MAX;
}
break;
case AshMaterial:
case LightMineralMaterial:
case DarkMineralMaterial:
case DarkRockMaterial:
case LavaMaterial:
case RockMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_rock_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_rock_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_rock_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_rock_cost);
}
case SteelMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_steel_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_steel_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_steel_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_steel_cost);
}
case BlacktopMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_blacktop_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_blacktop_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_blacktop_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_blacktop_cost);
}
case GlassMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_glass_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_glass_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_glass_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_glass_cost);
}
case GrassMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_grass_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_grass_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_grass_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_grass_cost);
}
case WoodMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_wood_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_wood_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_wood_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_wood_cost);
}
case DarkConcreteMaterial:
case ConcreteMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_concrete_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_concrete_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_concrete_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_concrete_cost);
}
case SnowMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_snow_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_snow_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_snow_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_snow_cost);
}
case FakeShallowWaterMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_shallowwater_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_shallowwater_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_shallowwater_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_shallowwater_cost);
}
break;
case FakeMidWaterMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_midwater_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_midwater_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_midwater_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_midwater_cost);
}
case FakeOceanicWaterMaterial:
switch (movetype)
{
case TRACKINDEX:
return data->Get (UserConstants::track_oceanicwater_cost);
case WHEELINDEX:
return data->Get (UserConstants::wheel_oceanicwater_cost);
case LEGINDEX:
return data->Get (UserConstants::leg_oceanicwater_cost);
case HOVERINDEX:
return data->Get (UserConstants::hover_oceanicwater_cost);
}
default:
#if defined(LAB_ONLY)
PAUSE (("ran into an unknown material type"));
#endif
return 0;
break;
}
return 0;
}
CMoveGrid::CMoveGrid (void)
{
m_Data = NULL;
m_MacroData = NULL;
m_Width = 0;
m_Height = 0;
m_AllocWidth = 0;
m_AllocHeight = 0;
}
CMoveGrid::CMoveGrid (Stuff::MemoryStream *stream)
{
DWORD datasize;
m_Data = NULL;
m_MacroData = NULL;
m_AllocWidth = 0;
m_AllocHeight = 0;
*stream >> m_Width;
*stream >> m_Height;
*stream >> datasize;
if ((m_Width == 0) && (m_Height == 0) && (datasize == 0))
STOP (("No Move grid created for this map, must exit now"));
// Verify (m_Width == MaxX);
// Verify (m_Height == MaxZ);
Construct (m_Width,m_Height);
Verify (datasize == (512*512*2));
stream->ReadBytes (m_Data,(512*512*2));
#if 0
int i,size,chunksize;
size = m_Height / 10;
chunksize = m_Width /10;
chunksize <<= 1;
for (i=0;i<size;i++)
{
stream->ReadBytes (m_Data[i],chunksize);
datasize -= chunksize;
}
#endif
{
int i,j;
int left,right,top,bottom;
left = (int) (MinX / BLOCK_GRID_RES);
top = (int) (MinZ / BLOCK_GRID_RES);
right = (int) (MaxX / BLOCK_GRID_RES);
bottom = (int) (MaxZ / BLOCK_GRID_RES);
for (i=left;i<(left+5);i++)
for (j=top;j<bottom;j++)
PassableLocal (i,j,BLOCKED_FLAGS);
for (i=(right-5);i<right;i++)
for (j=top;j<bottom;j++)
PassableLocal (i,j,BLOCKED_FLAGS);
for (i=left;i<right;i++)
for (j=top;j<(top+5);j++)
PassableLocal (i,j,BLOCKED_FLAGS);
for (i=left;i<right;i++)
for (j=(bottom-5);j<bottom;j++)
PassableLocal (i,j,BLOCKED_FLAGS);
}
CreateMacroData ();
}
void CMoveGrid::CreateMacroData (void)
{
int width,height;
int i,j;
width = m_Width;
height = m_Height;
width /= MACROBLOCK_GRID_RES;
height /= MACROBLOCK_GRID_RES;
m_MacroAllocWidth = width;
m_MacroAllocHeight = height;
gos_PushCurrentHeap(g_RailHeap);
m_MacroData = new unsigned char *[height];
for (i=0;i<height;i++)
{
m_MacroData[i] = new unsigned char[width];
}
gos_PopCurrentHeap ();
for (i=0;i<width;i++)
{
for (j=0;j<height;j++)
{
m_MacroData[j][i] = 0;
}
}
unsigned short mask;
for (i=0;i<m_AllocWidth;i++)
{
for (j=0;j<m_AllocHeight;j++)
{
mask = m_Data[(j*m_AllocWidth)+i];
if ((mask & BLOCKED_FLAGS) == BLOCKED_FLAGS)
{
m_MacroData[j>>3][i>>3] += 1;
}
}
}
}
void CMoveGrid::DeleteMacroData (void)
{
int i,width,height;
width = m_Width;
height = m_Height;
width /= MACROBLOCK_GRID_RES;
height /= MACROBLOCK_GRID_RES;
if (m_MacroData != NULL)
{
for (i=0;i<height;i++)
{
delete[] m_MacroData[i];
}
delete[] m_MacroData;
m_MacroData = NULL;
}
}
void CMoveGrid::SaveData (const char *filename)
{
int i,size,chunksize;
int temp;
unsigned char *data;
Stuff::FileStream stream(filename,Stuff::FileStream::WriteOnly);
temp = m_Width;
temp *= -1;
stream << temp;
temp = m_Height;
temp *= -1;
stream << temp;
size = m_Height / 10;
chunksize = m_Width /10;
chunksize <<= 1;
data = (unsigned char *) &(m_Data[0]);
stream << (DWORD) (chunksize * size);
for (i=0;i<size;i++)
{
stream.WriteBytes (data,chunksize);
data += chunksize;
}
}
bool CMoveGrid::ConstructStream (Stuff::MemoryStream *stream,const char *filename)
{
DWORD *file;
DWORD filesize;
DWORD *data;
unsigned char *dataptr;
int twidth,theight;
if (filename)
{
gos_GetFile (filename,(unsigned char **) &file,&filesize);
data = file;
twidth = *((int*) data);
if (twidth > 0)
{
char str[255];
sprintf (str,"need to recreate lattice for %s, very old data",filename);
STOP ((str));
}
data++;
theight = *((int*) data);
if (theight > 0)
{
char str[255];
sprintf (str,"need to recreate lattice for %s, very old data",filename);
STOP ((str));
}
// *stream << (-1*twidth); // width negative for new style
// *stream << (-1*theight); // height negative for 2 byte format
*stream << (5120); // width negative for new style
*stream << (5120); // height negative for 2 byte format
data++;
filesize -= (sizeof (DWORD) * 3);
// *stream << filesize;
*stream << (512*512*2);
data++;
int deltax=0,deltay=0;
switch (twidth)
{
case -1280:
deltax = 192;
break;
case -2560:
deltax = 128;
break;
case -3840:
deltax = 64;
break;
case -5120:
deltax = 0;
break;
default:
return false;
// STOP (("Unsupported map width in cmovegrid::constructstream"));
break;
}
switch (theight)
{
case -1280:
deltay = 192;
break;
case -2560:
deltay = 128;
break;
case -3840:
deltay = 64;
break;
case -5120:
deltay = 0;
break;
default:
return false;
// STOP (("Unsupported map height in cmovegrid::constructstream"));
break;
}
if (!filesize)
STOP (("no data in cmovegrid::constructstream"));
int x,y,linesize;
int byteswritten=0;
unsigned short blankline[512];
linesize = twidth/-10;
dataptr = (unsigned char *) data;
stream->AllocateBytes (512*512*2);
for (x=0;x<512;x++)
{
blankline[x] = BLOCKED_FLAGS;
}
for (y=0;y<deltay;y++)
{
stream->WriteBytes(blankline,512*2);
}
for (y=deltay;y<(512-deltay);y++)
{
// for (x=0;x<deltax;x++)
{
if (deltax != 0)
stream->WriteBytes (blankline,deltax*2);
}
// for (x=deltax;x<(512-deltax);x++)
{
stream->WriteBytes (dataptr,linesize*2);
dataptr += linesize*2;
byteswritten += linesize*2;
}
// for (x=(512-deltax);x<512;x++)
{
if (deltax != 0)
stream->WriteBytes (blankline,deltax*2);
}
}
for (y=(512-deltay);y<512;y++)
{
stream->WriteBytes(blankline,512*2);
}
// stream->WriteBytes (dataptr =,filesize);
gos_Free (file);
}
else
{
// PAUSE (("constructing passability map for unknown map, defaulting to impassable"));
int x,y;
unsigned short blankline[512];
stream->AllocateBytes (512*512*2);
for (x=0;x<512;x++)
{
blankline[x] = BLOCKED_FLAGS;
}
*stream << (5120); // width negative for new style
*stream << (5120); // height negative for 2 byte format
*stream << (512*512*2);
for (y=0;y<512;y++)
{
stream->WriteBytes(blankline,512*2);
}
return false;
}
return true;
}
void CMoveGrid::Clear (void)
{
int i,j;
for (i=0;i<m_AllocHeight;i++)
for (j=0;j<m_AllocWidth;j++)
m_Data [(i*m_AllocWidth)+j] = BLOCKED_FLAGS;
}
CAirMoveGrid::CAirMoveGrid (void)
{
m_Data = NULL;
m_Width = 0;
m_Height = 0;
m_AllocWidth = 0;
m_AllocHeight = 0;
}
CAirMoveGrid::CAirMoveGrid (Stuff::MemoryStream *stream)
{
int i,size,chunksize;
DWORD datasize;
m_Data = NULL;
m_AllocWidth = 0;
m_AllocHeight = 0;
*stream >> m_Width;
*stream >> m_Height;
*stream >> datasize;
if ((m_Width == 0) && (m_Height == 0) && (datasize == 0))
return;
Verify (m_Width == MaxX-MinX);
Verify (m_Height == MaxZ-MinZ);
Construct (m_Width,m_Height);
size = m_Height / AIR_BLOCK_GRID_RES;
chunksize = m_Width / AIR_BLOCK_GRID_RES;
for (i=0;i<size;i++)
{
stream->ReadBytes (m_Data[i],chunksize);
datasize -= chunksize;
}
// Verify (datasize == 0);
}
void CAirMoveGrid::SaveData (const char *filename)
{
int i,size,chunksize;
int temp;
Stuff::FileStream stream(filename,Stuff::FileStream::WriteOnly);
temp = m_Width;
stream << temp;
temp = m_Height;
stream << temp;
size = m_Height / AIR_BLOCK_GRID_RES;
chunksize = m_Width /AIR_BLOCK_GRID_RES;
stream << (DWORD) (chunksize * size);
for (i=0;i<size;i++)
{
stream.WriteBytes (m_Data[i],chunksize);
}
}
void CAirMoveGrid::ConstructStream (Stuff::MemoryStream *stream,const char *filename)
{
DWORD *file;
DWORD filesize;
DWORD *data;
int twidth,theight;
if (filename)
{
gos_GetFile (filename,(unsigned char **) &file,&filesize);
data = file;
twidth = *((int*) data);
data++;
theight = *((int*) data);
*stream << twidth; // width
*stream << theight; // height
data++;
filesize -= (sizeof (DWORD) * 3);
*stream << filesize;
data++;
if (filesize)
stream->WriteBytes (data,filesize);
gos_Free (file);
}
else
{
*stream << (DWORD) 0; // for width
*stream << (DWORD) 0; // for height
*stream << (DWORD) 0; // for datasize
}
}
void CAirMoveGrid::Clear (void)
{
int i,j;
for (i=0;i<m_AllocHeight;i++)
for (j=0;j<m_AllocWidth;j++)
m_Data [i][j] = 0;
}
void CRailGraph::AnalyzePaths (void)
{
int size;
NameTable *table = NameTable::GetInstance();
char text[255];
int index,j;
Check_Object (table);
{
size = table->nameTableArray[NameTable::PathArray].GetLength ();
for (j=0;j<size;j++)
{
NameTableEntry *data;
Entity *who;
Path *path;
data = &table->nameTableArray [NameTable::PathArray][j];
who = data->dataPointer->GetCurrent ();
if (!who)
continue;
Verify (who->IsDerivedFrom (Path::DefaultData));
path = (Path *) who;
stlport::vector<Stuff::Point3D>::iterator iter;
for (index=0,iter = path->pathPoints.begin ();iter != path->pathPoints.end ();iter++,index++)
{
int x,y;
x = (int) iter->x;
y = (int) iter->z;
x /= BLOCK_GRID_RES;
y /= BLOCK_GRID_RES;
if ((m_MoveGrid->PassableLocal (x,y) & BLOCKED_FLAGS) != BLOCKED_FLAGS)
continue;
{
sprintf (text,"Path %s, index %d is invalid. Do you wish to remove this point?",(char *) data->objectName,index);
if (MessageBox (NULL,text,"Path error",MB_YESNO) == IDYES)
{
iter = path->pathPoints.erase (iter);
iter--;
}
}
}
}
}
}