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; } }