TombEngine/TR5Main/Game/Lara/lara.cpp

1263 lines
27 KiB
C++
Raw Normal View History

2020-12-21 13:16:29 -03:00
#include "framework.h"
2021-09-10 00:18:47 +03:00
2020-12-21 13:16:29 -03:00
#include "Lara.h"
#include "lara_basic.h"
#include "lara_tests.h"
#include "lara_monkey.h"
#include "lara_crawl.h"
#include "lara_objects.h"
#include "lara_hang.h"
#include "lara_slide.h"
#include "lara_fire.h"
#include "lara_surface.h"
#include "lara_swim.h"
#include "lara_one_gun.h"
#include "lara_two_guns.h"
#include "lara_cheat.h"
#include "lara_climb.h"
#include "lara_initialise.h"
#include "motorbike.h"
#include "biggun.h"
#include "quad.h"
#include "snowmobile.h"
#include "jeep.h"
#include "boat.h"
#include "upv.h"
#include "kayak.h"
#include "minecart.h"
#include "animation.h"
2020-12-21 13:16:29 -03:00
#include "GameFlowScript.h"
#include "health.h"
#include "flipeffect.h"
2021-09-08 18:19:06 +03:00
#include "Sound\sound.h"
2020-12-21 13:16:29 -03:00
#include "savegame.h"
#include "rope.h"
#include "rubberboat.h"
#include "misc.h"
#include "control\volume.h"
2021-08-28 13:27:58 +02:00
#include "Renderer11.h"
#include "camera.h"
2021-09-25 16:00:30 +03:00
#include "items.h"
2021-11-16 15:51:50 +03:00
#include "gui.h"
2021-09-10 00:18:47 +03:00
#include "Objects/Generic/Object/rope.h"
using namespace TEN::Entities::Generic;
2020-12-21 13:16:29 -03:00
using std::function;
2021-08-30 18:03:21 +03:00
using TEN::Renderer::g_Renderer;
using namespace TEN::Control::Volumes;
2020-12-21 13:16:29 -03:00
LaraInfo Lara;
ITEM_INFO* LaraItem;
2021-09-16 01:12:19 +03:00
COLL_INFO LaraCollision = {};
2020-12-21 13:16:29 -03:00
byte LaraNodeUnderwater[NUM_LARA_MESHES];
2021-09-15 16:58:53 +03:00
function<LaraRoutineFunction> lara_control_routines[NUM_LARA_STATES + 1] =
{
2020-12-21 13:16:29 -03:00
lara_as_walk,
lara_as_run,
lara_as_stop,
lara_as_forwardjump,
lara_void_func,//4
lara_as_fastback,//5
lara_as_turn_r,//6
lara_as_turn_l,//7
lara_as_death,//8
lara_as_fastfall,
lara_as_hang,
lara_as_reach,
lara_as_splat,
lara_as_tread,
lara_void_func,
lara_as_compress,//15
lara_as_back,//16
lara_as_swim,//17
lara_as_glide,//18
lara_as_null,//19
lara_as_fastturn,//20
lara_as_stepright,//21
lara_as_stepleft,//22
lara_void_func,
lara_as_slide,//24
lara_as_backjump,//25
lara_as_rightjump,//26
lara_as_leftjump,//27
lara_as_upjump,//28
lara_as_fallback,//29
lara_as_hangleft,//30
lara_as_hangright,//31
lara_as_slideback,//32
lara_as_surftread,
lara_as_surfswim,
lara_as_dive,
lara_as_pushblock,//36
lara_as_pullblock,//37
lara_as_ppready,//38
lara_as_pickup,//39
lara_as_switchon,//40
lara_as_switchoff,//41
lara_as_usekey,//42
lara_as_usepuzzle,//43
lara_as_uwdeath,//44
lara_void_func,//45
lara_as_special,//46
lara_as_surfback,//47
lara_as_surfleft,//48
lara_as_surfright,//49
lara_void_func,//50
lara_void_func,//51
lara_as_swandive,//52
lara_as_fastdive,//53
lara_as_gymnast,//54
lara_as_waterout,
lara_as_climbstnc,
lara_as_climbing,
lara_as_climbleft,
lara_as_climbend,
lara_as_climbright,
lara_as_climbdown,//
lara_void_func,
lara_void_func,
lara_void_func,
lara_as_wade,//65
lara_as_waterroll,//66
lara_as_pickupflare,//67
lara_void_func,//68
lara_void_func,//69
lara_as_deathslide,//70
lara_as_duck,//71
lara_as_crouch_roll,//72
lara_as_dash,
lara_as_dashdive,
lara_as_hang2,
lara_as_monkeyswing,
lara_as_monkeyl,
lara_as_monkeyr,
lara_as_monkey180,
lara_as_all4s,//80
lara_as_crawl,//81
lara_as_hangturnl,
lara_as_hangturnr,
lara_as_all4turnl,//84
lara_as_all4turnr,//85
lara_as_crawlb,//86
lara_as_null,
lara_as_null,
lara_as_controlled,
lara_as_ropel,
lara_as_roper,
lara_as_controlled,
lara_as_controlled,
lara_as_controlled,
lara_as_controlledl,
lara_as_controlledl,
lara_as_controlled,
lara_as_pickup,//98
2021-11-21 20:50:17 +11:00
lara_as_pole_idle,//99
lara_as_pole_up,//100
lara_as_pole_down,//101
lara_as_pole_turn_clockwise,//102
lara_as_pole_turn_counter_clockwise,//103
2020-12-21 13:16:29 -03:00
lara_as_pulley,//104
lara_as_duckl,//105
lara_as_duckr,//106
lara_as_extcornerl,//107
lara_as_extcornerr,//108
lara_as_intcornerl,//109
lara_as_intcornerr,//110
lara_as_rope,//111
lara_as_climbrope,//112
lara_as_climbroped,//113
lara_as_rope,//114
lara_as_rope,//115
lara_void_func,
lara_as_controlled,
lara_as_swimcheat,
lara_as_trpose,//119
lara_as_null,//120
lara_as_trwalk,//121
lara_as_trfall,//122
lara_as_trfall,//123
lara_as_null,//124
#ifdef NEW_TIGHTROPE
lara_as_trexit,//125
#else // !NEW_TIGHTROPE
2020-12-21 13:16:29 -03:00
lara_as_null,//125
#endif
2020-12-21 13:16:29 -03:00
lara_as_switchon,//126
lara_as_null,//127
lara_as_parallelbars,//128
lara_as_pbleapoff,//129
lara_as_null,//130
lara_as_null,//131
lara_as_null,//132
lara_as_null,//133
lara_as_null,//134
lara_as_null,//135
lara_as_null,//136
lara_as_null,//137
lara_as_null,//138
2021-06-02 13:24:17 -05:00
lara_as_null,//ara_as_hang_feet,//139
2021-07-09 19:41:56 -05:00
lara_as_hang_feet_shimmyr,//140
lara_as_hang_feet_shimmyl,//141
lara_as_hang_feet_inRcorner,//142
lara_as_hang_feet_inLcorner,//143
lara_as_hang_feet_outRcorner,//144
lara_as_hang_feet_outLcorner,//145
2020-12-21 13:16:29 -03:00
lara_as_controlledl,
lara_as_null,
lara_as_null,
lara_as_null,
lara_as_stepoff_left,
lara_as_stepoff_right
};
2021-09-15 16:58:53 +03:00
2020-12-21 13:16:29 -03:00
function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1] = {
lara_col_walk,
lara_col_run,
lara_col_stop,
lara_col_forwardjump,
lara_col_pose,
lara_col_fastback,
lara_col_turn_r,
lara_col_turn_l,
lara_col_death,
lara_col_fastfall,
lara_col_hang,
lara_col_reach,
lara_col_splat,
lara_col_tread,
lara_col_land,
lara_col_compress,
lara_col_back,
lara_col_swim,
lara_col_glide,
lara_default_col,
lara_col_fastturn,
lara_col_stepright,
lara_col_stepleft,
lara_col_roll2,
lara_col_slide,
lara_col_backjump,
lara_col_rightjump,
lara_col_leftjump,
lara_col_upjump,
lara_col_fallback,
lara_col_hangleft,
lara_col_hangright,
lara_col_slideback,
lara_col_surftread,
lara_col_surfswim,
lara_col_dive,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_col_uwdeath,
lara_col_roll,
lara_void_func,
lara_col_surfback,
lara_col_surfleft,
lara_col_surfright,
lara_void_func,
lara_void_func,
lara_col_swandive,
lara_col_fastdive,
lara_default_col,
lara_default_col,
lara_col_climbstnc,
lara_col_climbing,
lara_col_climbleft,
lara_col_climbend,
lara_col_climbright,
lara_col_climbdown,
lara_void_func,
lara_void_func,
lara_void_func,
lara_col_wade,
lara_col_waterroll,
lara_default_col,
lara_void_func,
lara_void_func,
lara_void_func,
lara_col_duck,
lara_col_crouch_roll,
lara_col_dash,
lara_col_dashdive,
lara_col_hang2,
lara_col_monkeyswing,
lara_col_monkeyl,
lara_col_monkeyr,
lara_col_monkey180,
lara_col_all4s,
lara_col_crawl,
lara_col_hangturnlr,
lara_col_hangturnlr,
lara_col_all4turnlr,
lara_col_all4turnlr,
lara_col_crawlb,
lara_void_func,
lara_col_crawl2hang,
lara_default_col,
lara_void_func,
lara_void_func,
lara_default_col,
lara_void_func,
lara_void_func,
lara_col_turnswitch,
lara_void_func,
lara_void_func,
lara_default_col,
2021-11-21 20:50:17 +11:00
lara_col_pole_idle,
lara_col_pole_up,
lara_col_pole_down,
lara_col_pole_turn_clockwise,
lara_col_pole_turn_counter_clockwise,
2020-12-21 13:16:29 -03:00
lara_default_col,
lara_col_ducklr,
lara_col_ducklr,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_col_rope,
lara_void_func,
lara_void_func,
lara_col_ropefwd,
lara_col_ropefwd,
lara_void_func,
lara_void_func,
lara_col_swim,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
2021-07-09 19:41:56 -05:00
lara_col_hang_feet,
lara_col_hang_feet_shimmyr,
lara_col_hang_feet_shimmyl,
2020-12-21 13:16:29 -03:00
lara_default_col,
lara_default_col,
lara_default_col,
lara_default_col,
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func,
lara_default_col,
lara_default_col
};
2021-11-09 16:03:56 +11:00
void LaraControl(ITEM_INFO* item, COLL_INFO* coll)
2020-12-21 13:16:29 -03:00
{
LaraCheatyBits();
2021-09-16 01:12:19 +03:00
if (Lara.hasFired)
{
2021-11-09 16:03:56 +11:00
AlertNearbyGuards(item);
2021-09-16 01:12:19 +03:00
Lara.hasFired = false;
}
if (Lara.poisoned)
{
if (Lara.poisoned > 4096)
Lara.poisoned = 4096;
if (Lara.poisoned >= 256 && !(Wibble & 0xFF))
2021-11-09 16:03:56 +11:00
item->hitPoints -= Lara.poisoned >> 8;
2021-09-16 01:12:19 +03:00
}
2020-12-21 13:16:29 -03:00
if (Lara.isMoving)
{
if (Lara.moveCount > 90)
{
Lara.isMoving = false;
Lara.gunStatus = LG_NO_ARMS;
}
2021-11-09 16:03:56 +11:00
2020-12-21 13:16:29 -03:00
++Lara.moveCount;
}
2021-09-16 03:56:04 +03:00
if (!Lara.uncontrollable)
2020-12-21 13:16:29 -03:00
Lara.locationPad = 128;
2021-11-09 16:03:56 +11:00
int oldX = item->pos.xPos;
int oldY = item->pos.yPos;
int oldZ = item->pos.zPos;
2020-12-21 13:16:29 -03:00
if (Lara.gunStatus == LG_HANDS_BUSY &&
2021-11-09 16:03:56 +11:00
item->currentAnimState == LS_STOP &&
item->goalAnimState == LS_STOP &&
item->animNumber == LA_STAND_IDLE &&
!item->gravityStatus)
2020-12-21 13:16:29 -03:00
{
Lara.gunStatus = LG_NO_ARMS;
}
2021-11-10 16:11:36 +11:00
if (item->currentAnimState != LS_SPRINT && Lara.sprintTimer < LARA_SPRINT_MAX)
Lara.sprintTimer++;
2020-12-21 13:16:29 -03:00
Lara.isDucked = false;
2021-11-07 04:54:48 +03:00
bool isWater = TestLaraWater(item);
bool isSwamp = TestLaraSwamp(item);
2020-12-21 13:16:29 -03:00
2021-11-09 16:03:56 +11:00
int waterDepth = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
int waterHeight = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber);
2020-12-21 13:16:29 -03:00
2021-11-09 16:03:56 +11:00
int heightFromWater;
if (waterHeight != NO_HEIGHT)
heightFromWater = item->pos.yPos - waterHeight;
2020-12-21 13:16:29 -03:00
else
2021-11-09 16:03:56 +11:00
heightFromWater = NO_HEIGHT;
Lara.waterSurfaceDist = -heightFromWater;
2020-12-21 13:16:29 -03:00
if (Lara.Vehicle == NO_ITEM)
2021-11-09 16:03:56 +11:00
WadeSplash(item, waterHeight, waterDepth);
2020-12-21 13:16:29 -03:00
short roomNumber;
if (Lara.Vehicle == NO_ITEM && Lara.ExtraAnim == -1)
{
switch (Lara.waterStatus)
{
case LW_ABOVE_WATER:
2021-11-09 16:03:56 +11:00
if (heightFromWater == NO_HEIGHT || heightFromWater < WADE_DEPTH)
2021-11-07 04:54:48 +03:00
break;
2021-11-09 16:03:56 +11:00
Camera.targetElevation = -ANGLE(22.0f);
if (waterDepth > (SWIM_DEPTH - STEP_SIZE) &&
!isSwamp &&
item->currentAnimState != LS_RUN_FORWARD && // Prevent ridiculous entrances when stepping down into wade-height water. @Sezz 2021.11.17
item->currentAnimState != LS_WALK_FORWARD &&
item->currentAnimState != LS_WALK_BACK)
2020-12-21 13:16:29 -03:00
{
2021-11-07 16:07:16 +03:00
if (isWater)
{
Lara.air = 1800;
Lara.waterStatus = LW_UNDERWATER;
item->gravityStatus = false;
item->pos.yPos += 100;
2021-11-07 04:54:48 +03:00
2021-11-09 16:03:56 +11:00
UpdateItemRoom(item, 0);
2021-11-07 16:07:16 +03:00
StopSoundEffect(SFX_TR4_LARA_FALL);
2021-11-07 04:54:48 +03:00
2021-11-07 16:07:16 +03:00
if (item->currentAnimState == LS_SWANDIVE_START)
{
2021-11-09 16:03:56 +11:00
item->pos.xRot = -ANGLE(45.0f);
2021-11-07 16:07:16 +03:00
item->goalAnimState = LS_DIVE;
AnimateLara(item);
item->fallspeed *= 2;
}
else if (item->currentAnimState == LS_SWANDIVE_END)
{
2021-11-09 16:03:56 +11:00
item->pos.xRot = -ANGLE(85.0f);
2021-11-07 16:07:16 +03:00
item->goalAnimState = LS_DIVE;
AnimateLara(item);
item->fallspeed *= 2;
}
else
{
2021-11-09 16:03:56 +11:00
item->pos.xRot = -ANGLE(45.0f);
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_FREEFALL_DIVE);
2021-11-07 16:07:16 +03:00
item->fallspeed = 3 * item->fallspeed / 2;
}
2020-12-21 13:16:29 -03:00
2021-11-07 16:07:16 +03:00
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
2020-12-21 13:16:29 -03:00
2021-11-09 16:03:56 +11:00
Splash(item);
2021-11-07 16:07:16 +03:00
}
2021-11-07 04:54:48 +03:00
}
2021-11-09 16:03:56 +11:00
else if (heightFromWater > WADE_DEPTH)
2021-11-07 04:54:48 +03:00
{
Lara.waterStatus = LW_WADE;
2021-11-09 16:03:56 +11:00
if (!item->gravityStatus)
2021-11-07 04:54:48 +03:00
item->goalAnimState = LS_STOP;
else if (isSwamp)
{
if (item->currentAnimState == LS_SWANDIVE_START || item->currentAnimState == LS_SWANDIVE_END)
2021-11-09 16:03:56 +11:00
item->pos.yPos = waterHeight + (WALL_SIZE - 24);
2021-11-07 04:54:48 +03:00
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_WADE);
2021-11-07 04:54:48 +03:00
}
}
2021-11-09 16:03:56 +11:00
if (heightFromWater >= WADE_DEPTH)
2021-11-07 04:54:48 +03:00
{
2021-11-09 16:03:56 +11:00
if (heightFromWater > SWIM_DEPTH)
2021-11-07 04:54:48 +03:00
{
if (isSwamp)
SetAnimation(item, LA_WADE);
else
{
SetAnimation(item, LA_ONWATER_IDLE);
Lara.waterStatus = LW_SURFACE;
item->pos.yPos += 1 - heightFromWater;
Lara.diveCount = 0;
}
2021-11-07 04:54:48 +03:00
item->gravityStatus = false;
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
2020-12-21 13:16:29 -03:00
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
2021-11-07 04:54:48 +03:00
UpdateItemRoom(item, 0);
2020-12-21 13:16:29 -03:00
}
}
2021-11-07 04:54:48 +03:00
else
{
Lara.waterStatus = LW_ABOVE_WATER;
2021-11-07 04:54:48 +03:00
if (item->currentAnimState == LS_WADE_FORWARD)
item->goalAnimState = LS_RUN_FORWARD;
}
2020-12-21 13:16:29 -03:00
break;
case LW_UNDERWATER:
roomNumber = item->roomNumber;
2021-09-14 15:30:28 +03:00
GetFloor(item->pos.xPos, item->pos.yPos - STEP_SIZE, item->pos.zPos, &roomNumber);
2020-12-21 13:16:29 -03:00
2021-11-09 16:03:56 +11:00
if (isWater ||
waterDepth == DEEP_WATER ||
abs(heightFromWater) >= STEP_SIZE ||
item->animNumber == LA_UNDERWATER_RESURFACE ||
item->animNumber == LA_ONWATER_DIVE)
2020-12-21 13:16:29 -03:00
{
if (!isWater)
{
2021-11-09 16:03:56 +11:00
if (waterDepth == DEEP_WATER || abs(heightFromWater) >= STEP_SIZE)
2020-12-21 13:16:29 -03:00
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_FALL_START);
2020-12-21 13:16:29 -03:00
item->speed = item->fallspeed / 4;
item->gravityStatus = true;
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
Lara.waterStatus = LW_ABOVE_WATER;
2020-12-21 13:16:29 -03:00
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
}
else
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_UNDERWATER_RESURFACE);
2021-11-09 16:03:56 +11:00
item->pos.yPos = waterHeight;
2020-12-21 13:16:29 -03:00
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
Lara.waterStatus = LW_SURFACE;
2020-12-21 13:16:29 -03:00
Lara.diveCount = 11;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
2021-11-09 16:03:56 +11:00
UpdateItemRoom(item, -(STEPUP_HEIGHT - 3));
SoundEffect(SFX_TR4_LARA_BREATH, &item->pos, 2);
2020-12-21 13:16:29 -03:00
}
}
}
else
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_UNDERWATER_RESURFACE);
2021-11-09 16:03:56 +11:00
item->pos.yPos = waterHeight + 1;
2020-12-21 13:16:29 -03:00
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
Lara.waterStatus = LW_SURFACE;
2020-12-21 13:16:29 -03:00
Lara.diveCount = 11;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
UpdateItemRoom(item, 0);
2021-11-09 16:03:56 +11:00
SoundEffect(SFX_TR4_LARA_BREATH, &item->pos, 2);
2020-12-21 13:16:29 -03:00
}
break;
case LW_SURFACE:
if (!isWater)
{
2021-11-09 16:03:56 +11:00
if (heightFromWater <= WADE_DEPTH)
2020-12-21 13:16:29 -03:00
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_FALL_START);
2020-12-21 13:16:29 -03:00
item->speed = item->fallspeed / 4;
item->gravityStatus = true;
2021-11-09 16:03:56 +11:00
Lara.waterStatus = LW_ABOVE_WATER;
2020-12-21 13:16:29 -03:00
}
else
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_STAND_IDLE);
2021-11-10 12:26:27 +03:00
item->goalAnimState = LS_WADE_FORWARD; // TODO: Check if really needed? -- Lwmte, 10.11.21
2021-11-09 16:03:56 +11:00
Lara.waterStatus = LW_WADE;
2020-12-21 13:16:29 -03:00
AnimateItem(item);
}
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
2020-12-21 13:16:29 -03:00
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
}
2021-11-09 16:03:56 +11:00
2020-12-21 13:16:29 -03:00
break;
case LW_WADE:
2021-11-09 16:03:56 +11:00
Camera.targetElevation = -ANGLE(22.0f);
if (heightFromWater >= WADE_DEPTH)
2020-12-21 13:16:29 -03:00
{
2021-11-09 16:03:56 +11:00
if (heightFromWater > SWIM_DEPTH && !isSwamp)
2020-12-21 13:16:29 -03:00
{
2021-11-10 02:41:59 +03:00
SetAnimation(item, LA_ONWATER_IDLE);
2020-12-21 13:16:29 -03:00
Lara.waterStatus = LW_SURFACE;
2021-11-09 16:03:56 +11:00
item->pos.yPos += 1 - heightFromWater;
2020-12-21 13:16:29 -03:00
item->gravityStatus = false;
item->fallspeed = 0;
2021-11-09 16:03:56 +11:00
item->pos.zRot = 0;
item->pos.xRot = 0;
2020-12-21 13:16:29 -03:00
Lara.diveCount = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
UpdateItemRoom(item, 0);
2020-12-21 13:16:29 -03:00
}
}
else
{
Lara.waterStatus = LW_ABOVE_WATER;
2021-11-09 16:03:56 +11:00
2020-12-21 13:16:29 -03:00
if (item->currentAnimState == LS_WADE_FORWARD)
item->goalAnimState = LS_RUN_FORWARD;
}
2021-11-09 16:03:56 +11:00
2020-12-21 13:16:29 -03:00
break;
}
}
if (item->hitPoints <= 0)
{
item->hitPoints = -1;
if (Lara.deathCount == 0)
2021-09-16 01:12:19 +03:00
StopSoundTracks();
2020-12-21 13:16:29 -03:00
Lara.deathCount++;
2021-11-09 16:03:56 +11:00
if ((item->flags & 0x100))
2020-12-21 13:16:29 -03:00
{
Lara.deathCount++;
2021-11-09 16:03:56 +11:00
2020-12-21 13:16:29 -03:00
return;
}
}
switch (Lara.waterStatus)
{
case LW_ABOVE_WATER:
case LW_WADE:
2021-11-10 22:48:00 +11:00
if (isSwamp && Lara.waterSurfaceDist < -(LARA_HEIGHT + 8)) // TODO: Find best height. @Sezz 2021.11.10
2020-12-21 13:16:29 -03:00
{
if (item->hitPoints >= 0)
{
Lara.air -= 6;
if (Lara.air < 0)
{
Lara.air = -1;
item->hitPoints -= 10;
}
}
}
2021-11-10 16:11:36 +11:00
else if (Lara.air < LARA_AIR_MAX && item->hitPoints >= 0)
2020-12-21 13:16:29 -03:00
{
if (Lara.Vehicle == NO_ITEM) // only for the upv !!
{
Lara.air += 10;
2021-11-10 16:11:36 +11:00
if (Lara.air > LARA_AIR_MAX)
Lara.air = LARA_AIR_MAX;
2020-12-21 13:16:29 -03:00
}
}
2021-11-09 16:03:56 +11:00
LaraAboveWater(item, coll);
2020-12-21 13:16:29 -03:00
break;
case LW_UNDERWATER:
if (item->hitPoints >= 0)
{
2021-11-11 01:16:27 +03:00
auto level = g_GameFlow->GetLevel(CurrentLevel);
if (level->LaraType != LaraType::Divesuit)
2020-12-21 13:16:29 -03:00
Lara.air--;
2021-11-11 01:16:27 +03:00
2020-12-21 13:16:29 -03:00
if (Lara.air < 0)
{
// if (LaraDrawType == LARA_TYPE::DIVESUIT && Lara.anxiety < 251)
2021-07-08 14:15:14 -05:00
// Lara.anxiety += 4;
2020-12-21 13:16:29 -03:00
Lara.air = -1;
item->hitPoints -= 5;
}
}
2021-11-09 16:03:56 +11:00
LaraUnderWater(item, coll);
2020-12-21 13:16:29 -03:00
break;
case LW_SURFACE:
if (item->hitPoints >= 0)
{
Lara.air += 10;
2021-11-10 16:11:36 +11:00
if (Lara.air > LARA_AIR_MAX)
Lara.air = LARA_AIR_MAX;
2020-12-21 13:16:29 -03:00
}
2021-11-09 16:03:56 +11:00
LaraSurface(item, coll);
2020-12-21 13:16:29 -03:00
break;
case LW_FLYCHEAT:
2021-11-09 16:03:56 +11:00
LaraCheat(item, coll);
2020-12-21 13:16:29 -03:00
break;
}
Statistics.Game.Distance += sqrt(
2020-12-21 13:16:29 -03:00
SQUARE(item->pos.xPos - oldX) +
SQUARE(item->pos.yPos - oldY) +
SQUARE(item->pos.zPos - oldZ));
}
void LaraAboveWater(ITEM_INFO* item, COLL_INFO* coll)
2020-12-21 13:16:29 -03:00
{
2021-09-10 00:20:59 +03:00
coll->Setup.OldPosition.x = item->pos.xPos;
coll->Setup.OldPosition.y = item->pos.yPos;
coll->Setup.OldPosition.z = item->pos.zPos;
coll->Setup.OldAnimState = item->currentAnimState;
2021-10-09 19:19:02 +03:00
coll->Setup.OldAnimNumber = item->animNumber;
coll->Setup.OldFrameNumber = item->frameNumber;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpaz = true;
coll->Setup.SlopesAreWalls = false;
coll->Setup.SlopesArePits = false;
coll->Setup.DeathFlagIsPit = false;
2021-10-27 09:48:31 +03:00
coll->Setup.Mode = COLL_PROBE_MODE::QUADRANTS;
2021-10-09 19:19:02 +03:00
2021-09-10 00:20:59 +03:00
coll->Setup.Radius = LARA_RAD;
coll->Setup.Height = LARA_HEIGHT;
2020-12-21 13:16:29 -03:00
2021-11-10 16:11:36 +11:00
if (TrInput & IN_LOOK && Lara.look &&
Lara.ExtraAnim == NO_ITEM)
{
2020-12-21 13:16:29 -03:00
LookLeftRight();
2021-11-10 16:11:36 +11:00
}
2020-12-21 13:16:29 -03:00
else
ResetLook();
Lara.look = true;
UpdateItemRoom(item, -LARA_HEIGHT / 2);
2020-12-21 13:16:29 -03:00
// Process Vehicles
if (Lara.Vehicle != NO_ITEM)
{
switch (g_Level.Items[Lara.Vehicle].objectNumber)
{
case ID_QUAD:
2021-11-17 00:17:25 +11:00
if (QuadBikeControl(item, coll))
2020-12-21 13:16:29 -03:00
return;
break;
case ID_JEEP:
if (JeepControl())
return;
break;
case ID_MOTORBIKE:
if (MotorbikeControl())
return;
break;
case ID_KAYAK:
if (KayakControl())
return;
break;
case ID_SNOWMOBILE:
2021-11-17 23:56:34 +11:00
if (SkidooControl(item, coll))
2020-12-21 13:16:29 -03:00
return;
break;
case ID_UPV:
if (SubControl())
return;
break;
case ID_MINECART:
if (MineCartControl())
return;
break;
case ID_BIGGUN:
2021-11-16 22:30:37 +11:00
if (BigGunControl(item, coll))
2020-12-21 13:16:29 -03:00
return;
break;
default:
// Boats are processed like normal items in loop
2021-11-20 15:39:05 +11:00
LaraGun(item);
2020-12-21 13:16:29 -03:00
return;
}
}
// Handle current Lara status
lara_control_routines[item->currentAnimState](item, coll);
if (item->pos.zRot >= -ANGLE(1.0f) && item->pos.zRot <= ANGLE(1.0f))
item->pos.zRot = 0;
else if (item->pos.zRot < -ANGLE(1.0f))
item->pos.zRot += ANGLE(1.0f);
else
item->pos.zRot -= ANGLE(1.0f);
if (Lara.turnRate >= -ANGLE(2.0f) && Lara.turnRate <= ANGLE(2.0f))
Lara.turnRate = 0;
else if (Lara.turnRate < -ANGLE(2.0f))
Lara.turnRate += ANGLE(2.0f);
else
Lara.turnRate -= ANGLE(2.0f);
item->pos.yRot += Lara.turnRate;
// Animate Lara
AnimateLara(item);
if (Lara.ExtraAnim == -1)
{
// Check for collision with items
DoObjectCollision(item, coll);
2020-12-21 13:16:29 -03:00
// Handle Lara collision
if (Lara.Vehicle == NO_ITEM)
lara_collision_routines[item->currentAnimState](item, coll);
}
//if (Lara.gunType == WEAPON_CROSSBOW && !LaserSight)
// TrInput &= ~IN_ACTION;
// Handle weapons
2021-11-20 15:39:05 +11:00
LaraGun(item);
2020-12-21 13:16:29 -03:00
// Test for flags & triggers
ProcessSectorFlags(item);
2021-09-15 16:58:53 +03:00
TestTriggers(item, false);
TestVolumes(item);
2020-12-21 13:16:29 -03:00
}
2021-02-03 01:50:59 -03:00
void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)
2020-12-21 13:16:29 -03:00
{
2021-09-19 17:48:32 +03:00
coll->Setup.BadHeightDown = 32512;
coll->Setup.BadHeightUp = -400;
2021-09-10 00:20:59 +03:00
coll->Setup.BadCeilingHeight = 400;
2020-12-21 13:16:29 -03:00
2021-09-10 00:20:59 +03:00
coll->Setup.OldPosition.x = item->pos.xPos;
coll->Setup.OldPosition.y = item->pos.yPos;
coll->Setup.OldPosition.z = item->pos.zPos;
2020-12-21 13:16:29 -03:00
2021-09-10 00:20:59 +03:00
coll->Setup.SlopesAreWalls = false;
coll->Setup.SlopesArePits = false;
coll->Setup.DeathFlagIsPit = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpaz = false;
2021-10-27 09:48:31 +03:00
coll->Setup.Mode = COLL_PROBE_MODE::QUADRANTS;
2020-12-21 13:16:29 -03:00
2021-09-10 01:19:15 +03:00
coll->Setup.Radius = LARA_RAD_UNDERWATER;
coll->Setup.Height = LARA_HEIGHT;
2020-12-21 13:16:29 -03:00
if (TrInput & IN_LOOK && Lara.look)
LookLeftRight();
else
ResetLook();
Lara.look = true;
lara_control_routines[item->currentAnimState](item, coll);
2021-11-11 01:16:27 +03:00
auto level = g_GameFlow->GetLevel(CurrentLevel);
if (level->LaraType == LaraType::Divesuit)
2020-12-21 13:16:29 -03:00
{
2021-11-10 16:11:36 +11:00
if (Lara.turnRate < -ANGLE(0.5f))
Lara.turnRate += ANGLE(0.5f);
else if (Lara.turnRate > ANGLE(0.5f))
Lara.turnRate -= ANGLE(0.5f);
2020-12-21 13:16:29 -03:00
else
Lara.turnRate = 0;
}
2021-11-10 16:11:36 +11:00
else if (Lara.turnRate < -ANGLE(2.0f))
Lara.turnRate += ANGLE(2.0f);
else if (Lara.turnRate > ANGLE(2.0f))
Lara.turnRate -= ANGLE(2.0f);
2020-12-21 13:16:29 -03:00
else
Lara.turnRate = 0;
item->pos.yRot += Lara.turnRate;
2021-11-11 01:16:27 +03:00
if (level->LaraType == LaraType::Divesuit)
2020-12-21 13:16:29 -03:00
UpdateSubsuitAngles();
2021-11-10 16:11:36 +11:00
if (item->pos.zRot < -ANGLE(2.0f))
item->pos.zRot += ANGLE(2.0f);
else if (item->pos.zRot > ANGLE(2.0f))
item->pos.zRot -= ANGLE(2.0f);
2020-12-21 13:16:29 -03:00
else
item->pos.zRot = 0;
2021-11-10 16:11:36 +11:00
if (item->pos.xRot < -ANGLE(85.0f))
item->pos.xRot = -ANGLE(85.0f);
else if (item->pos.xRot > ANGLE(85.0f))
item->pos.xRot = ANGLE(85.0f);
2020-12-21 13:16:29 -03:00
2021-11-11 01:16:27 +03:00
if (level->LaraType == LaraType::Divesuit)
2020-12-21 13:16:29 -03:00
{
2021-11-10 16:11:36 +11:00
if (item->pos.zRot > ANGLE(44.0f))
item->pos.zRot = ANGLE(44.0f);
else if (item->pos.zRot < -ANGLE(44.0f))
item->pos.zRot = -ANGLE(44.0f);
2020-12-21 13:16:29 -03:00
}
else
{
2021-11-10 16:11:36 +11:00
if (item->pos.zRot > ANGLE(22.0f))
item->pos.zRot = ANGLE(22.0f);
else if (item->pos.zRot < -ANGLE(22.0f))
item->pos.zRot = -ANGLE(22.0f);
2020-12-21 13:16:29 -03:00
}
if (Lara.currentActive && Lara.waterStatus != LW_FLYCHEAT)
LaraWaterCurrent(coll);
AnimateLara(item);
item->pos.xPos += phd_cos(item->pos.xRot) * item->fallspeed * phd_sin(item->pos.yRot) / 4;
item->pos.yPos -= item->fallspeed * phd_sin(item->pos.xRot) / 4;
item->pos.zPos += phd_cos(item->pos.xRot) * item->fallspeed * phd_cos(item->pos.yRot) / 4;
DoObjectCollision(item, coll);
2020-12-21 13:16:29 -03:00
if (/*Lara.ExtraAnim == -1 &&*/ Lara.Vehicle == NO_ITEM)
lara_collision_routines[item->currentAnimState](item, coll);
UpdateItemRoom(item, 0);
2020-12-21 13:16:29 -03:00
2021-11-20 15:39:05 +11:00
LaraGun(item);
2020-12-21 13:16:29 -03:00
ProcessSectorFlags(item);
2021-09-15 16:58:53 +03:00
TestTriggers(item, false);
TestVolumes(item);
2020-12-21 13:16:29 -03:00
}
2021-02-03 01:50:59 -03:00
void LaraSurface(ITEM_INFO* item, COLL_INFO* coll)
2020-12-21 13:16:29 -03:00
{
2021-11-10 16:11:36 +11:00
Camera.targetElevation = -ANGLE(22.0f);
2020-12-21 13:16:29 -03:00
2021-09-19 17:48:32 +03:00
coll->Setup.BadHeightDown = 32512;
coll->Setup.BadHeightUp = -128;
2021-09-10 00:20:59 +03:00
coll->Setup.BadCeilingHeight = 100;
2020-12-21 13:16:29 -03:00
2021-09-10 00:20:59 +03:00
coll->Setup.OldPosition.x = item->pos.xPos;
coll->Setup.OldPosition.y = item->pos.yPos;
coll->Setup.OldPosition.z = item->pos.zPos;
2020-12-21 13:16:29 -03:00
2021-09-10 00:20:59 +03:00
coll->Setup.SlopesAreWalls = false;
coll->Setup.SlopesArePits = false;
coll->Setup.DeathFlagIsPit = false;
2021-09-10 00:20:59 +03:00
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpaz = false;
2021-10-27 09:48:31 +03:00
coll->Setup.Mode = COLL_PROBE_MODE::FREE_FORWARD;
2020-12-21 13:16:29 -03:00
2021-09-10 01:19:15 +03:00
coll->Setup.Radius = LARA_RAD;
2021-09-19 07:38:15 +03:00
coll->Setup.Height = LARA_HEIGHT_SURFACE;
2020-12-21 13:16:29 -03:00
if (TrInput & IN_LOOK && Lara.look)
LookLeftRight();
else
ResetLook();
Lara.look = true;
lara_control_routines[item->currentAnimState](item, coll);
2021-11-10 16:11:36 +11:00
if (item->pos.zRot >= -ANGLE(2) && item->pos.zRot <= ANGLE(2.0f))
2020-12-21 13:16:29 -03:00
item->pos.zRot = 0;
else if (item->pos.zRot < 0)
2021-11-10 16:11:36 +11:00
item->pos.zRot += ANGLE(2.0f);
2020-12-21 13:16:29 -03:00
else
2021-11-10 16:11:36 +11:00
item->pos.zRot -= ANGLE(2.0f);
2020-12-21 13:16:29 -03:00
if (Lara.currentActive && Lara.waterStatus != LW_FLYCHEAT)
LaraWaterCurrent(coll);
AnimateLara(item);
item->pos.xPos += item->fallspeed * phd_sin(Lara.moveAngle) / 4;
item->pos.zPos += item->fallspeed * phd_cos(Lara.moveAngle) / 4;
DoObjectCollision(item, coll);
2020-12-21 13:16:29 -03:00
if (Lara.Vehicle == NO_ITEM)
lara_collision_routines[item->currentAnimState](item, coll);
UpdateItemRoom(item, 100);
2020-12-21 13:16:29 -03:00
2021-11-20 15:39:05 +11:00
LaraGun(item);
2020-12-21 13:16:29 -03:00
ProcessSectorFlags(item);
2021-09-15 16:58:53 +03:00
TestTriggers(item, false);
TestVolumes(item);
2020-12-21 13:16:29 -03:00
}
2021-02-03 01:50:59 -03:00
void LaraCheat(ITEM_INFO* item, COLL_INFO* coll)
2020-12-21 13:16:29 -03:00
{
LaraItem->hitPoints = 1000;
LaraUnderWater(item, coll);
if (TrInput & IN_WALK && !(TrInput & IN_LOOK))
{
2021-11-07 04:54:48 +03:00
if (TestLaraWater(item) || (Lara.waterSurfaceDist > 0 && Lara.waterSurfaceDist != NO_HEIGHT))
2020-12-21 13:16:29 -03:00
{
Lara.waterStatus = LW_UNDERWATER;
2021-11-16 17:25:17 +03:00
SetAnimation(item, LA_UNDERWATER_IDLE);
2020-12-21 13:16:29 -03:00
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
}
else
{
Lara.waterStatus = LW_ABOVE_WATER;
2021-11-16 17:25:17 +03:00
SetAnimation(item, LA_STAND_SOLID);
2020-12-21 13:16:29 -03:00
item->pos.zRot = 0;
item->pos.xRot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.headYrot = 0;
Lara.headXrot = 0;
}
Lara.gunStatus = LG_NO_ARMS;
LaraInitialiseMeshes();
LaraItem->hitPoints = 1000;
}
}
void AnimateLara(ITEM_INFO* item)
{
item->frameNumber++;
ANIM_STRUCT* anim = &g_Level.Anims[item->animNumber];
if (anim->numberChanges > 0 && GetChange(item, anim))
{
anim = &g_Level.Anims[item->animNumber];
item->currentAnimState = anim->currentAnimState;
}
if (item->frameNumber > anim->frameEnd)
{
if (anim->numberCommands > 0)
{
short* cmd = &g_Level.Commands[anim->commandIndex];
for (int i = anim->numberCommands; i > 0; i--)
{
switch (*(cmd++))
{
case COMMAND_MOVE_ORIGIN:
TranslateItem(item, cmd[0], cmd[1], cmd[2]);
UpdateItemRoom(item, -LARA_HEIGHT / 2);
2020-12-21 13:16:29 -03:00
cmd += 3;
break;
case COMMAND_JUMP_VELOCITY:
item->fallspeed = *(cmd++);
item->speed = *(cmd++);
item->gravityStatus = true;
if (Lara.calcFallSpeed)
{
item->fallspeed = Lara.calcFallSpeed;
Lara.calcFallSpeed = 0;
}
break;
case COMMAND_ATTACK_READY:
if (Lara.gunStatus != LG_SPECIAL)
Lara.gunStatus = LG_NO_ARMS;
break;
case COMMAND_SOUND_FX:
case COMMAND_EFFECT:
cmd += 2;
break;
default:
break;
}
}
}
item->animNumber = anim->jumpAnimNum;
item->frameNumber = anim->jumpFrameNum;
anim = &g_Level.Anims[item->animNumber];
item->currentAnimState = anim->currentAnimState;
}
if (anim->numberCommands > 0)
{
short* cmd = &g_Level.Commands[anim->commandIndex];
int flags;
int effectID = 0;
for (int i = anim->numberCommands; i > 0; i--)
{
switch (*(cmd++))
{
case COMMAND_MOVE_ORIGIN:
cmd += 3;
break;
case COMMAND_JUMP_VELOCITY:
cmd += 2;
break;
case COMMAND_SOUND_FX:
if (item->frameNumber != *cmd)
{
cmd += 2;
break;
}
flags = cmd[1] & 0xC000;
2021-10-29 02:22:26 +03:00
if ( flags == (int)SOUND_PLAYCONDITION::LandAndWater ||
(flags == (int)SOUND_PLAYCONDITION::Land && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) ||
2021-11-07 04:54:48 +03:00
(flags == (int)SOUND_PLAYCONDITION::Water && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT && !TestLaraSwamp(item)))
2020-12-21 13:16:29 -03:00
{
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
}
cmd += 2;
break;
case COMMAND_EFFECT:
if (item->frameNumber != *cmd)
{
cmd += 2;
break;
}
effectID = cmd[1] & 0x3FFF;
2021-09-15 17:49:01 +03:00
DoFlipEffect(effectID, item);
2020-12-21 13:16:29 -03:00
cmd += 2;
break;
default:
break;
}
}
}
int lateral = anim->Xvelocity;
if (anim->Xacceleration)
lateral += anim->Xacceleration * (item->frameNumber - anim->frameBase);
lateral >>= 16;
2020-12-21 13:16:29 -03:00
2021-11-07 04:54:48 +03:00
if (item->gravityStatus)
2020-12-21 13:16:29 -03:00
{
2021-11-07 04:54:48 +03:00
if (TestLaraSwamp(item))
2020-12-21 13:16:29 -03:00
{
item->speed -= item->speed >> 3;
2020-12-21 13:16:29 -03:00
if (abs(item->speed) < 8)
{
item->speed = 0;
item->gravityStatus = false;
}
if (item->fallspeed > 128)
item->fallspeed /= 2;
item->fallspeed -= item->fallspeed / 4;
if (item->fallspeed < 4)
item->fallspeed = 4;
item->pos.yPos += item->fallspeed;
}
else
{
int velocity = (anim->velocity + anim->acceleration * (item->frameNumber - anim->frameBase - 1));
item->speed -= velocity >> 16;
item->speed += (velocity + anim->acceleration) >> 16;
2020-12-21 13:16:29 -03:00
item->fallspeed += (item->fallspeed >= 128 ? 1 : GRAVITY);
item->pos.yPos += item->fallspeed;
}
}
2021-11-07 04:54:48 +03:00
else
2020-12-21 13:16:29 -03:00
{
int velocity;
2021-11-07 04:54:48 +03:00
if (Lara.waterStatus == LW_WADE && TestLaraSwamp(item))
2020-12-21 13:16:29 -03:00
{
velocity = (anim->velocity >> 1);
2020-12-21 13:16:29 -03:00
if (anim->acceleration)
velocity += (anim->acceleration * (item->frameNumber - anim->frameBase)) >> 2;
2020-12-21 13:16:29 -03:00
}
else
{
velocity = anim->velocity;
if (anim->acceleration)
velocity += anim->acceleration * (item->frameNumber - anim->frameBase);
}
item->speed = velocity >> 16;
2020-12-21 13:16:29 -03:00
}
if (Lara.ropePtr != -1)
DelAlignLaraToRope(item);
if (!Lara.isMoving)
2021-10-25 12:12:36 +03:00
MoveItem(item, Lara.moveAngle, item->speed, lateral);
2020-12-21 13:16:29 -03:00
// Update matrices
g_Renderer.updateLaraAnimations(true);
}