Files
OldThink/Content.Server/Power/EntitySystems/ApcSystem.cs

204 lines
7.6 KiB
C#
Raw Normal View History

2023-03-06 22:05:12 +03:00
using Content.Server.Emp;
2022-01-15 11:32:46 -07:00
using Content.Server.Popups;
using Content.Server.Power.Components;
2023-04-19 22:10:08 +12:00
using Content.Server.Power.Pow3r;
2022-01-15 11:32:46 -07:00
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.APC;
using Content.Shared.Emag.Components;
2022-02-17 21:43:24 -05:00
using Content.Shared.Emag.Systems;
using Content.Shared.Popups;
2022-01-15 11:32:46 -07:00
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Timing;
namespace Content.Server.Power.EntitySystems
{
[UsedImplicitly]
internal sealed class ApcSystem : EntitySystem
{
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly PopupSystem _popup = default!;
2022-01-15 11:32:46 -07:00
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
2022-01-15 11:32:46 -07:00
public override void Initialize()
{
base.Initialize();
UpdatesAfter.Add(typeof(PowerNetSystem));
SubscribeLocalEvent<ApcComponent, BoundUIOpenedEvent>(OnBoundUiOpen);
2022-01-15 11:32:46 -07:00
SubscribeLocalEvent<ApcComponent, MapInitEvent>(OnApcInit);
SubscribeLocalEvent<ApcComponent, ChargeChangedEvent>(OnBatteryChargeChanged);
SubscribeLocalEvent<ApcComponent, ApcToggleMainBreakerMessage>(OnToggleMainBreaker);
2022-02-17 21:43:24 -05:00
SubscribeLocalEvent<ApcComponent, GotEmaggedEvent>(OnEmagged);
2023-03-06 22:05:12 +03:00
SubscribeLocalEvent<ApcComponent, EmpPulseEvent>(OnEmpPulse);
2022-01-15 11:32:46 -07:00
}
// Change the APC's state only when the battery state changes, or when it's first created.
2023-04-19 22:10:08 +12:00
private void OnBatteryChargeChanged(EntityUid uid, ApcComponent component, ref ChargeChangedEvent args)
2022-01-15 11:32:46 -07:00
{
UpdateApcState(uid, component);
}
private void OnApcInit(EntityUid uid, ApcComponent component, MapInitEvent args)
{
UpdateApcState(uid, component);
}
//Update the HasAccess var for UI to read
private void OnBoundUiOpen(EntityUid uid, ApcComponent component, BoundUIOpenedEvent args)
{
TryComp<AccessReaderComponent>(uid, out var access);
if (args.Session.AttachedEntity == null)
return;
if (access == null || _accessReader.IsAllowed(args.Session.AttachedEntity.Value, access))
{
component.HasAccess = true;
}
else
{
component.HasAccess = false;
}
2023-04-20 09:27:59 +03:00
UpdateApcState(uid, component);
}
2022-01-15 11:32:46 -07:00
private void OnToggleMainBreaker(EntityUid uid, ApcComponent component, ApcToggleMainBreakerMessage args)
{
var attemptEv = new ApcToggleMainBreakerAttemptEvent();
RaiseLocalEvent(uid, ref attemptEv);
if (attemptEv.Cancelled)
{
_popup.PopupCursor(Loc.GetString("apc-component-on-toggle-cancel"),
args.Session, PopupType.Medium);
return;
}
2022-01-15 11:32:46 -07:00
TryComp<AccessReaderComponent>(uid, out var access);
if (args.Session.AttachedEntity == null)
return;
if (access == null || _accessReader.IsAllowed(args.Session.AttachedEntity.Value, access))
2022-01-15 11:32:46 -07:00
{
ApcToggleBreaker(uid, component);
2022-01-15 11:32:46 -07:00
}
else
{
_popup.PopupCursor(Loc.GetString("apc-component-insufficient-access"),
args.Session, PopupType.Medium);
2022-01-15 11:32:46 -07:00
}
}
public void ApcToggleBreaker(EntityUid uid, ApcComponent? apc = null, PowerNetworkBatteryComponent? battery = null)
{
if (!Resolve(uid, ref apc, ref battery))
return;
apc.MainBreakerEnabled = !apc.MainBreakerEnabled;
battery.CanDischarge = apc.MainBreakerEnabled;
UpdateUIState(uid, apc);
_audio.PlayPvs(apc.OnReceiveMessageSound, uid, AudioParams.Default.WithVolume(-2f));
}
private void OnEmagged(EntityUid uid, ApcComponent comp, ref GotEmaggedEvent args)
2022-02-17 21:43:24 -05:00
{
// no fancy conditions
args.Handled = true;
2022-02-17 21:43:24 -05:00
}
2022-01-15 11:32:46 -07:00
public void UpdateApcState(EntityUid uid,
ApcComponent? apc=null,
2023-04-19 22:10:08 +12:00
PowerNetworkBatteryComponent? battery = null)
2022-01-15 11:32:46 -07:00
{
if (!Resolve(uid, ref apc, ref battery))
return;
2023-04-19 22:10:08 +12:00
var newState = CalcChargeState(uid, battery.NetworkBattery);
2022-01-15 11:32:46 -07:00
if (newState != apc.LastChargeState && apc.LastChargeStateTime + ApcComponent.VisualsChangeDelay < _gameTiming.CurTime)
{
apc.LastChargeState = newState;
apc.LastChargeStateTime = _gameTiming.CurTime;
if (TryComp(uid, out AppearanceComponent? appearance))
2022-01-15 11:32:46 -07:00
{
_appearance.SetData(uid, ApcVisuals.ChargeState, newState, appearance);
2022-01-15 11:32:46 -07:00
}
}
2023-04-19 22:10:08 +12:00
var extPowerState = CalcExtPowerState(uid, battery.NetworkBattery);
2022-01-15 11:32:46 -07:00
if (extPowerState != apc.LastExternalState
|| apc.LastUiUpdate + ApcComponent.VisualsChangeDelay < _gameTiming.CurTime)
{
apc.LastExternalState = extPowerState;
apc.LastUiUpdate = _gameTiming.CurTime;
UpdateUIState(uid, apc, battery);
}
}
public void UpdateUIState(EntityUid uid,
ApcComponent? apc = null,
2023-04-19 22:10:08 +12:00
PowerNetworkBatteryComponent? netBat = null,
2022-01-15 11:32:46 -07:00
ServerUserInterfaceComponent? ui = null)
{
2023-04-19 22:10:08 +12:00
if (!Resolve(uid, ref apc, ref netBat, ref ui))
2022-01-15 11:32:46 -07:00
return;
2023-04-19 22:10:08 +12:00
var battery = netBat.NetworkBattery;
2023-02-21 07:23:38 -08:00
2023-04-19 22:10:08 +12:00
var state = new ApcBoundInterfaceState(apc.MainBreakerEnabled, apc.HasAccess,
(int) MathF.Ceiling(battery.CurrentSupply), apc.LastExternalState,
2023-04-23 11:22:09 +03:00
battery.CurrentStorage / battery.Capacity);
2023-04-19 22:10:08 +12:00
_ui.TrySetUiState(uid, ApcUiKey.Key, state, ui: ui);
2022-01-15 11:32:46 -07:00
}
2023-04-19 22:10:08 +12:00
private ApcChargeState CalcChargeState(EntityUid uid, PowerState.Battery battery)
2022-01-15 11:32:46 -07:00
{
2023-04-19 22:10:08 +12:00
if (HasComp<EmaggedComponent>(uid))
2022-02-17 21:43:24 -05:00
return ApcChargeState.Emag;
2023-04-19 22:10:08 +12:00
if (battery.CurrentStorage / battery.Capacity > ApcComponent.HighPowerThreshold)
2022-01-15 11:32:46 -07:00
{
return ApcChargeState.Full;
}
2023-04-19 22:10:08 +12:00
var delta = battery.CurrentSupply - battery.CurrentReceiving;
2022-01-15 11:32:46 -07:00
return delta < 0 ? ApcChargeState.Charging : ApcChargeState.Lack;
}
2023-04-19 22:10:08 +12:00
private ApcExternalPowerState CalcExtPowerState(EntityUid uid, PowerState.Battery battery)
2022-01-15 11:32:46 -07:00
{
2023-04-19 22:10:08 +12:00
if (battery.CurrentReceiving == 0 && !MathHelper.CloseTo(battery.CurrentStorage / battery.Capacity, 1))
2022-01-15 11:32:46 -07:00
{
return ApcExternalPowerState.None;
}
2023-04-19 22:10:08 +12:00
var delta = battery.CurrentSupply - battery.CurrentReceiving;
2022-01-15 11:32:46 -07:00
if (!MathHelper.CloseToPercent(delta, 0, 0.1f) && delta < 0)
{
return ApcExternalPowerState.Low;
}
return ApcExternalPowerState.Good;
}
2023-03-06 22:05:12 +03:00
private void OnEmpPulse(EntityUid uid, ApcComponent component, ref EmpPulseEvent args)
{
if (component.MainBreakerEnabled)
{
args.Affected = true;
args.Disabled = true;
2023-03-06 22:05:12 +03:00
ApcToggleBreaker(uid, component);
}
}
2022-01-15 11:32:46 -07:00
}
[ByRefEvent]
public record struct ApcToggleMainBreakerAttemptEvent(bool Cancelled);
2022-01-15 11:32:46 -07:00
}