2021-09-27 18:18:03 +10:00
# include "framework.h"
2021-12-24 03:32:19 +03:00
# include "Game/Lara/lara_helpers.h"
2021-12-22 16:23:57 +03:00
# include "Game/collision/collide_room.h"
# include "Game/control/control.h"
# include "Game/items.h"
# include "Game/Lara/lara.h"
2022-02-14 17:05:52 +11:00
# include "Game/Lara/lara_collide.h"
2022-02-08 01:26:59 +11:00
# include "Game/Lara/lara_fire.h"
2021-12-22 16:23:57 +03:00
# include "Game/Lara/lara_tests.h"
# include "Scripting/GameFlowScript.h"
2021-12-24 03:32:19 +03:00
# include "Specific/input.h"
# include "Specific/level.h"
# include "Specific/setup.h"
2021-10-09 14:39:06 +11:00
2022-02-08 01:26:59 +11:00
# include "Objects/TR2/Vehicles/snowmobile.h"
# include "Objects/TR3/Vehicles/biggun.h"
# include "Objects/TR3/Vehicles/kayak.h"
# include "Objects/TR3/Vehicles/minecart.h"
# include "Objects/TR3/Vehicles/quad.h"
# include "Objects/TR3/Vehicles/upv.h"
# include "Objects/TR4/Vehicles/jeep.h"
# include "Objects/TR4/Vehicles/motorbike.h"
2021-10-18 20:15:53 +11:00
// -----------------------------
// HELPER FUNCTIONS
// For State Control & Collision
// -----------------------------
2021-12-23 18:41:37 +11:00
// TODO: Make lean rate proportional to the turn rate, allowing for nicer aesthetics with future analog stick input.
2022-01-15 22:48:35 +11:00
void DoLaraLean ( ITEM_INFO * item , COLL_INFO * coll , short maxAngle , short rate )
2021-12-23 18:41:37 +11:00
{
2022-02-09 13:20:57 +11:00
if ( ! item - > Velocity )
2021-12-23 18:41:37 +11:00
return ;
2022-02-17 15:01:48 +11:00
rate = abs ( rate ) ;
2021-12-23 18:41:37 +11:00
int sign = copysign ( 1 , maxAngle ) ;
if ( coll - > CollisionType = = CT_LEFT | | coll - > CollisionType = = CT_RIGHT )
2022-02-12 14:56:28 +11:00
item - > Position . zRot + = std : : min < short > ( rate , abs ( ( maxAngle * 3 ) / 5 - item - > Position . zRot ) / 3 ) * sign ;
2021-12-23 18:41:37 +11:00
else
2022-02-12 14:56:28 +11:00
item - > Position . zRot + = std : : min < short > ( rate , abs ( maxAngle - item - > Position . zRot ) / 3 ) * sign ;
}
2022-02-13 15:58:12 +11:00
// Works, but disabled for the time being. @Sezz 2022.02.13
2022-02-12 14:56:28 +11:00
void ApproachLaraTargetAngle ( ITEM_INFO * item , short targetAngle , float rate )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
if ( ! rate )
return ;
2022-02-12 14:56:28 +11:00
2022-02-14 17:05:52 +11:00
rate = abs ( rate ) ;
2022-02-12 14:56:28 +11:00
if ( abs ( ( short ) ( targetAngle - item - > Position . yRot ) ) > ANGLE ( 0.1f ) )
item - > Position . yRot + = ( short ) ( targetAngle - item - > Position . yRot ) / rate ;
else
item - > Position . yRot = targetAngle ;
2021-12-23 18:41:37 +11:00
}
2022-02-07 17:06:45 +11:00
void EaseOutLaraHeight ( ITEM_INFO * item , int height )
2021-10-09 14:39:06 +11:00
{
2022-02-07 17:06:45 +11:00
if ( height = = NO_HEIGHT )
2022-02-04 19:06:59 +11:00
return ;
2022-02-07 17:06:45 +11:00
// Translate Lara to new height.
// TODO: This approach may cause undesirable artefacts where an object pushes Lara rapidly up/down a slope or a platform rapidly ascends/descends.
2022-02-13 15:58:12 +11:00
static constexpr int rate = 50 ;
2022-02-09 13:20:57 +11:00
int threshold = std : : max ( abs ( item - > Velocity ) / 3 * 2 , STEP_SIZE / 16 ) ;
2022-02-07 17:06:45 +11:00
int sign = std : : copysign ( 1 , height ) ;
if ( TestEnvironment ( ENV_FLAG_SWAMP , item ) & & height > 0 )
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = SWAMP_GRAVITY ;
2022-02-07 17:06:45 +11:00
else if ( abs ( height ) > ( STEPUP_HEIGHT / 2 ) ) // Outer range.
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = rate * sign ;
2022-02-07 17:06:45 +11:00
else if ( abs ( height ) < = ( STEPUP_HEIGHT / 2 ) & & // Inner range.
abs ( height ) > = threshold )
{
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = std : : max < int > ( abs ( height / 2.75 ) , threshold ) * sign ;
2022-02-07 17:06:45 +11:00
}
else
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = height ;
2022-02-07 17:06:45 +11:00
}
// TODO: Some states can't make the most of this function due to missing step up/down animations.
// Try implementing leg IK as a substitute to make step animations obsolete. @Sezz 2021.10.09
void DoLaraStep ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-01-25 18:02:22 +11:00
if ( ! TestEnvironment ( ENV_FLAG_SWAMP , item ) )
2021-10-09 14:39:06 +11:00
{
2021-12-04 14:01:41 +11:00
if ( TestLaraStepUp ( item , coll ) )
2021-10-10 14:03:38 +11:00
{
2022-02-09 16:55:46 +11:00
item - > TargetState = LS_STEP_UP ;
if ( GetChange ( item , & g_Level . Anims [ item - > AnimNumber ] ) )
2021-12-04 14:01:41 +11:00
{
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = coll - > Middle . Floor ;
2021-12-04 14:01:41 +11:00
return ;
}
2021-10-10 14:03:38 +11:00
}
2021-12-04 14:01:41 +11:00
else if ( TestLaraStepDown ( item , coll ) )
2021-10-10 14:03:38 +11:00
{
2022-02-09 16:55:46 +11:00
item - > TargetState = LS_STEP_DOWN ;
if ( GetChange ( item , & g_Level . Anims [ item - > AnimNumber ] ) )
2021-12-04 14:01:41 +11:00
{
2022-02-09 16:55:46 +11:00
item - > Position . yPos + = coll - > Middle . Floor ;
2021-12-04 14:01:41 +11:00
return ;
}
2021-10-10 14:03:38 +11:00
}
2021-10-09 14:39:06 +11:00
}
2022-02-07 17:06:45 +11:00
EaseOutLaraHeight ( item , coll - > Middle . Floor ) ;
2021-10-09 14:39:06 +11:00
}
2022-01-16 13:56:39 +11:00
void DoLaraMonkeyStep ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-02-07 17:06:45 +11:00
EaseOutLaraHeight ( item , coll - > Middle . Ceiling ) ;
2022-01-16 13:56:39 +11:00
}
2022-01-03 17:57:57 +11:00
// TODO: Doesn't always work on bridges.
2021-10-18 15:22:38 +11:00
void DoLaraCrawlToHangSnap ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-02-09 16:55:46 +11:00
coll - > Setup . ForwardAngle = item - > Position . yRot + ANGLE ( 180.0f ) ;
2021-11-03 21:44:48 +11:00
GetCollisionInfo ( coll , item ) ;
SnapItemToLedge ( item , coll ) ;
2022-02-09 16:55:46 +11:00
MoveItem ( item , item - > Position . yRot , - LARA_RAD_CRAWL ) ;
item - > Position . yRot + = ANGLE ( 180.0f ) ;
2021-11-03 21:44:48 +11:00
LaraResetGravityStatus ( item , coll ) ;
2021-10-18 15:22:38 +11:00
}
2021-11-27 20:35:16 +11:00
void DoLaraCrawlFlex ( ITEM_INFO * item , COLL_INFO * coll , short maxAngle , short rate )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2021-11-27 20:35:16 +11:00
2022-02-09 13:20:57 +11:00
if ( ! item - > Velocity )
2021-12-14 14:35:42 +11:00
return ;
2021-11-27 20:35:16 +11:00
int sign = copysign ( 1 , maxAngle ) ;
rate = copysign ( rate , maxAngle ) ;
2022-02-15 21:25:24 +11:00
info - > ExtraTorsoRot . zRot + = std : : min ( abs ( rate ) , abs ( maxAngle - info - > ExtraTorsoRot . zRot ) / 6 ) * sign ;
2021-11-27 20:35:16 +11:00
if ( ! ( TrInput & IN_LOOK ) & &
2022-02-09 16:55:46 +11:00
item - > ActiveState ! = LS_CRAWL_BACK )
2021-11-27 20:35:16 +11:00
{
2022-02-15 21:25:24 +11:00
info - > ExtraHeadRot . zRot = info - > ExtraTorsoRot . zRot / 2 ;
info - > ExtraHeadRot . yRot = info - > ExtraHeadRot . zRot ;
2021-11-27 20:35:16 +11:00
}
}
2022-01-22 22:36:29 +11:00
void DoLaraFallDamage ( ITEM_INFO * item )
{
// TODO: Demagic more of these numbers.
2022-02-09 13:20:57 +11:00
int landSpeed = item - > VerticalVelocity - 140 ;
2022-01-22 22:36:29 +11:00
if ( landSpeed > 0 )
{
if ( landSpeed < = 14 )
2022-02-09 16:55:46 +11:00
item - > HitPoints - = LARA_HEALTH_MAX * pow ( landSpeed , 2 ) / 196 ;
2022-01-22 22:36:29 +11:00
else
2022-02-09 16:55:46 +11:00
item - > HitPoints = 0 ;
2022-01-22 22:36:29 +11:00
}
}
2022-02-12 00:25:05 +11:00
LaraInfo * & GetLaraInfo ( ITEM_INFO * item )
{
if ( item - > ObjectNumber ! = ID_LARA )
{
2022-02-14 17:05:52 +11:00
TENLog ( std : : string ( " Attempted to fetch LaraInfo data from item with object ID " ) + std : : to_string ( item - > ObjectNumber ) , LogLevel : : Warning ) ;
2022-02-12 00:25:05 +11:00
2022-02-14 17:05:52 +11:00
auto * firstLaraItem = FindItem ( ID_LARA ) ;
2022-02-13 15:58:12 +11:00
return ( LaraInfo * & ) firstLaraItem - > Data ;
2022-02-12 00:25:05 +11:00
}
return ( LaraInfo * & ) item - > Data ;
}
2022-01-23 18:16:29 +11:00
short GetLaraSlideDirection ( ITEM_INFO * item , COLL_INFO * coll )
2021-12-27 21:29:21 +11:00
{
2022-02-09 16:55:46 +11:00
short direction = item - > Position . yRot ;
2022-01-04 01:39:02 +11:00
2022-01-22 21:08:30 +11:00
//if (g_GameFlow->Animations.SlideExtended)
//{
// // TODO: Get true slope direction.
//}
//else
{
if ( coll - > FloorTiltX > 2 )
2022-01-23 18:16:29 +11:00
direction = - ANGLE ( 90.0f ) ;
2022-01-22 21:08:30 +11:00
else if ( coll - > FloorTiltX < - 2 )
2022-01-23 18:16:29 +11:00
direction = ANGLE ( 90.0f ) ;
2022-01-22 21:08:30 +11:00
if ( coll - > FloorTiltZ > 2 & & coll - > FloorTiltZ > abs ( coll - > FloorTiltX ) )
2022-01-23 18:16:29 +11:00
direction = ANGLE ( 180.0f ) ;
2022-01-22 21:08:30 +11:00
else if ( coll - > FloorTiltZ < - 2 & & - coll - > FloorTiltZ > abs ( coll - > FloorTiltX ) )
2022-02-12 20:23:45 +11:00
direction = 0 ;
2022-01-22 21:08:30 +11:00
}
2022-01-23 18:16:29 +11:00
return direction ;
2021-12-27 21:29:21 +11:00
}
2021-12-20 00:11:04 +11:00
void SetLaraJumpDirection ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2021-12-20 00:11:04 +11:00
if ( TrInput & IN_FORWARD & &
2022-01-02 15:54:43 +11:00
TestLaraJumpForward ( item , coll ) )
2021-12-20 00:11:04 +11:00
{
2022-02-10 01:38:32 +11:00
info - > Control . JumpDirection = JumpDirection : : Forward ;
2021-12-20 00:11:04 +11:00
}
else if ( TrInput & IN_BACK & &
2022-01-02 15:54:43 +11:00
TestLaraJumpBack ( item , coll ) )
2021-12-20 00:11:04 +11:00
{
2022-02-10 01:38:32 +11:00
info - > Control . JumpDirection = JumpDirection : : Back ;
2021-12-20 00:11:04 +11:00
}
else if ( TrInput & IN_LEFT & &
2022-01-02 15:54:43 +11:00
TestLaraJumpLeft ( item , coll ) )
2021-12-20 00:11:04 +11:00
{
2022-02-10 01:38:32 +11:00
info - > Control . JumpDirection = JumpDirection : : Left ;
2021-12-20 00:11:04 +11:00
}
else if ( TrInput & IN_RIGHT & &
2022-01-02 15:54:43 +11:00
TestLaraJumpRight ( item , coll ) )
2021-12-20 00:11:04 +11:00
{
2022-02-10 01:38:32 +11:00
info - > Control . JumpDirection = JumpDirection : : Right ;
2021-12-20 00:11:04 +11:00
}
2022-01-02 15:54:43 +11:00
else if ( TestLaraJumpUp ( item , coll ) ) [[likely]]
2022-02-10 01:38:32 +11:00
info - > Control . JumpDirection = JumpDirection : : Up ;
2021-12-20 00:11:04 +11:00
else
2022-02-10 16:18:15 +11:00
info - > Control . JumpDirection = JumpDirection : : None ;
2021-12-20 00:11:04 +11:00
}
2022-01-22 00:22:24 +11:00
// TODO: Add a timeout? Imagine a small, sad rain cloud with the properties of a ceiling following Lara overhead.
2022-02-10 01:38:32 +11:00
// RunJumpQueued will never reset, and when the sad cloud flies away after an indefinite amount of time, Lara will jump. @Sezz 2022.01.22
2022-01-22 00:22:24 +11:00
void SetLaraRunJumpQueue ( ITEM_INFO * item , COLL_INFO * coll )
2021-12-19 19:12:35 +11:00
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2021-12-19 19:12:35 +11:00
2022-02-09 16:55:46 +11:00
int y = item - > Position . yPos ;
2022-01-22 00:22:24 +11:00
int dist = WALL_SIZE ;
2022-02-09 16:55:46 +11:00
auto probe = GetCollisionResult ( item , item - > Position . yRot , dist , - coll - > Setup . Height ) ;
2021-12-19 19:12:35 +11:00
2022-01-22 00:22:24 +11:00
if ( ( TestLaraRunJumpForward ( item , coll ) | | // Area close ahead is permissive...
2022-02-02 21:59:34 +11:00
( probe . Position . Ceiling - y ) < - ( coll - > Setup . Height + ( LARA_HEADROOM * 0.8f ) ) | | // OR ceiling height is permissive far ahead
( probe . Position . Floor - y ) > = CLICK ( 0.5f ) ) & & // OR there is a drop below far ahead.
2022-01-04 16:25:12 +11:00
probe . Position . Floor ! = NO_HEIGHT )
2022-01-12 19:04:29 +11:00
{
2022-02-12 16:25:59 +11:00
info - > Control . RunJumpQueued = IsRunJumpQueueableState ( ( LaraState ) item - > TargetState ) ;
2022-01-12 19:04:29 +11:00
}
2021-12-19 19:12:35 +11:00
else
2022-02-10 01:38:32 +11:00
info - > Control . RunJumpQueued = false ;
2021-12-19 19:12:35 +11:00
}
2022-02-05 23:13:31 +11:00
void SetLaraVault ( ITEM_INFO * item , COLL_INFO * coll , VaultTestResult vaultResult )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2022-02-05 23:13:31 +11:00
2022-02-11 19:26:08 +11:00
info - > ProjectedFloorHeight = vaultResult . Height ;
2022-02-11 01:31:54 +11:00
info - > Control . HandStatus = vaultResult . SetBusyHands ? HandStatus : : Busy : info - > Control . HandStatus ;
2022-02-10 01:38:32 +11:00
info - > Control . TurnRate = 0 ;
2022-02-06 14:15:10 +11:00
2022-02-13 15:58:12 +11:00
// Disable smooth angle adjustment for now.
//info->Control.ApproachTargetAngle = vaultResult.ApproachLedgeAngle;
2022-02-06 14:15:10 +11:00
if ( vaultResult . SnapToLedge )
2022-02-17 02:00:40 +11:00
SnapItemToLedge ( item , coll , 0.2f ) ;
2022-02-05 23:13:31 +11:00
}
2022-01-22 21:08:30 +11:00
void SetLaraLand ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-02-09 13:20:57 +11:00
item - > Velocity = 0 ;
item - > VerticalVelocity = 0 ;
2022-02-18 21:43:45 +11:00
//item->Airborne = false; // TODO: Removing this addresses an unusual landing bug Core had worked around in an obscure way. I'd like to find a proper solution someday. @Sezz 2022.02.18
2022-01-22 21:08:30 +11:00
LaraSnapToHeight ( item , coll ) ;
}
2021-12-10 12:30:23 +11:00
void SetLaraFallState ( ITEM_INFO * item )
{
SetAnimation ( item , LA_FALL_START ) ;
2022-02-09 13:20:57 +11:00
item - > VerticalVelocity = 0 ;
item - > Airborne = true ;
2021-12-10 12:30:23 +11:00
}
void SetLaraFallBackState ( ITEM_INFO * item )
{
SetAnimation ( item , LA_FALL_BACK ) ;
2022-02-09 13:20:57 +11:00
item - > VerticalVelocity = 0 ;
item - > Airborne = true ;
2021-12-10 12:30:23 +11:00
}
2022-01-12 17:31:03 +11:00
void SetLaraMonkeyFallState ( ITEM_INFO * item )
{
2022-02-14 17:05:52 +11:00
// HACK: Disallow release during 180 turn action.
2022-02-09 16:55:46 +11:00
if ( item - > ActiveState = = LS_MONKEY_TURN_180 )
2022-01-19 16:17:16 +11:00
return ;
2022-01-26 17:48:50 +11:00
SetAnimation ( item , LA_MONKEY_TO_FREEFALL ) ;
2022-01-19 16:17:16 +11:00
SetLaraMonkeyRelease ( item ) ;
}
void SetLaraMonkeyRelease ( ITEM_INFO * item )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2022-01-19 16:17:16 +11:00
2022-02-09 13:20:57 +11:00
item - > Velocity = 2 ;
item - > VerticalVelocity = 1 ;
item - > Airborne = true ;
2022-02-11 01:31:54 +11:00
info - > Control . HandStatus = HandStatus : : Free ;
2022-01-12 17:31:03 +11:00
}
2021-12-18 20:42:15 +11:00
void SetLaraSlideState ( ITEM_INFO * item , COLL_INFO * coll )
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2021-12-18 20:42:15 +11:00
2022-01-23 18:16:29 +11:00
short direction = GetLaraSlideDirection ( item , coll ) ;
2022-02-09 16:55:46 +11:00
short delta = direction - item - > Position . yRot ;
2021-12-18 20:42:15 +11:00
static short oldAngle = 1 ;
ShiftItem ( item , coll ) ;
if ( delta < - ANGLE ( 90.0f ) | | delta > ANGLE ( 90.0f ) )
{
2022-02-09 16:55:46 +11:00
if ( item - > ActiveState = = LS_SLIDE_BACK & & oldAngle = = direction )
2021-12-18 20:42:15 +11:00
return ;
SetAnimation ( item , LA_SLIDE_BACK_START ) ;
2022-02-09 16:55:46 +11:00
item - > Position . yRot = direction + ANGLE ( 180.0f ) ;
2021-12-18 20:42:15 +11:00
}
else
{
2022-02-09 16:55:46 +11:00
if ( item - > ActiveState = = LS_SLIDE_FORWARD & & oldAngle = = direction )
2021-12-18 20:42:15 +11:00
return ;
SetAnimation ( item , LA_SLIDE_FORWARD ) ;
2022-02-09 16:55:46 +11:00
item - > Position . yRot = direction ;
2021-12-18 20:42:15 +11:00
}
2022-01-23 15:06:05 +11:00
LaraSnapToHeight ( item , coll ) ;
2022-02-10 01:38:32 +11:00
info - > Control . MoveAngle = direction ;
2022-01-23 15:06:05 +11:00
oldAngle = direction ;
2021-12-18 20:42:15 +11:00
}
2022-02-12 00:25:05 +11:00
void ResetLaraLean ( ITEM_INFO * item , float rate , bool resetRoll , bool resetPitch )
{
2022-02-14 17:05:52 +11:00
if ( ! rate )
return ;
2022-02-12 00:25:05 +11:00
2022-02-14 17:05:52 +11:00
rate = abs ( rate ) ;
2022-02-12 00:25:05 +11:00
if ( resetPitch )
{
if ( abs ( item - > Position . xRot ) > ANGLE ( 0.1f ) )
item - > Position . xRot + = item - > Position . xRot / - rate ;
else
item - > Position . xRot = 0 ;
}
2022-02-14 17:05:52 +11:00
if ( resetRoll )
{
if ( abs ( item - > Position . zRot ) > ANGLE ( 0.1f ) )
item - > Position . zRot + = item - > Position . zRot / - rate ;
else
item - > Position . zRot = 0 ;
}
2022-02-12 00:25:05 +11:00
}
2021-12-10 12:30:23 +11:00
void ResetLaraFlex ( ITEM_INFO * item , float rate )
2021-11-27 23:15:26 +11:00
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
if ( ! rate )
return ;
2022-02-12 00:25:05 +11:00
2022-02-14 17:05:52 +11:00
rate = abs ( rate ) ;
2021-11-27 23:15:26 +11:00
// Reset head.
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraHeadRot . xRot ) > ANGLE ( 0.1f ) )
info - > ExtraHeadRot . xRot + = info - > ExtraHeadRot . xRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraHeadRot . xRot = 0 ;
2021-11-27 23:15:26 +11:00
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraHeadRot . yRot ) > ANGLE ( 0.1f ) )
info - > ExtraHeadRot . yRot + = info - > ExtraHeadRot . yRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraHeadRot . yRot = 0 ;
2021-11-27 23:15:26 +11:00
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraHeadRot . zRot ) > ANGLE ( 0.1f ) )
info - > ExtraHeadRot . zRot + = info - > ExtraHeadRot . zRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraHeadRot . zRot = 0 ;
2021-11-27 23:15:26 +11:00
// Reset torso.
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraTorsoRot . xRot ) > ANGLE ( 0.1f ) )
info - > ExtraTorsoRot . xRot + = info - > ExtraTorsoRot . xRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraTorsoRot . xRot = 0 ;
2021-11-27 23:15:26 +11:00
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraTorsoRot . yRot ) > ANGLE ( 0.1f ) )
info - > ExtraTorsoRot . yRot + = info - > ExtraTorsoRot . yRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraTorsoRot . yRot = 0 ;
2021-11-27 23:15:26 +11:00
2022-02-15 21:25:24 +11:00
if ( abs ( info - > ExtraTorsoRot . zRot ) > ANGLE ( 0.1f ) )
info - > ExtraTorsoRot . zRot + = info - > ExtraTorsoRot . zRot / - rate ;
2021-11-27 23:15:26 +11:00
else
2022-02-15 21:25:24 +11:00
info - > ExtraTorsoRot . zRot = 0 ;
2021-11-27 23:15:26 +11:00
}
2021-12-10 12:30:23 +11:00
void HandleLaraMovementParameters ( ITEM_INFO * item , COLL_INFO * coll )
2021-09-27 18:18:03 +10:00
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2021-09-27 18:18:03 +10:00
2021-12-10 12:30:23 +11:00
// Reset running jump timer.
2022-02-12 16:25:59 +11:00
if ( ! IsRunJumpCountableState ( ( LaraState ) item - > ActiveState ) )
2022-02-11 19:26:08 +11:00
info - > Control . Count . RunJump = 0 ;
2022-02-04 22:18:55 +11:00
2022-01-03 17:01:07 +11:00
// Reset running jump action queue.
2022-02-12 16:25:59 +11:00
if ( ! IsRunJumpQueueableState ( ( LaraState ) item - > ActiveState ) )
2022-02-10 01:38:32 +11:00
info - > Control . RunJumpQueued = false ;
2021-12-12 13:27:26 +11:00
2021-12-10 12:30:23 +11:00
// Increment/reset AFK pose timer.
2022-02-11 19:26:08 +11:00
if ( info - > Control . Count . Pose < LARA_POSE_TIME & &
2021-12-10 12:30:23 +11:00
TestLaraPose ( item , coll ) & &
! ( TrInput & ( IN_WAKE | IN_LOOK ) ) & &
g_GameFlow - > Animations . Pose )
{
2022-02-11 19:26:08 +11:00
info - > Control . Count . Pose + + ;
2021-12-10 12:30:23 +11:00
}
else
2022-02-11 19:26:08 +11:00
info - > Control . Count . Pose = 0 ;
2021-12-10 12:30:23 +11:00
// Reset lean.
2022-02-10 01:38:32 +11:00
if ( ! info - > Control . IsMoving | | ( info - > Control . IsMoving & & ! ( TrInput & ( IN_LEFT | IN_RIGHT ) ) ) )
2022-02-12 00:25:05 +11:00
ResetLaraLean ( item , 6 ) ;
2021-12-22 16:00:13 +11:00
2021-12-10 12:30:23 +11:00
// Reset crawl flex.
if ( ! ( TrInput & IN_LOOK ) & &
2021-12-10 22:31:34 +11:00
coll - > Setup . Height > LARA_HEIGHT - LARA_HEADROOM & &
2022-02-09 13:20:57 +11:00
( ! item - > Velocity | | ( item - > Velocity & & ! ( TrInput & ( IN_LEFT | IN_RIGHT ) ) ) ) )
2021-12-10 12:30:23 +11:00
{
ResetLaraFlex ( item , 12 ) ;
}
// Reset turn rate.
2022-02-10 01:38:32 +11:00
int sign = copysign ( 1 , info - > Control . TurnRate ) ;
if ( abs ( info - > Control . TurnRate ) > ANGLE ( 2.0f ) )
info - > Control . TurnRate - = ANGLE ( 2.0f ) * sign ;
else if ( abs ( info - > Control . TurnRate ) > ANGLE ( 0.5f ) )
info - > Control . TurnRate - = ANGLE ( 0.5f ) * sign ;
2021-12-10 12:30:23 +11:00
else
2022-02-10 01:38:32 +11:00
info - > Control . TurnRate = 0 ;
item - > Position . yRot + = info - > Control . TurnRate ;
2021-10-14 19:58:29 +11:00
}
2022-02-08 01:26:59 +11:00
2022-02-08 20:45:21 +11:00
void HandleLaraVehicle ( ITEM_INFO * item , COLL_INFO * coll )
2022-02-08 01:26:59 +11:00
{
2022-02-14 17:05:52 +11:00
auto * info = GetLaraInfo ( item ) ;
2022-02-08 01:26:59 +11:00
if ( info - > Vehicle ! = NO_ITEM )
{
2022-02-09 16:55:46 +11:00
switch ( g_Level . Items [ info - > Vehicle ] . ObjectNumber )
2022-02-08 01:26:59 +11:00
{
case ID_QUAD :
if ( QuadBikeControl ( item , coll ) )
return ;
break ;
case ID_JEEP :
if ( JeepControl ( ) )
return ;
break ;
case ID_MOTORBIKE :
if ( MotorbikeControl ( ) )
return ;
break ;
case ID_KAYAK :
if ( KayakControl ( item ) )
return ;
break ;
case ID_SNOWMOBILE :
if ( SkidooControl ( item , coll ) )
return ;
break ;
case ID_UPV :
if ( SubControl ( item , coll ) )
return ;
break ;
case ID_MINECART :
if ( MineCartControl ( ) )
return ;
break ;
case ID_BIGGUN :
if ( BigGunControl ( item , coll ) )
return ;
break ;
// Boats are processed like normal items in loop.
default :
LaraGun ( item ) ;
return ;
}
}
}