Skip to content

Commit

Permalink
Movement acceleration (#8969)
Browse files Browse the repository at this point in the history
  • Loading branch information
metalgearsloth authored Jun 23, 2022
1 parent 25ae901 commit 5169ade
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 39 deletions.
2 changes: 1 addition & 1 deletion Content.Client/Physics/Controllers/MoverController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public override void UpdateBeforeSolve(bool prediction, float frameTime)
// Server-side should just be handled on its own so we'll just do this shizznit
if (TryComp(player, out IMobMoverComponent? mobMover))
{
HandleMobMovement(mover, body, mobMover, xform);
HandleMobMovement(mover, body, mobMover, xform, frameTime);
return;
}

Expand Down
3 changes: 0 additions & 3 deletions Content.Server/AI/Components/AiControllerComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ public float CurrentSprintSpeed
[ViewVariables(VVAccess.ReadWrite)]
public float PushStrength { get; set; } = IMobMoverComponent.PushStrengthDefault;

[ViewVariables(VVAccess.ReadWrite)]
public float WeightlessStrength { get; set; } = IMobMoverComponent.WeightlessStrengthDefault;

/// <inheritdoc />
[ViewVariables(VVAccess.ReadWrite)]
public float GrabRange { get; set; } = IMobMoverComponent.GrabRangeDefault;
Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Physics/Controllers/MoverController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override void UpdateBeforeSolve(bool prediction, float frameTime)
foreach (var (mobMover, mover, physics, xform) in EntityManager.EntityQuery<IMobMoverComponent, IMoverComponent, PhysicsComponent, TransformComponent>())
{
_excludedMobs.Add(mover.Owner);
HandleMobMovement(mover, physics, mobMover, xform);
HandleMobMovement(mover, physics, mobMover, xform, frameTime);
}

HandleShuttleMovement(frameTime);
Expand Down
52 changes: 50 additions & 2 deletions Content.Shared/CCVar/CCVars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,17 +380,65 @@ public static readonly CVarDef<bool>
* Physics
*/

/*
* WARNING: These are liable to get changed to datafields whenever movement refactor occurs and may no longer be valid.
* You were warned!
*/

/// <summary>
/// Minimum speed a mob has to be moving before applying movement friction.
/// </summary>
public static readonly CVarDef<float> MinimumFrictionSpeed =
CVarDef.Create("physics.minimum_friction_speed", 0.005f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The acceleration applied to mobs when moving.
/// </summary>
public static readonly CVarDef<float> MobAcceleration =
CVarDef.Create("physics.mob_acceleration", 14f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The negative velocity applied for friction.
/// </summary>
public static readonly CVarDef<float> MobFriction =
CVarDef.Create("physics.mob_friction", 14f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The acceleration applied to mobs when moving and weightless.
/// </summary>
public static readonly CVarDef<float> MobWeightlessAcceleration =
CVarDef.Create("physics.mob_weightless_acceleration", 1f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The negative velocity applied for friction when weightless and providing inputs.
/// </summary>
public static readonly CVarDef<float> MobWeightlessFriction =
CVarDef.Create("physics.mob_weightless_friction", 1f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The negative velocity applied for friction when weightless and not providing inputs.
/// This is essentially how much their speed decreases per second.
/// </summary>
public static readonly CVarDef<float> MobWeightlessFrictionNoInput =
CVarDef.Create("physics.mob_weightless_friction_no_input", 0.2f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// The movement speed modifier applied to a mob's total input velocity when weightless.
/// </summary>
public static readonly CVarDef<float> MobWeightlessModifier =
CVarDef.Create("physics.mob_weightless_modifier", 0.7f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// When a mob is walking should its X / Y movement be relative to its parent (true) or the map (false).
/// </summary>
public static readonly CVarDef<bool> RelativeMovement =
CVarDef.Create("physics.relative_movement", true, CVar.ARCHIVE | CVar.REPLICATED);

public static readonly CVarDef<float> TileFrictionModifier =
CVarDef.Create("physics.tile_friction", 40.0f);
CVarDef.Create("physics.tile_friction", 40.0f, CVar.ARCHIVE | CVar.REPLICATED);

public static readonly CVarDef<float> StopSpeed =
CVarDef.Create("physics.stop_speed", 0.1f);
CVarDef.Create("physics.stop_speed", 0.1f, CVar.ARCHIVE | CVar.REPLICATED);

/// <summary>
/// Whether mobs can push objects like lockers.
Expand Down
2 changes: 0 additions & 2 deletions Content.Shared/Movement/Components/IMobMoverComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ public interface IMobMoverComponent : IComponent
float GrabRange { get; set; }

float PushStrength { get; set; }

float WeightlessStrength { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ public sealed class SharedPlayerMobMoverComponent : Component, IMobMoverComponen
[DataField("pushStrength")]
private float _pushStrength = IMobMoverComponent.PushStrengthDefault;

[DataField("weightlessStrength")]
private float _weightlessStrength = IMobMoverComponent.WeightlessStrengthDefault;

[ViewVariables(VVAccess.ReadWrite)]
public EntityCoordinates LastPosition { get; set; }

Expand Down Expand Up @@ -62,18 +59,6 @@ public float PushStrength
}
}

[ViewVariables(VVAccess.ReadWrite)]
public float WeightlessStrength
{
get => _weightlessStrength;
set
{
if (MathHelper.CloseToPercent(_weightlessStrength, value)) return;
_weightlessStrength = value;
Dirty();
}
}

protected override void Initialize()
{
base.Initialize();
Expand All @@ -85,7 +70,7 @@ protected override void Initialize()

public override ComponentState GetComponentState()
{
return new PlayerMobMoverComponentState(_grabRange, _pushStrength, _weightlessStrength);
return new PlayerMobMoverComponentState(_grabRange, _pushStrength);
}

public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
Expand All @@ -101,13 +86,11 @@ private sealed class PlayerMobMoverComponentState : ComponentState
{
public float GrabRange;
public float PushStrength;
public float WeightlessStrength;

public PlayerMobMoverComponentState(float grabRange, float pushStrength, float weightlessStrength)
public PlayerMobMoverComponentState(float grabRange, float pushStrength)
{
GrabRange = grabRange;
PushStrength = pushStrength;
WeightlessStrength = weightlessStrength;
}
}
}
Expand Down
143 changes: 133 additions & 10 deletions Content.Shared/Movement/SharedMoverController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,46 @@ public abstract class SharedMoverController : VirtualController
private const float FootstepVariation = 0f;
private const float FootstepVolume = 1f;

/// <summary>
/// <see cref="CCVars.MinimumFrictionSpeed"/>
/// </summary>
private float _minimumFrictionSpeed;

/// <summary>
/// <see cref="CCVars.StopSpeed"/>
/// </summary>
private float _stopSpeed;

/// <summary>
/// <see cref="CCVars.MobAcceleration"/>
/// </summary>
private float _mobAcceleration;

/// <summary>
/// <see cref="CCVars.MobFriction"/>
/// </summary>
private float _frictionVelocity;

/// <summary>
/// <see cref="CCVars.MobWeightlessAcceleration"/>
/// </summary>
private float _mobWeightlessAcceleration;

/// <summary>
/// <see cref="CCVars.MobWeightlessFriction"/>
/// </summary>
private float _weightlessFrictionVelocity;

/// <summary>
/// <see cref="CCVars.MobWeightlessFrictionNoInput"/>
/// </summary>
private float _weightlessFrictionVelocityNoInput;

/// <summary>
/// <see cref="CCVars.MobWeightlessModifier"/>
/// </summary>
private float _mobWeightlessModifier;

private bool _relativeMovement;

/// <summary>
Expand All @@ -47,17 +87,42 @@ public override void Initialize()
{
base.Initialize();
var configManager = IoCManager.Resolve<IConfigurationManager>();
// Hello
configManager.OnValueChanged(CCVars.RelativeMovement, SetRelativeMovement, true);
configManager.OnValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed, true);
configManager.OnValueChanged(CCVars.MobFriction, SetFrictionVelocity, true);
configManager.OnValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity, true);
configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true);
configManager.OnValueChanged(CCVars.MobAcceleration, SetMobAcceleration, true);
configManager.OnValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration, true);
configManager.OnValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput, true);
configManager.OnValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier, true);
UpdatesBefore.Add(typeof(SharedTileFrictionController));
}

private void SetRelativeMovement(bool value) => _relativeMovement = value;
private void SetMinimumFrictionSpeed(float value) => _minimumFrictionSpeed = value;
private void SetStopSpeed(float value) => _stopSpeed = value;
private void SetFrictionVelocity(float value) => _frictionVelocity = value;
private void SetWeightlessFrictionVelocity(float value) => _weightlessFrictionVelocity = value;
private void SetMobAcceleration(float value) => _mobAcceleration = value;
private void SetMobWeightlessAcceleration(float value) => _mobWeightlessAcceleration = value;
private void SetWeightlessFrictionNoInput(float value) => _weightlessFrictionVelocityNoInput = value;
private void SetMobWeightlessModifier(float value) => _mobWeightlessModifier = value;

public override void Shutdown()
{
base.Shutdown();
var configManager = IoCManager.Resolve<IConfigurationManager>();
configManager.UnsubValueChanged(CCVars.RelativeMovement, SetRelativeMovement);
configManager.UnsubValueChanged(CCVars.MinimumFrictionSpeed, SetMinimumFrictionSpeed);
configManager.UnsubValueChanged(CCVars.StopSpeed, SetStopSpeed);
configManager.UnsubValueChanged(CCVars.MobFriction, SetFrictionVelocity);
configManager.UnsubValueChanged(CCVars.MobWeightlessFriction, SetWeightlessFrictionVelocity);
configManager.UnsubValueChanged(CCVars.MobAcceleration, SetMobAcceleration);
configManager.UnsubValueChanged(CCVars.MobWeightlessAcceleration, SetMobWeightlessAcceleration);
configManager.UnsubValueChanged(CCVars.MobWeightlessFrictionNoInput, SetWeightlessFrictionNoInput);
configManager.UnsubValueChanged(CCVars.MobWeightlessModifier, SetMobWeightlessModifier);
}

public override void UpdateAfterSolve(bool prediction, float frameTime)
Expand Down Expand Up @@ -108,7 +173,8 @@ protected void HandleMobMovement(
IMoverComponent mover,
PhysicsComponent physicsComponent,
IMobMoverComponent mobMover,
TransformComponent xform)
TransformComponent xform,
float frameTime)
{
DebugTools.Assert(!UsedMobMovement.ContainsKey(mover.Owner));

Expand All @@ -121,36 +187,53 @@ protected void HandleMobMovement(
UsedMobMovement[mover.Owner] = true;
var weightless = mover.Owner.IsWeightless(physicsComponent, mapManager: _mapManager, entityManager: EntityManager);
var (walkDir, sprintDir) = mover.VelocityDir;
bool touching = true;

// Handle wall-pushes.
if (weightless)
{
// No gravity: is our entity touching anything?
var touching = IsAroundCollider(_physics, xform, mobMover, physicsComponent);
touching = xform.GridUid != null || IsAroundCollider(_physics, xform, mobMover, physicsComponent);

if (!touching)
{
if (xform.GridUid != EntityUid.Invalid)
if (xform.GridUid != null)
mover.LastGridAngle = GetParentGridAngle(xform, mover);

xform.WorldRotation = physicsComponent.LinearVelocity.GetDir().ToAngle();
return;
}
}

// Regular movement.
// Target velocity.
// This is relative to the map / grid we're on.
var total = walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed;

var parentRotation = GetParentGridAngle(xform, mover);

var worldTotal = _relativeMovement ? parentRotation.RotateVec(total) : total;

DebugTools.Assert(MathHelper.CloseToPercent(total.Length, worldTotal.Length));

var velocity = physicsComponent.LinearVelocity;
float friction;
float weightlessModifier;
float accel;

if (weightless)
worldTotal *= mobMover.WeightlessStrength;
{
if (worldTotal != Vector2.Zero && touching)
friction = _weightlessFrictionVelocity;
else
friction = _weightlessFrictionVelocityNoInput;

weightlessModifier = _mobWeightlessModifier;
accel = _mobWeightlessAcceleration;
}
else
{
friction = _frictionVelocity;
weightlessModifier = 1f;
accel = _mobAcceleration;
}

Friction(frameTime, friction, ref velocity);

if (xform.GridUid != EntityUid.Invalid)
mover.LastGridAngle = parentRotation;
Expand All @@ -172,7 +255,47 @@ protected void HandleMobMovement(
}
}

_physics.SetLinearVelocity(physicsComponent, worldTotal);
worldTotal *= weightlessModifier;

if (touching)
Accelerate(ref velocity, in worldTotal, accel, frameTime);

_physics.SetLinearVelocity(physicsComponent, velocity);
}

private void Friction(float frameTime, float friction, ref Vector2 velocity)
{
var speed = velocity.Length;

if (speed < _minimumFrictionSpeed) return;

var drop = 0f;

var control = MathF.Max(_stopSpeed, speed);
drop += control * friction * frameTime;

var newSpeed = MathF.Max(0f, speed - drop);

if (newSpeed.Equals(speed)) return;

newSpeed /= speed;
velocity *= newSpeed;
}

private void Accelerate(ref Vector2 currentVelocity, in Vector2 velocity, float accel, float frameTime)
{
var wishDir = velocity != Vector2.Zero ? velocity.Normalized : Vector2.Zero;
var wishSpeed = velocity.Length;

var currentSpeed = Vector2.Dot(currentVelocity, wishDir);
var addSpeed = wishSpeed - currentSpeed;

if (addSpeed <= 0f) return;

var accelSpeed = accel * frameTime * wishSpeed;
accelSpeed = MathF.Min(accelSpeed, addSpeed);

currentVelocity += wishDir * accelSpeed;
}

public bool UseMobMovement(EntityUid uid)
Expand Down
6 changes: 5 additions & 1 deletion Content.Shared/Throwing/ThrowingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Content.Shared.Interaction;
using Content.Shared.Movement.Components;
using Content.Shared.Tag;
using Robust.Shared.Physics;
using Robust.Shared.Timing;
Expand Down Expand Up @@ -93,7 +94,10 @@ public void TryThrow(
}

// Give thrower an impulse in the other direction
if (user != null && pushbackRatio > 0.0f && physicsQuery.Value.TryGetComponent(user.Value, out var userPhysics))
if (user != null &&
pushbackRatio > 0.0f &&
physicsQuery.Value.TryGetComponent(user.Value, out var userPhysics) &&
user.Value.IsWeightless(userPhysics, entityManager: EntityManager))
{
var msg = new ThrowPushbackAttemptEvent();
RaiseLocalEvent(physics.Owner, msg, false);
Expand Down

0 comments on commit 5169ade

Please sign in to comment.