mirror of
https://github.com/OpenDriver2/REDRIVER2.git
synced 2024-11-22 10:22:48 +01:00
190 lines
4.0 KiB
C
190 lines
4.0 KiB
C
#include "driver2.h"
|
|
#include "cell.h"
|
|
#include "system.h"
|
|
#include "map.h"
|
|
#include "spool.h"
|
|
|
|
int cell_object_index = 0;
|
|
CELL_OBJECT cell_object_buffer[1024];
|
|
|
|
unsigned char cell_object_computed_values[2048];
|
|
|
|
extern u_char NumPlayers;
|
|
|
|
// [D] [T]
|
|
void ClearCopUsage(void)
|
|
{
|
|
ClearMem((char *)cell_object_computed_values, sizeof_cell_object_computed_values);
|
|
}
|
|
|
|
// [D] [T]
|
|
PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, int use_computed, int level)
|
|
{
|
|
PACKED_CELL_OBJECT *ppco;
|
|
|
|
u_int value;
|
|
u_short index;
|
|
u_short num;
|
|
int cbr;
|
|
CELL_DATA* cell;
|
|
ushort ptr;
|
|
|
|
index = (cellx / MAP_REGION_SIZE & 1) + (cellz / MAP_REGION_SIZE & 1) * 2;
|
|
|
|
#ifdef PSX
|
|
if (NumPlayers == 2)
|
|
#endif // else do this check always
|
|
{
|
|
// [A] don't draw loading region
|
|
if (loading_region[index] != -1)
|
|
return NULL;
|
|
|
|
if (RoadMapRegions[index] != (cellx / MAP_REGION_SIZE) + (cellz / MAP_REGION_SIZE) * (cells_across / MAP_REGION_SIZE))
|
|
return NULL;
|
|
}
|
|
|
|
cbr = (cellz % MAP_REGION_SIZE) * MAP_REGION_SIZE + index * (MAP_REGION_SIZE*MAP_REGION_SIZE) + (cellx % MAP_REGION_SIZE);
|
|
|
|
ptr = cell_ptrs[cbr];
|
|
|
|
if (ptr == 0xffff)
|
|
return NULL;
|
|
|
|
cell = &cells[ptr];
|
|
|
|
if (level == -1)
|
|
{
|
|
if (cell->num & 0x4000)
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Data looks like this:
|
|
|
|
45,34,773,456 - default list of cell objects
|
|
0x4000 | 100 - list 1 header - type 100
|
|
70,378,4557 - objects of list 1
|
|
0x4000 | 14 - list 2 header - type 14
|
|
8767,555,445,223 - objects of list 2
|
|
0x8000 - end of cell objects
|
|
*/
|
|
|
|
while (cell->num != (level | 0x4000)) // skip until we reach the needed list header
|
|
{
|
|
cell++;
|
|
|
|
if (cell->num & 0x8000) // end of cell objects?
|
|
return NULL;
|
|
}
|
|
cell++;
|
|
}
|
|
|
|
pci->nearCell.x = (cellx - (cells_across / 2)) * MAP_CELL_SIZE;
|
|
pci->nearCell.z = (cellz - (cells_down / 2)) * MAP_CELL_SIZE;
|
|
pci->use_computed = use_computed;
|
|
|
|
pci->pcd = cell;
|
|
|
|
num = cell->num;
|
|
ppco = &cell_objects[num & 0x3fff];
|
|
|
|
if (ppco->value == 0xffff && (ppco->pos.vy & 1))
|
|
{
|
|
ppco = GetNextPackedCop(pci);
|
|
}
|
|
else if (use_computed)
|
|
{
|
|
value = 1 << (num & 7) & 0xffff;
|
|
|
|
if (cell_object_computed_values[(num & 0x3fff) >> 3] & value) // get cached value
|
|
{
|
|
ppco = GetNextPackedCop(pci);
|
|
pci->ppco = ppco;
|
|
|
|
return ppco;
|
|
}
|
|
|
|
cell_object_computed_values[(num & 0x3fff) >> 3] |= value;
|
|
}
|
|
|
|
pci->ppco = ppco;
|
|
|
|
return ppco;
|
|
}
|
|
|
|
|
|
// [D] [T]
|
|
PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR* pci)
|
|
{
|
|
ushort num;
|
|
u_int value;
|
|
PACKED_CELL_OBJECT* ppco;
|
|
CELL_DATA* celld;
|
|
|
|
celld = pci->pcd;
|
|
|
|
do {
|
|
do {
|
|
if (celld->num & 0x8000) // end of cell objects?
|
|
return NULL;
|
|
|
|
celld++;
|
|
num = celld->num;
|
|
|
|
if (num & 0x4000) // end of list?
|
|
return NULL;
|
|
|
|
ppco = &cell_objects[num & 0x3fff];
|
|
} while (ppco->value == 0xffff && (ppco->pos.vy & 1));
|
|
|
|
if (!pci->use_computed)
|
|
break;
|
|
|
|
value = 1 << (num & 7) & 0xffff;
|
|
|
|
if ((cell_object_computed_values[(num & 0x3fff) >> 3] & value) == 0)
|
|
{
|
|
cell_object_computed_values[(num & 0x3fff) >> 3] |= value;
|
|
break;
|
|
}
|
|
|
|
} while (true);
|
|
|
|
pci->pcd = celld;
|
|
pci->ppco = ppco;
|
|
|
|
return ppco;
|
|
}
|
|
|
|
// [D] [T]
|
|
CELL_OBJECT* UnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near)
|
|
{
|
|
CELL_OBJECT* pco;
|
|
|
|
if (ppco == NULL)
|
|
return NULL;
|
|
|
|
pco = &cell_object_buffer[cell_object_index];
|
|
cell_object_index = cell_object_index + 1 & 0x3ff;
|
|
|
|
pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10);
|
|
pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10);
|
|
|
|
pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11;
|
|
pco->yang = ppco->value & 0x3f;
|
|
pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
|
|
|
|
return pco;
|
|
}
|
|
|
|
// [D] [T]
|
|
void QuickUnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near, CELL_OBJECT* pco)
|
|
{
|
|
pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10);
|
|
pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10);
|
|
|
|
pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11;
|
|
pco->yang = ppco->value & 0x3f;
|
|
pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
|
|
} |