Refactor as_reach

This commit is contained in:
Lwmte 2021-10-27 09:48:48 +03:00
parent 38862dac8d
commit f57d9080b8
3 changed files with 125 additions and 126 deletions

View file

@ -1006,9 +1006,6 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)
if (Lara.ropePtr == -1) if (Lara.ropePtr == -1)
item->gravityStatus = true; item->gravityStatus = true;
// Extend collision radius by fixed multiplier to avoid tunneling on high velocities.
constexpr auto collRadiusMult = 0.2f;
Lara.moveAngle = item->pos.yRot; Lara.moveAngle = item->pos.yRot;
coll->Setup.Height = LARA_HEIGHT_STRETCH; coll->Setup.Height = LARA_HEIGHT_STRETCH;
@ -1016,137 +1013,33 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)
coll->Setup.BadHeightUp = 0; coll->Setup.BadHeightUp = 0;
coll->Setup.BadCeilingHeight = BAD_JUMP_CEILING; coll->Setup.BadCeilingHeight = BAD_JUMP_CEILING;
coll->Setup.ForwardAngle = Lara.moveAngle; coll->Setup.ForwardAngle = Lara.moveAngle;
coll->Setup.Radius += coll->Setup.Radius * collRadiusMult; coll->Setup.Radius = coll->Setup.Radius * 1.2f;
coll->Setup.Mode = COLL_PROBE_MODE::CP_FREE_FORWARD; coll->Setup.Mode = COLL_PROBE_MODE::FREE_FORWARD;
GetCollisionInfo(coll, item); GetCollisionInfo(coll, item);
short angle; if (TestLaraHangJump(item, coll))
bool result = false; return;
int edge = 0;
int edgeCatch = 0;
if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && !coll->HitStatic) LaraSlideEdgeJump(item, coll);
coll->Setup.ForwardAngle = Lara.moveAngle;
GetCollisionInfo(coll, item);
ShiftItem(item, coll);
if (item->fallspeed > 0 && coll->Middle.Floor <= 0)
{ {
if (Lara.canMonkeySwing && coll->CollisionType == CT_TOP) if (LaraLandedBad(item, coll))
{ {
Lara.headYrot = 0; item->goalAnimState = LS_DEATH;
Lara.headXrot = 0; }
Lara.torsoYrot = 0; else
Lara.torsoXrot = 0; {
Lara.gunStatus = LG_HANDS_BUSY; item->goalAnimState = LS_STOP;
item->animNumber = LA_REACH_TO_MONKEYSWING;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LS_MONKEYSWING_IDLE;
item->currentAnimState = LS_MONKEYSWING_IDLE;
item->gravityStatus = false;
item->speed = 0;
item->fallspeed = 0; item->fallspeed = 0;
item->gravityStatus = false;
return; if (coll->Middle.Floor != NO_HEIGHT)
item->pos.yPos += coll->Middle.Floor;
} }
if (coll->Middle.Ceiling <= -384 &&
coll->Middle.Floor >= 200 &&
coll->CollisionType == CT_FRONT)
{
edgeCatch = TestLaraEdgeCatch(item, coll, &edge);
if (!(!edgeCatch || edgeCatch < 0 && !TestLaraHangOnClimbWall(item, coll)))
{
angle = item->pos.yRot;
result = TestValidLedge(item, coll, true);
}
}
}
if (!result)
{
LaraSlideEdgeJump(item, coll);
coll->Setup.ForwardAngle = Lara.moveAngle;
GetCollisionInfo(coll, item);
ShiftItem(item, coll);
if (item->fallspeed > 0 && coll->Middle.Floor <= 0)
{
if (LaraLandedBad(item, coll))
{
item->goalAnimState = LS_DEATH;
}
else
{
item->goalAnimState = LS_STOP;
item->fallspeed = 0;
item->gravityStatus = false;
if (coll->Middle.Floor != NO_HEIGHT)
item->pos.yPos += coll->Middle.Floor;
}
}
}
else
{
if (TestHangSwingIn(item, angle))
{
if (Lara.NewAnims.OscillateHanging)
{
Lara.headYrot = 0;
Lara.headXrot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
item->animNumber = LA_REACH_TO_HANG_OSCILLATE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG;
}
else
{
Lara.headYrot = 0;
Lara.headXrot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
item->animNumber = LA_REACH_TO_MONKEYSWING;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_MONKEYSWING_IDLE;
item->goalAnimState = LS_MONKEYSWING_IDLE;
}
}
else
{
if (TestHangFeet(item, angle))
{
item->animNumber = LA_REACH_TO_HANG;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG_FEET;
}
else
{
item->animNumber = LA_REACH_TO_HANG;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG;
}
}
BOUNDING_BOX* bounds = GetBoundsAccurate(item);
if (edgeCatch <= 0)
{
item->pos.yPos = edge - bounds->Y1 - 20;
item->pos.yRot = coll->NearestLedgeAngle;
}
else
{
item->pos.yPos += coll->Front.Floor - bounds->Y1 - 20;
SnapItemToLedge(item, coll, collRadiusMult);
}
item->gravityStatus = true;
item->speed = 2;
item->fallspeed = 1;
Lara.gunStatus = LG_HANDS_BUSY;
} }
} }

View file

@ -362,6 +362,111 @@ SPLAT_COLL TestLaraWall(ITEM_INFO* item, int front, int right, int down)
return SPLAT_COLL::NONE; return SPLAT_COLL::NONE;
} }
bool TestLaraHangJump(ITEM_INFO* item, COLL_INFO* coll)
{
if (!(TrInput & IN_ACTION) || (Lara.gunStatus != LG_NO_ARMS) || (coll->HitStatic))
return false;
if (Lara.canMonkeySwing && coll->CollisionType == CT_TOP)
{
Lara.headYrot = 0;
Lara.headXrot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
Lara.gunStatus = LG_HANDS_BUSY;
item->animNumber = LA_REACH_TO_MONKEYSWING;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = LS_MONKEYSWING_IDLE;
item->currentAnimState = LS_MONKEYSWING_IDLE;
item->gravityStatus = false;
item->speed = 0;
item->fallspeed = 0;
return true;
}
if ((coll->Middle.Ceiling > -STEPUP_HEIGHT) ||
(coll->Middle.Floor < 200) ||
(coll->CollisionType != CT_FRONT))
return false;
int edge = 0;
auto edgeCatch = TestLaraEdgeCatch(item, coll, &edge);
if (!edgeCatch)
return false;
if (!(TestLaraHangOnClimbWall(item, coll) && edgeCatch) &&
!(TestValidLedge(item, coll, true) && edgeCatch > 0))
return false;
auto angle = item->pos.yRot;
if (TestHangSwingIn(item, angle))
{
if (Lara.NewAnims.OscillateHanging)
{
Lara.headYrot = 0;
Lara.headXrot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
item->animNumber = LA_REACH_TO_HANG_OSCILLATE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG;
}
else
{
Lara.headYrot = 0;
Lara.headXrot = 0;
Lara.torsoYrot = 0;
Lara.torsoXrot = 0;
item->animNumber = LA_REACH_TO_MONKEYSWING;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_MONKEYSWING_IDLE;
item->goalAnimState = LS_MONKEYSWING_IDLE;
}
}
else
{
if (TestHangFeet(item, angle))
{
item->animNumber = LA_REACH_TO_HANG;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG_FEET;
}
else
{
item->animNumber = LA_REACH_TO_HANG;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->currentAnimState = LS_HANG;
item->goalAnimState = LS_HANG;
}
}
auto bounds = GetBoundsAccurate(item);
if (edgeCatch <= 0)
{
item->pos.yPos = edge - bounds->Y1 - 20;
item->pos.yRot = coll->NearestLedgeAngle;
}
else
{
item->pos.yPos += coll->Front.Floor - bounds->Y1 - 20;
SnapItemToLedge(item, coll, 0.2f);
}
item->gravityStatus = true;
item->speed = 2;
item->fallspeed = 1;
Lara.gunStatus = LG_HANDS_BUSY;
return true;
}
bool TestLaraHang(ITEM_INFO* item, COLL_INFO* coll) bool TestLaraHang(ITEM_INFO* item, COLL_INFO* coll)
{ {
ANIM_FRAME* frame; ANIM_FRAME* frame;

View file

@ -12,6 +12,7 @@ bool TestLaraStandUp(COLL_INFO* coll);
bool TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll); bool TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll);
bool TestLaraLean(ITEM_INFO* item, COLL_INFO* coll); bool TestLaraLean(ITEM_INFO* item, COLL_INFO* coll);
bool TestLaraHang(ITEM_INFO* item, COLL_INFO* coll); bool TestLaraHang(ITEM_INFO* item, COLL_INFO* coll);
bool TestLaraHangJump(ITEM_INFO* item, COLL_INFO* coll);
bool TestLaraClimbStance(ITEM_INFO* item, COLL_INFO* coll); bool TestLaraClimbStance(ITEM_INFO* item, COLL_INFO* coll);
bool TestLaraHangOnClimbWall(ITEM_INFO* item, COLL_INFO* coll); bool TestLaraHangOnClimbWall(ITEM_INFO* item, COLL_INFO* coll);
int TestLaraEdgeCatch(ITEM_INFO* item, COLL_INFO* coll, int* edge); int TestLaraEdgeCatch(ITEM_INFO* item, COLL_INFO* coll, int* edge);