2020-12-21 13:16:29 -03:00
|
|
|
#include "framework.h"
|
|
|
|
#include "control.h"
|
|
|
|
#include "collide.h"
|
|
|
|
#include "draw.h"
|
|
|
|
#include "Lara.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "effect.h"
|
|
|
|
#include "sphere.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "setup.h"
|
|
|
|
#include "sound.h"
|
|
|
|
#include "trmath.h"
|
|
|
|
#include "prng.h"
|
|
|
|
using std::vector;
|
2020-10-24 01:05:59 -03:00
|
|
|
using namespace T5M::Math::Random;
|
2021-01-07 11:16:21 -03:00
|
|
|
using namespace T5M::Floordata;
|
2020-12-21 13:16:29 -03:00
|
|
|
char LM[] =
|
|
|
|
{
|
|
|
|
LM_HIPS,
|
|
|
|
LM_LTHIGH,
|
|
|
|
LM_LSHIN,
|
|
|
|
LM_LFOOT,
|
|
|
|
LM_RTHIGH,
|
|
|
|
LM_RSHIN,
|
|
|
|
LM_RFOOT,
|
|
|
|
LM_TORSO,
|
|
|
|
LM_RINARM,
|
|
|
|
LM_ROUTARM,
|
|
|
|
LM_RHAND,
|
|
|
|
LM_LINARM,
|
|
|
|
LM_LOUTARM,
|
|
|
|
LM_LHAND,
|
|
|
|
LM_HEAD,
|
|
|
|
};
|
|
|
|
|
|
|
|
int hitSoundTimer;
|
|
|
|
int XFront, ZFront;
|
|
|
|
BOUNDING_BOX GlobalCollisionBounds;
|
2021-04-29 06:26:17 +02:00
|
|
|
ITEM_INFO* CollidedItems[MAX_COLLIDED_OBJECTS];
|
|
|
|
MESH_INFO* CollidedMeshes[MAX_COLLIDED_OBJECTS];
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
int CollideStaticObjects(COLL_INFO* coll, int x, int y, int z, short roomNumber, int hite)
|
|
|
|
{
|
|
|
|
ROOM_INFO* room;
|
|
|
|
MESH_INFO* mesh;
|
|
|
|
short roomList[255];
|
|
|
|
short numRooms = 0;
|
|
|
|
int xMin = 0, xMax = 0, zMin = 0, zMax = 0;
|
|
|
|
int inXmin, inXmax, inZmin, inZmax, inYmin;
|
|
|
|
|
|
|
|
coll->hitStatic = false;
|
|
|
|
|
|
|
|
inXmin = x - coll->radius;
|
|
|
|
inXmax = x + coll->radius;
|
|
|
|
inZmin = z - coll->radius;
|
|
|
|
inZmax = z + coll->radius;
|
|
|
|
inYmin = y - hite;
|
|
|
|
|
|
|
|
// Collect all the rooms where to check
|
|
|
|
GetRoomList(roomNumber, roomList, &numRooms);
|
|
|
|
|
|
|
|
for (int i = 0; i < numRooms; i++)
|
|
|
|
{
|
|
|
|
room = &g_Level.Rooms[roomList[i]];
|
|
|
|
for (int j = 0; j < room->mesh.size(); j++, mesh++)
|
|
|
|
{
|
|
|
|
mesh = &room->mesh[j];
|
|
|
|
STATIC_INFO* sInfo = &StaticObjects[mesh->staticNumber];
|
|
|
|
|
|
|
|
if ((sInfo->flags & 1)) // No collision
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int yMin = mesh->y + sInfo->collisionBox.Y1;
|
|
|
|
int yMax = mesh->y + sInfo->collisionBox.Y2;
|
|
|
|
short yRot = mesh->yRot;
|
|
|
|
|
|
|
|
if (yRot == ANGLE(180))
|
|
|
|
{
|
|
|
|
xMin = mesh->x - sInfo->collisionBox.X2;
|
|
|
|
xMax = mesh->x - sInfo->collisionBox.X1;
|
|
|
|
zMin = mesh->z - sInfo->collisionBox.Z2;
|
|
|
|
zMax = mesh->z - sInfo->collisionBox.Z1;
|
|
|
|
}
|
|
|
|
else if (yRot == -ANGLE(90))
|
|
|
|
{
|
|
|
|
xMin = mesh->x - sInfo->collisionBox.Z2;
|
|
|
|
xMax = mesh->x - sInfo->collisionBox.Z1;
|
|
|
|
zMin = mesh->z + sInfo->collisionBox.X1;
|
|
|
|
zMax = mesh->z + sInfo->collisionBox.X2;
|
|
|
|
}
|
|
|
|
else if (yRot == ANGLE(90))
|
|
|
|
{
|
|
|
|
|
|
|
|
xMin = mesh->x + sInfo->collisionBox.Z1;
|
|
|
|
xMax = mesh->x + sInfo->collisionBox.Z2;
|
|
|
|
zMin = mesh->z - sInfo->collisionBox.X2;
|
|
|
|
zMax = mesh->z - sInfo->collisionBox.X1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xMin = mesh->x + sInfo->collisionBox.X1;
|
|
|
|
xMax = mesh->x + sInfo->collisionBox.X2;
|
|
|
|
zMin = mesh->z + sInfo->collisionBox.Z1;
|
|
|
|
zMax = mesh->z + sInfo->collisionBox.Z2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inXmax <= xMin
|
|
|
|
|| inXmin >= xMax
|
|
|
|
|| y <= yMin
|
|
|
|
|| inYmin >= yMax
|
|
|
|
|| inZmax <= zMin
|
|
|
|
|| inZmin >= zMax)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
coll->hitStatic = true;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetCollidedObjects(ITEM_INFO* collidingItem, int radius, int onlyVisible, ITEM_INFO** collidedItems, MESH_INFO** collidedMeshes, int ignoreLara)
|
|
|
|
{
|
|
|
|
ROOM_INFO* room;
|
|
|
|
short roomsArray[255];
|
|
|
|
short numRooms;
|
|
|
|
short numItems = 0, numMeshes = 0;
|
|
|
|
float c, s;
|
|
|
|
int rx, rz;
|
|
|
|
|
|
|
|
// Collect all the rooms where to check
|
|
|
|
GetRoomList(collidingItem->roomNumber, roomsArray, &numRooms);
|
|
|
|
|
|
|
|
if (collidedMeshes)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numRooms; i++)
|
|
|
|
{
|
|
|
|
room = &g_Level.Rooms[roomsArray[i]];
|
|
|
|
|
|
|
|
for (int j = 0; j < room->mesh.size(); j++)
|
|
|
|
{
|
|
|
|
MESH_INFO* mesh = &room->mesh[j];
|
|
|
|
STATIC_INFO* staticMesh = &StaticObjects[mesh->staticNumber];
|
|
|
|
|
|
|
|
if (mesh->flags & 1)
|
|
|
|
{
|
|
|
|
if (collidingItem->pos.yPos + radius + STEP_SIZE/2 >= mesh->y + staticMesh->collisionBox.Y1)
|
|
|
|
{
|
|
|
|
if (collidingItem->pos.yPos <= mesh->y + staticMesh->collisionBox.Y2)
|
|
|
|
{
|
|
|
|
s = phd_sin(mesh->yRot);
|
|
|
|
c = phd_cos(mesh->yRot);
|
|
|
|
rx = (collidingItem->pos.xPos - mesh->x) * c - s * (collidingItem->pos.zPos - mesh->z);
|
|
|
|
rz = (collidingItem->pos.zPos - mesh->z) * c + s * (collidingItem->pos.xPos - mesh->x);
|
|
|
|
|
|
|
|
if (radius + rx + STEP_SIZE/2 >= staticMesh->collisionBox.X1 && rx - radius - STEP_SIZE/2 <= staticMesh->collisionBox.X2)
|
|
|
|
{
|
|
|
|
if (radius + rz + STEP_SIZE/2 >= staticMesh->collisionBox.Z1 && rz - radius - STEP_SIZE/2 <= staticMesh->collisionBox.Z2)
|
|
|
|
{
|
|
|
|
collidedMeshes[numMeshes++] = mesh;
|
|
|
|
if (!radius)
|
|
|
|
{
|
|
|
|
collidedItems[0] = NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
collidedMeshes[numMeshes] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collidedItems)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numRooms; i++)
|
|
|
|
{
|
|
|
|
ROOM_INFO* room = &g_Level.Rooms[roomsArray[i]];
|
|
|
|
|
|
|
|
int itemNumber = room->itemNumber;
|
|
|
|
if (itemNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
2021-04-29 06:26:17 +02:00
|
|
|
if ((item == collidingItem || ignoreLara && item == LaraItem)
|
|
|
|
|| (item->flags & 0x8000)
|
|
|
|
|| (item->meshBits == 0)
|
|
|
|
|| (Objects[item->objectNumber].drawRoutine == NULL)
|
|
|
|
|| (Objects[item->objectNumber].collision == NULL && item->objectNumber != ID_LARA)
|
|
|
|
|| (onlyVisible && item->status == ITEM_INVISIBLE)
|
|
|
|
|| item->objectNumber == ID_BURNING_FLOOR)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
continue;
|
|
|
|
}
|
2021-04-29 06:26:17 +02:00
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
/*this is awful*/
|
2021-04-29 06:26:17 +02:00
|
|
|
/*if (item->objectNumber == ID_UPV && item->hitPoints == 1)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (item->objectNumber == ID_BIGGUN && item->hitPoints == 1)
|
|
|
|
{
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
continue;
|
2021-04-29 06:26:17 +02:00
|
|
|
}*/
|
2020-12-21 13:16:29 -03:00
|
|
|
/*we need a better system*/
|
|
|
|
|
|
|
|
int dx = collidingItem->pos.xPos - item->pos.xPos;
|
|
|
|
int dy = collidingItem->pos.yPos - item->pos.yPos;
|
|
|
|
int dz = collidingItem->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
ANIM_FRAME* framePtr = GetBestFrame(item);
|
|
|
|
|
2021-04-29 06:26:17 +02:00
|
|
|
if (dx >= -2048
|
2020-12-21 13:16:29 -03:00
|
|
|
&& dx <= 2048
|
|
|
|
&& dy >= -2048
|
|
|
|
&& dy <= 2048
|
|
|
|
&& dz >= -2048
|
|
|
|
&& dz <= 2048
|
|
|
|
&& collidingItem->pos.yPos + radius + 128 >= item->pos.yPos + framePtr->boundingBox.Y1
|
2021-06-07 12:03:53 -04:00
|
|
|
&& collidingItem->pos.yPos - radius - 128 <= item->pos.yPos + framePtr->boundingBox.Y2
|
|
|
|
&& collidingItem->floor >= item->pos.yPos)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
float s = phd_sin(item->pos.yRot);
|
|
|
|
float c = phd_cos(item->pos.yRot);
|
|
|
|
|
|
|
|
int rx = dx * c - s * dz;
|
|
|
|
int rz = dz * c + s * dx;
|
|
|
|
|
|
|
|
if (item->objectNumber == ID_TURN_SWITCH)
|
|
|
|
{
|
2021-04-29 06:26:17 +02:00
|
|
|
framePtr->boundingBox.X1 = -256;
|
|
|
|
framePtr->boundingBox.X2 = 256;
|
|
|
|
framePtr->boundingBox.Z1 = -256;
|
|
|
|
framePtr->boundingBox.Z1 = 256;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (radius + rx + 128 >= framePtr->boundingBox.X1 && rx - radius - 128 <= framePtr->boundingBox.X2)
|
|
|
|
{
|
|
|
|
if (radius + rz + 128 >= framePtr->boundingBox.Z1 && rz - radius - 128 <= framePtr->boundingBox.Z2)
|
|
|
|
{
|
|
|
|
collidedItems[numItems++] = item;
|
|
|
|
if (!radius)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
|
|
|
|
} while (itemNumber != NO_ITEM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
collidedItems[numItems] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (numItems || numMeshes);
|
|
|
|
}
|
|
|
|
|
|
|
|
int TestWithGlobalCollisionBounds(ITEM_INFO* item, ITEM_INFO* lara, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
ANIM_FRAME* framePtr = GetBestFrame(lara);
|
|
|
|
|
|
|
|
if (item->pos.yPos + GlobalCollisionBounds.Y2 <= lara->pos.yPos + framePtr->boundingBox.Y1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (item->pos.yPos + GlobalCollisionBounds.Y1 >= framePtr->boundingBox.Y2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
float s = phd_sin(item->pos.yRot);
|
|
|
|
float c = phd_cos(item->pos.yRot);
|
|
|
|
|
|
|
|
int dx = lara->pos.xPos - item->pos.xPos;
|
|
|
|
int dz = lara->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
int x = c * dx - s * dz;
|
|
|
|
int z = c * dz + s * dx;
|
|
|
|
|
|
|
|
if (x < GlobalCollisionBounds.X1 - coll->radius ||
|
|
|
|
x > GlobalCollisionBounds.X2 + coll->radius ||
|
|
|
|
z < GlobalCollisionBounds.Z1 - coll->radius ||
|
|
|
|
z > GlobalCollisionBounds.Z2 + coll->radius)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrapCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
|
|
|
if (item->status == ITEM_ACTIVE)
|
|
|
|
{
|
|
|
|
if (!TestBoundsCollide(item, l, c->radius))
|
|
|
|
return;
|
|
|
|
|
|
|
|
TestCollision(item, LaraItem);
|
|
|
|
}
|
|
|
|
else if (item->status != ITEM_INVISIBLE)
|
|
|
|
ObjectCollision(itemNumber, l, c);
|
|
|
|
}
|
|
|
|
|
2021-02-03 01:50:59 -03:00
|
|
|
void TestForObjectOnLedge(ITEM_INFO* item, COLL_INFO* coll)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
GAME_VECTOR s;
|
|
|
|
s.x = (i * 256) - 0x80;
|
|
|
|
s.y = -256;
|
|
|
|
s.z = 0;
|
|
|
|
|
|
|
|
GetLaraJointPosition((PHD_VECTOR*)&s, LM_HEAD);
|
|
|
|
s.roomNumber = LaraItem->roomNumber;
|
|
|
|
|
|
|
|
GAME_VECTOR d;
|
|
|
|
d.x = s.x + phd_sin(LaraItem->pos.yRot) * 768;
|
|
|
|
d.y = s.y;
|
|
|
|
d.z = s.z + phd_cos(LaraItem->pos.yRot) * 768;
|
|
|
|
|
|
|
|
LOS(&s, &d);
|
|
|
|
|
|
|
|
PHD_VECTOR v;
|
|
|
|
MESH_INFO* mesh;
|
|
|
|
|
|
|
|
// CHECK
|
|
|
|
/*if (ObjectOnLOS2(&s, &d, &v, &mesh) != 999)
|
|
|
|
{
|
|
|
|
coll->hitStatic = true;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShiftItem(ITEM_INFO* item, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
item->pos.xPos += coll->shift.x;
|
|
|
|
item->pos.yPos += coll->shift.y;
|
|
|
|
item->pos.zPos += coll->shift.z;
|
|
|
|
coll->shift.z = 0;
|
|
|
|
coll->shift.y = 0;
|
|
|
|
coll->shift.x = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateLaraRoom(ITEM_INFO* item, int height)
|
|
|
|
{
|
|
|
|
int x = item->pos.xPos;
|
|
|
|
int y = height + item->pos.yPos;
|
|
|
|
int z = item->pos.zPos;
|
2021-01-07 11:16:21 -03:00
|
|
|
item->location = GetRoom(item->location, x, y, z);
|
|
|
|
item->floor = GetFloorHeight(item->location, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (item->roomNumber != item->location.roomNumber)
|
|
|
|
ItemNewRoom(Lara.itemNumber, item->location.roomNumber);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
short GetTiltType(FLOOR_INFO* floor, int x, int y, int z)
|
|
|
|
{
|
|
|
|
ROOM_INFO* r;
|
|
|
|
short* data;
|
|
|
|
short func;
|
|
|
|
int tilt, t0, t1, t2, t3;
|
|
|
|
int dx, dz;
|
|
|
|
short xOff, yOff;
|
|
|
|
|
|
|
|
while (floor->pitRoom != NO_ROOM)
|
|
|
|
{
|
|
|
|
if (CheckNoColFloorTriangle(floor, x, z) == TRUE)
|
|
|
|
break;
|
|
|
|
r = &g_Level.Rooms[floor->pitRoom];
|
|
|
|
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((y + CLICK(2)) < (floor->floor * CLICK(1)))
|
|
|
|
return FLOOR_TYPE;
|
|
|
|
|
|
|
|
if (!floor->index)
|
|
|
|
return FLOOR_TYPE;
|
|
|
|
|
|
|
|
data = &g_Level.FloorData[floor->index];
|
|
|
|
func = *data & DATA_TYPE;
|
|
|
|
|
|
|
|
if (func == TILT_TYPE)
|
|
|
|
return data[1];
|
|
|
|
|
|
|
|
if (func != SPLIT1
|
|
|
|
&& func != SPLIT2
|
|
|
|
&& func != NOCOLF1T
|
|
|
|
&& func != NOCOLF2T
|
|
|
|
&& func != NOCOLF1B
|
|
|
|
&& func != NOCOLF2B)
|
|
|
|
{
|
|
|
|
return FLOOR_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
tilt = data[1];
|
|
|
|
t0 = tilt & DATA_TILT;
|
|
|
|
t1 = (tilt / 16) & DATA_TILT;
|
|
|
|
t2 = (tilt / 256) & DATA_TILT;
|
|
|
|
t3 = (tilt / 4096) & DATA_TILT;
|
|
|
|
dx = x & (WALL_SIZE - 1);
|
|
|
|
dz = z & (WALL_SIZE - 1);
|
|
|
|
xOff = 0;
|
|
|
|
yOff = 0;
|
|
|
|
|
|
|
|
if (func == SPLIT1 || func == NOCOLF1T || func == NOCOLF1B)
|
|
|
|
{
|
|
|
|
if (dx > (SECTOR(1) - dz))
|
|
|
|
{
|
|
|
|
xOff = t3 - t0;
|
|
|
|
yOff = t3 - t2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xOff = t2 - t1;
|
|
|
|
yOff = t0 - t1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dx > dz)
|
|
|
|
{
|
|
|
|
xOff = t3 - t0;
|
|
|
|
yOff = t0 - t1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xOff = t2 - t1;
|
|
|
|
yOff = t3 - t2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((xOff * 256) | (yOff & DATA_STATIC));
|
|
|
|
}
|
|
|
|
|
|
|
|
int FindGridShift(int x, int z)
|
|
|
|
{
|
|
|
|
if ((x / SECTOR(1)) == (z / SECTOR(1)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ((z / SECTOR(1)) <= (x / SECTOR(1)))
|
|
|
|
return (-1 - (x & (WALL_SIZE - 1)));
|
|
|
|
else
|
|
|
|
return ((WALL_SIZE + 1) - (x & (WALL_SIZE - 1)));
|
|
|
|
}
|
|
|
|
|
|
|
|
int TestBoundsCollideStatic(BOUNDING_BOX* bounds, PHD_3DPOS* pos, int radius)
|
|
|
|
{
|
|
|
|
if (!(bounds->Z2 != 0 || bounds->Z1 != 0 || bounds->X1 != 0 || bounds->X2 != 0 || bounds->Y1 != 0 || bounds->Y2 != 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ANIM_FRAME* frame = GetBestFrame(LaraItem);
|
|
|
|
if (pos->yPos + bounds->Y2 <= LaraItem->pos.yPos + frame->boundingBox.Y1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (pos->yPos + bounds->Y1 >= LaraItem->pos.yPos + frame->boundingBox.Y2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
float c, s;
|
|
|
|
int x, z, dx, dz;
|
|
|
|
|
|
|
|
c = phd_cos(pos->yRot);
|
|
|
|
s = phd_sin(pos->yRot);
|
|
|
|
x = LaraItem->pos.xPos - pos->xPos;
|
|
|
|
z = LaraItem->pos.zPos - pos->zPos;
|
|
|
|
dx = c * x - s * z;
|
|
|
|
dz = c * z + s * x;
|
|
|
|
|
|
|
|
if (dx <= radius + bounds->X2
|
|
|
|
&& dx >= bounds->X1 - radius
|
|
|
|
&& dz <= radius + bounds->Z2
|
|
|
|
&& dz >= bounds->Z1 - radius)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ItemPushLaraStatic(ITEM_INFO* item, BOUNDING_BOX* bounds, PHD_3DPOS* pos, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
float c, s;
|
|
|
|
int dx, dz, rx, rz, minX, maxX, minZ, maxZ;
|
|
|
|
int left, right, top, bottom;
|
|
|
|
short oldFacing;
|
|
|
|
|
|
|
|
c = phd_cos(pos->yRot);
|
|
|
|
s = phd_sin(pos->yRot);
|
|
|
|
dx = LaraItem->pos.xPos - pos->xPos;
|
|
|
|
dz = LaraItem->pos.zPos - pos->zPos;
|
|
|
|
rx = c * dx - s * dz;
|
|
|
|
rz = c * dz + s * dx;
|
|
|
|
minX = bounds->X1 - coll->radius;
|
|
|
|
maxX = bounds->X2 + coll->radius;
|
|
|
|
minZ = bounds->Z1 - coll->radius;
|
|
|
|
maxZ = bounds->Z2 + coll->radius;
|
|
|
|
|
|
|
|
if (abs(dx) > 4608
|
|
|
|
|| abs(dz) > 4608
|
|
|
|
|| rx <= minX
|
|
|
|
|| rx >= maxX
|
|
|
|
|| rz <= minZ
|
|
|
|
|| rz >= maxZ)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
left = rx - minX;
|
|
|
|
top = maxZ - rz;
|
|
|
|
bottom = rz - minZ;
|
|
|
|
right = maxX - rx;
|
|
|
|
|
|
|
|
if (right <= left && right <= top && right <= bottom)
|
|
|
|
rx += right;
|
|
|
|
else if (left <= right && left <= top && left <= bottom)
|
|
|
|
rx -= left;
|
|
|
|
else if (top <= left && top <= right && top <= bottom)
|
|
|
|
rz += top;
|
|
|
|
else
|
|
|
|
rz -= bottom;
|
|
|
|
|
|
|
|
item->pos.xPos = pos->xPos + c * rx + s * rz;
|
|
|
|
item->pos.zPos = pos->zPos + c * rz - s * rx;
|
|
|
|
|
|
|
|
coll->badPos = NO_BAD_POS;
|
|
|
|
coll->badNeg = -STEPUP_HEIGHT;
|
|
|
|
coll->badCeiling = 0;
|
|
|
|
|
|
|
|
oldFacing = coll->facing;
|
|
|
|
coll->facing = phd_atan(item->pos.zPos - coll->old.z, item->pos.xPos - coll->old.x);
|
2021-01-07 11:16:21 -03:00
|
|
|
if (item == LaraItem)
|
|
|
|
{
|
|
|
|
GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GetObjectCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE);
|
|
|
|
}
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->facing = oldFacing;
|
|
|
|
|
|
|
|
if (coll->collType == CT_NONE)
|
|
|
|
{
|
|
|
|
coll->old.x = item->pos.xPos;
|
|
|
|
coll->old.y = item->pos.yPos;
|
|
|
|
coll->old.z = item->pos.zPos;
|
|
|
|
|
|
|
|
UpdateLaraRoom(item, -10);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.xPos = coll->old.x;
|
|
|
|
item->pos.zPos = coll->old.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item == LaraItem && Lara.isMoving && Lara.moveCount > 15)
|
|
|
|
{
|
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ItemPushLara(ITEM_INFO* item, ITEM_INFO* l, COLL_INFO* coll, int spazon, char bigpush)
|
|
|
|
{
|
|
|
|
float c, s;
|
|
|
|
int dx, dz, rx, rz, minX, maxX, minZ, maxZ;
|
|
|
|
int left, right, bottom, top;
|
|
|
|
BOUNDING_BOX* bounds;
|
|
|
|
short facing;
|
|
|
|
|
2021-08-16 18:55:25 +03:00
|
|
|
// Get item's rotation
|
|
|
|
c = phd_cos(item->pos.yRot);
|
2020-12-21 13:16:29 -03:00
|
|
|
s = phd_sin(item->pos.yRot);
|
2021-08-16 18:55:25 +03:00
|
|
|
|
|
|
|
// Get vector from item to Lara
|
|
|
|
dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
|
|
dz = LaraItem->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
// Rotate Lara vector into item frame
|
|
|
|
rx = c * dx - s * dz;
|
|
|
|
rz = c * dz + s * dx;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (bigpush & 2)
|
|
|
|
bounds = &GlobalCollisionBounds;
|
|
|
|
else
|
|
|
|
bounds = (BOUNDING_BOX*)GetBestFrame(item);
|
|
|
|
|
|
|
|
minX = bounds->X1;
|
|
|
|
maxX = bounds->X2;
|
|
|
|
minZ = bounds->Z1;
|
|
|
|
maxZ = bounds->Z2;
|
|
|
|
|
|
|
|
if (bigpush & 1)
|
|
|
|
{
|
|
|
|
minX -= coll->radius;
|
|
|
|
maxX += coll->radius;
|
|
|
|
minZ -= coll->radius;
|
|
|
|
maxZ += coll->radius;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Big enemies
|
|
|
|
if (abs(dx) > 4608
|
|
|
|
|| abs(dz) > 4608
|
|
|
|
|| rx <= minX
|
|
|
|
|| rx >= maxX
|
|
|
|
|| rz <= minZ
|
|
|
|
|| rz >= maxZ)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
left = rx - minX;
|
|
|
|
top = maxZ - rz;
|
|
|
|
bottom = rz - minZ;
|
|
|
|
right = maxX - rx;
|
|
|
|
|
|
|
|
if (right <= left && right <= top && right <= bottom)
|
|
|
|
rx += right;
|
|
|
|
else if (left <= right && left <= top && left <= bottom)
|
|
|
|
rx -= left;
|
|
|
|
else if (top <= left && top <= right && top <= bottom)
|
|
|
|
rz += top;
|
|
|
|
else
|
|
|
|
rz -= bottom;
|
|
|
|
|
|
|
|
l->pos.xPos = item->pos.xPos + c * rx + s * rz;
|
|
|
|
l->pos.zPos = item->pos.zPos + c * rz - s * rx;
|
|
|
|
|
|
|
|
if (spazon && bounds->Y2 - bounds->Y1 > STEP_SIZE)
|
|
|
|
{
|
|
|
|
rx = (bounds->X1 + bounds->X2) / 2;
|
|
|
|
rz = (bounds->Z1 + bounds->Z2) / 2;
|
|
|
|
|
|
|
|
dx -= c * rx + s * rz;
|
|
|
|
dz -= c * rz - s * rx;
|
|
|
|
|
|
|
|
Lara.hitDirection = (l->pos.yRot - phd_atan(dz, dz) - ANGLE(135)) / 16384;
|
|
|
|
|
|
|
|
if ((!Lara.hitFrame) && (!hitSoundTimer))
|
|
|
|
{
|
2021-05-26 06:04:32 +02:00
|
|
|
SoundEffect(SFX_TR4_LARA_INJURY, &l->pos, 0);
|
2020-12-21 13:16:29 -03:00
|
|
|
hitSoundTimer = generateFloat(5, 15);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hitSoundTimer)
|
|
|
|
hitSoundTimer--;
|
|
|
|
|
|
|
|
Lara.hitFrame++;
|
|
|
|
if (Lara.hitFrame > 34)
|
|
|
|
Lara.hitFrame = 34;
|
|
|
|
}
|
|
|
|
|
|
|
|
coll->badPos = NO_BAD_POS;
|
|
|
|
coll->badNeg = -STEPUP_HEIGHT;
|
|
|
|
coll->badCeiling = 0;
|
|
|
|
|
|
|
|
facing = coll->facing;
|
|
|
|
coll->facing = phd_atan(l->pos.zPos - coll->old.z, l->pos.xPos - coll->old.x);
|
2021-08-16 18:55:25 +03:00
|
|
|
|
|
|
|
if (l == LaraItem)
|
|
|
|
{
|
|
|
|
GetCollisionInfo(coll, l->pos.xPos, l->pos.yPos, l->pos.zPos, l->roomNumber, LARA_HITE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GetObjectCollisionInfo(coll, l->pos.xPos, l->pos.yPos, l->pos.zPos, l->roomNumber, LARA_HITE);
|
|
|
|
}
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->facing = facing;
|
|
|
|
|
|
|
|
if (coll->collType == CT_NONE)
|
|
|
|
{
|
|
|
|
coll->old.x = l->pos.xPos;
|
|
|
|
coll->old.y = l->pos.yPos;
|
|
|
|
coll->old.z = l->pos.zPos;
|
|
|
|
|
2021-08-16 18:55:25 +03:00
|
|
|
// Commented because causes Lara to jump out of the water if she touches an object on the surface. re: "kayak bug"
|
|
|
|
// UpdateLaraRoom(l, -10);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l->pos.xPos = coll->old.x;
|
|
|
|
l->pos.zPos = coll->old.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Lara.isMoving && Lara.moveCount > 15)
|
|
|
|
{
|
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AIPickupCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
if (item->objectNumber == ID_SHOOT_SWITCH1 && !(item->meshBits & 1))
|
|
|
|
item->status = ITEM_INVISIBLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjectCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* c)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
|
|
|
|
if (TestBoundsCollide(item, l, c->radius))
|
|
|
|
{
|
|
|
|
if (TestCollision(item, l))
|
|
|
|
{
|
|
|
|
if (c->enableBaddiePush)
|
2021-06-05 06:03:12 +02:00
|
|
|
ItemPushLara(item, l, c, false, true);
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AlignLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l)
|
|
|
|
{
|
|
|
|
int x, y, z;
|
|
|
|
|
|
|
|
l->pos.xRot = item->pos.xRot;
|
|
|
|
l->pos.yRot = item->pos.yRot;
|
|
|
|
l->pos.zRot = item->pos.zRot;
|
|
|
|
|
|
|
|
Matrix matrix = Matrix::CreateFromYawPitchRoll(
|
|
|
|
TO_RAD(item->pos.yRot),
|
|
|
|
TO_RAD(item->pos.xRot),
|
|
|
|
TO_RAD(item->pos.zRot)
|
|
|
|
);
|
|
|
|
|
|
|
|
Vector3 pos = Vector3::Transform(Vector3(vec->x, vec->y, vec->z), matrix);
|
|
|
|
|
|
|
|
l->pos.xPos = item->pos.xPos + pos.x;
|
|
|
|
l->pos.yPos = item->pos.yPos + pos.y;
|
|
|
|
l->pos.zPos = item->pos.zPos + pos.z;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TriggerLaraBlood()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int node = 1;
|
|
|
|
|
|
|
|
for (i = 0; i < 14; i++)
|
|
|
|
{
|
|
|
|
if (node & LaraItem->touchBits)
|
|
|
|
{
|
|
|
|
PHD_VECTOR vec;
|
|
|
|
vec.x = (GetRandomControl() & 31) - 16;
|
|
|
|
vec.y = (GetRandomControl() & 31) - 16;
|
|
|
|
vec.z = (GetRandomControl() & 31) - 16;
|
|
|
|
|
|
|
|
GetLaraJointPosition(&vec, LM[i]);
|
|
|
|
DoBloodSplat(vec.x, vec.y, vec.z, (GetRandomControl() & 7) + 8, 2 * GetRandomControl(), LaraItem->roomNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
node *= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int TestLaraPosition(OBJECT_COLLISION_BOUNDS* bounds, ITEM_INFO* item, ITEM_INFO* l)
|
|
|
|
{
|
|
|
|
int x, y, z, rx, ry, rz;
|
|
|
|
short xRotRel, yRotRel, zRotRel;
|
|
|
|
|
|
|
|
xRotRel = l->pos.xRot - item->pos.xRot;
|
|
|
|
yRotRel = l->pos.yRot - item->pos.yRot;
|
|
|
|
zRotRel = l->pos.zRot - item->pos.zRot;
|
|
|
|
|
|
|
|
if (xRotRel < bounds->rotX1)
|
|
|
|
return false;
|
|
|
|
if (xRotRel > bounds->rotX2)
|
|
|
|
return false;
|
|
|
|
if (yRotRel < bounds->rotY1)
|
|
|
|
return false;
|
|
|
|
if (yRotRel > bounds->rotY2)
|
|
|
|
return false;
|
|
|
|
if (zRotRel < bounds->rotZ1)
|
|
|
|
return false;
|
2021-05-31 07:18:02 +02:00
|
|
|
if (zRotRel > bounds->rotZ2)
|
2020-12-21 13:16:29 -03:00
|
|
|
return false;
|
|
|
|
|
2021-05-31 07:18:02 +02:00
|
|
|
x = l->pos.xPos - item->pos.xPos;
|
|
|
|
y = l->pos.yPos - item->pos.yPos;
|
|
|
|
z = l->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
Vector3 pos = Vector3(x, y, z);
|
|
|
|
|
2021-08-16 18:55:25 +03:00
|
|
|
// HACK (REMOVED FOR NOW): it seems that a minus sign may be required here.
|
|
|
|
// I don't know why, but it just works (tm) but we must do more tests -- Monty
|
|
|
|
// 16.08.21: Changed back to non-minus sign by request of Krys and ChocolateFan -- Lwmte
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
Matrix matrix = Matrix::CreateFromYawPitchRoll(
|
2021-08-16 18:55:25 +03:00
|
|
|
TO_RAD(item->pos.yRot),
|
2020-12-21 13:16:29 -03:00
|
|
|
TO_RAD(item->pos.xRot),
|
|
|
|
TO_RAD(item->pos.zRot)
|
|
|
|
);
|
|
|
|
|
|
|
|
pos = Vector3::Transform(pos, matrix);
|
|
|
|
|
|
|
|
rx = pos.x;
|
|
|
|
ry = pos.y;
|
|
|
|
rz = pos.z;
|
|
|
|
|
2021-05-31 07:18:02 +02:00
|
|
|
if (rx < bounds->boundingBox.X1 || rx > bounds->boundingBox.X2
|
2020-12-21 13:16:29 -03:00
|
|
|
|| ry < bounds->boundingBox.Y1 || ry > bounds->boundingBox.Y2
|
|
|
|
|| rz < bounds->boundingBox.Z1 || rz > bounds->boundingBox.Z2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Move3DPosTo3DPos(PHD_3DPOS* src, PHD_3DPOS* dest, int velocity, short angAdd)
|
|
|
|
{
|
|
|
|
int x, y, z;
|
|
|
|
int distance, direction;
|
|
|
|
int angle;
|
|
|
|
|
|
|
|
x = dest->xPos - src->xPos;
|
|
|
|
y = dest->yPos - src->yPos;
|
|
|
|
z = dest->zPos - src->zPos;
|
|
|
|
distance = sqrt(SQUARE(x) + SQUARE(y) + SQUARE(z));
|
|
|
|
|
|
|
|
if (velocity < distance)
|
|
|
|
{
|
|
|
|
src->xPos += x * velocity / distance;
|
|
|
|
src->yPos += y * velocity / distance;
|
|
|
|
src->zPos += z * velocity / distance;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src->xPos = dest->xPos;
|
|
|
|
src->yPos = dest->yPos;
|
|
|
|
src->zPos = dest->zPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Lara.isMoving)
|
|
|
|
{
|
|
|
|
if (Lara.waterStatus != LW_UNDERWATER)
|
|
|
|
{
|
|
|
|
angle = mGetAngle(dest->xPos, dest->zPos, src->xPos, src->zPos);
|
2021-08-16 18:55:25 +03:00
|
|
|
direction = (GetQuadrant(angle) - GetQuadrant(dest->yRot)) & 3;
|
2021-06-04 06:02:19 +02:00
|
|
|
|
2021-08-16 18:55:25 +03:00
|
|
|
// 16.08.21: code below was deliberately reintroduced by Monty for whatever reasons.
|
|
|
|
// Identified as regression by ChocolateFan and commented.
|
|
|
|
|
|
|
|
// angle = (angle + 0x2000) / 0x4000;
|
|
|
|
// angle = (angle - ((unsigned short)(dest->yRot + 0x2000) / 0x4000));
|
|
|
|
// angle &= 3;
|
2021-06-04 06:02:19 +02:00
|
|
|
|
2021-08-16 18:55:25 +03:00
|
|
|
switch (direction)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-08-16 18:55:25 +03:00
|
|
|
case 0:
|
|
|
|
LaraItem->animNumber = LA_SIDESTEP_LEFT;
|
|
|
|
LaraItem->frameNumber = GF(LA_SIDESTEP_LEFT, 0);
|
|
|
|
LaraItem->goalAnimState = LS_STEP_LEFT;
|
|
|
|
LaraItem->currentAnimState = LS_STEP_LEFT;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
LaraItem->animNumber = LA_WALK;
|
|
|
|
LaraItem->frameNumber = GF(LA_WALK, 0);
|
|
|
|
LaraItem->goalAnimState = LS_WALK_FORWARD;
|
|
|
|
LaraItem->currentAnimState = LS_WALK_FORWARD;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
LaraItem->animNumber = LA_WALK;
|
|
|
|
LaraItem->frameNumber = GF(LA_SIDESTEP_RIGHT, 0);
|
|
|
|
LaraItem->goalAnimState = LS_STEP_RIGHT;
|
|
|
|
LaraItem->currentAnimState = LS_STEP_RIGHT;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
default:
|
|
|
|
LaraItem->animNumber = LA_WALK_BACK;
|
|
|
|
LaraItem->frameNumber = GF(LA_WALK_BACK, 0);
|
|
|
|
LaraItem->goalAnimState = LS_WALK_BACK;
|
|
|
|
LaraItem->currentAnimState = LS_WALK_BACK;
|
|
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
|
|
break;
|
2020-12-21 13:16:29 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Lara.isMoving = true;
|
|
|
|
Lara.moveCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((short) (dest->xRot - src->xRot) <= angAdd)
|
|
|
|
{
|
|
|
|
if ((short) (dest->xRot - src->xRot) >= -angAdd)
|
|
|
|
src->xRot = dest->xRot;
|
|
|
|
else
|
|
|
|
src->xRot = src->xRot - angAdd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src->xRot = angAdd + src->xRot;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((short) (dest->yRot - src->yRot) <= angAdd)
|
|
|
|
{
|
|
|
|
if ((short) (dest->yRot - src->yRot) >= -angAdd)
|
|
|
|
src->yRot = dest->yRot;
|
|
|
|
else
|
|
|
|
src->yRot = src->yRot - angAdd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src->yRot = angAdd + src->yRot;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((short) (dest->zRot - src->zRot) <= angAdd)
|
|
|
|
{
|
|
|
|
if ((short) (dest->zRot - src->zRot) >= -angAdd)
|
|
|
|
src->zRot = dest->zRot;
|
|
|
|
else
|
|
|
|
src->zRot = src->zRot - angAdd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src->zRot = angAdd + src->zRot;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (src->xPos == dest->xPos
|
|
|
|
&& src->yPos == dest->yPos
|
|
|
|
&& src->zPos == dest->zPos
|
|
|
|
&& src->xRot == dest->xRot
|
|
|
|
&& src->yRot == dest->yRot
|
|
|
|
&& src->zRot == dest->zRot);
|
|
|
|
}
|
|
|
|
|
|
|
|
int MoveLaraPosition(PHD_VECTOR* vec, ITEM_INFO* item, ITEM_INFO* l)
|
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
PHD_3DPOS dest;
|
|
|
|
int height;
|
|
|
|
short roomNumber;
|
|
|
|
|
|
|
|
dest.xRot = item->pos.xRot;
|
|
|
|
dest.yRot = item->pos.yRot;
|
|
|
|
dest.zRot = item->pos.zRot;
|
|
|
|
|
|
|
|
Vector3 pos = Vector3(vec->x, vec->y, vec->z);
|
|
|
|
|
|
|
|
Matrix matrix = Matrix::CreateFromYawPitchRoll(
|
|
|
|
TO_RAD(item->pos.yRot),
|
|
|
|
TO_RAD(item->pos.xRot),
|
|
|
|
TO_RAD(item->pos.zRot)
|
|
|
|
);
|
|
|
|
|
|
|
|
pos = Vector3::Transform(pos, matrix);
|
|
|
|
|
|
|
|
dest.xPos = item->pos.xPos + pos.x;
|
|
|
|
dest.yPos = item->pos.yPos + pos.y;
|
|
|
|
dest.zPos = item->pos.zPos + pos.z;
|
|
|
|
|
|
|
|
if (item->objectNumber != ID_FLARE_ITEM && item->objectNumber != ID_BURNING_TORCH_ITEM)
|
|
|
|
return Move3DPosTo3DPos(&l->pos, &dest, LARA_VELOCITY, ANGLE(2));
|
|
|
|
|
|
|
|
roomNumber = l->roomNumber;
|
|
|
|
floor = GetFloor(dest.xPos, dest.yPos, dest.zPos, &roomNumber);
|
|
|
|
height = GetFloorHeight(floor, dest.xPos, dest.yPos, dest.zPos);
|
|
|
|
|
|
|
|
if (abs(height - l->pos.yPos) <= CLICK(2))
|
|
|
|
{
|
|
|
|
if (sqrt(SQUARE(dest.xPos - l->pos.xPos) + SQUARE(dest.yPos - l->pos.yPos) + SQUARE(dest.zPos - l->pos.zPos)) < (STEP_SIZE/2))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return Move3DPosTo3DPos(&l->pos, &dest, LARA_VELOCITY, ANGLE(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Lara.isMoving)
|
|
|
|
{
|
|
|
|
Lara.isMoving = false;
|
|
|
|
Lara.gunStatus = LG_NO_ARMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TestBoundsCollide(ITEM_INFO* item, ITEM_INFO* l, int radius)
|
|
|
|
{
|
|
|
|
BOUNDING_BOX* bounds;
|
|
|
|
BOUNDING_BOX* laraBounds;
|
|
|
|
float c, s;
|
|
|
|
int x, z;
|
|
|
|
int dx, dz;
|
|
|
|
|
|
|
|
bounds = (BOUNDING_BOX*)GetBestFrame(item);
|
|
|
|
laraBounds = (BOUNDING_BOX*)GetBestFrame(l);
|
|
|
|
|
|
|
|
if (item->pos.yPos + bounds->Y2 > l->pos.yPos + laraBounds->Y1)
|
|
|
|
{
|
|
|
|
if (item->pos.yPos + bounds->Y1 < l->pos.yPos + laraBounds->Y2)
|
|
|
|
{
|
|
|
|
c = phd_cos(item->pos.yRot);
|
|
|
|
s = phd_sin(item->pos.yRot);
|
|
|
|
x = l->pos.xPos - item->pos.xPos;
|
|
|
|
z = l->pos.zPos - item->pos.zPos;
|
|
|
|
dx = c * x - s * z;
|
|
|
|
dz = c * z + s * x;
|
|
|
|
|
|
|
|
if (dx >= bounds->X1 - radius
|
|
|
|
&& dx <= radius + bounds->X2
|
|
|
|
&& dz >= bounds->Z1 - radius
|
|
|
|
&& dz <= radius + bounds->Z2)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CreatureCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
float c, s;
|
|
|
|
int x, z, rx, rz;
|
|
|
|
ANIM_FRAME* frame;
|
|
|
|
|
|
|
|
if (item->objectNumber != ID_HITMAN || item->currentAnimState != LS_INSERT_PUZZLE)
|
|
|
|
{
|
|
|
|
if (TestBoundsCollide(item, l, coll->radius))
|
|
|
|
{
|
|
|
|
if (TestCollision(item, l))
|
|
|
|
{
|
|
|
|
if (coll->enableBaddiePush || Lara.waterStatus == LW_UNDERWATER || Lara.waterStatus == LW_SURFACE)
|
|
|
|
{
|
|
|
|
ItemPushLara(item, l, coll, coll->enableSpaz, 0);
|
|
|
|
}
|
|
|
|
else if (coll->enableSpaz)
|
|
|
|
{
|
|
|
|
x = l->pos.xPos - item->pos.xPos;
|
|
|
|
z = l->pos.zPos - item->pos.zPos;
|
|
|
|
c = phd_cos(item->pos.yRot);
|
|
|
|
s = phd_sin(item->pos.yRot);
|
|
|
|
frame = GetBestFrame(item);
|
|
|
|
rx = (frame->boundingBox.X1 + frame->boundingBox.X2) / 2;
|
|
|
|
rz = (frame->boundingBox.X2 + frame->boundingBox.Z2) / 2;
|
|
|
|
|
|
|
|
if (frame->boundingBox.Y2 - frame->boundingBox.Y1 > STEP_SIZE)
|
|
|
|
{
|
|
|
|
int angle = (l->pos.yRot - phd_atan(z - c * rx - s * rz, x - c * rx + s * rz) - ANGLE(135)) / 16384;
|
|
|
|
Lara.hitDirection = (short)angle;
|
|
|
|
// TODO: check if a second Lara.hitFrame++; is required there !
|
|
|
|
Lara.hitFrame++;
|
|
|
|
if (Lara.hitFrame > 30)
|
|
|
|
Lara.hitFrame = 30;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
COLL_RESULT GetCollisionResult(ITEM_INFO* item)
|
2021-02-06 18:33:33 -06:00
|
|
|
{
|
2021-08-22 01:39:14 +03:00
|
|
|
auto roomNumber = item->roomNumber;
|
|
|
|
auto floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
return GetCollisionResult(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
COLL_RESULT GetCollisionResult(int x, int y, int z, short roomNumber)
|
|
|
|
{
|
|
|
|
auto room = roomNumber;
|
|
|
|
auto floor = GetFloor(x, y, z, &room);
|
|
|
|
return GetCollisionResult(floor, x, y, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
COLL_RESULT GetCollisionResult(FLOOR_INFO* floor, int x, int y, int z)
|
|
|
|
{
|
|
|
|
COLL_RESULT result = {};
|
|
|
|
|
|
|
|
result.Block = floor;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
|
|
|
ROOM_INFO* r;
|
|
|
|
while (floor->pitRoom != NO_ROOM)
|
|
|
|
{
|
|
|
|
if (CheckNoColFloorTriangle(floor, x, z) == 1)
|
|
|
|
break;
|
|
|
|
r = &g_Level.Rooms[floor->pitRoom];
|
|
|
|
floor = &XZ_GET_SECTOR(r, x - r->x, z - r->z);
|
|
|
|
}
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
result.FloorHeight = GetFloorHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT);
|
|
|
|
|
|
|
|
if (floor->floor * 256 == NO_HEIGHT || floor->index == 0)
|
|
|
|
return result; // No floordata, block is flat.
|
|
|
|
|
2021-02-06 18:33:33 -06:00
|
|
|
int height = floor->floor * 256;
|
2021-08-22 01:39:14 +03:00
|
|
|
|
|
|
|
short* data = &g_Level.FloorData[floor->index];
|
|
|
|
short type, hadj;
|
|
|
|
|
|
|
|
int xOff, yOff, trigger;
|
|
|
|
int tilts, t0, t1, t2, t3, t4, dx, dz, h1, h2;
|
|
|
|
|
|
|
|
do
|
2021-02-06 18:33:33 -06:00
|
|
|
{
|
2021-08-22 01:39:14 +03:00
|
|
|
type = *(data++);
|
|
|
|
|
|
|
|
switch (type & DATA_TYPE)
|
2021-02-06 18:33:33 -06:00
|
|
|
{
|
2021-08-22 01:39:14 +03:00
|
|
|
case DOOR_TYPE:
|
|
|
|
case ROOF_TYPE:
|
|
|
|
data++;
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
case SPLIT3:
|
|
|
|
case SPLIT4:
|
|
|
|
case NOCOLC1T:
|
|
|
|
case NOCOLC1B:
|
|
|
|
case NOCOLC2T:
|
|
|
|
case NOCOLC2B:
|
|
|
|
result.SplitCeiling = type & DATA_TYPE;
|
|
|
|
data++;
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
case TILT_TYPE:
|
|
|
|
result.TiltX = xOff = (*data >> 8);
|
|
|
|
result.TiltZ = yOff = *(char*)data;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if ((abs(xOff)) > 2 || (abs(yOff)) > 2)
|
|
|
|
result.HeightType = BIG_SLOPE;
|
|
|
|
else
|
|
|
|
result.HeightType = SMALL_SLOPE;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (xOff >= 0)
|
|
|
|
height += (xOff * ((-1 - z) & 1023) >> 2);
|
|
|
|
else
|
|
|
|
height -= (xOff * (z & 1023) >> 2);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (yOff >= 0)
|
|
|
|
height += yOff * ((-1 - x) & 1023) >> 2;
|
|
|
|
else
|
|
|
|
height -= yOff * (x & 1023) >> 2;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
data++;
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
case TRIGGER_TYPE:
|
|
|
|
data++;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
trigger = *(data++);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (TRIG_BITS(trigger) != TO_OBJECT)
|
|
|
|
{
|
|
|
|
if (TRIG_BITS(trigger) == TO_CAMERA ||
|
|
|
|
TRIG_BITS(trigger) == TO_FLYBY)
|
2021-02-06 18:33:33 -06:00
|
|
|
{
|
|
|
|
trigger = *(data++);
|
2021-08-22 01:39:14 +03:00
|
|
|
}
|
|
|
|
}
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
} while (!(trigger & END_BIT));
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
case SPLIT1:
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
tilts = *data;
|
|
|
|
t0 = tilts & 15;
|
|
|
|
t1 = (tilts >> 4) & 15;
|
|
|
|
t2 = (tilts >> 8) & 15;
|
|
|
|
t3 = (tilts >> 12) & 15;
|
|
|
|
|
|
|
|
dx = x & 1023;
|
|
|
|
dz = z & 1023;
|
|
|
|
|
|
|
|
xOff = yOff = 0;
|
|
|
|
|
|
|
|
result.HeightType = SPLIT_TRI;
|
|
|
|
result.SplitFloor = (type & DATA_TYPE);
|
|
|
|
|
|
|
|
if ((type & DATA_TYPE) == SPLIT1 ||
|
|
|
|
(type & DATA_TYPE) == NOCOLF1T ||
|
|
|
|
(type & DATA_TYPE) == NOCOLF1B)
|
|
|
|
{
|
|
|
|
if (dx <= (1024 - dz))
|
|
|
|
{
|
|
|
|
hadj = (type >> 10) & 0x1F;
|
|
|
|
if (hadj & 0x10)
|
|
|
|
hadj |= 0xfff0;
|
|
|
|
height += 256 * hadj;
|
|
|
|
xOff = t2 - t1;
|
|
|
|
yOff = t0 - t1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hadj = (type >> 5) & 0x1F;
|
|
|
|
if (hadj & 0x10)
|
|
|
|
hadj |= 0xFFF0;
|
|
|
|
height += 256 * hadj;
|
|
|
|
xOff = t3 - t0;
|
|
|
|
yOff = t3 - t2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dx <= dz)
|
|
|
|
{
|
|
|
|
hadj = (type >> 10) & 0x1f;
|
|
|
|
if (hadj & 0x10)
|
|
|
|
hadj |= 0xfff0;
|
|
|
|
height += 256 * hadj;
|
|
|
|
xOff = t2 - t1;
|
|
|
|
yOff = t3 - t2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hadj = (type >> 5) & 0x1f;
|
|
|
|
if (hadj & 0x10)
|
|
|
|
hadj |= 0xfff0;
|
|
|
|
height += 256 * hadj;
|
|
|
|
xOff = t3 - t0;
|
|
|
|
yOff = t0 - t1;
|
|
|
|
}
|
|
|
|
}
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
result.TiltX = xOff;
|
|
|
|
result.TiltZ = yOff;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if ((abs(xOff)) > 2 || (abs(yOff)) > 2)
|
|
|
|
result.HeightType = DIAGONAL;
|
|
|
|
else if (result.HeightType != SPLIT_TRI)
|
|
|
|
result.HeightType = SMALL_SLOPE;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (xOff >= 0)
|
|
|
|
height += xOff * ((-1 - z) & 1023) >> 2;
|
|
|
|
else
|
|
|
|
height -= xOff * (z & 1023) >> 2;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (yOff >= 0)
|
|
|
|
height += yOff * ((-1 - x) & 1023) >> 2;
|
|
|
|
else
|
|
|
|
height -= yOff * (x & 1023) >> 2;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
data++;
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
default:
|
|
|
|
break;
|
2021-02-06 18:33:33 -06:00
|
|
|
}
|
2021-08-22 01:39:14 +03:00
|
|
|
} while (!(type & END_BIT));
|
|
|
|
|
|
|
|
return result;
|
2021-02-06 18:33:33 -06:00
|
|
|
}
|
2021-08-19 18:43:52 +03:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
void GetCollisionInfo(COLL_INFO* coll, int xPos, int yPos, int zPos, int roomNumber, int objectHeight)
|
|
|
|
{
|
|
|
|
int resetRoom;
|
|
|
|
if (objectHeight >= 0)
|
|
|
|
{
|
|
|
|
resetRoom = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
objectHeight = -objectHeight;
|
|
|
|
resetRoom = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
coll->collType = 0;
|
|
|
|
coll->shift.x = 0;
|
|
|
|
coll->shift.y = 0;
|
|
|
|
coll->shift.z = 0;
|
|
|
|
coll->quadrant = GetQuadrant(coll->facing);
|
|
|
|
|
|
|
|
int x = xPos;
|
|
|
|
int y = yPos - objectHeight;
|
|
|
|
int yTop = y - 160;
|
|
|
|
int z = zPos;
|
|
|
|
|
|
|
|
ROOM_VECTOR tfLocation = GetRoom(LaraItem->location, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
// DoFloorThings(floor, x, yTop, z);
|
|
|
|
auto collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
int height = GetFloorHeight(tfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
ROOM_VECTOR tcLocation = GetRoom(LaraItem->location, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
int ceiling = GetCeilingHeight(tcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->midCeiling = ceiling;
|
|
|
|
coll->midFloor = height;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->midType = collResult.HeightType;
|
|
|
|
coll->midSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->midSplitCeil = collResult.SplitCeiling;
|
|
|
|
|
|
|
|
short tRoomNumber = roomNumber;
|
|
|
|
int tilt = GetTiltType(GetFloor(x, yTop, z, &tRoomNumber), x, LaraItem->pos.yPos, z);
|
|
|
|
// ||| remove upper thingy if equal
|
|
|
|
collResult = GetCollisionResult(x, LaraItem->pos.yPos, z, roomNumber);
|
2021-01-07 11:16:21 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
2021-01-07 11:16:21 -03:00
|
|
|
coll->tiltX = tilt;
|
|
|
|
coll->tiltZ = tilt / 256;
|
2021-08-22 01:39:14 +03:00
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
|
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
if (collResult.TiltX != coll->tiltX || collResult.TiltZ != coll->tiltZ)
|
|
|
|
{
|
|
|
|
auto shit = 1;
|
|
|
|
}
|
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
int xright, xleft, zright, zleft;
|
|
|
|
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
ZFront = coll->radius;
|
|
|
|
xleft = -(coll->radius);
|
|
|
|
zleft = coll->radius;
|
|
|
|
xright = coll->radius;
|
|
|
|
zright = coll->radius;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
XFront = coll->radius;
|
|
|
|
ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
xleft = coll->radius;
|
|
|
|
zleft = coll->radius;
|
|
|
|
xright = coll->radius;
|
|
|
|
zright = -(coll->radius);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
ZFront = -coll->radius;
|
|
|
|
xleft = coll->radius;
|
|
|
|
zleft = -(coll->radius);
|
|
|
|
xright = -(coll->radius);
|
|
|
|
zright = -(coll->radius);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
XFront = -(coll->radius);
|
|
|
|
ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
xleft = -(coll->radius);
|
|
|
|
zleft = -(coll->radius);
|
|
|
|
xright = -(coll->radius);
|
|
|
|
zright = coll->radius;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
xleft = zleft = 0;
|
|
|
|
xright = zright = 0;
|
|
|
|
XFront = ZFront = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
//ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
//xleft = -ZFront;
|
|
|
|
//zleft = XFront;
|
|
|
|
//xright = ZFront;
|
|
|
|
//zright = -XFront;
|
|
|
|
|
|
|
|
x = XFront + xPos;
|
|
|
|
z = ZFront + zPos;
|
|
|
|
|
|
|
|
if (resetRoom)
|
|
|
|
{
|
|
|
|
tfLocation = LaraItem->location;
|
|
|
|
tcLocation = LaraItem->location;
|
2021-08-15 18:05:15 -03:00
|
|
|
tRoomNumber = roomNumber;
|
2021-01-07 11:16:21 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
tfLocation = GetRoom(tfLocation, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//DoFloorThings(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
height = GetFloorHeight(tfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
tcLocation = GetRoom(tcLocation, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
ceiling = GetCeilingHeight(tcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->frontCeiling = ceiling;
|
|
|
|
coll->frontFloor = height;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->frontType = collResult.HeightType;
|
|
|
|
coll->frontSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->frontSplitCeil = collResult.SplitCeiling;
|
2021-01-07 11:16:21 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//DoFloorThings(floor, x + XFront, yTop, z + ZFront);
|
|
|
|
//floor = GetFloor(x + XFront, yTop, z + ZFront, &tRoomNumber);
|
|
|
|
collResult = GetCollisionResult(x + XFront, yTop, z + ZFront, roomNumber);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
tfLocation = GetRoom(tfLocation, x + XFront, yTop, z + ZFront);
|
|
|
|
height = GetFloorHeight(tfLocation, x + XFront, z + ZFront).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
if ((coll->slopesAreWalls)
|
|
|
|
&& ((coll->frontType == BIG_SLOPE) || (coll->frontType == DIAGONAL))
|
|
|
|
&& (coll->frontFloor < coll->midFloor)
|
|
|
|
&& (height < coll->frontFloor)
|
|
|
|
&& (coll->frontFloor < 0))
|
|
|
|
{
|
|
|
|
coll->frontFloor = -32767;
|
|
|
|
}
|
|
|
|
else if (coll->slopesArePits
|
|
|
|
&& ((coll->frontType == BIG_SLOPE) || (coll->frontType == DIAGONAL))
|
|
|
|
&& (coll->frontFloor > coll->midFloor))
|
|
|
|
{
|
|
|
|
coll->frontFloor = 512;
|
|
|
|
}
|
|
|
|
else if ((coll->lavaIsPit)
|
2021-08-22 01:39:14 +03:00
|
|
|
&& (coll->frontFloor > 0)
|
|
|
|
&& collResult.Block->Flags.Death)
|
2021-01-07 11:16:21 -03:00
|
|
|
{
|
|
|
|
coll->frontFloor = 512;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = xPos + xleft;
|
|
|
|
z = zPos + zleft;
|
|
|
|
|
|
|
|
ROOM_VECTOR lrfLocation = GetRoom(LaraItem->location, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//short lrRoomNumber = roomNumber;
|
|
|
|
//floor = GetFloor(x, yTop, z, &lrRoomNumber);
|
|
|
|
//DoFloorThings(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
height = GetFloorHeight(lrfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
ROOM_VECTOR lrcLocation = GetRoom(LaraItem->location, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
ceiling = GetCeilingHeight(lrcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->leftFloor = height;
|
|
|
|
coll->leftCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftType = collResult.HeightType;
|
|
|
|
coll->leftSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->leftSplitCeil = collResult.SplitCeiling;
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->leftType == BIG_SLOPE || coll->leftType == DIAGONAL) && coll->leftFloor < 0)
|
|
|
|
coll->leftFloor = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->leftType == BIG_SLOPE || coll->leftType == DIAGONAL) && coll->leftFloor > 0)
|
|
|
|
coll->leftFloor = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->leftFloor > 0 && collResult.Block->Flags.Death)
|
2021-01-07 11:16:21 -03:00
|
|
|
coll->leftFloor = 512;
|
|
|
|
|
|
|
|
tfLocation = GetRoom(tfLocation, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x + XFront, yTop, z + ZFront, &tRoomNumber); // WRONG COPYPASTE BY CHOCO
|
|
|
|
//DoFloorThings(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber); // We use plain x/z values here, proposed by Choco
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
height = GetFloorHeight(tfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
tcLocation = GetRoom(tcLocation, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
ceiling = GetCeilingHeight(tcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->leftFloor2 = height;
|
|
|
|
coll->leftCeiling2 = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftType2 = collResult.HeightType;
|
|
|
|
coll->leftSplitFloor2 = collResult.SplitFloor;
|
|
|
|
coll->leftSplitCeil2 = collResult.SplitCeiling;
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->leftType2 == BIG_SLOPE || coll->leftType2 == DIAGONAL) && coll->leftFloor2 < 0)
|
|
|
|
coll->leftFloor2 = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->leftType2 == BIG_SLOPE || coll->leftType2 == DIAGONAL) && coll->leftFloor2 > 0)
|
|
|
|
coll->leftFloor2 = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->leftFloor2 > 0 && collResult.Block->Flags.Death)
|
2021-01-07 11:16:21 -03:00
|
|
|
coll->leftFloor2 = 512;
|
|
|
|
|
|
|
|
x = xPos + xright;
|
|
|
|
z = zPos + zright;
|
|
|
|
|
|
|
|
lrfLocation = GetRoom(LaraItem->location, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//lrRoomNumber = roomNumber;
|
|
|
|
//floor = GetFloor(x, yTop, z, &lrRoomNumber);
|
|
|
|
//DoFloorThings(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
height = GetFloorHeight(lrfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
lrcLocation = GetRoom(LaraItem->location, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
ceiling = GetCeilingHeight(lrcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->rightFloor = height;
|
|
|
|
coll->rightCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightType = collResult.HeightType;
|
|
|
|
coll->rightSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->rightSplitCeil = collResult.SplitCeiling;
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->rightType == BIG_SLOPE || coll->rightType == DIAGONAL) && coll->rightFloor < 0)
|
|
|
|
coll->rightFloor = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->rightType == BIG_SLOPE || coll->rightType == DIAGONAL) && coll->rightFloor > 0)
|
|
|
|
coll->rightFloor = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->rightFloor > 0 && collResult.Block->Flags.Death)
|
2021-01-07 11:16:21 -03:00
|
|
|
coll->rightFloor = 512;
|
|
|
|
|
|
|
|
tfLocation = GetRoom(tfLocation, x, yTop, z);
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//DoFloorThings(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2021-02-06 18:33:33 -06:00
|
|
|
|
2021-01-07 11:16:21 -03:00
|
|
|
height = GetFloorHeight(tfLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (height != NO_HEIGHT)
|
|
|
|
height -= yPos;
|
|
|
|
|
|
|
|
tcLocation = GetRoom(tcLocation, x, yTop - LaraItem->fallspeed, z);
|
|
|
|
|
|
|
|
ceiling = GetCeilingHeight(tcLocation, x, z).value_or(NO_HEIGHT);
|
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->rightFloor2 = height;
|
|
|
|
coll->rightCeiling2 = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightType2 = collResult.HeightType;
|
|
|
|
coll->rightSplitFloor2 = collResult.SplitFloor;
|
|
|
|
coll->rightSplitCeil2 = collResult.SplitCeiling;
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->rightType2 == BIG_SLOPE || coll->rightType2 == DIAGONAL) && coll->rightFloor2 < 0)
|
|
|
|
coll->rightFloor2 = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->rightType2 == BIG_SLOPE || coll->rightType2 == DIAGONAL) && coll->rightFloor2 > 0)
|
|
|
|
coll->rightFloor2 = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->rightFloor2 > 0 && collResult.Block->Flags.Death)
|
2021-01-07 11:16:21 -03:00
|
|
|
coll->rightFloor2 = 512;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
CollideStaticObjects(coll, xPos, yPos, zPos, roomNumber, objectHeight); // check if bugged with roomNumber insted of tRoomNumber
|
2021-01-07 11:16:21 -03:00
|
|
|
|
|
|
|
if (coll->midFloor == NO_HEIGHT)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->midFloor - coll->midCeiling <= 0)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_CLAMP;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->midCeiling >= 0)
|
|
|
|
{
|
|
|
|
coll->shift.y = coll->midCeiling;
|
|
|
|
coll->collType = CT_TOP;
|
|
|
|
coll->hitCeiling = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((coll->frontFloor > coll->badPos)
|
|
|
|
|| (coll->frontFloor < coll->badNeg)
|
|
|
|
|| (coll->frontCeiling > coll->badCeiling))
|
|
|
|
{
|
|
|
|
if ((coll->frontType == DIAGONAL)
|
|
|
|
|| (coll->frontType == SPLIT_TRI))
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = FindGridShift(zPos + ZFront, zPos);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.x = FindGridShift(xPos + XFront, xPos);
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
coll->collType = CT_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->frontCeiling >= coll->badCeiling)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_TOP_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->leftFloor > coll->badPos ||
|
|
|
|
coll->leftFloor < coll->badNeg ||
|
|
|
|
coll->leftCeiling > coll->badCeiling)
|
|
|
|
{
|
|
|
|
if (coll->leftType == SPLIT_TRI && coll->midType == SPLIT_TRI)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = FindGridShift(xPos + xleft, xPos + XFront);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.z = FindGridShift(zPos + zleft, zPos + ZFront);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->leftSplitFloor && coll->leftSplitFloor == coll->midSplitFloor)
|
|
|
|
{
|
|
|
|
int quarter = (unsigned short)(coll->facing) / ANGLE(90); // different from coll->quadrant!
|
|
|
|
quarter %= 2;
|
|
|
|
|
|
|
|
switch (coll->leftSplitFloor)
|
|
|
|
{
|
|
|
|
case SPLIT1:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
if (quarter)
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
break;
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
if (!quarter)
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->rightFloor > coll->badPos ||
|
|
|
|
coll->rightFloor < coll->badNeg ||
|
|
|
|
coll->rightCeiling > coll->badCeiling)
|
|
|
|
{
|
|
|
|
if (coll->rightType == SPLIT_TRI && coll->midType == SPLIT_TRI)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = FindGridShift(xPos + xright, xPos + XFront);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.z = FindGridShift(zPos + zright, zPos + ZFront);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->rightSplitFloor && coll->rightSplitFloor == coll->midSplitFloor)
|
|
|
|
{
|
|
|
|
int quarter = (unsigned short)(coll->facing) / ANGLE(90); // different from coll->quadrant!
|
|
|
|
quarter %= 2;
|
|
|
|
|
|
|
|
switch (coll->rightSplitFloor)
|
|
|
|
{
|
|
|
|
case SPLIT1:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
if (quarter)
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
break;
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
if (!quarter)
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetObjectCollisionInfo(COLL_INFO* coll, int xPos, int yPos, int zPos, int roomNumber, int objectHeight)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
int resetRoom;
|
|
|
|
if (objectHeight >= 0)
|
|
|
|
{
|
|
|
|
resetRoom = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
objectHeight = -objectHeight;
|
|
|
|
resetRoom = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
coll->collType = 0;
|
|
|
|
coll->shift.x = 0;
|
|
|
|
coll->shift.y = 0;
|
|
|
|
coll->shift.z = 0;
|
|
|
|
coll->quadrant = GetQuadrant(coll->facing);
|
|
|
|
|
|
|
|
int x = xPos;
|
|
|
|
int y = yPos - objectHeight;
|
|
|
|
int yTop = y - 160;
|
|
|
|
int z = zPos;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//short tRoomNumber = roomNumber;
|
|
|
|
//FLOOR_INFO* floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//int height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
auto collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
|
|
|
|
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
int ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->midCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->midFloor = collResult.FloorHeight;
|
|
|
|
coll->midType = collResult.HeightType;
|
|
|
|
coll->midSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->midSplitCeil = collResult.SplitCeiling;
|
|
|
|
|
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
// collResult = GetCollisionResult(x, LaraItem->pos.yPos, z, roomNumber); // uncomment this line if yes
|
|
|
|
int tilt = GetTiltType(collResult.Block, x, LaraItem->pos.yPos, z); // CHECK IF SAME
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->tiltX = tilt;
|
|
|
|
coll->tiltZ = tilt / 256;
|
2021-08-22 01:39:14 +03:00
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
|
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
|
|
|
if (collResult.TiltX != coll->tiltX || collResult.TiltZ != coll->tiltZ)
|
|
|
|
{
|
|
|
|
auto shit = 1;
|
|
|
|
}
|
|
|
|
// FIXME REPLACE WITH GetCollisionResult
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
int xright, xleft, zright, zleft;
|
|
|
|
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
ZFront = coll->radius;
|
|
|
|
xleft = -(coll->radius);
|
|
|
|
zleft = coll->radius;
|
|
|
|
xright = coll->radius;
|
|
|
|
zright = coll->radius;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
XFront = coll->radius;
|
|
|
|
ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
xleft = coll->radius;
|
|
|
|
zleft = coll->radius;
|
|
|
|
xright = coll->radius;
|
|
|
|
zright = -(coll->radius);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
ZFront = -coll->radius;
|
|
|
|
xleft = coll->radius;
|
|
|
|
zleft = -(coll->radius);
|
|
|
|
xright = -(coll->radius);
|
|
|
|
zright = -(coll->radius);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
XFront = -(coll->radius);
|
|
|
|
ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
xleft = -(coll->radius);
|
|
|
|
zleft = -(coll->radius);
|
|
|
|
xright = -(coll->radius);
|
|
|
|
zright = coll->radius;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
xleft = zleft = 0;
|
|
|
|
xright = zright = 0;
|
|
|
|
XFront = ZFront = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//XFront = phd_sin(coll->facing) * coll->radius;
|
|
|
|
//ZFront = phd_cos(coll->facing) * coll->radius;
|
|
|
|
//xleft = -ZFront;
|
|
|
|
//zleft = XFront;
|
|
|
|
//xright = ZFront;
|
|
|
|
//zright = -XFront;
|
|
|
|
|
|
|
|
x = XFront + xPos;
|
|
|
|
z = ZFront + zPos;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//if (resetRoom)
|
|
|
|
// tRoomNumber = roomNumber;
|
|
|
|
//
|
|
|
|
//floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//
|
|
|
|
//height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
|
|
|
|
|
|
|
ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
|
|
|
coll->frontCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->frontFloor = collResult.FloorHeight;
|
|
|
|
coll->frontType = collResult.HeightType;
|
|
|
|
coll->frontSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->frontSplitCeil = collResult.SplitCeiling;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x + XFront, yTop, z + ZFront, &tRoomNumber);
|
|
|
|
//height = GetFloorHeight(floor, x + XFront, yTop, z + ZFront);
|
|
|
|
collResult = GetCollisionResult(x + XFront, yTop, z + ZFront, roomNumber);
|
|
|
|
|
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if ((coll->slopesAreWalls)
|
|
|
|
&& ((coll->frontType == BIG_SLOPE) || (coll->frontType == DIAGONAL))
|
|
|
|
&& (coll->frontFloor < coll->midFloor)
|
2021-08-22 01:39:14 +03:00
|
|
|
&& (collResult.FloorHeight < coll->frontFloor)
|
2020-12-21 13:16:29 -03:00
|
|
|
&& (coll->frontFloor < 0))
|
|
|
|
{
|
|
|
|
coll->frontFloor = -32767;
|
|
|
|
}
|
|
|
|
else if (coll->slopesArePits
|
|
|
|
&& ((coll->frontType == BIG_SLOPE) || (coll->frontType == DIAGONAL))
|
|
|
|
&& (coll->frontFloor > coll->midFloor))
|
|
|
|
{
|
|
|
|
coll->frontFloor = 512;
|
|
|
|
}
|
|
|
|
else if ((coll->lavaIsPit)
|
|
|
|
&& (coll->frontFloor > 0)
|
2021-08-22 01:39:14 +03:00
|
|
|
&& collResult.Block->Flags.Death)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
coll->frontFloor = 512;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = xPos + xleft;
|
|
|
|
z = zPos + zleft;
|
2021-08-22 01:39:14 +03:00
|
|
|
//short lrRoomNumber = roomNumber;
|
|
|
|
//floor = GetFloor(x, yTop, z, &lrRoomNumber);
|
|
|
|
//
|
|
|
|
//height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x + XFront, yTop, z + ZFront, roomNumber);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftFloor = collResult.FloorHeight;
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->leftCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftType = collResult.HeightType;
|
|
|
|
coll->leftSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->leftSplitCeil = collResult.SplitCeiling;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->leftType == BIG_SLOPE || coll->leftType == DIAGONAL) && coll->leftFloor < 0)
|
|
|
|
coll->leftFloor = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->leftType == BIG_SLOPE || coll->leftType == DIAGONAL) && coll->leftFloor > 0)
|
|
|
|
coll->leftFloor = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->leftFloor > 0 && collResult.Block->Flags.Death)
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->leftFloor = 512;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//
|
|
|
|
//height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftFloor2 = collResult.FloorHeight;
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->leftCeiling2 = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->leftType2 = collResult.HeightType;
|
|
|
|
coll->leftSplitFloor2 = collResult.SplitFloor;
|
|
|
|
coll->leftSplitCeil2 = collResult.SplitCeiling;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->leftType2 == BIG_SLOPE || coll->leftType2 == DIAGONAL) && coll->leftFloor2 < 0)
|
|
|
|
coll->leftFloor2 = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->leftType2 == BIG_SLOPE || coll->leftType2 == DIAGONAL) && coll->leftFloor2 > 0)
|
|
|
|
coll->leftFloor2 = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->leftFloor2 > 0 && collResult.Block->Flags.Death)
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->leftFloor2 = 512;
|
|
|
|
|
|
|
|
x = xPos + xright;
|
|
|
|
z = zPos + zright;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//lrRoomNumber = roomNumber;
|
|
|
|
//floor = GetFloor(x, yTop, z, &lrRoomNumber);
|
|
|
|
//
|
|
|
|
//height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
|
|
|
|
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightFloor = collResult.FloorHeight;
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->rightCeiling = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightType = collResult.HeightType;
|
|
|
|
coll->rightSplitFloor = collResult.SplitFloor;
|
|
|
|
coll->rightSplitCeil = collResult.SplitCeiling;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->rightType == BIG_SLOPE || coll->rightType == DIAGONAL) && coll->rightFloor < 0)
|
|
|
|
coll->rightFloor = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->rightType == BIG_SLOPE || coll->rightType == DIAGONAL) && coll->rightFloor > 0)
|
|
|
|
coll->rightFloor = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->rightFloor > 0 && collResult.Block->Flags.Death)
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->rightFloor = 512;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
//floor = GetFloor(x, yTop, z, &tRoomNumber);
|
|
|
|
//
|
|
|
|
//height = GetFloorHeight(floor, x, yTop, z);
|
|
|
|
collResult = GetCollisionResult(x, yTop, z, roomNumber);
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
if (collResult.FloorHeight != NO_HEIGHT)
|
|
|
|
collResult.FloorHeight -= yPos;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
ceiling = GetCeiling(collResult.Block, x, yTop - LaraItem->fallspeed, z);
|
2020-12-21 13:16:29 -03:00
|
|
|
if (ceiling != NO_HEIGHT)
|
|
|
|
ceiling -= y;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightFloor2 = collResult.FloorHeight;
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->rightCeiling2 = ceiling;
|
2021-08-22 01:39:14 +03:00
|
|
|
coll->rightType2 = collResult.HeightType;
|
|
|
|
coll->rightSplitFloor2 = collResult.SplitFloor;
|
|
|
|
coll->rightSplitCeil2 = collResult.SplitCeiling;
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (coll->slopesAreWalls == 1 && (coll->rightType2 == BIG_SLOPE || coll->rightType2 == DIAGONAL) && coll->rightFloor2 < 0)
|
|
|
|
coll->rightFloor2 = -32767;
|
|
|
|
else if (coll->slopesArePits && (coll->rightType2 == BIG_SLOPE || coll->rightType2 == DIAGONAL) && coll->rightFloor2 > 0)
|
|
|
|
coll->rightFloor2 = 512;
|
2021-08-22 01:39:14 +03:00
|
|
|
else if (coll->lavaIsPit && coll->rightFloor2 > 0 && collResult.Block->Flags.Death)
|
2020-12-21 13:16:29 -03:00
|
|
|
coll->rightFloor2 = 512;
|
|
|
|
|
2021-08-22 01:39:14 +03:00
|
|
|
CollideStaticObjects(coll, xPos, yPos, zPos, roomNumber, objectHeight); // check if bugged with roomNumber insted of tRoomNumber
|
2020-12-21 13:16:29 -03:00
|
|
|
|
|
|
|
if (coll->midFloor == NO_HEIGHT)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->midFloor - coll->midCeiling <= 0)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_CLAMP;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->midCeiling >= 0)
|
|
|
|
{
|
|
|
|
coll->shift.y = coll->midCeiling;
|
|
|
|
coll->collType = CT_TOP;
|
|
|
|
coll->hitCeiling = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((coll->frontFloor > coll->badPos)
|
|
|
|
|| (coll->frontFloor < coll->badNeg)
|
|
|
|
|| (coll->frontCeiling > coll->badCeiling))
|
|
|
|
{
|
|
|
|
if ((coll->frontType == DIAGONAL)
|
|
|
|
|| (coll->frontType == SPLIT_TRI))
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = FindGridShift(zPos + ZFront, zPos);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.x = FindGridShift(xPos + XFront, xPos);
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
coll->collType = CT_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->frontCeiling >= coll->badCeiling)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.y = coll->old.y - yPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
coll->collType = CT_TOP_FRONT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->leftFloor > coll->badPos ||
|
|
|
|
coll->leftFloor < coll->badNeg ||
|
|
|
|
coll->leftCeiling > coll->badCeiling)
|
|
|
|
{
|
|
|
|
if (coll->leftType == SPLIT_TRI && coll->midType == SPLIT_TRI)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = FindGridShift(xPos + xleft, xPos + XFront);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.z = FindGridShift(zPos + zleft, zPos + ZFront);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->leftSplitFloor && coll->leftSplitFloor == coll->midSplitFloor)
|
|
|
|
{
|
|
|
|
int quarter = (unsigned short)(coll->facing) / ANGLE(90); // different from coll->quadrant!
|
|
|
|
quarter %= 2;
|
|
|
|
|
|
|
|
switch (coll->leftSplitFloor)
|
|
|
|
{
|
|
|
|
case SPLIT1:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
if (quarter)
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
break;
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
if (!quarter)
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
coll->collType = CT_LEFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->rightFloor > coll->badPos ||
|
|
|
|
coll->rightFloor < coll->badNeg ||
|
|
|
|
coll->rightCeiling > coll->badCeiling)
|
|
|
|
{
|
|
|
|
if (coll->rightType == SPLIT_TRI && coll->midType == SPLIT_TRI)
|
|
|
|
{
|
|
|
|
coll->shift.x = coll->old.x - xPos;
|
|
|
|
coll->shift.z = coll->old.z - zPos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (coll->quadrant)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
coll->shift.x = FindGridShift(xPos + xright, xPos + XFront);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
case 3:
|
|
|
|
coll->shift.z = FindGridShift(zPos + zright, zPos + ZFront);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->rightSplitFloor && coll->rightSplitFloor == coll->midSplitFloor)
|
|
|
|
{
|
|
|
|
int quarter = (unsigned short)(coll->facing) / ANGLE(90); // different from coll->quadrant!
|
|
|
|
quarter %= 2;
|
|
|
|
|
|
|
|
switch (coll->rightSplitFloor)
|
|
|
|
{
|
|
|
|
case SPLIT1:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
if (quarter)
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
break;
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
if (!quarter)
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
coll->collType = CT_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LaraBaddieCollision(ITEM_INFO* l, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item;
|
|
|
|
OBJECT_INFO* obj;
|
|
|
|
|
|
|
|
l->hitStatus = false;
|
|
|
|
Lara.hitDirection = -1;
|
|
|
|
|
|
|
|
if (l->hitPoints > 0)
|
|
|
|
{
|
|
|
|
short* door, numDoors;
|
|
|
|
short roomsToCheck[128];
|
|
|
|
short numRoomsToCheck = 0;
|
|
|
|
roomsToCheck[numRoomsToCheck++] = l->roomNumber;
|
|
|
|
|
|
|
|
ROOM_INFO* room = &g_Level.Rooms[l->roomNumber];
|
|
|
|
for (int i = 0; i < room->doors.size(); i++)
|
|
|
|
{
|
|
|
|
roomsToCheck[numRoomsToCheck++] = room->doors[i].room;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < numRoomsToCheck; i++)
|
|
|
|
{
|
|
|
|
short itemNumber = g_Level.Rooms[roomsToCheck[i]].itemNumber;
|
|
|
|
while (itemNumber != NO_ITEM)
|
|
|
|
{
|
|
|
|
item = &g_Level.Items[itemNumber];
|
|
|
|
if (item->collidable && item->status != ITEM_INVISIBLE)
|
|
|
|
{
|
|
|
|
obj = &Objects[item->objectNumber];
|
|
|
|
if (obj->collision != nullptr)
|
|
|
|
{
|
|
|
|
int x = l->pos.xPos - item->pos.xPos;
|
|
|
|
int y = l->pos.yPos - item->pos.yPos;
|
|
|
|
int z = l->pos.zPos - item->pos.zPos;
|
|
|
|
|
|
|
|
if (x > -3072 && x < 3072 && z > -3072 && z < 3072 && y > -3072 && y < 3072)
|
|
|
|
obj->collision(itemNumber, l, coll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
itemNumber = item->nextItem;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coll->enableSpaz)
|
|
|
|
{
|
|
|
|
for (int j = 0; j < g_Level.Rooms[roomsToCheck[i]].mesh.size(); j++)
|
|
|
|
{
|
|
|
|
MESH_INFO* mesh = &g_Level.Rooms[roomsToCheck[i]].mesh[j];
|
|
|
|
|
|
|
|
if (mesh->flags & 1)
|
|
|
|
{
|
|
|
|
int x = l->pos.xPos - mesh->x;
|
|
|
|
int y = l->pos.yPos - mesh->y;
|
|
|
|
int z = l->pos.zPos - mesh->z;
|
|
|
|
|
|
|
|
if (x > -3072 && x < 3072 && y > -3072 && y < 3072 && z > -3072 && z < 3072)
|
|
|
|
{
|
|
|
|
PHD_3DPOS pos;
|
|
|
|
pos.xPos = mesh->x;
|
|
|
|
pos.yPos = mesh->y;
|
|
|
|
pos.zPos = mesh->z;
|
|
|
|
pos.yRot = mesh->yRot;
|
|
|
|
|
|
|
|
if (TestBoundsCollideStatic(&StaticObjects[mesh->staticNumber].collisionBox, &pos, coll->radius))
|
|
|
|
ItemPushLaraStatic(l, &StaticObjects[mesh->staticNumber].collisionBox, &pos, coll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mesh++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Lara.hitDirection == -1)
|
|
|
|
Lara.hitFrame = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GenericSphereBoxCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll)
|
|
|
|
{
|
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNum];
|
|
|
|
|
|
|
|
if (item->status != ITEM_INVISIBLE)
|
|
|
|
{
|
|
|
|
if (TestBoundsCollide(item, l, coll->radius))
|
|
|
|
{
|
2021-06-04 06:02:19 +02:00
|
|
|
int collidedBits = TestCollision(item, l);
|
|
|
|
if (collidedBits)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
short oldRot = item->pos.yRot;
|
|
|
|
|
|
|
|
item->pos.yRot = 0;
|
|
|
|
GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity);
|
|
|
|
item->pos.yRot = oldRot;
|
2021-06-04 06:02:19 +02:00
|
|
|
|
|
|
|
int deadlyBits = item->itemFlags[0];
|
2020-12-21 13:16:29 -03:00
|
|
|
SPHERE* sphere = &CreatureSpheres[0];
|
2021-06-04 06:02:19 +02:00
|
|
|
|
|
|
|
if (item->itemFlags[2] != 0)
|
|
|
|
{
|
|
|
|
collidedBits &= ~1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (collidedBits)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
2021-06-04 06:02:19 +02:00
|
|
|
if (collidedBits & 1)
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
GlobalCollisionBounds.X1 = sphere->x - sphere->r - item->pos.xPos;
|
|
|
|
GlobalCollisionBounds.X2 = sphere->x + sphere->r - item->pos.xPos;
|
|
|
|
GlobalCollisionBounds.Y1 = sphere->y - sphere->r - item->pos.yPos;
|
|
|
|
GlobalCollisionBounds.Y2 = sphere->y + sphere->r - item->pos.yPos;
|
|
|
|
GlobalCollisionBounds.Z1 = sphere->z - sphere->r - item->pos.zPos;
|
|
|
|
GlobalCollisionBounds.Z2 = sphere->z + sphere->r - item->pos.zPos;
|
|
|
|
|
|
|
|
int x = l->pos.xPos;
|
|
|
|
int y = l->pos.yPos;
|
|
|
|
int z = l->pos.zPos;
|
|
|
|
|
2021-06-04 06:02:19 +02:00
|
|
|
if (ItemPushLara(item, l, coll, ((deadlyBits & 1) & coll->enableSpaz), 3) && (deadlyBits & 1))
|
2020-12-21 13:16:29 -03:00
|
|
|
{
|
|
|
|
l->hitPoints -= item->itemFlags[3];
|
2021-06-04 06:02:19 +02:00
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
int dx = x - l->pos.xPos;
|
|
|
|
int dy = y - l->pos.yPos;
|
|
|
|
int dz = z - l->pos.zPos;
|
|
|
|
|
2021-06-04 06:02:19 +02:00
|
|
|
if (dx || dy || dz)
|
|
|
|
{
|
|
|
|
if (TriggerActive(item))
|
|
|
|
TriggerLaraBlood();
|
|
|
|
}
|
|
|
|
|
2020-12-21 13:16:29 -03:00
|
|
|
if (!coll->enableBaddiePush)
|
|
|
|
{
|
|
|
|
l->pos.xPos += dx;
|
|
|
|
l->pos.yPos += dy;
|
|
|
|
l->pos.zPos += dz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-04 06:02:19 +02:00
|
|
|
collidedBits >>= 1;
|
|
|
|
deadlyBits >>= 1;
|
2020-12-21 13:16:29 -03:00
|
|
|
sphere++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CalcItemToFloorRotation(ITEM_INFO* item, int radiusDivide)
|
|
|
|
{
|
|
|
|
FLOOR_INFO* floor;
|
|
|
|
BOUNDING_BOX* bounds;
|
|
|
|
GAME_VECTOR pos;
|
|
|
|
int ratioXZ, frontHDif, sideHDif;
|
|
|
|
int frontX, frontZ, leftX, leftZ, rightX, rightZ;
|
|
|
|
int frontHeight, backHeight, leftHeight, rightHeight;
|
|
|
|
int radiusZ, radiusX;
|
|
|
|
|
|
|
|
bounds = GetBoundsAccurate(item);
|
|
|
|
pos.x = item->pos.xPos;
|
|
|
|
pos.y = item->pos.yPos;
|
|
|
|
pos.z = item->pos.zPos;
|
|
|
|
pos.roomNumber = item->roomNumber;
|
|
|
|
radiusX = bounds->X2;
|
|
|
|
radiusZ = bounds->Z2 / radiusDivide; // need divide in any case else it's too much !
|
|
|
|
|
|
|
|
ratioXZ = radiusZ / radiusX;
|
|
|
|
frontX = phd_sin(item->pos.yRot) * radiusZ;
|
|
|
|
frontZ = phd_cos(item->pos.yRot) * radiusZ;
|
|
|
|
leftX = -frontZ * ratioXZ;
|
|
|
|
leftZ = frontX * ratioXZ;
|
|
|
|
rightX = frontZ * ratioXZ;
|
|
|
|
rightZ = -frontX * ratioXZ;
|
|
|
|
|
|
|
|
floor = GetFloor(pos.x + frontX, pos.y, pos.z + frontZ, &pos.roomNumber);
|
|
|
|
frontHeight = GetFloorHeight(floor, pos.x + frontX, pos.y, pos.z + frontZ);
|
|
|
|
floor = GetFloor(pos.x - frontX, pos.y, pos.z - frontZ, &pos.roomNumber);
|
|
|
|
backHeight = GetFloorHeight(floor, pos.x - frontX, pos.y, pos.z - frontZ);
|
|
|
|
floor = GetFloor(pos.x + leftX, pos.y, pos.z + leftZ, &pos.roomNumber);
|
|
|
|
leftHeight = GetFloorHeight(floor, pos.x + leftX, pos.y, pos.z + leftZ);
|
|
|
|
floor = GetFloor(pos.x + rightX, pos.y, pos.z + rightZ, &pos.roomNumber);
|
|
|
|
rightHeight = GetFloorHeight(floor, pos.x + rightX, pos.y, pos.z + rightZ);
|
|
|
|
|
|
|
|
frontHDif = backHeight - frontHeight;
|
|
|
|
sideHDif = rightHeight - leftHeight;
|
|
|
|
// NOTE: float(atan2()) is required, else warning about double !
|
|
|
|
item->pos.xRot = ANGLE(float(atan2(frontHDif, 2 * radiusZ)) / RADIAN);
|
|
|
|
item->pos.zRot = ANGLE(float(atan2(sideHDif, 2 * radiusX)) / RADIAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SnapToQuadrant(short& angle, int interval)
|
|
|
|
{
|
|
|
|
if (abs(angle) <= ANGLE(interval))
|
|
|
|
{
|
|
|
|
angle = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= ANGLE(90 - interval) && angle <= ANGLE(interval + 90))
|
|
|
|
{
|
|
|
|
angle = ANGLE(90);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= ANGLE(180 - interval) || angle <= -ANGLE(180 - interval))
|
|
|
|
{
|
|
|
|
angle = ANGLE(180);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= -ANGLE(interval + 90) && angle <= -ANGLE(90 - interval))
|
|
|
|
{
|
|
|
|
angle = -ANGLE(90);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetQuadrant(short angle)
|
|
|
|
{
|
|
|
|
return (unsigned short) (angle + ANGLE(45)) / ANGLE(90);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SnapToDiagonal(short& angle, int interval)
|
|
|
|
{
|
|
|
|
if (angle >= ANGLE(45 - interval) && angle <= ANGLE(interval + 45))
|
|
|
|
{
|
|
|
|
angle = ANGLE(45);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= ANGLE(135 - interval) && angle <= ANGLE(interval + 135))
|
|
|
|
{
|
|
|
|
angle = ANGLE(135);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= -ANGLE(interval + 135) && angle <= -ANGLE(135 - interval))
|
|
|
|
{
|
|
|
|
angle = -ANGLE(135);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (angle >= -ANGLE(interval + 45) && angle <= -ANGLE(45 - interval))
|
|
|
|
{
|
|
|
|
angle = -ANGLE(45);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector2 GetDiagonalIntersect(int xPos, int zPos, int splitType, int radius, short yRot)
|
|
|
|
{
|
|
|
|
Vector2 vect;
|
|
|
|
|
|
|
|
int dx = (xPos % WALL_SIZE) - WALL_SIZE/2;
|
|
|
|
int dz = (zPos % WALL_SIZE) - WALL_SIZE/2;
|
|
|
|
int xGrid = xPos - dx;
|
|
|
|
int zGrid = zPos - dz;
|
|
|
|
|
|
|
|
switch (splitType)
|
|
|
|
{
|
|
|
|
case SPLIT1:
|
|
|
|
case NOCOLF1T:
|
|
|
|
case NOCOLF1B:
|
|
|
|
xPos = xGrid + (dx - dz) / 2;
|
|
|
|
zPos = zGrid - (dx - dz) / 2;
|
|
|
|
break;
|
|
|
|
case SPLIT2:
|
|
|
|
case NOCOLF2T:
|
|
|
|
case NOCOLF2B:
|
|
|
|
xPos = xGrid + (dx + dz) / 2;
|
|
|
|
zPos = zGrid + (dx + dz) / 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (splitType)
|
|
|
|
{
|
|
|
|
yRot = floor(yRot / 16384.0f) * ANGLE(90) + ANGLE(45);
|
|
|
|
xPos -= int(radius * sin(TO_RAD(yRot)));
|
|
|
|
zPos -= int(radius * cos(TO_RAD(yRot)));
|
|
|
|
}
|
|
|
|
|
|
|
|
vect.x = xPos;
|
|
|
|
vect.y = zPos;
|
|
|
|
|
|
|
|
return vect;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector2 GetOrthogonalIntersect(int xPos, int zPos, int radius, short yRot)
|
|
|
|
{
|
|
|
|
Vector2 vect;
|
|
|
|
|
2021-08-15 18:02:31 -03:00
|
|
|
int xGrid = xPos - (xPos % WALL_SIZE);
|
2020-12-21 13:16:29 -03:00
|
|
|
int zGrid = zPos - (zPos % WALL_SIZE);
|
|
|
|
|
|
|
|
int dir = (unsigned short)(yRot + ANGLE(45)) / ANGLE(90);
|
|
|
|
switch (dir)
|
|
|
|
{
|
|
|
|
case NORTH:
|
|
|
|
zPos = zGrid + (WALL_SIZE - 1) - radius;
|
|
|
|
break;
|
|
|
|
case EAST:
|
|
|
|
xPos = xGrid + (WALL_SIZE - 1) - radius;
|
|
|
|
break;
|
|
|
|
case SOUTH:
|
|
|
|
zPos = zGrid + radius;
|
|
|
|
break;
|
|
|
|
case WEST:
|
2021-08-15 18:02:31 -03:00
|
|
|
xPos = xGrid + radius;
|
2020-12-21 13:16:29 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
vect.x = xPos;
|
|
|
|
vect.y = zPos;
|
|
|
|
|
|
|
|
return vect;
|
|
|
|
}
|