diff --git a/Content.Client/Fluids/PuddleSystem.cs b/Content.Client/Fluids/PuddleSystem.cs index bf1a8cb50bc..a11bef7a761 100644 --- a/Content.Client/Fluids/PuddleSystem.cs +++ b/Content.Client/Fluids/PuddleSystem.cs @@ -55,6 +55,7 @@ private void OnPuddleAppearance(EntityUid uid, PuddleComponent component, ref Ap } } + var baseColor = Color.White; if (args.AppearanceData.TryGetValue(PuddleVisuals.SolutionColor, out var colorObj)) diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index d78b3780342..e02498b67db 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -105,6 +105,8 @@ public override void Update(float frameTime) } } + + if (respirator.Saturation < respirator.SuffocationThreshold) { if (_gameTiming.CurTime >= respirator.LastGaspEmoteTime + respirator.GaspEmoteCooldown) @@ -141,6 +143,9 @@ public void Inhale(Entity entity) if (!Resolve(entity, ref entity.Comp, logMissing: false)) return; + if (HasComp(entity)) + return; + // Inhale gas var ev = new InhaleLocationEvent { diff --git a/Content.Shared/Containers/NotBreathingComponent.cs b/Content.Shared/Containers/NotBreathingComponent.cs new file mode 100644 index 00000000000..e6b836c9329 --- /dev/null +++ b/Content.Shared/Containers/NotBreathingComponent.cs @@ -0,0 +1,8 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Body.Components; + +[NetworkedComponent, RegisterComponent] +public sealed partial class NotBreathingComponent : Component; // prevents breathing + + diff --git a/Content.Shared/Fluids/Components/PuddleComponent.cs b/Content.Shared/Fluids/Components/PuddleComponent.cs index 5d1cf2e5560..9ccffe9028a 100644 --- a/Content.Shared/Fluids/Components/PuddleComponent.cs +++ b/Content.Shared/Fluids/Components/PuddleComponent.cs @@ -2,6 +2,7 @@ using Content.Shared.FixedPoint; using Robust.Shared.Audio; using Robust.Shared.GameStates; +using Content.Shared.Atmos; namespace Content.Shared.Fluids.Components { @@ -28,6 +29,10 @@ public sealed partial class PuddleComponent : Component [ViewVariables] public Entity? Solution; + // amount before someone can drown in a puddle, for some reason the U required to is double this amount. + [DataField] + public FixedPoint2 DrownU = FixedPoint2.New(100); + [DataField] public bool AffectsMovement = true; diff --git a/Content.Shared/Fluids/SharedPuddleSystem.cs b/Content.Shared/Fluids/SharedPuddleSystem.cs index bc49d98c612..60b92e3a632 100644 --- a/Content.Shared/Fluids/SharedPuddleSystem.cs +++ b/Content.Shared/Fluids/SharedPuddleSystem.cs @@ -1,5 +1,7 @@ using System.Linq; +using System.Threading; using Content.Shared.Administration.Logs; +using Content.Shared.Atmos.Components; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.EntitySystems; @@ -24,11 +26,28 @@ using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Timing; +using Content.Shared.Body.Components; +using Robust.Shared.Physics.Events; +using Content.Shared.Clothing; namespace Content.Shared.Fluids; public abstract partial class SharedPuddleSystem : EntitySystem { + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] protected readonly ISharedAdminLogManager AdminLogger = default!; + [Dependency] protected readonly OpenableSystem Openable = default!; + [Dependency] protected readonly ReactiveSystem Reactive = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] protected readonly SharedAudioSystem Audio = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] protected readonly SharedPopupSystem Popups = default!; + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; + [Dependency] private readonly SpeedModifierContactsSystem _speedModContacts = default!; + [Dependency] private readonly StepTriggerSystem _stepTrigger = default!; + [Dependency] private readonly TileFrictionController _tile = default!; + [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] private IGameTiming _timing = default!; [Dependency] private IPrototypeManager _prototypeManager = default!; [Dependency] protected ISharedAdminLogManager AdminLogger = default!; @@ -71,6 +90,9 @@ public override void Initialize() SubscribeLocalEvent(OnGetFootstepSound); SubscribeLocalEvent(HandlePuddleExamined); SubscribeLocalEvent(OnEntRemoved); + SubscribeLocalEvent(DrowningStart); + SubscribeLocalEvent(DrowningEnd); + SubscribeLocalEvent(DrowningInternalsCheck); SubscribeLocalEvent(OnEvaporationMapInit); @@ -176,6 +198,49 @@ private void HandlePuddleExamined(Entity entity, ref ExaminedEv } } + // Todo more water levels (if flooded and can drown people, hide stuff inside tile) + + private void DrowningInternalsCheck(Entity entity, ref ItemMaskToggledEvent arg) + { + var uid = entity; + var nearbyEntities = _entityLookup.GetEntitiesInRange(Transform(uid).Coordinates, 1f); + + foreach (var ent in nearbyEntities) + { + if (HasComp(ent)) + { + RemComp(ent); + } + else if (!HasComp(ent)) + { + AddComp(ent); + } + } + } + + private void DrowningStart(Entity entity, ref StartCollideEvent arg) + { + if (HasComp(arg.OtherEntity)) + { + RemComp(arg.OtherEntity); + return; + } + + var (uid, puddle) = entity; + if (!_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution, out var solution)) + return; + + if (solution.Volume < puddle.DrownU) + return; + + EnsureComp(arg.OtherEntity); + } + + private void DrowningEnd(Entity entity, ref EndCollideEvent arg) + { + RemComp(arg.OtherEntity); + } + private void OnAnchorChanged(Entity entity, ref AnchorStateChangedEvent args) { if (!args.Anchored)