diff --git a/Content.Client/Friction/TileFrictionController.cs b/Content.Client/Friction/TileFrictionController.cs deleted file mode 100644 index 0b8aaeff55..0000000000 --- a/Content.Client/Friction/TileFrictionController.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Content.Client.Physics.Controllers; -using Content.Shared.Friction; -using Robust.Shared.GameObjects; - -namespace Content.Client.Friction -{ - public sealed class TileFrictionController : SharedTileFrictionController - { - public override void Initialize() - { - base.Initialize(); - Mover = Get(); - } - } -} diff --git a/Content.Client/Slippery/SlipperySystem.cs b/Content.Client/Slippery/SlipperySystem.cs deleted file mode 100644 index fcd2052e86..0000000000 --- a/Content.Client/Slippery/SlipperySystem.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Content.Shared.Slippery; - -namespace Content.Client.Slippery -{ - internal sealed class SlipperySystem : SharedSlipperySystem - { - protected override void PlaySound(SlipperyComponent component) {} - } -} diff --git a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs index 5f8113185f..4ba3efe658 100644 --- a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs @@ -36,6 +36,7 @@ namespace Content.Server.Chemistry.TileReactions var slippery = entityManager.EnsureComponent(puddle.Owner); slippery.LaunchForwardsMultiplier = _launchForwardsMultiplier; slippery.ParalyzeTime = _paralyzeTime; + entityManager.Dirty(slippery); var step = entityManager.EnsureComponent(puddle.Owner); entityManager.EntitySysManager.GetEntitySystem().SetRequiredTriggerSpeed(puddle.Owner, _requiredSlipSpeed, step); diff --git a/Content.Server/Friction/TileFrictionController.cs b/Content.Server/Friction/TileFrictionController.cs deleted file mode 100644 index 4a55244a47..0000000000 --- a/Content.Server/Friction/TileFrictionController.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Content.Server.Physics.Controllers; -using Content.Shared.Friction; - -namespace Content.Server.Friction -{ - public sealed class TileFrictionController : SharedTileFrictionController - { - public override void Initialize() - { - base.Initialize(); - Mover = Get(); - } - } -} diff --git a/Content.Server/Slippery/SlipperySystem.cs b/Content.Server/Slippery/SlipperySystem.cs deleted file mode 100644 index e0e5ba7276..0000000000 --- a/Content.Server/Slippery/SlipperySystem.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Content.Shared.Audio; -using Content.Shared.Slippery; -using Robust.Shared.Audio; -using Robust.Shared.Player; - -namespace Content.Server.Slippery -{ - internal sealed class SlipperySystem : SharedSlipperySystem - { - protected override void PlaySound(SlipperyComponent component) - { - SoundSystem.Play(component.SlipSound.GetSound(), Filter.Pvs(component.Owner), component.Owner, AudioHelpers.WithVariation(0.2f)); - } - } -} diff --git a/Content.Shared/Friction/SharedTileFrictionController.cs b/Content.Shared/Friction/TileFrictionController.cs similarity index 91% rename from Content.Shared/Friction/SharedTileFrictionController.cs rename to Content.Shared/Friction/TileFrictionController.cs index d30c5a6d41..9480937427 100644 --- a/Content.Shared/Friction/SharedTileFrictionController.cs +++ b/Content.Shared/Friction/TileFrictionController.cs @@ -1,7 +1,6 @@ using Content.Shared.CCVar; using Content.Shared.Gravity; -using Content.Shared.Movement; -using Content.Shared.Movement.Components; +using Content.Shared.Movement.Events; using Content.Shared.Movement.Systems; using Content.Shared.Pulling.Components; using JetBrains.Annotations; @@ -16,13 +15,13 @@ using Robust.Shared.Utility; namespace Content.Shared.Friction { - public abstract class SharedTileFrictionController : VirtualController + public sealed class TileFrictionController : VirtualController { [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly SharedGravitySystem _gravity = default!; - - protected SharedMoverController Mover = default!; + [Dependency] private readonly SharedMoverController _mover = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; private float _stopSpeed; private float _frictionModifier; @@ -79,7 +78,10 @@ namespace Content.Shared.Friction // Only apply friction when it's not a mob (or the mob doesn't have control) if (prediction && !body.Predict || body.BodyStatus == BodyStatus.InAir || - Mover.UseMobMovement(body.Owner)) continue; + _mover.UseMobMovement(body.Owner)) + { + continue; + } if (body.LinearVelocity.Equals(Vector2.Zero) && body.AngularVelocity.Equals(0f)) continue; @@ -99,6 +101,11 @@ namespace Content.Shared.Friction bodyModifier = frictionComp.Modifier; } + var ev = new TileFrictionEvent(bodyModifier); + + RaiseLocalEvent(body.Owner, ref ev); + bodyModifier = ev.Modifier; + // If we're sandwiched between 2 pullers reduce friction // Might be better to make this dynamic and check how many are in the pull chain? // Either way should be much faster for now. @@ -143,7 +150,7 @@ namespace Content.Shared.Friction var newSpeed = MathF.Max(0.0f, speed - drop); newSpeed /= speed; - body.LinearVelocity *= newSpeed; + _physics.SetLinearVelocity(body, body.LinearVelocity * newSpeed); } private void ReduceAngularVelocity(bool prediction, PhysicsComponent body, float friction, float frameTime) @@ -174,7 +181,7 @@ namespace Content.Shared.Friction var newSpeed = MathF.Max(0.0f, speed - drop); newSpeed /= speed; - body.AngularVelocity *= newSpeed; + _physics.SetAngularVelocity(body, body.AngularVelocity * newSpeed); } [Pure] diff --git a/Content.Shared/Friction/TileFrictionModifier.cs b/Content.Shared/Friction/TileFrictionModifier.cs index 72ba9a86ee..7aed89c79b 100644 --- a/Content.Shared/Friction/TileFrictionModifier.cs +++ b/Content.Shared/Friction/TileFrictionModifier.cs @@ -1,7 +1,7 @@ namespace Content.Shared.Friction { [RegisterComponent] - [Access(typeof(SharedTileFrictionController))] + [Access(typeof(TileFrictionController))] public sealed class TileFrictionModifierComponent : Component { /// diff --git a/Content.Shared/Movement/Events/TileFrictionEvent.cs b/Content.Shared/Movement/Events/TileFrictionEvent.cs new file mode 100644 index 0000000000..e355f21f45 --- /dev/null +++ b/Content.Shared/Movement/Events/TileFrictionEvent.cs @@ -0,0 +1,15 @@ +namespace Content.Shared.Movement.Events; + +/// +/// Raised to try and get any tile friction modifiers for a particular body. +/// +[ByRefEvent] +public struct TileFrictionEvent +{ + public float Modifier; + + public TileFrictionEvent(float modifier) + { + Modifier = modifier; + } +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 9b9c2836ff..fed4a8a8da 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -69,7 +69,7 @@ namespace Content.Shared.Movement.Systems InitializeRelay(); _configManager.OnValueChanged(CCVars.RelativeMovement, SetRelativeMovement, true); _configManager.OnValueChanged(CCVars.StopSpeed, SetStopSpeed, true); - UpdatesBefore.Add(typeof(SharedTileFrictionController)); + UpdatesBefore.Add(typeof(TileFrictionController)); } private void SetRelativeMovement(bool value) => _relativeMovement = value; diff --git a/Content.Shared/Slippery/SlipperyComponent.cs b/Content.Shared/Slippery/SlipperyComponent.cs index fb52504d47..ec32143a63 100644 --- a/Content.Shared/Slippery/SlipperyComponent.cs +++ b/Content.Shared/Slippery/SlipperyComponent.cs @@ -15,75 +15,29 @@ namespace Content.Shared.Slippery [NetworkedComponent] public sealed class SlipperyComponent : Component { - private float _paralyzeTime = 3f; - private float _launchForwardsMultiplier = 1f; - private SoundSpecifier _slipSound = new SoundPathSpecifier("/Audio/Effects/slip.ogg"); - /// - /// Path to the sound to be played when a mob slips. + /// Path to the sound to be played when a mob slips. /// [ViewVariables] [DataField("slipSound")] - public SoundSpecifier SlipSound - { - get => _slipSound; - set - { - if (value == _slipSound) - return; - - _slipSound = value; - Dirty(); - } - } + [Access(Other = AccessPermissions.ReadWriteExecute)] + public SoundSpecifier SlipSound = new SoundPathSpecifier("/Audio/Effects/slip.ogg"); /// - /// How many seconds the mob will be paralyzed for. + /// How many seconds the mob will be paralyzed for. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("paralyzeTime")] - public float ParalyzeTime - { - get => _paralyzeTime; - set - { - if (MathHelper.CloseToPercent(_paralyzeTime, value)) return; - - _paralyzeTime = value; - Dirty(); - } - } + [Access(Other = AccessPermissions.ReadWrite)] + public float ParalyzeTime = 3f; /// - /// The entity's speed will be multiplied by this to slip it forwards. + /// The entity's speed will be multiplied by this to slip it forwards. /// [ViewVariables(VVAccess.ReadWrite)] [DataField("launchForwardsMultiplier")] - public float LaunchForwardsMultiplier - { - get => _launchForwardsMultiplier; - set - { - if (MathHelper.CloseToPercent(_launchForwardsMultiplier, value)) return; - - _launchForwardsMultiplier = value; - Dirty(); - } - } - - public override ComponentState GetComponentState() - { - return new SlipperyComponentState(ParalyzeTime, LaunchForwardsMultiplier, SlipSound.GetSound()); - } - - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) - { - if (curState is not SlipperyComponentState state) return; - - _paralyzeTime = state.ParalyzeTime; - _launchForwardsMultiplier = state.LaunchForwardsMultiplier; - _slipSound = new SoundPathSpecifier(state.SlipSound); - } + [Access(Other = AccessPermissions.ReadWrite)] + public float LaunchForwardsMultiplier = 1f; } [Serializable, NetSerializable] diff --git a/Content.Shared/Slippery/SharedSlipperySystem.cs b/Content.Shared/Slippery/SlipperySystem.cs similarity index 72% rename from Content.Shared/Slippery/SharedSlipperySystem.cs rename to Content.Shared/Slippery/SlipperySystem.cs index e2dc51c589..54fab4b3bc 100644 --- a/Content.Shared/Slippery/SharedSlipperySystem.cs +++ b/Content.Shared/Slippery/SlipperySystem.cs @@ -5,14 +5,17 @@ using Content.Shared.StatusEffect; using Content.Shared.StepTrigger.Systems; using Content.Shared.Stunnable; using JetBrains.Annotations; +using Robust.Shared.Audio; using Robust.Shared.Containers; +using Robust.Shared.GameStates; namespace Content.Shared.Slippery { [UsedImplicitly] - public abstract class SharedSlipperySystem : EntitySystem + public sealed class SlipperySystem : EntitySystem { [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedStunSystem _stunSystem = default!; [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!; [Dependency] private readonly SharedContainerSystem _container = default!; @@ -24,6 +27,22 @@ namespace Content.Shared.Slippery SubscribeLocalEvent(HandleAttemptCollide); SubscribeLocalEvent(HandleStepTrigger); SubscribeLocalEvent(OnNoSlipAttempt); + SubscribeLocalEvent(OnSlipperyGetState); + SubscribeLocalEvent(OnSlipperyHandleState); + } + + private void OnSlipperyHandleState(EntityUid uid, SlipperyComponent component, ref ComponentHandleState args) + { + if (args.Current is not SlipperyComponentState state) return; + + component.ParalyzeTime = state.ParalyzeTime; + component.LaunchForwardsMultiplier = state.LaunchForwardsMultiplier; + component.SlipSound = new SoundPathSpecifier(state.SlipSound); + } + + private void OnSlipperyGetState(EntityUid uid, SlipperyComponent component, ref ComponentGetState args) + { + args.State = new SlipperyComponentState(component.ParalyzeTime, component.LaunchForwardsMultiplier, component.SlipSound.GetSound()); } private void HandleStepTrigger(EntityUid uid, SlipperyComponent component, ref StepTriggeredEvent args) @@ -69,14 +88,13 @@ namespace Content.Shared.Slippery // Preventing from playing the slip sound when you are already knocked down. if (playSound) - PlaySound(component); + { + _audio.PlayPredicted(component.SlipSound, other, other); + } _adminLogger.Add(LogType.Slip, LogImpact.Low, $"{ToPrettyString(other):mob} slipped on collision with {ToPrettyString(component.Owner):entity}"); } - - // Until we get predicted slip sounds TM? - protected abstract void PlaySound(SlipperyComponent component); } /// diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index c5d1ae1d22..cc3c58683d 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -26,6 +26,12 @@ namespace Content.Shared.Stunnable [Dependency] private readonly StatusEffectsSystem _statusEffectSystem = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + /// + /// Friction modifier for knocked down players. + /// Doesn't make them faster but makes them slow down... slower. + /// + public const float KnockDownModifier = 0.4f; + public override void Initialize() { SubscribeLocalEvent(OnKnockInit); @@ -48,6 +54,8 @@ namespace Content.Shared.Stunnable SubscribeLocalEvent(OnInteractHand); SubscribeLocalEvent(OnRefreshMovespeed); + SubscribeLocalEvent(OnKnockedTileFriction); + // Attempt event subscriptions. SubscribeLocalEvent(OnMoveAttempt); SubscribeLocalEvent(OnInteractAttempt); @@ -205,6 +213,7 @@ namespace Content.Shared.Stunnable if (args.Handled || knocked.HelpTimer > 0f) return; + // TODO: This should be an event. if (HasComp(uid)) return; @@ -215,11 +224,16 @@ namespace Content.Shared.Stunnable SoundSystem.Play(knocked.StunAttemptSound.GetSound(), Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.05f)); - knocked.Dirty(); + Dirty(knocked); args.Handled = true; } + private void OnKnockedTileFriction(EntityUid uid, KnockedDownComponent component, ref TileFrictionEvent args) + { + args.Modifier *= KnockDownModifier; + } + #region Attempt Event Handling private void OnMoveAttempt(EntityUid uid, StunnedComponent stunned, UpdateCanMoveEvent args)