TombEngine/TR5Main/Game/Lara/lara_surface.cpp

503 lines
11 KiB
C++
Raw Normal View History

#include "framework.h"
2020-08-09 22:09:14 -03:00
#include "lara_surface.h"
#include "lara_tests.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 "collide.h"
#include "items.h"
#include "Lara.h"
#include "level.h"
#include "input.h"
2021-09-25 11:27:47 +02:00
bool EnableCrawlFlexWaterPullUp, EnableCrawlFlexSubmerged;
2019-11-21 07:43:34 +01:00
void lara_col_surftread(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
if (item->goalAnimState == LS_UNDERWATER_FORWARD)
2019-11-21 07:43:34 +01:00
{
item->currentAnimState = LS_DIVE;
item->animNumber = LA_ONWATER_DIVE;
item->pos.xRot = -8190;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
2019-11-21 07:43:34 +01:00
item->fallspeed = 80;
Lara.waterStatus = LW_UNDERWATER;
}
Lara.moveAngle = item->pos.yRot;
2019-11-21 07:43:34 +01:00
LaraSurfaceCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_surfright(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
Lara.moveAngle = item->pos.yRot + ANGLE(90);
2019-11-21 07:43:34 +01:00
LaraSurfaceCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_surfleft(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
Lara.moveAngle = item->pos.yRot - ANGLE(90);
2019-11-21 07:43:34 +01:00
LaraSurfaceCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_surfback(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
Lara.moveAngle = item->pos.yRot + ANGLE(180);
2019-11-21 07:43:34 +01:00
LaraSurfaceCollision(item, coll);
}
2021-02-03 01:50:59 -03:00
void lara_col_surfswim(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2021-09-19 17:48:32 +03:00
coll->Setup.BadHeightUp = -STEPUP_HEIGHT;
Lara.moveAngle = item->pos.yRot;
2019-11-21 07:43:34 +01:00
LaraSurfaceCollision(item, coll);
LaraTestWaterClimbOut(item, coll);
LaraTestLadderClimbOut(item, coll);
2019-11-21 07:43:34 +01:00
}
2021-02-03 01:50:59 -03:00
void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
item->fallspeed -= 4;
if (item->fallspeed < 0)
item->fallspeed = 0;
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2019-11-21 07:43:34 +01:00
return;
}
if (TrInput & IN_LOOK)
{
LookUpDown();
return;
}
if (TrInput & IN_LEFT)
{
item->pos.yRot -= ANGLE(4);
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
item->pos.yRot += ANGLE(4);
2019-11-21 07:43:34 +01:00
}
if (TrInput & IN_FORWARD)
{
item->goalAnimState = LS_ONWATER_FORWARD;
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_BACK)
{
item->goalAnimState = LS_ONWATER_BACK;
2019-11-21 07:43:34 +01:00
}
if (TrInput & IN_LSTEP)
{
item->goalAnimState = LS_ONWATER_LEFT;
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RSTEP)
{
item->goalAnimState = LS_ONWATER_RIGHT;
2019-11-21 07:43:34 +01:00
}
if (TrInput & IN_JUMP)
{
2019-12-05 07:23:30 +01:00
Lara.diveCount++;
if (Lara.diveCount == 10)
item->goalAnimState = LS_UNDERWATER_FORWARD;
2019-11-21 07:43:34 +01:00
}
else
{
Lara.diveCount = 0;
}
}
2021-02-03 01:50:59 -03:00
void lara_as_surfright(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2019-11-21 07:43:34 +01:00
return;
}
Lara.diveCount = 0;
if (TrInput & IN_LEFT)
{
item->pos.yRot -= ANGLE(2);
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
item->pos.yRot += ANGLE(2);
2019-11-21 07:43:34 +01:00
}
if (!(TrInput & IN_RSTEP))
{
item->goalAnimState = LS_ONWATER_STOP;
2019-11-21 07:43:34 +01:00
}
item->fallspeed += 8;
if (item->fallspeed > 60)
item->fallspeed = 60;
}
2021-02-03 01:50:59 -03:00
void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2019-11-21 07:43:34 +01:00
return;
}
Lara.diveCount = 0;
if (TrInput & IN_LEFT)
{
item->pos.yRot -= ANGLE(2);
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
item->pos.yRot += ANGLE(2);
2019-11-21 07:43:34 +01:00
}
if (!(TrInput & IN_LSTEP))
{
item->goalAnimState = LS_ONWATER_STOP;
2019-11-21 07:43:34 +01:00
}
item->fallspeed += 8;
if (item->fallspeed > 60)
item->fallspeed = 60;
}
2021-02-03 01:50:59 -03:00
void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2019-11-21 07:43:34 +01:00
return;
}
Lara.diveCount = 0;
if (TrInput & IN_LEFT)
{
item->pos.yRot -= ANGLE(2);
2019-11-21 07:43:34 +01:00
}
else if (TrInput & IN_RIGHT)
{
item->pos.yRot += ANGLE(2);
2019-11-21 07:43:34 +01:00
}
if (!(TrInput & IN_BACK))
{
item->goalAnimState = LS_ONWATER_STOP;
2019-11-21 07:43:34 +01:00
}
item->fallspeed += 8;
if (item->fallspeed > 60)
item->fallspeed = 60;
}
2021-02-03 01:50:59 -03:00
void lara_as_surfswim(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_WATER_DEATH;
2019-11-21 07:43:34 +01:00
return;
}
Lara.diveCount = 0;
if (TrInput & IN_LEFT)
{
item->pos.yRot -= ANGLE(4);
}
else if (TrInput & IN_RIGHT)
{
item->pos.yRot += ANGLE(4);
}
if (!(TrInput & IN_FORWARD))
item->goalAnimState = LS_ONWATER_STOP;
2019-11-21 07:43:34 +01:00
if (TrInput & IN_JUMP)
item->goalAnimState = LS_ONWATER_STOP;
2019-11-21 07:43:34 +01:00
item->fallspeed += 8;
if (item->fallspeed > 60)
item->fallspeed = 60;
}
2021-02-03 01:50:59 -03:00
void LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2021-09-10 00:20:59 +03:00
coll->Setup.ForwardAngle = Lara.moveAngle;
2019-11-21 07:43:34 +01:00
GetCollisionInfo(coll, item, PHD_VECTOR(0, 700, 0));
2019-11-21 07:43:34 +01:00
ShiftItem(item, coll);
2021-09-10 00:18:47 +03:00
if (coll->CollisionType & (CT_FRONT | CT_TOP | CT_TOP_FRONT | CT_CLAMP) ||
coll->Middle.Floor < 0 && coll->Middle.Slope)
2019-11-21 07:43:34 +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-10 00:18:47 +03:00
else if (coll->CollisionType == CT_LEFT)
2019-11-21 07:43:34 +01:00
{
item->pos.yRot += ANGLE(5);
2019-11-21 07:43:34 +01:00
}
2021-09-10 00:18:47 +03:00
else if (coll->CollisionType == CT_RIGHT)
2019-11-21 07:43:34 +01:00
{
item->pos.yRot -= ANGLE(5);
2019-11-21 07:43:34 +01:00
}
if (GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber) - item->pos.yPos > -100)
{
LaraTestWaterStepOut(item, coll);
}
else
{
item->goalAnimState = LS_UNDERWATER_FORWARD;
item->currentAnimState = LS_DIVE;
item->animNumber = LA_ONWATER_DIVE;
item->pos.xRot = -8190;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
2019-11-21 07:43:34 +01:00
item->fallspeed = 80;
Lara.waterStatus = LW_UNDERWATER;
}
}
2021-02-03 01:50:59 -03:00
int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2021-09-10 00:18:47 +03:00
if (coll->CollisionType != CT_FRONT || !(TrInput & IN_ACTION))
return 0;
2019-11-21 07:43:34 +01:00
// FOR DEBUG PURPOSES UNTIL SCRIPTING IS READY-
EnableCrawlFlexWaterPullUp = false;
EnableCrawlFlexSubmerged = false;
if (Lara.gunStatus && (Lara.gunStatus != LG_READY || Lara.gunType != WEAPON_FLARE))
return 0;
2019-11-21 07:43:34 +01:00
if (coll->Middle.Ceiling > -STEPUP_HEIGHT)
return 0;
2019-11-21 07:43:34 +01:00
if (coll->ObjectHeadroom < (EnableCrawlFlexWaterPullUp ? LARA_HEIGHT_CRAWL : LARA_HEIGHT))
return 0;
2021-09-10 00:18:47 +03:00
int frontFloor = coll->Front.Floor + 700;
int frontCeiling = coll->Front.Ceiling + 700;
2019-11-21 07:43:34 +01:00
if (frontFloor <= -512 || frontFloor > 316)
return 0;
2019-11-21 07:43:34 +01:00
2019-12-02 09:11:21 +01:00
short rot = item->pos.yRot;
int slope = 0;
if (abs(coll->FrontRight.Floor - coll->FrontLeft.Floor) >= 60)
return 0;
bool result = SnapToQuadrant(rot, 35);
if (!result)
return 0;
2019-11-21 07:43:34 +01:00
2020-05-20 22:07:27 -05:00
if (frontFloor <= -256)
{
if (LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512)
2020-05-20 22:07:27 -05:00
{
if (EnableCrawlFlexWaterPullUp)
{
item->animNumber = LA_ONWATER_TO_CROUCH_1CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LA_CROUCH_IDLE;
}
else
return 0;
2020-05-20 22:07:27 -05:00
}
else
{
item->animNumber = LA_ONWATER_TO_STAND_1CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LS_STOP;
2020-05-20 22:07:27 -05:00
}
}
2020-05-21 02:42:10 -05:00
else if (frontFloor > 128)
2020-05-20 22:07:27 -05:00
{
if (LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512)
2020-05-20 22:07:27 -05:00
{
if (EnableCrawlFlexSubmerged)
{
item->animNumber = LA_ONWATER_TO_CROUCH_M1CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LA_CROUCH_IDLE;
}
else
return 0;
2020-05-20 22:07:27 -05:00
}
else
item->animNumber = LA_ONWATER_TO_STAND_M1CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
2020-05-20 22:07:27 -05:00
}
2020-05-21 02:42:10 -05:00
else
2019-11-21 07:43:34 +01:00
{
if (LaraCeilingFront(item, item->pos.yRot, 384, 512) >= -512)
2019-11-21 07:43:34 +01:00
{
if (EnableCrawlFlexWaterPullUp)
{
item->animNumber = LA_ONWATER_TO_CROUCH_0CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LA_CROUCH_IDLE;
}
else
return 0;
2019-11-21 07:43:34 +01:00
}
else
{
item->animNumber = LA_ONWATER_TO_STAND_0CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LS_STOP;
2019-11-21 07:43:34 +01:00
}
}
UpdateItemRoom(item, -LARA_HEIGHT / 2);
Vector2 v = GetOrthogonalIntersect(item->pos.xPos, item->pos.zPos, -LARA_RAD, item->pos.yRot);
item->pos.xPos = v.x;
item->pos.yPos += frontFloor - 5;
item->pos.zPos = v.y;
item->pos.xRot = 0;
2019-11-21 07:43:34 +01:00
item->pos.yRot = rot;
item->pos.zRot = 0;
item->currentAnimState = LS_ONWATER_EXIT;
2019-11-21 07:43:34 +01:00
item->gravityStatus = false;
item->speed = 0;
item->fallspeed = 0;
Lara.gunStatus = LG_HANDS_BUSY;
Lara.waterStatus = LW_ABOVE_WATER;
2019-11-21 07:43:34 +01:00
return 1;
2019-11-21 07:43:34 +01:00
}
2021-02-03 01:50:59 -03:00
int LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll)
2019-11-21 07:43:34 +01:00
{
2021-09-10 00:18:47 +03:00
if (coll->CollisionType == CT_FRONT
|| coll->Middle.Slope
2021-09-10 00:18:47 +03:00
|| coll->Middle.Floor >= 0)
2019-11-21 07:43:34 +01:00
{
return 0;
2019-11-21 07:43:34 +01:00
}
2021-09-10 00:18:47 +03:00
if (coll->Middle.Floor >= -128)
2019-11-21 07:43:34 +01:00
{
if (item->goalAnimState == LS_ONWATER_LEFT)
2019-11-21 07:43:34 +01:00
{
item->goalAnimState = LS_STEP_LEFT;
2019-11-21 07:43:34 +01:00
}
else if (item->goalAnimState == LS_ONWATER_RIGHT)
2019-11-21 07:43:34 +01:00
{
item->goalAnimState = LS_STEP_RIGHT;
2019-11-21 07:43:34 +01:00
}
else
{
item->animNumber = LA_WADE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LS_WADE_FORWARD;
item->currentAnimState = LS_WADE_FORWARD;
2019-11-21 07:43:34 +01:00
}
}
else
{
item->animNumber = LA_ONWATER_TO_WADE_1CLICK;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_ONWATER_EXIT;
item->goalAnimState = LS_STOP;
2019-11-21 07:43:34 +01:00
}
2021-09-10 00:18:47 +03:00
item->pos.yPos += coll->Front.Floor + 695;
2019-11-21 07:43:34 +01:00
UpdateItemRoom(item, -381);
2019-11-21 07:43:34 +01:00
item->pos.zRot = 0;
item->pos.xRot = 0;
item->gravityStatus = false;
2019-11-21 07:43:34 +01:00
item->speed = 0;
item->fallspeed = 0;
Lara.waterStatus = LW_WADE;
return 1;
2019-12-02 09:11:21 +01:00
}
int LaraTestLadderClimbOut(ITEM_INFO* item, COLL_INFO* coll) // NEW function for water to ladder move
{
2021-09-10 00:18:47 +03:00
if (!Lara.climbStatus || coll->CollisionType != CT_FRONT || !(TrInput & IN_ACTION))
return 0;
if (Lara.gunStatus && (Lara.gunStatus != LG_READY || Lara.gunType != WEAPON_FLARE))
return 0;
2021-09-14 00:30:44 +03:00
if (!TestLaraClimbStance(item, coll))
return 0;
short rot = item->pos.yRot;
if (rot >= -ANGLE(35.0f) && rot <= ANGLE(35.0f))
rot = 0;
else if (rot >= ANGLE(55.0f) && rot <= ANGLE(125.0f))
rot = ANGLE(90.0f);
else if (rot >= ANGLE(145.0f) || rot <= -ANGLE(145.0f))
rot = ANGLE(180.0f);
else if (rot >= -ANGLE(125.0f) && rot <= -ANGLE(55.0f))
rot = -ANGLE(90.0f);
if (rot & 0x3FFF)
return 0;
switch ((unsigned short)rot / ANGLE(90.0f))
{
case NORTH:
item->pos.zPos = (item->pos.zPos | (WALL_SIZE - 1)) - LARA_RAD - 1;
break;
case EAST:
item->pos.xPos = (item->pos.xPos | (WALL_SIZE - 1)) - LARA_RAD - 1;
break;
case SOUTH:
item->pos.zPos = (item->pos.zPos & -WALL_SIZE) + LARA_RAD + 1;
break;
case WEST:
item->pos.xPos = (item->pos.xPos & -WALL_SIZE) + LARA_RAD + 1;
break;
}
item->animNumber = LA_ONWATER_IDLE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_ONWATER_STOP;
item->goalAnimState = LS_LADDER_IDLE;
AnimateLara(item);
item->pos.yRot = rot;
2021-02-05 16:38:00 -06:00
item->pos.yPos -= 10;//otherwise she falls back into the water
Lara.gunStatus = LG_HANDS_BUSY;
item->pos.zRot = 0;
item->pos.xRot = 0;
item->gravityStatus = false;
item->speed = 0;
item->fallspeed = 0;
Lara.waterStatus = LW_ABOVE_WATER;
return 1;
}
2021-02-03 01:50:59 -03:00
void lara_as_waterout(ITEM_INFO* item, COLL_INFO* coll)
{
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
Camera.flags = CF_FOLLOW_CENTER;
Camera.laraNode = LM_HIPS; //forces the camera to follow Lara instead of snapping
}