From e8defe373c56b4157fc00e816d8dd09c1fc1cb86 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Wed, 11 Oct 2023 14:12:11 -0700 Subject: [PATCH 1/3] Add pipe node pressure limits --- .../NodeContainer/NodeGroups/PipeNet.cs | 30 +++++++++++++++++++ .../NodeContainer/Nodes/PipeNode.cs | 6 ++++ 2 files changed, 36 insertions(+) diff --git a/Content.Server/NodeContainer/NodeGroups/PipeNet.cs b/Content.Server/NodeContainer/NodeGroups/PipeNet.cs index e905a6e78e87bb..8c37a9625d00de 100644 --- a/Content.Server/NodeContainer/NodeGroups/PipeNet.cs +++ b/Content.Server/NodeContainer/NodeGroups/PipeNet.cs @@ -3,6 +3,7 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.NodeContainer.Nodes; using Content.Shared.Atmos; +using Content.Shared.Damage; using Robust.Shared.Utility; namespace Content.Server.NodeContainer.NodeGroups @@ -21,6 +22,7 @@ public sealed class PipeNet : BaseNodeGroup, IPipeNet [ViewVariables] public GasMixture Air { get; set; } = new() {Temperature = Atmospherics.T20C}; [ViewVariables] private AtmosphereSystem? _atmosphereSystem; + [ViewVariables] private DamageableSystem? _damage; public EntityUid? Grid { get; private set; } @@ -38,11 +40,39 @@ public override void Initialize(Node sourceNode, IEntityManager entMan) _atmosphereSystem = entMan.EntitySysManager.GetEntitySystem(); _atmosphereSystem.AddPipeNet(Grid.Value, this); + _damage = entMan.EntitySysManager.GetEntitySystem(); + } + + /// + /// Calculate pressure damage for pipe. There is no damage if the pressure is below MaxPressure, + /// and damage scales exponentially beyond that. + /// + private int PressureDamage(PipeNode pipe) + { + const float tau = 10; // number of atmos ticks to break pipe at nominal overpressure + var diff = pipe.Air.Pressure - pipe.MaxPressure; + const float alpha = 100/tau; + return diff > 0 ? (int)(alpha*float.Exp(diff / pipe.MaxPressure)) : 0; } public void Update() { _atmosphereSystem?.React(Air, this); + + // Check each pipe node for overpressure and apply damage if needed + foreach (var node in Nodes) + { + if (node is PipeNode pipe && pipe.MaxPressure > 0) + { + int dam = PressureDamage(pipe); + if (dam > 0) + { + var dspec = new DamageSpecifier(); + dspec.DamageDict.Add("Structural", dam); + _damage?.TryChangeDamage(pipe.Owner, dspec); + } + } + } } public override void LoadNodes(List groupNodes) diff --git a/Content.Server/NodeContainer/Nodes/PipeNode.cs b/Content.Server/NodeContainer/Nodes/PipeNode.cs index 14afa2f1083eca..500bed08ae45cc 100644 --- a/Content.Server/NodeContainer/Nodes/PipeNode.cs +++ b/Content.Server/NodeContainer/Nodes/PipeNode.cs @@ -102,6 +102,12 @@ public GasMixture Air private const float DefaultVolume = 200f; + /// + /// Pressure beyond which this pipe node starts taking damage. Set to zero for no pressure damage. + /// + [DataField] + public float MaxPressure = 0; + public override void Initialize(EntityUid owner, IEntityManager entMan) { base.Initialize(owner, entMan); From 72fc1a15998cca8254b52e7eb09ea78918180270 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Wed, 11 Oct 2023 15:13:39 -0700 Subject: [PATCH 2/3] Add pressure limits to YAML --- .../Entities/Structures/Piping/Atmospherics/pipes.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml index 132da2f1a841f2..dec739357a4c05 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/pipes.yml @@ -83,6 +83,7 @@ !type:PipeNode nodeGroupID: Pipe pipeDirection: Longitudinal + maxPressure: 6750 - type: Sprite layers: - state: pipeStraight @@ -102,6 +103,7 @@ !type:PipeNode nodeGroupID: Pipe pipeDirection: SWBend + maxPressure: 6750 - type: Sprite layers: - state: pipeBend @@ -121,6 +123,7 @@ !type:PipeNode nodeGroupID: Pipe pipeDirection: TSouth + maxPressure: 6750 - type: Sprite layers: - state: pipeTJunction @@ -142,6 +145,7 @@ !type:PipeNode nodeGroupID: Pipe pipeDirection: Fourway + maxPressure: 6750 - type: Sprite layers: - state: pipeFourway From 52d785746d030b8eaa7baccabb8b626ddf9b7dd1 Mon Sep 17 00:00:00 2001 From: Kevin Zheng Date: Fri, 13 Oct 2023 00:17:15 -0700 Subject: [PATCH 3/3] Probabilistically damage one pipe instead of the whole net --- .../NodeContainer/NodeGroups/PipeNet.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Content.Server/NodeContainer/NodeGroups/PipeNet.cs b/Content.Server/NodeContainer/NodeGroups/PipeNet.cs index 8c37a9625d00de..989209beb039ee 100644 --- a/Content.Server/NodeContainer/NodeGroups/PipeNet.cs +++ b/Content.Server/NodeContainer/NodeGroups/PipeNet.cs @@ -4,6 +4,7 @@ using Content.Server.NodeContainer.Nodes; using Content.Shared.Atmos; using Content.Shared.Damage; +using Robust.Shared.Random; using Robust.Shared.Utility; namespace Content.Server.NodeContainer.NodeGroups @@ -23,6 +24,8 @@ public sealed class PipeNet : BaseNodeGroup, IPipeNet [ViewVariables] private AtmosphereSystem? _atmosphereSystem; [ViewVariables] private DamageableSystem? _damage; + [ViewVariables] private IEntityManager? _entMan; + [ViewVariables] private IRobustRandom? _random; public EntityUid? Grid { get; private set; } @@ -41,6 +44,8 @@ public override void Initialize(Node sourceNode, IEntityManager entMan) _atmosphereSystem = entMan.EntitySysManager.GetEntitySystem(); _atmosphereSystem.AddPipeNet(Grid.Value, this); _damage = entMan.EntitySysManager.GetEntitySystem(); + _entMan = entMan; + _random = IoCManager.Resolve(); } /// @@ -64,6 +69,18 @@ public void Update() { if (node is PipeNode pipe && pipe.MaxPressure > 0) { + // Prefer damaging pipes that are already damaged. This means that only one pipe + // fails instead of the whole pipenet bursting at the same time. + const float baseChance = 0.5f; + float p = baseChance; + if (_entMan != null && _entMan.TryGetComponent(pipe.Owner, out var damage)) + { + p += (float)damage.TotalDamage * (1 - baseChance); + } + + if (_random != null && _random.Prob(1-p)) + continue; + int dam = PressureDamage(pipe); if (dam > 0) {