mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-02 09:47:58 +03:00
496 lines
12 KiB
C++
496 lines
12 KiB
C++
#include "framework.h"
|
|
#include "tr5_rollingball.h"
|
|
#include "sphere.h"
|
|
#include "camera.h"
|
|
#include "control.h"
|
|
#include "lara.h"
|
|
#include "setup.h"
|
|
#include "sound.h"
|
|
|
|
void RollingBallCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll)
|
|
{
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
if (TestBoundsCollide(item, l, coll->radius))
|
|
{
|
|
if (TestCollision(item, l))
|
|
{
|
|
if (TriggerActive(item) && (item->itemFlags[0] || item->fallspeed))
|
|
{
|
|
LaraItem->animNumber = LA_BOULDER_DEATH;
|
|
LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase;
|
|
LaraItem->goalAnimState = LS_DEATH;
|
|
LaraItem->currentAnimState = LS_DEATH;
|
|
LaraItem->gravityStatus = false;
|
|
}
|
|
else
|
|
{
|
|
ObjectCollision(itemNumber, l, coll);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void RollingBallControl(short itemNumber)
|
|
{
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
|
|
|
if (!TriggerActive(item))
|
|
return;
|
|
|
|
item->fallspeed += GRAVITY;
|
|
item->pos.xPos += item->itemFlags[0] / 32;
|
|
item->pos.yPos += item->fallspeed;
|
|
item->pos.zPos += item->itemFlags[1] / 32;
|
|
|
|
short roomNumber = item->roomNumber;
|
|
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
int dh = height - 512;
|
|
|
|
if (item->pos.yPos > height - 512)
|
|
{
|
|
if (abs(item->fallspeed) > 16)
|
|
{
|
|
int distance = sqrt(
|
|
SQUARE(Camera.pos.x - item->pos.xPos) +
|
|
SQUARE(Camera.pos.y - item->pos.yPos) +
|
|
SQUARE(Camera.pos.z - item->pos.zPos));
|
|
|
|
if (distance < 16384)
|
|
Camera.bounce = -(((16384 - distance) * abs(item->fallspeed)) / 16384);
|
|
}
|
|
|
|
if (item->pos.yPos - dh < 512)
|
|
item->pos.yPos = dh;
|
|
|
|
if (item->fallspeed <= 64)
|
|
{
|
|
if (abs(item->speed) <= 512 || GetRandomControl() & 0x1F)
|
|
item->fallspeed = 0;
|
|
else
|
|
item->fallspeed = -(short)(GetRandomControl() % (item->speed / 8));
|
|
}
|
|
else
|
|
{
|
|
item->fallspeed = -(short)(item->fallspeed / 4);
|
|
}
|
|
}
|
|
|
|
int x = item->pos.xPos;
|
|
int y = item->pos.yPos;
|
|
int z = item->pos.zPos;
|
|
|
|
floor = GetFloor(x, y, z + 128, &roomNumber);
|
|
int y1a = GetFloorHeight(floor, x, y, z + 128) - 512;
|
|
|
|
floor = GetFloor(x, y, z - 128, &roomNumber);
|
|
int y2a = GetFloorHeight(floor, x, y, z - 128) - 512;
|
|
|
|
floor = GetFloor(x + 128, y, z, &roomNumber);
|
|
int y3a = GetFloorHeight(floor, x + 128, y, z) - 512;
|
|
|
|
floor = GetFloor(x - 128, y, z, &roomNumber);
|
|
int y4a = GetFloorHeight(floor, x - 128, y, z) - 512;
|
|
|
|
floor = GetFloor(x, y, z + 512, &roomNumber);
|
|
int y1b = GetFloorHeight(floor, x, y, z + 512) - 512;
|
|
|
|
floor = GetFloor(x, y, z - 512, &roomNumber);
|
|
int y2b = GetFloorHeight(floor, x, y, z - 512) - 512;
|
|
|
|
floor = GetFloor(x + 512, y, z, &roomNumber);
|
|
int y3b = GetFloorHeight(floor, x + 512, y, z) - 512;
|
|
|
|
floor = GetFloor(x - 512, y, z, &roomNumber);
|
|
int y4b = GetFloorHeight(floor, x - 512, y, z) - 512;
|
|
|
|
if (item->pos.yPos - dh > -256
|
|
|| item->pos.yPos - y1b >= 512
|
|
|| item->pos.yPos - y3b >= 512
|
|
|| item->pos.yPos - y2b >= 512
|
|
|| item->pos.yPos - y4b >= 512)
|
|
{
|
|
int counterZ = 0;
|
|
|
|
if (y1a - dh <= 256)
|
|
{
|
|
if (y1b - dh < -1024 || y1a - dh < -256)
|
|
{
|
|
if (item->itemFlags[1] <= 0)
|
|
{
|
|
if (!item->itemFlags[1] && item->itemFlags[0])
|
|
{
|
|
item->pos.zPos = (item->pos.zPos & -512) + 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[1] = -item->itemFlags[1] / 2;
|
|
item->pos.zPos = (item->pos.zPos & -512) + 512;
|
|
}
|
|
}
|
|
else if (y1a == dh)
|
|
{
|
|
counterZ = 1;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[1] += (y1a - dh) / 2;
|
|
}
|
|
}
|
|
|
|
if (y2a - dh <= 256)
|
|
{
|
|
if (y2b - dh < -1024 || y2a - dh < -256)
|
|
{
|
|
if (item->itemFlags[1] >= 0)
|
|
{
|
|
if (!item->itemFlags[1] && item->itemFlags[0])
|
|
{
|
|
item->pos.zPos = (item->pos.zPos & -512) + 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[1] = -item->itemFlags[1] / 2;
|
|
item->pos.zPos = (item->pos.zPos & -512) + 512;
|
|
}
|
|
}
|
|
else if (y2a == dh)
|
|
{
|
|
counterZ++;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[1] -= (y2a - dh) / 2;
|
|
}
|
|
}
|
|
|
|
if (counterZ == 2)
|
|
{
|
|
if (abs(item->itemFlags[1]) <= 64)
|
|
item->itemFlags[1] = 0;
|
|
else
|
|
item->itemFlags[1] = item->itemFlags[1] - (item->itemFlags[1] / 64);
|
|
}
|
|
|
|
int counterX = 0;
|
|
|
|
if (y4a - dh <= 256)
|
|
{
|
|
if (y4b - dh < -1024 || y4a - dh < -256)
|
|
{
|
|
if (item->itemFlags[0] >= 0)
|
|
{
|
|
if (!item->itemFlags[0] && item->itemFlags[1])
|
|
{
|
|
item->pos.xPos = (item->pos.xPos & -512) + 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[0] = -item->itemFlags[0] / 2;
|
|
item->pos.xPos = (item->pos.xPos & -512) + 512;
|
|
}
|
|
}
|
|
else if (y4a == dh)
|
|
{
|
|
counterX = 1;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[0] -= (y4a - dh) / 2;
|
|
}
|
|
}
|
|
|
|
if (y3a - dh <= 256)
|
|
{
|
|
if (y3b - dh < -1024 || y3a - dh < -256)
|
|
{
|
|
if (item->itemFlags[0] <= 0)
|
|
{
|
|
if (!item->itemFlags[0] && item->itemFlags[1])
|
|
{
|
|
item->pos.xPos = (item->pos.xPos & -512) + 512;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[0] = -item->itemFlags[0] / 2;
|
|
item->pos.xPos = (item->pos.xPos & -512) + 512;
|
|
}
|
|
}
|
|
else if (y3a == dh)
|
|
{
|
|
counterX++;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[0] += (y3a - dh) / 2;
|
|
}
|
|
}
|
|
|
|
if (counterX == 2)
|
|
{
|
|
if (abs(item->itemFlags[0]) <= 64)
|
|
item->itemFlags[0] = 0;
|
|
else
|
|
item->itemFlags[0] = item->itemFlags[0] - (item->itemFlags[0] / 64);
|
|
}
|
|
}
|
|
|
|
GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
|
|
if (item->roomNumber != roomNumber)
|
|
ItemNewRoom(itemNumber, roomNumber);
|
|
|
|
if (item->itemFlags[0] <= 3072)
|
|
{
|
|
if (item->itemFlags[0] < -3072)
|
|
item->itemFlags[0] = -3072;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[0] = 3072;
|
|
}
|
|
|
|
if (item->itemFlags[1] <= 3072)
|
|
{
|
|
if (item->itemFlags[1] < -3072)
|
|
item->itemFlags[1] = -3072;
|
|
}
|
|
else
|
|
{
|
|
item->itemFlags[1] = 3072;
|
|
}
|
|
|
|
short angle = 0;
|
|
|
|
if (item->itemFlags[1] || item->itemFlags[0])
|
|
angle = phd_atan(item->itemFlags[1], item->itemFlags[0]);
|
|
else
|
|
angle = item->pos.yRot;
|
|
|
|
if (item->pos.yRot != angle)
|
|
{
|
|
if (((angle - item->pos.yRot) & 32767) >= 512)
|
|
{
|
|
if (angle <= item->pos.yRot || angle - item->pos.yRot >= 0x8000)
|
|
item->pos.yRot -= 512;
|
|
else
|
|
item->pos.yRot += 512;
|
|
}
|
|
else
|
|
{
|
|
item->pos.yRot = angle;
|
|
}
|
|
}
|
|
|
|
item->pos.xRot -= (abs(item->itemFlags[0]) + abs(item->itemFlags[1])) / 2;
|
|
|
|
roomNumber = item->roomNumber;
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
TestTriggers(TriggerIndex, TRUE, NULL);
|
|
}
|
|
|
|
void ClassicRollingBallCollision(short itemNum, ITEM_INFO* lara, COLL_INFO* coll)
|
|
{
|
|
int x, y, z;
|
|
short d;
|
|
ITEM_INFO* item;
|
|
|
|
item = &g_Level.Items[itemNum];
|
|
|
|
if (item->status == ITEM_ACTIVE)
|
|
{
|
|
if (!TestBoundsCollide(item, lara, coll->radius))
|
|
return;
|
|
if (!TestCollision(item, lara))
|
|
return;
|
|
if (lara->gravityStatus)
|
|
{
|
|
if (coll->enableBaddiePush)
|
|
ItemPushLara(item, lara, coll, coll->enableSpaz, 1);
|
|
lara->hitPoints -= 100;
|
|
x = lara->pos.xPos - item->pos.xPos;
|
|
y = (lara->pos.yPos - 350) - (item->pos.yPos - 512);
|
|
z = lara->pos.zPos - item->pos.zPos;
|
|
d = (short)sqrt(SQUARE(x) + SQUARE(y) + SQUARE(z));
|
|
if (d < 512)
|
|
d = 512;
|
|
x = item->pos.xPos + ((x * 512) / d);
|
|
y = item->pos.yPos - 512 + ((y * 512) / d);
|
|
z = item->pos.zPos + ((z * 512) / d);
|
|
DoBloodSplat(x, y, z, item->speed, item->pos.yRot, item->roomNumber);
|
|
}
|
|
else
|
|
{
|
|
lara->hitStatus = 1;
|
|
if (lara->hitPoints > 0)
|
|
{
|
|
lara->hitPoints = -1;//?
|
|
lara->pos.yRot = item->pos.yRot;
|
|
lara->pos.zPos = 0;
|
|
lara->pos.zRot = 0;
|
|
|
|
lara->animNumber = LA_BOULDER_DEATH;
|
|
lara->frameNumber = g_Level.Anims[lara->animNumber].frameBase;
|
|
lara->currentAnimState = LS_BOULDER_DEATH;
|
|
lara->goalAnimState = LS_BOULDER_DEATH;
|
|
|
|
Camera.flags = CF_FOLLOW_CENTER;
|
|
Camera.targetAngle = ANGLE(170);
|
|
Camera.targetElevation = -ANGLE(25);
|
|
for (int i = 0; i < 15; i++)
|
|
{
|
|
x = lara->pos.xPos + (GetRandomControl() - ANGLE(180) / 256);
|
|
y = lara->pos.yPos - (GetRandomControl() / 64);
|
|
z = lara->pos.zPos + (GetRandomControl() - ANGLE(180) / 256);
|
|
d = ((GetRandomControl() - ANGLE(180) / 8) + item->pos.yRot);
|
|
DoBloodSplat(x, y, z, (short)(item->speed * 2), d, item->roomNumber);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (item->status != ITEM_INVISIBLE)
|
|
ObjectCollision(itemNum, lara, coll);
|
|
|
|
}
|
|
|
|
void ClassicRollingBallControl(short itemNum)
|
|
{
|
|
short x, z, dist, oldx, oldz, roomNum;
|
|
short y1, y2, ydist;
|
|
ITEM_INFO* item;
|
|
FLOOR_INFO* floor;
|
|
GAME_VECTOR* old;
|
|
ROOM_INFO* r;
|
|
|
|
item = &g_Level.Items[itemNum];
|
|
if (item->status == ITEM_ACTIVE)
|
|
{
|
|
if (item->goalAnimState == 2)
|
|
{
|
|
AnimateItem(item);
|
|
return;
|
|
}
|
|
|
|
if (item->pos.yPos < item->floor)
|
|
{
|
|
if (!item->gravityStatus)
|
|
{
|
|
item->gravityStatus = 1;
|
|
item->fallspeed = -10;
|
|
}
|
|
}
|
|
else if (item->currentAnimState == 0)
|
|
item->goalAnimState = 1;
|
|
|
|
oldx = item->pos.xPos;
|
|
oldz = item->pos.zPos;
|
|
AnimateItem(item);
|
|
roomNum = item->roomNumber;
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum);
|
|
if (item->roomNumber != roomNum)
|
|
ItemNewRoom(itemNum, item->roomNumber);
|
|
|
|
item->floor = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
|
|
TestTriggers(TriggerIndex, TRUE, NULL);
|
|
|
|
if (item->pos.yPos >= (int)floor - 256)
|
|
{
|
|
item->gravityStatus = false;
|
|
item->fallspeed = 0;
|
|
item->pos.yPos = item->floor;
|
|
SoundEffect(SFX_TR3_ROLLING_BALL, &item->pos, 0);
|
|
dist = sqrt((SQUARE(Camera.mikePos.x - item->pos.xPos)) + (SQUARE(Camera.mikePos.z - item->pos.zPos)));
|
|
if (dist < 10240)
|
|
Camera.bounce = -40 * (10240 - dist) / 10240;
|
|
}
|
|
|
|
// dist = (item->objectNumber == ID_CLASSIC_ROLLING_BALL) ? 384 : 1024;//huh?
|
|
if (item->objectNumber == ID_CLASSIC_ROLLING_BALL)
|
|
{
|
|
dist = 320;
|
|
ydist = 832;
|
|
}
|
|
else if (item->objectNumber == ID_BIG_ROLLING_BALL)
|
|
{
|
|
dist = 1088;
|
|
ydist = 2112;
|
|
}
|
|
else
|
|
{
|
|
dist = 1024;
|
|
ydist = 1024;
|
|
}
|
|
|
|
x = item->pos.xPos + dist * phd_sin(item->pos.yRot);
|
|
z = item->pos.zPos + dist * phd_cos(item->pos.yRot);
|
|
|
|
floor = GetFloor(x, item->pos.yPos, z, &roomNum);
|
|
y1 = GetFloorHeight(floor, x, item->pos.yPos, z);
|
|
|
|
roomNum = item->roomNumber;
|
|
floor = GetFloor(x, item->pos.yPos - ydist, z, &roomNum);
|
|
y2 = GetCeiling(floor, x, item->pos.yPos - ydist, z);
|
|
|
|
if (y1 < item->pos.yPos || y2 > (item->pos.yPos-ydist)) //there's something wrong here, this if statement returns true, executing this block, deactivating the boulders.
|
|
{
|
|
/*stupid sound crap hardcoded to object # idk*/
|
|
item->status = ITEM_DEACTIVATED;
|
|
item->pos.yPos = item->floor;
|
|
item->pos.xPos = oldx;
|
|
item->pos.zPos = oldz;
|
|
item->speed = 0;
|
|
item->fallspeed = 0;
|
|
item->touchBits = 0;
|
|
}
|
|
}
|
|
else if (item->status == ITEM_DEACTIVATED)
|
|
{
|
|
if (!TriggerActive(item))
|
|
{
|
|
item->status = ITEM_NOT_ACTIVE;
|
|
old = (GAME_VECTOR*)item->data;
|
|
item->pos.xPos = old->x;
|
|
item->pos.yPos = old->y;
|
|
item->pos.zPos = old->z;
|
|
if (item->roomNumber != old->roomNumber)
|
|
{
|
|
RemoveDrawnItem(itemNum);
|
|
r = &g_Level.Rooms[old->roomNumber];
|
|
item->nextItem = r->itemNumber;
|
|
r->itemNumber = itemNum;
|
|
item->roomNumber = old->roomNumber;
|
|
}
|
|
item->currentAnimState = 0;
|
|
item->goalAnimState = 0;
|
|
item->animNumber = Objects[item->objectNumber].animIndex;
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
|
item->currentAnimState = g_Level.Anims[item->animNumber].currentAnimState;
|
|
item->goalAnimState = g_Level.Anims[item->animNumber].currentAnimState;
|
|
item->requiredAnimState = 0;
|
|
RemoveActiveItem(itemNum);
|
|
}
|
|
}
|
|
}
|
|
|
|
void InitialiseClassicRollingBall(short itemNum)
|
|
{
|
|
ITEM_INFO *item;
|
|
GAME_VECTOR* old;
|
|
|
|
item = &g_Level.Items[itemNum];
|
|
old = (GAME_VECTOR *)malloc(sizeof(GAME_VECTOR));
|
|
item->data = (GAME_VECTOR *)malloc(sizeof(GAME_VECTOR));
|
|
|
|
old->x = item->pos.xPos;
|
|
old->y = item->pos.yPos;
|
|
old->z = item->pos.zPos;
|
|
old->roomNumber = item->roomNumber;
|
|
|
|
}
|