Gas Condensers (#22436)
Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
@@ -0,0 +1,33 @@
|
||||
using Content.Server.Atmos.Piping.Unary.EntitySystems;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Used for an entity that converts moles of gas into units of reagent.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[Access(typeof(GasCondenserSystem))]
|
||||
public sealed partial class GasCondenserComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The ID for the pipe node.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string Inlet = "pipe";
|
||||
|
||||
/// <summary>
|
||||
/// The ID for the solution.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string SolutionId = "tank";
|
||||
|
||||
/// <summary>
|
||||
/// For a condenser, how many U of reagents are given per each mole of gas.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Derived from a standard of 500u per canister:
|
||||
/// 400u / 1871.71051 moles per canister
|
||||
/// </remarks>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public float MolesToReagentMultiplier = 0.2137f;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Server.Atmos.Piping.Unary.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 JetBrains.Annotations;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.EntitySystems;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class GasCondenserSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly PowerReceiverSystem _power = default!;
|
||||
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solution = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GasCondenserComponent, AtmosDeviceUpdateEvent>(OnCondenserUpdated);
|
||||
}
|
||||
|
||||
private void OnCondenserUpdated(EntityUid uid, GasCondenserComponent component, AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
if (!(_power.IsPowered(uid) && TryComp<ApcPowerReceiverComponent>(uid, out var receiver))
|
||||
|| !TryComp<NodeContainerComponent>(uid, out var nodeContainer)
|
||||
|| !_nodeContainer.TryGetNode(nodeContainer, component.Inlet, out PipeNode? inlet)
|
||||
|| !_solution.TryGetSolution(uid, component.SolutionId, out var solution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (solution.AvailableVolume == 0 || inlet.Air.TotalMoles == 0)
|
||||
return;
|
||||
|
||||
var molesToConvert = NumberOfMolesToConvert(receiver, inlet.Air, args.dt);
|
||||
var removed = inlet.Air.Remove(molesToConvert);
|
||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var moles = removed.Moles[i];
|
||||
if (moles <= 0)
|
||||
continue;
|
||||
|
||||
if (_atmosphereSystem.GetGas(i).Reagent is not {} gasReagent)
|
||||
continue;
|
||||
|
||||
var moleToReagentMultiplier = component.MolesToReagentMultiplier;
|
||||
var amount = moles * moleToReagentMultiplier;
|
||||
|
||||
if (_solution.TryAddReagent(uid, solution, gasReagent, amount, out var remaining))
|
||||
continue;
|
||||
|
||||
// if we have leftover reagent, then convert it back to moles and put it back in the mixture.
|
||||
inlet.Air.AdjustMoles(i, remaining.Float() / moleToReagentMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
public float NumberOfMolesToConvert(ApcPowerReceiverComponent comp, GasMixture mix, float dt)
|
||||
{
|
||||
var hc = _atmosphereSystem.GetHeatCapacity(mix);
|
||||
var alpha = 0.8f; // tuned to give us 1-ish u/second of reagent conversion
|
||||
// ignores the energy needed to cool down the solution to the condensation point, but that probably adds too much difficulty and so let's not simulate that
|
||||
var energy = comp.Load * dt;
|
||||
return energy / (alpha * hc);
|
||||
}
|
||||
}
|
||||
@@ -374,6 +374,22 @@ public sealed partial class SolutionContainerSystem : EntitySystem
|
||||
return acceptedQuantity == reagentQuantity.Quantity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds reagent of an Id to the container.
|
||||
/// </summary>
|
||||
/// <param name="targetUid"></param>
|
||||
/// <param name="targetSolution">Container to which we are adding reagent</param>
|
||||
/// <param name="prototype">The Id of the reagent to add.</param>
|
||||
/// <param name="quantity">The amount of reagent to add.</param>
|
||||
/// <returns>If all the reagent could be added.</returns>
|
||||
[PublicAPI]
|
||||
public bool TryAddReagent(EntityUid targetUid, Solution targetSolution, string prototype, FixedPoint2 quantity,
|
||||
float? temperature = null, ReagentData? data = null)
|
||||
{
|
||||
var reagent = new ReagentQuantity(prototype, quantity, data);
|
||||
return TryAddReagent(targetUid, targetSolution, reagent, out _, temperature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds reagent of an Id to the container.
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ wires-board-name-default = Wires
|
||||
wires-board-name-booze = BoozeDispenser
|
||||
wires-board-name-soda = SodaDispenser
|
||||
wires-board-name-thermomachine = Thermomachine
|
||||
wires-board-name-condenser = Condenser
|
||||
wires-board-name-pa = Mk2 Particle Accelerator
|
||||
wires-board-name-highsec = HighSec Control
|
||||
wires-board-name-vessel = Vessel
|
||||
|
||||
@@ -338,6 +338,21 @@
|
||||
deconstructionTarget: null
|
||||
node: heater
|
||||
|
||||
- type: entity
|
||||
id: CondenserMachineCircuitBoard
|
||||
parent: BaseMachineCircuitboard
|
||||
name: condenser machine board
|
||||
description: A machine printed circuit board for a condenser.
|
||||
components:
|
||||
- type: Sprite
|
||||
state: engineering
|
||||
- type: MachineBoard
|
||||
prototype: BaseGasCondenser
|
||||
requirements:
|
||||
MatterBin: 1
|
||||
materialRequirements:
|
||||
Glass: 1
|
||||
|
||||
- type: entity
|
||||
id: PortableScrubberMachineCircuitBoard
|
||||
parent: BaseMachineCircuitboard
|
||||
|
||||
@@ -306,6 +306,8 @@
|
||||
producingSound: /Audio/Machines/circuitprinter.ogg
|
||||
idleState: icon
|
||||
runningState: building
|
||||
staticRecipes:
|
||||
- CondenserMachineCircuitBoard
|
||||
dynamicRecipes:
|
||||
- ThermomachineFreezerMachineCircuitBoard
|
||||
- PortableScrubberMachineCircuitBoard
|
||||
|
||||
@@ -351,3 +351,89 @@
|
||||
enabled: true
|
||||
- type: ApcPowerReceiver
|
||||
powerDisabled: false
|
||||
|
||||
- type: entity
|
||||
parent: [ BaseMachinePowered, ConstructibleMachine ]
|
||||
id: BaseGasCondenser
|
||||
name: condenser
|
||||
description: Condenses gases into liquids. Now we just need some plumbing.
|
||||
placement:
|
||||
mode: SnapgridCenter
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Piping/Atmospherics/condenser.rsi
|
||||
snapCardinals: true
|
||||
granularLayersRendering: true
|
||||
layers:
|
||||
- state: off
|
||||
map: [ "enum.PowerDeviceVisualLayers.Powered" ]
|
||||
- state: panel
|
||||
map: ["enum.WiresVisualLayers.MaintenancePanel"]
|
||||
- state: pipe
|
||||
map: [ "enum.PipeVisualLayers.Pipe" ]
|
||||
renderingStrategy: Default
|
||||
- state: fill-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- state: trans
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.PowerDeviceVisuals.Powered:
|
||||
enum.PowerDeviceVisualLayers.Powered:
|
||||
True: { state: on }
|
||||
False: { state: off }
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 7
|
||||
fillBaseName: fill-
|
||||
- type: Appearance
|
||||
- type: PipeColorVisuals
|
||||
- type: Rotatable
|
||||
- type: GasCondenser
|
||||
- type: AtmosPipeColor
|
||||
- type: AtmosDevice
|
||||
- type: ApcPowerReceiver
|
||||
powerLoad: 10000
|
||||
- type: Machine
|
||||
board: CondenserMachineCircuitBoard
|
||||
- type: WiresPanel
|
||||
- type: Wires
|
||||
boardName: wires-board-name-condenser
|
||||
layoutId: Condenser
|
||||
- type: WiresVisuals
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 200
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 100
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: [ "Destruction" ]
|
||||
- !type:SpillBehavior
|
||||
solution: tank
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- type: NodeContainer
|
||||
nodes:
|
||||
pipe:
|
||||
!type:PipeNode
|
||||
nodeGroupID: Pipe
|
||||
pipeDirection: South
|
||||
- type: Transform
|
||||
noRot: false
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
tank:
|
||||
maxVol: 400
|
||||
canMix: true
|
||||
- type: DrainableSolution
|
||||
solution: tank
|
||||
- type: ExaminableSolution
|
||||
solution: tank
|
||||
- type: PowerSwitch
|
||||
|
||||
@@ -104,6 +104,14 @@
|
||||
Glass: 900
|
||||
Gold: 50
|
||||
|
||||
- type: latheRecipe
|
||||
id: CondenserMachineCircuitBoard
|
||||
result: CondenserMachineCircuitBoard
|
||||
completetime: 4
|
||||
materials:
|
||||
Steel: 100
|
||||
Glass: 900
|
||||
|
||||
- type: latheRecipe
|
||||
id: PortableScrubberMachineCircuitBoard
|
||||
result: PortableScrubberMachineCircuitBoard
|
||||
|
||||
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 168 B |
|
After Width: | Height: | Size: 164 B |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 184 B |
|
After Width: | Height: | Size: 185 B |
|
After Width: | Height: | Size: 187 B |
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"version":1,
|
||||
"size":
|
||||
{
|
||||
"x":32,
|
||||
"y":32
|
||||
},
|
||||
"copyright":"Created by EmoGarbage404 (github) for Space Station 14.",
|
||||
"license":"CC0-1.0",
|
||||
"states":
|
||||
[
|
||||
{
|
||||
"name":"off"
|
||||
},
|
||||
{
|
||||
"name":"on",
|
||||
"delays":
|
||||
[
|
||||
[
|
||||
0.05,
|
||||
0.05,
|
||||
0.05,
|
||||
0.05,
|
||||
0.05
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name":"panel"
|
||||
},
|
||||
{
|
||||
"name":"trans"
|
||||
},
|
||||
{
|
||||
"name":"pipe",
|
||||
"directions":4
|
||||
},
|
||||
{
|
||||
"name":"fill-1"
|
||||
},
|
||||
{
|
||||
"name":"fill-2"
|
||||
},
|
||||
{
|
||||
"name":"fill-3"
|
||||
},
|
||||
{
|
||||
"name":"fill-4"
|
||||
},
|
||||
{
|
||||
"name":"fill-5"
|
||||
},
|
||||
{
|
||||
"name":"fill-6"
|
||||
},
|
||||
{
|
||||
"name":"fill-7"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 687 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 272 B |
|
After Width: | Height: | Size: 344 B |
|
After Width: | Height: | Size: 346 B |