Tile friction ECS (#8012)
* Tile friction ECS Removes some resolves which is really nice. * Velocity checks
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Movement;
|
using Content.Shared.Movement;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Physics.Controllers;
|
using Robust.Shared.Physics.Controllers;
|
||||||
using Robust.Shared.Physics.Dynamics;
|
using Robust.Shared.Physics.Dynamics;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
|
||||||
namespace Content.Shared.Friction
|
namespace Content.Shared.Friction
|
||||||
@@ -31,6 +31,20 @@ namespace Content.Shared.Friction
|
|||||||
|
|
||||||
configManager.OnValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier, true);
|
configManager.OnValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier, true);
|
||||||
configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true);
|
configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<TileFrictionModifierComponent, ComponentGetState>(OnGetState);
|
||||||
|
SubscribeLocalEvent<TileFrictionModifierComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandleState(EntityUid uid, TileFrictionModifierComponent component, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not TileFrictionComponentState tileState) return;
|
||||||
|
component.Modifier = tileState.Modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetState(EntityUid uid, TileFrictionModifierComponent component, ref ComponentGetState args)
|
||||||
|
{
|
||||||
|
args.State = new TileFrictionComponentState(component.Modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetStopSpeed(float value) => _stopSpeed = value;
|
private void SetStopSpeed(float value) => _stopSpeed = value;
|
||||||
@@ -50,16 +64,27 @@ namespace Content.Shared.Friction
|
|||||||
{
|
{
|
||||||
base.UpdateBeforeMapSolve(prediction, mapComponent, frameTime);
|
base.UpdateBeforeMapSolve(prediction, mapComponent, frameTime);
|
||||||
|
|
||||||
|
var frictionQuery = GetEntityQuery<TileFrictionModifierComponent>();
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
|
||||||
foreach (var body in mapComponent.AwakeBodies)
|
foreach (var body in mapComponent.AwakeBodies)
|
||||||
{
|
{
|
||||||
// Only apply friction when it's not a mob (or the mob doesn't have control)
|
// Only apply friction when it's not a mob (or the mob doesn't have control)
|
||||||
if (body.Deleted ||
|
if (prediction && !body.Predict ||
|
||||||
prediction && !body.Predict ||
|
|
||||||
body.BodyStatus == BodyStatus.InAir ||
|
body.BodyStatus == BodyStatus.InAir ||
|
||||||
Mover.UseMobMovement(body.Owner)) continue;
|
Mover.UseMobMovement(body.Owner)) continue;
|
||||||
|
|
||||||
var surfaceFriction = GetTileFriction(body);
|
if (body.LinearVelocity.Equals(Vector2.Zero) && body.AngularVelocity.Equals(0f)) continue;
|
||||||
var bodyModifier = IoCManager.Resolve<IEntityManager>().GetComponentOrNull<TileFrictionModifierComponent>(body.Owner)?.Modifier ?? 1.0f;
|
|
||||||
|
DebugTools.Assert(!Deleted(body.Owner));
|
||||||
|
var surfaceFriction = GetTileFriction(body, xformQuery.GetComponent(body.Owner));
|
||||||
|
var bodyModifier = 1f;
|
||||||
|
|
||||||
|
if (frictionQuery.TryGetComponent(body.Owner, out var frictionComp))
|
||||||
|
{
|
||||||
|
bodyModifier = frictionComp.Modifier;
|
||||||
|
}
|
||||||
|
|
||||||
var friction = _frictionModifier * surfaceFriction * bodyModifier;
|
var friction = _frictionModifier * surfaceFriction * bodyModifier;
|
||||||
|
|
||||||
ReduceLinearVelocity(prediction, body, friction, frameTime);
|
ReduceLinearVelocity(prediction, body, friction, frameTime);
|
||||||
@@ -130,15 +155,13 @@ namespace Content.Shared.Friction
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Pure]
|
[Pure]
|
||||||
private float GetTileFriction(PhysicsComponent body)
|
private float GetTileFriction(PhysicsComponent body, TransformComponent xform)
|
||||||
{
|
{
|
||||||
var transform = IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(body.Owner);
|
var coords = xform.Coordinates;
|
||||||
var coords = transform.Coordinates;
|
|
||||||
|
|
||||||
// TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events
|
// TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events
|
||||||
if (body.BodyStatus == BodyStatus.InAir ||
|
if (body.Owner.IsWeightless(body, coords, _mapManager) ||
|
||||||
body.Owner.IsWeightless(body, coords, _mapManager) ||
|
!_mapManager.TryGetGrid(xform.GridID, out var grid))
|
||||||
!_mapManager.TryGetGrid(transform.GridID, out var grid))
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
if (!coords.IsValid(EntityManager)) return 0.0f;
|
if (!coords.IsValid(EntityManager)) return 0.0f;
|
||||||
@@ -147,5 +170,16 @@ namespace Content.Shared.Friction
|
|||||||
var tileDef = _tileDefinitionManager[tile.Tile.TypeId];
|
var tileDef = _tileDefinitionManager[tile.Tile.TypeId];
|
||||||
return tileDef.Friction;
|
return tileDef.Friction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NetSerializable, Serializable]
|
||||||
|
private sealed class TileFrictionComponentState : ComponentState
|
||||||
|
{
|
||||||
|
public float Modifier;
|
||||||
|
|
||||||
|
public TileFrictionComponentState(float modifier)
|
||||||
|
{
|
||||||
|
Modifier = modifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,14 @@
|
|||||||
using System;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Maths;
|
|
||||||
using Robust.Shared.Players;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
|
||||||
using Robust.Shared.ViewVariables;
|
|
||||||
|
|
||||||
namespace Content.Shared.Friction
|
namespace Content.Shared.Friction
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
|
[Friend(typeof(SharedTileFrictionController))]
|
||||||
public sealed class TileFrictionModifierComponent : Component
|
public sealed class TileFrictionModifierComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Multiply the tilefriction cvar by this to get the body's actual tilefriction.
|
/// Multiply the tilefriction cvar by this to get the body's actual tilefriction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float Modifier
|
|
||||||
{
|
|
||||||
get => _modifier;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (MathHelper.CloseToPercent(_modifier, value)) return;
|
|
||||||
|
|
||||||
_modifier = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataField("modifier")]
|
[DataField("modifier")]
|
||||||
private float _modifier = 1.0f;
|
public float Modifier;
|
||||||
|
|
||||||
public override ComponentState GetComponentState()
|
|
||||||
{
|
|
||||||
return new TileFrictionComponentState(_modifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
|
||||||
{
|
|
||||||
base.HandleComponentState(curState, nextState);
|
|
||||||
if (curState is not TileFrictionComponentState tileState) return;
|
|
||||||
_modifier = tileState.Modifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
[NetSerializable, Serializable]
|
|
||||||
private sealed class TileFrictionComponentState : ComponentState
|
|
||||||
{
|
|
||||||
public float Modifier;
|
|
||||||
|
|
||||||
public TileFrictionComponentState(float modifier)
|
|
||||||
{
|
|
||||||
Modifier = modifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user