Skip to content
24 changes: 24 additions & 0 deletions src/trx/game/lara/col.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,30 @@ void Lara_Col_GetInfo(const ITEM *const item, COLL_INFO *const coll)
LARA_HEIGHT);
}

bool Lara_Col_IsDiagonalLedge(const COLL_INFO *const coll)
{
const bool front_diagonal = coll->side_front.type == HT_DIAGONAL
|| coll->side_front.type == HT_SPLIT_TRI;
const bool left_diagonal =
coll->side_left2.type == HT_DIAGONAL
|| coll->side_left2.type == HT_SPLIT_TRI;
const bool right_diagonal =
coll->side_right2.type == HT_DIAGONAL
|| coll->side_right2.type == HT_SPLIT_TRI;

if (!front_diagonal && !left_diagonal && !right_diagonal) {
return false;
}

const int32_t left_floor = coll->side_left2.floor;
const int32_t right_floor = coll->side_right2.floor;
if (left_floor == NO_HEIGHT || right_floor == NO_HEIGHT) {
return false;
}

return ABS(left_floor - right_floor) >= SLOPE_DIF;
}

void Lara_Col_Shift(COLL_INFO *const coll)
{
ITEM *const lara_item = Lara_GetItem();
Expand Down
1 change: 1 addition & 0 deletions src/trx/game/lara/col.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ bool Lara_Col_TestCeiling(ITEM *item, const COLL_INFO *coll);
bool Lara_Col_TestHangSwingIn(const ITEM *item, int16_t angle);
EDGE_CATCH Lara_Col_TestEdgeCatch(
const ITEM *item, const COLL_INFO *coll, int32_t *edge);
bool Lara_Col_IsDiagonalLedge(const COLL_INFO *coll);
bool Lara_Col_Fallen(ITEM *item, const COLL_INFO *coll);
void Lara_Col_DeflectEdgeJump(ITEM *item, COLL_INFO *coll);
bool Lara_Col_LandedBad(ITEM *item);
Expand Down
105 changes: 64 additions & 41 deletions src/trx/game/lara/col/climb.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ void Lara_Col_HangTest(ITEM *const item, COLL_INFO *const coll)
coll->bad_neg = NO_BAD_NEG;
coll->bad_ceiling = 0;
Lara_Col_GetInfo(item, coll);
const bool flag = coll->side_front.floor < 200;
const bool initial_front_close = coll->side_front.floor < 200;

item->gravity = false;
item->fall_speed = 0;
Expand All @@ -238,28 +238,22 @@ void Lara_Col_HangTest(ITEM *const item, COLL_INFO *const coll)

const DIRECTION dir = Math_GetDirection(item->rot.y);
const int32_t hang_test_shift = g_TRVersion >= 3 ? 4 : 2;
switch (dir) {
case DIR_NORTH:
item->pos.z += hang_test_shift;
break;
case DIR_EAST:
item->pos.x += hang_test_shift;
break;
case DIR_SOUTH:
item->pos.z -= hang_test_shift;
break;
case DIR_WEST:
item->pos.x -= hang_test_shift;
break;
default:
break;
}
item->pos.x +=
(Math_Sin(item->rot.y) * hang_test_shift) >> W2V_SHIFT;
item->pos.z +=
(Math_Cos(item->rot.y) * hang_test_shift) >> W2V_SHIFT;

coll->bad_pos = NO_BAD_POS;
coll->bad_neg = -STEPUP_HEIGHT;
coll->bad_ceiling = 0;
Lara_Col_GetInfo(item, coll);

const bool diagonal_ledge = Lara_Col_IsDiagonalLedge(coll);
const bool front_close = diagonal_ledge ? false : initial_front_close;
const bool valid_coll_type = coll->coll_type == COLL_FRONT
|| (diagonal_ledge
&& (coll->coll_type == COLL_LEFT || coll->coll_type == COLL_RIGHT));

if (lara->climb_status) {
if (!g_Input.action || item->hit_points <= 0) {
XYZ_32 pos = {
Expand Down Expand Up @@ -304,7 +298,7 @@ void Lara_Col_HangTest(ITEM *const item, COLL_INFO *const coll)
}

if (!g_Input.action || item->hit_points <= 0
|| coll->side_front.floor > 0) {
|| (coll->side_front.floor > 0 && !diagonal_ledge)) {
item->goal_anim_state = LS(LS_JUMP_UP);
item->current_anim_state = LS(LS_JUMP_UP);
Item_SwitchToAnim(item, LA(LA_JUMP_UP), M_LF_STOP_HANG);
Expand All @@ -326,8 +320,9 @@ void Lara_Col_HangTest(ITEM *const item, COLL_INFO *const coll)
const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
const int32_t hdif = coll->side_front.floor - bounds->min.y;

if (ABS(coll->side_left2.floor - coll->side_right2.floor) >= SLOPE_DIF
|| coll->side_mid.ceiling >= 0 || coll->coll_type != COLL_FRONT || flag
if ((ABS(coll->side_left2.floor - coll->side_right2.floor) >= SLOPE_DIF
&& !diagonal_ledge)
|| coll->side_mid.ceiling >= 0 || !valid_coll_type || front_close
|| coll->hit_static || hdif < -SLOPE_DIF || hdif > SLOPE_DIF) {
item->pos = coll->old;
if (item->current_anim_state == LS(LS_SHIMMY_LEFT)
Expand All @@ -339,19 +334,24 @@ void Lara_Col_HangTest(ITEM *const item, COLL_INFO *const coll)
return;
}

switch (dir) {
case DIR_NORTH:
case DIR_SOUTH:
item->pos.z += coll->shift.z;
break;

case DIR_EAST:
case DIR_WEST:
if (diagonal_ledge) {
item->pos.x += coll->shift.x;
break;

default:
break;
item->pos.z += coll->shift.z;
} else {
switch (dir) {
case DIR_NORTH:
case DIR_SOUTH:
item->pos.z += coll->shift.z;
break;

case DIR_EAST:
case DIR_WEST:
item->pos.x += coll->shift.x;
break;

default:
break;
}
}

if (g_TRVersion >= 2 || (hdif >= -STEP_L && hdif <= STEP_L)) {
Expand Down Expand Up @@ -524,11 +524,28 @@ static void M_Hang(ITEM *const item, COLL_INFO *const coll)
return;
}

const bool diagonal_ledge = Lara_Col_IsDiagonalLedge(coll);
int32_t pullup_floor = coll->side_front.floor;
if (diagonal_ledge) {
const int16_t base_angle =
Math_DirectionToAngle(Math_GetDirection(item->rot.y));
const int32_t diff =
((int32_t)(item->rot.y - base_angle + DEG_180) % DEG_360)
- DEG_180;
pullup_floor =
diff > 0 ? coll->side_right2.floor : coll->side_left2.floor;
}
const bool front_diagonal = coll->side_front.type == HT_DIAGONAL
|| coll->side_front.type == HT_SPLIT_TRI;
const bool front_clear =
coll->side_front.floor - coll->side_front.ceiling >= 0;
const bool side_clear =
coll->side_left2.floor - coll->side_left2.ceiling >= 0
&& coll->side_right2.floor - coll->side_right2.ceiling >= 0;

if (g_Input.forward) {
if (coll->side_front.floor > -850 && coll->side_front.floor < -650
&& coll->side_front.floor - coll->side_front.ceiling >= 0
&& coll->side_left2.floor - coll->side_left2.ceiling >= 0
&& coll->side_right2.floor - coll->side_right2.ceiling >= 0
if (pullup_floor > -850 && pullup_floor < -650
&& front_clear && (diagonal_ledge || front_diagonal || side_clear)
&& !coll->hit_static) {
item->goal_anim_state = LS(g_Input.slow ? LS_GYMNAST : LS_PULL_UP);
return;
Expand All @@ -544,10 +561,11 @@ static void M_Hang(ITEM *const item, COLL_INFO *const coll)
}

if (g_TRVersion == 3 && (g_Input.forward || g_Input.crouch)
&& coll->side_front.floor > -850 && coll->side_front.floor < -650
&& pullup_floor > -850 && pullup_floor < -650
&& coll->side_front.floor - coll->side_front.ceiling >= -256
&& coll->side_left2.floor - coll->side_left2.ceiling >= -256
&& coll->side_right2.floor - coll->side_right2.ceiling >= -256
&& (diagonal_ledge || front_diagonal
|| (coll->side_left2.floor - coll->side_left2.ceiling >= -256
&& coll->side_right2.floor - coll->side_right2.ceiling >= -256))
&& !coll->hit_static) {
item->goal_anim_state = LS(LS_CLIMB_TO_CRAWL);
item->required_anim_state = LS(LS_CROUCH_IDLE);
Expand Down Expand Up @@ -865,7 +883,11 @@ bool Lara_Col_TestVault(ITEM *const item, COLL_INFO *const coll)
return false;
}

const DIRECTION dir = Math_GetDirectionCone(item->rot.y, M_VAULT_ANGLE);
const bool diagonal_ledge = Lara_Col_IsDiagonalLedge(coll);
DIRECTION dir = Math_GetDirectionCone(item->rot.y, M_VAULT_ANGLE);
if (dir == DIR_UNKNOWN && diagonal_ledge) {
dir = Math_GetDirection(item->rot.y);
}
if (dir == DIR_UNKNOWN) {
return false;
}
Expand All @@ -877,7 +899,8 @@ bool Lara_Col_TestVault(ITEM *const item, COLL_INFO *const coll)
const int32_t right_ceiling = coll->side_right2.ceiling;
const int32_t front_floor = coll->side_front.floor;
const int32_t front_ceiling = coll->side_front.ceiling;
const bool slope = ABS(left_floor - right_floor) >= SLOPE_DIF;
const bool slope =
!diagonal_ledge && ABS(left_floor - right_floor) >= SLOPE_DIF;
const int32_t mid = STEP_L / 2;
const ROOM *const room = Room_Get(item->room_num);

Expand Down
59 changes: 35 additions & 24 deletions src/trx/game/lara/col/crouch.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,17 @@ static void M_CrawlToClimb(ITEM *const item, COLL_INFO *const coll)
return;
}

const DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
const bool diagonal_ledge = Lara_Col_IsDiagonalLedge(coll);
DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
const bool diagonal_direction = diagonal_ledge && dir == DIR_UNKNOWN;
if (diagonal_direction) {
dir = Math_GetDirection(item->rot.y);
}
if (dir == DIR_UNKNOWN) {
return;
}
const int16_t angle = Math_DirectionToAngle(dir);
const int16_t angle =
diagonal_ledge ? item->rot.y : Math_DirectionToAngle(dir);

if (Lara_Col_TestHangSwingIn(item, angle)) {
lara->head_rot.x = 0;
Expand All @@ -379,33 +385,38 @@ static void M_CrawlToClimb(ITEM *const item, COLL_INFO *const coll)
if (edge_catch == EDGE_CATCH_POS) {
item->pos.y += coll->side_front.floor - bounds->min.y;

switch (Math_GetDirection(item->rot.y)) {
case DIR_NORTH:
item->pos.z =
ROUND_TO_SECTOR_END(item->pos.z) - M_CRAWL_TO_HANG_XZ_OFFSET;
if (diagonal_ledge) {
item->pos.x += coll->shift.x;
break;

case DIR_EAST:
item->pos.x =
ROUND_TO_SECTOR_END(item->pos.x) - M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.z += coll->shift.z;
break;
} else {
switch (Math_GetDirection(item->rot.y)) {
case DIR_NORTH:
item->pos.z =
ROUND_TO_SECTOR_END(item->pos.z) - M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.x += coll->shift.x;
break;

case DIR_SOUTH:
item->pos.z =
ROUND_TO_SECTOR(item->pos.z) + M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.x += coll->shift.x;
break;
case DIR_EAST:
item->pos.x =
ROUND_TO_SECTOR_END(item->pos.x) - M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.z += coll->shift.z;
break;

case DIR_WEST:
item->pos.x =
ROUND_TO_SECTOR(item->pos.x) + M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.z += coll->shift.z;
break;
case DIR_SOUTH:
item->pos.z =
ROUND_TO_SECTOR(item->pos.z) + M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.x += coll->shift.x;
break;

case DIR_WEST:
item->pos.x =
ROUND_TO_SECTOR(item->pos.x) + M_CRAWL_TO_HANG_XZ_OFFSET;
item->pos.z += coll->shift.z;
break;

default:
break;
default:
break;
}
}
} else {
item->pos.y = edge - bounds->min.y;
Expand Down
Loading
Loading