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.
310 lines
6.7 KiB
C++
310 lines
6.7 KiB
C++
#include "MW4Headers.hpp"
|
|
#include <stdio.h>
|
|
#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"
|
|
|
|
#pragma warning (push)
|
|
#include <vector>
|
|
#include <map>
|
|
#pragma warning (pop)
|
|
|
|
using namespace MW4AI;
|
|
using namespace MechWarrior4;
|
|
using namespace ElementRenderer;
|
|
|
|
#define BADSLOPE 0.707f
|
|
#define CELLSIZE 10
|
|
|
|
void ConvertMoveRectToZeroCenter (const char *filename,Stuff::Scalar xoffset,Stuff::Scalar zoffset)
|
|
{
|
|
if (!filename)
|
|
return;
|
|
|
|
DWORD *file;
|
|
DWORD filesize;
|
|
DWORD *data;
|
|
int numrects,i;
|
|
struct TRect
|
|
{
|
|
Scalar left,right,top,bottom;
|
|
int building;
|
|
bool vertical;
|
|
};
|
|
TRect *rects;
|
|
|
|
gos_GetFile (filename,(unsigned char **) &file,&filesize);
|
|
data = file;
|
|
numrects = *((int*) data);
|
|
data++;
|
|
rects = (TRect *) data;
|
|
|
|
Stuff::FileStream stream(filename,Stuff::FileStream::WriteOnly);
|
|
stream << numrects;
|
|
|
|
for (i=0;i<numrects;i++)
|
|
{
|
|
rects->bottom += zoffset;
|
|
rects->top += zoffset;
|
|
rects->left += xoffset;
|
|
rects->right += xoffset;
|
|
stream.WriteBytes (rects,sizeof (TRect));
|
|
rects++;
|
|
}
|
|
|
|
gos_Free (file);
|
|
}
|
|
|
|
CMoveRectList::CMoveRectList (void)
|
|
{
|
|
m_Rects.clear ();
|
|
}
|
|
|
|
CMoveRectList::CMoveRectList (Stuff::MemoryStream *stream)
|
|
{
|
|
int numrects,i;
|
|
|
|
AutoHeap local_heap (g_RailHeap);
|
|
m_Rects.clear ();
|
|
*stream >> numrects;
|
|
|
|
for (i=0;i<numrects;i++)
|
|
{
|
|
OBRect rect;
|
|
stream->ReadBytes (&rect,sizeof (OBRect));
|
|
rect.vertical = true;
|
|
m_Rects.push_back (rect);
|
|
}
|
|
}
|
|
|
|
CMoveRectList::~CMoveRectList (void)
|
|
{
|
|
}
|
|
|
|
void CMoveRectList::AddBuildingData (void)
|
|
{
|
|
// MSL 5.05 Added turretarray to list
|
|
int tablescan[] =
|
|
{
|
|
NameTable::BuildingArray,
|
|
NameTable::TurretArray,
|
|
NameTable::VehicleArray
|
|
};
|
|
int size,i,j;
|
|
NameTable *table = NameTable::GetInstance();
|
|
Check_Object (table);
|
|
AutoHeap local_heap (g_RailHeap);
|
|
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->GetHierarchicalVolume ()) && (!who->GetSolidVolume ()))
|
|
continue;
|
|
if (!who->IsDerivedFrom (Bridge::DefaultData))
|
|
continue;
|
|
if (!who->IsDerivedFrom (Cultural::DefaultData))
|
|
{
|
|
MWObject *obj;
|
|
obj = Cast_Object (MWObject *,who);
|
|
if ((obj->GetAI ()) && (tablescan[i] != NameTable::BuildingArray))
|
|
continue;
|
|
}
|
|
else
|
|
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);
|
|
Point3D loc = (Point3D) obb->localToParent;
|
|
|
|
OBRect rect (box.minX,box.minZ,box.maxX,box.maxZ,data->GetObjectID (),((box.maxX - box.minX) < (box.maxZ-box.minZ)));
|
|
m_Rects.push_back (rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMoveRectList::Create (WorkCallBack callback)
|
|
{
|
|
AddBuildingData ();
|
|
// DumpFile ();
|
|
}
|
|
|
|
void CMoveRectList::SaveFile (const char *filename)
|
|
{
|
|
|
|
Stuff::FileStream stream(filename,Stuff::FileStream::WriteOnly);
|
|
|
|
stream << m_Rects.size ();
|
|
|
|
stlport::vector<OBRect>::iterator iter;
|
|
iter = m_Rects.begin ();
|
|
while (iter != m_Rects.end ())
|
|
{
|
|
stream.WriteBytes (&(*iter),sizeof (OBRect));
|
|
iter++;
|
|
}
|
|
}
|
|
|
|
void CMoveRectList::ConstructStream (Stuff::MemoryStream *stream,const char *filename)
|
|
{
|
|
DWORD *file;
|
|
DWORD filesize;
|
|
DWORD *data;
|
|
int numrects;
|
|
|
|
if (filename)
|
|
{
|
|
gos_GetFile (filename,(unsigned char **) &file,&filesize);
|
|
data = file;
|
|
numrects = *((int*) data);
|
|
data++;
|
|
*stream << (numrects); // width negative for new style
|
|
filesize -= sizeof (int);
|
|
if (filesize)
|
|
stream->WriteBytes (data,filesize);
|
|
gos_Free (file);
|
|
}
|
|
else
|
|
{
|
|
*stream << (DWORD) 0; // for number of rects
|
|
}
|
|
}
|
|
|
|
void CMoveRectList::DumpFile (void)
|
|
{
|
|
FILE *file;
|
|
|
|
file = fopen ("f:\\fred.out","w");
|
|
|
|
stlport::vector<OBRect>::iterator iter;
|
|
iter = m_Rects.begin ();
|
|
while (iter != m_Rects.end ())
|
|
{
|
|
fprintf (file,"%d,%d %d,%d\n",iter->left,iter->top,iter->right,iter->bottom);
|
|
iter++;
|
|
}
|
|
fclose (file);
|
|
}
|
|
|
|
|
|
const OBRect *CMoveRectList::Collide (const Point3D& start,const Point3D& end) const
|
|
{
|
|
stlport::vector<OBRect>::const_iterator iter;
|
|
for (iter = m_Rects.begin ();iter != m_Rects.end ();iter++)
|
|
{
|
|
Scalar t,x,z;
|
|
|
|
if (iter->vertical)
|
|
{
|
|
if (end.z == start.z)
|
|
continue;
|
|
t = (iter->top - start.z) / (end.z - start.z);
|
|
if ((t>=0.0f) && (t<=1.0f))
|
|
{
|
|
x = start.x + ((end.x - start.x)*t);
|
|
if ((x >= iter->left) && (x <= iter->right))
|
|
return &(*iter);
|
|
}
|
|
|
|
t = (iter->bottom - start.z) / (end.z - start.z);
|
|
if ((t>=0.0f) && (t<=1.0f))
|
|
{
|
|
x = start.x + ((end.x - start.x)*t);
|
|
if ((x >= iter->left) && (x <= iter->right))
|
|
return &(*iter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (end.x == start.x)
|
|
continue;
|
|
t = (iter->left - start.x) / (end.x - start.x);
|
|
if ((t>=0.0f) && (t<=1.0f))
|
|
{
|
|
z = start.z + ((end.z - start.z)*t);
|
|
if ((z >= iter->top) && (z <= iter->bottom))
|
|
return &(*iter);
|
|
}
|
|
|
|
t = (iter->right - start.x) / (end.x - start.x);
|
|
if ((t>=0.0f) && (t<=1.0f))
|
|
{
|
|
z = start.z + ((end.z - start.z)*t);
|
|
if ((z >= iter->top) && (z <= iter->bottom))
|
|
return &(*iter);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool CMoveRectList::RectWithin (Stuff::Point3D& pt,Stuff::Scalar dist)
|
|
{
|
|
stlport::vector<OBRect>::const_iterator iter;
|
|
iter = m_Rects.begin ();
|
|
Stuff::Scalar value;
|
|
dist *= dist;
|
|
Stuff::Scalar cx,cz;
|
|
while (iter != m_Rects.end ())
|
|
{
|
|
cx = ((iter->right - iter->left)/2.0f) + iter->left;
|
|
cz = ((iter->bottom - iter->top)/2.0f) + iter->top;
|
|
value = (pt.x - cx) * (pt.x - cx);
|
|
value += ((pt.z - cz) * (pt.z - cz));
|
|
if (value < dist)
|
|
return true;
|
|
iter++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const OBRect *CMoveRectList::Inside (const Point3D& pt) const
|
|
{
|
|
stlport::vector<OBRect>::const_iterator iter;
|
|
iter = m_Rects.begin ();
|
|
while (iter != m_Rects.end ())
|
|
{
|
|
if ((pt.x >= iter->left) && (pt.x <= iter->right))
|
|
if ((pt.z >= iter->top) && (pt.z <= iter->bottom))
|
|
return &(*iter);
|
|
iter++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CMoveRectList::BridgeKilled (int id)
|
|
{
|
|
}
|