diff --git a/Content.Server/Body/Systems/InternalsSystem.cs b/Content.Server/Body/Systems/InternalsSystem.cs index 29c2c363d2..93dedf5fff 100644 --- a/Content.Server/Body/Systems/InternalsSystem.cs +++ b/Content.Server/Body/Systems/InternalsSystem.cs @@ -50,7 +50,7 @@ public sealed class InternalsSystem : SharedInternalsSystem if (!_respirator.CanMetabolizeGas(uid, tank.Value.Comp.Air)) return; - ToggleInternals(uid, uid, force: false, component); + ToggleInternals(uid, uid, force: false, component, ToggleMode.On); } private void OnInhaleLocation(Entity ent, ref InhaleLocationEvent args) diff --git a/Content.Shared/Body/Systems/SharedInternalsSystem.cs b/Content.Shared/Body/Systems/SharedInternalsSystem.cs index 0924d7a99e..7749432281 100644 --- a/Content.Shared/Body/Systems/SharedInternalsSystem.cs +++ b/Content.Shared/Body/Systems/SharedInternalsSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Atmos.EntitySystems; using Content.Shared.Body.Components; using Content.Shared.DoAfter; using Content.Shared.Hands.Components; +using Content.Shared.IdentityManagement; using Content.Shared.Internals; using Content.Shared.Inventory; using Content.Shared.Popups; @@ -50,73 +51,91 @@ public abstract class SharedInternalsSystem : EntitySystem InteractionVerb verb = new() { - Act = () => - { - ToggleInternals(ent, user, force: false, ent); - }, - Message = Loc.GetString("action-description-internals-toggle"), Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/dot.svg.192dpi.png")), - Text = Loc.GetString("action-name-internals-toggle"), }; + if (AreInternalsWorking(ent)) + { + verb.Act = () => ToggleInternals(ent, user, force: false, ent, ToggleMode.Off); + verb.Message = Loc.GetString("action-description-internals-toggle-off"); + verb.Text = Loc.GetString("action-name-internals-toggle-off"); + } + else + { + verb.Act = () => ToggleInternals(ent, user, force: false, ent, ToggleMode.On); + verb.Message = Loc.GetString("action-description-internals-toggle-on"); + verb.Text = Loc.GetString("action-name-internals-toggle-on"); + } + args.Verbs.Add(verb); } - public bool ToggleInternals( - EntityUid uid, + protected bool ToggleInternals( + EntityUid target, EntityUid user, bool force, - InternalsComponent? internals = null) + InternalsComponent? internals = null, + ToggleMode mode = ToggleMode.Toggle) { - if (!Resolve(uid, ref internals, logMissing: false)) + if (!Resolve(target, ref internals, logMissing: false)) return false; // Check if a mask is present. if (internals.BreathTools.Count == 0) { - _popupSystem.PopupClient(Loc.GetString("internals-no-breath-tool"), uid, user); + var message = user == target ? Loc.GetString("internals-self-no-breath-tool") : Loc.GetString("internals-other-no-breath-tool", ("ent", Identity.Name(target, EntityManager, user))); + _popupSystem.PopupClient(message, target, user); + return false; + } + + // Check if tank is present. + var tank = FindBestGasTank(target); + + // If they're not on then check if we have a mask to use + if (tank == null) + { + var message = user == target ? Loc.GetString("internals-self-no-tank") : Loc.GetString("internals-other-no-tank", ("ent", Identity.Name(target, EntityManager, user))); + _popupSystem.PopupClient(message, target, user); return false; } // Start the toggle do-after if it's on someone else. - if (!force && user != uid) + if (!force && user != target) { - return StartToggleInternalsDoAfter(user, (uid, internals)); + return StartToggleInternalsDoAfter(user, (target, internals), mode); } // Toggle off. if (TryComp(internals.GasTankEntity, out GasTankComponent? gas)) { + if (mode == ToggleMode.On) + return false; + return _gasTank.DisconnectFromInternals((internals.GasTankEntity.Value, gas), user); } - else - { - // Check if tank is present. - var tank = FindBestGasTank(uid); - // If they're not on then check if we have a mask to use - if (tank == null) - { - _popupSystem.PopupClient(Loc.GetString("internals-no-tank"), uid, user); - return false; - } + // No tank was connected, we’ll try to toggle internals on - return _gasTank.ConnectToInternals(tank.Value, user: user); - } + // If the intent was to disable internals there’s nothing left to do + if (mode == ToggleMode.Off) + return false; + + return _gasTank.ConnectToInternals(tank.Value, user: user); } - private bool StartToggleInternalsDoAfter(EntityUid user, Entity targetEnt) + private bool StartToggleInternalsDoAfter(EntityUid user, Entity targetEnt, ToggleMode mode) { // Is the target not you? If yes, use a do-after to give them time to respond. var isUser = user == targetEnt.Owner; var delay = !isUser ? targetEnt.Comp.Delay : TimeSpan.Zero; - return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, delay, new InternalsDoAfterEvent(), targetEnt, target: targetEnt) - { - BreakOnDamage = true, - BreakOnMove = true, - MovementThreshold = 0.1f, - }); + return _doAfter.TryStartDoAfter( + new DoAfterArgs(EntityManager, user, delay, new InternalsDoAfterEvent(mode), targetEnt, target: targetEnt) + { + BreakOnDamage = true, + BreakOnMove = true, + MovementThreshold = 0.1f, + }); } private void OnDoAfter(Entity ent, ref InternalsDoAfterEvent args) @@ -124,7 +143,7 @@ public abstract class SharedInternalsSystem : EntitySystem if (args.Cancelled || args.Handled) return; - ToggleInternals(ent, args.User, force: true, ent); + ToggleInternals(ent, args.User, force: true, ent, args.ToggleMode); args.Handled = true; } diff --git a/Content.Shared/Internals/InternalsDoAfterEvent.cs b/Content.Shared/Internals/InternalsDoAfterEvent.cs index 9c0174b4fd..66c2bd9327 100644 --- a/Content.Shared/Internals/InternalsDoAfterEvent.cs +++ b/Content.Shared/Internals/InternalsDoAfterEvent.cs @@ -4,9 +4,24 @@ using Robust.Shared.Serialization; namespace Content.Shared.Internals; -[Serializable, NetSerializable] -public sealed partial class InternalsDoAfterEvent : SimpleDoAfterEvent +public enum ToggleMode { + Toggle, + On, + Off +} + +[Serializable, NetSerializable] +public sealed partial class InternalsDoAfterEvent : DoAfterEvent +{ + public ToggleMode ToggleMode = ToggleMode.Toggle; + + public InternalsDoAfterEvent(ToggleMode mode) + { + ToggleMode = mode; + } + + public override DoAfterEvent Clone() => this; } public sealed partial class ToggleInternalsAlertEvent : BaseAlertEvent; diff --git a/Resources/Locale/en-US/actions/actions/internals.ftl b/Resources/Locale/en-US/actions/actions/internals.ftl index ead73cf1e5..e55a51f3d5 100644 --- a/Resources/Locale/en-US/actions/actions/internals.ftl +++ b/Resources/Locale/en-US/actions/actions/internals.ftl @@ -1,5 +1,9 @@ -action-name-internals-toggle = Toggle Internals -action-description-internals-toggle = Breathe from the equipped gas tank. Also requires equipped breath mask. +action-name-internals-toggle-on = Toggle Internals On +action-description-internals-toggle-on = Breathe from the equipped gas tank. Also requires equipped breath mask. +action-name-internals-toggle-off = Toggle Internals Off +action-description-internals-toggle-off = Breathe from the environment. -internals-no-breath-tool = You are not wearing a breathing tool -internals-no-tank = You are not wearing a gas tank +internals-self-no-breath-tool = You are not wearing a breathing tool +internals-other-no-breath-tool = {$ent} is not wearing a breathing tool +internals-self-no-tank = You are not wearing a gas tank +internals-other-no-tank = {$ent} is not wearing a gas tank