REDRIVER2/src_rebuild/Game/C/objcoll.c

1024 lines
25 KiB
C
Raw Normal View History

#include "driver2.h"
#include "objcoll.h"
#include "cars.h"
#include "camera.h"
#include "bcollide.h"
#include "event.h"
#include "map.h"
#include "draw.h"
#include "handling.h"
#include "models.h"
#include "pedest.h"
#include "spool.h"
#include "cell.h"
#include "players.h"
#include "main.h"
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
// [D] [T]
char CellEmpty(VECTOR *pPosition, int radius)
{
PACKED_CELL_OBJECT* ppco;
CELL_OBJECT tempCO;
MODEL* pModel;
int num_cb;
int box_loop;
int sphere_sq;
int xd, zd;
int sn, cs;
int xs, zs;
int ypos;
COLLISION_PACKET* collide;
int cell_x, cell_z;
int type;
2021-04-25 18:05:28 +02:00
#if 0
CELL_ITERATOR& ci = *(CELL_ITERATOR*)((u_char*)getScratchAddr(0) + 1024 - sizeof(CELL_ITERATOR));
2021-04-25 18:05:28 +02:00
#else
CELL_ITERATOR ci;
2021-04-25 18:05:28 +02:00
#endif
cell_x = (pPosition->vx + units_across_halved) / MAP_CELL_SIZE;
cell_z = (pPosition->vz + units_down_halved) / MAP_CELL_SIZE;
ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0);
while(ppco)
{
type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
pModel = modelpointers[type];
if ((uint)pModel->collision_block > 0 &&
2021-05-09 20:56:18 +02:00
(pModel->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0)
{
QuickUnpackCellObject(ppco, &ci.nearCell, &tempCO);
2020-10-17 12:48:32 +02:00
num_cb = *(int*)pModel->collision_block;
xd = (tempCO.pos.vx - pPosition->vx);
zd = (tempCO.pos.vz - pPosition->vz);
sphere_sq = pModel->bounding_sphere + 580;
sphere_sq = (sphere_sq * sphere_sq);
2020-10-17 12:48:32 +02:00
collide = (COLLISION_PACKET*)(pModel->collision_block + sizeof(int));
if (xd * xd + zd * zd < sphere_sq)
{
box_loop = 0;
while (box_loop < num_cb)
{
2020-10-17 12:48:32 +02:00
// [A] ORIGINAL
/*
zs = collide->zsize * 0x800 + radius * 0x1000;
xs = collide->xsize * 0x800 + radius * 0x1000;
theta = (tempCO.yang + collide->yang) * 64;
ypos = pPosition->vy + (tempCO.pos.vy + collide->ypos) + 80;
cs = RCOS(theta);
sn = RSIN(theta);
*/
2020-10-17 12:48:32 +02:00
// [A] NEW
int xxd, zzd;
int yang;
int theta;
MATRIX2* mat;
yang = -tempCO.yang & 0x3f;
theta = (tempCO.yang + collide->yang) * 64;
mat = &matrixtable[yang];
cs = RCOS(theta);
sn = RSIN(theta);
xxd = FIXEDH(collide->xpos * mat->m[0][0] + collide->zpos * mat->m[2][0]);
zzd = FIXEDH(collide->xpos * mat->m[0][2] + collide->zpos * mat->m[2][2]);
xd = (tempCO.pos.vx - pPosition->vx) + xxd;
zd = (tempCO.pos.vz - pPosition->vz) + zzd;
2020-10-22 22:22:38 +02:00
zs = ((collide->zsize + 10) * 2048 + radius * 4096);
xs = ((collide->xsize + 10) * 2048 + radius * 4096);
ypos = pPosition->vy + (tempCO.pos.vy + collide->ypos); // [A] removed excessive height
2021-04-25 23:19:22 +02:00
#if defined(COLLISION_DEBUG) && !defined(PSX)
int result = 0;
if (collide->ysize / 2 > ABS(ypos) &&
xs * 2 > ABS(xd * cs - zd * sn) + xs &&
zs * 2 > ABS(zd * cs + xd * sn) + zs)
{
result = 1;
}
extern int gShowCollisionDebug;
if (gShowCollisionDebug == 3)
{
CDATA2D cd[1];
cd[0].x.vx = (tempCO.pos.vx + xxd);//FIXEDH(collide->xpos * mat->m[0][0] + collide->zpos * mat->m[2][0]));
cd[0].x.vz = (tempCO.pos.vz + zzd);//FIXEDH(collide->xpos * mat->m[0][2] + collide->zpos * mat->m[2][2]));
cd[0].x.vy = pPosition->vy;
cd[0].theta = theta; // (tempCO.yang + collide->yang) * 64 & 0xfff;
cd[0].length[0] = collide->zsize / 2;
cd[0].length[1] = collide->xsize / 2;
// calc axes of box
int dtheta = cd[0].theta & 0xfff;
cd[0].axis[0].vx = RSIN(dtheta);
cd[0].axis[0].vz = RCOS(dtheta);
cd[0].axis[1].vz = -RSIN(dtheta);
cd[0].axis[1].vx = RCOS(dtheta);
extern void Debug_AddLine(VECTOR & pointA, VECTOR & pointB, CVECTOR & color);
extern void Debug_AddLineOfs(VECTOR & pointA, VECTOR & pointB, VECTOR & ofs, CVECTOR & color);
CVECTOR ggcv = { 0, 250, 0 };
CVECTOR rrcv = { 250, 0, 0 };
CVECTOR yycv = { 250, 250, 0 };
// show both box axes
{
VECTOR _zero = { 0 };
VECTOR b1p = cd[0].x;
// show position to position
//Debug_AddLine(b1p1, b2p1, yycv);
VECTOR b1ax[2] = { {0} , {0} };
b1ax[0].vx = FIXEDH(cd[0].axis[0].vx * cd[0].length[0]);
b1ax[0].vz = FIXEDH(cd[0].axis[0].vz * cd[0].length[0]);
b1ax[1].vx = FIXEDH(cd[0].axis[1].vx * cd[0].length[1]);
b1ax[1].vz = FIXEDH(cd[0].axis[1].vz * cd[0].length[1]);
// show axis of body 1
Debug_AddLineOfs(_zero, b1ax[0], b1p, rrcv);
Debug_AddLineOfs(_zero, b1ax[1], b1p, yycv);
// display 2D box 1
{
int h = b1ax[0].vy;
VECTOR box_points[4] = {
{b1ax[0].vx - b1ax[1].vx, h, b1ax[0].vz - b1ax[1].vz, 0}, // front left
{b1ax[0].vx + b1ax[1].vx, h, b1ax[0].vz + b1ax[1].vz, 0}, // front right
{-b1ax[0].vx + b1ax[1].vx, h, -b1ax[0].vz + b1ax[1].vz, 0}, // back right
{-b1ax[0].vx - b1ax[1].vx, h, -b1ax[0].vz - b1ax[1].vz, 0} // back left
};
Debug_AddLineOfs(box_points[0], box_points[1], b1p, result ? rrcv : ggcv);
Debug_AddLineOfs(box_points[1], box_points[2], b1p, result ? rrcv : ggcv);
Debug_AddLineOfs(box_points[2], box_points[3], b1p, result ? rrcv : ggcv);
Debug_AddLineOfs(box_points[3], box_points[0], b1p, result ? rrcv : ggcv);
}
}
}
if (result)
return 0;
#else
if (collide->ysize / 2 > ABS(ypos) &&
xs * 2 > ABS(xd * cs - zd * sn) + xs &&
zs * 2 > ABS(zd * cs + xd * sn) + zs)
{
return 0;
}
#endif
box_loop++;
collide++;
}
}
}
ppco = GetNextPackedCop(&ci);
}
return 1;
}
2020-10-17 12:48:32 +02:00
// [D] [T]
int GlobalPositionToCellNumber(VECTOR *pPosition)
{
2021-04-29 18:09:44 +02:00
int cellX, cellZ;
int cbrX, cbrZ;
2020-10-17 12:48:32 +02:00
int cbr;
2020-10-25 15:33:02 +01:00
cellX = (pPosition->vx + units_across_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
cellZ = (pPosition->vz + units_down_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
2020-10-17 12:48:32 +02:00
cbrX = cellX / MAP_REGION_SIZE;
cbrZ = cellZ / MAP_REGION_SIZE;
2020-10-17 12:48:32 +02:00
cbr = (cbrX & 1) + (cbrZ & 1) * 2;
2021-03-09 20:01:38 +01:00
if (RoadMapRegions[cbr] != cbrX + cbrZ * regions_across)
return -1;
2020-10-25 15:33:02 +01:00
return cell_ptrs[(cellZ - cbrZ * MAP_REGION_SIZE) * MAP_REGION_SIZE + cbr * (MAP_REGION_SIZE*MAP_REGION_SIZE) + cellX - cbrX * MAP_REGION_SIZE];
}
2020-10-17 12:48:32 +02:00
// [D] [T]
char CellAtPositionEmpty(VECTOR *pPosition, int radius)
{
2020-10-17 12:48:32 +02:00
if (GlobalPositionToCellNumber(pPosition) == -1)
return 1;
2020-10-17 12:48:32 +02:00
return CellEmpty(pPosition, radius);
}
2020-10-17 12:48:32 +02:00
// [D] [T]
int RaySlabsIntersection(tRay *ray, tAABB *bbox)
{
int dir;
2020-10-17 12:48:32 +02:00
int d;
int i;
tRange inside;
tRange cabbage;
tRange scaledCabbage;
inside.lower = 0;
inside.upper = 4096;
i = 0;
do {
2020-10-17 12:48:32 +02:00
d = -1;
cabbage.lower = bbox->slab[i].lower - ray->org[i];
cabbage.upper = bbox->slab[i].upper - ray->org[i];
dir = ray->dir[i];
if (dir > -1)
2020-10-17 12:48:32 +02:00
d = (dir != 0);
2020-10-17 12:48:32 +02:00
if (d == 0)
{
if (cabbage.lower > 0)
return 0;
if (cabbage.upper < 0)
return 0;
scaledCabbage.upper = 0x3000;
scaledCabbage.lower = -0x3000;
}
2020-10-17 12:48:32 +02:00
else if (d == -1)
{
scaledCabbage.upper = (cabbage.lower * 4096) / dir;
scaledCabbage.lower = (cabbage.upper * 4096) / dir;
}
2020-10-17 12:48:32 +02:00
else if (d == 1)
{
scaledCabbage.lower = (cabbage.lower * 4096) / dir;
scaledCabbage.upper = (cabbage.upper * 4096) / dir;
}
if (inside.lower < scaledCabbage.lower)
inside.lower = scaledCabbage.lower;
if (scaledCabbage.upper < inside.upper)
inside.upper = scaledCabbage.upper;
if (inside.upper < inside.lower)
return 0;
i++;
} while(i < 3);
return 1;
}
int testRadius = 222;
2020-10-17 12:48:32 +02:00
// [D] [T]
char lineClear(VECTOR *v1, VECTOR *v2)
{
PACKED_CELL_OBJECT* ppco;
CELL_OBJECT tempCO;
2020-08-24 12:02:00 +02:00
MATRIX2* mat;
int cell_z;
int cell_x;
2020-10-17 12:48:32 +02:00
int yang;
MODEL* pModel;
2020-10-17 12:48:32 +02:00
int theta;
int dx,dz;
2020-08-24 12:02:00 +02:00
int cs;
int sn;
2020-10-17 12:48:32 +02:00
COLLISION_PACKET* collide;
VECTOR pos;
VECTOR va;
VECTOR vb;
tRay ray;
tAABB box;
int we;
2020-08-24 12:02:00 +02:00
int ocz;
int ocx;
int box_loop; // $s5
int num_cb; // $s6
int sphere_sq; // $v0
int xd; // $a0
int zd; // $v1
2021-04-25 18:05:28 +02:00
#ifdef PSX
CELL_ITERATOR& ci = *(CELL_ITERATOR*)((u_char*)getScratchAddr(0) + 1024 - sizeof(CELL_ITERATOR));
2021-04-25 18:05:28 +02:00
#else
CELL_ITERATOR ci;
#endif
2020-08-24 12:02:00 +02:00
va.vx = v1->vx;
va.vy = v1->vy;
va.vz = v1->vz;
2020-08-24 12:02:00 +02:00
vb.vx = v2->vx;
vb.vy = v2->vy;
vb.vz = v2->vz;
pos.vx = vb.vx - va.vx;
pos.vz = vb.vz - va.vz;
2020-08-24 12:02:00 +02:00
ocx = -1;
ocz = -1;
we = 0;
do {
if (we == 0)
{
cell_x = (v2->vx + units_across_halved) / MAP_CELL_SIZE;
cell_z = (v2->vz + units_down_halved) / MAP_CELL_SIZE;
}
2020-08-24 12:02:00 +02:00
else
{
cell_x = (v1->vx + units_across_halved) / MAP_CELL_SIZE;
cell_z = (v1->vz + units_down_halved) / MAP_CELL_SIZE;
}
2020-08-24 12:02:00 +02:00
if ((ocx != cell_x) || (ocz != cell_z))
{
2020-08-24 12:02:00 +02:00
ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0);
while (ppco)
{
QuickUnpackCellObject(ppco, &ci.nearCell, &tempCO);
pModel = modelpointers[tempCO.type];
2020-08-24 12:02:00 +02:00
xd = ((tempCO.pos.vx - ((va.vx + vb.vx) / 2 & 0xffffU)) * 0x10000) >> 0x10;
zd = ((tempCO.pos.vz - ((va.vz + vb.vz) / 2 & 0xffffU)) * 0x10000) >> 0x10;
2020-08-24 12:02:00 +02:00
sphere_sq = pModel->bounding_sphere + 800;
if ((uint)pModel->collision_block > 0 &&
2021-05-09 20:56:18 +02:00
(pModel->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0 &&
2020-12-11 11:20:48 +01:00
(xd*xd + zd*zd < sphere_sq*sphere_sq))
{
2020-10-17 12:48:32 +02:00
num_cb = *(int*)pModel->collision_block;
2020-08-24 12:02:00 +02:00
box_loop = 0;
2020-10-17 12:48:32 +02:00
collide = (COLLISION_PACKET*)(pModel->collision_block + sizeof(int));
2020-08-24 12:02:00 +02:00
while (box_loop < num_cb)
{
yang = -tempCO.yang & 0x3f;
theta = (tempCO.yang + collide->yang) * 64;
2020-08-24 12:02:00 +02:00
2020-10-17 12:48:32 +02:00
mat = &matrixtable[yang];
2020-08-24 12:02:00 +02:00
cs = RCOS(theta);
sn = RSIN(theta);
2020-08-24 12:02:00 +02:00
dx = va.vx - (tempCO.pos.vx + FIXEDH(collide->xpos * mat->m[0][0] + collide->zpos * mat->m[2][0]));
dz = va.vz - (tempCO.pos.vz + FIXEDH(collide->xpos * mat->m[0][2] + collide->zpos * mat->m[2][2]));
2020-08-24 12:02:00 +02:00
2020-08-24 13:37:58 +02:00
box.slab[0].upper = collide->xsize / 2 +testRadius;
2020-08-24 12:02:00 +02:00
box.slab[0].lower = -box.slab[0].upper;
2020-08-24 13:37:58 +02:00
box.slab[1].upper = collide->ysize / 2 +testRadius;
2020-08-24 12:02:00 +02:00
box.slab[1].lower = -box.slab[1].upper;
2020-08-24 13:37:58 +02:00
box.slab[2].upper = collide->zsize / 2 +testRadius;
2020-08-24 12:02:00 +02:00
box.slab[2].lower = -box.slab[2].upper;
2020-10-17 12:48:32 +02:00
ray.org[0] = FIXEDH(cs * dx - sn * dz);
ray.org[2] = FIXEDH(cs * dz + sn * dx);
ray.org[1] = (va.vy - (((-collide->ypos - tempCO.pos.vy) * 0x10000) >> 0x10)) + 80;
2020-08-24 13:36:17 +02:00
ray.dir[0] = FIXEDH(cs * pos.vx - sn * pos.vz);
ray.dir[2] = FIXEDH(cs * pos.vz + sn * pos.vx);
2020-08-24 12:02:00 +02:00
ray.dir[1] = vb.vy - va.vy;
2021-04-25 23:19:22 +02:00
#if defined(COLLISION_DEBUG) && !defined(PSX)
2020-08-24 12:02:00 +02:00
int rayResult = RaySlabsIntersection(&ray, &box);
extern int gShowCollisionDebug;
if (gShowCollisionDebug == 3)
{
2020-08-24 12:02:00 +02:00
CDATA2D cd[1];
cd[0].x.vx = (tempCO.pos.vx + FIXEDH(collide->xpos * mat->m[0][0] + collide->zpos * mat->m[2][0]));
cd[0].x.vz = (tempCO.pos.vz + FIXEDH(collide->xpos * mat->m[0][2] + collide->zpos * mat->m[2][2]));
2020-08-24 12:02:00 +02:00
cd[0].x.vy = va.vy;
cd[0].theta = (tempCO.yang + collide->yang) * 64 & 0xfff;
2020-08-24 12:02:00 +02:00
cd[0].length[0] = collide->zsize / 2;
cd[0].length[1] = collide->xsize / 2;
2020-08-24 12:02:00 +02:00
// calc axes of box
int dtheta = cd[0].theta & 0xfff;
cd[0].axis[0].vx = RSIN(dtheta);
cd[0].axis[0].vz = RCOS(dtheta);
cd[0].axis[1].vz = -RSIN(dtheta);
cd[0].axis[1].vx = RCOS(dtheta);
2020-08-24 12:02:00 +02:00
extern void Debug_AddLine(VECTOR & pointA, VECTOR & pointB, CVECTOR & color);
extern void Debug_AddLineOfs(VECTOR & pointA, VECTOR & pointB, VECTOR & ofs, CVECTOR & color);
2020-08-24 12:02:00 +02:00
CVECTOR ggcv = { 0, 250, 0 };
CVECTOR rrcv = { 250, 0, 0 };
CVECTOR yycv = { 250, 250, 0 };
2020-08-24 12:02:00 +02:00
// show both box axes
{
VECTOR _zero = { 0 };
VECTOR b1p = cd[0].x;
2020-08-24 12:02:00 +02:00
// show position to position
//Debug_AddLine(b1p1, b2p1, yycv);
2020-08-24 12:02:00 +02:00
VECTOR b1ax[2] = { {0} , {0} };
b1ax[0].vx = FIXEDH(cd[0].axis[0].vx * cd[0].length[0]);
b1ax[0].vz = FIXEDH(cd[0].axis[0].vz * cd[0].length[0]);
b1ax[1].vx = FIXEDH(cd[0].axis[1].vx * cd[0].length[1]);
b1ax[1].vz = FIXEDH(cd[0].axis[1].vz * cd[0].length[1]);
2020-08-24 12:02:00 +02:00
// show axis of body 1
Debug_AddLineOfs(_zero, b1ax[0], b1p, rrcv);
Debug_AddLineOfs(_zero, b1ax[1], b1p, yycv);
2020-08-24 12:02:00 +02:00
// display 2D box 1
{
2020-08-24 12:02:00 +02:00
int h = b1ax[0].vy;
VECTOR box_points[4] = {
{b1ax[0].vx - b1ax[1].vx, h, b1ax[0].vz - b1ax[1].vz, 0}, // front left
{b1ax[0].vx + b1ax[1].vx, h, b1ax[0].vz + b1ax[1].vz, 0}, // front right
{-b1ax[0].vx + b1ax[1].vx, h, -b1ax[0].vz + b1ax[1].vz, 0}, // back right
{-b1ax[0].vx - b1ax[1].vx, h, -b1ax[0].vz - b1ax[1].vz, 0} // back left
};
2020-08-24 13:36:17 +02:00
Debug_AddLineOfs(box_points[0], box_points[1], b1p, rayResult ? rrcv : ggcv);
Debug_AddLineOfs(box_points[1], box_points[2], b1p, rayResult ? rrcv : ggcv);
Debug_AddLineOfs(box_points[2], box_points[3], b1p, rayResult ? rrcv : ggcv);
Debug_AddLineOfs(box_points[3], box_points[0], b1p, rayResult ? rrcv : ggcv);
}
2020-08-24 12:02:00 +02:00
}
}
2020-08-24 12:02:00 +02:00
if (rayResult != 0)
return 0;
#else
2020-08-24 12:02:00 +02:00
if (RaySlabsIntersection(&ray, &box) != 0)
return 0;
#endif
2020-08-24 12:02:00 +02:00
box_loop++;
collide++;
}
}
ppco = GetNextPackedCop(&ci);
}
}
2020-08-24 12:02:00 +02:00
we++;
2020-08-24 12:02:00 +02:00
ocx = cell_x;
ocz = cell_z;
} while (we < 2);
return 1;
}
2020-10-17 12:48:32 +02:00
// [D] [T]
void CollisionCopList(XZPAIR* pos, int* count)
{
2020-04-29 09:09:20 +02:00
static XZPAIR initial;
PACKED_CELL_OBJECT* ppco;
CELL_OBJECT* cop;
2021-04-04 10:37:21 +02:00
int i, j, cnt;
2020-04-29 09:09:20 +02:00
XZPAIR cell;
XZPAIR cbr;
2020-10-17 12:48:32 +02:00
MODEL* model;
int cellLevel;
int type;
2021-04-25 18:05:28 +02:00
#if 0
CELL_ITERATOR& ci = *(CELL_ITERATOR*)((u_char*)getScratchAddr(0) + 1024 - sizeof(CELL_ITERATOR));
2021-04-25 18:05:28 +02:00
#else
CELL_ITERATOR ci;
#endif
cellLevel = events.camera ? events.draw : -1;
2020-04-29 09:09:20 +02:00
if (pos == NULL)
{
2021-04-04 10:37:21 +02:00
cnt = *count;
2020-04-29 09:09:20 +02:00
cell.x = initial.x;
2021-04-04 10:37:21 +02:00
for (i = 0; i < 2; i++)
{
cbr.x = cell.x / MAP_REGION_SIZE;
2020-04-29 09:09:20 +02:00
cell.z = initial.z;
2021-04-04 10:37:21 +02:00
for (j = 0; j < 2; j++)
{
cbr.z = cell.z / MAP_REGION_SIZE;
2021-04-04 10:37:21 +02:00
// check if we have valid region
2021-03-09 20:01:38 +01:00
if (cbr.x + cbr.z * regions_across == RoadMapRegions[(cbr.x & 1) + (cbr.z & 1) * 2])
2020-04-29 09:09:20 +02:00
{
ppco = GetFirstPackedCop(cell.x, cell.z, &ci, 1, cellLevel);
2021-04-04 10:37:21 +02:00
while (ppco)
2020-04-29 09:09:20 +02:00
{
type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10);
2020-10-17 12:48:32 +02:00
model = modelpointers[type];
if ((uint)model->collision_block > 0 &&
2021-04-04 10:37:21 +02:00
/*model->num_vertices - 3 < 300 &&
2020-10-17 12:48:32 +02:00
model->num_point_normals < 300 &&
2021-04-04 10:37:21 +02:00
model->num_polys < 300 &&*/
*(int*)model->collision_block > 0)
2020-10-17 12:48:32 +02:00
{
cop = UnpackCellObject(ppco, &ci.nearCell);
cop->pad = cnt;
2021-04-04 10:37:21 +02:00
coplist[cnt] = cop;
pcoplist[cnt] = ppco;
2021-04-04 10:37:21 +02:00
cnt++;
2020-10-17 12:48:32 +02:00
}
2020-04-29 09:09:20 +02:00
ppco = GetNextPackedCop(&ci);
}
}
2020-04-29 09:09:20 +02:00
cell.z++;
2021-04-04 10:37:21 +02:00
}
2020-04-29 09:09:20 +02:00
cell.x++;
2021-04-04 10:37:21 +02:00
}
*count = cnt;
}
2020-04-29 09:09:20 +02:00
else
{
initial.x = pos->x;
initial.z = pos->z;
ClearCopUsage();
}
}
// [D] [T]
void SetCopListCell(int x, int z)
{
XZPAIR cell;
cell.x = x;
cell.z = z;
CollisionCopList(&cell, NULL);
}
// [D] [T]
void BuildCollisionCopList(int *count)
{
CollisionCopList(NULL, count);
}
int gCameraBoxOverlap;
2020-04-28 20:00:25 +02:00
int ExBoxDamage = 0;
2020-10-17 12:48:32 +02:00
// [D] [T]
void CheckScenaryCollisions(CAR_DATA *cp)
{
2020-10-17 12:48:32 +02:00
int count;
int num_cb;
int coll_test_count;
int yang;
int minDist;
COLLISION_PACKET *collide;
CELL_OBJECT *cop;
2020-04-28 20:00:25 +02:00
VECTOR player_pos;
BUILDING_BOX bbox;
2020-10-17 12:48:32 +02:00
XZPAIR cell;
2020-04-28 20:00:25 +02:00
int mdcount;
MODEL *model;
int lbody;
int extraDist;
2020-10-17 12:48:32 +02:00
int sphereSq;
int dx, dz;
if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER || cp->ap.carCos == NULL)
2020-04-28 20:00:25 +02:00
lbody = 360;
else
2020-04-28 20:00:25 +02:00
lbody = cp->ap.carCos->colBox.vz;
D_CHECK_ERROR(cp < car_data, "Invalid car");
2020-04-28 20:00:25 +02:00
2021-04-04 10:37:21 +02:00
if (ghost_mode || cp->controlType == CONTROL_TYPE_PLAYER && playerghost)
2020-10-17 12:48:32 +02:00
return;
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
EventCollisions(cp, 0);
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
player_pos.vx = cp->hd.where.t[0];
player_pos.vz = cp->hd.where.t[2];
2020-04-28 20:00:25 +02:00
gCameraBoxOverlap = -1;
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER)
extraDist = 100;
else
extraDist = 580;
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
// [A] FIXME: replace with 'cell_header.cell_size'
2020-10-25 15:33:02 +01:00
cell.x = (player_pos.vx + units_across_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
cell.z = (player_pos.vz + units_down_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
SetCopListCell(cell.x, cell.z);
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
mdcount = 0;
Havana3DOcclusion(BuildCollisionCopList, &mdcount);
count = 0;
while (count < mdcount + event_models_active)
{
if (count < mdcount)
cop = coplist[count];
else
cop = &EventCop[count - mdcount];
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
model = modelpointers[cop->type];
num_cb = *(int*)model->collision_block; // box count
if ((uint)model->collision_block > 0 /*&&
2021-04-04 10:37:21 +02:00
model->num_vertices - 3 < 300 &&
2020-10-17 12:48:32 +02:00
model->num_point_normals < 300 &&
model->num_polys < 300*/ &&
num_cb > 0)
2020-04-28 20:00:25 +02:00
{
2020-10-17 12:48:32 +02:00
dx = cop->pos.vx - player_pos.vx;
dz = cop->pos.vz - player_pos.vz;
sphereSq = model->bounding_sphere + extraDist + cp->hd.speed;
2020-10-17 12:48:32 +02:00
if (dx * dx + dz * dz < sphereSq * sphereSq)
{
collide = (COLLISION_PACKET*)(model->collision_block + sizeof(int));
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
while(num_cb--)
{
2021-04-04 10:37:21 +02:00
yang = -cop->yang & 63;
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
// box 'rotated' by matrix
// [A] FIXME: replace add+shift by division
bbox.pos.vx = cop->pos.vx + FIXEDH(collide->xpos * matrixtable[yang].m[0][0] + collide->zpos * matrixtable[yang].m[2][0]);
bbox.pos.vy = cop->pos.vy + collide->ypos;
bbox.pos.vz = cop->pos.vz + FIXEDH(collide->xpos * matrixtable[yang].m[0][2] + collide->zpos * matrixtable[yang].m[2][2]);
2020-04-28 20:00:25 +02:00
// [A] purposely make chair box smaller for Tanner
if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER && (model->flags2 & MODEL_FLAG_CHAIR))
{
bbox.xsize = (collide->zsize >> 1) - 20;
bbox.zsize = (collide->xsize >> 1) - 20;
}
else
{
bbox.xsize = collide->zsize >> 1;
bbox.zsize = collide->xsize >> 1;
}
2020-04-28 20:00:25 +02:00
2020-10-17 12:48:32 +02:00
bbox.height = collide->ysize;
bbox.theta = (cop->yang + collide->yang) * 64 & 0xfff;
bbox.model = cop->type; // [A]
2020-10-17 12:48:32 +02:00
if (CAR_INDEX(cp) == TANNER_COLLIDER_CARID)
2020-10-17 12:48:32 +02:00
{
2021-04-04 10:37:21 +02:00
if (count >= mdcount && cop->pad != 0) // kill by Vegas train
2020-10-17 12:48:32 +02:00
{
if (CarBuildingCollision(cp, &bbox, cop, 0))
2020-04-28 20:00:25 +02:00
{
2020-10-17 12:48:32 +02:00
if (!bKillTanner)
player[0].dying = 1;
2020-08-31 13:16:03 +02:00
2020-10-17 12:48:32 +02:00
bKillTanner = 1;
}
2020-10-17 12:48:32 +02:00
}
else
{
CarBuildingCollision(cp, &bbox, cop, 0);
}
}
else if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER)
{
2021-05-09 20:56:18 +02:00
if ((model->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0 &&
2020-12-11 11:20:48 +01:00
(bbox.xsize > 100 || (bbox.zsize > 100)))
2020-10-17 12:48:32 +02:00
{
coll_test_count = 5;
bbox.xsize += 100;
bbox.zsize += 100;
2020-08-31 13:16:03 +02:00
gCameraBoxOverlap = -1;
2020-09-04 19:40:23 +02:00
2020-10-17 12:48:32 +02:00
minDist = lbody / 2;
while (coll_test_count > 0 && minDist <= gCameraDistance && CarBuildingCollision(cp, &bbox, cop, 0))
{
gCameraDistance -= gCameraBoxOverlap;
2020-10-17 07:44:17 +02:00
2020-10-17 12:48:32 +02:00
if (gCameraDistance < minDist)
gCameraDistance = minDist;
2020-08-31 13:16:03 +02:00
cp->hd.where.t[0] = car_data[0].hd.where.t[0] + FIXEDH((gCameraDistance * RSIN(cp->hd.direction)) / 2);
cp->hd.where.t[2] = car_data[0].hd.where.t[2] + FIXEDH((gCameraDistance * RCOS(cp->hd.direction)) / 2);
2020-10-17 12:48:32 +02:00
coll_test_count--;
2020-08-31 13:16:03 +02:00
}
2020-10-17 12:48:32 +02:00
}
}
else
{
if (count >= mdcount && cop->pad != 0)
{
cp->st.n.linearVelocity[2] = ExBoxDamage + cp->st.n.linearVelocity[2];
2020-08-31 13:16:03 +02:00
if (CarBuildingCollision(cp, &bbox, cop, (cop->pad == 1) ? CollisionCheckFlag_IsVegasMovingTrain : 0))
2020-10-17 12:48:32 +02:00
{
cp->ap.needsDenting = 1;
}
2020-08-31 13:16:03 +02:00
2020-10-17 12:48:32 +02:00
//cp->st.n.linearVelocity[2] -= 700000; // [A] Vegas train velocity - disabled here
}
else
{
if (CarBuildingCollision(cp, &bbox, cop, (model->flags2 & MODEL_FLAG_BARRIER) ? CollisionCheckFlag_MightBeABarrier : 0))
2020-10-17 12:48:32 +02:00
cp->ap.needsDenting = 1;
}
}
2020-10-17 12:48:32 +02:00
collide++;
}
}
}
2020-10-17 12:48:32 +02:00
count++;
}
2020-10-17 12:48:32 +02:00
EventCollisions(cp, 1);
}
2020-10-17 12:48:32 +02:00
// [D] [T]
int QuickBuildingCollisionCheck(VECTOR *pPos, int dir, int l, int w, int extra)
{
2020-10-17 12:48:32 +02:00
int count;
int num_cb;
MODEL *model;
u_int yang;
2020-10-17 12:48:32 +02:00
int sphereSq;
COLLISION_PACKET *collide;
CELL_OBJECT *cop;
2020-10-17 12:48:32 +02:00
XZPAIR cell;
VECTOR player_pos;
BUILDING_BOX bbox;
VECTOR offset;
int mdcount;
2020-10-17 12:48:32 +02:00
int dx, dz;
2021-04-25 18:05:28 +02:00
#if 0
CDATA2D* cd = (CDATA2D*)((u_char*)getScratchAddr(0) + 1024 - sizeof(CDATA2D) * 2);
2021-04-25 18:05:28 +02:00
#else
CDATA2D cd[2] = { 0 };
#endif
gCameraBoxOverlap = -1;
2020-10-17 12:48:32 +02:00
player_pos.vx = pPos->vx;
player_pos.vz = pPos->vz;
2020-10-25 15:33:02 +01:00
cell.x = (player_pos.vx + units_across_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
cell.z = (player_pos.vz + units_down_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE;
2020-10-17 12:48:32 +02:00
SetCopListCell(cell.x, cell.z);
mdcount = 0;
Havana3DOcclusion(BuildCollisionCopList, &mdcount);
2020-10-17 12:48:32 +02:00
count = 0;
while (count < mdcount + event_models_active)
{
2020-10-17 12:48:32 +02:00
if (count < mdcount)
cop = coplist[count];
else
2021-04-04 10:37:21 +02:00
cop = &EventCop[count - mdcount];
2020-10-17 12:48:32 +02:00
count++;
2020-10-17 12:48:32 +02:00
model = modelpointers[cop->type];
if ((uint)model->collision_block > 0 /*&&
2020-10-17 12:48:32 +02:00
model->num_vertices - 3 < 300 &&
model->num_point_normals < 300 &&
2021-04-04 10:37:21 +02:00
model->num_polys < 300*/)
2020-10-17 12:48:32 +02:00
{
sphereSq = model->bounding_sphere + extra;
dx = cop->pos.vx - player_pos.vx;
dz = cop->pos.vz - player_pos.vz;
if (dx * dx + dz * dz < sphereSq * sphereSq)
{
num_cb = *(int *)model->collision_block;
collide = (COLLISION_PACKET*)(model->collision_block + sizeof(int));
2020-10-17 12:48:32 +02:00
while(num_cb--)
{
2020-10-17 12:48:32 +02:00
yang = -cop->yang & 0x3f;
bbox.pos.vy = cop->pos.vy + collide->ypos;
2020-10-17 12:48:32 +02:00
if (ABS(pPos->vy + bbox.pos.vy) < collide->ysize / 2)
{
2020-10-17 12:48:32 +02:00
cd[0].theta = dir;
cd[0].length[0] = l;
cd[0].length[1] = w;
2020-10-17 12:48:32 +02:00
cd[0].x.vx = pPos->vx;
cd[0].x.vz = pPos->vz;
2020-10-17 12:48:32 +02:00
cd[0].vel.vx = 0;
cd[0].vel.vz = 0;
2020-10-17 12:48:32 +02:00
offset.vx = cop->pos.vx + FIXEDH(collide->xpos * matrixtable[yang].m[0][0] + collide->zpos * matrixtable[yang].m[2][0]);
offset.vz = cop->pos.vz + FIXEDH(collide->xpos * matrixtable[yang].m[0][2] + collide->zpos * matrixtable[yang].m[2][2]);
2020-10-17 12:48:32 +02:00
cd[1].theta = (cop->yang + collide->yang) * 64 & 0xfff;
2020-10-17 12:48:32 +02:00
cd[1].length[0] = collide->zsize / 2 + 100;
cd[1].length[1] = collide->xsize / 2 + 100;
2020-10-17 12:48:32 +02:00
cd[1].x.vx = pPos->vx + (((offset.vx - pPos->vx) << 0x10) >> 0x10);
cd[1].x.vz = pPos->vz + (((offset.vz - pPos->vz) << 0x10) >> 0x10);
2020-10-17 12:48:32 +02:00
cd[1].vel.vx = 0;
cd[1].vel.vz = 0;
cd[1].avel = 0;
int res = bcollided2d(cd);
#if defined(COLLISION_DEBUG) && !defined(PSX)
2020-10-17 12:48:32 +02:00
extern int gShowCollisionDebug;
if (gShowCollisionDebug == 1)
{
extern void Debug_AddLine(VECTOR& pointA, VECTOR& pointB, CVECTOR& color);
extern void Debug_AddLineOfs(VECTOR& pointA, VECTOR& pointB, VECTOR& ofs, CVECTOR& color);
CVECTOR bbcv = { 0, 0, 250 };
CVECTOR rrcv = { 250, 0, 0 };
CVECTOR yycv = { 250, 250, 0 };
// show both box axes
{
2020-10-17 12:48:32 +02:00
VECTOR _zero = { 0 };
VECTOR b1p = cd[0].x;
VECTOR b2p = cd[1].x;
b2p.vy = b1p.vy;
// show position to position
//Debug_AddLine(b1p1, b2p1, yycv);
VECTOR b1ax[2] = { {0} , {0} };
b1ax[0].vx = FIXEDH(cd[0].axis[0].vx * cd[0].length[0]);
b1ax[0].vz = FIXEDH(cd[0].axis[0].vz * cd[0].length[0]);
b1ax[1].vx = FIXEDH(cd[0].axis[1].vx * cd[0].length[1]);
b1ax[1].vz = FIXEDH(cd[0].axis[1].vz * cd[0].length[1]);
2020-10-17 12:48:32 +02:00
// show axis of body 1
Debug_AddLineOfs(_zero, b1ax[0], b1p, rrcv);
Debug_AddLineOfs(_zero, b1ax[1], b1p, yycv);
2020-10-17 12:48:32 +02:00
// display 2D box 1
{
2020-10-17 12:48:32 +02:00
int h = b1ax[0].vy;
VECTOR box_points[4] = {
{b1ax[0].vx - b1ax[1].vx, h, b1ax[0].vz - b1ax[1].vz, 0}, // front left
{b1ax[0].vx + b1ax[1].vx, h, b1ax[0].vz + b1ax[1].vz, 0}, // front right
{-b1ax[0].vx + b1ax[1].vx, h, -b1ax[0].vz + b1ax[1].vz, 0}, // back right
{-b1ax[0].vx - b1ax[1].vx, h, -b1ax[0].vz - b1ax[1].vz, 0} // back left
};
Debug_AddLineOfs(box_points[0], box_points[1], b1p, bbcv);
Debug_AddLineOfs(box_points[1], box_points[2], b1p, bbcv);
Debug_AddLineOfs(box_points[2], box_points[3], b1p, bbcv);
Debug_AddLineOfs(box_points[3], box_points[0], b1p, bbcv);
}
VECTOR b2ax[2] = { {0} , {0} };
b2ax[0].vx += FIXEDH(cd[1].axis[0].vx * cd[1].length[0]);
b2ax[0].vz += FIXEDH(cd[1].axis[0].vz * cd[1].length[0]);
b2ax[1].vx += FIXEDH(cd[1].axis[1].vx * cd[1].length[1]);
b2ax[1].vz += FIXEDH(cd[1].axis[1].vz * cd[1].length[1]);
// show axis of body 2
Debug_AddLineOfs(_zero, b2ax[0], b2p, rrcv);
Debug_AddLineOfs(_zero, b2ax[1], b2p, yycv);
CVECTOR& collColor = res ? rrcv : yycv;
// display 2D box 2
{
int h = b2ax[0].vy;
VECTOR box_points[4] = {
{b2ax[0].vx - b2ax[1].vx, h, b2ax[0].vz - b2ax[1].vz, 0}, // front left
{b2ax[0].vx + b2ax[1].vx, h, b2ax[0].vz + b2ax[1].vz, 0}, // front right
{-b2ax[0].vx + b2ax[1].vx, h, -b2ax[0].vz + b2ax[1].vz, 0}, // back right
{-b2ax[0].vx - b2ax[1].vx, h, -b2ax[0].vz - b2ax[1].vz, 0} // back left
};
Debug_AddLineOfs(box_points[0], box_points[1], b2p, collColor);
Debug_AddLineOfs(box_points[1], box_points[2], b2p, collColor);
Debug_AddLineOfs(box_points[2], box_points[3], b2p, collColor);
Debug_AddLineOfs(box_points[3], box_points[0], b2p, collColor);
}
}
}
2020-10-17 12:48:32 +02:00
#endif
if(res)
return 1;
}
2020-10-17 12:48:32 +02:00
collide++;
}
}
2020-10-17 12:48:32 +02:00
}
}
return 0;
}
2020-10-17 12:48:32 +02:00
// [D] [T]
void DoScenaryCollisions(void)
{
CAR_DATA *cp;
cp = &car_data[MAX_CARS - 1];
2020-04-28 20:00:25 +02:00
do {
if (cp->controlType != CONTROL_TYPE_NONE)
2020-04-22 20:18:27 +02:00
{
// civ AI and dead cop cars perform less collision detection frames
2020-10-01 15:28:19 +02:00
if (cp->controlType == CONTROL_TYPE_CIV_AI ||
cp->controlType == CONTROL_TYPE_PURSUER_AI && cp->ai.p.dying > 85)
2020-04-22 20:18:27 +02:00
{
2020-10-01 15:28:19 +02:00
if (cp->totalDamage != 0 && (cp->hd.speed > 10 || (cp->id + CameraCnt & 3) == 0))
2020-04-22 20:18:27 +02:00
{
CheckScenaryCollisions(cp);
}
}
2020-10-02 11:51:54 +02:00
else
2020-04-22 20:18:27 +02:00
{
CheckScenaryCollisions(cp);
}
}
2020-04-28 20:00:25 +02:00
cp--;
} while (cp >= car_data);
}