]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Toilet Upgrade (needs review) (#22133)
authorbrainfood1183 <113240905+brainfood1183@users.noreply.github.com>
Sun, 31 Mar 2024 03:21:18 +0000 (04:21 +0100)
committerGitHub <noreply@github.com>
Sun, 31 Mar 2024 03:21:18 +0000 (14:21 +1100)
* Toilet Draft

* fixes

* toilets now have secret stash to place items in cistern.

* fixes

* plungers now unblock toilets.

* fix sprite

* new sprites and fix

* fixes

* improve seat sprites.

* fix

* removed visualisersystem changed to genericvisualizers

* flush sound for toilets and copyright for toilet sprites.

* fix atrributions

* fixes

* fix datafield flushtime

* sprite improvements

* fixes

* multiple changes

* fix

* fix

* fixes remove vv

* moved stash related functions to secret stash system from toilet.

* fix

* fix

* changes for recent review.

* fix

* fix

51 files changed:
Content.Client/Disposal/Systems/DisposalUnitSystem.cs
Content.Client/Toilet/ToiletVisualsSystem.cs [deleted file]
Content.Server/Construction/Conditions/ToiletLidClosed.cs [deleted file]
Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs
Content.Server/Resist/EscapeInventorySystem.cs
Content.Server/Storage/Components/SecretStashComponent.cs [deleted file]
Content.Server/Toilet/ToiletSystem.cs
Content.Shared/Buckle/Components/StrapComponent.cs
Content.Shared/Buckle/SharedBuckleSystem.Buckle.cs
Content.Shared/Disposal/Components/SharedDisposalUnitComponent.cs
Content.Shared/Disposal/SharedDisposalUnitSystem.cs
Content.Shared/Plants/PottedPlantHideComponent.cs [moved from Content.Server/Plants/Components/PottedPlantHideComponent.cs with 80% similarity]
Content.Shared/Plants/PottedPlantHideSystem.cs [moved from Content.Server/Plants/Systems/PottedPlantHideSystem.cs with 86% similarity]
Content.Shared/Plunger/Components/PlungerComponent.cs [new file with mode: 0644]
Content.Shared/Plunger/Components/PlungerUseComponent.cs [new file with mode: 0644]
Content.Shared/Plunger/PlungerDoAfterEvent.cs [new file with mode: 0644]
Content.Shared/Plunger/Systems/PlungerSystem.cs [new file with mode: 0644]
Content.Shared/Storage/Components/SecretStashComponent.cs [new file with mode: 0644]
Content.Shared/Storage/EntitySystems/SecretStashSystem.cs [moved from Content.Server/Storage/EntitySystems/SecretStashSystem.cs with 55% similarity]
Content.Shared/Toilet/Components/ToiletComponent.cs [new file with mode: 0644]
Content.Shared/Toilet/Systems/SharedToiletSystem.cs [new file with mode: 0644]
Content.Shared/Toilet/ToiletComponent.cs [deleted file]
Content.Shared/Toilet/ToiletVisuals.cs [deleted file]
Resources/Audio/Effects/Fluids/attributions.yml
Resources/Audio/Effects/Fluids/flush.ogg [new file with mode: 0644]
Resources/Audio/Effects/Fluids/splash.ogg [new file with mode: 0644]
Resources/Audio/Weapons/glug.ogg [new file with mode: 0644]
Resources/Locale/en-US/storage/components/secret-stash-component.ftl
Resources/Locale/en-US/toilet/toilet-component.ftl
Resources/Prototypes/Entities/Objects/Specific/Janitorial/janitor.yml
Resources/Prototypes/Entities/Structures/Furniture/toilet.yml
Resources/Prototypes/Entities/Structures/Piping/Disposal/units.yml
Resources/Prototypes/Recipes/Construction/Graphs/furniture/toilet.yml
Resources/Prototypes/Recipes/Construction/furniture.yml
Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_down.png [deleted file]
Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_up.png [deleted file]
Resources/Textures/Structures/Furniture/toilet.rsi/condisposal.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-charging.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-closed.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-down.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-flush.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-open.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal-up.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/disposal.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/dispover-charge.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/dispover-full.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/dispover-handle.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/dispover-ready.png [new file with mode: 0644]
Resources/Textures/Structures/Furniture/toilet.rsi/meta.json
Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_down.png [deleted file]
Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_up.png [deleted file]

index 8c40c78421991320696cd77b4c41750045757b39..b9e4a3866045e3f4755f3ab7149f808ec16d29cc 100644 (file)
@@ -96,24 +96,22 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
     private void UpdateState(EntityUid uid, SharedDisposalUnitComponent unit, SpriteComponent sprite, AppearanceComponent appearance)
     {
         if (!_appearanceSystem.TryGetData<VisualState>(uid, Visuals.VisualState, out var state, appearance))
-        {
             return;
-        }
 
         sprite.LayerSetVisible(DisposalUnitVisualLayers.Unanchored, state == VisualState.UnAnchored);
         sprite.LayerSetVisible(DisposalUnitVisualLayers.Base, state == VisualState.Anchored);
-        sprite.LayerSetVisible(DisposalUnitVisualLayers.BaseFlush, state is VisualState.Flushing or VisualState.Charging);
+        sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayFlush, state is VisualState.OverlayFlushing or VisualState.OverlayCharging);
 
         var chargingState = sprite.LayerMapTryGet(DisposalUnitVisualLayers.BaseCharging, out var chargingLayer)
             ? sprite.LayerGetState(chargingLayer)
             : new RSI.StateId(DefaultChargeState);
 
         // This is a transient state so not too worried about replaying in range.
-        if (state == VisualState.Flushing)
+        if (state == VisualState.OverlayFlushing)
         {
             if (!_animationSystem.HasRunningAnimation(uid, AnimationKey))
             {
-                var flushState = sprite.LayerMapTryGet(DisposalUnitVisualLayers.BaseFlush, out var flushLayer)
+                var flushState = sprite.LayerMapTryGet(DisposalUnitVisualLayers.OverlayFlush, out var flushLayer)
                     ? sprite.LayerGetState(flushLayer)
                     : new RSI.StateId(DefaultFlushState);
 
@@ -125,7 +123,7 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
                     {
                         new AnimationTrackSpriteFlick
                         {
-                            LayerKey = DisposalUnitVisualLayers.BaseFlush,
+                            LayerKey = DisposalUnitVisualLayers.OverlayFlush,
                             KeyFrames =
                             {
                                 // Play the flush animation
@@ -154,26 +152,18 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
                 _animationSystem.Play(uid, anim, AnimationKey);
             }
         }
-        else if (state == VisualState.Charging)
-        {
-            sprite.LayerSetState(DisposalUnitVisualLayers.BaseFlush, chargingState);
-        }
+        else if (state == VisualState.OverlayCharging)
+            sprite.LayerSetState(DisposalUnitVisualLayers.OverlayFlush, new RSI.StateId("disposal-charging"));
         else
-        {
             _animationSystem.Stop(uid, AnimationKey);
-        }
 
         if (!_appearanceSystem.TryGetData<HandleState>(uid, Visuals.Handle, out var handleState, appearance))
-        {
             handleState = HandleState.Normal;
-        }
 
         sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayEngaged, handleState != HandleState.Normal);
 
         if (!_appearanceSystem.TryGetData<LightStates>(uid, Visuals.Light, out var lightState, appearance))
-        {
             lightState = LightStates.Off;
-        }
 
         sprite.LayerSetVisible(DisposalUnitVisualLayers.OverlayCharging,
                 (lightState & LightStates.Charging) != 0);
@@ -189,7 +179,7 @@ public enum DisposalUnitVisualLayers : byte
     Unanchored,
     Base,
     BaseCharging,
-    BaseFlush,
+    OverlayFlush,
     OverlayCharging,
     OverlayReady,
     OverlayFull,
diff --git a/Content.Client/Toilet/ToiletVisualsSystem.cs b/Content.Client/Toilet/ToiletVisualsSystem.cs
deleted file mode 100644 (file)
index 5367772..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-using Content.Shared.Toilet;
-using Robust.Client.GameObjects;
-
-namespace Content.Client.Toilet;
-
-public sealed class ToiletVisualsSystem : VisualizerSystem<ToiletComponent>
-{
-    protected override void OnAppearanceChange(EntityUid uid, ToiletComponent component, ref AppearanceChangeEvent args)
-    {
-        if (args.Sprite == null) return;
-
-        AppearanceSystem.TryGetData<bool>(uid, ToiletVisuals.LidOpen, out var lidOpen, args.Component);
-        AppearanceSystem.TryGetData<bool>(uid, ToiletVisuals.SeatUp, out var seatUp, args.Component);
-
-        var state = (lidOpen, seatUp) switch
-        {
-            (false, false) => "closed_toilet_seat_down",
-            (false, true) => "closed_toilet_seat_up",
-            (true, false) => "open_toilet_seat_down",
-            (true, true) => "open_toilet_seat_up"
-        };
-
-        args.Sprite.LayerSetState(0, state);
-    }
-}
diff --git a/Content.Server/Construction/Conditions/ToiletLidClosed.cs b/Content.Server/Construction/Conditions/ToiletLidClosed.cs
deleted file mode 100644 (file)
index 40a3be0..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-using Content.Shared.Construction;
-using Content.Shared.Examine;
-using Content.Shared.Toilet;
-using JetBrains.Annotations;
-
-namespace Content.Server.Construction.Conditions
-{
-    [UsedImplicitly]
-    [DataDefinition]
-    public sealed partial class ToiletLidClosed : IGraphCondition
-    {
-        public bool Condition(EntityUid uid, IEntityManager entityManager)
-        {
-            if (!entityManager.TryGetComponent(uid, out ToiletComponent? toilet))
-                return false;
-
-            return !toilet.LidOpen;
-        }
-
-        public bool DoExamine(ExaminedEvent args)
-        {
-            var entity = args.Examined;
-
-            if (!IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out ToiletComponent? toilet)) return false;
-            if (!toilet.LidOpen) return false;
-
-            args.PushMarkup(Loc.GetString("construction-examine-condition-toilet-lid-closed") + "\n");
-            return true;
-        }
-
-        public IEnumerable<ConstructionGuideEntry> GenerateGuideEntry()
-        {
-            yield return new ConstructionGuideEntry()
-            {
-                Localization = "construction-step-condition-toilet-lid-closed"
-            };
-        }
-    }
-}
index a03ba5d23136808b05498810117a62a9ef1a25e3..8a7ea438be20fc8eb1cbd70d4f45fd379097387d 100644 (file)
@@ -135,8 +135,7 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
     {
         // This is not an interaction, activation, or alternative verb type because unfortunately most users are
         // unwilling to accept that this is where they belong and don't want to accidentally climb inside.
-        if (!component.MobsCanEnter ||
-            !args.CanAccess ||
+        if (!args.CanAccess ||
             !args.CanInteract ||
             component.Container.ContainedEntities.Contains(args.User) ||
             !_actionBlockerSystem.CanMove(args.User))
@@ -630,10 +629,10 @@ public sealed class DisposalUnitSystem : SharedDisposalUnitSystem
         switch (state)
         {
             case DisposalsPressureState.Flushed:
-                _appearance.SetData(uid, SharedDisposalUnitComponent.Visuals.VisualState, SharedDisposalUnitComponent.VisualState.Flushing, appearance);
+                _appearance.SetData(uid, SharedDisposalUnitComponent.Visuals.VisualState, SharedDisposalUnitComponent.VisualState.OverlayFlushing, appearance);
                 break;
             case DisposalsPressureState.Pressurizing:
-                _appearance.SetData(uid, SharedDisposalUnitComponent.Visuals.VisualState, SharedDisposalUnitComponent.VisualState.Charging, appearance);
+                _appearance.SetData(uid, SharedDisposalUnitComponent.Visuals.VisualState, SharedDisposalUnitComponent.VisualState.OverlayCharging, appearance);
                 break;
             case DisposalsPressureState.Ready:
                 _appearance.SetData(uid, SharedDisposalUnitComponent.Visuals.VisualState, SharedDisposalUnitComponent.VisualState.Anchored, appearance);
index 6bce38fbacffa76d5dd28915cd7e81b9c8b71b1d..35c7d0bc65b0bfadaa091963299edb265c6b5fbd 100644 (file)
@@ -1,5 +1,5 @@
 using Content.Server.Popups;
-using Content.Server.Storage.Components;
+using Content.Shared.Storage.Components;
 using Content.Shared.ActionBlocker;
 using Content.Shared.DoAfter;
 using Content.Shared.Hands.EntitySystems;
diff --git a/Content.Server/Storage/Components/SecretStashComponent.cs b/Content.Server/Storage/Components/SecretStashComponent.cs
deleted file mode 100644 (file)
index a63cb07..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-using Content.Server.Storage.EntitySystems;
-using Content.Shared.Containers.ItemSlots;
-using Content.Shared.Item;
-using Content.Shared.Toilet;
-using Robust.Shared.Containers;
-using Robust.Shared.Prototypes;
-
-namespace Content.Server.Storage.Components
-{
-    /// <summary>
-    ///     Logic for a secret slot stash, like plant pot or toilet cistern.
-    ///     Unlike <see cref="ItemSlotsComponent"/> it doesn't have interaction logic or verbs.
-    ///     Other classes like <see cref="ToiletComponent"/> should implement it.
-    /// </summary>
-    [RegisterComponent]
-    [Access(typeof(SecretStashSystem))]
-    public sealed partial class SecretStashComponent : Component
-    {
-        /// <summary>
-        ///     Max item size that can be fitted into secret stash.
-        /// </summary>
-        [DataField("maxItemSize")]
-        public ProtoId<ItemSizePrototype> MaxItemSize = "Small";
-
-        /// <summary>
-        ///     IC secret stash name. For example "the toilet cistern".
-        ///     If empty string, will replace it with entity name in init.
-        /// </summary>
-        [DataField("secretPartName", readOnly: true)]
-        public string SecretPartName { get; set; } = "";
-
-        /// <summary>
-        ///     Container used to keep secret stash item.
-        /// </summary>
-        [ViewVariables]
-        public ContainerSlot ItemContainer = default!;
-
-    }
-}
index 8bf8457e075b3e39b199fc03a0eb2800e6dee8a4..e184ddf0d5b8fdc67da6ed869d25fcf8a488b051 100644 (file)
@@ -1,197 +1,8 @@
-using Content.Server.Body.Systems;
-using Content.Shared.Buckle;
-using Content.Server.Popups;
-using Content.Server.Storage.Components;
-using Content.Server.Storage.EntitySystems;
-using Content.Shared.Audio;
-using Content.Shared.Body.Components;
-using Content.Shared.Body.Part;
-using Content.Shared.Buckle.Components;
-using Content.Shared.Examine;
-using Content.Shared.IdentityManagement;
-using Content.Shared.Interaction;
-using Content.Shared.Interaction.Events;
-using Content.Shared.Popups;
-using Content.Shared.Toilet;
-using Content.Shared.Tools;
-using Content.Shared.Tools.Components;
-using Content.Shared.Verbs;
-using Robust.Shared.Audio;
-using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
-using Robust.Shared.Random;
-using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem;
+using Content.Shared.Toilet.Systems;
 
-namespace Content.Server.Toilet
-{
-    public sealed class ToiletSystem : EntitySystem
-    {
-        [Dependency] private readonly IRobustRandom _random = default!;
-        [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
-        [Dependency] private readonly BodySystem _body = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly SecretStashSystem _secretStash = default!;
-        [Dependency] private readonly PopupSystem _popup = default!;
-        [Dependency] private readonly SharedToolSystem _tool = default!;
-
-        public override void Initialize()
-        {
-            base.Initialize();
-            SubscribeLocalEvent<ToiletComponent, ComponentInit>(OnInit);
-            SubscribeLocalEvent<ToiletComponent, MapInitEvent>(OnMapInit);
-            SubscribeLocalEvent<ToiletComponent, InteractUsingEvent>(OnInteractUsing);
-            SubscribeLocalEvent<ToiletComponent, InteractHandEvent>(OnInteractHand);
-            SubscribeLocalEvent<ToiletComponent, ExaminedEvent>(OnExamine);
-            SubscribeLocalEvent<ToiletComponent, SuicideEvent>(OnSuicide);
-            SubscribeLocalEvent<ToiletComponent, ToiletPryDoAfterEvent>(OnToiletPried);
-            SubscribeLocalEvent<ToiletComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleSeatVerb);
-        }
-
-        private void OnSuicide(EntityUid uid, ToiletComponent component, SuicideEvent args)
-        {
-            if (args.Handled)
-                return;
-
-            // Check that victim has a head
-            // FIXME: since suiciding turns you into a ghost immediately, both messages are seen, not sure how this can be fixed
-            if (TryComp<BodyComponent>(args.Victim, out var body) &&
-                _body.BodyHasPartType(args.Victim, BodyPartType.Head, body))
-            {
-                var othersMessage = Loc.GetString("toilet-component-suicide-head-message-others",
-                    ("victim", Identity.Entity(args.Victim, EntityManager)), ("owner", uid));
-                _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(args.Victim), true, PopupType.MediumCaution);
-
-                var selfMessage = Loc.GetString("toilet-component-suicide-head-message",
-                    ("owner", uid));
-                _popup.PopupEntity(selfMessage, uid, args.Victim, PopupType.LargeCaution);
-
-                args.SetHandled(SuicideKind.Asphyxiation);
-            }
-            else
-            {
-                var othersMessage = Loc.GetString("toilet-component-suicide-message-others",
-                    ("victim", Identity.Entity(args.Victim, EntityManager)), ("owner", uid));
-                _popup.PopupEntity(othersMessage, uid, Filter.PvsExcept(uid), true, PopupType.MediumCaution);
-
-                var selfMessage = Loc.GetString("toilet-component-suicide-message",
-                    ("owner", uid));
-                _popup.PopupEntity(selfMessage, uid, args.Victim, PopupType.LargeCaution);
-
-                args.SetHandled(SuicideKind.Blunt);
-            }
-        }
-
-        private void OnInit(EntityUid uid, ToiletComponent component, ComponentInit args)
-        {
-            EnsureComp<SecretStashComponent>(uid);
-        }
-
-        private void OnMapInit(EntityUid uid, ToiletComponent component, MapInitEvent args)
-        {
-            // roll is toilet seat will be up or down
-            component.IsSeatUp = _random.Prob(0.5f);
-            UpdateSprite(uid, component);
-        }
-
-        private void OnInteractUsing(EntityUid uid, ToiletComponent component, InteractUsingEvent args)
-        {
-            if (args.Handled)
-                return;
-
-            // are player trying place or lift of cistern lid?
-            if (_tool.UseTool(args.Used, args.User, uid, component.PryLidTime, component.PryingQuality, new ToiletPryDoAfterEvent()))
-            {
-                args.Handled = true;
-            }
-            // maybe player trying to hide something inside cistern?
-            else if (component.LidOpen)
-            {
-                args.Handled = true;
-                _secretStash.TryHideItem(uid, args.User, args.Used);
-            }
-        }
-
-        private void OnInteractHand(EntityUid uid, ToiletComponent component, InteractHandEvent args)
-        {
-            if (args.Handled)
-                return;
+namespace Content.Server.Toilet;
 
-            // trying get something from stash?
-            if (component.LidOpen)
-            {
-                var gotItem = _secretStash.TryGetItem(uid, args.User);
-                if (gotItem)
-                {
-                    args.Handled = true;
-                    return;
-                }
-            }
-
-            args.Handled = true;
-        }
-
-        private void OnToggleSeatVerb(EntityUid uid, ToiletComponent component, GetVerbsEvent<AlternativeVerb> args)
-        {
-            if (!args.CanInteract || !args.CanAccess || !CanToggle(uid))
-                return;
-
-            var alterToiletSeatText = component.IsSeatUp ? Loc.GetString("toilet-seat-close") : Loc.GetString("toilet-seat-open");
-
-            var verb = new AlternativeVerb()
-            {
-                Act = () => {
-                    if (CanToggle(uid))
-                        ToggleToiletSeat(uid, component);
-                },
-                Text = alterToiletSeatText
-            };
-
-            args.Verbs.Add(verb);
-        }
-
-        private void OnExamine(EntityUid uid, ToiletComponent component, ExaminedEvent args)
-        {
-            if (args.IsInDetailsRange && component.LidOpen)
-            {
-                if (_secretStash.HasItemInside(uid))
-                {
-                    var msg = Loc.GetString("toilet-component-on-examine-found-hidden-item");
-                    args.PushMarkup(msg);
-                }
-            }
-        }
-
-        private void OnToiletPried(EntityUid uid, ToiletComponent toilet, ToiletPryDoAfterEvent args)
-        {
-            if (args.Cancelled)
-                return;
-
-            toilet.LidOpen = !toilet.LidOpen;
-            UpdateSprite(uid, toilet);
-        }
-
-        public bool CanToggle(EntityUid uid)
-        {
-            return TryComp<StrapComponent>(uid, out var strap) && strap.BuckledEntities.Count == 0;
-        }
-
-        public void ToggleToiletSeat(EntityUid uid, ToiletComponent? component = null)
-        {
-            if (!Resolve(uid, ref component))
-                return;
-
-            component.IsSeatUp = !component.IsSeatUp;
-            _audio.PlayPvs(component.ToggleSound, uid, AudioParams.Default.WithVariation(SharedContentAudioSystem.DefaultVariation));
-            UpdateSprite(uid, component);
-        }
-
-        private void UpdateSprite(EntityUid uid, ToiletComponent component)
-        {
-            if (!TryComp<AppearanceComponent>(uid, out var appearance))
-                return;
+public sealed class ToiletSystem : SharedToiletSystem
+{
 
-            _appearance.SetData(uid, ToiletVisuals.LidOpen, component.LidOpen, appearance);
-            _appearance.SetData(uid, ToiletVisuals.SeatUp, component.IsSeatUp, appearance);
-        }
-    }
 }
index f25e1b0374164a5740f267c833d3cebfebca9eca..72c92ebf84b926d87d8b085017d1f005c14bfa4c 100644 (file)
@@ -22,9 +22,14 @@ public sealed partial class StrapComponent : Component
     /// Entities that this strap accepts and can buckle
     /// If null it accepts any entity
     /// </summary>
-    [DataField]
-    [ViewVariables]
-    public EntityWhitelist? AllowedEntities;
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public EntityWhitelist? Whitelist;
+
+    /// <summary>
+    /// Entities that this strap does not accept and cannot buckle.
+    /// </summary>
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public EntityWhitelist? Blacklist;
 
     /// <summary>
     /// The change in position to the strapped mob
index 3d1fbf2b69624493f20a9b164c8a2d57b3ddcd2d..0d67473ffee9a7aa5a39551c47dd855e053ba747 100644 (file)
@@ -221,8 +221,8 @@ public abstract partial class SharedBuckleSystem
         }
 
         // Does it pass the Whitelist
-        if (strapComp.AllowedEntities != null &&
-            !strapComp.AllowedEntities.IsValid(userUid, EntityManager))
+        if (strapComp.Whitelist != null &&
+            !strapComp.Whitelist.IsValid(buckleUid, EntityManager) || strapComp.Blacklist?.IsValid(buckleUid, EntityManager) == true)
         {
             if (_netManager.IsServer)
                 _popup.PopupEntity(Loc.GetString("buckle-component-cannot-fit-message"), userUid, buckleUid, PopupType.Medium);
index 72586be1ec624922b784ff4d84f1bfa5619a8640..4948cb6640e1e8d9158b0f05be5ff1887f69a9ca 100644 (file)
@@ -1,4 +1,5 @@
 using Robust.Shared.Audio;
+using Content.Shared.Whitelist;
 using Robust.Shared.Containers;
 using Robust.Shared.GameStates;
 using Robust.Shared.Serialization;
@@ -17,6 +18,18 @@ public abstract partial class SharedDisposalUnitComponent : Component
     [ViewVariables(VVAccess.ReadWrite), DataField("soundFlush")]
     public SoundSpecifier? FlushSound = new SoundPathSpecifier("/Audio/Machines/disposalflush.ogg");
 
+    /// <summary>
+    /// Blacklists (prevents) entities listed from being placed inside.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Blacklist;
+
+    /// <summary>
+    /// Whitelists (allows) entities listed from being placed inside.
+    /// </summary>
+    [DataField]
+    public EntityWhitelist? Whitelist;
+
     /// <summary>
     /// Sound played when an object is inserted into the disposal unit.
     /// </summary>
@@ -33,20 +46,20 @@ public abstract partial class SharedDisposalUnitComponent : Component
     /// <summary>
     /// State for this disposals unit.
     /// </summary>
-    [DataField("state")]
+    [DataField]
     public DisposalsPressureState State;
 
     // TODO: Just make this use vaulting.
     /// <summary>
     /// We'll track whatever just left disposals so we know what collision we need to ignore until they stop intersecting our BB.
     /// </summary>
-    [ViewVariables, DataField("recentlyEjected")]
+    [ViewVariables, DataField]
     public List<EntityUid> RecentlyEjected = new();
 
     /// <summary>
     /// Next time the disposal unit will be pressurized.
     /// </summary>
-    [DataField("nextPressurized", customTypeSerializer:typeof(TimeOffsetSerializer))]
+    [DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
     public TimeSpan NextPressurized = TimeSpan.Zero;
 
     /// <summary>
@@ -58,63 +71,60 @@ public abstract partial class SharedDisposalUnitComponent : Component
     /// <summary>
     /// How long it takes from the start of a flush animation to return the sprite to normal.
     /// </summary>
-    [DataField("flushDelay")]
+    [DataField]
     public TimeSpan FlushDelay = TimeSpan.FromSeconds(3);
 
-    [DataField("mobsCanEnter")]
-    public bool MobsCanEnter = true;
-
     /// <summary>
     /// Removes the pressure requirement for flushing.
     /// </summary>
-    [DataField("disablePressure"), ViewVariables(VVAccess.ReadWrite)]
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
     public bool DisablePressure;
 
     /// <summary>
-    ///     Last time that an entity tried to exit this disposal unit.
+    /// Last time that an entity tried to exit this disposal unit.
     /// </summary>
     [ViewVariables]
     public TimeSpan LastExitAttempt;
 
-    [DataField("autoEngageEnabled")]
+    [DataField]
     public bool AutomaticEngage = true;
 
     [ViewVariables(VVAccess.ReadWrite)]
-    [DataField("autoEngageTime")]
+    [DataField]
     public TimeSpan AutomaticEngageTime = TimeSpan.FromSeconds(30);
 
     /// <summary>
-    ///     Delay from trying to enter disposals ourselves.
+    /// Delay from trying to enter disposals ourselves.
     /// </summary>
     [ViewVariables(VVAccess.ReadWrite)]
-    [DataField("entryDelay")]
+    [DataField]
     public float EntryDelay = 0.5f;
 
     /// <summary>
-    ///     Delay from trying to shove someone else into disposals.
+    /// Delay from trying to shove someone else into disposals.
     /// </summary>
     [ViewVariables(VVAccess.ReadWrite)]
     public float DraggedEntryDelay = 2.0f;
 
     /// <summary>
-    ///     Container of entities inside this disposal unit.
+    /// Container of entities inside this disposal unit.
     /// </summary>
     [ViewVariables] public Container Container = default!;
 
     // TODO: Network power shit instead fam.
-    [ViewVariables, DataField("powered")]
+    [ViewVariables, DataField]
     public bool Powered;
 
     /// <summary>
     /// Was the disposals unit engaged for a manual flush.
     /// </summary>
-    [ViewVariables(VVAccess.ReadWrite), DataField("engaged")]
+    [ViewVariables(VVAccess.ReadWrite), DataField]
     public bool Engaged;
 
     /// <summary>
     /// Next time this unit will flush. Is the lesser of <see cref="FlushDelay"/> and <see cref="AutomaticEngageTime"/>
     /// </summary>
-    [ViewVariables, DataField("nextFlush", customTypeSerializer:typeof(TimeOffsetSerializer))]
+    [ViewVariables, DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
     public TimeSpan? NextFlush;
 
     [Serializable, NetSerializable]
@@ -130,8 +140,8 @@ public abstract partial class SharedDisposalUnitComponent : Component
     {
         UnAnchored,
         Anchored,
-        Flushing,
-        Charging
+        OverlayFlushing,
+        OverlayCharging
     }
 
     [Serializable, NetSerializable]
index 9afd683cbdc1ec0f30ea904622f2a522164ac917..c39139f9a57daba0512ef41553ad307c7c76a271 100644 (file)
@@ -1,12 +1,10 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.CodeAnalysis;
 using Content.Shared.Body.Components;
 using Content.Shared.Disposal.Components;
 using Content.Shared.DoAfter;
 using Content.Shared.DragDrop;
 using Content.Shared.Emag.Systems;
 using Content.Shared.Item;
-using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
 using Content.Shared.Throwing;
 using Robust.Shared.Audio;
 using Robust.Shared.Physics.Components;
@@ -26,7 +24,6 @@ public abstract class SharedDisposalUnitSystem : EntitySystem
 {
     [Dependency] protected readonly IGameTiming GameTiming = default!;
     [Dependency] protected readonly MetaDataSystem Metadata = default!;
-    [Dependency] private   readonly MobStateSystem _mobState = default!;
     [Dependency] protected readonly SharedJointSystem Joints = default!;
 
     protected static TimeSpan ExitAttemptDelay = TimeSpan.FromSeconds(0.5);
@@ -112,19 +109,21 @@ public abstract class SharedDisposalUnitSystem : EntitySystem
         if (!Transform(uid).Anchored)
             return false;
 
-        // TODO: Probably just need a disposable tag.
         var storable = HasComp<ItemComponent>(entity);
         if (!storable && !HasComp<BodyComponent>(entity))
             return false;
 
-        //Check if the entity is a mob and if mobs can be inserted
-        if (TryComp<MobStateComponent>(entity, out var damageState) && !component.MobsCanEnter)
+        if (component.Blacklist?.IsValid(entity, EntityManager) == true)
             return false;
 
-        if (TryComp<PhysicsComponent>(entity, out var physics) && (physics.CanCollide || storable))
+        if (component.Whitelist != null && component.Whitelist?.IsValid(entity, EntityManager) != true)
+            return false;
+
+        if (TryComp<PhysicsComponent>(entity, out var physics) && (physics.CanCollide) || storable)
             return true;
+        else
+            return false;
 
-        return damageState != null && (!component.MobsCanEnter || _mobState.IsDead(entity, damageState));
     }
 
     public abstract void DoInsertDisposalUnit(EntityUid uid, EntityUid toInsert, EntityUid user, SharedDisposalUnitComponent? disposal = null);
similarity index 80%
rename from Content.Server/Plants/Components/PottedPlantHideComponent.cs
rename to Content.Shared/Plants/PottedPlantHideComponent.cs
index bc35bbe44f9e9e3adc6118a620107ea4c6539359..2e02272494fe90965d69421caec63df59e169c27 100644 (file)
@@ -1,8 +1,7 @@
-using Content.Server.Plants.Systems;
-using Content.Server.Storage.Components;
+using Content.Shared.Storage.Components;
 using Robust.Shared.Audio;
 
-namespace Content.Server.Plants.Components
+namespace Content.Shared.Plants
 {
     /// <summary>
     ///     Interaction wrapper for <see cref="SecretStashComponent"/>.
similarity index 86%
rename from Content.Server/Plants/Systems/PottedPlantHideSystem.cs
rename to Content.Shared/Plants/PottedPlantHideSystem.cs
index 09571c60a1309699458a1439864feeff996f30bb..fd256fd926342aab8c10b86c97811b087eac349d 100644 (file)
@@ -1,18 +1,15 @@
-using Content.Server.Plants.Components;
-using Content.Server.Popups;
-using Content.Server.Storage.Components;
-using Content.Server.Storage.EntitySystems;
-using Content.Shared.Audio;
+using Content.Shared.Popups;
+using Content.Shared.Storage.Components;
+using Content.Shared.Storage.EntitySystems;
 using Content.Shared.Interaction;
 using Robust.Shared.Audio;
 using Robust.Shared.Audio.Systems;
-using Robust.Shared.Player;
 
-namespace Content.Server.Plants.Systems
+namespace Content.Shared.Plants
 {
     public sealed class PottedPlantHideSystem : EntitySystem
     {
-        [Dependency] private readonly PopupSystem _popupSystem = default!;
+        [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
         [Dependency] private readonly SecretStashSystem _stashSystem = default!;
         [Dependency] private readonly SharedAudioSystem _audio = default!;
 
diff --git a/Content.Shared/Plunger/Components/PlungerComponent.cs b/Content.Shared/Plunger/Components/PlungerComponent.cs
new file mode 100644 (file)
index 0000000..101121f
--- /dev/null
@@ -0,0 +1,18 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Plunger.Components
+{
+    /// <summary>
+    /// Allows entity to unblock target entity with PlungerUseComponent.
+    /// </summary>
+    [RegisterComponent, NetworkedComponent,AutoGenerateComponentState]
+    public sealed partial class PlungerComponent : Component
+    {
+        /// <summary>
+        /// Duration of plunger doafter event.
+        /// </summary>
+        [DataField]
+        [AutoNetworkedField]
+        public float PlungeDuration = 2f;
+    }
+}
diff --git a/Content.Shared/Plunger/Components/PlungerUseComponent.cs b/Content.Shared/Plunger/Components/PlungerUseComponent.cs
new file mode 100644 (file)
index 0000000..e886a4e
--- /dev/null
@@ -0,0 +1,42 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+using Content.Shared.Random;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Plunger.Components
+{
+    /// <summary>
+    /// Entity can interact with plungers.
+    /// </summary>
+    [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+    public sealed partial class PlungerUseComponent : Component
+    {
+        /// <summary>
+        /// If true entity has been plungered.
+        /// </summary>
+        [DataField]
+        [AutoNetworkedField]
+        public bool Plunged;
+
+        /// <summary>
+        /// If true entity can interact with plunger.
+        /// </summary>
+        [DataField]
+        [AutoNetworkedField]
+        public bool NeedsPlunger = false;
+
+        /// <summary>
+        /// A weighted random entity prototype containing the different loot that rummaging can provide.
+        /// </summary>
+        [DataField]
+        [AutoNetworkedField]
+        public ProtoId<WeightedRandomEntityPrototype> PlungerLoot = "PlungerLoot";
+
+
+        /// <summary>
+        /// Sound played on rummage completion.
+        /// </summary>
+        [DataField]
+        public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Effects/Fluids/glug.ogg");
+    }
+}
diff --git a/Content.Shared/Plunger/PlungerDoAfterEvent.cs b/Content.Shared/Plunger/PlungerDoAfterEvent.cs
new file mode 100644 (file)
index 0000000..b803f51
--- /dev/null
@@ -0,0 +1,10 @@
+
+using Content.Shared.DoAfter;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Plunger;
+
+[Serializable, NetSerializable]
+public sealed partial class PlungerDoAfterEvent : SimpleDoAfterEvent
+{
+}
diff --git a/Content.Shared/Plunger/Systems/PlungerSystem.cs b/Content.Shared/Plunger/Systems/PlungerSystem.cs
new file mode 100644 (file)
index 0000000..57bd77a
--- /dev/null
@@ -0,0 +1,79 @@
+using Content.Shared.DoAfter;
+using Content.Shared.Interaction;
+using Content.Shared.Popups;
+using Content.Shared.Plunger.Components;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Timing;
+using Content.Shared.Random.Helpers;
+using Robust.Shared.Network;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+using Content.Shared.Random;
+
+namespace Content.Shared.Plunger.Systems;
+
+/// <summary>
+/// Plungers can be used to unblock entities with PlungerUseComponent.
+/// </summary>
+public sealed class PlungerSystem : EntitySystem
+{
+    [Dependency] protected readonly IPrototypeManager _proto = default!;
+    [Dependency] protected readonly IRobustRandom _random = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<PlungerComponent, AfterInteractEvent>(OnInteract);
+        SubscribeLocalEvent<PlungerComponent, PlungerDoAfterEvent>(OnDoAfter);
+    }
+
+    private void OnInteract(EntityUid uid, PlungerComponent component, AfterInteractEvent args)
+    {
+        if (args.Handled)
+            return;
+
+        if (!args.CanReach || args.Target is not { Valid: true } target)
+            return;
+
+        if (!TryComp<PlungerUseComponent>(args.Target, out var plunger))
+            return;
+
+        if (plunger.NeedsPlunger)
+            return;
+
+        _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.PlungeDuration, new PlungerDoAfterEvent(), uid, target, uid)
+        {
+            BreakOnMove = true,
+            BreakOnDamage = true,
+            MovementThreshold = 1.0f,
+        });
+        args.Handled = true;
+    }
+
+    private void OnDoAfter(EntityUid uid, PlungerComponent component, DoAfterEvent args)
+    {
+        if (args.Cancelled || args.Handled || args.Args.Target == null)
+            return;
+
+        if (args.Target is not { Valid: true } target)
+            return;
+
+        if (!TryComp(target, out PlungerUseComponent? plunge))
+            return;
+
+        _popup.PopupClient(Loc.GetString("plunger-unblock", ("target", target)), args.User, args.User, PopupType.Medium);
+        plunge.Plunged = true;
+
+        var spawn = _proto.Index<WeightedRandomEntityPrototype>(plunge.PlungerLoot).Pick(_random);
+
+        _audio.PlayPredicted(plunge.Sound, uid, uid);
+        Spawn(spawn, Transform(target).Coordinates);
+        RemComp<PlungerUseComponent>(target);
+        Dirty(target, plunge);
+
+        args.Handled = true;
+    }
+}
+
diff --git a/Content.Shared/Storage/Components/SecretStashComponent.cs b/Content.Shared/Storage/Components/SecretStashComponent.cs
new file mode 100644 (file)
index 0000000..8595f79
--- /dev/null
@@ -0,0 +1,90 @@
+using Content.Shared.Storage.EntitySystems;
+using Content.Shared.Containers.ItemSlots;
+using Content.Shared.Item;
+using Robust.Shared.Containers;
+using Robust.Shared.Prototypes;
+using Content.Shared.Tools;
+using Robust.Shared.GameStates;
+using Content.Shared.DoAfter;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Storage.Components
+{
+    /// <summary>
+    ///     Logic for a secret slot stash, like plant pot or toilet cistern.
+    ///     Unlike <see cref="ItemSlotsComponent"/> it doesn't have interaction logic or verbs.
+    ///     Other classes like <see cref="ToiletComponent"/> should implement it.
+    /// </summary>
+    [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+    [Access(typeof(SecretStashSystem))]
+    public sealed partial class SecretStashComponent : Component
+    {
+        /// <summary>
+        ///     Max item size that can be fitted into secret stash.
+        /// </summary>
+        [DataField("maxItemSize")]
+        public ProtoId<ItemSizePrototype> MaxItemSize = "Small";
+
+        /// <summary>
+        /// If stash has way to open then this will switch between open and closed.
+        /// </summary>
+        [DataField, AutoNetworkedField]
+        public bool ToggleOpen;
+
+        /// <summary>
+        /// Prying the door.
+        /// </summary>
+        [DataField]
+        public float PryDoorTime = 1f;
+
+        [DataField]
+        public ProtoId<ToolQualityPrototype> PryingQuality = "Prying";
+
+        /// <summary>
+        /// Is stash openable?.
+        /// </summary>
+        [DataField, AutoNetworkedField]
+        public bool OpenableStash = false;
+
+        /// <summary>
+        ///     IC secret stash name. For example "the toilet cistern".
+        ///     If empty string, will replace it with entity name in init.
+        /// </summary>
+        [DataField]
+        public string SecretPartName { get; set; } = "";
+
+        [DataField, AutoNetworkedField]
+        public string ExamineStash = "comp-secret-stash-on-examine-found-hidden-item";
+
+        /// <summary>
+        ///     Container used to keep secret stash item.
+        /// </summary>
+        [ViewVariables]
+        public ContainerSlot ItemContainer = default!;
+
+    }
+
+    /// <summary>
+    /// Simple pry event for prying open a stash door.
+    /// </summary>
+    [Serializable, NetSerializable]
+    public sealed partial class StashPryDoAfterEvent : SimpleDoAfterEvent
+    {
+    }
+
+    /// <summary>
+    /// Visualizers for handling stash open closed state if stash has door.
+    /// </summary>
+    [Serializable, NetSerializable]
+    public enum StashVisuals : byte
+    {
+        DoorVisualState,
+    }
+
+    [Serializable, NetSerializable]
+    public enum DoorVisualState : byte
+    {
+        DoorOpen,
+        DoorClosed
+    }
+}
similarity index 55%
rename from Content.Server/Storage/EntitySystems/SecretStashSystem.cs
rename to Content.Shared/Storage/EntitySystems/SecretStashSystem.cs
index 49be0a2f880f15be58da55a49359f0434102b4f7..9aee1b982e0a56fab657cd4c8760779f2985151b 100644 (file)
@@ -1,25 +1,37 @@
-using Content.Server.Popups;
-using Content.Server.Storage.Components;
+using Content.Shared.Popups;
+using Content.Shared.Storage.Components;
 using Content.Shared.Destructible;
 using Content.Shared.Hands.Components;
 using Content.Shared.Hands.EntitySystems;
 using Content.Shared.Item;
 using Robust.Shared.Containers;
+using Content.Shared.Interaction;
+using Content.Shared.Tools.Systems;
+using Content.Shared.Examine;
 
-namespace Content.Server.Storage.EntitySystems
+namespace Content.Shared.Storage.EntitySystems
 {
+    /// <summary>
+    /// Secret Stash allows an item to be hidden within.
+    /// </summary>
     public sealed class SecretStashSystem : EntitySystem
     {
-        [Dependency] private readonly PopupSystem _popupSystem = default!;
+        [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
         [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
         [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
         [Dependency] private readonly SharedItemSystem _item = default!;
+        [Dependency] private readonly SharedToolSystem _tool = default!;
+        [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
 
         public override void Initialize()
         {
             base.Initialize();
             SubscribeLocalEvent<SecretStashComponent, ComponentInit>(OnInit);
             SubscribeLocalEvent<SecretStashComponent, DestructionEventArgs>(OnDestroyed);
+            SubscribeLocalEvent<SecretStashComponent, StashPryDoAfterEvent>(OnSecretStashPried);
+            SubscribeLocalEvent<SecretStashComponent, InteractUsingEvent>(OnInteractUsing);
+            SubscribeLocalEvent<SecretStashComponent, InteractHandEvent>(OnInteractHand);
+            SubscribeLocalEvent<SecretStashComponent, ExaminedEvent>(OnExamine);
         }
 
         private void OnInit(EntityUid uid, SecretStashComponent component, ComponentInit args)
@@ -42,6 +54,73 @@ namespace Content.Server.Storage.EntitySystems
             return component.ItemContainer.ContainedEntity != null;
         }
 
+        private void OnInteractUsing(EntityUid uid, SecretStashComponent component, InteractUsingEvent args)
+        {
+            if (args.Handled)
+                return;
+
+            if (!component.OpenableStash)
+                return;
+
+            // is player trying place or lift off cistern lid?
+            if (_tool.UseTool(args.Used, args.User, uid, component.PryDoorTime, component.PryingQuality, new StashPryDoAfterEvent()))
+                args.Handled = true;
+            // maybe player is trying to hide something inside cistern?
+            else if (component.ToggleOpen)
+            {
+                TryHideItem(uid, args.User, args.Used);
+                args.Handled = true;
+            }
+        }
+
+        private void OnInteractHand(EntityUid uid, SecretStashComponent component, InteractHandEvent args)
+        {
+            if (args.Handled)
+                return;
+
+            if (!component.OpenableStash)
+                return;
+
+            // trying to get something from stash?
+            if (component.ToggleOpen)
+            {
+                var gotItem = TryGetItem(uid, args.User);
+                if (gotItem)
+                {
+                    args.Handled = true;
+                    return;
+                }
+            }
+            args.Handled = true;
+        }
+
+        private void OnSecretStashPried(EntityUid uid, SecretStashComponent component, StashPryDoAfterEvent args)
+        {
+            if (args.Cancelled)
+                return;
+
+            ToggleOpen(uid, component);
+        }
+
+        public void ToggleOpen(EntityUid uid, SecretStashComponent? component = null, MetaDataComponent? meta = null)
+        {
+            if (!Resolve(uid, ref component))
+                return;
+
+            component.ToggleOpen = !component.ToggleOpen;
+
+            UpdateAppearance(uid, component);
+            Dirty(uid, component, meta);
+        }
+
+        private void UpdateAppearance(EntityUid uid, SecretStashComponent? component = null)
+        {
+            if (!Resolve(uid, ref component))
+                return;
+
+            _appearance.SetData(uid, StashVisuals.DoorVisualState, component.ToggleOpen ? DoorVisualState.DoorOpen : DoorVisualState.DoorClosed);
+        }
+
         /// <summary>
         ///     Tries to hide item inside secret stash from hands of user.
         /// </summary>
@@ -62,7 +141,7 @@ namespace Content.Server.Storage.EntitySystems
             if (container.ContainedEntity != null)
             {
                 var msg = Loc.GetString("comp-secret-stash-action-hide-container-not-empty");
-                _popupSystem.PopupEntity(msg, uid, userUid);
+                _popupSystem.PopupClient(msg, uid, userUid);
                 return false;
             }
 
@@ -71,7 +150,7 @@ namespace Content.Server.Storage.EntitySystems
             {
                 var msg = Loc.GetString("comp-secret-stash-action-hide-item-too-big",
                     ("item", itemToHideUid), ("stash", GetSecretPartName(uid, component)));
-                _popupSystem.PopupEntity(msg, uid, userUid);
+                _popupSystem.PopupClient(msg, uid, userUid);
                 return false;
             }
 
@@ -84,7 +163,7 @@ namespace Content.Server.Storage.EntitySystems
             // all done, show success message
             var successMsg = Loc.GetString("comp-secret-stash-action-hide-success",
                 ("item", itemToHideUid), ("this", GetSecretPartName(uid, component)));
-            _popupSystem.PopupEntity(successMsg, uid, userUid);
+            _popupSystem.PopupClient(successMsg, uid, userUid);
             return true;
         }
 
@@ -113,11 +192,23 @@ namespace Content.Server.Storage.EntitySystems
             // show success message
             var successMsg = Loc.GetString("comp-secret-stash-action-get-item-found-something",
                 ("stash", GetSecretPartName(uid, component)));
-            _popupSystem.PopupEntity(successMsg, uid, userUid);
+            _popupSystem.PopupClient(successMsg, uid, userUid);
 
             return true;
         }
 
+        private void OnExamine(EntityUid uid, SecretStashComponent component, ExaminedEvent args)
+        {
+            if (args.IsInDetailsRange && component.ToggleOpen)
+            {
+                if (HasItemInside(uid))
+                {
+                    var msg = Loc.GetString(component.ExamineStash);
+                    args.PushMarkup(msg);
+                }
+            }
+        }
+
         private string GetSecretPartName(EntityUid uid, SecretStashComponent stash)
         {
             if (stash.SecretPartName != "")
diff --git a/Content.Shared/Toilet/Components/ToiletComponent.cs b/Content.Shared/Toilet/Components/ToiletComponent.cs
new file mode 100644 (file)
index 0000000..5de74e0
--- /dev/null
@@ -0,0 +1,40 @@
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Toilet.Components
+{
+    /// <summary>
+    /// Toilets that can be flushed, seats toggled up and down, items hidden in cistern.
+    /// </summary>
+    [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+    public sealed partial class ToiletComponent : Component
+    {
+        /// <summary>
+        /// Toggles seat state.
+        /// </summary>
+        [DataField, AutoNetworkedField]
+        public bool ToggleSeat;
+
+
+        /// <summary>
+        /// Sound to play when toggling toilet seat.
+        /// </summary>
+        [DataField]
+        public SoundSpecifier SeatSound = new SoundPathSpecifier("/Audio/Effects/toilet_seat_down.ogg");
+    }
+
+    [Serializable, NetSerializable]
+    public enum ToiletVisuals : byte
+    {
+        SeatVisualState,
+    }
+
+    [Serializable, NetSerializable]
+    public enum SeatVisualState : byte
+    {
+        SeatUp,
+        SeatDown
+    }
+}
+
diff --git a/Content.Shared/Toilet/Systems/SharedToiletSystem.cs b/Content.Shared/Toilet/Systems/SharedToiletSystem.cs
new file mode 100644 (file)
index 0000000..87df69e
--- /dev/null
@@ -0,0 +1,109 @@
+using Content.Shared.Buckle.Components;
+using Content.Shared.Interaction;
+using Content.Shared.Verbs;
+using Content.Shared.Plunger.Components;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Random;
+using Robust.Shared.Utility;
+using Content.Shared.Toilet.Components;
+
+namespace Content.Shared.Toilet.Systems
+{
+    /// <summary>
+    /// Handles sprite changes for both toilet seat up and down as well as for lid open and closed. Handles interactions with hidden stash
+    /// </summary>
+
+    public abstract class SharedToiletSystem : EntitySystem
+    {
+        [Dependency] private readonly IRobustRandom _random = default!;
+        [Dependency] private readonly SharedAudioSystem _audio = default!;
+        [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+
+        public override void Initialize()
+        {
+            base.Initialize();
+
+            SubscribeLocalEvent<ToiletComponent, MapInitEvent>(OnMapInit);
+            SubscribeLocalEvent<ToiletComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleSeatVerb);
+            SubscribeLocalEvent<ToiletComponent, ActivateInWorldEvent>(OnActivateInWorld);
+        }
+
+        private void OnMapInit(EntityUid uid, ToiletComponent component, MapInitEvent args)
+        {
+            if (_random.Prob(0.5f))
+                component.ToggleSeat = true;
+
+            if (_random.Prob(0.3f))
+            {
+                TryComp<PlungerUseComponent>(uid, out var plunger);
+
+                if (plunger == null)
+                    return;
+
+                plunger.NeedsPlunger = true;
+            }
+
+            UpdateAppearance(uid);
+            Dirty(uid, component);
+        }
+
+        public bool CanToggle(EntityUid uid)
+        {
+            return TryComp<StrapComponent>(uid, out var strap) && strap.BuckledEntities.Count == 0;
+        }
+
+        private void OnToggleSeatVerb(EntityUid uid, ToiletComponent component, GetVerbsEvent<AlternativeVerb> args)
+        {
+            if (!args.CanInteract || !args.CanAccess || !CanToggle(uid) || args.Hands == null)
+                return;
+
+            AlternativeVerb toggleVerb = new()
+            {
+                Act = () => ToggleToiletSeat(uid, args.User, component)
+            };
+
+            if (component.ToggleSeat)
+            {
+                toggleVerb.Text = Loc.GetString("toilet-seat-close");
+                toggleVerb.Icon =
+                    new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/close.svg.192dpi.png"));
+            }
+            else
+            {
+                toggleVerb.Text = Loc.GetString("toilet-seat-open");
+                toggleVerb.Icon =
+                    new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/open.svg.192dpi.png"));
+            }
+            args.Verbs.Add(toggleVerb);
+        }
+
+        private void OnActivateInWorld(EntityUid uid, ToiletComponent comp, ActivateInWorldEvent args)
+        {
+            if (args.Handled)
+                return;
+
+            args.Handled = true;
+            ToggleToiletSeat(uid, args.User, comp);
+        }
+
+        public void ToggleToiletSeat(EntityUid uid, EntityUid? user = null, ToiletComponent? component = null, MetaDataComponent? meta = null)
+        {
+            if (!Resolve(uid, ref component))
+                return;
+
+            component.ToggleSeat = !component.ToggleSeat;
+
+            _audio.PlayPredicted(component.SeatSound, uid, uid);
+            UpdateAppearance(uid, component);
+            Dirty(uid, component, meta);
+        }
+
+        private void UpdateAppearance(EntityUid uid, ToiletComponent? component = null)
+        {
+            if (!Resolve(uid, ref component))
+                return;
+
+            _appearance.SetData(uid, ToiletVisuals.SeatVisualState, component.ToggleSeat ? SeatVisualState.SeatUp : SeatVisualState.SeatDown);
+        }
+    }
+}
diff --git a/Content.Shared/Toilet/ToiletComponent.cs b/Content.Shared/Toilet/ToiletComponent.cs
deleted file mode 100644 (file)
index 161bf81..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-using Content.Shared.DoAfter;
-using Content.Shared.Tools;
-using Robust.Shared.Audio;
-using Robust.Shared.Serialization;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-
-namespace Content.Shared.Toilet
-{
-    [RegisterComponent]
-    public sealed partial class ToiletComponent : Component
-    {
-        [DataField("pryLidTime")]
-        public float PryLidTime = 1f;
-
-        [DataField("pryingQuality", customTypeSerializer:typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
-        public string PryingQuality = "Prying";
-
-        [DataField("toggleSound")]
-        public SoundSpecifier ToggleSound = new SoundPathSpecifier("/Audio/Effects/toilet_seat_down.ogg");
-
-        [DataField("lidOpen")]
-        public bool LidOpen = false;
-
-        [DataField("isSeatUp")]
-        public bool IsSeatUp = false;
-    }
-
-    [Serializable, NetSerializable]
-    public sealed partial class ToiletPryDoAfterEvent : SimpleDoAfterEvent
-    {
-    }
-}
diff --git a/Content.Shared/Toilet/ToiletVisuals.cs b/Content.Shared/Toilet/ToiletVisuals.cs
deleted file mode 100644 (file)
index c5992bc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-using Robust.Shared.Serialization;
-
-namespace Content.Shared.Toilet;
-
-[Serializable, NetSerializable]
-public enum ToiletVisuals
-{
-    LidOpen,
-    SeatUp
-}
index 4e28c992528b5b02baf5855b5db5d833edbbf48b..aebe3e3c3ff0fa01a187aa8ff3604615a1492dea 100644 (file)
   license: "CC0-1.0"
   copyright: "Created by brittmosel"
   source: "https://freesound.org/people/brittmosel/sounds/529300/"
+
+- files: ["splash.ogg"]
+  license: "CC0-1.0"
+  copyright: "Created by deadrobotmusic"
+  source: "https://freesound.org/people/deadrobotmusic/sounds/609953/"
+
+- files: ["flush.ogg"]
+  license: "CC-BY-SA-3.0"
+  copyright: "Created by the_toilet_guy"
+  source: "https://freesound.org/people/the_toilet_guy/sounds/98770/"
diff --git a/Resources/Audio/Effects/Fluids/flush.ogg b/Resources/Audio/Effects/Fluids/flush.ogg
new file mode 100644 (file)
index 0000000..f4ef31c
Binary files /dev/null and b/Resources/Audio/Effects/Fluids/flush.ogg differ
diff --git a/Resources/Audio/Effects/Fluids/splash.ogg b/Resources/Audio/Effects/Fluids/splash.ogg
new file mode 100644 (file)
index 0000000..4233eff
Binary files /dev/null and b/Resources/Audio/Effects/Fluids/splash.ogg differ
diff --git a/Resources/Audio/Weapons/glug.ogg b/Resources/Audio/Weapons/glug.ogg
new file mode 100644 (file)
index 0000000..424bedd
Binary files /dev/null and b/Resources/Audio/Weapons/glug.ogg differ
index d41933b3744dc910c1cf6cd8d992f14db7a14eb1..d0dfed2b5dda7cd3d217f1c8c8d379f2bc9de625 100644 (file)
@@ -5,6 +5,7 @@ comp-secret-stash-action-hide-success = You hide { THE($item) } in { $this }
 comp-secret-stash-action-hide-container-not-empty = There's already something in here?!
 comp-secret-stash-action-hide-item-too-big = { THE($item) } is too big to fit in {$stash}!
 comp-secret-stash-action-get-item-found-something = There was something inside {$stash}!
+comp-secret-stash-on-examine-found-hidden-item = There is something hidden inside.
 
 secret-stash-part-plant = the plant
 secret-stash-part-toilet = the toilet cistern
index 7807759e42c428978c7bdb350bda5d0b7555e5ae..1129f61b4d7a1a7078ccc1e34d3f061ebda11146 100644 (file)
@@ -7,3 +7,5 @@ toilet-component-suicide-message-others = {CAPITALIZE(THE($victim))} bashes them
 toilet-component-suicide-message = You bash yourself with {THE($owner)}!
 toilet-seat-close = Close Seat
 toilet-seat-open = Open Seat
+
+plunger-unblock = You unblock the {THE($target)}!
index db08481dc5306098624bcbadfe837a8c0cc76be8..cad2d9a924512ead4b08a63dfb242f16ad54d5a4 100644 (file)
     damage:
       types:
         Blunt: 3
+  - type: Plunger
+
+- type: weightedRandomEntity
+  id: PlungerLoot
+  weights:
+    RandomSpawner100: 56
+    SpacemenFigureSpawner: 28
+    SpawnMobCockroach: 5
+    MaintenanceToolSpawner: 5
 
 - type: entity
   parent: BaseItem
index a6f14b383cb6d2ecbc91942c3ddb39d369ef9e55..f02b12624894e3e1cd85dafa1f9dca1db01e43c2 100644 (file)
   name: toilet
   id: ToiletEmpty
   suffix: Empty
-  parent: SeatBase
+  parent: [ DisposalUnitBase, SeatBase ]
   description: The HT-451, a torque rotation-based, waste disposal unit for small matter. This one seems remarkably clean.
   components:
-  - type: MeleeSound
-    soundGroups:
-      Brute:
-        path:
-          "/Audio/Weapons/slash.ogg"
-  - type: Anchorable
   - type: Sprite
     sprite: Structures/Furniture/toilet.rsi
-    state: closed_toilet_seat_up
+    layers:
+    - state: condisposal
+      map: [ "enum.DisposalUnitVisualLayers.Unanchored" ]
+    - state: disposal
+      map: [ "enum.DisposalUnitVisualLayers.Base" ]
+    - state: disposal-flush
+      map: [ "enum.DisposalUnitVisualLayers.OverlayFlush" ]
+    - state: dispover-charge
+      map: [ "enum.DisposalUnitVisualLayers.OverlayCharging" ]
+    - state: dispover-ready
+      map: [ "enum.DisposalUnitVisualLayers.OverlayReady" ]
+    - state: dispover-full
+      map: [ "enum.DisposalUnitVisualLayers.OverlayFull" ]
+    - state: dispover-handle
+      map: [ "enum.DisposalUnitVisualLayers.OverlayEngaged" ]
+    - map: [ "DoorVisualState.DoorOpen" ]
+    - map: [ "SeatVisualState.SeatUp" ]
+  - type: Rotatable
+  - type: Transform
+    noRot: false
+  - type: Strap
+    whitelist:
+      components:
+      - HumanoidAppearance
+  - type: DisposalUnit
+    autoEngageEnabled: false
+    noUI: true
+    blacklist:
+      components:
+      - HumanoidAppearance
+      - Plunger
+      - SolutionTransfer
+    whitelist:
+      components:
+      - Item
+    soundFlush: /Audio/Effects/Fluids/flush.ogg
+    soundInsert: /Audio/Effects/Fluids/splash.ogg
   - type: Toilet
-  - type: SecretStash
-    secretPartName: secret-stash-part-toilet
   - type: ContainerContainer
     containers:
       stash: !type:ContainerSlot {}
-  - type: SolutionContainerManager
-    solutions:
-      drainBuffer:
-        maxVol: 500
-      toilet:
-        maxVol: 250
-  - type: Transform
-    anchored: true
+      disposals: !type:Container
   - type: Physics
     bodyType: Static
   - type: Construction
     graph: Toilet
     node: toilet
+  - type: PlungerUse
   - type: Appearance
+  - type: SecretStash
+    secretPartName: secret-stash-part-toilet
+    examineStash: toilet-component-on-examine-found-hidden-item
+    openableStash: true
   - type: Drain
     autoDrain: false
-  - type: DumpableSolution
-    solution: drainBuffer
-  - type: SolutionContainerVisuals
-    maxFillLevels: 1
-    fillBaseName: fill-
-    solutionName: drainBuffer
   - type: StaticPrice
     price: 25
+  - type: UserInterface
+    interfaces:
+    - key: enum.DisposalUnitUiKey.Key
+      type: DisposalUnitBoundUserInterface
+  - type: RatKingRummageable
+  - type: SolutionContainerManager
+    solutions:
+      drainBuffer:
+        maxVol: 100
+      tank:
+        maxVol: 500
+  - type: SolutionRegeneration
+    solution: tank
+    generated:
+      reagents:
+      - ReagentId: Water
+        Quantity: 1
+  - type: DrainableSolution
+    solution: tank
+  - type: ReagentTank
+  - type: DumpableSolution
+    solution: drainBuffer
+  - type: GenericVisualizer
+    visuals:
+      enum.ToiletVisuals.SeatVisualState:
+        SeatVisualState.SeatUp:
+          SeatUp: { state: disposal-up }
+          SeatDown: { state: disposal-down }
+      enum.StashVisuals.DoorVisualState:
+        DoorVisualState.DoorOpen:
+          DoorOpen: { state: disposal-open }
+          DoorClosed: { state: disposal-closed }
 
 - type: entity
   id: ToiletDirtyWater
index 1193182d09f93daa441e22fd98bddbd1d3b08133..25047bb57523648489671cfbe8449808991aa540 100644 (file)
@@ -10,7 +10,6 @@
   components:
   - type: Sprite
     sprite: Structures/Piping/disposal.rsi
-    snapCardinals: true
     layers:
     - state: condisposal
       map: [ "enum.DisposalUnitVisualLayers.Unanchored" ]
@@ -19,7 +18,7 @@
     - state: disposal-charging
       map: [ "enum.DisposalUnitVisualLayers.BaseCharging" ]
     - state: disposal-flush
-      map: [ "enum.DisposalUnitVisualLayers.BaseFlush" ]
+      map: [ "enum.DisposalUnitVisualLayers.OverlayFlush" ]
     - state: dispover-charge
       map: [ "enum.DisposalUnitVisualLayers.OverlayCharging" ]
     - state: dispover-ready
       map: [ "enum.DisposalUnitVisualLayers.OverlayEngaged" ]
   - type: Physics
     bodyType: Static
-  - type: Fixtures
-    fixtures:
-      fix1:
-        shape:
-          !type:PhysShapeAabb
-          bounds: "-0.25,-0.4,0.25,0.4"
-        density: 75
-        mask:
-        - MachineMask
-        layer:
-        - MachineLayer
   - type: Destructible
     thresholds:
     - trigger:
@@ -82,6 +70,9 @@
   parent: DisposalUnitBase
   name: disposal unit
   components:
+  - type: Sprite
+    sprite: Structures/Piping/disposal.rsi
+    snapCardinals: true
   - type: Construction
     graph: DisposalMachine
     node: disposal_unit
   components:
   - type: Sprite
     sprite: Structures/Piping/disposal.rsi
+    snapCardinals: true
     layers:
       - state: conmailing
         map: [ "enum.DisposalUnitVisualLayers.Unanchored" ]
       - state: mailing-charging
         map: [ "enum.DisposalUnitVisualLayers.BaseCharging" ]
       - state: mailing-flush
-        map: [ "enum.DisposalUnitVisualLayers.BaseFlush" ]
+        map: [ "enum.DisposalUnitVisualLayers.OverlayFlush" ]
       - state: dispover-charge
         map: [ "enum.DisposalUnitVisualLayers.OverlayCharging" ]
       - state: dispover-ready
index 7daf9ca22dfe3b574c908e72f362443abb3836c8..d9a4cd02fb4874404b659d15ee3b075152f35f8e 100644 (file)
@@ -24,7 +24,6 @@
           conditions:
             - !type:EntityAnchored
               anchored: false
-            - !type:ToiletLidClosed {}
           steps:
             - tool: Welding
               doAfter: 2
index 2597877187227430f584210abcf2a53ba8c78db8..a5cf53107dbe14458ca5d4283555271a52e5341c 100644 (file)
   description: A human excrement flushing apparatus.
   icon:
     sprite: Structures/Furniture/toilet.rsi
-    state: closed_toilet_seat_up
+    state: disposal
   objectType: Structure
   placementMode: SnapgridCenter
   canBuildInImpassable: false
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_down.png b/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_down.png
deleted file mode 100644 (file)
index 738c92a..0000000
Binary files a/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_down.png and /dev/null differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_up.png b/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_up.png
deleted file mode 100644 (file)
index 204c5ff..0000000
Binary files a/Resources/Textures/Structures/Furniture/toilet.rsi/closed_toilet_seat_up.png and /dev/null differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/condisposal.png b/Resources/Textures/Structures/Furniture/toilet.rsi/condisposal.png
new file mode 100644 (file)
index 0000000..c60cabe
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/condisposal.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-charging.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-charging.png
new file mode 100644 (file)
index 0000000..cb9ad3a
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-charging.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-closed.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-closed.png
new file mode 100644 (file)
index 0000000..98c4088
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-closed.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-down.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-down.png
new file mode 100644 (file)
index 0000000..97712dd
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-down.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-flush.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-flush.png
new file mode 100644 (file)
index 0000000..8112844
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-flush.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-open.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-open.png
new file mode 100644 (file)
index 0000000..f48f67b
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-open.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-up.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-up.png
new file mode 100644 (file)
index 0000000..3b37aba
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal-up.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/disposal.png b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal.png
new file mode 100644 (file)
index 0000000..cb2db2f
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/disposal.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-charge.png b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-charge.png
new file mode 100644 (file)
index 0000000..23ecafa
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-charge.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-full.png b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-full.png
new file mode 100644 (file)
index 0000000..ceb04df
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-full.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-handle.png b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-handle.png
new file mode 100644 (file)
index 0000000..4f40192
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-handle.png differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-ready.png b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-ready.png
new file mode 100644 (file)
index 0000000..bac1c76
Binary files /dev/null and b/Resources/Textures/Structures/Furniture/toilet.rsi/dispover-ready.png differ
index 07619942779c9c45feeaf08c4472c7419327a52b..047ddbb24bf763e6760d5adafb71fdf99ca1c67e 100644 (file)
         "x": 32,
         "y": 32
     },
-    "license": "CC-BY-SA-3.0",
-    "copyright": "Taken from cev-eris at commit https://github.com/discordia-space/CEV-Eris/commit/2cb66bae0e253e13d37f8939e0983bb94fee243e",
+    "license": "CC-BY-NC-SA-3.0",
+    "copyright": "Made by brainfood1183 (github) for ss14",
     "states": [
         {
-            "name": "closed_toilet_seat_down",
-            "directions": 4
+            "name": "condisposal",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
         },
         {
-            "name": "closed_toilet_seat_up",
-            "directions": 4
+            "name": "disposal-open",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
         },
         {
-            "name": "open_toilet_seat_down",
-            "directions": 4
+            "name": "disposal-closed",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
         },
         {
-            "name": "open_toilet_seat_up",
-            "directions": 4
+            "name": "disposal",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "disposal-up",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "disposal-down",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "disposal-charging",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "disposal-flush",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0
+                ],
+                [
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0
+                ],
+                [
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0
+                ],
+                [
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0,
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "dispover-charge",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "dispover-full",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "dispover-handle",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
+        },
+        {
+            "name": "dispover-ready",
+            "directions": 4,
+            "delays": [
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ],
+                [
+                    1.0
+                ]
+            ]
         }
     ]
-}
\ No newline at end of file
+}
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_down.png b/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_down.png
deleted file mode 100644 (file)
index a487afc..0000000
Binary files a/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_down.png and /dev/null differ
diff --git a/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_up.png b/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_up.png
deleted file mode 100644 (file)
index 7799565..0000000
Binary files a/Resources/Textures/Structures/Furniture/toilet.rsi/open_toilet_seat_up.png and /dev/null differ