diff --git a/Content.Server/Toilet/ToiletSystem.cs b/Content.Server/Toilet/ToiletSystem.cs deleted file mode 100644 index e184ddf0d5..0000000000 --- a/Content.Server/Toilet/ToiletSystem.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Shared.Toilet.Systems; - -namespace Content.Server.Toilet; - -public sealed class ToiletSystem : SharedToiletSystem -{ - -} diff --git a/Content.Shared/Toilet/Components/ToiletComponent.cs b/Content.Shared/Toilet/Components/ToiletComponent.cs index 5de74e08f6..ab1d390980 100644 --- a/Content.Shared/Toilet/Components/ToiletComponent.cs +++ b/Content.Shared/Toilet/Components/ToiletComponent.cs @@ -2,39 +2,36 @@ using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Serialization; -namespace Content.Shared.Toilet.Components +namespace Content.Shared.Toilet.Components; + +/// +/// Seats that can toggled up and down with visuals to match. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ToiletComponent : Component { /// - /// Toilets that can be flushed, seats toggled up and down, items hidden in cistern. + /// Toggles seat state. /// - [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] - public sealed partial class ToiletComponent : Component - { - /// - /// Toggles seat state. - /// - [DataField, AutoNetworkedField] - public bool ToggleSeat; + [DataField, AutoNetworkedField] + public bool ToggleSeat; - - /// - /// Sound to play when toggling toilet seat. - /// - [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 - } + /// + /// Sound to play when toggling toilet seat. + /// + [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 deleted file mode 100644 index f11af33552..0000000000 --- a/Content.Shared/Toilet/Systems/SharedToiletSystem.cs +++ /dev/null @@ -1,109 +0,0 @@ -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 -{ - /// - /// Handles sprite changes for both toilet seat up and down as well as for lid open and closed. Handles interactions with hidden stash - /// - - 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(OnMapInit); - SubscribeLocalEvent>(OnToggleSeatVerb); - SubscribeLocalEvent(OnActivateInWorld); - } - - private void OnMapInit(EntityUid uid, ToiletComponent component, MapInitEvent args) - { - if (_random.Prob(0.5f)) - component.ToggleSeat = true; - - if (_random.Prob(0.3f)) - { - TryComp(uid, out var plunger); - - if (plunger == null) - return; - - plunger.NeedsPlunger = true; - } - - UpdateAppearance(uid); - Dirty(uid, component); - } - - public bool CanToggle(EntityUid uid) - { - return TryComp(uid, out var strap) && strap.BuckledEntities.Count == 0; - } - - private void OnToggleSeatVerb(EntityUid uid, ToiletComponent component, GetVerbsEvent 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 || !args.Complex) - 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/Systems/ToiletSystem.cs b/Content.Shared/Toilet/Systems/ToiletSystem.cs new file mode 100644 index 0000000000..ad08012b11 --- /dev/null +++ b/Content.Shared/Toilet/Systems/ToiletSystem.cs @@ -0,0 +1,116 @@ +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; + +/// +/// Handles sprite changes for both toilet seat up and down as well as for lid +/// open and closed. +/// +public sealed class ToiletSystem : 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(OnMapInit); + SubscribeLocalEvent>(OnToggleSeatVerb); + SubscribeLocalEvent(OnActivateInWorld); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + if (_random.Prob(0.5f)) + { + ent.Comp.ToggleSeat = true; + Dirty(ent); + } + + if (_random.Prob(0.3f) + && TryComp(ent, out var plunger)) + { + plunger.NeedsPlunger = true; + Dirty(ent, plunger); + } + + UpdateAppearance(ent); + } + + private void OnToggleSeatVerb(Entity ent, ref GetVerbsEvent args) + { + if (!args.CanInteract || !args.CanAccess || args.Hands == null || !CanToggle(ent)) + return; + + var user = args.User; + AlternativeVerb toggleVerb = new() { Act = () => ToggleToiletSeat(ent.AsNullable(), user) }; + + if (ent.Comp.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(Entity ent, ref ActivateInWorldEvent args) + { + if (args.Handled || !args.Complex) + return; + + args.Handled = true; + ToggleToiletSeat(ent.AsNullable(), args.User); + } + + private void UpdateAppearance(Entity ent) + { + _appearance.SetData(ent, + ToiletVisuals.SeatVisualState, + ent.Comp.ToggleSeat ? SeatVisualState.SeatUp : SeatVisualState.SeatDown); + } + + + /// + /// Toggles a toilet's seat. Yup. Doesn't check if anyone is on the seat. + /// + /// The toilet being seat-toggled. + /// The user doing the toggling; used for predicted audio. + /// + public void ToggleToiletSeat(Entity ent, EntityUid? user = null) + { + if (!Resolve(ent, ref ent.Comp)) + return; + + ent.Comp.ToggleSeat = !ent.Comp.ToggleSeat; + + _audio.PlayPredicted(ent.Comp.SeatSound, ent, user); + UpdateAppearance((ent, ent.Comp)); + Dirty(ent); + } + + /// + /// Whether or not a toilet seat can be toggled without phasing through + /// someone's back. (That is, no one is seated on it.) + /// + /// + public bool CanToggle(EntityUid uid) + { + return TryComp(uid, out var strap) && strap.BuckledEntities.Count == 0; + } +} diff --git a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml index 1b5ac30a9c..a6753766d5 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml @@ -75,6 +75,9 @@ autoDrain: false - type: StaticPrice price: 100 + - type: ActivatableUI + key: enum.DisposalUnitUiKey.Key + verbOnly: true # Not strictly needed, but we want E to toggle lid - type: UserInterface interfaces: enum.DisposalUnitUiKey.Key: