Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 15546f5

Browse files
committed
Implemented WalkAngle shenanigans for AHuman + other cleanup and optimization
1 parent efed75e commit 15546f5

File tree

4 files changed

+115
-109
lines changed

4 files changed

+115
-109
lines changed

Entities/AHuman.cpp

Lines changed: 97 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ void AHuman::Clear()
8181
m_FGArmFlailScalar = 0.0F;
8282
m_BGArmFlailScalar = 0.7F;
8383
m_EquipHUDTimer.Reset();
84+
m_WalkAngle.fill(Matrix());
8485

8586
m_DeviceState = SCANNING;
8687
m_SweepState = NOSWEEP;
@@ -1796,6 +1797,41 @@ bool AHuman::UpdateMovePath()
17961797
return true;
17971798
}
17981799

1800+
//////////////////////////////////////////////////////////////////////////////////////////
1801+
1802+
void AHuman::UpdateWalkAngle(AHuman::Layer whichLayer) {
1803+
if (m_Controller.IsState(BODY_JUMP)) {
1804+
m_WalkAngle[whichLayer] = Matrix(c_QuarterPI * GetFlipFactor());
1805+
} else if (m_MaintainUpright) {
1806+
// Cast rays to calculate the approximate shape of terrain.
1807+
int rayCount = 4;
1808+
float rayLength = 10.0F;
1809+
Vector hipPos = m_Pos;
1810+
if (whichLayer == AHuman::Layer::FGROUND && m_pFGLeg) {
1811+
rayLength += m_pFGLeg->GetMaxLength();
1812+
hipPos += RotateOffset(m_pFGLeg->GetParentOffset());
1813+
} else if (m_pBGLeg) {
1814+
rayLength += m_pBGLeg->GetMaxLength();
1815+
hipPos += RotateOffset(m_pBGLeg->GetParentOffset());
1816+
}
1817+
float traceRotation = rayCount > 1 ? c_HalfPI / static_cast<float>(rayCount - 1) * GetFlipFactor() : 0;
1818+
Vector hitPos;
1819+
Vector terrainVector(0, rayLength);
1820+
Vector trace(0, rayLength);
1821+
for (int i = 0; i < rayCount; i++) {
1822+
if (g_SceneMan.CastStrengthRay(hipPos, trace, 10.0F, hitPos, 4, g_MaterialGrass)) {
1823+
terrainVector += trace - g_SceneMan.ShortestDistance(hipPos, hitPos, g_SceneMan.SceneWrapsX());
1824+
} else {
1825+
// Reinforce focus on previously assumed terrain.
1826+
terrainVector *= 1.5F;
1827+
}
1828+
trace.RadRotate(traceRotation);
1829+
}
1830+
m_WalkAngle[whichLayer] = Matrix((terrainVector * GetFlipFactor()).GetAbsRadAngle() + c_HalfPI * GetFlipFactor());
1831+
} else {
1832+
m_WalkAngle[whichLayer] = m_Rotation;
1833+
}
1834+
}
17991835

18001836
//////////////////////////////////////////////////////////////////////////////////////////
18011837
// Virtual method: UpdateAI
@@ -3565,51 +3601,39 @@ void AHuman::Update()
35653601
float FGLegProg = m_Paths[FGROUND][WALK].GetRegularProgress();
35663602
float BGLegProg = m_Paths[BGROUND][WALK].GetRegularProgress();
35673603

3568-
bool playStride = false;
3604+
bool restarted = false;
35693605

35703606
// Make sure we are starting a stride if we're basically stopped.
35713607
if (isStill) { m_StrideStart = true; }
35723608

3573-
if (m_pFGLeg && (!m_pBGLeg || (!(m_Paths[FGROUND][WALK].PathEnded() && BGLegProg < 0.5) || m_StrideStart)))
3574-
{
3575-
// m_StrideStart = false;
3576-
// Reset the stride timer if the path is about to restart
3577-
if (m_Paths[FGROUND][WALK].PathEnded() || m_Paths[FGROUND][WALK].PathIsAtStart())
3578-
m_StrideTimer.Reset();
3579-
m_ArmClimbing[BGROUND] = !m_pFGFootGroup->PushAsLimb(m_Pos +
3580-
m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped),
3581-
m_Vel,
3582-
Matrix(),
3583-
m_Paths[FGROUND][WALK],
3584-
deltaTime,
3585-
&playStride,
3586-
false);
3587-
}
3588-
else
3589-
m_ArmClimbing[BGROUND] = false;
3590-
3591-
if (m_pBGLeg && (!m_pFGLeg || !(m_Paths[BGROUND][WALK].PathEnded() && FGLegProg < 0.5)))
3592-
{
3593-
m_StrideStart = false;
3594-
// Reset the stride timer if the path is about to restart
3595-
if (m_Paths[BGROUND][WALK].PathEnded() || m_Paths[BGROUND][WALK].PathIsAtStart())
3596-
m_StrideTimer.Reset();
3597-
m_ArmClimbing[FGROUND] = !m_pBGFootGroup->PushAsLimb(m_Pos +
3598-
m_pBGLeg->GetParentOffset().GetXFlipped(m_HFlipped),
3599-
m_Vel,
3600-
Matrix(),
3601-
m_Paths[BGROUND][WALK],
3602-
deltaTime,
3603-
&playStride,
3604-
false);
3605-
}
3606-
else
3607-
m_ArmClimbing[FGROUND] = false;
3609+
if (m_pFGLeg && (!m_pBGLeg || !(m_Paths[FGROUND][WALK].PathEnded() && BGLegProg < 0.5F) || m_StrideStart)) {
3610+
// Reset the stride timer if the path is about to restart.
3611+
if (m_Paths[FGROUND][WALK].PathEnded() || m_Paths[FGROUND][WALK].PathIsAtStart()) { m_StrideTimer.Reset(); }
3612+
m_ArmClimbing[BGROUND] = !(m_pFGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pFGLeg->GetParentOffset()), m_Vel, m_WalkAngle[FGROUND], m_Paths[FGROUND][WALK], deltaTime, &restarted, false));
3613+
if (restarted) { UpdateWalkAngle(FGROUND); }
3614+
} else {
3615+
m_ArmClimbing[BGROUND] = false;
3616+
}
3617+
if (m_pBGLeg && (!m_pFGLeg || !(m_Paths[BGROUND][WALK].PathEnded() && FGLegProg < 0.5F))) {
3618+
m_StrideStart = false;
3619+
// Reset the stride timer if the path is about to restart.
3620+
if (m_Paths[BGROUND][WALK].PathEnded() || m_Paths[BGROUND][WALK].PathIsAtStart()) { m_StrideTimer.Reset(); }
3621+
m_ArmClimbing[FGROUND] = !m_pBGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pBGLeg->GetParentOffset()), m_Vel, m_WalkAngle[BGROUND], m_Paths[BGROUND][WALK], deltaTime, &restarted, false);
3622+
if (restarted) { UpdateWalkAngle(BGROUND); }
3623+
} else {
3624+
if (m_pBGLeg) { m_pBGFootGroup->FlailAsLimb(m_Pos, RotateOffset(m_pBGLeg->GetParentOffset()), m_pBGLeg->GetMaxLength(), m_PrevVel, m_AngularVel, m_pBGLeg->GetMass(), deltaTime); }
3625+
m_ArmClimbing[FGROUND] = false;
3626+
}
3627+
bool climbing = m_ArmClimbing[FGROUND] || m_ArmClimbing[BGROUND];
36083628

3609-
// Play the stride sound, if applicable
3610-
if (playStride && !m_ArmClimbing[FGROUND] && !m_ArmClimbing[BGROUND]) {
3611-
if (m_StrideSound) { m_StrideSound->Play(m_Pos); }
3612-
RunScriptedFunctionInAppropriateScripts("OnStride");
3629+
if (restarted) {
3630+
if (!climbing) {
3631+
if (m_StrideSound) { m_StrideSound->Play(m_Pos); }
3632+
RunScriptedFunctionInAppropriateScripts("OnStride");
3633+
} else {
3634+
m_WalkAngle[FGROUND] = Matrix();
3635+
m_WalkAngle[BGROUND] = Matrix();
3636+
}
36133637
}
36143638

36153639
////////////////////////////////////////
@@ -3620,61 +3644,41 @@ void AHuman::Update()
36203644
float FGArmProg = m_Paths[FGROUND][CLIMB].GetRegularProgress();
36213645
float BGArmProg = m_Paths[BGROUND][CLIMB].GetRegularProgress();
36223646

3647+
// TODO: Figure out what this comment means, and then rephrase it better!
36233648
// Slightly negative BGArmProg makes sense because any progress on the starting segments are reported as negative,
36243649
// and there's many starting segments on properly formed climbing paths
3625-
if (m_pFGArm && (m_ArmClimbing[FGROUND] || m_ArmClimbing[BGROUND]) && (!m_pBGArm || !m_pFGLeg || BGArmProg > 0.1))
3626-
{
3627-
m_ArmClimbing[FGROUND] = true;
3628-
m_Paths[FGROUND][WALK].Terminate();
3629-
// m_Paths[BGROUND][WALK].Terminate();
3630-
m_StrideStart = true;
3631-
// Reset the stride timer if the path is about to restart
3632-
if (m_Paths[FGROUND][CLIMB].PathEnded() || m_Paths[FGROUND][CLIMB].PathIsAtStart())
3633-
m_StrideTimer.Reset();
3634-
m_pFGHandGroup->PushAsLimb(m_Pos +
3635-
m_pFGArm->GetParentOffset().GetXFlipped(m_HFlipped),
3636-
m_Vel,
3637-
m_Rotation,
3638-
m_Paths[FGROUND][CLIMB],
3639-
deltaTime);
3640-
}
3641-
else
3642-
{
3643-
m_ArmClimbing[FGROUND] = false;
3644-
m_Paths[FGROUND][CLIMB].Terminate();
3645-
}
3646-
3647-
if (m_pBGArm && (m_ArmClimbing[FGROUND] || m_ArmClimbing[BGROUND]))
3648-
{
3649-
m_ArmClimbing[BGROUND] = true;
3650-
// m_Paths[FGROUND][WALK].Terminate();
3651-
m_Paths[BGROUND][WALK].Terminate();
3652-
m_StrideStart = true;
3653-
// Reset the stride timer if the path is about to restart
3654-
if (m_Paths[BGROUND][CLIMB].PathEnded() || m_Paths[BGROUND][CLIMB].PathIsAtStart())
3655-
m_StrideTimer.Reset();
3656-
m_pBGHandGroup->PushAsLimb(m_Pos +
3657-
m_pBGArm->GetParentOffset().GetXFlipped(m_HFlipped),
3658-
m_Vel,
3659-
m_Rotation,
3660-
m_Paths[BGROUND][CLIMB],
3661-
deltaTime);
3662-
}
3663-
else
3664-
{
3665-
m_ArmClimbing[BGROUND] = false;
3666-
m_Paths[BGROUND][CLIMB].Terminate();
3667-
}
3650+
if (climbing) {
3651+
if (m_pFGArm && !(m_Paths[FGROUND][CLIMB].PathEnded() && BGArmProg > 0.1F)) { // < 0.5F
3652+
m_ArmClimbing[FGROUND] = true;
3653+
m_Paths[FGROUND][WALK].Terminate();
3654+
m_StrideStart = true;
3655+
// Reset the stride timer if the path is about to restart.
3656+
if (m_Paths[FGROUND][CLIMB].PathEnded() || m_Paths[FGROUND][CLIMB].PathIsAtStart()) { m_StrideTimer.Reset(); }
3657+
m_pFGHandGroup->PushAsLimb(m_Pos + Vector(0, m_pFGArm->GetParentOffset().m_Y).RadRotate(-rot), m_Vel, Matrix(), m_Paths[FGROUND][CLIMB], deltaTime, 0, false);
3658+
} else {
3659+
m_ArmClimbing[FGROUND] = false;
3660+
m_Paths[FGROUND][CLIMB].Terminate();
3661+
}
3662+
if (m_pBGArm) {
3663+
m_ArmClimbing[BGROUND] = true;
3664+
m_Paths[BGROUND][WALK].Terminate();
3665+
m_StrideStart = true;
3666+
// Reset the stride timer if the path is about to restart.
3667+
if (m_Paths[BGROUND][CLIMB].PathEnded() || m_Paths[BGROUND][CLIMB].PathIsAtStart()) { m_StrideTimer.Reset(); }
3668+
m_pBGHandGroup->PushAsLimb(m_Pos + Vector(0, m_pBGArm->GetParentOffset().m_Y).RadRotate(-rot), m_Vel, Matrix(), m_Paths[BGROUND][CLIMB], deltaTime, 0, false);
3669+
} else {
3670+
m_ArmClimbing[BGROUND] = false;
3671+
m_Paths[BGROUND][CLIMB].Terminate();
3672+
}
3673+
}
36683674

3669-
// Restart the climbing stroke if the current one seems to be taking too long with no movement.
3670-
if ((m_ArmClimbing[FGROUND] || m_ArmClimbing[BGROUND]) && isStill && m_StrideTimer.IsPastSimMS(static_cast<double>(m_Paths[BGROUND][CLIMB].GetTotalPathTime() * 0.5F))) {
3675+
// Restart the climbing stroke if the current one seems to be taking too long with no movement.
3676+
if (climbing && isStill && m_StrideTimer.IsPastSimMS(static_cast<double>(m_Paths[BGROUND][CLIMB].GetTotalPathTime() * 0.5F))) {
36713677
m_StrideStart = true;
36723678
m_Paths[FGROUND][CLIMB].Terminate();
36733679
m_Paths[BGROUND][CLIMB].Terminate();
3674-
}
3675-
// Reset the walking stride if it's taking too long
3676-
else if (m_StrideTimer.IsPastSimMS(m_Paths[FGROUND][WALK].GetTotalPathTime()))
3677-
{
3680+
} else if (m_StrideTimer.IsPastSimMS(static_cast<double>(m_Paths[FGROUND][WALK].GetTotalPathTime() * 1.1F))) {
3681+
// Reset the walking stride if it's taking longer than it should.
36783682
m_StrideStart = true;
36793683
m_Paths[FGROUND][WALK].Terminate();
36803684
m_Paths[BGROUND][WALK].Terminate();
@@ -3692,15 +3696,8 @@ void AHuman::Update()
36923696
{
36933697
// m_StrideStart = false;
36943698
// Reset the stride timer if the path is about to restart
3695-
if (m_Paths[FGROUND][CRAWL].PathEnded() || m_Paths[FGROUND][CRAWL].PathIsAtStart())
3696-
m_StrideTimer.Reset();
3697-
m_pFGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pFGLeg->GetParentOffset()),
3698-
m_Vel,
3699-
m_Rotation,
3700-
m_Paths[FGROUND][CRAWL],
3701-
deltaTime,
3702-
0,
3703-
true);
3699+
if (m_Paths[FGROUND][CRAWL].PathEnded() || m_Paths[FGROUND][CRAWL].PathIsAtStart()) { m_StrideTimer.Reset(); }
3700+
m_pFGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pFGLeg->GetParentOffset()), m_Vel, m_Rotation, m_Paths[FGROUND][CRAWL], deltaTime);
37043701
}
37053702
else
37063703
m_Paths[FGROUND][CRAWL].Terminate();
@@ -3710,16 +3707,8 @@ void AHuman::Update()
37103707
{
37113708
m_StrideStart = false;
37123709
// Reset the stride timer if the path is about to restart
3713-
if (m_Paths[BGROUND][CRAWL].PathEnded() || m_Paths[BGROUND][CRAWL].PathIsAtStart())
3714-
m_StrideTimer.Reset();
3715-
// If both legs can't find free resrtart, ti's time to use the arm!
3716-
m_pBGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pBGLeg->GetParentOffset()),
3717-
m_Vel,
3718-
m_Rotation,
3719-
m_Paths[BGROUND][CRAWL],
3720-
deltaTime,
3721-
0,
3722-
true);
3710+
if (m_Paths[BGROUND][CRAWL].PathEnded() || m_Paths[BGROUND][CRAWL].PathIsAtStart()) { m_StrideTimer.Reset(); }
3711+
m_pBGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pBGLeg->GetParentOffset()), m_Vel, m_Rotation, m_Paths[BGROUND][CRAWL], deltaTime);
37233712
}
37243713
else
37253714
m_Paths[BGROUND][CRAWL].Terminate();

Entities/AHuman.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,21 @@ ClassInfoGetters;
761761
bool UpdateMovePath() override;
762762

763763

764+
/// <summary>
765+
/// Detects slopes in terrain and updates the walk path rotation for the corresponding Layer accordingly.
766+
/// </summary>
767+
/// <param name="whichLayer">The Layer in question.</param>
768+
void UpdateWalkAngle(AHuman::Layer whichLayer);
769+
770+
771+
/// <summary>
772+
/// Sets the walk path rotation for the specified Layer.
773+
/// </summary>
774+
/// <param name="whichLayer">The Layer in question.</param>
775+
/// <param name="angle">The angle to set.</param>
776+
void SetWalkAngle(AHuman::Layer whichLayer, float angle) { m_WalkAngle[whichLayer] = Matrix(angle); }
777+
778+
764779
//////////////////////////////////////////////////////////////////////////////////////////
765780
// Virtual method: UpdateAI
766781
//////////////////////////////////////////////////////////////////////////////////////////
@@ -997,6 +1012,7 @@ ClassInfoGetters;
9971012
float m_FGArmFlailScalar; //!< The rate at which this AHuman's FG Arm follows the the bodily rotation. Best to keep this at 0 so it doesn't complicate aiming.
9981013
float m_BGArmFlailScalar; //!< The rate at which this AHuman's BG Arm follows the the bodily rotation. Set to a negative value for a "counterweight" effect.
9991014
Timer m_EquipHUDTimer; //!< Timer for showing the name of any newly equipped Device.
1015+
std::array<Matrix, 2> m_WalkAngle; //!< An array of rot angle targets for different movement states.
10001016

10011017
////////////////
10021018
// AI States

Entities/LimbPath.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ Vector LimbPath::GetCurrentVel(const Vector &limbPos)
300300
{
301301
Vector returnVel;
302302
Vector distVect = g_SceneMan.ShortestDistance(limbPos, GetCurrentSegTarget());
303-
float adjustedTravelSpeed = m_TravelSpeed[m_WhichSpeed] / (1.0F + m_JointVel.GetMagnitude() * 0.1F);
303+
float adjustedTravelSpeed = m_TravelSpeed[m_WhichSpeed] / std::max((std::abs(m_JointVel.GetY()) - std::abs(m_JointVel.GetX())) * 0.5F, 1.0F);
304304

305305
if (IsStaticPoint())
306306
{

Lua/LuaBindingsEntities.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ namespace RTE {
442442
.def("SetLimbPathSpeed", &AHuman::SetLimbPathSpeed)
443443
.def("GetRotAngleTarget", &AHuman::GetRotAngleTarget)
444444
.def("SetRotAngleTarget", &AHuman::SetRotAngleTarget)
445+
.def("SetWalkAngle", &AHuman::SetWalkAngle)
445446

446447
.enum_("UpperBodyState")[
447448
luabind::value("WEAPON_READY", AHuman::UpperBodyState::WEAPON_READY),

0 commit comments

Comments
 (0)