diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 18c88c4231..631a57ce52 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Fluids; using Content.Shared.Popups; using Content.Shared.Slippery; using Content.Shared.Fluids.Components; +using Content.Shared.Friction; using Content.Shared.StepTrigger.Components; using Content.Shared.StepTrigger.Systems; using Robust.Server.GameObjects; @@ -45,6 +46,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem [Dependency] private readonly SharedPopupSystem _popups = default!; [Dependency] private readonly StepTriggerSystem _stepTrigger = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly TileFrictionController _tile = default!; public static float PuddleVolume = 1000; @@ -307,10 +309,13 @@ public sealed partial class PuddleSystem : SharedPuddleSystem { var comp = EnsureComp(entityUid); _stepTrigger.SetActive(entityUid, true, comp); + var friction = EnsureComp(entityUid); + _tile.SetModifier(entityUid, TileFrictionController.DefaultFriction * 0.5f, friction); } else if (TryComp(entityUid, out var comp)) { _stepTrigger.SetActive(entityUid, false, comp); + RemCompDeferred(entityUid); } } diff --git a/Content.Shared/Friction/TileFrictionController.cs b/Content.Shared/Friction/TileFrictionController.cs index f3f760f0a0..afd3290177 100644 --- a/Content.Shared/Friction/TileFrictionController.cs +++ b/Content.Shared/Friction/TileFrictionController.cs @@ -20,7 +20,7 @@ namespace Content.Shared.Friction { public sealed class TileFrictionController : VirtualController { - [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IConfigurationManager _configManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly SharedGravitySystem _gravity = default!; [Dependency] private readonly SharedMoverController _mover = default!; @@ -28,30 +28,14 @@ namespace Content.Shared.Friction private float _stopSpeed; private float _frictionModifier; - private const float DefaultFriction = 0.3f; + public const float DefaultFriction = 0.3f; public override void Initialize() { base.Initialize(); - var configManager = IoCManager.Resolve(); - - configManager.OnValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier, true); - configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true); - - SubscribeLocalEvent(OnGetState); - SubscribeLocalEvent(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); + _configManager.OnValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier, true); + _configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true); } private void SetStopSpeed(float value) => _stopSpeed = value; @@ -61,10 +45,9 @@ namespace Content.Shared.Friction public override void Shutdown() { base.Shutdown(); - var configManager = IoCManager.Resolve(); - configManager.UnsubValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier); - configManager.UnsubValueChanged(CCVars.StopSpeed, SetStopSpeed); + _configManager.UnsubValueChanged(CCVars.TileFrictionModifier, SetFrictionModifier); + _configManager.UnsubValueChanged(CCVars.StopSpeed, SetStopSpeed); } public override void UpdateBeforeMapSolve(bool prediction, PhysicsMapComponent mapComponent, float frameTime) @@ -75,6 +58,7 @@ namespace Content.Shared.Friction var xformQuery = GetEntityQuery(); var pullerQuery = GetEntityQuery(); var pullableQuery = GetEntityQuery(); + var gridQuery = GetEntityQuery(); foreach (var body in mapComponent.AwakeBodies) { @@ -97,7 +81,7 @@ namespace Content.Shared.Friction continue; } - var surfaceFriction = GetTileFriction(uid, body, xform); + var surfaceFriction = GetTileFriction(uid, body, xform, gridQuery, frictionQuery); var bodyModifier = 1f; if (frictionQuery.TryGetComponent(uid, out var frictionComp)) @@ -130,7 +114,8 @@ namespace Content.Shared.Friction { var speed = body.LinearVelocity.Length; - if (speed <= 0.0f) return; + if (speed <= 0.0f) + return; // This is the *actual* amount that speed will drop by, we just do some multiplication around it to be easier. var drop = 0.0f; @@ -161,7 +146,8 @@ namespace Content.Shared.Friction { var speed = MathF.Abs(body.AngularVelocity); - if (speed <= 0.0f) return; + if (speed <= 0.0f) + return; // This is the *actual* amount that speed will drop by, we just do some multiplication around it to be easier. var drop = 0.0f; @@ -189,42 +175,58 @@ namespace Content.Shared.Friction } [Pure] - private float GetTileFriction(EntityUid uid, PhysicsComponent body, TransformComponent xform) + private float GetTileFriction( + EntityUid uid, + PhysicsComponent body, + TransformComponent xform, + EntityQuery gridQuery, + EntityQuery frictionQuery) { // TODO: Make IsWeightless event-based; we already have grid traversals tracked so just raise events if (_gravity.IsWeightless(uid, body, xform)) return 0.0f; - if (!xform.Coordinates.IsValid(EntityManager)) return 0.0f; + if (!xform.Coordinates.IsValid(EntityManager)) + return 0.0f; - if (_mapManager.TryGetGrid(xform.GridUid, out var grid)) + // If not on a grid then return the map's friction. + if (!gridQuery.TryGetComponent(xform.GridUid, out var grid)) { - var tile = grid.GetTileRef(xform.Coordinates); - - // If it's a map but on an empty tile then just assume it has gravity. - if (tile.Tile.IsEmpty && - HasComp(xform.GridUid) && - (!TryComp(xform.GridUid, out var gravity) || gravity.Enabled)) - { - return DefaultFriction; - } - - var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; - return tileDef.Friction; + return frictionQuery.TryGetComponent(xform.MapUid, out var friction) + ? friction.Modifier + : DefaultFriction; } - return TryComp(xform.MapUid, out var friction) ? friction.Modifier : DefaultFriction; + var tile = grid.GetTileRef(xform.Coordinates); + + // If it's a map but on an empty tile then just assume it has gravity. + if (tile.Tile.IsEmpty && + HasComp(xform.GridUid) && + (!TryComp(xform.GridUid, out var gravity) || gravity.Enabled)) + { + return DefaultFriction; + } + + // If there's an anchored ent that modifies friction then fallback to that instead. + var anc = grid.GetAnchoredEntitiesEnumerator(tile.GridIndices); + + while (anc.MoveNext(out var tileEnt)) + { + if (frictionQuery.TryGetComponent(tileEnt, out var friction)) + return friction.Modifier; + } + + var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; + return tileDef.Friction; } - [NetSerializable, Serializable] - private sealed class TileFrictionComponentState : ComponentState + public void SetModifier(EntityUid entityUid, float value, TileFrictionModifierComponent? friction = null) { - public float Modifier; + if (!Resolve(entityUid, ref friction) || value.Equals(friction.Modifier)) + return; - public TileFrictionComponentState(float modifier) - { - Modifier = modifier; - } + friction.Modifier = value; + Dirty(friction); } } } diff --git a/Content.Shared/Friction/TileFrictionModifier.cs b/Content.Shared/Friction/TileFrictionModifier.cs index 7aed89c79b..4c0db04485 100644 --- a/Content.Shared/Friction/TileFrictionModifier.cs +++ b/Content.Shared/Friction/TileFrictionModifier.cs @@ -1,14 +1,15 @@ -namespace Content.Shared.Friction +using Robust.Shared.GameStates; + +namespace Content.Shared.Friction; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(TileFrictionController)), AutoGenerateComponentState] +public sealed partial class TileFrictionModifierComponent : Component { - [RegisterComponent] - [Access(typeof(TileFrictionController))] - public sealed class TileFrictionModifierComponent : Component - { - /// - /// Multiply the tilefriction cvar by this to get the body's actual tilefriction. - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("modifier")] - public float Modifier; - } + /// + /// Multiply the tilefriction cvar by this to get the body's actual tilefriction. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("modifier"), AutoNetworkedField] + public float Modifier; } diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index e4d8189860..df1c894ab9 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -118,7 +118,7 @@ sprite: Mobs/Silicon/Bots/honkbot.rsi state: honkbot - type: Slippery - launchForwardsMultiplier: 6.0 + launchForwardsMultiplier: 2 - type: StepTrigger intersectRatio: 0.2 - type: Physics @@ -167,7 +167,7 @@ sprite: Mobs/Silicon/Bots/honkbot.rsi state: jonkbot - type: Slippery - launchForwardsMultiplier: 7.0 + launchForwardsMultiplier: 2 - type: Construction graph: JonkBot node: bot diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml index 9fde289e9f..964d661ccb 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/produce.yml @@ -230,7 +230,7 @@ heldPrefix: peel - type: Slippery paralyzeTime: 4 - launchForwardsMultiplier: 5 + launchForwardsMultiplier: 2 - type: entity name: banana peel diff --git a/Resources/Prototypes/Entities/Objects/Fun/error.yml b/Resources/Prototypes/Entities/Objects/Fun/error.yml index 13e2e1254e..8f3fc21137 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/error.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/error.yml @@ -16,7 +16,7 @@ - ReagentId: Nutriment Quantity: 5 - type: Slippery - launchForwardsMultiplier: 20 + launchForwardsMultiplier: 5 - type: StepTrigger intersectRatio: 0.2 - type: CollisionWake diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml index fae2eb9781..44e7f1d9b7 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml @@ -70,7 +70,7 @@ state: syndie - type: Slippery paralyzeTime: 5 - launchForwardsMultiplier: 9.0 + launchForwardsMultiplier: 2.5 - type: StepTrigger - type: Item heldPrefix: syndie @@ -99,7 +99,7 @@ state: omega - type: Slippery paralyzeTime: 7 - launchForwardsMultiplier: 9.0 + launchForwardsMultiplier: 3 - type: StepTrigger - type: Item heldPrefix: omega diff --git a/Resources/Prototypes/Reagents/cleaning.yml b/Resources/Prototypes/Reagents/cleaning.yml index a254af4282..a7f01b5c1a 100644 --- a/Resources/Prototypes/Reagents/cleaning.yml +++ b/Resources/Prototypes/Reagents/cleaning.yml @@ -46,5 +46,5 @@ tileReactions: - !type:SpillTileReaction paralyzeTime: 3 - launchForwardsMultiplier: 4 + launchForwardsMultiplier: 2 requiredSlipSpeed: 1