2020-09-26 05:06:08 +10:00
# include "framework.h"
# include "lara.h"
# include "lara_tests.h"
# include "input.h"
2021-09-19 18:29:25 +03:00
# include "level.h"
2021-09-16 05:06:03 +03:00
# include "animation.h"
2020-09-26 05:06:08 +10:00
# include "lara_climb.h"
# include "lara_collide.h"
2021-09-27 18:18:03 +10:00
# include "lara_flare.h"
2021-09-19 23:41:26 +03:00
# include "control/control.h"
2021-09-27 18:18:03 +10:00
# include "control/los.h"
2021-09-25 16:00:30 +03:00
# include "items.h"
2021-10-08 00:54:00 +03:00
# include "Renderer11.h"
2021-09-25 11:27:47 +02:00
2021-10-08 00:54:00 +03:00
using namespace TEN : : Renderer ;
2021-08-30 18:03:21 +03:00
using namespace TEN : : Floordata ;
2021-01-17 15:56:48 -03:00
2020-09-26 05:06:08 +10:00
static short LeftClimbTab [ 4 ] = // offset 0xA0638
{
0x0200 , 0x0400 , 0x0800 , 0x0100
} ;
static short RightClimbTab [ 4 ] = // offset 0xA0640
{
0x0800 , 0x0100 , 0x0200 , 0x0400
} ;
/*this file has all the generic test functions called in lara's state code*/
2021-10-07 16:45:26 +03:00
// Test if a ledge in front of item is valid to climb.
bool TestValidLedge ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
2021-10-07 19:49:59 +03:00
// Determine probe base point.
// We use double-radius here for two purposes. First - we can't guarantee that
// shifts weren't already applied and misfire may occur. Second - it guarantees
// that Lara won't land on a very thin edge of diagonal geometry.
2020-09-26 05:06:08 +10:00
2021-10-07 19:39:41 +03:00
int xf = phd_sin ( coll - > NearestLedgeAngle ) * ( coll - > Setup . Radius * 2 ) ;
int zf = phd_cos ( coll - > NearestLedgeAngle ) * ( coll - > Setup . Radius * 2 ) ;
2020-09-26 05:06:08 +10:00
2021-10-07 19:49:59 +03:00
// Determine probe left/right points
2021-10-07 19:39:41 +03:00
int xl = xf + phd_sin ( coll - > NearestLedgeAngle - ANGLE ( 90 ) ) * coll - > Setup . Radius ;
int zl = zf + phd_cos ( coll - > NearestLedgeAngle - ANGLE ( 90 ) ) * coll - > Setup . Radius ;
int xr = xf + phd_sin ( coll - > NearestLedgeAngle + ANGLE ( 90 ) ) * coll - > Setup . Radius ;
int zr = zf + phd_cos ( coll - > NearestLedgeAngle + ANGLE ( 90 ) ) * coll - > Setup . Radius ;
2020-09-26 05:06:08 +10:00
2021-10-08 00:54:00 +03:00
// Determine probe top point
int y = item - > pos . yPos - coll - > Setup . Height ;
2020-09-26 05:06:08 +10:00
2021-10-07 19:49:59 +03:00
// Get floor heights at both points
2021-10-08 00:54:00 +03:00
auto left = GetCollisionResult ( item - > pos . xPos + xl , y , item - > pos . zPos + zl , GetRoom ( item - > location , item - > pos . xPos , y , item - > pos . zPos ) . roomNumber ) . Position . Floor ;
auto right = GetCollisionResult ( item - > pos . xPos + xr , y , item - > pos . zPos + zr , GetRoom ( item - > location , item - > pos . xPos , y , item - > pos . zPos ) . roomNumber ) . Position . Floor ;
2021-10-07 14:36:41 +03:00
2021-10-08 00:54:00 +03:00
//g_Renderer.addDebugSphere(Vector3(item->pos.xPos + xl, left, item->pos.zPos + zl), 64, Vector4::One, RENDERER_DEBUG_PAGE::LOGIC_STATS);
//g_Renderer.addDebugSphere(Vector3(item->pos.xPos + xr, right, item->pos.zPos + zr), 64, Vector4::One, RENDERER_DEBUG_PAGE::LOGIC_STATS);
2021-10-07 16:45:26 +03:00
2021-10-07 19:49:59 +03:00
// Determine allowed slope difference for a given collision radius
auto slopeDelta = ( ( float ) STEPUP_HEIGHT / ( float ) WALL_SIZE ) * ( coll - > Setup . Radius * 2 ) ;
2021-10-07 16:45:26 +03:00
2021-10-07 19:49:59 +03:00
// Discard if there is a slope beyond tolerance delta
if ( abs ( left - right ) > = slopeDelta )
2021-10-07 16:45:26 +03:00
return false ;
2021-10-08 01:16:49 +03:00
if ( abs ( ( short ) ( coll - > NearestLedgeAngle - coll - > Setup . ForwardAngle ) ) > LARA_GRAB_THRESHOLD )
2021-10-07 23:58:29 +03:00
return false ;
auto headroom = ( coll - > Front . Floor + coll - > Setup . Height ) - coll - > Middle . Ceiling ;
if ( headroom < STEP_SIZE )
2021-10-07 19:49:59 +03:00
return false ;
2021-10-07 16:45:26 +03:00
return ( coll - > CollisionType = = CT_FRONT ) ;
}
2020-09-26 05:06:08 +10:00
2021-09-13 23:44:52 +03:00
bool TestLaraVault ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
if ( ! ( TrInput & IN_ACTION ) | | Lara . gunStatus ! = LG_NO_ARMS )
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
2021-10-08 01:46:29 +03:00
// TODO: Enable with lua!
Lara . NewAnims . CrawlVault1click = 1 ;
Lara . NewAnims . CrawlVault2click = 1 ;
Lara . NewAnims . CrawlVault3click = 1 ;
Lara . NewAnims . MonkeyVault = 1 ;
2020-09-26 05:06:08 +10:00
2021-10-07 16:45:26 +03:00
if ( TestValidLedge ( item , coll ) )
2020-09-26 05:06:08 +10:00
{
2021-10-10 20:59:12 +11:00
if ( coll - > Front . Floor < 0 & & coll - > Front . Floor > = - 256 & & Lara . NewAnims . CrawlVault1click )
2020-09-26 05:06:08 +10:00
{
2021-10-07 16:45:26 +03:00
if ( Lara . NewAnims . CrawlVault1click & & ( abs ( coll - > Front . Ceiling - coll - > Front . Floor ) < 256 ) )
2020-09-26 05:06:08 +10:00
{
item - > animNumber = LA_VAULT_TO_CROUCH_1CLICK ;
item - > currentAnimState = LS_GRABBING ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_CROUCH_IDLE ;
2021-09-10 00:18:47 +03:00
item - > pos . yPos + = coll - > Front . Floor + 256 ;
2020-09-26 05:06:08 +10:00
Lara . gunStatus = LG_HANDS_BUSY ;
}
}
2021-09-10 00:18:47 +03:00
else if ( coll - > Front . Floor > = - 640 & & coll - > Front . Floor < = - 384 )
2020-09-26 05:06:08 +10:00
{
2021-10-07 16:45:26 +03:00
if ( coll - > Front . Floor - coll - > Front . Ceiling > = 0 & &
2021-09-10 00:18:47 +03:00
coll - > FrontLeft . Floor - coll - > FrontLeft . Ceiling > = 0 & &
2021-10-07 11:01:39 +03:00
coll - > FrontRight . Floor - coll - > FrontRight . Ceiling > = 0 )
2020-09-26 05:06:08 +10:00
{
#if 0
if ( g_Level . Rooms [ item - > roomNumber ] . flags & ENV_FLAG_SWAMP & & Lara . waterSurfaceDist < - 768 )
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
# endif
item - > animNumber = LA_VAULT_TO_STAND_2CLICK_START ;
item - > currentAnimState = LS_GRABBING ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_STOP ;
2021-09-10 00:18:47 +03:00
item - > pos . yPos + = coll - > Front . Floor + 512 ;
2020-09-26 05:06:08 +10:00
Lara . gunStatus = LG_HANDS_BUSY ;
}
2021-10-07 16:45:26 +03:00
else if ( Lara . NewAnims . CrawlVault2click & & ( abs ( coll - > Front . Ceiling - coll - > Front . Floor ) < 256 ) )
2020-09-26 05:06:08 +10:00
{
item - > animNumber = LA_VAULT_TO_CROUCH_2CLICK ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > currentAnimState = LS_GRABBING ;
item - > goalAnimState = LS_CROUCH_IDLE ;
2021-09-10 00:18:47 +03:00
item - > pos . yPos + = coll - > Front . Floor + 512 ;
2020-09-26 05:06:08 +10:00
Lara . gunStatus = LG_HANDS_BUSY ;
}
else
{
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
}
2021-09-10 00:18:47 +03:00
else if ( coll - > Front . Floor > = - 896 & & coll - > Front . Floor < = - 640 )
2020-09-26 05:06:08 +10:00
{
2021-10-07 16:45:26 +03:00
if ( coll - > Front . Floor - coll - > Front . Ceiling > = 0 & &
2021-09-10 00:18:47 +03:00
coll - > FrontLeft . Floor - coll - > FrontLeft . Ceiling > = 0 & &
2021-10-07 11:01:39 +03:00
coll - > FrontRight . Floor - coll - > FrontRight . Ceiling > = 0 )
2020-09-26 05:06:08 +10:00
{
#if 0
if ( g_Level . Rooms [ item - > roomNumber ] . flags & ENV_FLAG_SWAMP & & Lara . waterSurfaceDist < - 768 )
return 0 ;
# endif
item - > animNumber = LA_VAULT_TO_STAND_3CLICK ;
item - > currentAnimState = LS_GRABBING ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_STOP ;
2021-09-10 00:18:47 +03:00
item - > pos . yPos + = coll - > Front . Floor + 768 ;
2020-09-26 05:06:08 +10:00
Lara . gunStatus = LG_HANDS_BUSY ;
}
2021-10-07 16:45:26 +03:00
else if ( Lara . NewAnims . CrawlVault3click & & ( abs ( coll - > Front . Ceiling - coll - > Front . Floor ) < 256 ) )
2020-09-26 05:06:08 +10:00
{
item - > animNumber = LA_VAULT_TO_CROUCH_3CLICK ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > currentAnimState = LS_GRABBING ;
item - > goalAnimState = LS_CROUCH_IDLE ;
2021-09-10 00:18:47 +03:00
item - > pos . yPos + = coll - > Front . Floor + 768 ;
2020-09-26 05:06:08 +10:00
Lara . gunStatus = LG_HANDS_BUSY ;
}
else
{
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
}
2021-10-07 16:45:26 +03:00
else if ( coll - > Front . Floor > = - 1920 & & coll - > Front . Floor < = - 896 )
2020-09-26 05:06:08 +10:00
{
#if 0
if ( g_Level . Rooms [ item - > roomNumber ] . flags & ENV_FLAG_SWAMP )
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
# endif
item - > animNumber = LA_STAND_SOLID ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_JUMP_UP ;
item - > currentAnimState = LS_STOP ;
2021-09-10 00:18:47 +03:00
Lara . calcFallSpeed = - 3 - sqrt ( - 9600 - 12 * coll - > Front . Floor ) ;
2020-09-26 05:06:08 +10:00
AnimateLara ( item ) ;
}
2021-10-09 01:55:22 +03:00
item - > pos . yRot = coll - > NearestLedgeAngle ;
ShiftItem ( item , coll ) ;
item - > pos . xPos + = phd_sin ( coll - > NearestLedgeAngle ) * coll - > NearestLedgeDistance ;
item - > pos . zPos + = phd_cos ( coll - > NearestLedgeAngle ) * coll - > NearestLedgeDistance ;
return true ;
}
else if ( Lara . climbStatus )
{
if ( coll - > Front . Floor > - 1920 | | Lara . waterStatus = = LW_WADE | | coll - > FrontLeft . Floor > - 1920 | | coll - > FrontRight . Floor > - 2048 | | coll - > Middle . Ceiling > - 1158 )
{
if ( ( coll - > Front . Floor < - 1024 | | coll - > Front . Ceiling > = 506 ) & & coll - > Middle . Ceiling < = - 518 )
2020-09-26 05:06:08 +10:00
{
2021-10-09 01:55:22 +03:00
ShiftItem ( item , coll ) ;
if ( TestLaraClimbStance ( item , coll ) )
2020-09-26 05:06:08 +10:00
{
2021-10-09 01:55:22 +03:00
item - > animNumber = LA_STAND_SOLID ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_LADDER_IDLE ;
item - > currentAnimState = LS_STOP ;
AnimateLara ( item ) ;
item - > pos . yRot = coll - > NearestLedgeAngle ;
Lara . gunStatus = LG_HANDS_BUSY ;
return true ;
2020-09-26 05:06:08 +10:00
}
}
2021-10-09 01:55:22 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-10-09 01:55:22 +03:00
item - > animNumber = LA_STAND_SOLID ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_JUMP_UP ;
item - > currentAnimState = LS_STOP ;
Lara . calcFallSpeed = - 116 ;
AnimateLara ( item ) ;
2021-10-07 16:45:26 +03:00
item - > pos . yRot = coll - > NearestLedgeAngle ;
2020-09-26 05:06:08 +10:00
ShiftItem ( item , coll ) ;
2021-10-07 17:34:12 +03:00
item - > pos . xPos + = phd_sin ( coll - > NearestLedgeAngle ) * coll - > NearestLedgeDistance ;
item - > pos . zPos + = phd_cos ( coll - > NearestLedgeAngle ) * coll - > NearestLedgeDistance ;
2021-09-13 20:19:33 +02:00
2021-09-13 23:44:52 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
2021-10-09 01:55:22 +03:00
else if ( Lara . NewAnims . MonkeyVault & & Lara . canMonkeySwing )
2020-09-26 05:06:08 +10:00
{
2021-10-09 01:55:22 +03:00
short roomNum = item - > roomNumber ;
int ceiling = ( GetCeiling ( GetFloor ( item - > pos . xPos , item - > pos . yPos , item - > pos . zPos , & roomNum ) ,
item - > pos . xPos , item - > pos . yPos , item - > pos . zPos ) ) - ( item - > pos . yPos ) ;
2021-07-08 14:15:14 -05:00
2021-10-09 01:55:22 +03:00
if ( ceiling > 1792 | | ceiling < - 1792 | | abs ( ceiling ) = = 768 )
return false ;
2021-07-08 14:15:14 -05:00
2021-10-09 01:55:22 +03:00
item - > animNumber = LA_STAND_IDLE ;
item - > frameNumber = g_Level . Anims [ LA_STAND_IDLE ] . frameBase ;
item - > goalAnimState = LS_JUMP_UP ;
item - > currentAnimState = LS_TEST_1 ;
return true ;
2020-09-26 05:06:08 +10:00
}
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-10-16 21:52:45 +11:00
bool TestLaraKeepDucked ( COLL_INFO * coll )
2021-09-09 20:21:05 +03:00
{
2021-10-15 21:59:41 +11:00
// TODO: Cannot use as a failsafe; this is bugged with slanted ceilings reaching the ground. @Sezz 2021.10.15
2021-10-16 21:52:45 +11:00
if ( coll - > Middle . Ceiling > = - LARA_HEIGHT_CRAWL ) // Was -362.
2021-10-15 21:59:41 +11:00
return true ;
return false ;
2021-09-09 20:21:05 +03:00
}
2021-09-27 18:18:03 +10:00
// LEGACY
// TODO: Gradually replace calls with new TestLaraSlide() (currently TestLaraSlideNew()) and SetLaraSlideState(). @Sezz 2021.09.27
2021-09-13 09:12:46 +03:00
bool TestLaraSlide ( ITEM_INFO * item , COLL_INFO * coll )
{
static short oldAngle = 1 ;
if ( abs ( coll - > TiltX ) < = 2 & & abs ( coll - > TiltZ ) < = 2 )
return false ;
short angle = ANGLE ( 0.0f ) ;
if ( coll - > TiltX > 2 )
angle = - ANGLE ( 90.0f ) ;
else if ( coll - > TiltX < - 2 )
angle = ANGLE ( 90.0f ) ;
if ( coll - > TiltZ > 2 & & coll - > TiltZ > abs ( coll - > TiltX ) )
angle = ANGLE ( 180.0f ) ;
else if ( coll - > TiltZ < - 2 & & - coll - > TiltZ > abs ( coll - > TiltX ) )
angle = ANGLE ( 0.0f ) ;
short delta = angle - item - > pos . yRot ;
ShiftItem ( item , coll ) ;
if ( delta < - ANGLE ( 90.0f ) | | delta > ANGLE ( 90.0f ) )
{
if ( item - > currentAnimState = = LS_SLIDE_BACK & & oldAngle = = angle )
return true ;
item - > animNumber = LA_SLIDE_BACK_START ;
item - > goalAnimState = LS_SLIDE_BACK ;
item - > currentAnimState = LS_SLIDE_BACK ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > pos . yRot = angle + ANGLE ( 180.0f ) ;
}
else
{
if ( item - > currentAnimState = = LS_SLIDE_FORWARD & & oldAngle = = angle )
return true ;
item - > animNumber = LA_SLIDE_FORWARD ;
item - > goalAnimState = LS_SLIDE_FORWARD ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > currentAnimState = LS_SLIDE_FORWARD ;
item - > pos . yRot = angle ;
}
Lara . moveAngle = angle ;
oldAngle = angle ;
return true ;
}
2021-09-14 00:41:11 +03:00
SPLAT_COLL TestLaraWall ( ITEM_INFO * item , int front , int right , int down )
2020-09-26 05:06:08 +10:00
{
int x = item - > pos . xPos ;
int y = item - > pos . yPos + down ;
int z = item - > pos . zPos ;
short angle = GetQuadrant ( item - > pos . yRot ) ;
short roomNum = item - > roomNumber ;
FLOOR_INFO * floor ;
int h , c ;
switch ( angle )
{
case NORTH :
x - = right ;
break ;
case EAST :
z - = right ;
break ;
case SOUTH :
x + = right ;
break ;
case WEST :
z + = right ;
break ;
default :
break ;
}
GetFloor ( x , y , z , & roomNum ) ;
switch ( angle )
{
case NORTH :
z + = front ;
break ;
case EAST :
x + = front ;
break ;
case SOUTH :
z - = front ;
break ;
case WEST :
x - = front ;
break ;
default :
break ;
}
floor = GetFloor ( x , y , z , & roomNum ) ;
h = GetFloorHeight ( floor , x , y , z ) ;
c = GetCeiling ( floor , x , y , z ) ;
if ( h = = NO_HEIGHT )
2021-09-13 23:44:52 +03:00
return SPLAT_COLL : : SPLAT_WALL ;
2020-09-26 05:06:08 +10:00
if ( y > = h | | y < = c )
2021-09-13 23:44:52 +03:00
return SPLAT_COLL : : SPLAT_STEP ;
2020-09-26 05:06:08 +10:00
2021-09-13 23:44:52 +03:00
return SPLAT_COLL : : SPLAT_NONE ;
2020-09-26 05:06:08 +10:00
}
2021-09-14 00:30:44 +03:00
bool TestLaraHang ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
ANIM_FRAME * frame ;
2021-09-14 00:03:24 +03:00
auto delta = 0 ;
auto flag = 0 ;
auto angle = Lara . moveAngle ;
2020-12-19 23:34:52 -03:00
if ( angle = = ( short ) ( item - > pos . yRot - ANGLE ( 90 ) ) )
2020-09-26 05:06:08 +10:00
{
delta = - 100 ;
}
2020-12-19 23:34:52 -03:00
else if ( angle = = ( short ) ( item - > pos . yRot + ANGLE ( 90 ) ) )
2020-09-26 05:06:08 +10:00
{
delta = 100 ;
}
2021-09-14 00:03:24 +03:00
auto hdif = LaraFloorFront ( item , angle , 100 ) ;
2020-09-26 05:06:08 +10:00
if ( hdif < 200 )
flag = 1 ;
2021-09-14 00:03:24 +03:00
auto cdif = LaraCeilingFront ( item , angle , 100 , 0 ) ;
auto dir = GetQuadrant ( item - > pos . yRot ) ;
2020-09-26 05:06:08 +10:00
switch ( dir )
{
case NORTH :
item - > pos . zPos + = 4 ;
break ;
case EAST :
item - > pos . xPos + = 4 ;
break ;
case SOUTH :
item - > pos . zPos - = 4 ;
break ;
case WEST :
item - > pos . xPos - = 4 ;
break ;
}
2021-09-14 00:03:24 +03:00
Lara . moveAngle = item - > pos . yRot ;
2021-09-19 17:48:32 +03:00
coll - > Setup . BadHeightDown = NO_BAD_POS ;
coll - > Setup . BadHeightUp = - STEPUP_HEIGHT ;
2021-09-10 00:20:59 +03:00
coll - > Setup . BadCeilingHeight = 0 ;
coll - > Setup . ForwardAngle = Lara . moveAngle ;
2021-09-14 00:03:24 +03:00
2021-09-19 06:42:24 +03:00
GetCollisionInfo ( coll , item ) ;
2021-09-14 00:03:24 +03:00
2021-09-16 01:56:02 +03:00
bool result = false ;
2020-09-26 05:06:08 +10:00
if ( Lara . climbStatus )
{
if ( TrInput & IN_ACTION & & item - > hitPoints > 0 )
{
Lara . moveAngle = angle ;
2021-09-14 00:03:24 +03:00
2021-09-14 00:30:44 +03:00
if ( ! TestLaraHangOnClimbWall ( item , coll ) )
2020-09-26 05:06:08 +10:00
{
if ( item - > animNumber ! = LA_LADDER_TO_HANG_RIGHT & & item - > animNumber ! = LA_LADDER_TO_HANG_LEFT )
{
2021-09-25 13:00:14 +03:00
LaraSnapToEdgeOfBlock ( item , coll , dir ) ;
2021-09-10 00:20:59 +03:00
item - > pos . yPos = coll - > Setup . OldPosition . y ;
2020-09-26 05:06:08 +10:00
item - > currentAnimState = LS_HANG ;
item - > goalAnimState = LS_HANG ;
item - > animNumber = LA_REACH_TO_HANG ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase + 21 ;
}
2021-09-14 00:03:24 +03:00
result = true ;
2020-09-26 05:06:08 +10:00
}
else
{
2021-09-14 00:30:44 +03:00
if ( item - > animNumber = = LA_REACH_TO_HANG & & item - > frameNumber = = g_Level . Anims [ LA_REACH_TO_HANG ] . frameBase + 21 & & TestLaraClimbStance ( item , coll ) )
2020-09-26 05:06:08 +10:00
item - > goalAnimState = LS_LADDER_IDLE ;
}
}
else
{
item - > animNumber = LA_FALL_START ;
item - > currentAnimState = LS_JUMP_FORWARD ;
item - > goalAnimState = LS_JUMP_FORWARD ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > pos . yPos + = 256 ;
item - > gravityStatus = true ;
item - > speed = 2 ;
item - > fallspeed = 1 ;
Lara . gunStatus = LG_NO_ARMS ;
}
}
else
{
2021-09-10 00:18:47 +03:00
if ( TrInput & IN_ACTION & & item - > hitPoints > 0 & & coll - > Front . Floor < = 0 )
2020-09-26 05:06:08 +10:00
{
2021-09-10 00:18:47 +03:00
if ( flag & & hdif > 0 & & delta > 0 = = coll - > MiddleLeft . Floor > coll - > MiddleRight . Floor )
2020-09-26 05:06:08 +10:00
flag = 0 ;
2021-09-14 00:03:24 +03:00
2020-09-26 05:06:08 +10:00
frame = ( ANIM_FRAME * ) GetBoundsAccurate ( item ) ;
2021-09-14 00:03:24 +03:00
auto front = coll - > Front . Floor ;
auto dfront = coll - > Front . Floor - frame - > boundingBox . Y1 ;
auto flag2 = 0 ;
auto x = item - > pos . xPos ;
auto z = item - > pos . zPos ;
2020-09-26 05:06:08 +10:00
switch ( dir )
{
case NORTH :
x + = delta ;
break ;
case EAST :
z - = delta ;
break ;
case SOUTH :
x - = delta ;
break ;
case WEST :
z + = delta ;
break ;
}
2021-09-14 00:03:24 +03:00
2020-09-26 05:06:08 +10:00
Lara . moveAngle = angle ;
2021-09-14 00:03:24 +03:00
2021-08-20 02:01:50 +03:00
if ( 256 < < dir & GetClimbFlags ( x , item - > pos . yPos , z , item - > roomNumber ) )
2020-09-26 05:06:08 +10:00
{
2021-09-14 00:30:44 +03:00
if ( ! TestLaraHangOnClimbWall ( item , coll ) )
2020-09-26 05:06:08 +10:00
dfront = 0 ;
}
2021-09-10 00:18:47 +03:00
else if ( abs ( coll - > FrontLeft . Floor - coll - > FrontRight . Floor ) > = 60 )
2020-09-26 05:06:08 +10:00
{
2021-09-10 00:18:47 +03:00
if ( delta < 0 & & coll - > FrontLeft . Floor ! = coll - > Front . Floor | | delta > 0 & & coll - > FrontRight . Floor ! = coll - > Front . Floor )
2020-09-26 05:06:08 +10:00
flag2 = 1 ;
}
2021-09-14 00:03:24 +03:00
2021-09-10 00:18:47 +03:00
coll - > Front . Floor = front ;
2021-09-14 00:03:24 +03:00
2021-09-10 00:18:47 +03:00
if ( ! flag2 & & coll - > Middle . Ceiling < 0 & & coll - > CollisionType = = CT_FRONT & & ! flag & & ! coll - > HitStatic & & cdif < = - 950 & & dfront > = - 60 & & dfront < = 60 )
2020-09-26 05:06:08 +10:00
{
switch ( dir )
{
case NORTH :
case SOUTH :
2021-09-10 00:18:47 +03:00
item - > pos . zPos + = coll - > Shift . z ;
2020-09-26 05:06:08 +10:00
break ;
case EAST :
case WEST :
2021-09-10 00:18:47 +03:00
item - > pos . xPos + = coll - > Shift . x ;
2020-09-26 05:06:08 +10:00
break ;
}
2021-09-14 00:03:24 +03:00
2020-09-26 05:06:08 +10:00
item - > pos . yPos + = dfront ;
}
else
{
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 ;
2021-09-14 00:03:24 +03:00
2020-09-26 05:06:08 +10:00
if ( item - > currentAnimState = = LS_SHIMMY_LEFT | | item - > currentAnimState = = LS_SHIMMY_RIGHT )
{
item - > currentAnimState = LS_HANG ;
item - > goalAnimState = LS_HANG ;
item - > animNumber = LA_REACH_TO_HANG ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase + 21 ;
}
2021-07-09 19:41:56 -05:00
else if ( item - > currentAnimState = = LS_SHIMMY_FEET_LEFT | | item - > currentAnimState = = LS_SHIMMY_FEET_RIGHT )
2020-09-26 05:06:08 +10:00
{
item - > currentAnimState = LS_HANG_FEET ;
item - > goalAnimState = LS_HANG_FEET ;
item - > animNumber = LA_HANG_FEET_IDLE ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
2021-07-09 19:41:56 -05:00
}
2021-09-14 00:03:24 +03:00
result = true ;
2020-09-26 05:06:08 +10:00
}
}
else
{
item - > currentAnimState = LS_JUMP_UP ;
item - > goalAnimState = LS_JUMP_UP ;
item - > animNumber = LA_JUMP_UP ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase + 9 ;
frame = ( ANIM_FRAME * ) GetBoundsAccurate ( item ) ;
2021-09-10 00:18:47 +03:00
item - > pos . xPos + = coll - > Shift . x ;
2020-09-26 05:06:08 +10:00
item - > pos . yPos + = frame - > boundingBox . Y2 ;
2021-09-10 00:18:47 +03:00
item - > pos . zPos + = coll - > Shift . z ;
2020-09-26 05:06:08 +10:00
item - > gravityStatus = true ;
item - > speed = 2 ;
item - > fallspeed = 1 ;
Lara . gunStatus = LG_NO_ARMS ;
}
}
2021-09-14 00:03:24 +03:00
2020-09-26 05:06:08 +10:00
return result ;
}
2021-09-16 01:56:02 +03:00
int TestLaraHangLeftCorner ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
2021-07-09 19:41:56 -05:00
if ( item - > animNumber ! = LA_REACH_TO_HANG & & item - > animNumber ! = LA_HANG_FEET_IDLE )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:18:47 +03:00
if ( coll - > HitStatic )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
int x ;
int z ;
int oldXpos = item - > pos . xPos ;
int oldZpos = item - > pos . zPos ;
short oldYrot = item - > pos . yRot ;
2021-09-10 00:18:47 +03:00
int oldFrontFloor = coll - > Front . Floor ;
2020-09-26 05:06:08 +10:00
short angle = GetQuadrant ( item - > pos . yRot ) ;
if ( angle ! = NORTH & & angle ! = SOUTH )
{
x = item - > pos . xPos ^ ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ;
z = item - > pos . zPos ^ ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ;
}
else
{
x = ( item - > pos . xPos & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) + SECTOR ( 1 ) ;
z = ( item - > pos . zPos & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) + SECTOR ( 1 ) ;
}
item - > pos . xPos = x ;
Lara . cornerX = x ;
item - > pos . zPos = z ;
Lara . cornerZ = z ;
item - > pos . yRot - = ANGLE ( 90.0f ) ;
2021-09-16 01:56:02 +03:00
auto result = - TestLaraValidHangPos ( item , coll ) ;
2020-09-26 05:06:08 +10:00
if ( result )
{
if ( Lara . climbStatus )
{
2021-08-20 02:01:50 +03:00
if ( GetClimbFlags ( x , item - > pos . yPos , z , item - > roomNumber ) & RightClimbTab [ angle ] )
2020-09-26 05:06:08 +10:00
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
}
else
{
2021-09-10 00:18:47 +03:00
if ( abs ( oldFrontFloor - coll - > Front . Floor ) < = 60 )
2020-09-26 05:06:08 +10:00
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
}
}
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
if ( LaraFloorFront ( item , oldYrot - ANGLE ( 90.0f ) , 116 ) < 0 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
switch ( angle )
{
case NORTH :
x = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ item - > pos . xPos - SECTOR ( 1 ) ;
z = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ item - > pos . zPos + SECTOR ( 1 ) ;
break ;
case SOUTH :
x = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ ( item - > pos . xPos + SECTOR ( 1 ) ) ;
z = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ ( item - > pos . zPos - SECTOR ( 1 ) ) ;
break ;
case WEST :
x = ( item - > pos . xPos & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) ;
z = ( item - > pos . zPos & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) ;
break ;
default :
x = ( ( item - > pos . xPos + SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) + SECTOR ( 1 ) ;
z = ( ( item - > pos . zPos + SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) + SECTOR ( 1 ) ;
break ;
}
item - > pos . xPos = x ;
Lara . cornerX = x ;
item - > pos . zPos = z ;
Lara . cornerZ = z ;
item - > pos . yRot + = ANGLE ( 90.0f ) ;
2021-09-14 00:30:44 +03:00
result = TestLaraValidHangPos ( item , coll ) ;
2020-09-26 05:06:08 +10:00
if ( ! result )
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
if ( ! Lara . climbStatus )
{
2021-09-10 00:18:47 +03:00
if ( abs ( oldFrontFloor - coll - > Front . Floor ) < = 60 )
2020-09-26 05:06:08 +10:00
{
switch ( angle )
{
case NORTH :
if ( ( oldXpos & 0x3FF ) > 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case EAST :
if ( ( oldZpos & 0x3FF ) < 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case SOUTH :
if ( ( oldXpos & 0x3FF ) < 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case WEST :
if ( ( oldZpos & 0x3FF ) > 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
}
return result ;
}
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
}
2021-08-20 02:01:50 +03:00
if ( GetClimbFlags ( x , item - > pos . yPos , z , item - > roomNumber ) & LeftClimbTab [ angle ] )
2020-09-26 05:06:08 +10:00
return result ;
short front = LaraFloorFront ( item , item - > pos . yRot , 116 ) ;
2021-09-10 00:18:47 +03:00
if ( abs ( front - coll - > Front . Floor ) > 60 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
if ( front < - 768 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
return result ;
}
2021-09-16 01:56:02 +03:00
int TestLaraHangRightCorner ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
2021-07-09 19:41:56 -05:00
if ( item - > animNumber ! = LA_REACH_TO_HANG & & item - > animNumber ! = LA_HANG_FEET_IDLE )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:18:47 +03:00
if ( coll - > HitStatic )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
int x ;
int z ;
int oldXpos = item - > pos . xPos ;
int oldZpos = item - > pos . zPos ;
short oldYrot = item - > pos . yRot ;
2021-09-10 00:18:47 +03:00
int oldFrontFloor = coll - > Front . Floor ;
2020-09-26 05:06:08 +10:00
short angle = GetQuadrant ( item - > pos . yRot ) ;
if ( angle ! = NORTH & & angle ! = SOUTH )
{
x = ( item - > pos . xPos & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) + SECTOR ( 1 ) ;
z = ( item - > pos . zPos & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) + SECTOR ( 1 ) ;
}
else
{
x = item - > pos . xPos ^ ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ;
z = item - > pos . zPos ^ ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ;
}
item - > pos . xPos = x ;
Lara . cornerX = x ;
item - > pos . zPos = z ;
Lara . cornerZ = z ;
item - > pos . yRot + = ANGLE ( 90.0f ) ;
2021-09-16 01:56:02 +03:00
auto result = - TestLaraValidHangPos ( item , coll ) ;
2020-09-26 05:06:08 +10:00
if ( result )
{
if ( Lara . climbStatus )
{
2021-08-20 02:01:50 +03:00
if ( GetClimbFlags ( x , item - > pos . yPos , z , item - > roomNumber ) & LeftClimbTab [ angle ] )
2020-09-26 05:06:08 +10:00
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
}
else
{
2021-09-10 00:18:47 +03:00
if ( abs ( oldFrontFloor - coll - > Front . Floor ) < = 60 )
2020-09-26 05:06:08 +10:00
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
}
}
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
if ( LaraFloorFront ( item , oldYrot + ANGLE ( 90.0f ) , 116 ) < 0 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
switch ( angle )
{
case NORTH :
x = ( ( item - > pos . xPos + SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) + SECTOR ( 1 ) ;
z = ( ( item - > pos . zPos + SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) + SECTOR ( 1 ) ;
break ;
case SOUTH :
x = ( ( item - > pos . xPos - SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . zPos & 0x3FF ) + SECTOR ( 1 ) ;
z = ( ( item - > pos . zPos - SECTOR ( 1 ) ) & 0xFFFFFC00 ) - ( item - > pos . xPos & 0x3FF ) + SECTOR ( 1 ) ;
break ;
case WEST :
x = ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ^ ( item - > pos . xPos - SECTOR ( 1 ) ) ;
z = ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ^ ( item - > pos . zPos + SECTOR ( 1 ) ) ;
break ;
default :
x = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ ( item - > pos . xPos + SECTOR ( 1 ) ) ;
z = ( ( item - > pos . xPos ^ item - > pos . zPos ) & 0x3FF ) ^ ( item - > pos . zPos - SECTOR ( 1 ) ) ;
break ;
}
item - > pos . xPos = x ;
Lara . cornerX = x ;
item - > pos . zPos = z ;
Lara . cornerZ = z ;
item - > pos . yRot - = ANGLE ( 90.0f ) ;
2021-09-14 00:30:44 +03:00
result = TestLaraValidHangPos ( item , coll ) ;
2020-09-26 05:06:08 +10:00
if ( ! result )
{
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
return result ;
}
item - > pos . xPos = oldXpos ;
item - > pos . zPos = oldZpos ;
item - > pos . yRot = oldYrot ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = oldYrot ;
2020-09-26 05:06:08 +10:00
if ( ! Lara . climbStatus )
{
2021-09-10 00:18:47 +03:00
if ( abs ( oldFrontFloor - coll - > Front . Floor ) < = 60 )
2020-09-26 05:06:08 +10:00
{
switch ( angle )
{
case NORTH :
if ( ( oldXpos & 0x3FF ) < 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case EAST :
if ( ( oldZpos & 0x3FF ) > 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case SOUTH :
if ( ( oldXpos & 0x3FF ) > 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
case WEST :
if ( ( oldZpos & 0x3FF ) < 512 )
2021-09-16 01:56:02 +03:00
result = 0 ;
2020-09-26 05:06:08 +10:00
break ;
}
return result ;
}
2021-09-14 00:03:24 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-08-20 02:01:50 +03:00
if ( GetClimbFlags ( x , item - > pos . yPos , z , item - > roomNumber ) & RightClimbTab [ angle ] )
2020-09-26 05:06:08 +10:00
return result ;
short front = LaraFloorFront ( item , item - > pos . yRot , 116 ) ;
2021-09-10 00:18:47 +03:00
if ( abs ( front - coll - > Front . Floor ) > 60 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
if ( front < - 768 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
return result ;
}
2021-09-16 01:56:02 +03:00
int TestLaraValidHangPos ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
2020-12-19 23:34:52 -03:00
if ( LaraFloorFront ( item , Lara . moveAngle , 100 ) < 200 )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
short angle = GetQuadrant ( item - > pos . yRot ) ;
switch ( angle )
{
case NORTH :
item - > pos . zPos + = 4 ;
break ;
case EAST :
item - > pos . xPos + = 4 ;
break ;
case SOUTH :
item - > pos . zPos - = 4 ;
break ;
case WEST :
item - > pos . xPos - = 4 ;
break ;
default :
break ;
}
2021-09-19 17:48:32 +03:00
coll - > Setup . BadHeightDown = NO_BAD_POS ;
coll - > Setup . BadHeightUp = - 512 ;
2021-09-10 00:20:59 +03:00
coll - > Setup . BadCeilingHeight = 0 ;
2020-09-26 05:06:08 +10:00
2020-12-19 23:34:52 -03:00
Lara . moveAngle = item - > pos . yRot ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:20:59 +03:00
coll - > Setup . ForwardAngle = Lara . moveAngle ;
2021-09-19 06:42:24 +03:00
GetCollisionInfo ( coll , item ) ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:18:47 +03:00
if ( coll - > Middle . Ceiling > = 0 | | coll - > CollisionType ! = CT_FRONT | | coll - > HitStatic )
2021-09-16 01:56:02 +03:00
return 0 ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:18:47 +03:00
return abs ( coll - > Front . Floor - coll - > FrontRight . Floor ) < 60 ;
2020-09-26 05:06:08 +10:00
}
2021-09-14 00:30:44 +03:00
bool TestLaraClimbStance ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
int shift_r , shift_l ;
2021-09-10 00:20:59 +03:00
if ( LaraTestClimbPos ( item , coll - > Setup . Radius , coll - > Setup . Radius + 120 , - 700 , 512 , & shift_r ) ! = 1 )
2020-09-26 05:06:08 +10:00
return false ;
2021-09-10 00:20:59 +03:00
if ( LaraTestClimbPos ( item , coll - > Setup . Radius , - ( coll - > Setup . Radius + 120 ) , - 700 , 512 , & shift_l ) ! = 1 )
2020-09-26 05:06:08 +10:00
return false ;
if ( shift_r )
{
if ( shift_l )
{
if ( shift_r < 0 ! = shift_l < 0 )
return false ;
if ( ( shift_r < 0 & & shift_l < shift_r ) | |
( shift_r > 0 & & shift_l > shift_r ) )
{
item - > pos . yPos + = shift_l ;
return true ;
}
}
item - > pos . yPos + = shift_r ;
}
else if ( shift_l )
{
item - > pos . yPos + = shift_l ;
}
return true ;
}
2021-09-14 00:30:44 +03:00
bool TestLaraHangOnClimbWall ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
BOUNDING_BOX * bounds ;
int shift , result ;
if ( Lara . climbStatus = = 0 )
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
if ( item - > fallspeed < 0 )
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
switch ( GetQuadrant ( item - > pos . yRot ) )
{
case NORTH :
case SOUTH :
2021-09-10 00:18:47 +03:00
item - > pos . zPos + = coll - > Shift . z ;
2020-09-26 05:06:08 +10:00
break ;
case EAST :
case WEST :
2021-09-10 00:18:47 +03:00
item - > pos . xPos + = coll - > Shift . x ;
2020-09-26 05:06:08 +10:00
break ;
default :
break ;
}
bounds = GetBoundsAccurate ( item ) ;
2020-12-19 23:34:52 -03:00
if ( Lara . moveAngle ! = item - > pos . yRot )
2020-09-26 05:06:08 +10:00
{
short l = LaraCeilingFront ( item , item - > pos . yRot , 0 , 0 ) ;
2020-12-19 23:34:52 -03:00
short r = LaraCeilingFront ( item , Lara . moveAngle , 128 , 0 ) ;
2020-09-26 05:06:08 +10:00
if ( abs ( l - r ) > 60 )
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-09-10 00:20:59 +03:00
if ( LaraTestClimbPos ( item , coll - > Setup . Radius , coll - > Setup . Radius , bounds - > Y1 , bounds - > Y2 - bounds - > Y1 , & shift ) & &
LaraTestClimbPos ( item , coll - > Setup . Radius , - coll - > Setup . Radius , bounds - > Y1 , bounds - > Y2 - bounds - > Y1 , & shift ) )
2020-09-26 05:06:08 +10:00
{
2021-09-10 00:20:59 +03:00
result = LaraTestClimbPos ( item , coll - > Setup . Radius , 0 , bounds - > Y1 , bounds - > Y2 - bounds - > Y1 , & shift ) ;
2020-09-26 05:06:08 +10:00
if ( result )
{
if ( result ! = 1 )
item - > pos . yPos + = shift ;
2021-09-13 09:12:46 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
}
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-09-14 00:30:44 +03:00
int TestLaraEdgeCatch ( ITEM_INFO * item , COLL_INFO * coll , int * edge )
2020-09-26 05:06:08 +10:00
{
BOUNDING_BOX * bounds = GetBoundsAccurate ( item ) ;
2021-09-10 00:18:47 +03:00
int hdif = coll - > Front . Floor - bounds - > Y1 ;
2020-09-26 05:06:08 +10:00
if ( hdif < 0 = = hdif + item - > fallspeed < 0 )
{
hdif = item - > pos . yPos + bounds - > Y1 ;
if ( ( hdif + item - > fallspeed & 0xFFFFFF00 ) ! = ( hdif & 0xFFFFFF00 ) )
{
if ( item - > fallspeed > 0 )
* edge = ( hdif + item - > fallspeed ) & 0xFFFFFF00 ;
else
* edge = hdif & 0xFFFFFF00 ;
return - 1 ;
}
return 0 ;
}
2021-09-13 03:11:13 +03:00
if ( abs ( coll - > FrontLeft . Floor - coll - > FrontRight . Floor ) > = SLOPE_DIFFERENCE )
2020-09-26 05:06:08 +10:00
return 0 ;
return 1 ;
}
2021-09-13 09:12:46 +03:00
bool TestHangSwingIn ( ITEM_INFO * item , short angle )
2020-09-26 05:06:08 +10:00
{
int x = item - > pos . xPos ;
int y = item - > pos . yPos ;
int z = item - > pos . zPos ;
short roomNum = item - > roomNumber ;
FLOOR_INFO * floor ;
int h , c ;
//debug till scripting be ready
2021-07-09 19:41:56 -05:00
Lara . NewAnims . OscillateHanging = 0 ;
2020-09-26 05:06:08 +10:00
2020-10-05 22:24:57 -03:00
z + = phd_cos ( angle ) * STEP_SIZE ;
x + = phd_sin ( angle ) * STEP_SIZE ;
2020-09-26 05:06:08 +10:00
floor = GetFloor ( x , y , z , & roomNum ) ;
h = GetFloorHeight ( floor , x , y , z ) ;
c = GetCeiling ( floor , x , y , z ) ;
if ( h ! = NO_HEIGHT )
{
2021-07-09 19:41:56 -05:00
if ( Lara . NewAnims . OscillateHanging )
2020-09-26 05:06:08 +10:00
{
2021-07-09 19:41:56 -05:00
if ( h - y > 0 & & c - y < - 400 )
2021-09-13 09:12:46 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
else
2021-07-09 19:41:56 -05:00
{
if ( h - y > 0 & & c - y < - 400 & & ( y - 819 - c > - 72 ) )
2021-09-13 09:12:46 +03:00
return true ;
2021-07-09 19:41:56 -05:00
}
2020-09-26 05:06:08 +10:00
}
2021-09-13 09:12:46 +03:00
return false ;
2021-07-09 19:41:56 -05:00
}
2020-09-26 05:06:08 +10:00
2021-07-09 19:41:56 -05:00
bool TestHangFeet ( ITEM_INFO * item , short angle )
{
//##LUA debug etc.
Lara . NewAnims . FeetHanging = 0 ;
2020-09-26 05:06:08 +10:00
2021-07-09 19:41:56 -05:00
if ( Lara . climbStatus | | ! Lara . NewAnims . FeetHanging )
2021-09-13 23:44:52 +03:00
return false ;
2020-09-26 05:06:08 +10:00
int x = item - > pos . xPos ;
int y = item - > pos . yPos ;
int z = item - > pos . zPos ;
short roomNum = item - > roomNumber ;
FLOOR_INFO * floor ;
int h , c , g , m , j ;
2021-07-09 19:41:56 -05:00
z + = phd_cos ( angle ) * STEP_SIZE ;
x + = phd_sin ( angle ) * STEP_SIZE ;
2020-09-26 05:06:08 +10:00
floor = GetFloor ( x , y , z , & roomNum ) ;
h = GetFloorHeight ( floor , x , y , z ) ;
c = GetCeiling ( floor , x , y , z ) ;
g = h - y ;
m = c - y ;
j = y - 128 - c ;
2021-07-09 19:41:56 -05:00
if ( h ! = NO_HEIGHT )
2020-09-26 05:06:08 +10:00
{
2021-07-09 19:41:56 -05:00
if ( g > 0 & & m < - 128 & & j > - 72 )
2021-09-13 23:44:52 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
2021-09-13 23:44:52 +03:00
return false ;
2021-07-09 19:41:56 -05:00
}
2020-09-26 05:06:08 +10:00
2021-09-14 00:30:44 +03:00
bool TestLaraHangSideways ( ITEM_INFO * item , COLL_INFO * coll , short angle )
2020-09-26 05:06:08 +10:00
{
int oldx = item - > pos . xPos ;
int oldz = item - > pos . zPos ;
int x = item - > pos . xPos ;
int z = item - > pos . zPos ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = item - > pos . yRot + angle ;
2020-09-26 05:06:08 +10:00
2020-12-19 23:34:52 -03:00
switch ( GetQuadrant ( Lara . moveAngle ) )
2020-09-26 05:06:08 +10:00
{
case 0 :
z + = 16 ;
break ;
case 1 :
x + = 16 ;
break ;
case 2 :
z - = 16 ;
break ;
case 3 :
x - = 16 ;
break ;
}
item - > pos . xPos = x ;
item - > pos . zPos = z ;
2021-09-10 00:20:59 +03:00
coll - > Setup . OldPosition . y = item - > pos . yPos ;
2020-09-26 05:06:08 +10:00
2021-09-14 00:30:44 +03:00
auto res = TestLaraHang ( item , coll ) ;
2020-09-26 05:06:08 +10:00
item - > pos . xPos = oldx ;
item - > pos . zPos = oldz ;
2020-12-19 23:34:52 -03:00
Lara . moveAngle = item - > pos . yRot + angle ;
2020-09-26 05:06:08 +10:00
return ! res ;
}
2021-02-03 01:50:59 -03:00
void SetCornerAnim ( ITEM_INFO * item , COLL_INFO * coll , short rot , short flip )
2020-09-26 05:06:08 +10:00
{
if ( item - > hitPoints < = 0 )
{
item - > goalAnimState = LS_JUMP_FORWARD ;
item - > currentAnimState = LS_JUMP_FORWARD ;
item - > animNumber = LA_FALL_START ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > gravityStatus = true ;
item - > speed = 2 ;
item - > pos . yPos + = 256 ;
item - > fallspeed = 1 ;
Lara . gunStatus = LG_NO_ARMS ;
item - > pos . yRot + = rot / 2 ;
}
else if ( flip )
{
if ( Lara . isClimbing )
{
item - > animNumber = LA_LADDER_IDLE ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_LADDER_IDLE ;
item - > currentAnimState = LS_LADDER_IDLE ;
}
else
{
item - > animNumber = LA_REACH_TO_HANG ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase + 21 ;
item - > goalAnimState = LS_HANG ;
item - > currentAnimState = LS_HANG ;
}
2021-09-10 00:20:59 +03:00
coll - > Setup . OldPosition . x = Lara . cornerX ;
2020-09-26 05:06:08 +10:00
item - > pos . xPos = Lara . cornerX ;
2021-09-10 00:20:59 +03:00
coll - > Setup . OldPosition . z = Lara . cornerZ ;
2020-09-26 05:06:08 +10:00
item - > pos . zPos = Lara . cornerZ ;
item - > pos . yRot + = rot ;
}
}
2021-07-09 19:41:56 -05:00
void SetCornerAnimFeet ( ITEM_INFO * item , COLL_INFO * coll , short rot , short flip )
2020-09-26 05:06:08 +10:00
{
if ( item - > hitPoints < = 0 )
{
item - > goalAnimState = LS_JUMP_FORWARD ;
item - > currentAnimState = LS_JUMP_FORWARD ;
item - > animNumber = LA_FALL_START ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > gravityStatus = true ;
item - > speed = 2 ;
item - > pos . yPos + = 256 ;
item - > fallspeed = 1 ;
Lara . gunStatus = LG_NO_ARMS ;
item - > pos . yRot + = rot / 2 ;
}
else if ( flip )
{
item - > animNumber = LA_HANG_FEET_IDLE ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > goalAnimState = LS_HANG_FEET ;
item - > currentAnimState = LS_HANG_FEET ;
2021-09-10 00:20:59 +03:00
coll - > Setup . OldPosition . x = Lara . cornerX ;
2020-09-26 05:06:08 +10:00
item - > pos . xPos = Lara . cornerX ;
2021-09-10 00:20:59 +03:00
coll - > Setup . OldPosition . z = Lara . cornerZ ;
2020-09-26 05:06:08 +10:00
item - > pos . zPos = Lara . cornerZ ;
item - > pos . yRot + = rot ;
}
2021-07-09 19:41:56 -05:00
}
2020-09-26 05:06:08 +10:00
2021-10-16 23:51:42 +11:00
bool TestLaraFacingCorner ( ITEM_INFO * item , short angle , int dist )
2021-08-29 23:53:58 +03:00
{
2021-10-16 22:53:29 +11:00
// TODO: Objects? Lara will attempt to jump against them.
// TODO: Check for ceilings! @Sezz 2021.10.16
2021-10-16 13:49:14 +11:00
auto x = item - > pos . xPos ;
auto y = item - > pos . yPos ;
auto z = item - > pos . zPos ;
2021-08-29 23:53:58 +03:00
2021-10-16 23:51:42 +11:00
auto angleA = angle + ANGLE ( 15.0f ) ;
auto angleB = angle - ANGLE ( 15.0f ) ;
2021-08-29 23:53:58 +03:00
2021-10-16 22:53:29 +11:00
auto probeA = GetCollisionResult ( item , angleA , dist , 0 ) ;
auto probeB = GetCollisionResult ( item , angleB , dist , 0 ) ;
2021-08-29 23:53:58 +03:00
2021-10-16 23:51:42 +11:00
if ( probeA . Position . Floor - y < - STEPUP_HEIGHT & &
2021-10-16 14:14:11 +11:00
probeB . Position . Floor - y < - STEPUP_HEIGHT )
2021-10-16 13:49:14 +11:00
{
return true ;
}
2021-08-29 23:53:58 +03:00
2021-10-16 13:49:14 +11:00
return false ;
2021-08-29 23:53:58 +03:00
}
2021-10-16 23:51:42 +11:00
bool TestLaraStandingJump ( ITEM_INFO * item , COLL_INFO * coll , short angle )
{
auto y = item - > pos . yPos ;
auto probe = GetCollisionResult ( item , angle , STEP_SIZE , coll - > Setup . Height ) ;
if ( ! TestLaraFacingCorner ( item , angle , STEP_SIZE ) & &
probe . Position . Floor - y > = - ( STEP_SIZE + STEP_SIZE / 2 ) & &
probe . Position . Ceiling - y < = 0 )
{
return true ;
}
return false ;
}
2021-02-06 11:50:08 -03:00
int LaraFloorFront ( ITEM_INFO * item , short ang , int dist )
2021-08-24 16:54:26 +03:00
{
2021-09-10 00:43:26 +03:00
return LaraCollisionFront ( item , ang , dist ) . Position . Floor ;
2021-08-24 16:54:26 +03:00
}
COLL_RESULT LaraCollisionFront ( ITEM_INFO * item , short ang , int dist )
2020-09-26 05:06:08 +10:00
{
2020-10-05 22:24:57 -03:00
int x = item - > pos . xPos + dist * phd_sin ( ang ) ;
2021-08-29 23:53:58 +03:00
int y = item - > pos . yPos - LARA_HEIGHT ;
2020-10-05 22:24:57 -03:00
int z = item - > pos . zPos + dist * phd_cos ( ang ) ;
2020-09-26 05:06:08 +10:00
2021-08-24 16:54:26 +03:00
auto collResult = GetCollisionResult ( x , y , z , item - > roomNumber ) ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:43:26 +03:00
if ( collResult . Position . Floor ! = NO_HEIGHT )
collResult . Position . Floor - = item - > pos . yPos ;
2020-09-26 05:06:08 +10:00
2021-08-24 16:54:26 +03:00
return collResult ;
2020-09-26 05:06:08 +10:00
}
2021-10-03 22:09:19 +03:00
COLL_RESULT LaraCollisionAboveFront ( ITEM_INFO * item , short ang , int dist , int h )
{
int x = item - > pos . xPos + dist * phd_sin ( ang ) ;
int y = item - > pos . yPos - h ;
int z = item - > pos . zPos + dist * phd_cos ( ang ) ;
return GetCollisionResult ( x , y , z , GetCollisionResult ( item - > pos . xPos , y , item - > pos . zPos , item - > roomNumber ) . RoomNumber ) ;
}
2021-02-06 11:50:08 -03:00
int LaraCeilingFront ( ITEM_INFO * item , short ang , int dist , int h )
2021-08-24 16:54:26 +03:00
{
2021-09-10 00:43:26 +03:00
return LaraCeilingCollisionFront ( item , ang , dist , h ) . Position . Ceiling ;
2021-08-24 16:54:26 +03:00
}
COLL_RESULT LaraCeilingCollisionFront ( ITEM_INFO * item , short ang , int dist , int h )
2020-09-26 05:06:08 +10:00
{
2020-10-05 22:24:57 -03:00
int x = item - > pos . xPos + dist * phd_sin ( ang ) ;
2020-09-26 05:06:08 +10:00
int y = item - > pos . yPos - h ;
2020-10-05 22:24:57 -03:00
int z = item - > pos . zPos + dist * phd_cos ( ang ) ;
2020-09-26 05:06:08 +10:00
2021-08-24 16:54:26 +03:00
auto collResult = GetCollisionResult ( x , y , z , item - > roomNumber ) ;
2020-09-26 05:06:08 +10:00
2021-09-10 00:43:26 +03:00
if ( collResult . Position . Ceiling ! = NO_HEIGHT )
collResult . Position . Ceiling + = h - item - > pos . yPos ;
2020-09-26 05:06:08 +10:00
2021-08-24 16:54:26 +03:00
return collResult ;
2020-09-26 05:06:08 +10:00
}
2021-09-13 09:12:46 +03:00
bool LaraFallen ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
2021-09-10 00:18:47 +03:00
if ( Lara . waterStatus = = LW_WADE | | coll - > Middle . Floor < = STEPUP_HEIGHT )
2020-09-26 05:06:08 +10:00
{
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
item - > animNumber = LA_FALL_START ;
item - > currentAnimState = LS_JUMP_FORWARD ;
item - > goalAnimState = LS_JUMP_FORWARD ;
item - > frameNumber = g_Level . Anims [ item - > animNumber ] . frameBase ;
item - > fallspeed = 0 ;
item - > gravityStatus = true ;
2021-09-13 09:12:46 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
2021-09-13 09:12:46 +03:00
bool LaraLandedBad ( ITEM_INFO * item , COLL_INFO * coll )
2020-09-26 05:06:08 +10:00
{
int landspeed = item - > fallspeed - 140 ;
if ( landspeed > 0 )
{
if ( landspeed < = 14 )
{
item - > hitPoints - = 1000 * SQUARE ( landspeed ) / 196 ;
return item - > hitPoints < = 0 ;
}
else
{
item - > hitPoints = - 1 ;
2021-09-13 09:12:46 +03:00
return true ;
2020-09-26 05:06:08 +10:00
}
}
2021-09-13 09:12:46 +03:00
return false ;
2020-09-26 05:06:08 +10:00
}
2021-09-13 09:12:46 +03:00
2021-09-05 14:49:00 +02:00
# ifndef NEW_TIGHTROPE
void GetTighRopeFallOff ( int regularity ) {
if ( LaraItem - > hitPoints < = 0 | | LaraItem - > hitStatus )
2020-09-26 05:06:08 +10:00
{
LaraItem - > goalAnimState = LS_TIGHTROPE_UNBALANCE_LEFT ;
LaraItem - > currentAnimState = LS_TIGHTROPE_UNBALANCE_LEFT ;
LaraItem - > animNumber = LA_TIGHTROPE_FALL_LEFT ;
LaraItem - > frameNumber = g_Level . Anims [ LaraItem - > animNumber ] . frameBase ;
}
2021-09-05 14:49:00 +02:00
if ( ! Lara . tightRopeFall & & ! ( GetRandomControl ( ) & regularity ) )
2020-09-26 05:06:08 +10:00
Lara . tightRopeFall = 2 - ( ( GetRandomControl ( ) & 0xF ) ! = 0 ) ;
}
2021-09-05 14:49:00 +02:00
# endif // !NEW_TIGHTROPE
2020-12-21 13:16:29 -03:00
bool TestLaraLean ( ITEM_INFO * item , COLL_INFO * coll )
{
2021-09-10 00:18:47 +03:00
if ( coll - > CollisionType = = CT_RIGHT | | coll - > CollisionType = = CT_LEFT )
2021-09-13 09:12:46 +03:00
return false ;
2021-07-09 19:41:56 -05:00
2021-10-16 20:50:16 +11:00
return true ;
}
bool IsStandingWeapon ( LARA_WEAPON_TYPE gunType )
{
if ( gunType = = WEAPON_SHOTGUN | |
gunType = = WEAPON_HK | |
gunType = = WEAPON_CROSSBOW | |
gunType = = WEAPON_TORCH | |
gunType = = WEAPON_GRENADE_LAUNCHER | |
gunType = = WEAPON_HARPOON_GUN | |
gunType = = WEAPON_ROCKET_LAUNCHER | |
gunType = = WEAPON_SNOWMOBILE )
{
return true ;
}
return false ;
}
// TODO: Try using each state's BadStep up/down. @Sezz 2021.10.11
bool TestLaraStep ( COLL_INFO * coll )
{
if ( coll - > Middle . Floor > = - STEPUP_HEIGHT & &
coll - > Middle . Floor < = STEPUP_HEIGHT )
{
return true ;
}
return false ;
}
bool TestLaraStepUp ( ITEM_INFO * item , COLL_INFO * coll )
{
if ( coll - > Middle . Floor < - STEP_SIZE / 2 & &
coll - > Middle . Floor > = - STEPUP_HEIGHT & &
coll - > Middle . Floor ! = NO_HEIGHT & &
item - > currentAnimState ! = LS_WALK_BACK & &
item - > currentAnimState ! = LS_HOP_BACK & &
item - > currentAnimState ! = LS_SPRINT )
{
return true ;
}
return false ;
}
bool TestLaraStepDown ( ITEM_INFO * item , COLL_INFO * coll )
{
if ( coll - > Middle . Floor > STEP_SIZE / 2 & &
coll - > Middle . Floor < = STEPUP_HEIGHT & &
coll - > Middle . Floor ! = NO_HEIGHT & &
item - > currentAnimState ! = LS_RUN_FORWARD & &
item - > currentAnimState ! = LS_HOP_BACK & &
item - > currentAnimState ! = LS_SPRINT )
{
return true ;
}
return false ;
2020-12-21 13:16:29 -03:00
}
2021-09-26 20:59:16 +10:00
bool TestLaraFall ( COLL_INFO * coll )
{
2021-10-14 01:17:21 +11:00
if ( coll - > Middle . Floor < = STEPUP_HEIGHT | |
Lara . waterStatus = = LW_WADE ) // TODO: This causes a legacy floor snap BUG when lara wades off a ledge into a dry room. @Sezz 2021.09.26
2021-09-26 20:59:16 +10:00
{
return false ;
}
return true ;
}
2021-09-27 18:18:03 +10:00
// TODO: Remane when legacy TestLaraSlide() is removed.
bool TestLaraSlideNew ( COLL_INFO * coll )
2021-09-26 20:59:16 +10:00
{
if ( abs ( coll - > TiltX ) < = 2 & & abs ( coll - > TiltZ ) < = 2 )
return false ;
return true ;
}
2021-10-04 22:02:02 +11:00
bool TestLaraStepLeft ( ITEM_INFO * item )
{
auto collFloorResult = LaraCollisionFront ( item , item - > pos . yRot - ANGLE ( 90.0f ) , LARA_RAD + 48 ) ;
auto collCeilingResult = LaraCeilingCollisionFront ( item , item - > pos . yRot - ANGLE ( 90.0f ) , LARA_RAD + 48 , LARA_HEIGHT ) ;
2021-10-14 01:17:21 +11:00
if ( ( collFloorResult . Position . Floor < STEP_SIZE / 2 & & collFloorResult . Position . Floor > - STEP_SIZE / 2 ) & &
collCeilingResult . Position . Ceiling < = 0 & &
! collFloorResult . Position . Slope )
2021-10-04 22:02:02 +11:00
{
return true ;
}
return false ;
}
bool TestLaraStepRight ( ITEM_INFO * item )
{
auto collFloorResult = LaraCollisionFront ( item , item - > pos . yRot + ANGLE ( 90.0f ) , LARA_RAD + 48 ) ;
auto collCeilingResult = LaraCeilingCollisionFront ( item , item - > pos . yRot + ANGLE ( 90.0f ) , LARA_RAD + 48 , LARA_HEIGHT ) ;
2021-10-14 01:17:21 +11:00
if ( ( collFloorResult . Position . Floor < STEP_SIZE / 2 & & collFloorResult . Position . Floor > - STEP_SIZE / 2 ) & &
collCeilingResult . Position . Ceiling < = 0 & &
! collFloorResult . Position . Slope )
2021-10-04 22:02:02 +11:00
{
return true ;
}
return false ;
}
2021-09-27 18:18:03 +10:00
bool TestLaraCrawl ( ITEM_INFO * item )
2021-09-26 20:59:16 +10:00
{
2021-10-14 01:17:21 +11:00
if ( Lara . gunStatus = = LG_NO_ARMS & &
/*Lara.waterSurfaceDist >= -STEP_SIZE &&*/
! ( TrInput & ( IN_FLARE | IN_DRAW ) ) & & // Avoid unsightly concurrent actions.
( Lara . gunType ! = WEAPON_FLARE | | Lara . flareAge > 0 ) ) // Flare is not being handled.
2021-09-27 18:18:03 +10:00
{
return true ;
}
2021-09-26 20:59:16 +10:00
2021-09-27 18:18:03 +10:00
return false ;
2021-09-26 20:59:16 +10:00
}
2021-10-14 01:17:21 +11:00
bool TestLaraCrouchRoll ( ITEM_INFO * item , COLL_INFO * coll )
2021-09-27 18:18:03 +10:00
{
2021-10-14 01:17:21 +11:00
// This is a discrete probe and fails in many cases. Perhaps we need a ray for these kinds of tests. @Sezz 2021.10.14
2021-10-16 20:50:16 +11:00
// Ceiling?
2021-10-14 01:17:21 +11:00
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , WALL_SIZE , 0 ) ;
2021-10-14 01:17:21 +11:00
if ( Lara . gunStatus = = LG_NO_ARMS & &
Lara . waterSurfaceDist > = - STEP_SIZE & & // Water depth is optically feasible for action.
2021-10-16 20:50:16 +11:00
probe . Position . Floor - y < STEP_SIZE & & // No drop.
probe . Position . Floor - y > - STEP_SIZE & & // No wall.
2021-10-14 01:17:21 +11:00
! probe . Position . Slope & & // No slope.
! ( TrInput & ( IN_FLARE | IN_DRAW ) ) & & // Avoid unsightly concurrent actions.
2021-10-16 20:50:16 +11:00
( Lara . gunType ! = WEAPON_FLARE | | Lara . flareAge > 0 ) ) // Not handling flare.
{
return true ;
}
return false ;
}
2021-10-17 14:47:56 +11:00
// BUG: If Lara crawls up/down into an area under a slanted ceiling, she will sometimes teleport back.
// I'm unable to reproduce this every time so I'm not sure what the exact conditions for it are. @Sezz 2021.10.17
2021-10-16 20:50:16 +11:00
bool TestLaraCrawlUpStep ( ITEM_INFO * item , COLL_INFO * coll )
{
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , STEP_SIZE , 0 ) ;
2021-10-16 20:50:16 +11:00
2021-10-17 14:47:56 +11:00
if ( probe . Position . Floor - y < = - STEP_SIZE & & // Lower floor boundary.
probe . Position . Floor - y > = - STEPUP_HEIGHT & & // Upper floor boundary.
2021-10-16 20:50:16 +11:00
abs ( probe . Position . Ceiling - probe . Position . Floor ) > = LARA_HEIGHT_CRAWL & & // Space is not a clamp. TODO: coll->Setup.Height not working?
2021-10-17 14:47:56 +11:00
probe . Position . Floor - y ! = NO_HEIGHT )
2021-09-26 20:59:16 +10:00
{
2021-09-27 18:18:03 +10:00
return true ;
2021-09-26 20:59:16 +10:00
}
2021-09-27 18:18:03 +10:00
return false ;
2021-09-26 20:59:16 +10:00
}
2021-10-16 20:50:16 +11:00
bool TestLaraCrawlDownStep ( ITEM_INFO * item , COLL_INFO * coll )
{
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , STEP_SIZE , 0 ) ;
2021-10-16 20:50:16 +11:00
2021-10-17 14:47:56 +11:00
if ( probe . Position . Floor - y < = STEPUP_HEIGHT & & // Lower floor boundary.
probe . Position . Floor - y > = STEP_SIZE & & // Upper floor boundary.
2021-10-16 20:50:16 +11:00
probe . Position . Ceiling - y < = - ( STEP_SIZE / 2 ) & & // Ceiling lower boundary.
abs ( probe . Position . Ceiling - probe . Position . Floor ) > = LARA_HEIGHT_CRAWL & & // Space is not a clamp. TODO: coll->Setup.Height not working?
2021-10-17 14:47:56 +11:00
probe . Position . Floor - y ! = NO_HEIGHT )
2021-10-16 20:50:16 +11:00
{
return true ;
}
return false ;
}
bool TestLaraCrawlExitDownStep ( ITEM_INFO * item , COLL_INFO * coll )
{
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , STEP_SIZE , 0 ) ;
2021-10-16 20:50:16 +11:00
// TODO: Consider height of ceiling directly above. Lara could potentially exit where a very, very steep ceiling meets the crawlspace exit at a slant.
2021-10-17 14:47:56 +11:00
if ( probe . Position . Floor - y < = STEPUP_HEIGHT & & // Lower floor boundary.
probe . Position . Floor - y > = STEP_SIZE & & // Upper floor boundary.
2021-10-16 20:50:16 +11:00
probe . Position . Ceiling - y < = STEP_SIZE & & // Ceiling lower boundary. Necessary?
abs ( probe . Position . Ceiling - probe . Position . Floor ) > = LARA_HEIGHT & & // Space is not a clamp. TODO: Consider headroom?
2021-10-17 14:47:56 +11:00
probe . Position . Floor - y ! = NO_HEIGHT )
2021-10-16 20:50:16 +11:00
{
return true ;
}
return false ;
}
bool TestLaraCrawlExitJump ( ITEM_INFO * item , COLL_INFO * coll )
{
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , STEP_SIZE , 0 ) ;
2021-10-16 20:50:16 +11:00
2021-10-17 23:13:40 +11:00
if ( probe . Position . Floor - y > STEPUP_HEIGHT & & // Upper floor boundary.
probe . Position . Ceiling - y < LARA_HEIGHT & & // TODO: Check this. Consider headroom?
2021-10-16 20:50:16 +11:00
probe . Position . Floor - y ! = NO_HEIGHT )
{
return true ;
}
return false ;
}
bool TestLaraCrawlVault ( ITEM_INFO * item , COLL_INFO * coll )
{
auto y = item - > pos . yPos ;
2021-10-17 15:11:05 +11:00
auto probe = GetCollisionResult ( item , coll - > Setup . ForwardAngle , STEP_SIZE , 0 ) ;
2021-10-16 20:50:16 +11:00
2021-10-17 20:07:30 +11:00
// TODO: False positive at all times. Why??
2021-10-16 20:50:16 +11:00
if ( abs ( probe . Position . Floor - y ) > = STEP_SIZE & & // Upper/lower floor boundary.
probe . Position . Floor - y ! = NO_HEIGHT )
{
return true ;
}
return false ;
}
2021-10-17 22:10:01 +11:00
bool TestLaraCrawlToHang ( ITEM_INFO * item , COLL_INFO * coll )
{
// TODO: Probe for objects.
// TODO: If Lara is crawling on a very steep slope, don't allow her to descend.
// TODO: Ceiling tolerance.
auto y = item - > pos . yPos ;
auto probeBack = GetCollisionResult ( item , coll - > Setup . ForwardAngle + ANGLE ( 180.0f ) , coll - > Setup . Radius + STEP_SIZE / 2 , 0 ) ;
auto probeBackL = GetCollisionResult ( item , coll - > Setup . ForwardAngle - ANGLE ( 135.0f ) , coll - > Setup . Radius + STEP_SIZE , 0 ) ;
auto probeBackR = GetCollisionResult ( item , coll - > Setup . ForwardAngle + ANGLE ( 135.0f ) , coll - > Setup . Radius + STEP_SIZE , 0 ) ;
if ( probeBack . Position . Floor - y > = LARA_HEIGHT_STRETCH & & /*
probeBackL . Position . Floor - y > = LARA_HEIGHT_STRETCH & & // Are these side probes are really necessary? Angle tolerance should be done another way. @Sezz 2021.10.16
probeBackR . Position . Floor - y > = LARA_HEIGHT_STRETCH */
probeBack . Position . Floor - y ! = NO_HEIGHT )
{
return true ;
}
return false ;
}
2021-10-16 20:50:16 +11:00
// Entirely temporary. @Sezz 2021.10.16
bool TestLaraDrawWeaponsFromCrawlIdle ( ITEM_INFO * item )
{
if ( item - > animNumber = = LA_CRAWL_IDLE | |
( item - > animNumber = = LA_CROUCH_TO_CRAWL_START & &
item - > frameNumber > = g_Level . Anims [ item - > animNumber ] . frameBase + 8 ) )
return true ;
return false ;
}