diff --git a/Content.Server/Power/Components/BreakerComponent.cs b/Content.Server/Power/Components/BreakerComponent.cs new file mode 100644 index 0000000000..bc58956879 --- /dev/null +++ b/Content.Server/Power/Components/BreakerComponent.cs @@ -0,0 +1,14 @@ +using Content.Server.Power.EntitySystems; + +namespace Content.Server.Power.Components; + +[RegisterComponent] +[Access(typeof(BreakerSystem))] +public sealed class BreakerComponent : Component +{ + /// + /// Once power supplied exceeds this limit the breaker will pop. + /// + [DataField("limit", required: true), ViewVariables(VVAccess.ReadWrite)] + public float Limit; +} diff --git a/Content.Server/Power/EntitySystems/ApcSystem.cs b/Content.Server/Power/EntitySystems/ApcSystem.cs index db07eb7aa9..4df8c33c5b 100644 --- a/Content.Server/Power/EntitySystems/ApcSystem.cs +++ b/Content.Server/Power/EntitySystems/ApcSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Emp; using Content.Server.Popups; using Content.Server.Power.Components; +using Content.Server.Power.Events; using Content.Server.Power.Pow3r; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; @@ -36,6 +37,7 @@ namespace Content.Server.Power.EntitySystems SubscribeLocalEvent(OnBatteryChargeChanged); SubscribeLocalEvent(OnToggleMainBreaker); SubscribeLocalEvent(OnEmagged); + SubscribeLocalEvent(OnBreakerPopped); SubscribeLocalEvent(OnEmpPulse); } @@ -111,6 +113,18 @@ namespace Content.Server.Power.EntitySystems args.Handled = true; } + private void OnBreakerPopped(EntityUid uid, ApcComponent comp, BreakerPoppedEvent args) + { + // already disabled, do nothing + if (!comp.MainBreakerEnabled) + return; + + ApcToggleBreaker(uid, comp); + + // popup so its clear what happened + _popup.PopupEntity(Loc.GetString("apc-component-breaker-popped"), uid); + } + public void UpdateApcState(EntityUid uid, ApcComponent? apc=null, PowerNetworkBatteryComponent? battery = null) diff --git a/Content.Server/Power/EntitySystems/BreakerSystem.cs b/Content.Server/Power/EntitySystems/BreakerSystem.cs new file mode 100644 index 0000000000..f8333c3147 --- /dev/null +++ b/Content.Server/Power/EntitySystems/BreakerSystem.cs @@ -0,0 +1,30 @@ +using Content.Server.Administration.Logs; +using Content.Server.Power.Components; +using Content.Server.Power.Events; +using Content.Shared.Database; + +namespace Content.Server.Power.EntitySystems; + +/// +/// Handles raising BreakerPopEvent when a power provider exceeds its maximum power. +/// +public sealed class BreakerSystem : EntitySystem +{ + [Dependency] private readonly IAdminLogManager _adminLogger = default!; + + /// + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var breaker, out var battery)) + { + if (battery.CurrentSupply > breaker.Limit) + { + _adminLogger.Add(LogType.Action, LogImpact.Low, $"Breaker of {ToPrettyString(uid):battery)} popped from supplying {battery.CurrentSupply} with a breaker limit of {breaker.Limit}"); + RaiseLocalEvent(uid, new BreakerPoppedEvent()); + } + } + } +} diff --git a/Content.Server/Power/Events/BreakerPoppedEvent.cs b/Content.Server/Power/Events/BreakerPoppedEvent.cs new file mode 100644 index 0000000000..930d1fa2bb --- /dev/null +++ b/Content.Server/Power/Events/BreakerPoppedEvent.cs @@ -0,0 +1,8 @@ +namespace Content.Server.Power.Events; + +/// +/// Invoked on a target power provider when its power exceeds BreakerComponent MaxPower, popping the breaker or blowing the fuse. +/// +public sealed class BreakerPoppedEvent : EntityEventArgs +{ +} diff --git a/Resources/Locale/en-US/apc/components/apc-component.ftl b/Resources/Locale/en-US/apc/components/apc-component.ftl index 6e152adb1d..8348bbf00d 100644 --- a/Resources/Locale/en-US/apc/components/apc-component.ftl +++ b/Resources/Locale/en-US/apc/components/apc-component.ftl @@ -2,3 +2,4 @@ apc-component-insufficient-access = Insufficient access! apc-component-on-examine-panel-open = The [color=lightgray]APC electronics panel[/color] is [color=red]open[/color]. apc-component-on-examine-panel-closed = The [color=lightgray]APC electronics panel[/color] is [color=darkgreen]closed[/color]. apc-component-on-toggle-cancel = It does nothing! +apc-component-breaker-popped = The APC's breaker popped! diff --git a/Resources/Prototypes/Entities/Structures/Power/apc.yml b/Resources/Prototypes/Entities/Structures/Power/apc.yml index 45d08af354..236c066762 100644 --- a/Resources/Prototypes/Entities/Structures/Power/apc.yml +++ b/Resources/Prototypes/Entities/Structures/Power/apc.yml @@ -70,6 +70,9 @@ voltage: Medium - type: PowerProvider voltage: Apc + - type: Breaker + # 100A at 240V - 24kW + limit: 24000 - type: Apc voltage: Apc - type: ExtensionCableProvider