RespiratorSystem Cleanup (#38572)
* Respirator Debodied * Forgot about alerts (also respirator testa and events) * Fix Urist eating air and not giving it back * Stop nuke ops from taking in a breath then taking in a second breath causing them to get a headache from carbon dioxide poisoning and failing TryStopNukeOpsFromConstantlyFailing(); * Consts are smelly, * Actually we don't need to raise the entity, just the component * Don't forget to remove the unused code today, said me yesterday * Remove all fallbacks * Debody that too --------- Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
e916135a9c
commit
d7d83bd87c
@@ -1,4 +1,6 @@
|
|||||||
using Content.Server.Body.Systems;
|
using Content.Server.Body.Systems;
|
||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Chat.Prototypes;
|
using Content.Shared.Chat.Prototypes;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -9,6 +11,28 @@ namespace Content.Server.Body.Components
|
|||||||
[RegisterComponent, Access(typeof(RespiratorSystem))]
|
[RegisterComponent, Access(typeof(RespiratorSystem))]
|
||||||
public sealed partial class RespiratorComponent : Component
|
public sealed partial class RespiratorComponent : Component
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gas container for this entity
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public GasMixture Air = new()
|
||||||
|
{
|
||||||
|
Volume = 6, // 6 liters, the average lung capacity for a human according to Google
|
||||||
|
Temperature = Atmospherics.NormalBodyTemperature
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume of our breath in liters
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float BreathVolume = Atmospherics.BreathVolume;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much of the gas we inhale is metabolized? Value range is (0, 1]
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float Ratio = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The next time that this body will inhale or exhale.
|
/// The next time that this body will inhale or exhale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
|
using Content.Server.Body.Components;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
@@ -58,7 +59,7 @@ public sealed class InternalsSystem : SharedInternalsSystem
|
|||||||
if (AreInternalsWorking(ent))
|
if (AreInternalsWorking(ent))
|
||||||
{
|
{
|
||||||
var gasTank = Comp<GasTankComponent>(ent.Comp.GasTankEntity!.Value);
|
var gasTank = Comp<GasTankComponent>(ent.Comp.GasTankEntity!.Value);
|
||||||
args.Gas = _gasTank.RemoveAirVolume((ent.Comp.GasTankEntity.Value, gasTank), Atmospherics.BreathVolume);
|
args.Gas = _gasTank.RemoveAirVolume((ent.Comp.GasTankEntity.Value, gasTank), args.Respirator.BreathVolume);
|
||||||
// TODO: Should listen to gas tank updates instead I guess?
|
// TODO: Should listen to gas tank updates instead I guess?
|
||||||
_alerts.ShowAlert(ent, ent.Comp.InternalsAlert, GetSeverity(ent));
|
_alerts.ShowAlert(ent, ent.Comp.InternalsAlert, GetSeverity(ent));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ public sealed class LungSystem : EntitySystem
|
|||||||
_solutionContainerSystem.UpdateChemicals(lung.Solution.Value);
|
_solutionContainerSystem.UpdateChemicals(lung.Solution.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This should really be moved to somewhere in the atmos system and modernized,
|
||||||
|
so that other systems, like CondenserSystem, can use it.
|
||||||
|
*/
|
||||||
private void GasToReagent(GasMixture gas, Solution solution)
|
private void GasToReagent(GasMixture gas, Solution solution)
|
||||||
{
|
{
|
||||||
foreach (var gasId in Enum.GetValues<Gas>())
|
foreach (var gasId in Enum.GetValues<Gas>())
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
|
SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||||
SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||||
|
SubscribeLocalEvent<BodyComponent, InhaledGasEvent>(OnGasInhaled);
|
||||||
|
SubscribeLocalEvent<BodyComponent, ExhaledGasEvent>(OnGasExhaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
|
private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
|
||||||
@@ -77,18 +79,18 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
if (_mobState.IsDead(uid))
|
if (_mobState.IsDead(uid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
UpdateSaturation(uid, -(float) respirator.UpdateInterval.TotalSeconds, respirator);
|
UpdateSaturation(uid, -(float)respirator.UpdateInterval.TotalSeconds, respirator);
|
||||||
|
|
||||||
if (!_mobState.IsIncapacitated(uid)) // cannot breathe in crit.
|
if (!_mobState.IsIncapacitated(uid)) // cannot breathe in crit.
|
||||||
{
|
{
|
||||||
switch (respirator.Status)
|
switch (respirator.Status)
|
||||||
{
|
{
|
||||||
case RespiratorStatus.Inhaling:
|
case RespiratorStatus.Inhaling:
|
||||||
Inhale(uid, body);
|
Inhale(uid);
|
||||||
respirator.Status = RespiratorStatus.Exhaling;
|
respirator.Status = RespiratorStatus.Exhaling;
|
||||||
break;
|
break;
|
||||||
case RespiratorStatus.Exhaling:
|
case RespiratorStatus.Exhaling:
|
||||||
Exhale(uid, body);
|
Exhale(uid);
|
||||||
respirator.Status = RespiratorStatus.Inhaling;
|
respirator.Status = RespiratorStatus.Inhaling;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -99,7 +101,10 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
|
if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown)
|
||||||
{
|
{
|
||||||
respirator.LastGaspEmoteTime = _gameTiming.CurTime;
|
respirator.LastGaspEmoteTime = _gameTiming.CurTime;
|
||||||
_chat.TryEmoteWithChat(uid, respirator.GaspEmote, ChatTransmitRange.HideChat, ignoreActionBlocker: true);
|
_chat.TryEmoteWithChat(uid,
|
||||||
|
respirator.GaspEmote,
|
||||||
|
ChatTransmitRange.HideChat,
|
||||||
|
ignoreActionBlocker: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TakeSuffocationDamage((uid, respirator));
|
TakeSuffocationDamage((uid, respirator));
|
||||||
@@ -112,68 +117,54 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inhale(EntityUid uid, BodyComponent? body = null)
|
public bool Inhale(Entity<RespiratorComponent?> entity)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref body, logMissing: false))
|
if (!Resolve(entity, ref entity.Comp, logMissing: false))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((uid, body));
|
|
||||||
|
|
||||||
// Inhale gas
|
// Inhale gas
|
||||||
var ev = new InhaleLocationEvent();
|
var ev = new InhaleLocationEvent
|
||||||
RaiseLocalEvent(uid, ref ev);
|
{
|
||||||
|
Respirator = entity.Comp,
|
||||||
|
};
|
||||||
|
RaiseLocalEvent(entity, ref ev);
|
||||||
|
|
||||||
ev.Gas ??= _atmosSys.GetContainingMixture(uid, excite: true);
|
ev.Gas ??= _atmosSys.GetContainingMixture(entity.Owner, excite: true);
|
||||||
|
|
||||||
if (ev.Gas is null)
|
if (ev.Gas is null)
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var actualGas = ev.Gas.RemoveVolume(Atmospherics.BreathVolume);
|
var gas = ev.Gas.RemoveVolume(entity.Comp.BreathVolume);
|
||||||
|
|
||||||
var lungRatio = 1.0f / organs.Count;
|
var inhaleEv = new InhaledGasEvent(gas);
|
||||||
var gas = organs.Count == 1 ? actualGas : actualGas.RemoveRatio(lungRatio);
|
RaiseLocalEvent(entity, ref inhaleEv);
|
||||||
foreach (var (organUid, lung, _) in organs)
|
|
||||||
{
|
return inhaleEv.Handled && inhaleEv.Succeeded;
|
||||||
// Merge doesn't remove gas from the giver.
|
|
||||||
_atmosSys.Merge(lung.Air, gas);
|
|
||||||
_lungSystem.GasToReagent(organUid, lung);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Exhale(EntityUid uid, BodyComponent? body = null)
|
public void Exhale(Entity<RespiratorComponent?> entity)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref body, logMissing: false))
|
if (!Resolve(entity, ref entity.Comp, logMissing: false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((uid, body));
|
|
||||||
|
|
||||||
// exhale gas
|
// exhale gas
|
||||||
|
|
||||||
var ev = new ExhaleLocationEvent();
|
var ev = new ExhaleLocationEvent();
|
||||||
RaiseLocalEvent(uid, ref ev, broadcast: false);
|
RaiseLocalEvent(entity, ref ev, broadcast: false);
|
||||||
|
|
||||||
if (ev.Gas is null)
|
if (ev.Gas is null)
|
||||||
{
|
{
|
||||||
ev.Gas = _atmosSys.GetContainingMixture(uid, excite: true);
|
ev.Gas = _atmosSys.GetContainingMixture(entity.Owner, excite: true);
|
||||||
|
|
||||||
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
|
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
|
||||||
// but this also means you cannot exhale on some grids.
|
// but this also means you cannot exhale on some grids.
|
||||||
ev.Gas ??= GasMixture.SpaceGas;
|
ev.Gas ??= GasMixture.SpaceGas;
|
||||||
}
|
}
|
||||||
|
|
||||||
var outGas = new GasMixture(ev.Gas.Volume);
|
var exhaleEv = new ExhaledGasEvent(ev.Gas);
|
||||||
foreach (var (organUid, lung, _) in organs)
|
RaiseLocalEvent(entity, ref exhaleEv);
|
||||||
{
|
|
||||||
_atmosSys.Merge(outGas, lung.Air);
|
|
||||||
lung.Air.Clear();
|
|
||||||
|
|
||||||
if (_solutionContainerSystem.ResolveSolution(organUid, lung.SolutionName, ref lung.Solution))
|
|
||||||
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
_atmosSys.Merge(ev.Gas, outGas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -199,14 +190,15 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
if (!Resolve(ent, ref ent.Comp))
|
if (!Resolve(ent, ref ent.Comp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ev = new InhaleLocationEvent();
|
if (!Inhale(ent))
|
||||||
RaiseLocalEvent(ent, ref ev);
|
|
||||||
|
|
||||||
var gas = ev.Gas ?? _atmosSys.GetContainingMixture(ent.Owner);
|
|
||||||
if (gas == null)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return CanMetabolizeGas(ent, gas);
|
// If we don't have a body we can't be poisoned by gas, yet...
|
||||||
|
var success = TryMetabolizeGas((ent, ent.Comp));
|
||||||
|
|
||||||
|
// Don't keep that gas in our lungs lest it poisons a poor nuclear operative.
|
||||||
|
Exhale(ent);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -224,7 +216,7 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
|
|
||||||
gas = new GasMixture(gas);
|
gas = new GasMixture(gas);
|
||||||
var lungRatio = 1.0f / organs.Count;
|
var lungRatio = 1.0f / organs.Count;
|
||||||
gas.Multiply(MathF.Min(lungRatio * gas.Volume/Atmospherics.BreathVolume, lungRatio));
|
gas.Multiply(MathF.Min(lungRatio * gas.Volume / ent.Comp.BreathVolume, lungRatio));
|
||||||
var solution = _lungSystem.GasToReagent(gas);
|
var solution = _lungSystem.GasToReagent(gas);
|
||||||
|
|
||||||
float saturation = 0;
|
float saturation = 0;
|
||||||
@@ -238,6 +230,71 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
return saturation > ent.Comp.UpdateInterval.TotalSeconds;
|
return saturation > ent.Comp.UpdateInterval.TotalSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryInhaleGasToBody(Entity<BodyComponent?> entity, GasMixture gas)
|
||||||
|
{
|
||||||
|
if (!Resolve(entity, ref entity.Comp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((entity, entity.Comp));
|
||||||
|
if (organs.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var lungRatio = 1.0f / organs.Count;
|
||||||
|
var splitGas = organs.Count == 1 ? gas : gas.RemoveRatio(lungRatio);
|
||||||
|
foreach (var (organUid, lung, _) in organs)
|
||||||
|
{
|
||||||
|
// Merge doesn't remove gas from the giver.
|
||||||
|
_atmosSys.Merge(lung.Air, splitGas);
|
||||||
|
_lungSystem.GasToReagent(organUid, lung);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGasFromBody(Entity<BodyComponent> ent, GasMixture gas)
|
||||||
|
{
|
||||||
|
var outGas = new GasMixture(gas.Volume);
|
||||||
|
|
||||||
|
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, ent.Comp));
|
||||||
|
if (organs.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var (organUid, lung, _) in organs)
|
||||||
|
{
|
||||||
|
_atmosSys.Merge(outGas, lung.Air);
|
||||||
|
lung.Air.Clear();
|
||||||
|
|
||||||
|
if (_solutionContainerSystem.ResolveSolution(organUid, lung.SolutionName, ref lung.Solution))
|
||||||
|
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_atmosSys.Merge(gas, outGas);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to safely metabolize the current solutions in a body's lungs.
|
||||||
|
/// </summary>
|
||||||
|
private bool TryMetabolizeGas(Entity<RespiratorComponent, BodyComponent?> ent)
|
||||||
|
{
|
||||||
|
if (!Resolve(ent, ref ent.Comp2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
|
||||||
|
if (organs.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float saturation = 0;
|
||||||
|
foreach (var organ in organs)
|
||||||
|
{
|
||||||
|
var solution = _lungSystem.GasToReagent(organ.Comp1.Air);
|
||||||
|
saturation += GetSaturation(solution, organ.Owner, out var toxic);
|
||||||
|
if (toxic)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return saturation > ent.Comp1.UpdateInterval.TotalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the amount of saturation that would be generated if the lung were to metabolize the given solution.
|
/// Get the amount of saturation that would be generated if the lung were to metabolize the given solution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -301,6 +358,8 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
if (ent.Comp.SuffocationCycles == 2)
|
if (ent.Comp.SuffocationCycles == 2)
|
||||||
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
|
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} started suffocating");
|
||||||
|
|
||||||
|
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
|
||||||
|
|
||||||
if (ent.Comp.SuffocationCycles >= ent.Comp.SuffocationCycleThreshold)
|
if (ent.Comp.SuffocationCycles >= ent.Comp.SuffocationCycleThreshold)
|
||||||
{
|
{
|
||||||
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
|
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
|
||||||
@@ -310,8 +369,6 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
_alertsSystem.ShowAlert(ent, entity.Comp1.Alert);
|
_alertsSystem.ShowAlert(ent, entity.Comp1.Alert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_damageableSys.TryChangeDamage(ent, ent.Comp.Damage, interruptsDoAfters: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopSuffocation(Entity<RespiratorComponent> ent)
|
private void StopSuffocation(Entity<RespiratorComponent> ent)
|
||||||
@@ -319,18 +376,17 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
if (ent.Comp.SuffocationCycles >= 2)
|
if (ent.Comp.SuffocationCycles >= 2)
|
||||||
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
|
_adminLogger.Add(LogType.Asphyxiation, $"{ToPrettyString(ent):entity} stopped suffocating");
|
||||||
|
|
||||||
|
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
|
||||||
|
|
||||||
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
|
// TODO: This is not going work with multiple different lungs, if that ever becomes a possibility
|
||||||
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
|
var organs = _bodySystem.GetBodyOrganEntityComps<LungComponent>((ent, null));
|
||||||
foreach (var entity in organs)
|
foreach (var entity in organs)
|
||||||
{
|
{
|
||||||
_alertsSystem.ClearAlert(ent, entity.Comp1.Alert);
|
_alertsSystem.ClearAlert(ent, entity.Comp1.Alert);
|
||||||
}
|
}
|
||||||
|
|
||||||
_damageableSys.TryChangeDamage(ent, ent.Comp.DamageRecovery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSaturation(EntityUid uid, float amount,
|
public void UpdateSaturation(EntityUid uid, float amount, RespiratorComponent? respirator = null)
|
||||||
RespiratorComponent? respirator = null)
|
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref respirator, false))
|
if (!Resolve(uid, ref respirator, false))
|
||||||
return;
|
return;
|
||||||
@@ -362,10 +418,30 @@ public sealed class RespiratorSystem : EntitySystem
|
|||||||
ent.Comp.MaxSaturation /= args.Multiplier;
|
ent.Comp.MaxSaturation /= args.Multiplier;
|
||||||
ent.Comp.MinSaturation /= args.Multiplier;
|
ent.Comp.MinSaturation /= args.Multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGasInhaled(Entity<BodyComponent> entity, ref InhaledGasEvent args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
|
args.Succeeded = TryInhaleGasToBody((entity, entity.Comp), args.Gas);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGasExhaled(Entity<BodyComponent> entity, ref ExhaledGasEvent args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
|
RemoveGasFromBody(entity, args.Gas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct InhaleLocationEvent(GasMixture? Gas);
|
public record struct InhaleLocationEvent(GasMixture? Gas, RespiratorComponent Respirator);
|
||||||
|
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct ExhaleLocationEvent(GasMixture? Gas);
|
public record struct ExhaleLocationEvent(GasMixture? Gas);
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct InhaledGasEvent(GasMixture Gas, bool Handled = false, bool Succeeded = false);
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct ExhaledGasEvent(GasMixture Gas, bool Handled = false);
|
||||||
|
|||||||
Reference in New Issue
Block a user