diff --git a/Source/Entities/AHuman.cpp b/Source/Entities/AHuman.cpp index 5cf483ea88..41bc6f0c20 100644 --- a/Source/Entities/AHuman.cpp +++ b/Source/Entities/AHuman.cpp @@ -1,6 +1,7 @@ #include "AHuman.h" #include "AtomGroup.h" +#include "RTETools.h" #include "ThrownDevice.h" #include "Arm.h" #include "Leg.h" @@ -2563,8 +2564,8 @@ void AHuman::Update() { if (m_ProneState == GOPRONE) { if (!m_ProneTimer.IsPastSimMS(333)) { if (std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { - m_AngularVel += rotDiff * 0.4F; - m_Vel.m_X += (m_HFlipped ? -std::abs(rotDiff) : std::abs(rotDiff)) / std::max(m_Vel.GetMagnitude(), 4.0F); + m_AngularVel += rotDiff * 24.0F * g_TimerMan.GetDeltaTimeSecs(); + m_Vel.m_X += (m_HFlipped ? -std::abs(rotDiff) : std::abs(rotDiff)) / std::max(m_Vel.GetMagnitude(), 4.0F) * 60.0F * g_TimerMan.GetDeltaTimeSecs(); } } else { // Done going down, now stay down without spring. @@ -2574,9 +2575,9 @@ void AHuman::Update() { } else if (m_ProneState == LAYINGPRONE) { // If down, try to keep flat against the ground. if (std::abs(rotDiff) > c_SixteenthPI && std::abs(rotDiff) < c_HalfPI) { - m_AngularVel += rotDiff * 0.65F; + m_AngularVel += rotDiff * 39.0F * g_TimerMan.GetDeltaTimeSecs(); } else if (std::abs(m_AngularVel) > 0.3F) { - m_AngularVel *= 0.85F; + m_AngularVel = ExpDecay(m_AngularVel, 0, 10, g_TimerMan.GetDeltaTimeSecs()); } } } else { @@ -2596,6 +2597,7 @@ void AHuman::Update() { rot = rotTarget; } else { // Lerp towards the angle + // TODO: make framerate independent m_AngularVel = m_AngularVel * (0.98F - 0.06F * (m_Health / m_MaxHealth)) - (rotDiff * 0.5F); } @@ -2612,14 +2614,14 @@ void AHuman::Update() { float rotDiff = rotTarget - rot; if (std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { - m_AngularVel += rotDiff * 0.05F; + m_AngularVel += rotDiff * 3.0F * g_TimerMan.GetDeltaTimeSecs(); } } else if (m_Status == DYING) { float rotTarget = m_Vel.m_X - (rot + m_AngularVel) > 0 ? -c_HalfPI : c_HalfPI; float rotDiff = rotTarget - rot; if (!m_DeathTmr.IsPastSimMS(125) && std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { // TODO: finetune this for situations like low gravity! - float velScalar = 0.5F; //* (g_SceneMan.GetGlobalAcc().GetY() * m_GlobalAccScalar) / c_PPM; + float velScalar = 30.0F * g_TimerMan.GetDeltaTimeSecs(); //* (g_SceneMan.GetGlobalAcc().GetY() * m_GlobalAccScalar) / c_PPM; m_AngularVel += rotDiff * velScalar; m_Vel.m_X += (rotTarget > 0 ? -std::abs(rotDiff) : std::abs(rotDiff)) * velScalar * 0.5F; } else { @@ -2634,7 +2636,7 @@ void AHuman::Update() { if (!m_pHead && m_Status != DYING && m_Status != DEAD) { m_Health -= m_MaxHealth + 1.0F; } else if (!m_pFGArm && !m_pBGArm && !m_pFGLeg && !m_pBGLeg && m_Status != DYING && m_Status != DEAD) { - m_Health -= 0.1F; + m_Health -= 6.0F * g_TimerMan.GetDeltaTimeSecs(); } if (m_Status == DYING) { diff --git a/Source/System/RTETools.h b/Source/System/RTETools.h index 26b14ce615..a7045b41d3 100644 --- a/Source/System/RTETools.h +++ b/Source/System/RTETools.h @@ -301,5 +301,35 @@ namespace RTE { template int Sign(const Type& value) { return (Type(0) < value) - (Type(0) > value); } + + /// Exponential decay function. Allows decaying a value from A to B at the same rate regardless of delta time. Always stable. + /// + /// As an example, assuming variables like this: + /// float current = 1.0f; + /// float target = 0.0f; + /// float decay = 10.0f; + /// + /// Then running this: + /// + /// current = ExpDecay(current, target, decay, 1.0f / 30.0f); + /// + /// Preduces the same result (barring precision errors) as: + /// + /// current = ExpDecay(current, target, decay, 1.0f / 60.0f); + /// current = ExpDecay(current, target, decay, 1.0f / 60.0f); + /// + /// In both cases, "current" will be equal to about 0.716531310573789. + /// + /// Lecture on the topic: https://youtube.com/watch?v=LSNQuFEDOyQ + /// + /// @param current The current value that we're decaying. + /// @param target Target we're decaying to. + /// @param decay Rate of decay. For example, with 0.7 the value will be decayed about halfway there in 1 second. + /// @param deltaTime Amount of time of decay to simulate. + /// @returns The decayed value. + inline float ExpDecay(float current, float target, float decay, float deltaTime) { + return target + (current - target) * std::exp(-decay * deltaTime); + } + #pragma endregion } // namespace RTE