WIP: New functions for turning states.

This commit is contained in:
Sezz 2021-10-08 15:47:54 +11:00
parent f16f967399
commit 4f908e3413

View file

@ -17,6 +17,8 @@
#include "items.h" #include "items.h"
#include "camera.h" #include "camera.h"
using namespace std;
/*generic functions*/ /*generic functions*/
void lara_void_func(ITEM_INFO* item, COLL_INFO* coll) void lara_void_func(ITEM_INFO* item, COLL_INFO* coll)
{ {
@ -470,6 +472,7 @@ void lara_col_run(ITEM_INFO* item, COLL_INFO* coll)
// Collision: lara_col_stop() // Collision: lara_col_stop()
void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll) void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
{ {
// TODO: New probe.
auto fHeight = LaraCollisionFront(item, item->pos.yRot, LARA_RAD + 4); auto fHeight = LaraCollisionFront(item, item->pos.yRot, LARA_RAD + 4);
auto cHeight = LaraCeilingCollisionFront(item, item->pos.yRot, LARA_RAD + 4, LARA_HEIGHT); auto cHeight = LaraCeilingCollisionFront(item, item->pos.yRot, LARA_RAD + 4, LARA_HEIGHT);
auto rHeight = LaraCollisionFront(item, item->pos.yRot + ANGLE(180.0f), LARA_RAD + 4); auto rHeight = LaraCollisionFront(item, item->pos.yRot + ANGLE(180.0f), LARA_RAD + 4);
@ -493,15 +496,17 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
if (TrInput & IN_LOOK) if (TrInput & IN_LOOK)
LookUpDown(); LookUpDown();
// TODO: Slight speed advantage when intention is to turn. Check how significant. @Sezz 2021.10.05 // TODO: Slight speed advantage when intention is to turn. Check how significant.
// Permit turning when Lara is stationary and cannot dispatch into a true turn. // Permit turning when Lara is stationary and cannot dispatch into a true turn.
if (TrInput & IN_LEFT && !(TrInput & IN_JUMP)) if (TrInput & IN_LEFT &&
!(TrInput & IN_JUMP)) // Temp solution: JUMP locks y rotation.
{ {
Lara.turnRate -= LARA_TURN_RATE; Lara.turnRate -= LARA_TURN_RATE;
if (Lara.turnRate < -LARA_SLOW_TURN) if (Lara.turnRate < -LARA_SLOW_TURN)
Lara.turnRate = -LARA_SLOW_TURN; Lara.turnRate = -LARA_SLOW_TURN;
} }
else if (TrInput & IN_RIGHT && !(TrInput & IN_JUMP)) else if (TrInput & IN_RIGHT &&
!(TrInput & IN_JUMP))
{ {
Lara.turnRate += LARA_TURN_RATE; Lara.turnRate += LARA_TURN_RATE;
if (Lara.turnRate > LARA_SLOW_TURN) if (Lara.turnRate > LARA_SLOW_TURN)
@ -516,8 +521,8 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
if (TrInput & IN_JUMP if (TrInput & IN_JUMP &&
&& (coll->Middle.Ceiling < -LARA_HEADROOM * 0.7f)) (coll->Middle.Ceiling < -LARA_HEADROOM * 0.7f))
{ {
item->goalAnimState = LS_JUMP_PREPARE; item->goalAnimState = LS_JUMP_PREPARE;
@ -526,7 +531,8 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
// TODO: The way sprinting works is messy. Lara should be able to stop sooner if // TODO: The way sprinting works is messy. Lara should be able to stop sooner if
// the state is set here. @ Sezz 2021.10.04 // the state is set here. @ Sezz 2021.10.04
if (TrInput & IN_SPRINT && TrInput & IN_FORWARD) if (TrInput & IN_SPRINT &&
TrInput & IN_FORWARD)
{ {
item->goalAnimState = LS_SPRINT; item->goalAnimState = LS_SPRINT;
@ -541,8 +547,8 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
} }
// TODO: Test failsafe which automatically crouches Lara if the ceiling above her is too low. // TODO: Test failsafe which automatically crouches Lara if the ceiling above her is too low.
if ((TrInput & IN_DUCK || TestLaraStandUp(coll)) if ((TrInput & IN_DUCK || TestLaraStandUp(coll)) &&
&& (Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType))) (Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType)))
{ {
if (Lara.gunType == WEAPON_REVOLVER) if (Lara.gunType == WEAPON_REVOLVER)
{ {
@ -555,14 +561,14 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
if (TrInput & IN_FORWARD if (TrInput & IN_FORWARD &&
&& !((fHeight.Position.Slope && (fHeight.Position.Floor < 0 || cHeight.Position.Ceiling > 0)) // Slope in front. !((fHeight.Position.Slope && (fHeight.Position.Floor < 0 || cHeight.Position.Ceiling > 0)) || // Slope in front.
|| coll->CollisionType == CT_FRONT)) // Wall/ceiling/object in front. coll->CollisionType == CT_FRONT)) // Wall/ceiling/object in front.
{ {
if (Lara.waterStatus == LW_WADE) if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WADE_FORWARD; item->goalAnimState = LS_WADE_FORWARD;
else if (TrInput & IN_WALK) else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_FORWARD; //test item->goalAnimState = LS_WALK_FORWARD;
else [[likely]] else [[likely]]
item->goalAnimState = LS_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
@ -576,7 +582,7 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
if (TrInput & IN_WALK if (TrInput & IN_WALK
&& (rHeight.Position.Floor < (STEPUP_HEIGHT - 1)) && (rHeight.Position.Floor < (STEPUP_HEIGHT - 1))
&& (rHeight.Position.Floor > -(STEPUP_HEIGHT - 1)) && (rHeight.Position.Floor > -(STEPUP_HEIGHT - 1))
&& !rHeight.Position.Slope) // TODO: This works when walking at the side of a slope, but not the front. && !rHeight.Position.Slope)
{ {
item->goalAnimState = LS_WALK_BACK; item->goalAnimState = LS_WALK_BACK;
} }
@ -589,19 +595,6 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
if (TrInput & IN_LEFT)
{
item->goalAnimState = LS_TURN_LEFT_SLOW;
return;
}
else if (TrInput & IN_RIGHT)
{
item->goalAnimState = LS_TURN_RIGHT_SLOW;
return;
}
if (TrInput & IN_LSTEP if (TrInput & IN_LSTEP
&& TestLaraStepLeft(item)) && TestLaraStepLeft(item))
{ {
@ -617,6 +610,21 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
if (TrInput & IN_LEFT)
{
// TODO: Direct dispatch to fast turn if sprint is held or Lara is wielding a weapon.
item->goalAnimState = LS_TURN_LEFT_SLOW;
return;
}
else if (TrInput & IN_RIGHT)
{
item->goalAnimState = LS_TURN_RIGHT_SLOW;
return;
}
item->goalAnimState = LS_STOP; item->goalAnimState = LS_STOP;
} }
@ -1136,21 +1144,19 @@ void lara_col_fastback(ITEM_INFO* item, COLL_INFO* coll)
// Collision: lara_col_turn_r() // Collision: lara_col_turn_r()
void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll) void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll)
{ {
auto fHeight = LaraCollisionFront(item, item->pos.yRot, LARA_RAD + 4); // TODO: Tests for forward/back movement dispatches.
auto cHeight = LaraCeilingCollisionFront(item, item->pos.yRot, LARA_RAD + 4, LARA_HEIGHT);
auto rHeight = LaraCollisionFront(item, item->pos.yRot + ANGLE(180.0f), LARA_RAD + 4);
if (item->hitPoints <= 0) if (item->hitPoints <= 0)
{ {
item->goalAnimState = LS_STOP; // Dispatch required. @Sezz 2021.10.05 item->goalAnimState = LS_DEATH;
return; return;
} }
// TODO: Looking needs better handling. // TODO: Looking needs better handling.
// TODO: Why can't this be anywhere below the run dispatch? // TODO: This can't be anywhere below the run dispatch because tests to prevent forward/back movement currently don't exist.
Lara.turnRate += LARA_TURN_RATE; // TODO: Sometimes, she inappropriately gains speed when stationary. Stop state to blame? @Sezz 2021.10.06 Lara.turnRate += LARA_TURN_RATE;
if (TrInput & IN_JUMP) if (TrInput & IN_JUMP)
{ {
@ -1159,51 +1165,50 @@ void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
if (TrInput & IN_SPRINT && TrInput & IN_FORWARD) if (TrInput & IN_SPRINT &&
TrInput & IN_FORWARD &&
Lara.waterStatus != LW_WADE)
{ {
item->goalAnimState = LS_SPRINT; item->goalAnimState = LS_SPRINT;
return; return;
} }
if (TrInput & IN_ROLL if (TrInput & IN_ROLL &&
&& Lara.waterStatus != LW_WADE) Lara.waterStatus != LW_WADE)
{ {
item->goalAnimState = LS_ROLL_FORWARD; item->goalAnimState = LS_ROLL_FORWARD;
return; return;
} }
if (TrInput & IN_DUCK if (TrInput & IN_DUCK &&
&& (Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType)) (Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType)) &&
&& Lara.waterStatus != LW_WADE) Lara.waterStatus != LW_WADE)
{ {
item->goalAnimState = LS_CROUCH_IDLE; item->goalAnimState = LS_CROUCH_IDLE;
return; return;
} }
// TODO: Collision checks don't seem to work? Investigate. @Sezz 2021.10.06 if (TrInput & IN_FORWARD &&
if (TrInput & IN_FORWARD Lara.waterStatus != LW_WADE)
&& !((fHeight.Position.Slope && (fHeight.Position.Floor < 0 || cHeight.Position.Ceiling > 0)) // Slope in front.
|| coll->CollisionType == CT_FRONT)) // Wall / ceiling / object in front.
{ {
if (Lara.waterStatus == LW_WADE) if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WADE_FORWARD; item->goalAnimState = LS_WADE_FORWARD;
else if (TrInput & IN_WALK) else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_FORWARD; item->goalAnimState = LS_WALK_FORWARD; // TODO: This is a frame-perfect input.
else [[likely]] else [[likely]]
item->goalAnimState = LS_RUN_FORWARD; item->goalAnimState = LS_RUN_FORWARD;
return; return;
} }
// TODO: Check for collision in back. @Sezz 2021.10.05
if (TrInput & IN_BACK) if (TrInput & IN_BACK)
{ {
if (Lara.waterStatus == LW_WADE) if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WALK_BACK; item->goalAnimState = LS_WALK_BACK;
else if (TrInput & IN_WALK) // TODO: This is a frame-perfect input. Somehow, Lara is able to sidestep from this state. @Sezz 2021.10.05 else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_BACK; item->goalAnimState = LS_WALK_BACK;
else [[likely]] else [[likely]]
item->goalAnimState = LS_HOP_BACK; item->goalAnimState = LS_HOP_BACK;
@ -1211,24 +1216,37 @@ void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll)
return; return;
} }
// TODO: Hold sprint to make her turn fast immediately? This way, the if (TrInput & IN_LSTEP &&
// "pro strat" of pulling out pistols to turn fast won't be necessary. @Sezz 2021.10.05 TestLaraStepLeft(item))
{
item->goalAnimState = LS_STEP_LEFT;
return;
}
else if (TrInput & IN_RSTEP &&
TestLaraStepRight(item))
{
item->goalAnimState = LS_STEP_RIGHT;
return;
}
if (TrInput & IN_RIGHT) if (TrInput & IN_RIGHT)
{ {
if (Lara.waterStatus == LW_WADE) if (TrInput & IN_WALK || // TODO: This doesn't work since TR1.
Lara.waterStatus == LW_WADE)
{ {
if (Lara.turnRate > LARA_SLOW_TURN) if (Lara.turnRate > LARA_SLOW_TURN)
Lara.turnRate = LARA_SLOW_TURN; Lara.turnRate = LARA_SLOW_TURN;
item->goalAnimState = LS_TURN_RIGHT_SLOW; item->goalAnimState = LS_TURN_RIGHT_SLOW;
} }
else if (Lara.gunStatus == LG_READY) else if (TrInput & IN_SPRINT || // TODO: Allow this to dispatch when SPRINT is pressed AFTER Lara has already entered this state.
Lara.turnRate > LARA_SLOW_TURN ||
Lara.gunStatus == LG_READY)
{ {
//Lara.turnRate = LARA_MED_TURN; // TODO: Finetune starting turn rate. Or, dispatch directly to fast turn state. @Sezz 2021.10.05 item->goalAnimState = LS_TURN_FAST; // TODO: New state for fast turn right.
item->goalAnimState = LS_TURN_FAST;
} }
else if (Lara.turnRate > LARA_SLOW_TURN)
item->goalAnimState = LS_TURN_FAST;
else [[likely]] else [[likely]]
item->goalAnimState = LS_TURN_RIGHT_SLOW; item->goalAnimState = LS_TURN_RIGHT_SLOW;
@ -1334,7 +1352,119 @@ void lara_col_turn_r(ITEM_INFO* item, COLL_INFO* coll)
#endif #endif
} }
// State: LS_TURN_LEFT_SLOW (7)
// Collision: lara_col_turn_l()
void lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll) void lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_DEATH;
return;
}
Lara.turnRate -= LARA_TURN_RATE;
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_PREPARE;
return;
}
if (TrInput & IN_SPRINT &&
TrInput & IN_FORWARD &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_SPRINT;
return;
}
if (TrInput & IN_ROLL &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_ROLL_FORWARD;
return;
}
if (TrInput & IN_DUCK &&
(Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType)) &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_CROUCH_IDLE;
return;
}
if (TrInput & IN_FORWARD &&
Lara.waterStatus != LW_WADE)
{
if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WADE_FORWARD;
else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_FORWARD;
else [[likely]]
item->goalAnimState = LS_RUN_FORWARD;
return;
}
if (TrInput & IN_BACK)
{
if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WALK_BACK;
else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_BACK;
else [[likely]]
item->goalAnimState = LS_HOP_BACK;
return;
}
if (TrInput & IN_LSTEP &&
TestLaraStepLeft(item))
{
item->goalAnimState = LS_STEP_LEFT;
return;
}
else if (TrInput & IN_RSTEP &&
TestLaraStepRight(item))
{
item->goalAnimState = LS_STEP_RIGHT;
return;
}
if (TrInput & IN_LEFT)
{
if (TrInput & IN_WALK ||
Lara.waterStatus == LW_WADE)
{
if (Lara.turnRate < -LARA_SLOW_TURN)
Lara.turnRate = -LARA_SLOW_TURN;
item->goalAnimState = LS_TURN_LEFT_SLOW;
}
else if (TrInput & IN_SPRINT ||
Lara.turnRate < -LARA_SLOW_TURN ||
Lara.gunStatus == LG_READY)
{
item->goalAnimState = LS_TURN_FAST; // TODO: New state for fast turn left; this is currently broken.
}
else [[likely]]
item->goalAnimState = LS_TURN_RIGHT_SLOW;
return;
}
item->goalAnimState = LS_STOP;
}
// LEGACY
void old_lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll)
{ {
/*state 7*/ /*state 7*/
/*collision: lara_col_turn_l*/ /*collision: lara_col_turn_l*/
@ -1817,7 +1947,106 @@ void lara_col_back(ITEM_INFO* item, COLL_INFO* coll)
#endif #endif
} }
// NEW fast turn right
// TODO: Dispatch and state value required. @Sezz 2021.09.29
void lara_as_fastturn(ITEM_INFO* item, COLL_INFO* coll) void lara_as_fastturn(ITEM_INFO* item, COLL_INFO* coll)
{
if (item->hitPoints <= 0)
{
item->goalAnimState = LS_DEATH;
return;
}
if (TrInput & IN_SPRINT &&
TrInput & IN_FORWARD &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_SPRINT;
return;
}
if (TrInput & IN_JUMP)
{
item->goalAnimState = LS_JUMP_PREPARE;
return;
}
if (TrInput & IN_ROLL &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_ROLL_FORWARD;
return;
}
if (TrInput & IN_DUCK &&
(Lara.gunStatus == LG_NO_ARMS || !IsStandingWeapon(Lara.gunType)) &&
Lara.waterStatus != LW_WADE)
{
item->goalAnimState = LS_CROUCH_IDLE;
return;
}
if (TrInput & IN_FORWARD &&
coll->CollisionType != CT_FRONT)
{
if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WADE_FORWARD;
else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_FORWARD;
else [[likely]]
item->goalAnimState = LS_RUN_FORWARD;
return;
}
if (TrInput & IN_BACK)
{
if (Lara.waterStatus == LW_WADE)
item->goalAnimState = LS_WALK_BACK;
else if (TrInput & IN_WALK)
item->goalAnimState = LS_WALK_BACK;
else [[likely]]
item->goalAnimState = LS_HOP_BACK;
return;
}
if (TrInput & IN_LSTEP &&
TestLaraStepLeft(item))
{
item->goalAnimState = LS_STEP_LEFT;
return;
}
else if (TrInput & IN_RSTEP &&
TestLaraStepRight(item))
{
item->goalAnimState = LS_STEP_RIGHT;
return;
}
// TODO: Hold WALK to slow down again.
if (TrInput & IN_RIGHT)
{
Lara.turnRate += LARA_TURN_RATE;
Lara.turnRate = clamp(Lara.turnRate, LARA_MED_TURN, LARA_FAST_TURN);
//item->goalAnimState = LS_TURN_RIGHT_FAST; // TODO: New state.
return;
}
item->goalAnimState = LS_STOP;
}
// LEGACY still used
void old_lara_as_fastturn(ITEM_INFO* item, COLL_INFO* coll)
{ {
/*state 20*/ /*state 20*/
/*collision: lara_col_fastturn*/ /*collision: lara_col_fastturn*/