TombEngine/TR5Main/Objects/TR5/Object/tr5_rollingball.cpp
2020-10-17 23:36:06 -05:00

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;
}