Files
wwdpublic/Content.Server/Power/Generator/GasPowerReceiverSystem.cs
RedFoxIV 17ea2b7853 EE - Power Supply and Load Stuff (#1033)
* Power Supply and Load Stuff (#2505)

# Description

Changes how `ApcPowerReceiverComponent` works a bit.
Separated the `Load` variable into main and side power loads.
If main power demand is not met, the machine is considered unpowered.
Side power demand is "optional", as can be met only partially (or not at
all) and the device will continue to operate.
Depending on the device, this may have different negative effects on its
operaton. such as lights dimming and weapon rechargers not charging at
full speed.

This was first intended to fix an annoying bug with `ChargerComponent`
and `ApcPowerReceiverBatteryComponent`, that made the powernet spaz out
for a while if their power demand was too high.
This is now fixed.

---

<details><summary><h1>Media</h1></summary>
<p>

<details><summary>Before (heavy flashing lights)</summary>
<p>


https://github.com/user-attachments/assets/de7fb84f-54d0-4c8a-ba9e-7a97e8489980

</p>
</details>

<details><summary>After</summary>
<p>


https://github.com/user-attachments/assets/9cece608-24f7-4ec9-95cd-0c719c7beddb

</p>
</details>

</p>
</details>

---

# Changelog

🆑
- fix: Chargers and energy turrets no longer make the lights flash
rapidly if their power draw is too high
- add: Lights dim if the powernet they're connected to is overloaded

* больно много жрёт

---------

Co-authored-by: VMSolidus <evilexecutive@gmail.com>
2026-01-18 00:39:43 +03:00

81 lines
2.9 KiB
C#

using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos;
using Content.Shared.Power;
namespace Content.Server.Power.Generator;
/// <summary>
/// This handles gas power receivers, allowing devices to accept power in the form of a gas.
/// </summary>
public sealed class GasPowerReceiverSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<GasPowerReceiverComponent, AtmosDeviceUpdateEvent>(OnDeviceUpdated);
}
private void OnDeviceUpdated(EntityUid uid, GasPowerReceiverComponent component, ref AtmosDeviceUpdateEvent args)
{
var timeDelta = args.dt;
if (!_nodeContainer.TryGetNode(uid, "pipe", out PipeNode? pipe))
return;
// if we're below the max temperature, then we are simply consuming our target gas
if (pipe.Air.Temperature <= component.MaxTemperature)
{
// we have enough gas, so we consume it and are powered
if (pipe.Air[(int) component.TargetGas] > component.MolesConsumedSec * timeDelta)
{
pipe.Air.AdjustMoles(component.TargetGas, -component.MolesConsumedSec * timeDelta);
SetPowered(uid, component, true);
}
else // we do not have enough gas, so we power off
{
SetPowered(uid, component, false);
}
}
else // we are exceeding the max temp and are now operating in pressure mode
{
var pres = component.PressureConsumedSec * timeDelta;
if (pipe.Air.Pressure >= pres)
{
// remove gas from the pipe
var res = pipe.Air.Remove(pres * 100.0f / (Atmospherics.R * pipe.Air.Temperature));
if (component.OffVentGas)
{
// eject the gas into the atmosphere
var mix = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, false, true);
if (mix is not null)
_atmosphereSystem.Merge(res, mix);
}
SetPowered(uid, component, true);
}
else // if we do not have high enough pressure to operate, power off
{
SetPowered(uid, component, false);
}
}
}
private void SetPowered(EntityUid uid, GasPowerReceiverComponent comp, bool state)
{
if (state != comp.Powered)
{
comp.Powered = state;
var ev = new PowerChangedEvent(state, 0);
RaiseLocalEvent(uid, ref ev);
}
}
}