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); }
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); }
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(); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); }
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; } } }
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; } }
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); }
private Dictionary <Gas, float> GasProduced(RespiratorComponent respirator, float usedAverage) { return(respirator.ProducesGases.ToDictionary(pair => pair.Key, pair => GasProducedMultiplier(respirator, pair.Key, usedAverage))); }