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.
281 lines
5.3 KiB
C++
281 lines
5.3 KiB
C++
|
|
#ifndef SENSORCELLMAP_HPP
|
|
#define SENSORCELLMAP_HPP
|
|
|
|
#pragma warning(disable : 4284)
|
|
#pragma warning(push)
|
|
#include <stlport\slist>
|
|
#include <stlport\vector>
|
|
#pragma warning(pop)
|
|
|
|
|
|
class SensorCellMap
|
|
{
|
|
public:
|
|
SensorCellMap()
|
|
{
|
|
}
|
|
|
|
~SensorCellMap()
|
|
{
|
|
}
|
|
|
|
typedef stlport::slist<MechWarrior4::MWObject*> list_type;
|
|
typedef stlport::vector<int> checksum_type;
|
|
|
|
class Cell
|
|
{
|
|
public:
|
|
Cell()
|
|
: m_Checksum(0)
|
|
{
|
|
}
|
|
|
|
list_type::const_iterator begin()
|
|
{
|
|
return (entries.begin());
|
|
}
|
|
|
|
list_type::const_iterator end()
|
|
{
|
|
return (entries.end());
|
|
}
|
|
|
|
void Add(MechWarrior4::MWObject* ptr)
|
|
{
|
|
Verify(std::find(begin(),end(),ptr) == end());
|
|
|
|
entries.insert(entries.begin(),ptr);
|
|
|
|
RecalcChecksum();
|
|
}
|
|
|
|
void Remove(MechWarrior4::MWObject* ptr)
|
|
{
|
|
Verify(std::find(begin(),end(),ptr) != end());
|
|
|
|
entries.remove(ptr);
|
|
|
|
RecalcChecksum();
|
|
}
|
|
|
|
void RecalcChecksum()
|
|
{
|
|
m_Checksum = entries.size() << 24;
|
|
|
|
{for (list_type::const_iterator i = begin();
|
|
i != end();
|
|
++i)
|
|
{
|
|
m_Checksum += ((*i)->objectID & 0x00FFFFFF);
|
|
}}
|
|
}
|
|
|
|
int GetChecksum() const
|
|
{
|
|
return (m_Checksum);
|
|
}
|
|
|
|
private:
|
|
stlport::slist<MechWarrior4::MWObject*> entries;
|
|
int m_Checksum;
|
|
};
|
|
|
|
Cell& GetCell(int x, int z)
|
|
{
|
|
Verify(x >= 0);
|
|
Verify(x < WIDTH);
|
|
Verify(z >= 0);
|
|
Verify(z < HEIGHT);
|
|
|
|
return (m_Entries[x][z]);
|
|
}
|
|
|
|
void Fill(int x1, int z1,
|
|
int x2, int z2,
|
|
list_type& output,
|
|
checksum_type& checksums)
|
|
{
|
|
{for (int i_x = x1;
|
|
i_x <= x2;
|
|
++i_x)
|
|
{
|
|
{for (int i_z = z1;
|
|
i_z <= z2;
|
|
++i_z)
|
|
{
|
|
Cell& cell = GetCell(i_x,i_z);
|
|
|
|
{for (list_type::const_iterator i = cell.begin();
|
|
i != cell.end();
|
|
++i)
|
|
{
|
|
output.insert(output.begin(),*i);
|
|
}}
|
|
|
|
checksums.push_back(cell.GetChecksum());
|
|
}}
|
|
}}
|
|
}
|
|
|
|
int CellIndex(Stuff::Scalar pos)
|
|
{
|
|
Verify(CELL_WIDTH == 256);
|
|
Verify(CELL_HEIGHT == 256);
|
|
|
|
int p((int)(pos + (Scalar)COORD_ADD));
|
|
return (p >> 8);
|
|
}
|
|
|
|
void ClampIndex(int& index, int min, int max)
|
|
{
|
|
if (index < min)
|
|
{
|
|
index = min;
|
|
}
|
|
else
|
|
{
|
|
if (index > max)
|
|
{
|
|
index = max;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetCellPos(int& x, int& z, const Stuff::LinearMatrix4D& local_to_world)
|
|
{
|
|
x = CellIndex(local_to_world(W_Axis, X_Axis));
|
|
z = CellIndex(local_to_world(W_Axis, Z_Axis));
|
|
|
|
ClampIndex(x,0,WIDTH - 1);
|
|
ClampIndex(z,0,HEIGHT - 1);
|
|
}
|
|
|
|
void GetRect(int& x1, int& z1, int& x2, int& z2, const Stuff::LinearMatrix4D& local_to_world, Stuff::Scalar radius)
|
|
{
|
|
Scalar x = local_to_world(W_Axis, X_Axis);
|
|
Scalar z = local_to_world(W_Axis, Z_Axis);
|
|
|
|
Scalar _x1 = x - radius;
|
|
if (_x1 < (Stuff::Scalar)LEFT_BOUNDS)
|
|
{
|
|
_x1 = (Stuff::Scalar)LEFT_BOUNDS;
|
|
}
|
|
x1 = CellIndex(_x1);
|
|
|
|
Scalar _x2 = x + radius;
|
|
if (_x2 >= (Stuff::Scalar)RIGHT_BOUNDS)
|
|
{
|
|
_x2 = (Stuff::Scalar)RIGHT_BOUNDS;
|
|
}
|
|
x2 = CellIndex(_x2);
|
|
|
|
Scalar _z1 = z - radius;
|
|
if (_z1 < (Stuff::Scalar)TOP_BOUNDS)
|
|
{
|
|
_z1 = (Stuff::Scalar)TOP_BOUNDS;
|
|
}
|
|
z1 = CellIndex(_z1);
|
|
|
|
Scalar _z2 = z + radius;
|
|
if (_z2 >= (Stuff::Scalar)BOTTOM_BOUNDS)
|
|
{
|
|
_z2 = (Stuff::Scalar)BOTTOM_BOUNDS;
|
|
}
|
|
z2 = CellIndex(_z2);
|
|
}
|
|
|
|
void Fill(const Stuff::LinearMatrix4D& local_to_world,
|
|
Stuff::Scalar radius,
|
|
list_type& output,
|
|
checksum_type& checksums)
|
|
{
|
|
checksums.clear();
|
|
|
|
int x1, z1, x2, z2;
|
|
GetRect(x1,z1,x2,z2,local_to_world,radius);
|
|
Fill(x1,z1,x2,z2,output,checksums);
|
|
}
|
|
|
|
bool ChecksumMatches(const Stuff::LinearMatrix4D& local_to_world,
|
|
Stuff::Scalar radius,
|
|
checksum_type& checksums)
|
|
{
|
|
int x1, z1, x2, z2;
|
|
GetRect(x1,z1,x2,z2,local_to_world,radius);
|
|
|
|
if (checksums.size() != (x2 - x1 + 1) * (z2 - z1 + 1))
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
checksum_type::const_iterator i_checksum = checksums.begin();
|
|
|
|
{for (int i_x = x1;
|
|
i_x <= x2;
|
|
++i_x)
|
|
{
|
|
{for (int i_z = z1;
|
|
i_z <= z2;
|
|
++i_z)
|
|
{
|
|
// TODO: REWRITE THIS BEFORE CHECKING IN!!!
|
|
Cell& cell = GetCell(i_x,i_z);
|
|
if (cell.GetChecksum() != *(i_checksum))
|
|
{
|
|
return (false);
|
|
}
|
|
|
|
++i_checksum;
|
|
}}
|
|
}}
|
|
|
|
return (true);
|
|
}
|
|
|
|
void Add(MechWarrior4::MWObject* ptr, int x, int z)
|
|
{
|
|
Cell& cell = GetCell(x,z);
|
|
|
|
cell.Add(ptr);
|
|
}
|
|
|
|
void Add(MechWarrior4::MWObject* ptr, const Stuff::LinearMatrix4D& local_to_world)
|
|
{
|
|
int x, z;
|
|
GetCellPos(x,z,local_to_world);
|
|
Add(ptr,x,z);
|
|
}
|
|
|
|
void Remove(MechWarrior4::MWObject* ptr, int x, int z)
|
|
{
|
|
Cell& cell = GetCell(x,z);
|
|
|
|
cell.Remove(ptr);
|
|
}
|
|
|
|
void Remove(MechWarrior4::MWObject* ptr, const Stuff::LinearMatrix4D& local_to_world)
|
|
{
|
|
int x, z;
|
|
GetCellPos(x,z,local_to_world);
|
|
Remove(ptr,x,z);
|
|
}
|
|
|
|
private:
|
|
enum { CELL_WIDTH = 256 };
|
|
enum { CELL_HEIGHT = CELL_WIDTH };
|
|
enum { WIDTH = 20 };
|
|
enum { HEIGHT = 20 };
|
|
enum { COORD_ADD = 2560 };
|
|
enum { GRID_WIDTH = WIDTH * CELL_WIDTH };
|
|
enum { GRID_HEIGHT = HEIGHT * CELL_HEIGHT };
|
|
enum { LEFT_BOUNDS = -COORD_ADD + 1 };
|
|
enum { TOP_BOUNDS = -COORD_ADD + 1 };
|
|
enum { RIGHT_BOUNDS = COORD_ADD - 1 };
|
|
enum { BOTTOM_BOUNDS = COORD_ADD - 1 };
|
|
|
|
Cell m_Entries[WIDTH][HEIGHT];
|
|
};
|
|
|
|
|
|
#endif // SENSORCELLMAP_HPP
|