Beispiel #1
0
        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.
                }
            }
        }
Beispiel #2
0
    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();
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
            }
        }
    }
Beispiel #10
0
        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));
            }
        }
Beispiel #11
0
        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);
        }