diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs
index c9e838f30b..88c4476301 100644
--- a/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs
+++ b/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs
@@ -42,7 +42,24 @@ namespace Content.Server.Atmos.Piping.Unary.Components
///
[ViewVariables(VVAccess.ReadWrite)]
[DataField("underPressureLockoutThreshold")]
- public float UnderPressureLockoutThreshold = 1;
+ public float UnderPressureLockoutThreshold = 2;
+
+ ///
+ /// Pressure locked vents still leak a little (leading to eventual pressurization of sealed sections)
+ ///
+ ///
+ /// Ratio of pressure difference between pipes and atmosphere that will leak each second, in moles.
+ /// If the pipes are 200 kPa and the room is spaced, at 0.01 UnderPressureLockoutLeaking, the room will fill
+ /// at a rate of 2 moles / sec. It will then reach 2 kPa (UnderPressureLockoutThreshold) and begin normal
+ /// filling after about 20 seconds (depending on room size).
+ ///
+ /// Since we want to prevent automating the work of atmos, the leaking rate of 0.0001f is set to make auto
+ /// repressurizing of the development map take about 30 minutes using an oxygen tank (high pressure)
+ ///
+
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("underPressureLockoutLeaking")]
+ public float UnderPressureLockoutLeaking = 0.0001f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("externalPressureBound")]
@@ -89,6 +106,17 @@ namespace Content.Server.Atmos.Piping.Unary.Components
[DataField("targetPressureChange")]
public float TargetPressureChange = Atmospherics.OneAtmosphere;
+ ///
+ /// Ratio of max output air pressure and pipe pressure, representing the vent's ability to increase pressure
+ ///
+ ///
+ /// 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
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("PumpPower")]
+ public float PumpPower = 2.0f;
+
#region Machine Linking
///
/// Whether or not machine linking is enabled for this component.
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
index 53ce579b1c..d14bc43d16 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
@@ -88,15 +88,18 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
if (environment.Pressure > vent.MaxPressure)
return;
- if (environment.Pressure < vent.UnderPressureLockoutThreshold)
- {
- vent.UnderPressureLockout = true;
- return;
- }
- vent.UnderPressureLockout = false;
+ vent.UnderPressureLockout = (environment.Pressure < vent.UnderPressureLockoutThreshold);
if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0)
- pressureDelta = MathF.Min(pressureDelta, vent.ExternalPressureBound - environment.Pressure);
+ {
+ // Vents cannot supply high pressures from an almost empty pipe, instead it's proportional to the pipe
+ // pressure, up to a limit.
+ // This also means supply pipe pressure indicates minimum pressure on the station, with lower pressure
+ // sections getting air first.
+ var supplyPressure = MathF.Min(pipe.Air.Pressure * vent.PumpPower, vent.ExternalPressureBound);
+ // Calculate the ratio of supply pressure to current pressure.
+ pressureDelta = MathF.Min(pressureDelta, supplyPressure - environment.Pressure);
+ }
if (pressureDelta <= 0)
return;
@@ -105,6 +108,15 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
// (ignoring temperature differences because I am lazy)
var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R);
+ if (vent.UnderPressureLockout)
+ {
+ // Leak only a small amount of gas as a proportion of supply pipe pressure.
+ var pipeDelta = pipe.Air.Pressure - environment.Pressure;
+ transferMoles = (float)timeDelta * pipeDelta * vent.UnderPressureLockoutLeaking;
+ if (transferMoles < 0.0)
+ return;
+ }
+
// limit transferMoles so the source doesn't go below its bound.
if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0)
{