Movement acceleration (#8969)
This commit is contained in:
@@ -36,6 +36,46 @@ namespace Content.Shared.Movement
|
||||
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>
|
||||
@@ -47,17 +87,42 @@ namespace Content.Shared.Movement
|
||||
{
|
||||
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)
|
||||
@@ -108,7 +173,8 @@ namespace Content.Shared.Movement
|
||||
IMoverComponent mover,
|
||||
PhysicsComponent physicsComponent,
|
||||
IMobMoverComponent mobMover,
|
||||
TransformComponent xform)
|
||||
TransformComponent xform,
|
||||
float frameTime)
|
||||
{
|
||||
DebugTools.Assert(!UsedMobMovement.ContainsKey(mover.Owner));
|
||||
|
||||
@@ -121,20 +187,18 @@ namespace Content.Shared.Movement
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,15 +206,34 @@ namespace Content.Shared.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;
|
||||
@@ -172,7 +255,47 @@ namespace Content.Shared.Movement
|
||||
}
|
||||
}
|
||||
|
||||
_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)
|
||||
|
||||
Reference in New Issue
Block a user