diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs index d02dd44e81f..2eaf19170b7 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.Spillable.cs @@ -27,8 +27,6 @@ protected override void InitializeSpillable() SubscribeLocalEvent(SpillOnLand); // Openable handles the event if it's closed SubscribeLocalEvent(SplashOnMeleeHit, after: [typeof(OpenableSystem)]); - SubscribeLocalEvent(OnGotEquipped); - SubscribeLocalEvent(OnGotUnequipped); SubscribeLocalEvent(OnOverflow); SubscribeLocalEvent(OnDoAfter); SubscribeLocalEvent(OnAttemptPacifiedThrow); @@ -97,33 +95,6 @@ private void SplashOnMeleeHit(Entity entity, ref MeleeHitEve } } - private void OnGotEquipped(Entity entity, ref ClothingGotEquippedEvent args) - { - if (!entity.Comp.SpillWorn) - return; - - if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution)) - return; - - // block access to the solution while worn - AddComp(entity); - - if (solution.Volume == 0) - return; - - // spill all solution on the player - var drainedSolution = _solutionContainerSystem.Drain(entity.Owner, soln.Value, solution.Volume); - TrySplashSpillAt(entity.Owner, Transform(args.Wearer).Coordinates, drainedSolution, out _); - } - - private void OnGotUnequipped(Entity entity, ref ClothingGotUnequippedEvent args) - { - if (!entity.Comp.SpillWorn) - return; - - RemCompDeferred(entity); - } - private void SpillOnLand(Entity entity, ref LandEvent args) { if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out var soln, out var solution)) diff --git a/Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs b/Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs deleted file mode 100644 index 182f92d7d33..00000000000 --- a/Content.Shared/Chemistry/Components/BlockSolutionAccessComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared.Chemistry.Components; - -/// -/// Blocks all attempts to access solutions contained by this entity. -/// -[RegisterComponent, NetworkedComponent] -public sealed partial class BlockSolutionAccessComponent : Component -{ -} diff --git a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs index 5e58a0944a4..7e00157b6ee 100644 --- a/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs +++ b/Content.Shared/Chemistry/EntitySystems/SharedSolutionContainerSystem.cs @@ -48,6 +48,12 @@ public partial record struct SolutionOverflowEvent(Entity Sol public bool Handled = false; } +[ByRefEvent] +public partial record struct SolutionAccessAttemptEvent(string SolutionName) +{ + public bool Cancelled; +} + /// /// Part of Chemistry system deal with SolutionContainers /// @@ -156,12 +162,6 @@ public bool TryGetSolution( [NotNullWhen(true)] out Entity? entity, bool errorOnMissing = false) { - if (TryComp(container, out BlockSolutionAccessComponent? blocker)) - { - entity = null; - return false; - } - EntityUid uid; if (name is null) uid = container; @@ -170,7 +170,18 @@ public bool TryGetSolution( solutionContainer is ContainerSlot solutionSlot && solutionSlot.ContainedEntity is { } containedSolution ) + { + var attemptEv = new SolutionAccessAttemptEvent(name); + RaiseLocalEvent(container, ref attemptEv); + + if (attemptEv.Cancelled) + { + entity = null; + return false; + } + uid = containedSolution; + } else { entity = null; @@ -218,11 +229,14 @@ public bool TryGetSolution(SolutionContainerManagerComponent container, if (!Resolve(container, ref container.Comp, logMissing: false)) yield break; - if (HasComp(container)) - yield break; - foreach (var name in container.Comp.Containers) { + var attemptEv = new SolutionAccessAttemptEvent(name); + RaiseLocalEvent(container, ref attemptEv); + + if (attemptEv.Cancelled) + continue; + if (ContainerSystem.GetContainer(container, $"solution@{name}") is ContainerSlot slot && slot.ContainedEntity is { } solutionId) yield return (name, (solutionId, Comp(solutionId))); } diff --git a/Content.Shared/Fluids/Components/SpillWhenWornComponent.cs b/Content.Shared/Fluids/Components/SpillWhenWornComponent.cs new file mode 100644 index 00000000000..d456d181b4a --- /dev/null +++ b/Content.Shared/Fluids/Components/SpillWhenWornComponent.cs @@ -0,0 +1,24 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Fluids.Components; + +/// +/// This entity will spill its contained solution onto the wearer when worn, and its +/// (empty) contents will be inaccessible while still worn. +/// +[RegisterComponent] +[NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SpillWhenWornComponent : Component +{ + /// + /// Name of the solution to spill. + /// + [DataField] + public string Solution = "default"; + + /// + /// Tracks if this item is currently being worn. + /// + [DataField, AutoNetworkedField] + public bool IsWorn; +} diff --git a/Content.Shared/Fluids/Components/SpillableComponent.cs b/Content.Shared/Fluids/Components/SpillableComponent.cs index 51bb73a11fe..cc57dbf2b60 100644 --- a/Content.Shared/Fluids/Components/SpillableComponent.cs +++ b/Content.Shared/Fluids/Components/SpillableComponent.cs @@ -14,13 +14,6 @@ public sealed partial class SpillableComponent : Component [DataField("solution")] public string SolutionName = "puddle"; - /// - /// Should this item be spilled when worn as clothing? - /// Doesn't count for pockets or hands. - /// - [DataField] - public bool SpillWorn = true; - [DataField] public float? SpillDelay; diff --git a/Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs b/Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs new file mode 100644 index 00000000000..210dbfd4de7 --- /dev/null +++ b/Content.Shared/Fluids/EntitySystems/SpillWhenWornSystem.cs @@ -0,0 +1,55 @@ +using Content.Shared.Chemistry.EntitySystems; +using Content.Shared.Clothing; +using Content.Shared.Fluids.Components; + +namespace Content.Shared.Fluids.EntitySystems; + +/// +public sealed class SpillWhenWornSystem : EntitySystem +{ + [Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!; + [Dependency] private readonly SharedPuddleSystem _puddle = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGotEquipped); + SubscribeLocalEvent(OnGotUnequipped); + SubscribeLocalEvent(OnSolutionAccessAttempt); + } + + private void OnGotEquipped(Entity ent, ref ClothingGotEquippedEvent args) + { + if (_solutionContainer.TryGetSolution(ent.Owner, ent.Comp.Solution, out var soln, out var solution) + && solution.Volume > 0) + { + // Spill all solution on the player + var drainedSolution = _solutionContainer.Drain(ent.Owner, soln.Value, solution.Volume); + _puddle.TrySplashSpillAt(ent.Owner, Transform(args.Wearer).Coordinates, drainedSolution, out _); + } + + // Flag as worn after draining, otherwise we'll block ourself from accessing! + ent.Comp.IsWorn = true; + Dirty(ent); + } + + private void OnGotUnequipped(Entity ent, ref ClothingGotUnequippedEvent args) + { + ent.Comp.IsWorn = false; + Dirty(ent); + } + + private void OnSolutionAccessAttempt(Entity ent, ref SolutionAccessAttemptEvent args) + { + // If we're not being worn right now, we don't care + if (!ent.Comp.IsWorn) + return; + + // Make sure it's the right solution + if (ent.Comp.Solution != args.SolutionName) + return; + + args.Cancelled = true; + } +} diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 9a5de7a56f9..ea68fd3804c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Plykiya - changes: - - message: Dropped items are no longer rotated to world north. - type: Fix - id: 6295 - time: '2024-04-03T05:31:57.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/26662 - author: deltanedas changes: - message: Disabled scooping foam due to a reagent duplication bug. @@ -3845,3 +3838,10 @@ id: 6794 time: '2024-06-20T14:19:22.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/29210 +- author: MilenVolf + changes: + - message: Stasis bed can be toggled on or off! + type: Tweak + id: 6795 + time: '2024-06-21T03:02:23.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/29268 diff --git a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml index 77c5e548978..58c8dae2b05 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/bucket.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/bucket.yml @@ -45,6 +45,8 @@ Blunt: 0 - type: Spillable solution: bucket + - type: SpillWhenWorn + solution: bucket - type: DrawableSolution solution: bucket - type: RefillableSolution diff --git a/Resources/Prototypes/Entities/Structures/Machines/stasisbed.yml b/Resources/Prototypes/Entities/Structures/Machines/stasisbed.yml index ba9d7be88b0..4dd1197593c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/stasisbed.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/stasisbed.yml @@ -59,3 +59,4 @@ - type: GuideHelp guides: - Medical Doctor + - type: PowerSwitch