コード例 #1
0
        public GasMixture Clean(EntityUid uid, RespiratorComponent respirator, BloodstreamComponent bloodstream)
        {
            var gasMixture = new GasMixture(bloodstream.Air.Volume)
            {
                Temperature = bloodstream.Air.Temperature
            };

            for (Gas gas = 0; gas < (Gas)Atmospherics.TotalNumberOfGases; gas++)
            {
                float amount;
                var   molesInBlood = bloodstream.Air.GetMoles(gas);

                if (!respirator.NeedsGases.TryGetValue(gas, out var needed))
                {
                    amount = molesInBlood;
                }
                else
                {
                    var overflowThreshold = needed * 5f;

                    amount = molesInBlood > overflowThreshold
                        ? molesInBlood - overflowThreshold
                        : 0;
                }

                gasMixture.AdjustMoles(gas, amount);
                bloodstream.Air.AdjustMoles(gas, -amount);
            }

            return(gasMixture);
        }
コード例 #2
0
        private void StopSuffocation(EntityUid uid, RespiratorComponent respirator)
        {
            if (respirator.SuffocationCycles >= 2)
            {
                _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} stopped suffocating");
            }

            _alertsSystem.ClearAlert(uid, AlertType.LowOxygen);

            _damageableSys.TryChangeDamage(uid, respirator.DamageRecovery, true);
        }
コード例 #3
0
        public async Task NoSuffocationTest()
        {
            var options = new ServerContentIntegrationOption {
                ExtraPrototypes = Prototypes
            };
            var server = StartServer(options);

            await server.WaitIdleAsync();

            var mapLoader     = server.ResolveDependency <IMapLoader>();
            var mapManager    = server.ResolveDependency <IMapManager>();
            var entityManager = server.ResolveDependency <IEntityManager>();

            MapId               mapId;
            IMapGrid            grid       = null;
            RespiratorComponent respirator = null;
            EntityUid           human      = default;

            var testMapName = "Maps/Test/Breathing/3by3-20oxy-80nit.yml";

            await server.WaitPost(() =>
            {
                mapId = mapManager.CreateMap();
                grid  = mapLoader.LoadBlueprint(mapId, testMapName);
            });

            Assert.NotNull(grid, $"Test blueprint {testMapName} not found.");

            await server.WaitAssertion(() =>
            {
                var center      = new Vector2(0.5f, -1.5f);
                var coordinates = new EntityCoordinates(grid.GridEntityId, center);
                human           = entityManager.SpawnEntity("HumanBodyAndBloodstreamDummy", coordinates);

                Assert.True(entityManager.HasComponent <SharedBodyComponent>(human));
                Assert.True(entityManager.TryGetComponent(human, out respirator));
                Assert.False(respirator.Suffocating);
            });

            var increment = 10;


            for (var tick = 0; tick < 600; tick += increment)
            {
                await server.WaitRunTicks(increment);

                await server.WaitAssertion(() =>
                {
                    Assert.False(respirator.Suffocating, $"Entity {entityManager.GetComponent<MetaDataComponent>(human).EntityName} is suffocating on tick {tick}");
                });
            }

            await server.WaitIdleAsync();
        }
コード例 #4
0
        private Dictionary <Gas, float> NeedsAndDeficit(RespiratorComponent respirator)
        {
            var needs = new Dictionary <Gas, float>(respirator.NeedsGases);

            foreach (var(gas, amount) in respirator.DeficitGases)
            {
                var newAmount = (needs.GetValueOrDefault(gas) + amount);
                needs[gas] = newAmount;
            }

            return(needs);
        }
コード例 #5
0
        private void TakeSuffocationDamage(EntityUid uid, RespiratorComponent respirator)
        {
            if (!respirator.Suffocating)
            {
                _logSys.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} started suffocating");
            }

            respirator.Suffocating = true;

            _alertsSystem.ShowAlert(uid, AlertType.LowOxygen);

            _damageableSys.TryChangeDamage(uid, respirator.Damage, true, false);
        }
コード例 #6
0
        private void TakeSuffocationDamage(EntityUid uid, RespiratorComponent respirator)
        {
            if (respirator.SuffocationCycles == 2)
            {
                _adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} started suffocating");
            }

            if (respirator.SuffocationCycles >= respirator.SuffocationCycleThreshold)
            {
                _alertsSystem.ShowAlert(uid, AlertType.LowOxygen);
            }

            _damageableSys.TryChangeDamage(uid, respirator.Damage, true, false);
        }
コード例 #7
0
        private float GasProducedMultiplier(RespiratorComponent respirator, Gas gas, float usedAverage)
        {
            if (!respirator.ProducesGases.TryGetValue(gas, out var produces))
            {
                return(0);
            }

            if (!respirator.NeedsGases.TryGetValue(gas, out var needs))
            {
                needs = 1;
            }

            return(needs * produces * usedAverage);
        }
コード例 #8
0
        public async Task NoSuffocationTest()
        {
            await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings { NoClient = true, ExtraPrototypes = Prototypes });

            var server = pairTracker.Pair.Server;

            var mapLoader     = server.ResolveDependency <IMapLoader>();
            var mapManager    = server.ResolveDependency <IMapManager>();
            var entityManager = server.ResolveDependency <IEntityManager>();

            MapId               mapId;
            EntityUid?          grid       = null;
            RespiratorComponent respirator = null;
            EntityUid           human      = default;

            var testMapName = "Maps/Test/Breathing/3by3-20oxy-80nit.yml";

            await server.WaitPost(() =>
            {
                mapId = mapManager.CreateMap();
                grid  = mapLoader.LoadBlueprint(mapId, testMapName).gridId;
            });

            Assert.NotNull(grid, $"Test blueprint {testMapName} not found.");

            await server.WaitAssertion(() =>
            {
                var center      = new Vector2(0.5f, -1.5f);
                var coordinates = new EntityCoordinates(grid.Value, center);
                human           = entityManager.SpawnEntity("HumanBodyDummy", coordinates);

                Assert.True(entityManager.HasComponent <SharedBodyComponent>(human));
                Assert.True(entityManager.TryGetComponent(human, out respirator));
                Assert.False(respirator.SuffocationCycles > respirator.SuffocationCycleThreshold);
            });

            var increment = 10;

            for (var tick = 0; tick < 600; tick += increment)
            {
                await server.WaitRunTicks(increment);

                await server.WaitAssertion(() =>
                {
                    Assert.False(respirator.SuffocationCycles > respirator.SuffocationCycleThreshold, $"Entity {entityManager.GetComponent<MetaDataComponent>(human).EntityName} is suffocating on tick {tick}");
                });
            }

            await pairTracker.CleanReturnAsync();
        }
コード例 #9
0
        private void StopSuffocation(EntityUid uid, RespiratorComponent respirator)
        {
            if (respirator.Suffocating)
            {
                _logSys.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} stopped suffocating");
            }

            respirator.Suffocating = false;

            if (EntityManager.TryGetComponent(uid, out ServerAlertsComponent? alertsComponent))
            {
                alertsComponent.ClearAlert(AlertType.LowOxygen);
            }

            _damageableSys.TryChangeDamage(uid, respirator.DamageRecovery, true);
        }
コード例 #10
0
        private void TakeSuffocationDamage(EntityUid uid, RespiratorComponent respirator)
        {
            if (!respirator.Suffocating)
            {
                _logSys.Add(LogType.Asphyxiation, $"{ToPrettyString(uid):entity} started suffocating");
            }

            respirator.Suffocating = true;

            if (EntityManager.TryGetComponent(uid, out ServerAlertsComponent? alertsComponent))
            {
                alertsComponent.ShowAlert(AlertType.LowOxygen);
            }

            _damageableSys.TryChangeDamage(uid, respirator.Damage, true, false);
        }
コード例 #11
0
        private float SuffocatingPercentage(RespiratorComponent respirator)
        {
            var total = 0f;

            foreach (var(gas, deficit) in respirator.DeficitGases)
            {
                var lack = 1f;
                if (respirator.NeedsGases.TryGetValue(gas, out var needed))
                {
                    lack = deficit / needed;
                }

                total += lack / Atmospherics.TotalNumberOfGases;
            }

            return(total);
        }
コード例 #12
0
        private void ClampDeficit(RespiratorComponent respirator)
        {
            var deficitGases = new Dictionary <Gas, float>(respirator.DeficitGases);

            foreach (var(gas, deficit) in deficitGases)
            {
                if (!respirator.NeedsGases.TryGetValue(gas, out var need))
                {
                    respirator.DeficitGases.Remove(gas);
                    continue;
                }

                if (deficit > need)
                {
                    respirator.DeficitGases[gas] = need;
                }
            }
        }
コード例 #13
0
 private void OnApplyMetabolicMultiplier(EntityUid uid, RespiratorComponent component, ApplyMetabolicMultiplierEvent args)
 {
     if (args.Apply)
     {
         component.CycleDelay    *= args.Multiplier;
         component.Saturation    *= args.Multiplier;
         component.MaxSaturation *= args.Multiplier;
         component.MinSaturation *= args.Multiplier;
         return;
     }
     // This way we don't have to worry about it breaking if the stasis bed component is destroyed
     component.CycleDelay    /= args.Multiplier;
     component.Saturation    /= args.Multiplier;
     component.MaxSaturation /= args.Multiplier;
     component.MinSaturation /= args.Multiplier;
     // Reset the accumulator properly
     if (component.AccumulatedFrametime >= component.CycleDelay)
     {
         component.AccumulatedFrametime = component.CycleDelay;
     }
 }
コード例 #14
0
        private void ProcessGases(EntityUid uid, RespiratorComponent respirator,
                                  BloodstreamComponent?bloodstream,
                                  SharedBodyComponent?body)
        {
            if (!Resolve(uid, ref bloodstream, ref body, false))
            {
                return;
            }

            var lungs = _bodySystem.GetComponentsOnMechanisms <LungComponent>(uid, body).ToArray();

            var needs = NeedsAndDeficit(respirator);
            var used  = 0f;

            foreach (var(lung, mech) in lungs)
            {
                _lungSystem.UpdateLung(lung.Owner, lung, mech);
            }

            foreach (var(gas, amountNeeded) in needs)
            {
                var bloodstreamAmount = bloodstream.Air.GetMoles(gas);
                var deficit           = 0f;

                if (bloodstreamAmount < amountNeeded)
                {
                    // Panic inhale
                    foreach (var(lung, mech) in lungs)
                    {
                        _lungSystem.Gasp((lung).Owner, lung, mech);
                    }

                    bloodstreamAmount = bloodstream.Air.GetMoles(gas);

                    deficit = Math.Max(0, amountNeeded - bloodstreamAmount);

                    if (deficit > 0)
                    {
                        bloodstream.Air.SetMoles(gas, 0);
                    }
                    else
                    {
                        bloodstream.Air.AdjustMoles(gas, -amountNeeded);
                    }
                }
                else
                {
                    bloodstream.Air.AdjustMoles(gas, -amountNeeded);
                }

                respirator.DeficitGases[gas] = deficit;

                used += (amountNeeded - deficit) / amountNeeded;
            }

            var produced = GasProduced(respirator, used / needs.Count);

            foreach (var(gas, amountProduced) in produced)
            {
                bloodstream.Air.AdjustMoles(gas, amountProduced);
            }

            ClampDeficit(respirator);
        }
コード例 #15
0
 private Dictionary <Gas, float> GasProduced(RespiratorComponent respirator, float usedAverage)
 {
     return(respirator.ProducesGases.ToDictionary(pair => pair.Key, pair => GasProducedMultiplier(respirator, pair.Key, usedAverage)));
 }