public void Inhale(float frameTime, GasMixture from) { var ratio = Atmospherics.BreathPercentage * frameTime; Transfer(from, Air, ratio); ToBloodstream(Air); }
public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); Air = new GasMixture(6); serializer.DataField(ref _initialMaxVolume, "maxVolume", ReagentUnit.New(250)); }
public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); Air = new GasMixture(); serializer.DataField(this, x => x.Air, "air", new GasMixture()); }
public static bool IsMixtureOxygenated(GasMixture gas, float partial) { if (gas.O2Partial >= partial) { return(true); } return(false); }
public static bool IsMixtureCo2Toxic(GasMixture gas) { if (gas.Co2Partial >= 5f)//conditions for hypercapnia { return(true); } return(true); }
/// <summary> /// Calculates the molar density of a given gas mixture in g/mol. /// </summary> /// <param name="mix">GasMixture to have its desnity calculated.</param> /// <returns>Gas density (g/mol)</returns> public static float MolarGasDensity(GasMixture mix) { return((mix.Oxygen.Quantity / mix.TotalMolesGassesAndLiquids * 31.9988f) + (mix.Nitrogen.Quantity / mix.TotalMolesGassesAndLiquids * 28.0134f) + (mix.CarbonDioxide.Quantity / mix.TotalMolesGassesAndLiquids * 44.0095f) + (mix.Volatiles.Quantity / mix.TotalMolesGassesAndLiquids * 2.01588f) + (mix.Pollutant.Quantity / mix.TotalMolesGassesAndLiquids * 70.906f) + (mix.Water.Quantity / mix.TotalMolesGassesAndLiquids * 18.0153f)); }
public void Transfer(BloodstreamComponent @from, GasMixture to, Gas gas, float pressure) { var transfer = new GasMixture(); var molesInBlood = @from.Air.GetMoles(gas); transfer.SetMoles(gas, molesInBlood); transfer.ReleaseGasTo(to, pressure); @from.Air.Merge(transfer); }
private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, AtmosDeviceUpdateEvent args) { var appearance = EntityManager.GetComponentOrNull <AppearanceComponent>(filter.Owner); if (!filter.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device) || !nodeContainer.TryGetNode(filter.InletName, out PipeNode? inletNode) || !nodeContainer.TryGetNode(filter.FilterName, out PipeNode? filterNode) || !nodeContainer.TryGetNode(filter.OutletName, out PipeNode? outletNode) || outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) // No need to transfer if target is full. { appearance?.SetData(FilterVisuals.Enabled, false); _ambientSoundSystem.SetAmbience(filter.Owner, false); return; } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(filter.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inletNode.Air.Volume; if (transferRatio <= 0) { appearance?.SetData(FilterVisuals.Enabled, false); _ambientSoundSystem.SetAmbience(filter.Owner, false); return; } var removed = inletNode.Air.RemoveRatio(transferRatio); if (filter.FilteredGas.HasValue) { appearance?.SetData(FilterVisuals.Enabled, true); var filteredOut = new GasMixture() { Temperature = removed.Temperature }; filteredOut.SetMoles(filter.FilteredGas.Value, removed.GetMoles(filter.FilteredGas.Value)); removed.SetMoles(filter.FilteredGas.Value, 0f); var target = filterNode.Air.Pressure < Atmospherics.MaxOutputPressure ? filterNode : inletNode; _atmosphereSystem.Merge(target.Air, filteredOut); if (filteredOut.Pressure != 0f) { _ambientSoundSystem.SetAmbience(filter.Owner, true); } else { _ambientSoundSystem.SetAmbience(filter.Owner, false); } } _atmosphereSystem.Merge(outletNode.Air, removed); }
public float pressure = 0; // in kPa void Start() { // Get surrounding tiles, because we will need to update them surroundedTiles = new List <Tile>(); surroundedTiles.Add(GetSurroundedTile(transform.forward)); surroundedTiles.Add(GetSurroundedTile(-transform.right)); surroundedTiles.Add(GetSurroundedTile(-transform.forward)); surroundedTiles.Add(GetSurroundedTile(transform.right)); gasMixture = new GasMixture(); }
public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); Air = new GasMixture(6) { Temperature = Atmospherics.NormalBodyTemperature }; serializer.DataField(ref _initialMaxVolume, "maxVolume", ReagentUnit.New(250)); }
private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, AtmosDeviceUpdateEvent args) { if (!filter.Enabled) { return; } if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!ComponentManager.TryGetComponent(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(filter.InletName, out PipeNode? inletNode) || !nodeContainer.TryGetNode(filter.FilterName, out PipeNode? filterNode) || !nodeContainer.TryGetNode(filter.OutletName, out PipeNode? outletNode)) { return; } if (outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) { return; // No need to transfer if target is full. } // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(filter.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inletNode.Air.Volume; if (transferRatio <= 0) { return; } var removed = inletNode.Air.RemoveRatio(transferRatio); if (filter.FilteredGas.HasValue) { var filteredOut = new GasMixture() { Temperature = removed.Temperature }; filteredOut.SetMoles(filter.FilteredGas.Value, removed.GetMoles(filter.FilteredGas.Value)); removed.SetMoles(filter.FilteredGas.Value, 0f); var target = filterNode.Air.Pressure < Atmospherics.MaxOutputPressure ? filterNode : inletNode; target.AssumeAir(filteredOut); } outletNode.AssumeAir(removed); }
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, GridTileLookupSystem gridLookup) { var result = ReactionResult.NoReaction; foreach (var effect in _effects) { result |= effect.React(mixture, holder, gridLookup); } return(result); }
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder) { var result = ReactionResult.NoReaction; foreach (var effect in _effects) { result |= effect.React(mixture, holder); } return(result); }
public void Update(GasMixture air, float frameDelta, AtmosphereSystem atmosphereSystem) { // TODO: I'm coming for you next, TemperatureComponent... Fear me for I am death, destroyer of shitcode. if (_temperatureComponent != null) { var temperatureDelta = air.Temperature - _temperatureComponent.CurrentTemperature; var tileHeatCapacity = atmosphereSystem.GetHeatCapacity(air); var heat = temperatureDelta * (tileHeatCapacity * _temperatureComponent.HeatCapacity / (tileHeatCapacity + _temperatureComponent.HeatCapacity)); _temperatureComponent.ReceiveHeat(heat); _temperatureComponent.Update(); } }
public void ToBloodstream(GasMixture mixture) { if (!Owner.TryGetComponent(out BloodstreamComponent bloodstream)) { return; } var to = bloodstream.Air; to.Merge(mixture); mixture.Clear(); }
public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); GasMixture = new GasMixture(); serializer.DataReadWriteFunction( "volume", 0f, vol => GasMixture.Volume = vol, () => GasMixture.Volume); }
public ReactionResult React(GasMixture mixture, IGasMixtureHolder?holder, AtmosphereSystem atmosphereSystem) { var initialMiasma = mixture.GetMoles(Gas.Miasma); var initialFrezon = mixture.GetMoles(Gas.Frezon); var convert = Math.Min(Math.Min(initialFrezon, initialMiasma), Atmospherics.MiasmicSubsumationMaxConversionRate); mixture.AdjustMoles(Gas.Miasma, convert); mixture.AdjustMoles(Gas.Frezon, -convert); return(ReactionResult.Reacting); }
public ReactionResult React(GasMixture mixture, IGasMixtureHolder?holder, AtmosphereSystem atmosphereSystem) { var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); var temperature = mixture.Temperature; var energyModifier = 1f; var scale = (temperature - Atmospherics.FrezonCoolLowerTemperature) / (Atmospherics.FrezonCoolMidTemperature - Atmospherics.FrezonCoolLowerTemperature); if (scale > 1f) { // Scale energy but not frezon usage if we're in a very, very hot place energyModifier = Math.Min(scale, Atmospherics.FrezonCoolMaximumEnergyModifier); scale = 1f; } if (scale <= 0) { return(ReactionResult.NoReaction); } var initialNit = mixture.GetMoles(Gas.Nitrogen); var initialFrezon = mixture.GetMoles(Gas.Frezon); var burnRate = initialFrezon * scale / Atmospherics.FrezonCoolRateModifier; var energyReleased = 0f; if (burnRate > Atmospherics.MinimumHeatCapacity) { var nitAmt = Math.Min(burnRate * Atmospherics.FrezonNitrogenCoolRatio, initialNit); var frezonAmt = Math.Min(burnRate, initialFrezon); mixture.AdjustMoles(Gas.Nitrogen, -nitAmt); mixture.AdjustMoles(Gas.Frezon, -frezonAmt); mixture.AdjustMoles(Gas.NitrousOxide, nitAmt + frezonAmt); energyReleased = burnRate * Atmospherics.FrezonCoolEnergyReleased * energyModifier; } if (energyReleased >= 0f) { return(ReactionResult.NoReaction); } var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) { mixture.Temperature = (temperature * oldHeatCapacity + energyReleased) / newHeatCapacity; } return(ReactionResult.Reacting); }
public void PumpToxins(GasMixture into, float pressure) { if (!Owner.TryGetComponent(out MetabolismComponent metabolism)) { Air.PumpGasTo(into, pressure); return; } var toxins = metabolism.Clean(this); toxins.PumpGasTo(into, pressure); Air.Merge(toxins); }
public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); Air = new GasMixture(); serializer.DataReadWriteFunction( "volume", 6, vol => Air.Volume = vol, () => Air.Volume); serializer.DataField(this, l => l.Pressure, "pressure", 100); }
private void ExcitedGroupSelfBreakdown(GridAtmosphereComponent gridAtmosphere, ExcitedGroup excitedGroup) { DebugTools.Assert(!excitedGroup.Disposed, "Excited group is disposed!"); DebugTools.Assert(gridAtmosphere.ExcitedGroups.Contains(excitedGroup), "Grid Atmosphere does not contain Excited Group!"); var combined = new GasMixture(Atmospherics.CellVolume); var tileSize = excitedGroup.Tiles.Count; if (excitedGroup.Disposed) { return; } if (tileSize == 0) { ExcitedGroupDispose(gridAtmosphere, excitedGroup); return; } foreach (var tile in excitedGroup.Tiles) { if (tile?.Air == null) { continue; } Merge(combined, tile.Air); if (!ExcitedGroupsSpaceIsAllConsuming || !tile.Air.Immutable) { continue; } combined.Clear(); break; } combined.Multiply(1 / (float)tileSize); foreach (var tile in excitedGroup.Tiles) { if (tile?.Air == null) { continue; } tile.Air.CopyFromMutable(combined); InvalidateVisuals(tile.GridIndex, tile.GridIndices); } excitedGroup.BreakdownCooldown = 0; }
private void UpdateTileTemperature(TemperatureArtifactComponent component, GasMixture environment) { var dif = component.TargetTemperature - environment.Temperature; var absDif = Math.Abs(dif); if (absDif < component.MaxTemperatureDifference) { return; } var step = Math.Min(absDif, component.SpawnTemperature); environment.Temperature += dif > 0 ? step : -step; }
public static bool IsMixtureToxic(GasMixture gas) { if (IsMixtureCo2Toxic(gas))//conditions for hypercapnia { return(true); } if (!IsMixtureOxygenated(gas)) { return(true); } return(false); }
private void RefillGasTank(EntityUid tank, Gas gasType, GasTankComponent?tankComponent) { if (!Resolve(tank, ref tankComponent)) { return; } var mixSize = tankComponent.Air.Volume; var newMix = new GasMixture(mixSize); newMix.SetMoles(gasType, (1000.0f * mixSize) / (Atmospherics.R * Atmospherics.T20C)); // Fill the tank to 1000KPA. newMix.Temperature = Atmospherics.T20C; tankComponent.Air = newMix; }
/// <summary> /// Divides a source gas mixture into several recipient mixtures, scaled by their relative volumes. Does not /// modify the source gas mixture. Used for pipe network splitting. Note that the total destination volume /// may be larger or smaller than the source mixture. /// </summary> public void DivideInto(GasMixture source, List <GasMixture> receivers) { var totalVolume = 0f; foreach (var receiver in receivers) { if (!receiver.Immutable) { totalVolume += receiver.Volume; } } float?sourceHeatCapacity = null; var buffer = new float[Atmospherics.AdjustedNumberOfGases]; foreach (var receiver in receivers) { if (receiver.Immutable) { continue; } var fraction = receiver.Volume / totalVolume; // Set temperature, if necessary. if (MathF.Abs(receiver.Temperature - source.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider) { // Often this divides a pipe net into new and completely empty pipe nets if (receiver.TotalMoles == 0) { receiver.Temperature = source.Temperature; } else { sourceHeatCapacity ??= GetHeatCapacity(source); var receiverHeatCapacity = GetHeatCapacity(receiver); var combinedHeatCapacity = receiverHeatCapacity + sourceHeatCapacity.Value * fraction; if (combinedHeatCapacity > 0f) { receiver.Temperature = (GetThermalEnergy(source, sourceHeatCapacity.Value * fraction) + GetThermalEnergy(receiver, receiverHeatCapacity)) / combinedHeatCapacity; } } } // transfer moles NumericsHelpers.Multiply(source.Moles, fraction, buffer); NumericsHelpers.Add(receiver.Moles, buffer); } }
public void Update(GasMixture air, float frameDelta, AtmosphereSystem atmosphereSystem) { if (_temperatureComponent != null) { var temperatureDelta = air.Temperature - _temperatureComponent.CurrentTemperature; var tileHeatCapacity = atmosphereSystem.GetHeatCapacity(air); var heat = temperatureDelta * (tileHeatCapacity * _temperatureComponent.HeatCapacity / (tileHeatCapacity + _temperatureComponent.HeatCapacity)); _temperatureComponent.ReceiveHeat(heat); _temperatureComponent.Update(); } _barotraumaComponent?.Update(air.Pressure); _flammableComponent?.Update(air); }
public void ScrubInto(GasMixture mixture, GasMixture destination, IReadOnlyCollection <Gas> filterGases) { var buffer = new GasMixture(mixture.Volume) { Temperature = mixture.Temperature }; foreach (var gas in filterGases) { buffer.AdjustMoles(gas, mixture.GetMoles(gas)); mixture.SetMoles(gas, 0f); } Merge(destination, buffer); }
/// <summary> /// Mix air from a gas container into a pipe net. /// Useful for anything that uses connector ports. /// </summary> public void MixContainerWithPipeNet(GasMixture containerAir, GasMixture pipeNetAir) { var buffer = new GasMixture(pipeNetAir.Volume + containerAir.Volume); _atmosphereSystem.Merge(buffer, pipeNetAir); _atmosphereSystem.Merge(buffer, containerAir); pipeNetAir.Clear(); _atmosphereSystem.Merge(pipeNetAir, buffer); pipeNetAir.Multiply(pipeNetAir.Volume / buffer.Volume); containerAir.Clear(); _atmosphereSystem.Merge(containerAir, buffer); containerAir.Multiply(containerAir.Volume / buffer.Volume); }
private void OnBeforeUnanchored(EntityUid uid, AtmosUnsafeUnanchorComponent component, BeforeUnanchoredEvent args) { if (!component.Enabled || !ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodes)) { return; } if (!component.Owner.Transform.Coordinates.TryGetTileAtmosphere(out var environment)) { environment = null; } var environmentPressure = environment?.Air?.Pressure ?? 0f; var environmentVolume = environment?.Air?.Volume ?? Atmospherics.CellVolume; var environmentTemperature = environment?.Air?.Volume ?? Atmospherics.TCMB; var lost = 0f; var timesLost = 0; foreach (var node in nodes.Nodes.Values) { if (node is not PipeNode pipe) { continue; } var difference = pipe.Air.Pressure - environmentPressure; lost += difference * environmentVolume / (environmentTemperature * Atmospherics.R); timesLost++; } var sharedLoss = lost / timesLost; var buffer = new GasMixture(); var atmosphereSystem = Get <AtmosphereSystem>(); foreach (var node in nodes.Nodes.Values) { if (node is not PipeNode pipe) { continue; } atmosphereSystem.Merge(buffer, pipe.Air.Remove(sharedLoss)); } environment?.AssumeAir(buffer); }
public ReactionResult React(GasMixture mixture, IGasMixtureHolder?holder) { var reaction = ReactionResult.NoReaction; var temperature = mixture.Temperature; var energy = GetThermalEnergy(mixture); foreach (var prototype in GasReactions) { if (energy < prototype.MinimumEnergyRequirement || temperature < prototype.MinimumTemperatureRequirement || temperature > prototype.MaximumTemperatureRequirement) { continue; } var doReaction = true; for (var i = 0; i < prototype.MinimumRequirements.Length; i++) { if (i > Atmospherics.TotalNumberOfGases) { throw new IndexOutOfRangeException("Reaction Gas Minimum Requirements Array Prototype exceeds total number of gases!"); } var req = prototype.MinimumRequirements[i]; if (!(mixture.GetMoles(i) < req)) { continue; } doReaction = false; break; } if (!doReaction) { continue; } reaction = prototype.React(mixture, holder, this); if (reaction.HasFlag(ReactionResult.StopReactions)) { break; } } return(reaction); }