TombEngine/TR5Main/Game/Lara/lara_swim.cpp

656 lines
14 KiB
C++
Raw Normal View History

#include "framework.h"
2020-08-09 22:09:14 -03:00
#include "lara_swim.h"
2021-09-19 23:41:26 +03:00
#include "control/control.h"
2019-11-21 07:43:34 +01:00
#include "camera.h"
#include "items.h"
#include "Lara.h"
#include "animation.h"
#include "level.h"
#include "input.h"
2021-09-25 16:00:30 +03:00
#include "Sound/sound.h"
#include "GameFlowScript.h"
2021-09-25 11:27:47 +02:00
struct SUBSUIT_INFO
{
short XRot;
short dXRot;
short XRotVel;
short Vel[2];
short YVel;
};
SUBSUIT_INFO Subsuit;
2019-12-01 08:13:19 +01:00
byte SubHitCount = 0;
2019-11-21 07:43:34 +01:00
2021-02-03 01:50:59 -03:00
void LaraWaterCurrent(COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
if (Lara.currentActive)
{
SINK_INFO* sink = &g_Level.Sinks[Lara.currentActive - 1];
2019-12-01 08:13:19 +01:00
2019-12-02 09:11:21 +01:00
short angle = mGetAngle(sink->x, sink->z, LaraItem->pos.xPos, LaraItem->pos.zPos);
2021-11-10 01:06:40 +11:00
Lara.currentXvel += (sink->strength * 1024 * phd_sin(angle - ANGLE(90.0f)) - Lara.currentXvel) / 16;
Lara.currentZvel += (sink->strength * 1024 * phd_cos(angle - ANGLE(90.0f)) - Lara.currentZvel) / 16;
2019-12-01 08:13:19 +01:00
LaraItem->pos.yPos += (sink->y - LaraItem->pos.yPos) >> 4;
2019-12-01 08:13:19 +01:00
}
else
{
2019-12-02 09:11:21 +01:00
int shift = 0;
2019-12-01 08:13:19 +01:00
if (abs(Lara.currentXvel) <= 16)
shift = (abs(Lara.currentXvel) > 8) + 2;
else
shift = 4;
Lara.currentXvel -= Lara.currentXvel >> shift;
if (abs(Lara.currentXvel) < 4)
Lara.currentXvel = 0;
if (abs(Lara.currentZvel) <= 16)
shift = (abs(Lara.currentZvel) > 8) + 2;
else
shift = 4;
Lara.currentZvel -= Lara.currentZvel >> shift;
if (abs(Lara.currentZvel) < 4)
Lara.currentZvel = 0;
if (!Lara.currentXvel && !Lara.currentZvel)
return;
}
LaraItem->pos.xPos += Lara.currentXvel >> 8;
LaraItem->pos.zPos += Lara.currentZvel >> 8;
2019-12-01 08:13:19 +01:00
Lara.currentActive = 0;
2021-09-10 00:20:59 +03:00
coll->Setup.ForwardAngle = phd_atan(LaraItem->pos.zPos - coll->Setup.OldPosition.z, LaraItem->pos.xPos - coll->Setup.OldPosition.x);
coll->Setup.Height = LARA_HEIGHT_CRAWL;
2019-12-01 08:13:19 +01:00
GetCollisionInfo(coll, LaraItem, PHD_VECTOR(0, 200, 0));
2019-12-01 08:13:19 +01:00
2021-09-10 00:18:47 +03:00
if (coll->CollisionType == CT_FRONT)
2019-12-01 08:13:19 +01:00
{
2021-11-10 01:06:40 +11:00
if (LaraItem->pos.xRot > ANGLE(35.0f))
LaraItem->pos.xRot += ANGLE(1.0f);
else if (LaraItem->pos.xRot < -ANGLE(35.0f))
LaraItem->pos.xRot -= ANGLE(1.0f);
2019-12-22 00:35:48 -03:00
else
LaraItem->fallspeed = 0;
2019-12-01 08:13:19 +01:00
}
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_TOP)
2021-11-10 01:06:40 +11:00
LaraItem->pos.xRot -= ANGLE(1.0f);
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_TOP_FRONT)
2019-12-22 00:35:48 -03:00
LaraItem->fallspeed = 0;
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_LEFT)
2021-11-10 01:06:40 +11:00
LaraItem->pos.yRot += ANGLE(5.0f);
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_RIGHT)
2021-11-10 01:06:40 +11:00
LaraItem->pos.yRot -= ANGLE(5.0f);
2019-12-01 08:13:19 +01:00
2021-09-10 00:18:47 +03:00
if (coll->Middle.Floor < 0 && coll->Middle.Floor != NO_HEIGHT)
LaraItem->pos.yPos += coll->Middle.Floor;
2019-12-01 08:13:19 +01:00
ShiftItem(LaraItem, coll);
2021-09-10 00:20:59 +03:00
coll->Setup.OldPosition.x = LaraItem->pos.xPos;
coll->Setup.OldPosition.y = LaraItem->pos.yPos;
coll->Setup.OldPosition.z = LaraItem->pos.zPos;
2019-11-21 07:43:34 +01:00
}
2021-02-03 01:50:59 -03:00
int GetWaterDepth(int x, int y, int z, short roomNumber)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
FLOOR_INFO* floor;
ROOM_INFO* r = &g_Level.Rooms[roomNumber];
2019-12-01 08:13:19 +01:00
2019-12-02 09:11:21 +01:00
short roomIndex = NO_ROOM;
2019-12-01 08:13:19 +01:00
do
{
2021-09-08 03:01:32 -05:00
int zFloor = (z - r->z) / SECTOR(1);
int xFloor = (x - r->x) / SECTOR(1);
2019-12-01 08:13:19 +01:00
if (zFloor <= 0)
{
zFloor = 0;
if (xFloor < 1)
xFloor = 1;
2021-11-08 17:28:04 +03:00
else if (xFloor > r->xSize - 2)
xFloor = r->xSize - 2;
2019-12-01 08:13:19 +01:00
}
2021-11-08 17:28:04 +03:00
else if (zFloor >= r->zSize - 1)
2019-12-01 08:13:19 +01:00
{
2021-11-08 17:28:04 +03:00
zFloor = r->zSize - 1;
2019-12-01 08:13:19 +01:00
if (xFloor < 1)
xFloor = 1;
2021-11-08 17:28:04 +03:00
else if (xFloor > r->xSize - 2)
xFloor = r->xSize - 2;
2019-12-01 08:13:19 +01:00
}
else if (xFloor < 0)
xFloor = 0;
2021-11-08 17:28:04 +03:00
else if (xFloor >= r->xSize)
xFloor = r->xSize - 1;
2019-12-01 08:13:19 +01:00
2021-11-08 17:28:04 +03:00
floor = &r->floor[zFloor + xFloor * r->zSize];
2021-09-11 22:41:25 +03:00
roomIndex = floor->WallPortal;
2019-12-01 08:13:19 +01:00
if (roomIndex != NO_ROOM)
{
roomNumber = roomIndex;
r = &g_Level.Rooms[roomIndex];
2019-12-01 08:13:19 +01:00
}
} while (roomIndex != NO_ROOM);
2021-11-07 04:54:48 +03:00
if (r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
2019-12-01 08:13:19 +01:00
{
2021-11-08 17:48:57 +03:00
while (floor->RoomAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM)
2019-12-01 08:13:19 +01:00
{
2021-11-08 17:48:57 +03:00
r = &g_Level.Rooms[floor->RoomAbove(x, y, z).value_or(floor->Room)];
if (!(r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP)))
2019-12-01 08:13:19 +01:00
{
2021-09-14 13:41:29 +03:00
int wh = floor->CeilingHeight(x, z);
2019-12-01 08:13:19 +01:00
floor = GetFloor(x, y, z, &roomNumber);
return (GetFloorHeight(floor, x, y, z) - wh);
}
2021-09-17 16:07:53 +03:00
floor = GetSector(r, x - r->x, z - r->z);
2019-12-01 08:13:19 +01:00
}
2021-09-18 01:32:48 +03:00
return DEEP_WATER;
2019-12-01 08:13:19 +01:00
}
else
{
2021-11-08 17:48:57 +03:00
while (floor->RoomBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM)
2019-12-01 08:13:19 +01:00
{
2021-11-08 17:48:57 +03:00
r = &g_Level.Rooms[floor->RoomBelow(x, y, z).value_or(floor->Room)];
if (r->flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP))
2019-12-01 08:13:19 +01:00
{
2021-09-14 13:41:29 +03:00
int wh = floor->FloorHeight(x, z);
2019-12-01 08:13:19 +01:00
floor = GetFloor(x, y, z, &roomNumber);
return (GetFloorHeight(floor, x, y, z) - wh);
}
2021-09-17 16:07:53 +03:00
floor = GetSector(r, x - r->x, z - r->z);
2019-12-01 08:13:19 +01:00
}
2021-09-18 01:32:48 +03:00
2019-12-01 08:13:19 +01:00
return NO_HEIGHT;
}
2019-11-21 07:43:34 +01:00
}
2021-02-03 01:50:59 -03:00
void lara_col_waterroll(ITEM_INFO* item, COLL_INFO* coll)
{
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_uwdeath(ITEM_INFO* item, COLL_INFO* coll)
{
item->hitPoints = -1;
Lara.air = -1;
Lara.gunStatus = LG_HANDS_BUSY;
2021-11-10 01:06:40 +11:00
auto waterHeight = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
if (waterHeight < (item->pos.yPos - (STEP_SIZE / 5 * 2) - 2) &&
waterHeight != NO_HEIGHT)
{
2021-11-10 01:06:40 +11:00
item->pos.yPos -= 5;
}
2021-11-10 01:06:40 +11:00
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_dive(ITEM_INFO* item, COLL_INFO* coll)
{
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_tread(ITEM_INFO* item, COLL_INFO* coll)
{
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_glide(ITEM_INFO* item, COLL_INFO* coll)
{
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_swim(ITEM_INFO* item, COLL_INFO* coll)
{
LaraSwimCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_as_waterroll(ITEM_INFO* item, COLL_INFO* coll)
{
item->fallspeed = 0;
}
2021-02-03 01:50:59 -03:00
void lara_as_uwdeath(ITEM_INFO* item, COLL_INFO* coll)
{
Lara.look = 0;
item->fallspeed -= 8;
if (item->fallspeed <= 0)
item->fallspeed = 0;
2021-11-10 01:06:40 +11:00
if (item->pos.xRot < -ANGLE(2.0f) ||
item->pos.xRot > ANGLE(2.0f))
{
if (item->pos.xRot >= 0)
2021-11-10 01:06:40 +11:00
item->pos.xRot -= ANGLE(2.0f);
else
2021-11-10 01:06:40 +11:00
item->pos.xRot += ANGLE(2.0f);
}
else
item->pos.xRot = 0;
}
2021-02-03 01:50:59 -03:00
void lara_as_dive(ITEM_INFO* item, COLL_INFO* coll)
{
if (TrInput & IN_FORWARD)
2021-11-10 01:06:40 +11:00
item->pos.xRot -= ANGLE(1.0f);
}
2021-02-03 01:50:59 -03:00
void lara_as_tread(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2021-11-10 01:06:40 +11:00
return;
}
if (TrInput & IN_ROLL && LaraDrawType != LARA_TYPE::DIVESUIT)
{
item->animNumber = LA_UNDERWATER_ROLL_180_START;
2021-11-10 01:06:40 +11:00
item->frameNumber = GF(LA_UNDERWATER_ROLL_180_START, 0);
item->currentAnimState = LS_UNDERWATER_ROLL;
}
else
{
if (TrInput & IN_LOOK)
LookUpDown();
if (LaraDrawType == LARA_TYPE::DIVESUIT)
SwimTurnSubsuit(item);
else
SwimTurn(item);
if (TrInput & IN_JUMP)
item->goalAnimState = LS_UNDERWATER_FORWARD;
item->fallspeed -= 6;
if (item->fallspeed < 0)
item->fallspeed = 0;
if (Lara.gunStatus == LG_HANDS_BUSY)
Lara.gunStatus = LG_NO_ARMS;
}
}
2021-02-03 01:50:59 -03:00
void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2021-11-10 01:06:40 +11:00
return;
}
if (TrInput & IN_ROLL)
{
if (LaraDrawType != LARA_TYPE::DIVESUIT)
{
item->animNumber = LA_UNDERWATER_ROLL_180_START;
2021-11-10 01:06:40 +11:00
item->frameNumber = GF(LA_UNDERWATER_ROLL_180_START, 0);
item->currentAnimState = LS_UNDERWATER_ROLL;
return;
}
}
else if (LaraDrawType != LARA_TYPE::DIVESUIT)
SwimTurn(item);
else
SwimTurnSubsuit(item);
if (TrInput & IN_JUMP)
item->goalAnimState = LS_UNDERWATER_FORWARD;
item->fallspeed -= 6;
if (item->fallspeed < 0)
item->fallspeed = 0;
if (item->fallspeed <= 133)
item->goalAnimState = LS_UNDERWATER_STOP;
}
2021-02-03 01:50:59 -03:00
void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2021-11-10 01:06:40 +11:00
return;
}
if (TrInput & IN_ROLL)
{
if (LaraDrawType != LARA_TYPE::DIVESUIT)
{
item->animNumber = LA_UNDERWATER_ROLL_180_START;
2021-11-10 01:06:40 +11:00
item->frameNumber = GF(LA_UNDERWATER_ROLL_180_START, 0);
item->currentAnimState = LS_UNDERWATER_ROLL;
return;
}
}
else if (LaraDrawType != LARA_TYPE::DIVESUIT)
SwimTurn(item);
else
SwimTurnSubsuit(item);
item->fallspeed += 8;
if (item->fallspeed > 200)
item->fallspeed = 200;
if (!(TrInput & IN_JUMP))
item->goalAnimState = LS_UNDERWATER_INERTIA;
}
2021-02-03 01:50:59 -03:00
void UpdateSubsuitAngles()
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
if (Subsuit.YVel != 0)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
LaraItem->pos.yPos += Subsuit.YVel / 4;
Subsuit.YVel = ceil(0.9375 * Subsuit.YVel - 1); // YVel * (15/16)
2019-11-21 07:43:34 +01:00
}
2019-12-01 08:13:19 +01:00
Subsuit.Vel[0] = Subsuit.Vel[1] = -4 * LaraItem->fallspeed;
2019-11-21 07:43:34 +01:00
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot >= Subsuit.dXRot)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot > Subsuit.dXRot)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot > 0 && Subsuit.dXRot < 0)
Subsuit.XRot = ceil(0.75 * Subsuit.XRot);
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
Subsuit.XRot -= ANGLE(2.0f);
2019-11-21 07:43:34 +01:00
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot < Subsuit.dXRot)
Subsuit.XRot = Subsuit.dXRot;
2019-11-21 07:43:34 +01:00
}
}
else
{
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot < 0 && Subsuit.dXRot > 0)
Subsuit.XRot = ceil(0.75 * Subsuit.XRot);
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
Subsuit.XRot += ANGLE(2.0f);
2019-11-21 07:43:34 +01:00
2019-12-01 08:13:19 +01:00
if (Subsuit.XRot > Subsuit.dXRot)
Subsuit.XRot = Subsuit.dXRot;
2019-11-21 07:43:34 +01:00
}
2019-12-01 08:13:19 +01:00
if (Subsuit.dXRot != 0)
2019-11-21 07:43:34 +01:00
{
short rot = Subsuit.dXRot >> 3;
2021-11-10 01:06:40 +11:00
if (rot < -ANGLE(2.0f))
rot = -ANGLE(2.0f);
else if (rot > ANGLE(2.0f))
rot = ANGLE(2.0f);
2019-12-01 08:13:19 +01:00
LaraItem->pos.xRot += rot;
2019-11-21 07:43:34 +01:00
}
Subsuit.Vel[0] += abs(Subsuit.XRot >> 3);
Subsuit.Vel[1] += abs(Subsuit.XRot >> 3);
2019-11-21 07:43:34 +01:00
if (Lara.turnRate > 0)
{
2019-12-01 08:13:19 +01:00
Subsuit.Vel[0] += 2 * abs(Lara.turnRate);
2019-11-21 07:43:34 +01:00
}
else if (Lara.turnRate < 0)
{
2019-12-01 08:13:19 +01:00
Subsuit.Vel[1] += 2 * abs(Lara.turnRate);
2019-11-21 07:43:34 +01:00
}
2019-12-01 08:13:19 +01:00
if (Subsuit.Vel[0] > 1536)
Subsuit.Vel[0] = 1536;
2019-11-21 07:43:34 +01:00
2019-12-01 08:13:19 +01:00
if (Subsuit.Vel[1] > 1536)
Subsuit.Vel[1] = 1536;
2019-11-21 07:43:34 +01:00
2019-12-01 08:13:19 +01:00
if (Subsuit.Vel[0] != 0 || Subsuit.Vel[1] != 0)
2019-11-21 07:43:34 +01:00
{
SoundEffect(SFX_TR5_LARA_UNDERWATER_ENGINE, &LaraItem->pos, (((Subsuit.Vel[0] + Subsuit.Vel[1]) * 4) & 0x1F00) + 10);
2019-11-21 07:43:34 +01:00
}
}
2021-02-03 01:50:59 -03:00
void SwimTurnSubsuit(ITEM_INFO* item)
2019-11-21 07:43:34 +01:00
{
if (item->pos.yPos < 14080)
Subsuit.YVel += (14080 - item->pos.yPos) >> 4;
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
if (TrInput & IN_FORWARD && item->pos.xRot > -ANGLE(85.0f))
Subsuit.dXRot = -ANGLE(45.0f);
else if (TrInput & IN_BACK && item->pos.xRot < ANGLE(85.0f))
Subsuit.dXRot = ANGLE(45.0f);
2019-11-21 07:43:34 +01:00
else
2019-12-01 08:13:19 +01:00
Subsuit.dXRot = 0;
2019-11-21 07:43:34 +01:00
if (TrInput & IN_LEFT)
{
2021-11-10 01:06:40 +11:00
Lara.turnRate -= SUB_SUIT_TURN_RATE;
if (Lara.turnRate < -LARA_MED_TURN)
Lara.turnRate = -LARA_MED_TURN;
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
item->pos.zRot -= LARA_LEAN_RATE * 2;
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
2021-11-10 01:06:40 +11:00
Lara.turnRate += SUB_SUIT_TURN_RATE;
if (Lara.turnRate > LARA_MED_TURN)
Lara.turnRate = LARA_MED_TURN;
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
item->pos.zRot += LARA_LEAN_RATE * 2;
2019-11-21 07:43:34 +01:00
}
}
2021-02-03 01:50:59 -03:00
void SwimTurn(ITEM_INFO* item)
2019-11-21 07:43:34 +01:00
{
if (TrInput & IN_FORWARD)
2021-11-10 01:06:40 +11:00
item->pos.xRot -= ANGLE(2.0f);
2019-11-21 07:43:34 +01:00
else if (TrInput & IN_BACK)
2021-11-10 01:06:40 +11:00
item->pos.xRot += ANGLE(2.0f);
2019-11-21 07:43:34 +01:00
if (TrInput & IN_LEFT)
{
2021-11-10 01:06:40 +11:00
Lara.turnRate -= LARA_TURN_RATE;
if (Lara.turnRate < -LARA_MED_TURN)
Lara.turnRate = -LARA_MED_TURN;
item->pos.zRot -= LARA_LEAN_RATE * 2;
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
2021-11-10 01:06:40 +11:00
Lara.turnRate += LARA_TURN_RATE;
if (Lara.turnRate > LARA_MED_TURN)
Lara.turnRate = LARA_MED_TURN;
item->pos.zRot += LARA_LEAN_RATE * 2;
2019-11-21 07:43:34 +01:00
}
}
2021-02-03 01:50:59 -03:00
void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2019-12-02 09:11:21 +01:00
int oldX = item->pos.xPos;
int oldY = item->pos.yPos;
int oldZ = item->pos.zPos;
short oldXrot = item->pos.xRot;
short oldYrot = item->pos.yRot;
short oldZrot = item->pos.zRot;
2019-12-01 08:13:19 +01:00
2021-11-10 01:06:40 +11:00
if (item->pos.xRot < -ANGLE(90.0f) ||
item->pos.xRot > ANGLE(90.0f))
2019-12-01 08:13:19 +01:00
{
2021-11-10 01:06:40 +11:00
Lara.moveAngle = item->pos.yRot + ANGLE(180.0f);
coll->Setup.ForwardAngle = item->pos.yRot - ANGLE(180.0f);
2019-12-01 08:13:19 +01:00
}
else
{
Lara.moveAngle = item->pos.yRot;
2021-09-10 00:20:59 +03:00
coll->Setup.ForwardAngle = item->pos.yRot;
2019-12-01 08:13:19 +01:00
}
int height = LARA_HEIGHT * phd_sin(item->pos.xRot);
2019-12-12 22:06:57 +01:00
height = abs(height);
if (height < ((LaraDrawType == LARA_TYPE::DIVESUIT) << 6) + 200)
height = ((LaraDrawType == LARA_TYPE::DIVESUIT) << 6) + 200;
2021-11-10 01:06:40 +11:00
coll->Setup.BadHeightUp = -(STEP_SIZE / 4);
coll->Setup.Height = height;
GetCollisionInfo(coll, item, PHD_VECTOR(0, height / 2, 0));
auto c1 = *coll;
2021-11-10 01:06:40 +11:00
c1.Setup.ForwardAngle += ANGLE(45.0f);
GetCollisionInfo(&c1, item, PHD_VECTOR(0, height / 2, 0));
auto c2 = *coll;
2021-11-10 01:06:40 +11:00
c2.Setup.ForwardAngle -= ANGLE(45.0f);
GetCollisionInfo(&c2, item, PHD_VECTOR(0, height / 2, 0));
2019-12-01 08:13:19 +01:00
ShiftItem(item, coll);
2019-12-02 09:11:21 +01:00
int flag = 0;
2019-12-01 08:13:19 +01:00
2021-09-10 00:18:47 +03:00
switch (coll->CollisionType)
2019-12-01 08:13:19 +01:00
{
case CT_FRONT:
2021-11-10 01:06:40 +11:00
if (item->pos.xRot <= ANGLE(25.0f))
2019-12-01 08:13:19 +01:00
{
2021-11-10 01:06:40 +11:00
if (item->pos.xRot >= -ANGLE(25.0f))
2019-12-01 08:13:19 +01:00
{
2021-11-10 01:06:40 +11:00
if (item->pos.xRot > ANGLE(5.0f))
item->pos.xRot += ANGLE(0.5f);
else if (item->pos.xRot < -ANGLE(5.0f))
item->pos.xRot -= ANGLE(0.5f);
2019-12-01 08:13:19 +01:00
else if (item->pos.xRot > 0)
item->pos.xRot += 45;
else if (item->pos.xRot < 0)
item->pos.xRot -= 45;
else
{
item->fallspeed = 0;
flag = 1;
}
}
else
{
2021-11-10 01:06:40 +11:00
item->pos.xRot -= ANGLE(1.0f);
2019-12-01 08:13:19 +01:00
flag = 1;
}
}
else
{
2021-11-10 01:06:40 +11:00
item->pos.xRot += ANGLE(1.0f);
2019-12-01 08:13:19 +01:00
flag = 1;
}
2021-09-10 00:18:47 +03:00
if (c1.CollisionType == CT_LEFT)
2021-11-10 01:06:40 +11:00
item->pos.yRot += ANGLE(2.0f);
2021-09-10 00:18:47 +03:00
else if (c1.CollisionType == CT_RIGHT)
2021-11-10 01:06:40 +11:00
item->pos.yRot -= ANGLE(2.0f);
2021-09-10 00:18:47 +03:00
else if (c2.CollisionType == CT_LEFT)
2021-11-10 01:06:40 +11:00
item->pos.yRot += ANGLE(2.0f);
2021-09-10 00:18:47 +03:00
else if (c2.CollisionType == CT_RIGHT)
2021-11-10 01:06:40 +11:00
item->pos.yRot -= ANGLE(2.0f);
2019-12-01 08:13:19 +01:00
break;
2019-12-12 22:06:57 +01:00
2019-12-01 08:13:19 +01:00
case CT_TOP:
2019-12-12 22:06:57 +01:00
if (item->pos.xRot >= -8190)
2019-12-01 08:13:19 +01:00
{
flag = 1;
2021-11-10 01:06:40 +11:00
item->pos.xRot -= ANGLE(1.0f);
2019-12-01 08:13:19 +01:00
}
2021-11-10 01:06:40 +11:00
2019-12-01 08:13:19 +01:00
break;
2019-12-12 22:06:57 +01:00
2019-12-01 08:13:19 +01:00
case CT_TOP_FRONT:
item->fallspeed = 0;
flag = 1;
2021-11-10 01:06:40 +11:00
2019-12-01 08:13:19 +01:00
break;
2019-12-12 22:06:57 +01:00
2019-12-01 08:13:19 +01:00
case CT_LEFT:
2021-11-10 01:06:40 +11:00
item->pos.yRot += ANGLE(2.0f);
2019-12-01 08:13:19 +01:00
flag = 1;
2021-11-10 01:06:40 +11:00
2019-12-01 08:13:19 +01:00
break;
2019-12-12 22:06:57 +01:00
2019-12-01 08:13:19 +01:00
case CT_RIGHT:
2021-11-10 01:06:40 +11:00
item->pos.yRot -= ANGLE(2.0f);
2019-12-01 08:13:19 +01:00
flag = 1;
2021-11-10 01:06:40 +11:00
2019-12-01 08:13:19 +01:00
break;
2019-12-12 22:06:57 +01:00
2019-12-01 08:13:19 +01:00
case CT_CLAMP:
flag = 2;
2021-09-10 00:20:59 +03:00
item->pos.xPos = coll->Setup.OldPosition.x;
item->pos.yPos = coll->Setup.OldPosition.y;
item->pos.zPos = coll->Setup.OldPosition.z;
2019-12-01 08:13:19 +01:00
item->fallspeed = 0;
2021-11-10 01:06:40 +11:00
2019-12-01 08:13:19 +01:00
break;
}
2021-09-10 00:18:47 +03:00
if (coll->Middle.Floor < 0 && coll->Middle.Floor != NO_HEIGHT)
2019-12-01 08:13:19 +01:00
{
flag = 1;
2021-11-10 01:06:40 +11:00
item->pos.xRot += ANGLE(1.0f);
2021-09-10 00:18:47 +03:00
item->pos.yPos += coll->Middle.Floor;
2019-12-01 08:13:19 +01:00
}
2021-11-10 01:06:40 +11:00
if (oldX == item->pos.xPos &&
oldY == item->pos.yPos &&
oldZ == item->pos.zPos &&
oldXrot == item->pos.xRot &&
oldYrot == item->pos.yRot ||
flag != 1)
2019-12-01 08:13:19 +01:00
{
2019-12-12 22:06:57 +01:00
if (flag == 2)
2019-12-01 08:13:19 +01:00
return;
}
if (Lara.waterStatus != LW_FLYCHEAT && Lara.ExtraAnim == NO_ITEM)
2021-11-10 01:06:40 +11:00
TestLaraWaterDepth(item, coll);
2019-11-21 07:43:34 +01:00
}
2021-11-10 01:06:40 +11:00
void TestLaraWaterDepth(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2019-12-02 09:11:21 +01:00
short roomNumber = item->roomNumber;
2019-12-01 08:13:19 +01:00
FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber);
2021-11-10 01:06:40 +11:00
int waterDepth = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, roomNumber);
2019-11-21 07:43:34 +01:00
2021-11-10 01:06:40 +11:00
if (waterDepth == NO_HEIGHT)
2019-11-21 07:43:34 +01:00
{
2019-12-01 08:13:19 +01:00
item->fallspeed = 0;
2021-09-10 00:20:59 +03:00
item->pos.xPos = coll->Setup.OldPosition.x;
item->pos.yPos = coll->Setup.OldPosition.y;
item->pos.zPos = coll->Setup.OldPosition.z;
2019-11-21 07:43:34 +01:00
}
2021-09-14 02:37:56 +03:00
// Height check was at STEP_SIZE * 2 before but changed to this
// because now Lara surfaces on a head level, not mid-body level.
2021-11-10 01:06:40 +11:00
if (waterDepth <= LARA_HEIGHT - LARA_HEADROOM / 2)
2019-11-21 07:43:34 +01:00
{
item->animNumber = LA_UNDERWATER_TO_STAND;
2021-11-10 01:06:40 +11:00
item->frameNumber = GF(LA_UNDERWATER_TO_STAND, 0);
item->currentAnimState = LS_ONWATER_EXIT;
item->goalAnimState = LS_STOP;
2019-11-21 07:43:34 +01:00
item->pos.zRot = 0;
item->pos.xRot = 0;
item->speed = 0;
item->fallspeed = 0;
2019-12-01 08:13:19 +01:00
item->gravityStatus = false;
Lara.waterStatus = LW_WADE;
item->pos.yPos = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
}
}