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

Walkpath Auto Crouch #576

Merged
merged 22 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f088716
First implementation of auto walkpath crouching
Causeless Dec 26, 2023
1982920
Improved walkpath auto crouch
Causeless Dec 26, 2023
6df4484
Lua, INI bindings and changelog
Causeless Dec 27, 2023
04829b5
Little cleanup, tweaking and adjustment
Causeless Dec 27, 2023
7bfdfb4
Stop bouncing when prone
Causeless Dec 27, 2023
cc0e182
Added crouch rotation
Causeless Dec 27, 2023
7014cad
Reset walk crouching when jumping
Causeless Dec 27, 2023
ae3a2a3
Whoops, missing ;
Causeless Dec 27, 2023
c7037ed
Whoops, unfucked crouching
Causeless Dec 27, 2023
a7cd3f0
Avoid unnecessary ducking
Causeless Dec 27, 2023
fe59de9
Reduced stumbling dramatically
Causeless Dec 27, 2023
c003b2c
Merge branch 'development' into walkpath-auto-crouch
Causeless Dec 27, 2023
c031177
Made crouch detection a bit more accurate and nicer
Causeless Dec 27, 2023
cbb2726
Merge branch 'development' into walkpath-auto-crouch
Causeless Dec 27, 2023
6fe7421
Update crouching in our own function, and reduce speed when crouching
Causeless Dec 27, 2023
060fe74
Slightly cleaner code
Causeless Dec 28, 2023
bf25eca
Stopped crouching when walking up hillside
Causeless Dec 28, 2023
ce42a5d
Actually fixed it this time...
Causeless Dec 28, 2023
37f9f0a
Duh.
Causeless Dec 28, 2023
b3d1f2b
Lua bindings to get current crouch amount or set an override
Causeless Dec 28, 2023
7478bb7
Merge branch 'development' into walkpath-auto-crouch
Causeless Dec 28, 2023
8182cf2
Made Lua set crouch amount lerp instead of snap
Causeless Dec 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- New `Actor` INI and Lua (R/W) property `PainThreshold`, which determines how much damage this actor must take in a frame to play their `PainSound`. This can be set to 0 to never manually play the sound. Defaults to 15.

- New `AHuman` INI and Lua (R/W) property `MaxWalkPathCrouchShift`, which determines how much the actor will automatically duck down to avoid low ceilings above them. This can be set to 0 to never duck. Defaults to 6.

- New `AHuman` INI and Lua (R/W) property `MaxCrouchRotation`, which determines how much the actor will rotate when ducking to avoid low ceilings above them. This can be set to 0 to never duck. Defaults to a quarter of Pi * 1.25 (roughly 56 degrees).

- New `AHuman` Lua (R/W) property `CrouchAmountOverride`, which enforces that the actor crouch a certain amount, where 0 means fully standing and 1 is fully crouching. This override can be disabled by setting it to -1.0.

- New `AHuman` Lua (R) property `CrouchAmount`, which returns how much the actor is crouching, where 0 means fully standing and 1 is fully crouching.

- New `MOPixel` INI and Lua (R/W) property `Staininess`, which defines how likely a pixel is to stain a surface when it collides with it. Staining a surface changes that surface's `Color` to that of this `MOPixel`, without changing the underlying material. Value can be between 0 and 1. Defaults to 0 (never stain).

- New `Activity` INI and Lua (R/W) property `AllowsUserSaving`, which can be used to enable/disable manual user saving/loading. This defaults to true for all `GAScripted` with an `OnSave()` function, but false otherwise. Lua `ActivityMan::SaveGame()` function now forces a save even if `AllowsUserSaving` is disabled. This allows mods and scripted gamemodes to handle saving in their own way (for example, only allowing saving at set points).
Expand Down
102 changes: 91 additions & 11 deletions Entities/AHuman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "GUI.h"
#include "AllegroBitmap.h"

#include "PrimitiveMan.h"

#include "tracy/Tracy.hpp"

namespace RTE {
Expand Down Expand Up @@ -63,6 +65,9 @@ void AHuman::Clear()
m_MoveState = STAND;
m_ProneState = NOTPRONE;
m_ProneTimer.Reset();
m_MaxWalkPathCrouchShift = 6.0F;
m_MaxCrouchRotation = c_QuarterPI * 1.25F;
m_CrouchAmountOverride = -1.0F;
for (int i = 0; i < MOVEMENTSTATECOUNT; ++i) {
m_Paths[FGROUND][i].Reset();
m_Paths[BGROUND][i].Reset();
Expand All @@ -85,6 +90,7 @@ void AHuman::Clear()
m_BGArmFlailScalar = 0.7F;
m_EquipHUDTimer.Reset();
m_WalkAngle.fill(Matrix());
m_WalkPathOffset.Reset();
m_ArmSwingRate = 1.0F;
m_DeviceArmSwayRate = 0.5F;

Expand Down Expand Up @@ -207,6 +213,9 @@ int AHuman::Create(const AHuman &reference) {
m_BackupBGFootGroup->SetOwner(this);
m_BackupBGFootGroup->SetLimbPos(atomGroupToUseAsFootGroupBG->GetLimbPos());

m_MaxWalkPathCrouchShift = reference.m_MaxWalkPathCrouchShift;
m_MaxCrouchRotation = reference.m_MaxCrouchRotation;

if (reference.m_StrideSound) { m_StrideSound = dynamic_cast<SoundContainer*>(reference.m_StrideSound->Clone()); }

m_ArmsState = reference.m_ArmsState;
Expand Down Expand Up @@ -283,6 +292,8 @@ int AHuman::ReadProperty(const std::string_view &propName, Reader &reader) {
m_BackupBGFootGroup = new AtomGroup(*m_pBGFootGroup);
m_BackupBGFootGroup->RemoveAllAtoms();
});
MatchProperty("MaxWalkPathCrouchShift", { reader >> m_MaxWalkPathCrouchShift; });
MatchProperty("MaxCrouchRotation", { reader >> m_MaxCrouchRotation; });
MatchProperty("StrideSound", {
m_StrideSound = new SoundContainer;
reader >> m_StrideSound;
Expand Down Expand Up @@ -346,6 +357,10 @@ int AHuman::Save(Writer &writer) const
writer << m_pFGFootGroup;
writer.NewProperty("BGFootGroup");
writer << m_pBGFootGroup;
writer.NewProperty("MaxWalkPathCrouchShift");
writer << m_MaxWalkPathCrouchShift;
writer.NewProperty("MaxCrouchRotation");
writer << m_MaxCrouchRotation;
writer.NewProperty("StrideSound");
writer << m_StrideSound;

Expand Down Expand Up @@ -1710,6 +1725,54 @@ void AHuman::UpdateWalkAngle(AHuman::Layer whichLayer) {

//////////////////////////////////////////////////////////////////////////////////////////

void AHuman::UpdateCrouching() {
if (!m_Controller.IsState(BODY_JUMP) && m_pHead) {
float desiredWalkPathYOffset = 0.0F;
if (m_CrouchAmountOverride == -1.0F) {
// Cast a ray above our head to either side to determine whether we need to crouch
float desiredCrouchHeadRoom = std::floor(m_pHead->GetRadius() + 2.0f);
float toPredicted = std::floor(m_Vel.m_X * m_pHead->GetRadius()); // Check where we'll be a second from now
Vector hitPosStart = (m_pHead->GetPos() + Vector(0.0F, m_SpriteRadius * 0.5F)).Floor();
Vector hitPosPredictedStart = (m_pHead->GetPos() + Vector(toPredicted, m_SpriteRadius * 0.5F)).Floor();
Vector hitPos, hitPosPredicted;
g_SceneMan.CastStrengthRay(hitPosStart, Vector(0.0F, -desiredCrouchHeadRoom + m_SpriteRadius * -0.5F), 1.0F, hitPos, 0, g_MaterialGrass);
g_SceneMan.CastStrengthRay(hitPosPredictedStart, Vector(0.0F, -desiredCrouchHeadRoom + m_SpriteRadius * -0.5F), 1.0F, hitPosPredicted, 0, g_MaterialGrass);

// Don't do it if we're already hitting, we're probably in a weird spot
if (hitPosStart.m_Y - hitPos.m_Y <= 2.0F) {
hitPos.m_Y = 0.0F;
}

if (hitPosPredictedStart.m_Y - hitPosPredicted.m_Y <= 2.0F) {
hitPosPredicted.m_Y = 0.0F;
}

float headroom = m_pHead->GetPos().m_Y - std::max(hitPos.m_Y, hitPosPredicted.m_Y);
desiredWalkPathYOffset = desiredCrouchHeadRoom - headroom;
} else {
desiredWalkPathYOffset = m_CrouchAmountOverride * m_MaxWalkPathCrouchShift;
}

float finalWalkPathYOffset = std::clamp(LERP(0.0F, 1.0F, -m_WalkPathOffset.m_Y, desiredWalkPathYOffset, 0.3F), 0.0F, m_MaxWalkPathCrouchShift);
m_WalkPathOffset.m_Y = -finalWalkPathYOffset;

// If crouching, move at reduced speed
const float crouchSpeedMultiplier = 0.5F;
float travelSpeedMultiplier = LERP(0.0F, m_MaxWalkPathCrouchShift, 1.0F, crouchSpeedMultiplier, -m_WalkPathOffset.m_Y);
m_Paths[FGROUND][WALK].SetTravelSpeedMultiplier(travelSpeedMultiplier);
m_Paths[BGROUND][WALK].SetTravelSpeedMultiplier(travelSpeedMultiplier);

// Adjust our X offset to try to keep our legs under our centre-of-mass
const float ratioBetweenBodyAndHeadToAimFor = 0.15F;
float predictedPosition = ((m_pHead->GetPos().m_X - m_Pos.m_X) * ratioBetweenBodyAndHeadToAimFor) + m_Vel.m_X;
m_WalkPathOffset.m_X = predictedPosition;
} else {
m_WalkPathOffset.Reset();
}
}

//////////////////////////////////////////////////////////////////////////////////////////

void AHuman::PreControllerUpdate()
{
ZoneScoped;
Expand Down Expand Up @@ -2182,6 +2245,8 @@ void AHuman::PreControllerUpdate()

m_StrideFrame = false;

UpdateCrouching();

if (m_Status == STABLE && !m_LimbPushForcesAndCollisionsDisabled && m_MoveState != NOMOVE)
{
// This exists to support disabling foot collisions if the limbpath has that flag set.
Expand All @@ -2194,6 +2259,9 @@ void AHuman::PreControllerUpdate()
std::swap(m_pBGFootGroup, m_BackupBGFootGroup);
}

if (m_pFGLeg) { UpdateWalkAngle(FGROUND); }
if (m_pBGLeg) { UpdateWalkAngle(BGROUND); }

// WALKING, OR WE ARE JETPACKING AND STUCK
if (m_MoveState == WALK || (m_MoveState == JUMP && isStill)) {
m_Paths[FGROUND][STAND].Terminate();
Expand All @@ -2212,17 +2280,17 @@ void AHuman::PreControllerUpdate()
if (m_pFGLeg && (!m_pBGLeg || !(m_Paths[FGROUND][WALK].PathEnded() && BGLegProg < 0.5F) || m_StrideStart)) {
// Reset the stride timer if the path is about to restart.
if (m_Paths[FGROUND][WALK].PathEnded() || m_Paths[FGROUND][WALK].PathIsAtStart()) { m_StrideTimer.Reset(); }
m_ArmClimbing[BGROUND] = !m_pFGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pFGLeg->GetParentOffset()), m_Vel, m_WalkAngle[FGROUND], m_Paths[FGROUND][WALK], deltaTime, &restarted, false, Vector(0.0F, m_Paths[FGROUND][WALK].GetLowestY()));
if (restarted) { UpdateWalkAngle(FGROUND); }
Vector jointPos = m_Pos + RotateOffset(m_pFGLeg->GetParentOffset());
m_ArmClimbing[BGROUND] = !m_pFGFootGroup->PushAsLimb(jointPos, m_Vel, m_WalkAngle[FGROUND], m_Paths[FGROUND][WALK], deltaTime, &restarted, false, Vector(0.0F, m_Paths[FGROUND][WALK].GetLowestY()), m_WalkPathOffset);
} else {
m_ArmClimbing[BGROUND] = false;
}
if (m_pBGLeg && (!m_pFGLeg || !(m_Paths[BGROUND][WALK].PathEnded() && FGLegProg < 0.5F))) {
m_StrideStart = false;
// Reset the stride timer if the path is about to restart.
if (m_Paths[BGROUND][WALK].PathEnded() || m_Paths[BGROUND][WALK].PathIsAtStart()) { m_StrideTimer.Reset(); }
m_ArmClimbing[FGROUND] = !m_pBGFootGroup->PushAsLimb(m_Pos + RotateOffset(m_pBGLeg->GetParentOffset()), m_Vel, m_WalkAngle[BGROUND], m_Paths[BGROUND][WALK], deltaTime, &restarted, false, Vector(0.0F, m_Paths[BGROUND][WALK].GetLowestY()));
if (restarted) { UpdateWalkAngle(BGROUND); }
Vector jointPos = m_Pos + RotateOffset(m_pBGLeg->GetParentOffset());
m_ArmClimbing[FGROUND] = !m_pBGFootGroup->PushAsLimb(jointPos, m_Vel, m_WalkAngle[BGROUND], m_Paths[BGROUND][WALK], deltaTime, &restarted, false, Vector(0.0F, m_Paths[BGROUND][WALK].GetLowestY()), m_WalkPathOffset);
} else {
if (m_pBGLeg) { m_pBGFootGroup->FlailAsLimb(m_Pos, RotateOffset(m_pBGLeg->GetParentOffset()), m_pBGLeg->GetMaxLength(), m_PrevVel, m_AngularVel, m_pBGLeg->GetMass(), deltaTime); }
m_ArmClimbing[FGROUND] = false;
Expand Down Expand Up @@ -2360,9 +2428,15 @@ void AHuman::PreControllerUpdate()
m_Paths[FGROUND][ARMCRAWL].Terminate();
m_Paths[BGROUND][ARMCRAWL].Terminate();

if (m_pFGLeg) { m_pFGFootGroup->PushAsLimb(m_Pos.GetFloored() + m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped), m_Vel, m_WalkAngle[FGROUND], m_Paths[FGROUND][STAND], deltaTime, nullptr, !m_pBGLeg, Vector(0.0F, m_Paths[FGROUND][STAND].GetLowestY())); }
if (m_pFGLeg) {
Vector jointPos = m_Pos.GetFloored() + m_pFGLeg->GetParentOffset().GetXFlipped(m_HFlipped);
m_pFGFootGroup->PushAsLimb(jointPos, m_Vel, m_WalkAngle[FGROUND], m_Paths[FGROUND][STAND], deltaTime, nullptr, !m_pBGLeg, Vector(0.0F, m_Paths[FGROUND][STAND].GetLowestY()), m_WalkPathOffset);
}

if (m_pBGLeg) { m_pBGFootGroup->PushAsLimb(m_Pos.GetFloored() + m_pBGLeg->GetParentOffset().GetXFlipped(m_HFlipped), m_Vel, m_WalkAngle[BGROUND], m_Paths[BGROUND][STAND], deltaTime, nullptr, !m_pFGLeg, Vector(0.0F, m_Paths[FGROUND][STAND].GetLowestY())); }
if (m_pBGLeg) {
Vector jointPos = m_Pos.GetFloored() + m_pBGLeg->GetParentOffset().GetXFlipped(m_HFlipped);
m_pBGFootGroup->PushAsLimb(jointPos, m_Vel, m_WalkAngle[BGROUND], m_Paths[BGROUND][STAND], deltaTime, nullptr, !m_pFGLeg, Vector(0.0F, m_Paths[FGROUND][STAND].GetLowestY()), m_WalkPathOffset);
}
}
}
}
Expand Down Expand Up @@ -2613,7 +2687,13 @@ void AHuman::Update()
}
} else {
// Upright body posture
float rotDiff = rot - (GetRotAngleTarget(m_MoveState) * (m_AimAngle > 0 ? 1.0F - (m_AimAngle / c_HalfPI) : 1.0F) * GetFlipFactor());
float rotTarget = (GetRotAngleTarget(m_MoveState) * (m_AimAngle > 0 ? 1.0F - (m_AimAngle / c_HalfPI) : 1.0F) * GetFlipFactor());

// Lean forwards when crouching
float crouchAngleAdjust = m_HFlipped ? m_MaxCrouchRotation : -m_MaxCrouchRotation;
rotTarget += LERP(0.0F, m_MaxWalkPathCrouchShift, 0.0F, crouchAngleAdjust, m_WalkPathOffset.m_Y * -1.0F);

float rotDiff = rot - rotTarget;
m_AngularVel = m_AngularVel * (0.98F - 0.06F * (m_Health / m_MaxHealth)) - (rotDiff * 0.5F);
}
}
Expand Down Expand Up @@ -2722,10 +2802,10 @@ void AHuman::Draw(BITMAP *pTargetBitmap, const Vector &targetPos, DrawMode mode,
}

if (mode == g_DrawColor && !onlyPhysical && g_SettingsMan.DrawLimbPathVisualizations()) {
m_Paths[m_HFlipped][WALK].Draw(pTargetBitmap, targetPos, 122);
m_Paths[m_HFlipped][CRAWL].Draw(pTargetBitmap, targetPos, 122);
m_Paths[m_HFlipped][ARMCRAWL].Draw(pTargetBitmap, targetPos, 13);
m_Paths[m_HFlipped][CLIMB].Draw(pTargetBitmap, targetPos, 165);
m_Paths[m_HFlipped][WALK].Draw(pTargetBitmap, targetPos, 122);
m_Paths[m_HFlipped][CRAWL].Draw(pTargetBitmap, targetPos, 122);
m_Paths[m_HFlipped][ARMCRAWL].Draw(pTargetBitmap, targetPos, 13);
m_Paths[m_HFlipped][CLIMB].Draw(pTargetBitmap, targetPos, 165);
}
}

Expand Down
54 changes: 54 additions & 0 deletions Entities/AHuman.h
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,11 @@ DefaultPieMenuNameGetter("Default Human Pie Menu");
/// <param name="whichLayer">The Layer in question.</param>
void UpdateWalkAngle(AHuman::Layer whichLayer);

/// <summary>
/// Detects overhead ceilings and crouches for them.
/// </summary>
void UpdateCrouching();

/// <summary>
/// Gets the walk path rotation for the specified Layer.
/// </summary>
Expand Down Expand Up @@ -863,6 +868,48 @@ DefaultPieMenuNameGetter("Default Human Pie Menu");
/// <param name="newValue">The new device arm sway rate for this AHuman.</param>
void SetDeviceArmSwayRate(float newValue) { m_DeviceArmSwayRate = newValue; }

/// <summary>
/// Gets this AHuman's max walkpath adjustment upwards to crouch below low ceilings.
/// </summary>
/// <returns>This AHuman's max walkpath adjustment.</returns>
float GetMaxWalkPathCrouchShift() const { return m_MaxWalkPathCrouchShift; }

/// <summary>
/// Sets this AHuman's max walkpath adjustment upwards to crouch below low ceilings.
/// </summary>
/// <param name="newValue">The new value for this AHuman's max walkpath adjustment.</param>
void SetMaxWalkPathCrouchShift(float newValue) { m_MaxWalkPathCrouchShift = newValue; }

/// <summary>
/// Gets this AHuman's max crouch rotation to duck below low ceilings.
/// </summary>
/// <returns>This AHuman's max crouch rotation adjustment.</returns>
float GetMaxCrouchRotation() const { return m_MaxCrouchRotation; }

/// <summary>
/// Sets this AHuman's max crouch rotation to duck below low ceilings.
/// </summary>
/// <param name="newValue">The new value for this AHuman's max crouch rotation adjustment.</param>
void SetMaxCrouchRotation(float newValue) { m_MaxCrouchRotation = newValue; }

/// <summary>
/// Gets this AHuman's current crouch amount. 0.0 == fully standing, 1.0 == fully crouched.
/// </summary>
/// <returns>This AHuman's current crouch amount.</returns>
float GetCrouchAmount() const { return (m_WalkPathOffset.m_Y * -1.0F) / m_MaxWalkPathCrouchShift; }

/// <summary>
/// Gets this AHuman's current crouch amount override. 0.0 == fully standing, 1.0 == fully crouched, -1 == no override.
/// </summary>
/// <returns>This AHuman's current crouch amount override.</returns>
float GetCrouchAmountOverride() const { return m_CrouchAmountOverride; }

/// <summary>
/// Sets this AHuman's current crouch amount override.
/// </summary>
/// <param name="newValue">The new value for this AHuman's current crouch amount override.</param>
void SetCrouchAmountOverride(float newValue) { m_CrouchAmountOverride = newValue; }

/// <summary>
/// Gets this AHuman's stride sound. Ownership is NOT transferred!
/// </summary>
Expand Down Expand Up @@ -935,6 +982,12 @@ DefaultPieMenuNameGetter("Default Human Pie Menu");
ProneState m_ProneState;
// Timer for the going prone procedural animation
Timer m_ProneTimer;
// The maximum amount our walkpath can be shifted upwards to crouch and avoid ceilings above us
float m_MaxWalkPathCrouchShift;
// The maximum amount we will duck our head down to avoid obstacles above us.
float m_MaxCrouchRotation;
// The script-set forced crouching amount. 0.0 == fully standing, 1.0 == fully crouched, -1 == no override.
float m_CrouchAmountOverride;
// Limb paths for different movement states.
// [0] is for the foreground limbs, and [1] is for BG.
LimbPath m_Paths[2][MOVEMENTSTATECOUNT];
Expand All @@ -958,6 +1011,7 @@ DefaultPieMenuNameGetter("Default Human Pie Menu");
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.
Timer m_EquipHUDTimer; //!< Timer for showing the name of any newly equipped Device.
std::array<Matrix, 2> m_WalkAngle; //!< An array of rot angle targets for different movement states.
Vector m_WalkPathOffset;
float m_ArmSwingRate; //!< Controls the rate at which this AHuman's Arms follow the movement of its Legs while they're not holding device(s).
float m_DeviceArmSwayRate; //!< Controls the rate at which this AHuman's Arms follow the movement of its Legs while they're holding device(s). One-handed devices sway half as much as two-handed ones. Defaults to three quarters of Arm swing rate.

Expand Down
11 changes: 8 additions & 3 deletions Entities/AtomGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ namespace RTE {

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool AtomGroup::PushAsLimb(const Vector &jointPos, const Vector &velocity, const Matrix &rotation, LimbPath &limbPath, const float travelTime, bool *restarted, bool affectRotation, Vector rotationOffset) {
bool AtomGroup::PushAsLimb(const Vector &jointPos, const Vector &velocity, const Matrix &rotation, LimbPath &limbPath, const float travelTime, bool *restarted, bool affectRotation, Vector rotationOffset, Vector positionOffset) {
RTEAssert(m_OwnerMOSR, "Tried to push-as-limb an AtomGroup that has no parent!");

bool didWrap = false;
Expand All @@ -1234,6 +1234,7 @@ namespace RTE {
limbPath.SetJointVel(velocity);
limbPath.SetRotation(rotation);
limbPath.SetRotationOffset(rotationOffset);
limbPath.SetPositionOffset(positionOffset);
limbPath.SetFrameTime(travelTime);

Vector limbDist = g_SceneMan.ShortestDistance(adjustedJointPos, m_LimbPos, g_SceneMan.SceneWrapsX());
Expand Down Expand Up @@ -1266,9 +1267,13 @@ namespace RTE {
owner->GetController()->IsState(MOVE_RIGHT) && pushImpulse.m_X < 0.0F;
if (againstTravelDirection) {
// Filter some of our impulse out. We're pushing against an obstacle, but we don't want to kick backwards!
// Translate it into to upwards motion to step over what we're walking into instead ;)
const float againstIntendedDirectionMultiplier = 0.5F;
pushImpulse.m_Y -= std::abs(pushImpulse.m_X * (1.0F - againstIntendedDirectionMultiplier));

if (!owner->GetController()->IsState(BODY_CROUCH) && !owner->GetController()->IsState(MOVE_DOWN)) {
// Translate it into to upwards motion to step over what we're walking into instead ;)
pushImpulse.m_Y -= std::abs(pushImpulse.m_X * (1.0F - againstIntendedDirectionMultiplier));
}

pushImpulse.m_X *= againstIntendedDirectionMultiplier;
}
}
Expand Down
3 changes: 2 additions & 1 deletion Entities/AtomGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,9 @@ namespace RTE {
/// <param name="restarted">Pointer to a bool which gets set to true if the LimbPath got restarted during this push. It does NOT get initialized to false!</param>
/// <param name="affectRotation">Whether the forces created by this should have rotational leverage on the owner or only have translational effect.</param>
/// <param name="rotationOffset">The position, relative to the owning actor's position, that we should rotate around.</param>
/// <param name="rotationOffset">The positional offset to apply to our limb path.</param>
/// <returns>Whether the LimbPath passed in could start free of terrain or not.</returns>
bool PushAsLimb(const Vector &jointPos, const Vector &velocity, const Matrix &rotation, LimbPath &limbPath, const float travelTime, bool *restarted = nullptr, bool affectRotation = true, Vector rotationOffset = Vector());
bool PushAsLimb(const Vector &jointPos, const Vector &velocity, const Matrix &rotation, LimbPath &limbPath, const float travelTime, bool *restarted = nullptr, bool affectRotation = true, Vector rotationOffset = Vector(), Vector positionOffset = Vector());

/// <summary>
/// Makes this AtomGroup travel as a lifeless limb, constrained to a radius around the joint pin in the center.
Expand Down
Loading