]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
[NEW STATUS SYSTEM] Drunkenness, Stuttering, Slurred Speech, and Bloodloss (#38678)
authorPrincess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com>
Mon, 18 Aug 2025 20:26:29 +0000 (13:26 -0700)
committerGitHub <noreply@github.com>
Mon, 18 Aug 2025 20:26:29 +0000 (16:26 -0400)
* The only commit that matters

* I had to stop playing with my cat to push this change

* Yaml removal

* Proper drunk status effect and remove shitcode

* Review changes

* whoops

* Whoops x2

* Update master fix merge conflicts

* Fix merge conflicts

* Dunk Component kill

* MORE RELAYS

* Holy fucking breaking changes

* Ough

* 46 file diff

* Fix bad commits

* Erm what the test fail?

* Fix those last two

* Merge conflicts

* Me when I fix the merge conflicts

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
27 files changed:
Content.Client/Drunk/DrunkOverlay.cs
Content.Client/Drunk/DrunkSystem.cs
Content.Server/Electrocution/ElectrocutionSystem.cs
Content.Server/Speech/Components/StutteringAccentComponent.cs
Content.Server/Speech/EntitySystems/SlurredSystem.cs
Content.Server/Speech/EntitySystems/StutteringSystem.cs
Content.Shared/Body/Components/BloodstreamComponent.cs
Content.Shared/Body/Systems/SharedBloodstreamSystem.cs
Content.Shared/Drunk/DrunkComponent.cs [deleted file]
Content.Shared/Drunk/DrunkStatusEffectComponent.cs [new file with mode: 0644]
Content.Shared/Drunk/DrunkSystem.cs [deleted file]
Content.Shared/Drunk/SharedDrunkSystem.cs [new file with mode: 0644]
Content.Shared/EntityEffects/Effects/Drunk.cs
Content.Shared/Speech/EntitySystems/SharedSlurredSystem.cs
Content.Shared/Speech/EntitySystems/SharedStutteringSystem.cs
Content.Shared/StatusEffectNew/Components/StatusEffectComponent.cs
Content.Shared/StatusEffectNew/StatusEffectSystem.Relay.cs
Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml
Resources/Prototypes/Entities/Mobs/NPCs/elemental.yml
Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml
Resources/Prototypes/Entities/Mobs/Player/dragon.yml
Resources/Prototypes/Entities/Mobs/Species/base.yml
Resources/Prototypes/Entities/StatusEffects/body.yml [new file with mode: 0644]
Resources/Prototypes/Entities/StatusEffects/misc.yml
Resources/Prototypes/Entities/StatusEffects/speech.yml [new file with mode: 0644]
Resources/Prototypes/Reagents/medicine.yml

index 1f26e75ffc9209b89359b34a9dd136df695092e4..c806cdad660fc0a3e2b3305088fcba63624566a7 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Shared.Drunk;
 using Content.Shared.StatusEffect;
+using Content.Shared.StatusEffectNew;
 using Robust.Client.Graphics;
 using Robust.Client.Player;
 using Robust.Shared.Enums;
@@ -43,19 +44,21 @@ public sealed class DrunkOverlay : Overlay
         if (playerEntity == null)
             return;
 
-        if (!_entityManager.HasComponent<DrunkComponent>(playerEntity)
-            || !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
+        var statusSys = _sysMan.GetEntitySystem<Shared.StatusEffectNew.StatusEffectsSystem>();
+        if (!statusSys.TryGetMaxTime<DrunkStatusEffectComponent>(playerEntity.Value, out var status))
             return;
 
-        var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
-        if (!statusSys.TryGetTime(playerEntity.Value, SharedDrunkSystem.DrunkKey, out var time, status))
-            return;
+        var time = status.Item2;
 
-        var curTime = _timing.CurTime;
-        var timeLeft = (float) (time.Value.Item2 - curTime).TotalSeconds;
+        var power = SharedDrunkSystem.MagicNumber;
 
+        if (time != null)
+        {
+            var curTime = _timing.CurTime;
+            power = (float) (time - curTime).Value.TotalSeconds;
+        }
 
-        CurrentBoozePower += 8f * (0.5f*timeLeft - CurrentBoozePower) * args.DeltaSeconds / (timeLeft+1);
+        CurrentBoozePower += 8f * (power * 0.5f - CurrentBoozePower) * args.DeltaSeconds / (power+1);
     }
 
     protected override bool BeforeDraw(in OverlayDrawArgs args)
index d9c6bb192fdcaa500c3629b017d6c7d61a8d5674..c5fab75e7ddb6789c71cb0f55e147a481ab97725 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Shared.Drunk;
+using Content.Shared.StatusEffectNew;
 using Robust.Client.Graphics;
 using Robust.Client.Player;
 using Robust.Shared.Player;
@@ -16,38 +17,41 @@ public sealed class DrunkSystem : SharedDrunkSystem
     {
         base.Initialize();
 
-        SubscribeLocalEvent<DrunkComponent, ComponentInit>(OnDrunkInit);
-        SubscribeLocalEvent<DrunkComponent, ComponentShutdown>(OnDrunkShutdown);
+        SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusApplied);
+        SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRemovedEvent>(OnStatusRemoved);
 
-        SubscribeLocalEvent<DrunkComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
-        SubscribeLocalEvent<DrunkComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
+        SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerAttachedEvent>>(OnPlayerAttached);
+        SubscribeLocalEvent<DrunkStatusEffectComponent, StatusEffectRelayedEvent<LocalPlayerDetachedEvent>>(OnPlayerDetached);
 
         _overlay = new();
     }
 
-    private void OnPlayerAttached(EntityUid uid, DrunkComponent component, LocalPlayerAttachedEvent args)
+    private void OnStatusApplied(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectAppliedEvent args)
     {
-        _overlayMan.AddOverlay(_overlay);
+        if (!_overlayMan.HasOverlay<DrunkOverlay>())
+            _overlayMan.AddOverlay(_overlay);
     }
 
-    private void OnPlayerDetached(EntityUid uid, DrunkComponent component, LocalPlayerDetachedEvent args)
+    private void OnStatusRemoved(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRemovedEvent args)
     {
+        if (Status.HasEffectComp<DrunkStatusEffectComponent>(args.Target))
+            return;
+
+        if (_player.LocalEntity != args.Target)
+            return;
+
         _overlay.CurrentBoozePower = 0;
         _overlayMan.RemoveOverlay(_overlay);
     }
 
-    private void OnDrunkInit(EntityUid uid, DrunkComponent component, ComponentInit args)
+    private void OnPlayerAttached(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRelayedEvent<LocalPlayerAttachedEvent> args)
     {
-        if (_player.LocalEntity == uid)
-            _overlayMan.AddOverlay(_overlay);
+        _overlayMan.AddOverlay(_overlay);
     }
 
-    private void OnDrunkShutdown(EntityUid uid, DrunkComponent component, ComponentShutdown args)
+    private void OnPlayerDetached(Entity<DrunkStatusEffectComponent> entity, ref StatusEffectRelayedEvent<LocalPlayerDetachedEvent> args)
     {
-        if (_player.LocalEntity == uid)
-        {
-            _overlay.CurrentBoozePower = 0;
-            _overlayMan.RemoveOverlay(_overlay);
-        }
+        _overlay.CurrentBoozePower = 0;
+        _overlayMan.RemoveOverlay(_overlay);
     }
 }
index 1f04421c0f29c384bad17f0bf0c068f45898d90c..a162b29e19678bd5776c6b8f2003c91e9fc215bc 100644 (file)
@@ -418,7 +418,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
             }
         }
 
-        _stuttering.DoStutter(uid, time * StutteringTimeMultiplier, refresh, statusEffects);
+        _stuttering.DoStutter(uid, time * StutteringTimeMultiplier, refresh);
         _jittering.DoJitter(uid, time * JitterTimeMultiplier, refresh, JitterAmplitude, JitterFrequency, true, statusEffects);
 
         _popup.PopupEntity(Loc.GetString("electrocuted-component-mob-shocked-popup-player"), uid, uid);
index e82cd9b12b0f24ee85464cb6bcfb2252c7469b5e..dd65ef66e0d4761f71481008c8f351fa869ae067 100644 (file)
@@ -6,29 +6,25 @@ namespace Content.Server.Speech.Components
         /// <summary>
         /// Percentage chance that a stutter will occur if it matches.
         /// </summary>
-        [DataField("matchRandomProb")]
-        [ViewVariables(VVAccess.ReadWrite)]
+        [DataField]
         public float MatchRandomProb = 0.8f;
 
         /// <summary>
         /// Percentage chance that a stutter occurs f-f-f-f-four times.
         /// </summary>
-        [DataField("fourRandomProb")]
-        [ViewVariables(VVAccess.ReadWrite)]
+        [DataField]
         public float FourRandomProb = 0.1f;
 
         /// <summary>
         /// Percentage chance that a stutter occurs t-t-t-three times.
         /// </summary>
-        [DataField("threeRandomProb")]
-        [ViewVariables(VVAccess.ReadWrite)]
+        [DataField]
         public float ThreeRandomProb = 0.2f;
 
         /// <summary>
         /// Percentage chance that a stutter cut off.
         /// </summary>
-        [DataField("cutRandomProb")]
-        [ViewVariables(VVAccess.ReadWrite)]
+        [DataField]
         public float CutRandomProb = 0.05f;
     }
 }
index 5ac1ba037f21238ab16eb3f9862803c1be693a6d..8690079de1d0047527553ff32c0110b005e314aa 100644 (file)
@@ -3,8 +3,7 @@ using Content.Server.Speech.Components;
 using Content.Shared.Drunk;
 using Content.Shared.Speech;
 using Content.Shared.Speech.EntitySystems;
-using Content.Shared.StatusEffect;
-using Robust.Shared.Prototypes;
+using Content.Shared.StatusEffectNew;
 using Robust.Shared.Random;
 using Robust.Shared.Timing;
 
@@ -12,26 +11,15 @@ namespace Content.Server.Speech.EntitySystems;
 
 public sealed class SlurredSystem : SharedSlurredSystem
 {
-    [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
+    [Dependency] private readonly StatusEffectsSystem _status = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly IGameTiming _timing = default!;
 
-    private static readonly ProtoId<StatusEffectPrototype> SlurKey = "SlurredSpeech";
-
     public override void Initialize()
     {
         SubscribeLocalEvent<SlurredAccentComponent, AccentGetEvent>(OnAccent);
-    }
-
-    public override void DoSlur(EntityUid uid, TimeSpan time, StatusEffectsComponent? status = null)
-    {
-        if (!Resolve(uid, ref status, false))
-            return;
 
-        if (!_statusEffectsSystem.HasStatusEffect(uid, SlurKey, status))
-            _statusEffectsSystem.TryAddStatusEffect<SlurredAccentComponent>(uid, SlurKey, time, true, status);
-        else
-            _statusEffectsSystem.TryAddTime(uid, SlurKey, time, status);
+        SubscribeLocalEvent<SlurredAccentComponent, StatusEffectRelayedEvent<AccentGetEvent>>(OnAccentRelayed);
     }
 
     /// <summary>
@@ -39,15 +27,33 @@ public sealed class SlurredSystem : SharedSlurredSystem
     /// </summary>
     private float GetProbabilityScale(EntityUid uid)
     {
-        if (!_statusEffectsSystem.TryGetTime(uid, SharedDrunkSystem.DrunkKey, out var time))
+        if (!_status.TryGetMaxTime<DrunkStatusEffectComponent>(uid, out var time))
             return 0;
 
-        var curTime = _timing.CurTime;
-        var timeLeft = (float) (time.Value.Item2 - curTime).TotalSeconds;
-        return Math.Clamp((timeLeft - 80) / 1100, 0f, 1f);
+        // This is a magic number. Why this value? No clue it was made 3 years before I refactored this.
+        var magic = SharedDrunkSystem.MagicNumber;
+
+        if (time.Item2 != null)
+        {
+            var curTime = _timing.CurTime;
+            magic = (float) (time.Item2 - curTime).Value.TotalSeconds - 80f;
+        }
+
+        return Math.Clamp(magic / SharedDrunkSystem.MagicNumber, 0f, 1f);
+    }
+
+    private void OnAccent(Entity<SlurredAccentComponent> entity, ref AccentGetEvent args)
+    {
+        GetAccent(entity, ref args);
+    }
+
+    private void OnAccentRelayed(Entity<SlurredAccentComponent> entity, ref StatusEffectRelayedEvent<AccentGetEvent> args)
+    {
+        var ev = args.Args;
+        GetAccent(args.Args.Entity, ref ev);
     }
 
-    private void OnAccent(EntityUid uid, SlurredAccentComponent component, AccentGetEvent args)
+    private void GetAccent(EntityUid uid, ref AccentGetEvent args)
     {
         var scale = GetProbabilityScale(uid);
         args.Message = Accentuate(args.Message, scale);
index f47bff3523f4f4b46ccf6106484c71dc841563f0..2c78eb181ec7d1687993e244b154b3a46b9ee024 100644 (file)
@@ -3,14 +3,13 @@ using System.Text.RegularExpressions;
 using Content.Server.Speech.Components;
 using Content.Shared.Speech;
 using Content.Shared.Speech.EntitySystems;
-using Content.Shared.StatusEffect;
+using Content.Shared.StatusEffectNew;
 using Robust.Shared.Random;
 
 namespace Content.Server.Speech.EntitySystems
 {
     public sealed class StutteringSystem : SharedStutteringSystem
     {
-        [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
 
         // Regex of characters to stutter.
@@ -20,19 +19,36 @@ namespace Content.Server.Speech.EntitySystems
         public override void Initialize()
         {
             SubscribeLocalEvent<StutteringAccentComponent, AccentGetEvent>(OnAccent);
+
+            SubscribeLocalEvent<StutteringAccentComponent, StatusEffectRelayedEvent<AccentGetEvent>>(OnAccent);
         }
 
-        public override void DoStutter(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null)
+        public override void DoStutter(EntityUid uid, TimeSpan time, bool refresh)
         {
-            if (!Resolve(uid, ref status, false))
-                return;
+            if (refresh)
+                Status.TryUpdateStatusEffectDuration(uid, Stuttering, time);
+            else
+                Status.TryAddStatusEffectDuration(uid, Stuttering, time);
+        }
+
+        public override void DoRemoveStutterTime(EntityUid uid, TimeSpan timeRemoved)
+        {
+            Status.TryAddTime(uid, Stuttering, -timeRemoved);
+        }
 
-            _statusEffectsSystem.TryAddStatusEffect<StutteringAccentComponent>(uid, StutterKey, time, refresh, status);
+        public override void DoRemoveStutter(EntityUid uid)
+        {
+            Status.TryRemoveStatusEffect(uid, Stuttering);
+        }
+
+        private void OnAccent(Entity<StutteringAccentComponent> entity, ref AccentGetEvent args)
+        {
+            args.Message = Accentuate(args.Message, entity.Comp);
         }
 
-        private void OnAccent(EntityUid uid, StutteringAccentComponent component, AccentGetEvent args)
+        private void OnAccent(Entity<StutteringAccentComponent> entity, ref StatusEffectRelayedEvent<AccentGetEvent> args)
         {
-            args.Message = Accentuate(args.Message, component);
+            args.Args.Message = Accentuate(args.Args.Message, entity.Comp);
         }
 
         public string Accentuate(string message, StutteringAccentComponent component)
index 013993226214573137280d4b8932424a01738701..51814eaba9d52446bc1287437d0d3fed392d4259 100644 (file)
@@ -198,12 +198,6 @@ public sealed partial class BloodstreamComponent : Component
     [ViewVariables]
     public Entity<SolutionComponent>? TemporarySolution;
 
-    /// <summary>
-    /// Variable that stores the amount of status time added by having a low blood level.
-    /// </summary>
-    [DataField, AutoNetworkedField]
-    public TimeSpan StatusTime;
-
     /// <summary>
     /// Alert to show when bleeding.
     /// </summary>
index ac385040a9415f9e37fea6a2c30ecb25c1c5c063..182cdb47d36b90957ef38bf01a6832b01c3286a5 100644 (file)
@@ -6,7 +6,6 @@ using Content.Shared.Chemistry.EntitySystems;
 using Content.Shared.Chemistry.Reaction;
 using Content.Shared.Chemistry.Reagent;
 using Content.Shared.Damage;
-using Content.Shared.Drunk;
 using Content.Shared.EntityEffects.Effects;
 using Content.Shared.FixedPoint;
 using Content.Shared.Fluids;
@@ -16,7 +15,7 @@ using Content.Shared.Mobs.Systems;
 using Content.Shared.Popups;
 using Content.Shared.Random.Helpers;
 using Content.Shared.Rejuvenate;
-using Content.Shared.Speech.EntitySystems;
+using Content.Shared.StatusEffectNew;
 using Robust.Shared.Audio.Systems;
 using Robust.Shared.Containers;
 using Robust.Shared.Prototypes;
@@ -27,17 +26,18 @@ namespace Content.Shared.Body.Systems;
 
 public abstract class SharedBloodstreamSystem : EntitySystem
 {
+    public static readonly EntProtoId Bloodloss = "StatusEffectBloodloss";
+
     [Dependency] protected readonly SharedSolutionContainerSystem SolutionContainer = default!;
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly SharedPopupSystem _popup = default!;
     [Dependency] private readonly SharedPuddleSystem _puddle = default!;
+    [Dependency] private readonly StatusEffectsSystem _status = default!;
     [Dependency] private readonly AlertsSystem _alertsSystem = default!;
     [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
     [Dependency] private readonly DamageableSystem _damageableSystem = default!;
-    [Dependency] private readonly SharedDrunkSystem _drunkSystem = default!;
-    [Dependency] private readonly SharedStutteringSystem _stutteringSystem = default!;
 
     public override void Initialize()
     {
@@ -100,15 +100,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
                 // Apply dizziness as a symptom of bloodloss.
                 // The effect is applied in a way that it will never be cleared without being healthy.
                 // Multiplying by 2 is arbitrary but works for this case, it just prevents the time from running out
-                _drunkSystem.TryApplyDrunkenness(
-                    uid,
-                    (float)bloodstream.AdjustedUpdateInterval.TotalSeconds * 2,
-                    applySlur: false);
-                _stutteringSystem.DoStutter(uid, bloodstream.AdjustedUpdateInterval * 2, refresh: false);
-
-                // storing the drunk and stutter time so we can remove it independently from other effects additions
-                bloodstream.StatusTime += bloodstream.AdjustedUpdateInterval * 2;
-                DirtyField(uid, bloodstream, nameof(BloodstreamComponent.StatusTime));
+                _status.TrySetStatusEffectDuration(uid, Bloodloss);
             }
             else if (!_mobStateSystem.IsDead(uid))
             {
@@ -118,12 +110,7 @@ public abstract class SharedBloodstreamSystem : EntitySystem
                     bloodstream.BloodlossHealDamage * bloodPercentage,
                     ignoreResistances: true, interruptsDoAfters: false);
 
-                // Remove the drunk effect when healthy. Should only remove the amount of drunk and stutter added by low blood level
-                _drunkSystem.TryRemoveDrunkenessTime(uid, bloodstream.StatusTime.TotalSeconds);
-                _stutteringSystem.DoRemoveStutterTime(uid, bloodstream.StatusTime.TotalSeconds);
-                // Reset the drunk and stutter time to zero
-                bloodstream.StatusTime = TimeSpan.Zero;
-                DirtyField(uid, bloodstream, nameof(BloodstreamComponent.StatusTime));
+                _status.TryRemoveStatusEffect(uid, Bloodloss);
             }
         }
     }
diff --git a/Content.Shared/Drunk/DrunkComponent.cs b/Content.Shared/Drunk/DrunkComponent.cs
deleted file mode 100644 (file)
index 61c195d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-using Robust.Shared.GameStates;
-
-namespace Content.Shared.Drunk;
-
-[RegisterComponent, NetworkedComponent]
-public sealed partial class DrunkComponent : Component { }
diff --git a/Content.Shared/Drunk/DrunkStatusEffectComponent.cs b/Content.Shared/Drunk/DrunkStatusEffectComponent.cs
new file mode 100644 (file)
index 0000000..69ad7c3
--- /dev/null
@@ -0,0 +1,11 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Drunk;
+
+/// <summary>
+/// This is used by a status effect entity to apply the <see cref="DrunkComponent"/> to an entity.
+/// </summary>
+[RegisterComponent, NetworkedComponent]
+public sealed partial class DrunkStatusEffectComponent : Component
+{
+}
diff --git a/Content.Shared/Drunk/DrunkSystem.cs b/Content.Shared/Drunk/DrunkSystem.cs
deleted file mode 100644 (file)
index 236ce2d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-using Content.Shared.Speech.EntitySystems;
-using Content.Shared.StatusEffect;
-using Content.Shared.Traits.Assorted;
-using Robust.Shared.Prototypes;
-
-namespace Content.Shared.Drunk;
-
-public abstract class SharedDrunkSystem : EntitySystem
-{
-    public static readonly ProtoId<StatusEffectPrototype> DrunkKey = "Drunk";
-
-    [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
-    [Dependency] private readonly SharedSlurredSystem _slurredSystem = default!;
-
-    public void TryApplyDrunkenness(EntityUid uid, float boozePower, bool applySlur = true,
-        StatusEffectsComponent? status = null)
-    {
-        if (!Resolve(uid, ref status, false))
-            return;
-
-        if (TryComp<LightweightDrunkComponent>(uid, out var trait))
-            boozePower *= trait.BoozeStrengthMultiplier;
-
-        if (applySlur)
-        {
-            _slurredSystem.DoSlur(uid, TimeSpan.FromSeconds(boozePower), status);
-        }
-
-        if (!_statusEffectsSystem.HasStatusEffect(uid, DrunkKey, status))
-        {
-            _statusEffectsSystem.TryAddStatusEffect<DrunkComponent>(uid, DrunkKey, TimeSpan.FromSeconds(boozePower), true, status);
-        }
-        else
-        {
-            _statusEffectsSystem.TryAddTime(uid, DrunkKey, TimeSpan.FromSeconds(boozePower), status);
-        }
-    }
-
-    public void TryRemoveDrunkenness(EntityUid uid)
-    {
-        _statusEffectsSystem.TryRemoveStatusEffect(uid, DrunkKey);
-    }
-    public void TryRemoveDrunkenessTime(EntityUid uid, double timeRemoved)
-    {
-        _statusEffectsSystem.TryRemoveTime(uid, DrunkKey, TimeSpan.FromSeconds(timeRemoved));
-    }
-
-}
diff --git a/Content.Shared/Drunk/SharedDrunkSystem.cs b/Content.Shared/Drunk/SharedDrunkSystem.cs
new file mode 100644 (file)
index 0000000..96aff82
--- /dev/null
@@ -0,0 +1,50 @@
+using Content.Shared.Speech.EntitySystems;
+using Content.Shared.StatusEffectNew;
+using Content.Shared.Traits.Assorted;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Drunk;
+
+public abstract class SharedDrunkSystem : EntitySystem
+{
+    public static EntProtoId Drunk = "StatusEffectDrunk";
+    public static EntProtoId Woozy = "StatusEffectWoozy";
+
+    /* I have no clue why this magic number was chosen, I copied it from slur system and needed it for the overlay
+    If you have a more intelligent magic number be my guest to completely explode this value.
+    There were no comments as to why this value was chosen three years ago. */
+    public static float MagicNumber = 1100f;
+
+    [Dependency] protected readonly StatusEffectsSystem Status = default!;
+
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<LightweightDrunkComponent, DrunkEvent>(OnLightweightDrinking);
+    }
+
+    public void TryApplyDrunkenness(EntityUid uid, TimeSpan boozePower)
+    {
+        var ev = new DrunkEvent(boozePower);
+        RaiseLocalEvent(uid, ref ev);
+
+        Status.TryAddStatusEffectDuration(uid, Drunk, ev.Duration);
+    }
+
+    public void TryRemoveDrunkenness(EntityUid uid)
+    {
+        Status.TryRemoveStatusEffect(uid, Drunk);
+    }
+
+    public void TryRemoveDrunkennessTime(EntityUid uid, TimeSpan boozePower)
+    {
+        Status.TryAddTime(uid, Drunk, - boozePower);
+    }
+
+    private void OnLightweightDrinking(Entity<LightweightDrunkComponent> entity, ref DrunkEvent args)
+    {
+        args.Duration *= entity.Comp.BoozeStrengthMultiplier;
+    }
+
+    [ByRefEvent]
+    public record struct DrunkEvent(TimeSpan Duration);
+}
index 5f7f29c342be5690b0eec0b2c9d8efbcbc2eb97e..aa15df8f3d8f95fd3bf937191d1a6b5caeab7790 100644 (file)
@@ -9,13 +9,7 @@ public sealed partial class Drunk : EntityEffect
     ///     BoozePower is how long each metabolism cycle will make the drunk effect last for.
     /// </summary>
     [DataField]
-    public float BoozePower = 3f;
-
-    /// <summary>
-    ///     Whether speech should be slurred.
-    /// </summary>
-    [DataField]
-    public bool SlurSpeech = true;
+    public TimeSpan BoozePower = TimeSpan.FromSeconds(3f);
 
     protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
         => Loc.GetString("reagent-effect-guidebook-drunk", ("chance", Probability));
@@ -24,11 +18,10 @@ public sealed partial class Drunk : EntityEffect
     {
         var boozePower = BoozePower;
 
-        if (args is EntityEffectReagentArgs reagentArgs) {
+        if (args is EntityEffectReagentArgs reagentArgs)
             boozePower *= reagentArgs.Scale.Float();
-        }
 
         var drunkSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedDrunkSystem>();
-        drunkSys.TryApplyDrunkenness(args.TargetEntity, boozePower, SlurSpeech);
+        drunkSys.TryApplyDrunkenness(args.TargetEntity, boozePower);
     }
 }
index 8718e054ba299edfb19266dfae92ee5d96ffd953..aadda6aa098939d8da28c023b2da690691b4dd2e 100644 (file)
@@ -1,8 +1,11 @@
 using Content.Shared.StatusEffect;
+using Robust.Shared.Prototypes;
 
 namespace Content.Shared.Speech.EntitySystems;
 
 public abstract class SharedSlurredSystem : EntitySystem
 {
+    public static readonly EntProtoId Stutter = "StatusEffectSlurred";
+
     public virtual void DoSlur(EntityUid uid, TimeSpan time, StatusEffectsComponent? status = null) { }
 }
index 05358a04bbc1f85878fbbb8042fb919f9de00c56..90cd8bc4de9cc86c0bc3a7f93d8c6fa0107aab39 100644 (file)
@@ -1,26 +1,24 @@
-using Content.Shared.StatusEffect;
+using Content.Shared.StatusEffectNew;
 using Robust.Shared.Prototypes;
 
 namespace Content.Shared.Speech.EntitySystems;
 
 public abstract class SharedStutteringSystem : EntitySystem
 {
-    public static readonly ProtoId<StatusEffectPrototype> StutterKey = "Stutter";
+    public static readonly EntProtoId Stuttering = "StatusEffectStutter";
 
-    [Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
+    [Dependency] protected readonly StatusEffectsSystem Status = default!;
 
     // For code in shared... I imagine we ain't getting accent prediction anytime soon so let's not bother.
-    public virtual void DoStutter(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null)
+    public virtual void DoStutter(EntityUid uid, TimeSpan time, bool refresh)
     {
     }
 
-    public virtual void DoRemoveStutterTime(EntityUid uid, double timeRemoved)
+    public virtual void DoRemoveStutterTime(EntityUid uid, TimeSpan timeRemoved)
     {
-        _statusEffectsSystem.TryRemoveTime(uid, StutterKey, TimeSpan.FromSeconds(timeRemoved));
     }
 
-    public void DoRemoveStutter(EntityUid uid, double timeRemoved)
+    public virtual void DoRemoveStutter(EntityUid uid)
     {
-       _statusEffectsSystem.TryRemoveStatusEffect(uid, StutterKey);
     }
 }
index 25f40718e9753af0b8b9437a453bd523b09d50db..67ff8b3e616961263ad7beb0138343f249f44996 100644 (file)
@@ -1,4 +1,3 @@
-using Content.Shared.Alert;
 using Content.Shared.Whitelist;
 using Robust.Shared.GameStates;
 using Robust.Shared.Prototypes;
index 0c4c5cf1f7f23effca56973556dc181db5b6eeb5..3644bed45e527314d9fab06213f8f29983dd4b63 100644 (file)
@@ -1,6 +1,7 @@
 using Content.Shared.Movement.Events;
 using Content.Shared.Movement.Systems;
 using Content.Shared.Rejuvenate;
+using Content.Shared.Speech;
 using Content.Shared.StatusEffectNew.Components;
 using Content.Shared.Stunnable;
 using Robust.Shared.Player;
@@ -23,6 +24,8 @@ public sealed partial class StatusEffectsSystem
 
         SubscribeLocalEvent<StatusEffectContainerComponent, StandUpAttemptEvent>(RefRelayStatusEffectEvent);
         SubscribeLocalEvent<StatusEffectContainerComponent, StunEndAttemptEvent>(RefRelayStatusEffectEvent);
+
+        SubscribeLocalEvent<StatusEffectContainerComponent, AccentGetEvent>(RelayStatusEffectEvent);
     }
 
     private void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
index d2dd76146871dffe4cc59c4b9eee3d68a5b6a6ff..909e11e21f2404a79df8a7d3ee65df68ab007175 100644 (file)
@@ -19,7 +19,6 @@
     group: GenericNumber
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
     - TemporaryBlindness
     - RadiationProtection
index ba4c5e3698c8009320d6d4280beb4bdb7243115f..eba25717f33d0a553195e0fd7dfe58a6b8ff371f 100644 (file)
@@ -35,7 +35,6 @@
     bodyType: KinematicController # Same for all inheritors
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
   - type: Pullable
   - type: Tag
index 279dbe9f5430498b3fe672fd2cf7c26a1d447917..fd700d7a4c9d80314c5f7e7a1ae0446d6ee887d6 100644 (file)
@@ -15,7 +15,6 @@
     bodyType: KinematicController # Same for all inheritors
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
   - type: Repairable
     doAfterDelay: 8
index 11c0f0d21d5d0a24ecd11ae0a72e7e9fe608f108..4090138b5718b9f0c585344ddd73d21b240e79b6 100644 (file)
@@ -19,7 +19,6 @@
     baseSprintSpeed : 4
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
     - TemporaryBlindness
     - Pacified
@@ -93,7 +92,6 @@
     baseDecayRate: 0.04
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
     - TemporaryBlindness
     - Pacified
index b6b344d6b5508ace6ed29c62f685aeca5f32f188..441751a80b23becd612f86bfd578691e86c6d9ba 100644 (file)
       types: {}
   - type: StatusEffects # Overwriting basesimplemob to remove flash, getting flashed as dragon just feelsbad
     allowed:
-    - Stutter
     - Electrocution
     - TemporaryBlindness
     - Pacified
index 10c39ed7a082ca35f235176e9a688bcbd942d517..3bb43c26cb40b7a7c0aa312f27e04ee1e9cec98f 100644 (file)
       - !type:WashCreamPieReaction
   - type: StatusEffects
     allowed:
-    - Stutter
     - Electrocution
-    - Drunk
-    - SlurredSpeech
     - RatvarianLanguage
     - PressureImmunity
     - Muted
diff --git a/Resources/Prototypes/Entities/StatusEffects/body.yml b/Resources/Prototypes/Entities/StatusEffects/body.yml
new file mode 100644 (file)
index 0000000..3765ebe
--- /dev/null
@@ -0,0 +1,18 @@
+- type: entity
+  parent: MobStatusEffectBase
+  id: BloodstreamStatusEffectBase
+  abstract: true
+  components:
+    - type: StatusEffect
+      whitelist:
+        components:
+          - Bloodstream
+
+- type: entity
+  parent: [ BloodstreamStatusEffectBase ]
+  id: StatusEffectBloodloss
+  name: bloodloss
+  components:
+    - type: StutteringAccent
+    - type: DrunkStatusEffect
+    - type: RejuvenateRemovedStatusEffect
index 3ce81081c0ebd32c48e30f537cfdd48772c07100..14c6b5b649d17a6296f75c3eaf57e959e2b37d1e 100644 (file)
   name: hallucinations
   components:
   - type: SeeingRainbowsStatusEffect
+
+# Causes your vision to become blurry and gives me a headache.
+- type: entity
+  parent: MobStatusEffectDebuff
+  id: StatusEffectWoozy
+  name: woozy
+  components:
+  - type: DrunkStatusEffect
+
+# Causes you to get drunk
+- type: entity
+  parent: [ StatusEffectWoozy, StatusEffectSlurred ]
+  id: StatusEffectDrunk
+  name: drunk
diff --git a/Resources/Prototypes/Entities/StatusEffects/speech.yml b/Resources/Prototypes/Entities/StatusEffects/speech.yml
new file mode 100644 (file)
index 0000000..17e533b
--- /dev/null
@@ -0,0 +1,27 @@
+- type: entity
+  parent: MobStatusEffectDebuff
+  id: SpeechStatusEffectBase
+  abstract: true
+  components:
+  - type: StatusEffect
+    whitelist:
+      components:
+      - MobState
+      - Speech
+      requireAll: true
+
+# Causes you to st-t-u-t-t-t-er randomly when talking.
+- type: entity
+  parent: SpeechStatusEffectBase
+  id: StatusEffectStutter
+  name: stutter
+  components:
+  - type: StutteringAccent
+
+# Causes you to schlur your words schwhen talking.
+- type: entity
+  parent: SpeechStatusEffectBase
+  id: StatusEffectSlurred
+  name: slurred
+  components:
+  - type: SlurredAccent
index 6ac69c84ebfdb0424e75d1ea74f5c4454e3d5c7d..f0a11706b0bafcc745a82a857e3401c7a384ed3b 100644 (file)
@@ -12,9 +12,9 @@
       - !type:GenericStatusEffect
         key: Stutter
         component: ScrambledAccent
-      - !type:Drunk
-        slurSpeech: false
-        boozePower: 20
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectSlurred
+        time: 20.0
 
 - type: reagent
   id: Dylovene
   metabolisms:
     Medicine:
       effects:
-      - !type:GenericStatusEffect
-        key: Drunk
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectDrunk
         time: 6.0
         type: Remove
       - !type:HealthChange
         key: Jitter
         time: 2.0
         type: Remove
-      - !type:GenericStatusEffect
-        key: Drunk
+      - !type:ModifyStatusEffect
+        effectProto: StatusEffectDrunk
         time: 6.0
         type: Remove
       - !type:PopupMessage # we dont have sanity/mood so this will have to do