diff --git a/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs deleted file mode 100644 index 636595ca4c..0000000000 --- a/Content.Client/GameObjects/Components/Movement/SlipperyComponent.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Shared.GameObjects.Components.Movement; -using Robust.Shared.GameObjects; - -namespace Content.Client.GameObjects.Components.Movement -{ - [RegisterComponent] - [ComponentReference(typeof(SharedSlipperyComponent))] - public class SlipperyComponent : SharedSlipperyComponent - { - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) - { - base.HandleComponentState(curState, nextState); - - if (curState is not SlipperyComponentState state) return; - - _slippery = state.Slippery; - _intersectPercentage = state.IntersectPercentage; - _paralyzeTime = state.ParalyzeTime; - _requiredSlipSpeed = state.RequiredSlipSpeed; - _launchForwardsMultiplier = state.LaunchForwardsMultiplier; - } - } -} diff --git a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs index f54cba13ba..76a0179de0 100644 --- a/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/SpillTileReaction.cs @@ -1,6 +1,7 @@ using Content.Server.GameObjects.Components.Fluids; using Content.Server.GameObjects.Components.Movement; using Content.Shared.Chemistry; +using Content.Shared.GameObjects.Components.Movement; using Content.Shared.Interfaces.Chemistry; using JetBrains.Annotations; using Robust.Shared.Map; diff --git a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs index cffa60c3e4..2e6076e95c 100644 --- a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs @@ -5,6 +5,7 @@ using System.Threading; using Content.Server.GameObjects.Components.Chemistry; using Content.Server.GameObjects.Components.Movement; using Content.Shared.Chemistry; +using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Maps; using Content.Shared.Physics; diff --git a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs deleted file mode 100644 index 98ec258aa6..0000000000 --- a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Shared.Audio; -using Content.Shared.GameObjects.Components.Movement; -using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.Players; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; - -namespace Content.Server.GameObjects.Components.Movement -{ - [RegisterComponent] - [ComponentReference(typeof(SharedSlipperyComponent))] - public class SlipperyComponent : SharedSlipperyComponent - { - /// - /// Path to the sound to be played when a mob slips. - /// - [ViewVariables] - [DataField("slipSound")] - public string SlipSound { get; set; } = "/Audio/Effects/slip.ogg"; - - protected override void OnSlip() - { - if (!string.IsNullOrEmpty(SlipSound)) - { - EntitySystem.Get() - .PlayFromEntity(SlipSound, Owner, AudioHelpers.WithVariation(0.2f)); - } - } - - public override ComponentState GetComponentState(ICommonSession player) - { - return new SlipperyComponentState(ParalyzeTime, IntersectPercentage, RequiredSlipSpeed, LaunchForwardsMultiplier, Slippery); - } - } -} diff --git a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs b/Content.Shared/GameObjects/Components/Movement/SlipperyComponent.cs similarity index 63% rename from Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs rename to Content.Shared/GameObjects/Components/Movement/SlipperyComponent.cs index 64619da459..565a64537c 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SlipperyComponent.cs @@ -2,35 +2,67 @@ using System; using System.Collections.Generic; using System.Linq; +using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems.EffectBlocker; -using Content.Shared.Physics; +using Content.Shared.Interfaces; +using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision; +using Robust.Shared.Player; +using Robust.Shared.Players; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Shared.GameObjects.Components.Movement { - public abstract class SharedSlipperyComponent : Component, IStartCollide + [RegisterComponent] + public class SlipperyComponent : Component, IStartCollide { - public sealed override string Name => "Slippery"; + [Dependency] private IModuleManager _moduleManager = default!; - protected float _paralyzeTime = 3f; - protected float _intersectPercentage = 0.3f; - protected float _requiredSlipSpeed = 0.1f; - protected float _launchForwardsMultiplier = 1f; - protected bool _slippery = true; + public sealed override string Name => "Slippery"; + public override uint? NetID => ContentNetIDs.SLIP; + + private float _paralyzeTime = 3f; + private float _intersectPercentage = 0.3f; + private float _requiredSlipSpeed = 0.1f; + private float _launchForwardsMultiplier = 1f; + private bool _slippery = true; + private string _slipSound = "/Audio/Effects/slip.ogg"; /// - /// The list of entities that have been slipped by this component, - /// and which have not stopped colliding with its owner yet. + /// List of entities that are currently colliding with the entity. /// - protected readonly List _slipped = new(); + private readonly HashSet _colliding = new(); + + /// + /// The list of entities that have been slipped by this component, which shouldn't be slipped again. + /// + private readonly HashSet _slipped = new(); + + /// + /// Path to the sound to be played when a mob slips. + /// + [ViewVariables] + [DataField("slipSound")] + public string SlipSound + { + get => _slipSound; + set + { + if (value == _slipSound) + return; + + _slipSound = value; + Dirty(); + } + } /// /// How many seconds the mob will be paralyzed for. @@ -148,17 +180,19 @@ namespace Content.Shared.GameObjects.Components.Movement stun.Paralyze(5); _slipped.Add(otherBody.Entity.Uid); + Dirty(); - OnSlip(); + if (!string.IsNullOrEmpty(SlipSound) && _moduleManager.IsServerModule) + { + SoundSystem.Play(Filter.Broadcast(), SlipSound, Owner, AudioHelpers.WithVariation(0.2f)); + } return true; } - protected virtual void OnSlip() { } - void IStartCollide.CollideWith(IPhysBody ourBody, IPhysBody otherBody, in Manifold manifold) { - TrySlip(ourBody, otherBody); + _colliding.Add(otherBody.Owner.Uid); } public void Update() @@ -166,11 +200,13 @@ namespace Content.Shared.GameObjects.Components.Movement if (!Slippery) return; - foreach (var uid in _slipped.ToArray()) + foreach (var uid in _colliding.ToArray()) { if (!uid.IsValid() || !Owner.EntityManager.EntityExists(uid)) { + _colliding.Remove(uid); _slipped.Remove(uid); + Dirty(); continue; } @@ -180,8 +216,37 @@ namespace Content.Shared.GameObjects.Components.Movement if (!physics.GetWorldAABB().Intersects(otherPhysics.GetWorldAABB())) { + _colliding.Remove(uid); _slipped.Remove(uid); + Dirty(); + continue; } + + if (!_slipped.Contains(uid)) + TrySlip(physics, otherPhysics); + } + } + + public override ComponentState GetComponentState(ICommonSession player) + { + return new SlipperyComponentState(ParalyzeTime, IntersectPercentage, RequiredSlipSpeed, LaunchForwardsMultiplier, Slippery, SlipSound, _slipped.ToArray()); + } + + public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) + { + if (curState is not SlipperyComponentState state) return; + + _slippery = state.Slippery; + _intersectPercentage = state.IntersectPercentage; + _paralyzeTime = state.ParalyzeTime; + _requiredSlipSpeed = state.RequiredSlipSpeed; + _launchForwardsMultiplier = state.LaunchForwardsMultiplier; + _slipSound = state.SlipSound; + _slipped.Clear(); + + foreach (var slipped in state.Slipped) + { + _slipped.Add(slipped); } } } @@ -194,14 +259,18 @@ namespace Content.Shared.GameObjects.Components.Movement public float RequiredSlipSpeed { get; } public float LaunchForwardsMultiplier { get; } public bool Slippery { get; } + public string SlipSound { get; } + public readonly EntityUid[] Slipped; - public SlipperyComponentState(float paralyzeTime, float intersectPercentage, float requiredSlipSpeed, float launchForwardsMultiplier, bool slippery) : base(ContentNetIDs.SLIP) + public SlipperyComponentState(float paralyzeTime, float intersectPercentage, float requiredSlipSpeed, float launchForwardsMultiplier, bool slippery, string slipSound, EntityUid[] slipped) : base(ContentNetIDs.SLIP) { ParalyzeTime = paralyzeTime; IntersectPercentage = intersectPercentage; RequiredSlipSpeed = requiredSlipSpeed; LaunchForwardsMultiplier = launchForwardsMultiplier; Slippery = slippery; + SlipSound = slipSound; + Slipped = slipped; } } } diff --git a/Content.Shared/GameObjects/EntitySystems/SlipperySystem.cs b/Content.Shared/GameObjects/EntitySystems/SlipperySystem.cs index 367835df15..dd6feabd28 100644 --- a/Content.Shared/GameObjects/EntitySystems/SlipperySystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SlipperySystem.cs @@ -11,7 +11,7 @@ namespace Content.Shared.GameObjects.EntitySystems /// public override void Update(float frameTime) { - foreach (var slipperyComp in ComponentManager.EntityQuery(true)) + foreach (var slipperyComp in ComponentManager.EntityQuery(false)) { slipperyComp.Update(); }