Makes it possible to disable the vent pressure lockout temporarily with a screwdriver (#31050)

* builds

* doesn't crash

* seems to work

* distance cap was dumb

* Requested changes

* can't find any issues from making the changes

* Check for anchor and minor optimisation

* Removed unnecessary usings

* Code less verbose and cleanup
This commit is contained in:
PotentiallyTom
2024-09-22 20:59:56 +01:00
committed by GitHub
parent f8514e7815
commit d3ff4d5401
3 changed files with 85 additions and 39 deletions

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
namespace Content.Server.Atmos.Piping.Unary.Components namespace Content.Server.Atmos.Piping.Unary.Components
{ {
// The world if people documented their shit. // The world if people documented their shit.
[AutoGenerateComponentPause]
[RegisterComponent] [RegisterComponent]
public sealed partial class GasVentPumpComponent : Component public sealed partial class GasVentPumpComponent : Component
{ {
@@ -15,31 +16,25 @@ namespace Content.Server.Atmos.Piping.Unary.Components
[ViewVariables] [ViewVariables]
public bool IsDirty { get; set; } = false; public bool IsDirty { get; set; } = false;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("inlet")]
public string Inlet { get; set; } = "pipe"; public string Inlet { get; set; } = "pipe";
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("outlet")]
public string Outlet { get; set; } = "pipe"; public string Outlet { get; set; } = "pipe";
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("pumpDirection")]
public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing; public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("pressureChecks")]
public VentPressureBound PressureChecks { get; set; } = VentPressureBound.ExternalBound; public VentPressureBound PressureChecks { get; set; } = VentPressureBound.ExternalBound;
[ViewVariables(VVAccess.ReadOnly)] [DataField]
[DataField("underPressureLockout")]
public bool UnderPressureLockout { get; set; } = false; public bool UnderPressureLockout { get; set; } = false;
/// <summary> /// <summary>
/// In releasing mode, do not pump when environment pressure is below this limit. /// In releasing mode, do not pump when environment pressure is below this limit.
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("underPressureLockoutThreshold")]
public float UnderPressureLockoutThreshold = 80; // this must be tuned in conjunction with atmos.mmos_spacing_speed public float UnderPressureLockoutThreshold = 80; // this must be tuned in conjunction with atmos.mmos_spacing_speed
/// <summary> /// <summary>
@@ -55,12 +50,30 @@ namespace Content.Server.Atmos.Piping.Unary.Components
/// repressurizing of the development map take about 30 minutes using an oxygen tank (high pressure) /// repressurizing of the development map take about 30 minutes using an oxygen tank (high pressure)
/// </remarks> /// </remarks>
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("underPressureLockoutLeaking")]
public float UnderPressureLockoutLeaking = 0.0001f; public float UnderPressureLockoutLeaking = 0.0001f;
/// <summary>
/// Is the vent pressure lockout currently manually disabled?
/// </summary>
[DataField]
public bool IsPressureLockoutManuallyDisabled = false;
/// <summary>
/// The time when the manual pressure lockout will be reenabled.
/// </summary>
[DataField]
[AutoPausedField]
public TimeSpan ManualLockoutReenabledAt;
/// <summary>
/// How long the lockout should remain manually disabled after being interacted with.
/// </summary>
[DataField]
public TimeSpan ManualLockoutDisabledDuration = TimeSpan.FromSeconds(30); // Enough time to fill a 5x5 room
/// <summary>
/// How long the doAfter should take when attempting to manually disable the pressure lockout.
/// </summary>
public float ManualLockoutDisableDoAfter = 2.0f;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("externalPressureBound")]
public float ExternalPressureBound public float ExternalPressureBound
{ {
get => _externalPressureBound; get => _externalPressureBound;
@@ -72,8 +85,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
private float _externalPressureBound = Atmospherics.OneAtmosphere; private float _externalPressureBound = Atmospherics.OneAtmosphere;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("internalPressureBound")]
public float InternalPressureBound public float InternalPressureBound
{ {
get => _internalPressureBound; get => _internalPressureBound;
@@ -88,8 +100,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
/// <summary> /// <summary>
/// Max pressure of the target gas (NOT relative to source). /// Max pressure of the target gas (NOT relative to source).
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("maxPressure")]
public float MaxPressure = Atmospherics.MaxOutputPressure; public float MaxPressure = Atmospherics.MaxOutputPressure;
/// <summary> /// <summary>
@@ -100,8 +111,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
/// is too high, and the vent is connected to a large pipe-net, then someone can nearly instantly flood a /// is too high, and the vent is connected to a large pipe-net, then someone can nearly instantly flood a
/// room with gas. /// room with gas.
/// </remarks> /// </remarks>
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("targetPressureChange")]
public float TargetPressureChange = Atmospherics.OneAtmosphere; public float TargetPressureChange = Atmospherics.OneAtmosphere;
/// <summary> /// <summary>
@@ -111,29 +121,26 @@ namespace Content.Server.Atmos.Piping.Unary.Components
/// Vents cannot suck a pipe completely empty, instead pressurizing a section to a max of /// Vents cannot suck a pipe completely empty, instead pressurizing a section to a max of
/// pipe pressure * PumpPower (in kPa). So a 51 kPa pipe is required for 101 kPA sections at PumpPower 2.0 /// pipe pressure * PumpPower (in kPa). So a 51 kPa pipe is required for 101 kPA sections at PumpPower 2.0
/// </remarks> /// </remarks>
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("PumpPower")]
public float PumpPower = 2.0f; public float PumpPower = 2.0f;
#region Machine Linking #region Machine Linking
/// <summary> /// <summary>
/// Whether or not machine linking is enabled for this component. /// Whether or not machine linking is enabled for this component.
/// </summary> /// </summary>
[DataField("canLink")] [DataField]
public bool CanLink = false; public bool CanLink = false;
[DataField("pressurizePort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))] [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string PressurizePort = "Pressurize"; public string PressurizePort = "Pressurize";
[DataField("depressurizePort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))] [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string DepressurizePort = "Depressurize"; public string DepressurizePort = "Depressurize";
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("pressurizePressure")]
public float PressurizePressure = Atmospherics.OneAtmosphere; public float PressurizePressure = Atmospherics.OneAtmosphere;
[ViewVariables(VVAccess.ReadWrite)] [DataField]
[DataField("depressurizePressure")]
public float DepressurizePressure = 0; public float DepressurizePressure = 0;
// When true, ignore under-pressure lockout. Used to re-fill rooms in air alarm "Fill" mode. // When true, ignore under-pressure lockout. Used to re-fill rooms in air alarm "Fill" mode.

View File

@@ -7,21 +7,22 @@ using Content.Server.DeviceLinking.Systems;
using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems; using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems; using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes; using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Piping.Unary;
using Content.Shared.Atmos.Piping.Unary.Components; using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Atmos.Visuals; using Content.Shared.Atmos.Visuals;
using Content.Shared.Audio; using Content.Shared.Audio;
using Content.Shared.DeviceNetwork; using Content.Shared.DeviceNetwork;
using Content.Shared.DoAfter;
using Content.Shared.Examine; using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Power; using Content.Shared.Power;
using Content.Shared.Tools.Systems; using Content.Shared.Tools.Systems;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects; using Robust.Shared.Timing;
namespace Content.Server.Atmos.Piping.Unary.EntitySystems namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{ {
@@ -35,7 +36,9 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!; [Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly WeldableSystem _weldable = default!; [Dependency] private readonly WeldableSystem _weldable = default!;
[Dependency] private readonly SharedToolSystem _toolSystem = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -51,6 +54,8 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
SubscribeLocalEvent<GasVentPumpComponent, SignalReceivedEvent>(OnSignalReceived); SubscribeLocalEvent<GasVentPumpComponent, SignalReceivedEvent>(OnSignalReceived);
SubscribeLocalEvent<GasVentPumpComponent, GasAnalyzerScanEvent>(OnAnalyzed); SubscribeLocalEvent<GasVentPumpComponent, GasAnalyzerScanEvent>(OnAnalyzed);
SubscribeLocalEvent<GasVentPumpComponent, WeldableChangedEvent>(OnWeldChanged); SubscribeLocalEvent<GasVentPumpComponent, WeldableChangedEvent>(OnWeldChanged);
SubscribeLocalEvent<GasVentPumpComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<GasVentPumpComponent, VentScrewedDoAfterEvent>(OnVentScrewed);
} }
private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, ref AtmosDeviceUpdateEvent args) private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, ref AtmosDeviceUpdateEvent args)
@@ -80,11 +85,16 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{ {
return; return;
} }
// If the lockout has expired, disable it.
if (vent.IsPressureLockoutManuallyDisabled && _timing.CurTime >= vent.ManualLockoutReenabledAt)
{
vent.IsPressureLockoutManuallyDisabled = false;
}
var timeDelta = args.dt; var timeDelta = args.dt;
var pressureDelta = timeDelta * vent.TargetPressureChange; var pressureDelta = timeDelta * vent.TargetPressureChange;
var lockout = (environment.Pressure < vent.UnderPressureLockoutThreshold); var lockout = (environment.Pressure < vent.UnderPressureLockoutThreshold) && !vent.IsPressureLockoutManuallyDisabled;
if (vent.UnderPressureLockout != lockout) // update visuals only if this changes if (vent.UnderPressureLockout != lockout) // update visuals only if this changes
{ {
vent.UnderPressureLockout = lockout; vent.UnderPressureLockout = lockout;
@@ -115,7 +125,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R); var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R);
// Only run if the device is under lockout and not being overriden // Only run if the device is under lockout and not being overriden
if (vent.UnderPressureLockout & !vent.PressureLockoutOverride) if (vent.UnderPressureLockout & !vent.PressureLockoutOverride & !vent.IsPressureLockoutManuallyDisabled)
{ {
// Leak only a small amount of gas as a proportion of supply pipe pressure. // Leak only a small amount of gas as a proportion of supply pipe pressure.
var pipeDelta = pipe.Air.Pressure - environment.Pressure; var pipeDelta = pipe.Air.Pressure - environment.Pressure;
@@ -273,7 +283,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
} }
else if (vent.PumpDirection == VentPumpDirection.Releasing) else if (vent.PumpDirection == VentPumpDirection.Releasing)
{ {
if (vent.UnderPressureLockout & !vent.PressureLockoutOverride) if (vent.UnderPressureLockout & !vent.PressureLockoutOverride & !vent.IsPressureLockoutManuallyDisabled)
_appearance.SetData(uid, VentPumpVisuals.State, VentPumpState.Lockout, appearance); _appearance.SetData(uid, VentPumpVisuals.State, VentPumpState.Lockout, appearance);
else else
_appearance.SetData(uid, VentPumpVisuals.State, VentPumpState.Out, appearance); _appearance.SetData(uid, VentPumpVisuals.State, VentPumpState.Out, appearance);
@@ -290,7 +300,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
return; return;
if (args.IsInDetailsRange) if (args.IsInDetailsRange)
{ {
if (pumpComponent.PumpDirection == VentPumpDirection.Releasing & pumpComponent.UnderPressureLockout & !pumpComponent.PressureLockoutOverride) if (pumpComponent.PumpDirection == VentPumpDirection.Releasing & pumpComponent.UnderPressureLockout & !pumpComponent.PressureLockoutOverride & !pumpComponent.IsPressureLockoutManuallyDisabled)
{ {
args.PushMarkup(Loc.GetString("gas-vent-pump-uvlo")); args.PushMarkup(Loc.GetString("gas-vent-pump-uvlo"));
} }
@@ -325,5 +335,25 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{ {
UpdateState(uid, component); UpdateState(uid, component);
} }
private void OnInteractUsing(EntityUid uid, GasVentPumpComponent component, InteractUsingEvent args)
{
if (args.Handled
|| component.UnderPressureLockout == false
|| !_toolSystem.HasQuality(args.Used, "Screwing")
|| !Transform(uid).Anchored
)
{
return;
}
args.Handled = true;
_doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.ManualLockoutDisableDoAfter, new VentScrewedDoAfterEvent(), uid, uid, args.Used));
}
private void OnVentScrewed(EntityUid uid, GasVentPumpComponent component, VentScrewedDoAfterEvent args)
{
component.ManualLockoutReenabledAt = _timing.CurTime + component.ManualLockoutDisabledDuration;
component.IsPressureLockoutManuallyDisabled = true;
}
} }
} }

View File

@@ -0,0 +1,9 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared.Atmos.Piping.Unary;
[Serializable, NetSerializable]
public sealed partial class VentScrewedDoAfterEvent : SimpleDoAfterEvent
{
}