The real movement refactor (#9645)

* The real movement refactor

* ref events

* Jetpack cleanup

* a

* Vehicles partially working

* Balance tweaks

* Restore some shitcode

* AAAAAAAA

* Even more prediction

* ECS compstate trying to fix this

* yml

* vehicles kill me

* Don't lock keys

* a

* Fix problem

* Fix sounds

* shuttle inputs

* Shuttle controls

* space brakes

* Keybinds

* Fix merge

* Handle shutdown

* Fix keys

* Bump friction

* fix buckle offset

* Fix relay and friction

* Fix jetpack turning

* contexts amirite
This commit is contained in:
metalgearsloth
2022-07-16 13:51:52 +10:00
committed by GitHub
parent e0b7b48cae
commit b9e876ca92
109 changed files with 1752 additions and 1584 deletions

View File

@@ -5,16 +5,19 @@ using Content.Shared.Friction;
using Content.Shared.Inventory;
using Content.Shared.Maps;
using Content.Shared.MobState.Components;
using Content.Shared.MobState.EntitySystems;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
using Content.Shared.Pulling.Components;
using Content.Shared.Tag;
using Robust.Shared.Audio;
using Robust.Shared.Configuration;
using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Controllers;
using Robust.Shared.Player;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Shared.Movement.Systems
@@ -26,9 +29,12 @@ namespace Content.Shared.Movement.Systems
public abstract partial class SharedMoverController : VirtualController
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] protected readonly IGameTiming Timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedMobStateSystem _mobState = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly TagSystem _tags = default!;
@@ -39,46 +45,11 @@ namespace Content.Shared.Movement.Systems
private const float FootstepVolume = 3f;
private const float FootstepWalkingAddedVolumeMultiplier = 0f;
/// <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>
@@ -90,29 +61,16 @@ namespace Content.Shared.Movement.Systems
{
base.Initialize();
InitializeInput();
InitializeMob();
InitializePushing();
// Hello
InitializeRelay();
_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()
{
@@ -120,14 +78,7 @@ namespace Content.Shared.Movement.Systems
ShutdownInput();
ShutdownPushing();
_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)
@@ -136,7 +87,7 @@ namespace Content.Shared.Movement.Systems
UsedMobMovement.Clear();
}
protected Angle GetParentGridAngle(TransformComponent xform, IMoverComponent mover)
protected Angle GetParentGridAngle(TransformComponent xform, InputMoverComponent mover)
{
if (!_mapManager.TryGetGrid(xform.GridUid, out var grid))
return mover.LastGridAngle;
@@ -144,43 +95,12 @@ namespace Content.Shared.Movement.Systems
return grid.WorldRotation;
}
/// <summary>
/// A generic kinematic mover for entities.
/// </summary>
protected void HandleKinematicMovement(IMoverComponent mover, PhysicsComponent physicsComponent)
{
var (walkDir, sprintDir) = mover.VelocityDir;
var transform = EntityManager.GetComponent<TransformComponent>(mover.Owner);
var parentRotation = GetParentGridAngle(transform, mover);
// Regular movement.
// Target velocity.
var moveSpeedComponent = CompOrNull<MovementSpeedModifierComponent>(mover.Owner);
var walkSpeed = moveSpeedComponent?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed;
var sprintSpeed = moveSpeedComponent?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed;
var total = walkDir * walkSpeed + sprintDir * sprintSpeed;
var worldTotal = _relativeMovement ? parentRotation.RotateVec(total) : total;
if (transform.GridUid != null)
mover.LastGridAngle = parentRotation;
if (worldTotal != Vector2.Zero)
transform.LocalRotation = transform.GridUid != null
? total.ToWorldAngle()
: worldTotal.ToWorldAngle();
_physics.SetLinearVelocity(physicsComponent, worldTotal);
}
/// <summary>
/// Movement while considering actionblockers, weightlessness, etc.
/// </summary>
protected void HandleMobMovement(
IMoverComponent mover,
InputMoverComponent mover,
PhysicsComponent physicsComponent,
IMobMoverComponent mobMover,
TransformComponent xform,
float frameTime)
{
@@ -194,7 +114,7 @@ namespace Content.Shared.Movement.Systems
UsedMobMovement[mover.Owner] = true;
var weightless = mover.Owner.IsWeightless(physicsComponent, mapManager: _mapManager, entityManager: EntityManager);
var (walkDir, sprintDir) = mover.VelocityDir;
var (walkDir, sprintDir) = GetVelocityInput(mover);
var touching = false;
// Handle wall-pushes.
@@ -208,7 +128,10 @@ namespace Content.Shared.Movement.Systems
var ev = new CanWeightlessMoveEvent();
RaiseLocalEvent(xform.Owner, ref ev);
// No gravity: is our entity touching anything?
touching = ev.CanMove || IsAroundCollider(_physics, xform, mobMover, physicsComponent);
touching = ev.CanMove;
if (!touching && TryComp<MobMoverComponent>(xform.Owner, out var mobMover))
touching |= IsAroundCollider(_physics, xform, mobMover, physicsComponent);
}
if (!touching)
@@ -222,8 +145,10 @@ namespace Content.Shared.Movement.Systems
// Target velocity.
// This is relative to the map / grid we're on.
var moveSpeedComponent = CompOrNull<MovementSpeedModifierComponent>(mover.Owner);
var walkSpeed = moveSpeedComponent?.CurrentWalkSpeed ?? MovementSpeedModifierComponent.DefaultBaseWalkSpeed;
var sprintSpeed = moveSpeedComponent?.CurrentSprintSpeed ?? MovementSpeedModifierComponent.DefaultBaseSprintSpeed;
var total = walkDir * walkSpeed + sprintDir * sprintSpeed;
var parentRotation = GetParentGridAngle(xform, mover);
@@ -239,37 +164,30 @@ namespace Content.Shared.Movement.Systems
if (weightless)
{
if (worldTotal != Vector2.Zero && touching)
friction = _weightlessFrictionVelocity;
friction = moveSpeedComponent?.WeightlessFriction ?? MovementSpeedModifierComponent.DefaultWeightlessFriction;
else
friction = _weightlessFrictionVelocityNoInput;
friction = moveSpeedComponent?.WeightlessFrictionNoInput ?? MovementSpeedModifierComponent.DefaultWeightlessFrictionNoInput;
weightlessModifier = _mobWeightlessModifier;
accel = _mobWeightlessAcceleration;
weightlessModifier = moveSpeedComponent?.WeightlessModifier ?? MovementSpeedModifierComponent.DefaultWeightlessModifier;
accel = moveSpeedComponent?.WeightlessAcceleration ?? MovementSpeedModifierComponent.DefaultWeightlessAcceleration;
}
else
{
friction = _frictionVelocity;
if (worldTotal != Vector2.Zero || moveSpeedComponent?.FrictionNoInput == null)
{
friction = moveSpeedComponent?.Friction ?? MovementSpeedModifierComponent.DefaultFriction;
}
else
{
friction = moveSpeedComponent.FrictionNoInput ?? MovementSpeedModifierComponent.DefaultFrictionNoInput;
}
weightlessModifier = 1f;
accel = _mobAcceleration;
accel = moveSpeedComponent?.Acceleration ?? MovementSpeedModifierComponent.DefaultAcceleration;
}
var profile = new MobMovementProfileEvent(
touching,
weightless,
friction,
weightlessModifier,
accel);
RaiseLocalEvent(xform.Owner, ref profile);
if (profile.Override)
{
friction = profile.Friction;
weightlessModifier = profile.WeightlessModifier;
accel = profile.Acceleration;
}
Friction(frameTime, friction, ref velocity);
var minimumFrictionSpeed = moveSpeedComponent?.MinimumFrictionSpeed ?? MovementSpeedModifierComponent.DefaultMinimumFrictionSpeed;
Friction(minimumFrictionSpeed, frameTime, friction, ref velocity);
if (xform.GridUid != EntityUid.Invalid)
mover.LastGridAngle = parentRotation;
@@ -278,12 +196,24 @@ namespace Content.Shared.Movement.Systems
{
// This should have its event run during island solver soooo
xform.DeferUpdates = true;
xform.LocalRotation = xform.GridUid != null
TransformComponent rotateXform;
// If we're in a container then relay rotation to the parent instead
if (_container.TryGetContainingContainer(xform.Owner, out var container))
{
rotateXform = Transform(container.Owner);
}
else
{
rotateXform = xform;
}
rotateXform.LocalRotation = xform.GridUid != null
? total.ToWorldAngle()
: worldTotal.ToWorldAngle();
xform.DeferUpdates = false;
rotateXform.DeferUpdates = false;
if (!weightless && TryGetSound(mover, mobMover, xform, out var variation, out var sound))
if (!weightless && TryComp<MobMoverComponent>(mover.Owner, out var mobMover) && TryGetSound(mover, mobMover, xform, out var variation, out var sound))
{
var soundModifier = mover.Sprinting ? 1.0f : FootstepWalkingAddedVolumeMultiplier;
SoundSystem.Play(sound,
@@ -300,11 +230,11 @@ namespace Content.Shared.Movement.Systems
_physics.SetLinearVelocity(physicsComponent, velocity);
}
private void Friction(float frameTime, float friction, ref Vector2 velocity)
private void Friction(float minimumFrictionSpeed, float frameTime, float friction, ref Vector2 velocity)
{
var speed = velocity.Length;
if (speed < _minimumFrictionSpeed) return;
if (speed < minimumFrictionSpeed) return;
var drop = 0f;
@@ -340,11 +270,11 @@ namespace Content.Shared.Movement.Systems
return UsedMobMovement.TryGetValue(uid, out var used) && used;
}
protected bool UseMobMovement(IMoverComponent mover, PhysicsComponent body)
protected bool UseMobMovement(InputMoverComponent mover, PhysicsComponent body)
{
return mover.CanMove &&
body.BodyStatus == BodyStatus.OnGround &&
HasComp<MobStateComponent>(body.Owner) &&
HasComp<InputMoverComponent>(body.Owner) &&
// If we're being pulled then don't mess with our velocity.
(!TryComp(body.Owner, out SharedPullableComponent? pullable) || !pullable.BeingPulled);
}
@@ -352,9 +282,9 @@ namespace Content.Shared.Movement.Systems
/// <summary>
/// Used for weightlessness to determine if we are near a wall.
/// </summary>
private bool IsAroundCollider(SharedPhysicsSystem broadPhaseSystem, TransformComponent transform, IMobMoverComponent mover, IPhysBody collider)
private bool IsAroundCollider(SharedPhysicsSystem broadPhaseSystem, TransformComponent transform, MobMoverComponent mover, IPhysBody collider)
{
var enlargedAABB = collider.GetWorldAABB().Enlarged(mover.GrabRange);
var enlargedAABB = collider.GetWorldAABB().Enlarged(mover.GrabRangeVV);
foreach (var otherCollider in broadPhaseSystem.GetCollidingEntities(transform.MapID, enlargedAABB))
{
@@ -381,7 +311,7 @@ namespace Content.Shared.Movement.Systems
protected abstract bool CanSound();
private bool TryGetSound(IMoverComponent mover, IMobMoverComponent mobMover, TransformComponent xform, out float variation, [NotNullWhen(true)] out string? sound)
private bool TryGetSound(InputMoverComponent mover, MobMoverComponent mobMover, TransformComponent xform, out float variation, [NotNullWhen(true)] out string? sound)
{
sound = null;
variation = 0f;