private void OnUnanchorAttempt(EntityUid uid, AtmosUnsafeUnanchorComponent component, UnanchorAttemptEvent args) { if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes)) { return; } if (_atmosphereSystem.GetContainingMixture(uid, true) is not { } environment) { return; } foreach (var node in nodes.Nodes.Values) { if (node is not PipeNode pipe) { continue; } if ((pipe.Air.Pressure - environment.Pressure) > 2 * Atmospherics.OneAtmosphere) { args.Delay += 1.5f; _popupSystem.PopupCursor(Loc.GetString("comp-atmos-unsafe-unanchor-warning"), Filter.Entities(args.User), PopupType.MediumCaution); return; // Show the warning only once. } } }
private void OnActivate(EntityUid uid, GasArtifactComponent component, ArtifactActivatedEvent args) { if (component.SpawnGas == null || component.SpawnTemperature == null) { return; } var transform = Transform(uid); var environment = _atmosphereSystem.GetContainingMixture(uid, false, true); if (environment == null) { return; } if (environment.Pressure >= component.MaxExternalPressure) { return; } var merger = new GasMixture(1) { Temperature = component.SpawnTemperature.Value }; merger.SetMoles(component.SpawnGas.Value, component.SpawnAmount); _atmosphereSystem.Merge(environment, merger); }
/// <summary> /// Completely dumps the content of the canister into the world. /// </summary> public void PurgeContents(EntityUid uid, GasCanisterComponent?canister = null, TransformComponent?transform = null) { if (!Resolve(uid, ref canister, ref transform)) { return; } var environment = _atmosphereSystem.GetContainingMixture(uid, false, true); if (environment is not null) { _atmosphereSystem.Merge(environment, canister.Air); } _adminLogger.Add(LogType.CanisterPurged, LogImpact.Medium, $"Canister {ToPrettyString(uid):canister} purged its contents of {canister.Air:gas} into the environment."); canister.Air.Clear(); }
/// <summary> /// When this is destroyed, we dump out all the gas inside. /// </summary> private void OnDestroyed(EntityUid uid, PortableScrubberComponent component, DestructionEventArgs args) { var environment = _atmosphereSystem.GetContainingMixture(uid, false, true); if (environment != null) { _atmosphereSystem.Merge(environment, component.Air); } _adminLogger.Add(LogType.CanisterPurged, LogImpact.Medium, $"Portable scrubber {ToPrettyString(uid):canister} purged its contents of {component.Air:gas} into the environment."); component.Air.Clear(); }
public void Inhale(EntityUid uid, SharedBodyComponent?body = null) { if (!Resolve(uid, ref body, false)) { return; } var organs = _bodySystem.GetComponentsOnMechanisms <LungComponent>(uid, body); // Inhale gas var ev = new InhaleLocationEvent(); RaiseLocalEvent(uid, ev, false); if (ev.Gas == null) { ev.Gas = _atmosSys.GetContainingMixture(uid, false, true); if (ev.Gas == null) { return; } } var ratio = (Atmospherics.BreathVolume / ev.Gas.Volume); var actualGas = ev.Gas.RemoveRatio(ratio); var lungRatio = 1.0f / organs.Count; var gas = organs.Count == 1 ? actualGas : actualGas.RemoveRatio(lungRatio); foreach (var(lung, _) in organs) { // Merge doesn't remove gas from the giver. _atmosSys.Merge(lung.Air, gas); _lungSystem.GasToReagent(lung.Owner, lung); } }
private void OnOutletInjectorUpdated(EntityUid uid, GasOutletInjectorComponent injector, AtmosDeviceUpdateEvent args) { if (!injector.Enabled) { return; } if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!TryComp(uid, out AtmosDeviceComponent? device)) { return; } if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet)) { return; } var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); if (environment == null) { return; } if (inlet.Air.Temperature < 0) { return; } if (environment.Pressure > injector.MaxPressure) { return; } var timeDelta = (float)(_gameTiming.CurTime - device.LastProcess).TotalSeconds; // TODO adjust ratio so that environment does not go above MaxPressure? var ratio = MathF.Min(1f, timeDelta * injector.TransferRate / inlet.Air.Volume); var removed = inlet.Air.RemoveRatio(ratio); _atmosphereSystem.Merge(environment, removed); }
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, AtmosDeviceUpdateEvent args) { var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); if (environment == null) { return; } if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) { return; } if (!nodeContainer.TryGetNode(vent.InletName, out PipeNode? inlet)) { return; } var environmentPressure = environment.Pressure; var pressureDelta = MathF.Abs(environmentPressure - inlet.Air.Pressure); if ((environment.Temperature > 0 || inlet.Air.Temperature > 0) && pressureDelta > 0.5f) { if (environmentPressure < inlet.Air.Pressure) { var airTemperature = environment.Temperature > 0 ? environment.Temperature : inlet.Air.Temperature; var transferMoles = pressureDelta * environment.Volume / (airTemperature * Atmospherics.R); var removed = inlet.Air.Remove(transferMoles); _atmosphereSystem.Merge(environment, removed); } else { var airTemperature = inlet.Air.Temperature > 0 ? inlet.Air.Temperature : environment.Temperature; var outputVolume = inlet.Air.Volume; var transferMoles = (pressureDelta * outputVolume) / (airTemperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, environment.TotalMoles * inlet.Air.Volume / environment.Volume); var removed = environment.Remove(transferMoles); _atmosphereSystem.Merge(inlet.Air, removed); } } }
private bool CheckMinerOperation(GasMinerComponent miner, [NotNullWhen(true)] out GasMixture?environment) { var uid = miner.Owner; environment = _atmosphereSystem.GetContainingMixture(uid, true, true); var transform = Transform(uid); var position = _transformSystem.GetGridOrMapTilePosition(uid, transform); // Space. if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position)) { miner.Broken = true; return(false); } // Air-blocked location. if (environment == null) { miner.Broken = true; return(false); } // External pressure above threshold. if (!float.IsInfinity(miner.MaxExternalPressure) && environment.Pressure > miner.MaxExternalPressure - miner.SpawnAmount * miner.SpawnTemperature * Atmospherics.R / environment.Volume) { miner.Broken = true; return(false); } // External gas amount above threshold. if (!float.IsInfinity(miner.MaxExternalAmount) && environment.TotalMoles > miner.MaxExternalAmount) { miner.Broken = true; return(false); } miner.Broken = false; return(true); }
private void OnActivate(EntityUid uid, TemperatureArtifactComponent component, ArtifactActivatedEvent args) { var transform = Transform(uid); var center = _atmosphereSystem.GetContainingMixture(uid, false, true); if (center == null) { return; } UpdateTileTemperature(component, center); if (component.EffectAdjacentTiles && transform.GridUid != null) { var adjacent = _atmosphereSystem.GetAdjacentTileMixtures(transform.GridUid.Value, _transformSystem.GetGridOrMapTilePosition(uid, transform), excite: true); foreach (var mixture in adjacent) { UpdateTileTemperature(component, mixture); } } }
private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, AtmosDeviceUpdateEvent args) { //Bingo waz here if (vent.Welded) { return; } var nodeName = vent.PumpDirection switch { VentPumpDirection.Releasing => vent.Inlet, VentPumpDirection.Siphoning => vent.Outlet, _ => throw new ArgumentOutOfRangeException() }; if (!vent.Enabled || !TryComp(uid, out AtmosDeviceComponent? device) || !TryComp(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(nodeName, out PipeNode? pipe)) { return; } var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); // We're in an air-blocked tile... Do nothing. if (environment == null) { return; } var timeDelta = (_gameTiming.CurTime - device.LastProcess).TotalSeconds; var pressureDelta = (float)timeDelta * vent.TargetPressureChange; if (vent.PumpDirection == VentPumpDirection.Releasing && pipe.Air.Pressure > 0) { if (environment.Pressure > vent.MaxPressure) { return; } if (environment.Pressure < vent.UnderPressureLockoutThreshold) { vent.UnderPressureLockout = true; return; } vent.UnderPressureLockout = false; if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, vent.ExternalPressureBound - environment.Pressure); } if (pressureDelta <= 0) { return; } // how many moles to transfer to change external pressure by pressureDelta // (ignoring temperature differences because I am lazy) var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R); // limit transferMoles so the source doesn't go below its bound. if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { var internalDelta = pipe.Air.Pressure - vent.InternalPressureBound; if (internalDelta <= 0) { return; } var maxTransfer = internalDelta * pipe.Air.Volume / (pipe.Air.Temperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, maxTransfer); } _atmosphereSystem.Merge(environment, pipe.Air.Remove(transferMoles)); } else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Pressure > 0) { if (pipe.Air.Pressure > vent.MaxPressure) { return; } if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) { pressureDelta = MathF.Min(pressureDelta, vent.InternalPressureBound - pipe.Air.Pressure); } if (pressureDelta <= 0) { return; } // how many moles to transfer to change internal pressure by pressureDelta // (ignoring temperature differences because I am lazy) var transferMoles = pressureDelta * pipe.Air.Volume / (environment.Temperature * Atmospherics.R); // limit transferMoles so the source doesn't go below its bound. if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { var externalDelta = environment.Pressure - vent.ExternalPressureBound; if (externalDelta <= 0) { return; } var maxTransfer = externalDelta * environment.Volume / (environment.Temperature * Atmospherics.R); transferMoles = MathF.Min(transferMoles, maxTransfer); } _atmosphereSystem.Merge(pipe.Air, environment.Remove(transferMoles)); } }
public void ExitDisposals(EntityUid uid, DisposalHolderComponent?holder = null, TransformComponent?holderTransform = null) { if (!Resolve(uid, ref holder, ref holderTransform)) { return; } if (holder.IsExitingDisposals) { Logger.ErrorS("c.s.disposal.holder", "Tried exiting disposals twice. This should never happen."); return; } holder.IsExitingDisposals = true; // Check for a disposal unit to throw them into and then eject them from it. // *This ejection also makes the target not collide with the unit.* // *This is on purpose.* DisposalUnitComponent?duc = null; if (_mapManager.TryGetGrid(holderTransform.GridUid, out var grid)) { foreach (var contentUid in grid.GetLocal(holderTransform.Coordinates)) { if (EntityManager.TryGetComponent(contentUid, out duc)) { break; } } } foreach (var entity in holder.Container.ContainedEntities.ToArray()) { RemComp <BeingDisposedComponent>(entity); if (EntityManager.TryGetComponent(entity, out IPhysBody? physics)) { physics.CanCollide = true; } var meta = MetaData(entity); holder.Container.ForceRemove(entity, EntityManager, meta); var xform = Transform(entity); if (xform.ParentUid != uid) { continue; } if (duc != null) { duc.Container.Insert(entity, EntityManager, xform, meta: meta); } else { xform.AttachParentToContainerOrGrid(EntityManager); } } if (duc != null) { _disposalUnitSystem.TryEjectContents(duc); } if (_atmosphereSystem.GetContainingMixture(uid, false, true) is {} environment) { _atmosphereSystem.Merge(environment, holder.Air); holder.Air.Clear(); } EntityManager.DeleteEntity(uid); }