]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
MessyDrinker for dogs (#38852)
authorScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Wed, 6 Aug 2025 13:00:32 +0000 (15:00 +0200)
committerGitHub <noreply@github.com>
Wed, 6 Aug 2025 13:00:32 +0000 (15:00 +0200)
Content.Server/Nutrition/Components/MessyDrinkerComponent.cs [new file with mode: 0644]
Content.Server/Nutrition/EntitySystems/DrinkSystem.cs
Content.Server/Nutrition/EntitySystems/MessyDrinkerSystem.cs [new file with mode: 0644]
Content.Server/Nutrition/Events/DrinkEvents.cs [new file with mode: 0644]
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Resources/Prototypes/Entities/Mobs/NPCs/pets.yml

diff --git a/Content.Server/Nutrition/Components/MessyDrinkerComponent.cs b/Content.Server/Nutrition/Components/MessyDrinkerComponent.cs
new file mode 100644 (file)
index 0000000..6a1a3a0
--- /dev/null
@@ -0,0 +1,22 @@
+using Content.Shared.FixedPoint;
+
+namespace Content.Server.Nutrition.Components;
+
+/// <summary>
+/// Entities with this component occasionally spill some of their drink when drinking.
+/// </summary>
+[RegisterComponent]
+public sealed partial class MessyDrinkerComponent : Component
+{
+    [DataField]
+    public float SpillChance = 0.2f;
+
+    /// <summary>
+    /// The amount of solution that is spilled when <see cref="SpillChance"/> procs.
+    /// </summary>
+    [DataField]
+    public FixedPoint2 SpillAmount = 1.0;
+
+    [DataField]
+    public LocId? SpillMessagePopup;
+}
index deb49ea66855cc9206d700df21b5a473e7da030b..6e1824c843c9da00959a9e0df081debdaf91536b 100644 (file)
@@ -2,6 +2,7 @@ using Content.Server.Body.Systems;
 using Content.Server.Fluids.EntitySystems;
 using Content.Server.Forensics;
 using Content.Server.Inventory;
+using Content.Server.Nutrition.Events;
 using Content.Server.Popups;
 using Content.Shared.Administration.Logs;
 using Content.Shared.Body.Components;
@@ -242,11 +243,18 @@ public sealed class DrinkSystem : SharedDrinkSystem
 
         _audio.PlayPvs(entity.Comp.UseSound, args.Target.Value, AudioParams.Default.WithVolume(-2f).WithVariation(0.25f));
 
-        _reaction.DoEntityReaction(args.Target.Value, solution, ReactionMethod.Ingestion);
-        _stomach.TryTransferSolution(firstStomach.Value.Owner, drained, firstStomach.Value.Comp1);
+        var beforeDrinkEvent = new BeforeIngestDrinkEvent(entity.Owner, drained, forceDrink);
+        RaiseLocalEvent(args.Target.Value, ref beforeDrinkEvent);
 
         _forensics.TransferDna(entity, args.Target.Value);
 
+        _reaction.DoEntityReaction(args.Target.Value, solution, ReactionMethod.Ingestion);
+
+        if (drained.Volume == 0)
+            return;
+
+        _stomach.TryTransferSolution(firstStomach.Value.Owner, drained, firstStomach.Value.Comp1);
+
         if (!forceDrink && solution.Volume > 0)
             args.Repeat = true;
     }
diff --git a/Content.Server/Nutrition/EntitySystems/MessyDrinkerSystem.cs b/Content.Server/Nutrition/EntitySystems/MessyDrinkerSystem.cs
new file mode 100644 (file)
index 0000000..f92318d
--- /dev/null
@@ -0,0 +1,41 @@
+using Content.Server.Fluids.EntitySystems;
+using Content.Server.Nutrition.Components;
+using Content.Server.Nutrition.Events;
+using Content.Shared.Popups;
+using Robust.Shared.Random;
+
+namespace Content.Server.Nutrition.EntitySystems;
+
+public sealed class MessyDrinkerSystem : EntitySystem
+{
+    [Dependency] private readonly PuddleSystem _puddle = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<MessyDrinkerComponent, BeforeIngestDrinkEvent>(OnBeforeIngestDrink);
+    }
+
+    private void OnBeforeIngestDrink(Entity<MessyDrinkerComponent> ent, ref BeforeIngestDrinkEvent ev)
+    {
+        if (ev.Solution.Volume <= ent.Comp.SpillAmount)
+            return;
+
+        // Cannot spill if you're being forced to drink.
+        if (ev.Forced)
+            return;
+
+        if (!_random.Prob(ent.Comp.SpillChance))
+            return;
+
+        if (ent.Comp.SpillMessagePopup != null)
+            _popup.PopupEntity(Loc.GetString(ent.Comp.SpillMessagePopup), ent, ent, PopupType.MediumCaution);
+
+        var split = ev.Solution.SplitSolution(ent.Comp.SpillAmount);
+
+        _puddle.TrySpillAt(ent, split, out _);
+    }
+}
diff --git a/Content.Server/Nutrition/Events/DrinkEvents.cs b/Content.Server/Nutrition/Events/DrinkEvents.cs
new file mode 100644 (file)
index 0000000..b7a7403
--- /dev/null
@@ -0,0 +1,12 @@
+using Content.Shared.Chemistry.Components;
+
+namespace Content.Server.Nutrition.Events;
+
+/// <summary>
+/// Raised on the entity drinking. This is right before they actually transfer the solution into the stomach.
+/// </summary>
+/// <param name="Drink">The drink that is being drank.</param>
+/// <param name="Solution">The solution that will be digested.</param>
+/// <param name="Forced">Whether the target was forced to drink the solution by somebody else.</param>
+[ByRefEvent]
+public record struct BeforeIngestDrinkEvent(EntityUid Drink, Solution Solution, bool Forced);
index 41a66d2ef08b9244ac6f5fcd13467ba9e3cb44b1..920468605f5a96e5f58860c75546e3cf6937cad6 100644 (file)
   - type: HTN
     rootTask:
       task: RuminantHostileCompound
+  - type: MessyDrinker
   - type: Tag
     tags:
     - VimPilot
       gender: epicene
   - type: MobPrice
     price: 200
+  - type: MessyDrinker
 
 - type: entity
   parent: MobCorgiBase
index 75aacadd352bc22f05308caec8ca776283796dc9..dcfd6b41fc967a624ca9a4d519f004046137ed01 100644 (file)
     - VimPilot
   - type: StealTarget
     stealGroup: AnimalMcGriff
+  - type: MessyDrinker
 
 - type: entity
   name: Paperwork
   - type: Speech
     speechVerb: Canine
     speechSounds: Dog
+  - type: MessyDrinker
 
 - type: entity
   name: Morty