diff --git a/Content.Client/Inventory/ClientInventoryComponent.cs b/Content.Client/Inventory/ClientInventoryComponent.cs index 2e53ad3ac9..a4e378b1a7 100644 --- a/Content.Client/Inventory/ClientInventoryComponent.cs +++ b/Content.Client/Inventory/ClientInventoryComponent.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Client.Clothing; using Content.Shared.CharacterAppearance; -using Content.Shared.EffectBlocker; using Content.Shared.Inventory; using Content.Shared.Movement.Components; using Robust.Client.GameObjects; @@ -21,7 +20,7 @@ namespace Content.Client.Inventory /// [RegisterComponent] [ComponentReference(typeof(SharedInventoryComponent))] - public class ClientInventoryComponent : SharedInventoryComponent, IEffectBlocker + public class ClientInventoryComponent : SharedInventoryComponent { private readonly Dictionary _slots = new(); @@ -284,10 +283,5 @@ namespace Content.Client.Inventory return false; } - - bool IEffectBlocker.CanSlip() - { - return !TryGetSlot(Slots.SHOES, out var shoes) || shoes == null || EffectBlockerSystem.CanSlip(shoes); - } } } diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 4a2d71e23b..0d826ccf29 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -1,5 +1,8 @@ using Content.Client.HUD; +using Content.Client.Items.Components; using Content.Shared.Input; +using Content.Shared.Inventory; +using Content.Shared.Slippery; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; @@ -24,6 +27,17 @@ namespace Content.Client.Inventory SubscribeLocalEvent((_, component, _) => component.PlayerAttached()); SubscribeLocalEvent((_, component, _) => component.PlayerDetached()); + + SubscribeLocalEvent(OnSlipAttemptEvent); + } + + // jesus christ, this is duplicated to server/client, should really just be shared.. + private void OnSlipAttemptEvent(EntityUid uid, ClientInventoryComponent component, SlipAttemptEvent args) + { + if (component.TryGetSlot(EquipmentSlotDefines.Slots.SHOES, out IEntity? shoes)) + { + RaiseLocalEvent(shoes.Uid, args, false); + } } public override void Shutdown() diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 4dba1073d7..f28578a252 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -8,9 +8,9 @@ using Content.Shared.Body.Components; using Content.Shared.Body.Part; using Content.Shared.Buckle.Components; using Content.Shared.Coordinates; -using Content.Shared.EffectBlocker; using Content.Shared.Interaction.Events; using Content.Shared.Movement; +using Content.Shared.Standing; using NUnit.Framework; using Robust.Server.Player; using Robust.Shared.GameObjects; @@ -69,7 +69,9 @@ namespace Content.IntegrationTests.Tests.Buckle { var mapManager = IoCManager.Resolve(); var entityManager = IoCManager.Resolve(); + var actionBlocker = EntitySystem.Get(); + var standingState = EntitySystem.Get(); var gridId = new GridId(1); var grid = mapManager.GetGrid(gridId); @@ -85,7 +87,8 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.False(buckle.Buckled); Assert.True(actionBlocker.CanMove(human)); Assert.True(actionBlocker.CanChangeDirection(human)); - Assert.True(EffectBlockerSystem.CanFall(human)); + Assert.True(standingState.Down(human.Uid)); + Assert.True(standingState.Stand(human.Uid)); // Default state, no buckled entities, strap Assert.True(chair.TryGetComponent(out strap)); @@ -102,7 +105,7 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.True(((BuckleComponentState) buckle.GetComponentState(player)).Buckled); Assert.False(actionBlocker.CanMove(human)); Assert.False(actionBlocker.CanChangeDirection(human)); - Assert.False(EffectBlockerSystem.CanFall(human)); + Assert.False(standingState.Down(human.Uid)); Assert.That((human.Transform.WorldPosition - chair.Transform.WorldPosition).Length, Is.LessThanOrEqualTo(buckle.BuckleOffset.Length)); // Side effects of buckling for the strap @@ -125,6 +128,7 @@ namespace Content.IntegrationTests.Tests.Buckle await server.WaitAssertion(() => { var actionBlocker = EntitySystem.Get(); + var standingState = EntitySystem.Get(); // Still buckled Assert.True(buckle.Buckled); @@ -135,7 +139,7 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.False(buckle.Buckled); Assert.True(actionBlocker.CanMove(human)); Assert.True(actionBlocker.CanChangeDirection(human)); - Assert.True(EffectBlockerSystem.CanFall(human)); + Assert.True(standingState.Down(human.Uid)); // Unbuckle, strap Assert.IsEmpty(strap.BuckledEntities); @@ -160,6 +164,7 @@ namespace Content.IntegrationTests.Tests.Buckle await server.WaitAssertion(() => { var actionBlocker = EntitySystem.Get(); + var standingState = EntitySystem.Get(); // Still buckled Assert.True(buckle.Buckled); @@ -192,7 +197,7 @@ namespace Content.IntegrationTests.Tests.Buckle Assert.False(buckle.Buckled); Assert.True(actionBlocker.CanMove(human)); Assert.True(actionBlocker.CanChangeDirection(human)); - Assert.True(EffectBlockerSystem.CanFall(human)); + Assert.True(standingState.Down(human.Uid)); // Re-buckle Assert.True(buckle.TryBuckle(human, chair)); diff --git a/Content.Server/Clothing/MagbootsSystem.cs b/Content.Server/Clothing/MagbootsSystem.cs index cc005a29b1..b46fec5e25 100644 --- a/Content.Server/Clothing/MagbootsSystem.cs +++ b/Content.Server/Clothing/MagbootsSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Clothing.Components; +using Content.Shared.Slippery; using Content.Shared.Verbs; using Robust.Shared.GameObjects; using Robust.Shared.Localization; @@ -12,6 +13,7 @@ namespace Content.Server.Clothing base.Initialize(); SubscribeLocalEvent(AddToggleVerb); + SubscribeLocalEvent(OnSlipAttempt); } private void AddToggleVerb(EntityUid uid, MagbootsComponent component, GetActivationVerbsEvent args) @@ -25,5 +27,13 @@ namespace Content.Server.Clothing // TODO VERB ICON add toggle icon? maybe a computer on/off symbol? args.Verbs.Add(verb); } + + private void OnSlipAttempt(EntityUid uid, MagbootsComponent component, SlipAttemptEvent args) + { + if (component.On) + { + args.Cancel(); + } + } } } diff --git a/Content.Server/Inventory/Components/InventoryComponent.cs b/Content.Server/Inventory/Components/InventoryComponent.cs index b6c56dfeb6..0e7f3e00c8 100644 --- a/Content.Server/Inventory/Components/InventoryComponent.cs +++ b/Content.Server/Inventory/Components/InventoryComponent.cs @@ -10,7 +10,6 @@ using Content.Server.Items; using Content.Server.Storage.Components; using Content.Shared.ActionBlocker; using Content.Shared.Acts; -using Content.Shared.EffectBlocker; using Content.Shared.Inventory; using Content.Shared.Movement.Components; using Content.Shared.Popups; @@ -36,7 +35,7 @@ namespace Content.Server.Inventory.Components { [RegisterComponent] [ComponentReference(typeof(SharedInventoryComponent))] - public class InventoryComponent : SharedInventoryComponent, IExAct, IEffectBlocker + public class InventoryComponent : SharedInventoryComponent, IExAct { [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; @@ -101,11 +100,6 @@ namespace Content.Server.Inventory.Components } } - bool IEffectBlocker.CanSlip() - { - return !TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent? shoes) || EffectBlockerSystem.CanSlip(shoes.Owner); - } - protected override void OnRemove() { var slots = _slotContainers.Keys.ToList(); diff --git a/Content.Server/Inventory/InventorySystem.cs b/Content.Server/Inventory/InventorySystem.cs index 7cbc3ad769..515d328bb3 100644 --- a/Content.Server/Inventory/InventorySystem.cs +++ b/Content.Server/Inventory/InventorySystem.cs @@ -1,5 +1,8 @@ using Content.Server.Atmos; using Content.Server.Inventory.Components; +using Content.Server.Items; +using Content.Shared.Inventory; +using Content.Shared.Slippery; using Content.Shared.Damage; using Robust.Shared.Containers; using Robust.Shared.GameObjects; @@ -17,6 +20,15 @@ namespace Content.Server.Inventory SubscribeLocalEvent(OnHighPressureEvent); SubscribeLocalEvent(OnLowPressureEvent); SubscribeLocalEvent(OnDamageModify); + SubscribeLocalEvent(OnSlipAttemptEvent); + } + + private void OnSlipAttemptEvent(EntityUid uid, InventoryComponent component, SlipAttemptEvent args) + { + if (component.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent? shoes)) + { + RaiseLocalEvent(shoes.Owner.Uid, args, false); + } } private static void HandleInvRemovedFromContainer(EntityUid uid, InventoryComponent component, EntRemovedFromContainerMessage args) diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs index 186d96f17f..bc6f8e14f5 100644 --- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs @@ -1,5 +1,4 @@ using Content.Shared.DragDrop; -using Content.Shared.EffectBlocker; using Content.Shared.Emoting; using Content.Shared.Interaction.Events; using Content.Shared.Inventory.Events; @@ -15,7 +14,6 @@ namespace Content.Shared.ActionBlocker { /// /// Utility methods to check if a specific entity is allowed to perform an action. - /// For effects see /// [UsedImplicitly] public class ActionBlockerSystem : EntitySystem diff --git a/Content.Shared/Buckle/Components/SharedBuckleComponent.cs b/Content.Shared/Buckle/Components/SharedBuckleComponent.cs index 6ee880c22c..3f94cdedb7 100644 --- a/Content.Shared/Buckle/Components/SharedBuckleComponent.cs +++ b/Content.Shared/Buckle/Components/SharedBuckleComponent.cs @@ -1,6 +1,5 @@ using System; using Content.Shared.DragDrop; -using Content.Shared.EffectBlocker; using Content.Shared.Interaction; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; @@ -11,7 +10,7 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.Buckle.Components { [NetworkedComponent()] - public abstract class SharedBuckleComponent : Component, IEffectBlocker, IDraggable + public abstract class SharedBuckleComponent : Component, IDraggable { public sealed override string Name => "Buckle"; @@ -35,8 +34,6 @@ namespace Content.Shared.Buckle.Components public abstract bool TryBuckle(IEntity? user, IEntity to); - bool IEffectBlocker.CanFall() => !Buckled; - bool IDraggable.CanDrop(CanDropEvent args) { return args.Target.HasComponent(); diff --git a/Content.Shared/EffectBlocker/EffectBlockerExtensions.cs b/Content.Shared/EffectBlocker/EffectBlockerExtensions.cs deleted file mode 100644 index ae1c6abe99..0000000000 --- a/Content.Shared/EffectBlocker/EffectBlockerExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Robust.Shared.GameObjects; - -namespace Content.Shared.EffectBlocker -{ - public static class EffectBlockerExtensions - { - public static bool CanFall(this IEntity entity) - { - return EffectBlockerSystem.CanFall(entity); - } - - public static bool CanSlip(this IEntity entity) - { - return EffectBlockerSystem.CanSlip(entity); - } - } -} diff --git a/Content.Shared/EffectBlocker/EffectBlockerSystem.cs b/Content.Shared/EffectBlocker/EffectBlockerSystem.cs deleted file mode 100644 index 0d80537800..0000000000 --- a/Content.Shared/EffectBlocker/EffectBlockerSystem.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Content.Shared.ActionBlocker; -using JetBrains.Annotations; -using Robust.Shared.GameObjects; - -namespace Content.Shared.EffectBlocker -{ - /// - /// Utility methods to check if an effect is allowed to affect a specific entity. - /// For actions see - /// - [UsedImplicitly] - public class EffectBlockerSystem : EntitySystem - { - // TODO: Make these methods not static. Maybe move them to their relevant EntitySystems? - // TODO: Add EntityUid overloads. - - public static bool CanFall(IEntity entity) - { - var canFall = true; - - foreach (var blocker in entity.GetAllComponents()) - { - canFall &= blocker.CanFall(); // Sets var to false if false - } - - return canFall; - } - - public static bool CanSlip(IEntity entity) - { - var canSlip = true; - - foreach (var blocker in entity.GetAllComponents()) - { - canSlip &= blocker.CanSlip(); // Sets var to false if false - } - - return canSlip; - } - } -} diff --git a/Content.Shared/EffectBlocker/IEffectBlocker.cs b/Content.Shared/EffectBlocker/IEffectBlocker.cs deleted file mode 100644 index 6f1ce4b541..0000000000 --- a/Content.Shared/EffectBlocker/IEffectBlocker.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Content.Shared.ActionBlocker; - -namespace Content.Shared.EffectBlocker -{ - /// - /// This interface gives components the ability to block certain effects - /// from affecting the owning entity. - /// - public interface IEffectBlocker - { - bool CanFall() => true; - bool CanSlip() => true; - } -} diff --git a/Content.Shared/Slippery/NoSlipComponent.cs b/Content.Shared/Slippery/NoSlipComponent.cs index 1c924f1873..3ec6c91af1 100644 --- a/Content.Shared/Slippery/NoSlipComponent.cs +++ b/Content.Shared/Slippery/NoSlipComponent.cs @@ -1,13 +1,10 @@ -using Content.Shared.EffectBlocker; using Robust.Shared.GameObjects; namespace Content.Shared.Slippery { [RegisterComponent] - public class NoSlipComponent : Component, IEffectBlocker + public class NoSlipComponent : Component { public override string Name => "NoSlip"; - - bool IEffectBlocker.CanSlip() => false; } } diff --git a/Content.Shared/Slippery/SharedSlipperySystem.cs b/Content.Shared/Slippery/SharedSlipperySystem.cs index 97fb9a9127..26c1b5e796 100644 --- a/Content.Shared/Slippery/SharedSlipperySystem.cs +++ b/Content.Shared/Slippery/SharedSlipperySystem.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Content.Shared.EffectBlocker; using Content.Shared.StatusEffect; using Content.Shared.Stunnable; using JetBrains.Annotations; @@ -26,6 +25,7 @@ namespace Content.Shared.Slippery { base.Initialize(); SubscribeLocalEvent(HandleCollide); + SubscribeLocalEvent(OnNoSlipAttempt); } private void HandleCollide(EntityUid uid, SlipperyComponent component, StartCollideEvent args) @@ -40,6 +40,11 @@ namespace Content.Shared.Slippery component.Colliding.Add(otherUid); } + private void OnNoSlipAttempt(EntityUid uid, NoSlipComponent component, SlipAttemptEvent args) + { + args.Cancel(); + } + /// public override void Update(float frameTime) { @@ -80,10 +85,10 @@ namespace Content.Shared.Slippery return false; } - if (!EffectBlockerSystem.CanSlip(otherBody.Owner)) - { + var ev = new SlipAttemptEvent(); + RaiseLocalEvent(otherBody.Owner.Uid, ev, false); + if (ev.Cancelled) return false; - } otherBody.LinearVelocity *= component.LaunchForwardsMultiplier; @@ -136,4 +141,11 @@ namespace Content.Shared.Slippery return false; } } + + /// + /// Raised on an entity to determine if it can slip or not. + /// + public class SlipAttemptEvent : CancellableEntityEventArgs + { + } } diff --git a/Content.Shared/Slippery/SlipperyComponent.cs b/Content.Shared/Slippery/SlipperyComponent.cs index 1cc3142534..da92da0886 100644 --- a/Content.Shared/Slippery/SlipperyComponent.cs +++ b/Content.Shared/Slippery/SlipperyComponent.cs @@ -20,7 +20,7 @@ namespace Content.Shared.Slippery private float _paralyzeTime = 3f; private float _intersectPercentage = 0.3f; - private float _requiredSlipSpeed = 0.1f; + private float _requiredSlipSpeed = 5f; private float _launchForwardsMultiplier = 1f; private bool _slippery = true; private SoundSpecifier _slipSound = new SoundPathSpecifier("/Audio/Effects/slip.ogg"); diff --git a/Content.Shared/Standing/StandingStateComponent.cs b/Content.Shared/Standing/StandingStateComponent.cs index cd246587cf..f20afe5546 100644 --- a/Content.Shared/Standing/StandingStateComponent.cs +++ b/Content.Shared/Standing/StandingStateComponent.cs @@ -1,5 +1,4 @@ using System; -using Content.Shared.EffectBlocker; using Content.Shared.Sound; using Robust.Shared.Analyzers; using Robust.Shared.GameObjects; @@ -13,7 +12,7 @@ namespace Content.Shared.Standing { [Friend(typeof(StandingStateSystem))] [RegisterComponent, NetworkedComponent] - public sealed class StandingStateComponent : Component, IEffectBlocker + public sealed class StandingStateComponent : Component { public override string Name => "StandingState"; @@ -25,8 +24,6 @@ namespace Content.Shared.Standing [DataField("standing")] public bool Standing { get; set; } = true; - public bool CanFall() => Standing; - public override ComponentState GetComponentState(ICommonSession player) { return new StandingComponentState(Standing); diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index 69a594bab6..14f1907976 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -37,7 +37,7 @@ - type: entity parent: ClothingShoesBase id: ClothingShoesGaloshes - name: galoshes shoes + name: galoshes description: Rubber boots. components: - type: Sprite