diff --git a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs index bd91aab4a2..102128b178 100644 --- a/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs +++ b/Content.Server/Disposal/Unit/EntitySystems/DisposalUnitSystem.cs @@ -8,6 +8,7 @@ using Content.Server.DoAfter; using Content.Server.Hands.Components; using Content.Server.Popups; using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; using Content.Shared.ActionBlocker; using Content.Shared.Atmos; using Content.Shared.Construction.Components; @@ -25,13 +26,11 @@ using Content.Shared.Popups; using Content.Shared.Throwing; using Content.Shared.Verbs; using Robust.Server.GameObjects; -using Robust.Shared.Audio; using Robust.Shared.Containers; -using Robust.Shared.Map; -using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Player; using Robust.Shared.Random; +using Robust.Shared.Map.Components; namespace Content.Server.Disposal.Unit.EntitySystems { @@ -50,6 +49,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly UserInterfaceSystem _ui = default!; + [Dependency] private readonly PowerReceiverSystem _power = default!; public override void Initialize() { @@ -223,13 +223,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):player} hit flush button on {ToPrettyString(uid)}, it's now {(component.Engaged ? "on" : "off")}"); break; case SharedDisposalUnitComponent.UiButton.Power: - TogglePower(component); - _audio.PlayPvs(new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"), component.Owner, - AudioParams.Default.WithVolume(-2f)); - if (EntityManager.TryGetComponent(component.Owner, out ApcPowerReceiverComponent? receiver)) - { - _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):player} hit power button on {ToPrettyString(uid)}, it's now {(!receiver.PowerDisabled ? "on" : "off")}"); - } + _power.TogglePower(uid, user: args.Session.AttachedEntity); break; default: throw new ArgumentOutOfRangeException(); @@ -249,17 +243,6 @@ namespace Content.Server.Disposal.Unit.EntitySystems Disengage(component); } } - - public void TogglePower(DisposalUnitComponent component) - { - if (!EntityManager.TryGetComponent(component.Owner, out ApcPowerReceiverComponent? receiver)) - { - return; - } - - receiver.PowerDisabled = !receiver.PowerDisabled; - UpdateInterface(component, receiver.Powered); - } #endregion #region Eventbus Handlers diff --git a/Content.Server/Power/Components/PowerSwitchComponent.cs b/Content.Server/Power/Components/PowerSwitchComponent.cs new file mode 100644 index 0000000000..3124557f81 --- /dev/null +++ b/Content.Server/Power/Components/PowerSwitchComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server.Power.Components +{ + /// + /// Provides an alt verb to toggle power. + /// + [RegisterComponent] + public sealed class PowerSwitchComponent : Component + {} +} diff --git a/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs b/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs index 467b29c5e1..1e605efb12 100644 --- a/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs +++ b/Content.Server/Power/EntitySystems/PowerReceiverSystem.cs @@ -1,14 +1,20 @@ using Content.Server.Power.Components; +using Content.Server.Hands.Components; +using Content.Server.Administration.Logs; using Content.Shared.Examine; using Content.Shared.Power; +using Content.Shared.Verbs; +using Content.Shared.Database; using Robust.Server.GameObjects; +using Robust.Shared.Audio; namespace Content.Server.Power.EntitySystems { public sealed class PowerReceiverSystem : EntitySystem { + [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly AppearanceSystem _appearance = default!; - + [Dependency] private readonly AudioSystem _audio = default!; public override void Initialize() { base.Initialize(); @@ -20,6 +26,8 @@ namespace Content.Server.Power.EntitySystems SubscribeLocalEvent(OnProviderShutdown); SubscribeLocalEvent(OnReceiverConnected); SubscribeLocalEvent(OnReceiverDisconnected); + + SubscribeLocalEvent>(AddSwitchPowerVerb); } /// @@ -78,6 +86,33 @@ namespace Content.Server.Power.EntitySystems } } + private void AddSwitchPowerVerb(EntityUid uid, PowerSwitchComponent component, GetVerbsEvent args) + { + if(!args.CanAccess || !args.CanInteract) + return; + + if (!HasComp(args.User)) + return; + + if (!TryComp(uid, out var receiver)) + return; + + if (!receiver.NeedsPower) + return; + + AlternativeVerb verb = new() + { + Act = () => + { + TogglePower(uid, user: args.User); + }, + IconTexture = "/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png", + Text = Loc.GetString("power-switch-component-toggle-verb"), + Priority = -3 + }; + args.Verbs.Add(verb); + } + private void ProviderChanged(ApcPowerReceiverComponent receiver) { receiver.NetworkLoad.LinkedNetwork = default; @@ -99,5 +134,35 @@ namespace Content.Server.Power.EntitySystems return receiver.Powered; } + + /// + /// Turn this machine on or off. + /// Returns true if we turned it on, false if we turned it off. + /// + public bool TogglePower(EntityUid uid, bool playSwitchSound = true, ApcPowerReceiverComponent? receiver = null, EntityUid? user = null) + { + if (!Resolve(uid, ref receiver, false)) + return true; + + // it'll save a lot of confusion if 'always powered' means 'always powered' + if (!receiver.NeedsPower) + { + receiver.PowerDisabled = false; + return true; + } + + receiver.PowerDisabled = !receiver.PowerDisabled; + + if (user != null) + _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(user.Value):player} hit power button on {ToPrettyString(uid)}, it's now {(!receiver.PowerDisabled ? "on" : "off")}"); + + if (playSwitchSound) + { + _audio.PlayPvs(new SoundPathSpecifier("/Audio/Machines/machine_switch.ogg"), uid, + AudioParams.Default.WithVolume(-2f)); + } + + return !receiver.PowerDisabled; // i.e. PowerEnabled + } } } diff --git a/Resources/Locale/en-US/power/components/power-switch-component.ftl b/Resources/Locale/en-US/power/components/power-switch-component.ftl new file mode 100644 index 0000000000..826b5c9fd0 --- /dev/null +++ b/Resources/Locale/en-US/power/components/power-switch-component.ftl @@ -0,0 +1 @@ +power-switch-component-toggle-verb = Toggle power diff --git a/Resources/Prototypes/Entities/Structures/Piping/Disposal/units.yml b/Resources/Prototypes/Entities/Structures/Piping/Disposal/units.yml index 76eaa94707..139c08d32f 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Disposal/units.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Disposal/units.yml @@ -76,6 +76,7 @@ DisposalUnit: !type:Container - type: StaticPrice price: 100 + - type: PowerSwitch - type: entity id: DisposalUnit @@ -92,7 +93,6 @@ - key: enum.DisposalUnitUiKey.Key type: DisposalUnitBoundUserInterface - - type: entity id: MailingUnit parent: DisposalUnitBase diff --git a/Resources/Textures/Interface/VerbIcons/Spare/path4.svg b/Resources/Textures/Interface/VerbIcons/Spare/path4.svg new file mode 100644 index 0000000000..e34684a6fd --- /dev/null +++ b/Resources/Textures/Interface/VerbIcons/Spare/path4.svg @@ -0,0 +1,40 @@ + + + + + + + + diff --git a/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg b/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg index ce880e4a57..18ba878ced 100644 --- a/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg +++ b/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg @@ -1 +1,54 @@ - \ No newline at end of file + + + + + + + + diff --git a/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png b/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png new file mode 100644 index 0000000000..dbacdd4abf Binary files /dev/null and b/Resources/Textures/Interface/VerbIcons/Spare/poweronoff.svg.192dpi.png differ