GasVentPumpComponent.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using Content.Shared.Atmos;
  2. using Content.Shared.Atmos.Piping.Unary.Components;
  3. using Content.Shared.DeviceLinking;
  4. using Content.Shared.Guidebook;
  5. using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
  6. namespace Content.Server.Atmos.Piping.Unary.Components
  7. {
  8. // The world if people documented their shit.
  9. [AutoGenerateComponentPause]
  10. [RegisterComponent]
  11. public sealed partial class GasVentPumpComponent : Component
  12. {
  13. /// <summary>
  14. /// Identifies if the device is enabled by an air alarm. Does not indicate if the device is powered.
  15. /// By default, all air vents start enabled, whether linked to an alarm or not.
  16. /// </summary>
  17. [ViewVariables(VVAccess.ReadWrite)]
  18. public bool Enabled { get; set; } = true;
  19. [ViewVariables]
  20. public bool IsDirty { get; set; } = false;
  21. [DataField]
  22. public string Inlet { get; set; } = "pipe";
  23. [DataField]
  24. public string Outlet { get; set; } = "pipe";
  25. [DataField]
  26. public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing;
  27. [DataField]
  28. public VentPressureBound PressureChecks { get; set; } = VentPressureBound.ExternalBound;
  29. [DataField]
  30. public bool UnderPressureLockout { get; set; } = false;
  31. /// <summary>
  32. /// In releasing mode, do not pump when environment pressure is below this limit.
  33. /// </summary>
  34. [DataField]
  35. [GuidebookData]
  36. public float UnderPressureLockoutThreshold = 80; // this must be tuned in conjunction with atmos.mmos_spacing_speed
  37. /// <summary>
  38. /// Pressure locked vents still leak a little (leading to eventual pressurization of sealed sections)
  39. /// </summary>
  40. /// <remarks>
  41. /// Ratio of pressure difference between pipes and atmosphere that will leak each second, in moles.
  42. /// If the pipes are 200 kPa and the room is spaced, at 0.01 UnderPressureLockoutLeaking, the room will fill
  43. /// at a rate of 2 moles / sec. It will then reach 2 kPa (UnderPressureLockoutThreshold) and begin normal
  44. /// filling after about 20 seconds (depending on room size).
  45. ///
  46. /// Since we want to prevent automating the work of atmos, the leaking rate of 0.0001f is set to make auto
  47. /// repressurizing of the development map take about 30 minutes using an oxygen tank (high pressure)
  48. /// </remarks>
  49. [DataField]
  50. public float UnderPressureLockoutLeaking = 0.0001f;
  51. /// <summary>
  52. /// Is the vent pressure lockout currently manually disabled?
  53. /// </summary>
  54. [DataField]
  55. public bool IsPressureLockoutManuallyDisabled = false;
  56. /// <summary>
  57. /// The time when the manual pressure lockout will be reenabled.
  58. /// </summary>
  59. [DataField]
  60. [AutoPausedField]
  61. public TimeSpan ManualLockoutReenabledAt;
  62. /// <summary>
  63. /// How long the lockout should remain manually disabled after being interacted with.
  64. /// </summary>
  65. [DataField]
  66. public TimeSpan ManualLockoutDisabledDuration = TimeSpan.FromSeconds(30); // Enough time to fill a 5x5 room
  67. /// <summary>
  68. /// How long the doAfter should take when attempting to manually disable the pressure lockout.
  69. /// </summary>
  70. public float ManualLockoutDisableDoAfter = 2.0f;
  71. [DataField]
  72. public float ExternalPressureBound
  73. {
  74. get => _externalPressureBound;
  75. set
  76. {
  77. _externalPressureBound = Math.Clamp(value, 0, MaxPressure);
  78. }
  79. }
  80. private float _externalPressureBound = Atmospherics.OneAtmosphere;
  81. [DataField]
  82. public float InternalPressureBound
  83. {
  84. get => _internalPressureBound;
  85. set
  86. {
  87. _internalPressureBound = Math.Clamp(value, 0, MaxPressure);
  88. }
  89. }
  90. private float _internalPressureBound = 0;
  91. /// <summary>
  92. /// Max pressure of the target gas (NOT relative to source).
  93. /// </summary>
  94. [DataField]
  95. [GuidebookData]
  96. public float MaxPressure = Atmospherics.MaxOutputPressure;
  97. /// <summary>
  98. /// Pressure pump speed in kPa/s. Determines how much gas is moved.
  99. /// </summary>
  100. /// <remarks>
  101. /// The pump will attempt to modify the destination's final pressure by this quantity every second. If this
  102. /// is too high, and the vent is connected to a large pipe-net, then someone can nearly instantly flood a
  103. /// room with gas.
  104. /// </remarks>
  105. [DataField]
  106. public float TargetPressureChange = Atmospherics.OneAtmosphere;
  107. /// <summary>
  108. /// Ratio of max output air pressure and pipe pressure, representing the vent's ability to increase pressure
  109. /// </summary>
  110. /// <remarks>
  111. /// Vents cannot suck a pipe completely empty, instead pressurizing a section to a max of
  112. /// pipe pressure * PumpPower (in kPa). So a 51 kPa pipe is required for 101 kPA sections at PumpPower 2.0
  113. /// </remarks>
  114. [DataField]
  115. public float PumpPower = 2.0f;
  116. #region Machine Linking
  117. /// <summary>
  118. /// Whether or not machine linking is enabled for this component.
  119. /// </summary>
  120. [DataField]
  121. public bool CanLink = false;
  122. [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
  123. public string PressurizePort = "Pressurize";
  124. [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
  125. public string DepressurizePort = "Depressurize";
  126. [DataField]
  127. public float PressurizePressure = Atmospherics.OneAtmosphere;
  128. [DataField]
  129. public float DepressurizePressure = 0;
  130. // When true, ignore under-pressure lockout. Used to re-fill rooms in air alarm "Fill" mode.
  131. [DataField]
  132. public bool PressureLockoutOverride = false;
  133. #endregion
  134. public GasVentPumpData ToAirAlarmData()
  135. {
  136. return new GasVentPumpData
  137. {
  138. Enabled = Enabled,
  139. Dirty = IsDirty,
  140. PumpDirection = PumpDirection,
  141. PressureChecks = PressureChecks,
  142. ExternalPressureBound = ExternalPressureBound,
  143. InternalPressureBound = InternalPressureBound,
  144. PressureLockoutOverride = PressureLockoutOverride
  145. };
  146. }
  147. public void FromAirAlarmData(GasVentPumpData data)
  148. {
  149. Enabled = data.Enabled;
  150. IsDirty = data.Dirty;
  151. PumpDirection = data.PumpDirection;
  152. PressureChecks = data.PressureChecks;
  153. ExternalPressureBound = data.ExternalPressureBound;
  154. InternalPressureBound = data.InternalPressureBound;
  155. PressureLockoutOverride = data.PressureLockoutOverride;
  156. }
  157. #region GuidebookData
  158. [GuidebookData]
  159. public float DefaultExternalBound => Atmospherics.OneAtmosphere;
  160. #endregion
  161. }
  162. }