Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atmos gas interaction reworks #9

Merged
merged 4 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ public sealed partial class AtmosphereSystem
[ViewVariables(VVAccess.ReadWrite)]
public string? HotspotSound { get; private set; } = "/Audio/Effects/fire.ogg";

private const float min_moles_for_hotspot=.5f; //min moles of fuel+ox to allow combustion

private float GetHotspotTotalFuel(TileAtmosphere tile){
if (tile==null || tile.Air==null) return 0f;
return tile.Air.GetMoles(Gas.Plasma)+tile.Air.GetMoles(Gas.Ammonia)+tile.Air.GetMoles(Gas.Tritium);
}
private float GetHotspotTotalOxidizer(TileAtmosphere tile){
if (tile==null || tile.Air==null) return 0f;
//nitro is .5 because of how it breaks down. (into 1 mole of n2, .5 mole of o2)
return tile.Air.GetMoles(Gas.Oxygen)+tile.Air.GetMoles(Gas.NitrousOxide)*.5f;
}


private void ProcessHotspot(
Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent> ent,
TileAtmosphere tile)
Expand All @@ -46,9 +59,9 @@ private void ProcessHotspot(
ExcitedGroupResetCooldowns(tile.ExcitedGroup);

if ((tile.Hotspot.Temperature < Atmospherics.FireMinimumTemperatureToExist) || (tile.Hotspot.Volume <= 1f)
|| tile.Air == null || tile.Air.GetMoles(Gas.Oxygen) < 0.5f || (tile.Air.GetMoles(Gas.Plasma) < 0.5f && tile.Air.GetMoles(Gas.Tritium) < 0.5f))
|| tile.Air == null || GetHotspotTotalFuel(tile)<min_moles_for_hotspot || GetHotspotTotalOxidizer(tile)<min_moles_for_hotspot )
{
tile.Hotspot = new Hotspot();
tile.Hotspot = new Hotspot();
InvalidateVisuals(ent, tile);
return;
}
Expand Down Expand Up @@ -121,25 +134,31 @@ private void ProcessHotspot(
// TODO ATMOS Maybe destroy location here?
}

//this function is called by items which make a hotspot in order to register the hotspot
private void HotspotExpose(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile,
float exposedTemperature, float exposedVolume, bool soh = false, EntityUid? sparkSourceUid = null)
{
const float min_moles_to_validate=.33f;
if (tile.Air == null)
return;

var oxygen = tile.Air.GetMoles(Gas.Oxygen);
// var oxygen = tile.Air.GetMoles(Gas.Oxygen);

if (oxygen < 0.5f)
return;
//if (oxygen < 0.5f)
// return;

float plasma = tile.Air.GetMoles(Gas.Plasma);
float tritium = tile.Air.GetMoles(Gas.Tritium);
float oxygen = tile.Air.GetMoles(Gas.Oxygen);

var plasma = tile.Air.GetMoles(Gas.Plasma);
var tritium = tile.Air.GetMoles(Gas.Tritium);
//allow the hotspot if it would cause an ignition (oxy/n2o+assorted gasses). we allow n2o because it's an oxidizer, and thermal decomposition.
bool allowhotspotignite= GetHotspotTotalFuel(tile)>=min_moles_for_hotspot && GetHotspotTotalOxidizer(tile)>=min_moles_for_hotspot;

if (tile.Hotspot.Valid)
{
if (soh)
{
if (plasma > 0.5f || tritium > 0.5f)
if (allowhotspotignite)
{
if (tile.Hotspot.Temperature < exposedTemperature)
tile.Hotspot.Temperature = exposedTemperature;
Expand All @@ -151,7 +170,7 @@ private void HotspotExpose(GridAtmosphereComponent gridAtmosphere, TileAtmospher
return;
}

if ((exposedTemperature > Atmospherics.PlasmaMinimumBurnTemperature) && (plasma > 0.5f || tritium > 0.5f))
if ((exposedTemperature > Atmospherics.FireMinimumTemperatureToExist) && allowhotspotignite)
{
if (sparkSourceUid.HasValue)
_adminLog.Add(LogType.Flammable, LogImpact.High, $"Heat/spark of {ToPrettyString(sparkSourceUid.Value)} caused atmos ignition of gas: {tile.Air.Temperature.ToString():temperature}K - {oxygen}mol Oxygen, {plasma}mol Plasma, {tritium}mol Tritium");
Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Atmos/IGasReactionEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ public partial interface IGasReactionEffect
/// <param name="heatScale">Scaling factor that should be applied to all heat input or outputs.</param>
ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem,
float heatScale);
}
}
}
34 changes: 0 additions & 34 deletions Content.Server/Atmos/Reactions/AmmoniaOxygenReaction.cs

This file was deleted.

71 changes: 71 additions & 0 deletions Content.Server/Atmos/Reactions/AmoniaOxygen_fire.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
using JetBrains.Annotations;

using Content.Server.Atmos.GasReactionHelpers;

namespace Content.Server.Atmos.Reactions
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class AmoniaOxygen_fire : IGasReactionEffect
{
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale)
{
mixture.ReactionResults[GasReaction.Fire]=0f;
// 2(O2) + 2(NH3) -> N2O + 3(H2O)
const float energy_per_mole = 46e3f; //46 kJ/mol.
const float minimum_temp = Atmospherics.T0C+250f; // 275C. this number is pure make-believe.
const float halfstep_temp = 150f; // 150C. what temp past min it will be at half speed.

float currenttemp=mixture.Temperature;
float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp;
float oxy = mixture.GetMoles(Gas.Oxygen);
float amonia = mixture.GetMoles(Gas.Ammonia);
float nitrox = mixture.GetMoles(Gas.NitrousOxide);
float stm = mixture.GetMoles(Gas.NitrousOxide);
float conversionratio=1.0f;

if(oxy<=0.0f || amonia<=0.0f){
return ReactionResult.NoReaction;
}

conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.5f,oxy,amonia); // equal parts.
conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp );
conversionratio*=(oxy+amonia)/(mixture.TotalMoles-(nitrox+stm));



if (conversionratio>0.0f){
float molesconv=MathF.Min(oxy,amonia)*conversionratio;

totalsystemenergy+= energy_per_mole*.5f*molesconv/heatScale; //half it because that is for a complete reaction, whereas we just use half moles.

mixture.AdjustMoles(Gas.Ammonia, -molesconv );
mixture.AdjustMoles(Gas.Oxygen, -molesconv );
mixture.AdjustMoles(Gas.NitrousOxide, molesconv*.5f );
mixture.AdjustMoles(Gas.WaterVapor, molesconv*1.5f );

float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat
if (newheatcap > Atmospherics.MinimumHeatCapacity){
mixture.Temperature=totalsystemenergy/newheatcap;
}

if (molesconv>.01f){
mixture.ReactionResults[GasReaction.Fire] += molesconv;
var location = holder as TileAtmosphere; //start fires
if (location!=null && mixture.Temperature > Atmospherics.FireMinimumTemperatureToExist){
atmosphereSystem.HotspotExpose(location, mixture.Temperature, mixture.Volume);
}
}

return ReactionResult.Reacting;
}
return ReactionResult.NoReaction;



}
}
}
59 changes: 0 additions & 59 deletions Content.Server/Atmos/Reactions/FrezonCoolantReaction.cs

This file was deleted.

56 changes: 56 additions & 0 deletions Content.Server/Atmos/Reactions/FrezonOxygen_dissapation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
using JetBrains.Annotations;

using Content.Server.Atmos.GasReactionHelpers;

namespace Content.Server.Atmos.Reactions
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class FrezonOxygenReaction : IGasReactionEffect
{
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale)
{
const float energy_per_mole = 250e3f; //250 kJ/mol. endothermic. this has to be high because we are deleting moles which messes with the total energy quite a bit.
const float minimum_temp = Atmospherics.T0C-30f; // -40C
const float halfstep_temp = 80f;

float currenttemp=mixture.Temperature;
float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp;
float oxy = mixture.GetMoles(Gas.Oxygen);
float frez = mixture.GetMoles(Gas.Frezon);
float conversionratio=1.0f;



if(oxy<=0f || frez<=0f){
return ReactionResult.NoReaction;
}

conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp );
conversionratio*=(frez+oxy)/(mixture.TotalMoles);

if (conversionratio>0f){
float molestoreact=MathF.Min(oxy,frez)*conversionratio;

totalsystemenergy-=molestoreact*energy_per_mole/heatScale;

mixture.AdjustMoles(Gas.Frezon, -molestoreact);

float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat
if (newheatcap > Atmospherics.MinimumHeatCapacity){
mixture.Temperature=totalsystemenergy/newheatcap;
}

return ReactionResult.Reacting;
}
return ReactionResult.NoReaction;




}
}
}
55 changes: 55 additions & 0 deletions Content.Server/Atmos/Reactions/FrezonPlasma_cooldown.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
using JetBrains.Annotations;

using Content.Server.Atmos.GasReactionHelpers;

namespace Content.Server.Atmos.Reactions
{
[UsedImplicitly]
[DataDefinition]
public sealed partial class FrezonPlasmaReaction : IGasReactionEffect
{
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem, float heatScale)
{
const float energy_per_mole = 1000e3f; //900 kJ/mol. endothermic.
const float minimum_temp = 0f; // 0K. ice cold.
const float halfstep_temp = Atmospherics.T0C; //0C

float currenttemp=mixture.Temperature;
float totalsystemenergy= atmosphereSystem.GetHeatCapacity(mixture, true)*currenttemp;
float plas = mixture.GetMoles(Gas.Plasma);
float frez = mixture.GetMoles(Gas.Frezon);
float conversionratio=1.0f;

if(plas<=0f || frez<=0f){
return ReactionResult.NoReaction;
}

conversionratio*=GasReactionHelperFunctions.reaction_mult_2gas_idealratio(.5f,plas,frez);
conversionratio*=GasReactionHelperFunctions.reaction_mult_mintemp_higher_asymptote(currenttemp, minimum_temp ,halfstep_temp );
conversionratio*=(frez+plas)/(mixture.TotalMoles);

if (conversionratio>0f){
float molestoreact=MathF.Min(plas,frez)*conversionratio;

totalsystemenergy-=molestoreact*energy_per_mole/heatScale;

mixture.AdjustMoles(Gas.Frezon, -molestoreact);

float newheatcap=atmosphereSystem.GetHeatCapacity(mixture, true); //add new heat
if (newheatcap > Atmospherics.MinimumHeatCapacity){
mixture.Temperature=totalsystemenergy/newheatcap;
}

return ReactionResult.Reacting;
}
return ReactionResult.NoReaction;




}
}
}
Loading