From f1c859a9ee5832f55a3f164b26ac6c77eeff631d Mon Sep 17 00:00:00 2001 From: Milon Date: Wed, 20 Nov 2024 01:59:17 +0100 Subject: [PATCH] pain system + addictions + traits (#2192) * the nightmare continues unchecked * HOLY FUCKING SHITCODE * Update traits.ftl * makes the yaml linter happy * we'll regret this later * what why --- Content.Client/DeltaV/Overlays/PainOverlay.cs | 52 +++++++ Content.Client/DeltaV/Overlays/PainSystem.cs | 65 +++++++++ .../DeltaV/Addictions/AddictionSystem.cs | 13 ++ .../DeltaV/EntityEffects/Effects/Addicted.cs | 9 +- .../DeltaV/EntityEffects/Effects/InPain.cs | 30 ++++ .../Effects/SuppressAddiction.cs | 31 ++++ .../EntityEffects/Effects/SuppressPain.cs | 38 +++++ Content.Server/DeltaV/Pain/PainSystem.cs | 90 ++++++++++++ .../Addictions/SharedAddictionSystem.cs | 13 ++ Content.Shared/DeltaV/Pain/PainComponent.cs | 69 +++++++++ .../DeltaV/Pain/SharedPainSystem.cs | 44 ++++++ .../Locale/en-US/_CD/reagents/RPmeds.ftl | 43 ++++-- .../deltav/guidebook/chemistry/effects.ftl | 14 +- .../Locale/en-US/deltav/traits/traits.ftl | 6 + Resources/Prototypes/DeltaV/Datasets/pain.yml | 5 + .../DeltaV/Shaders/chromatic_aberration.yml | 4 + .../Prototypes/DeltaV/Traits/disabilities.yml | 16 ++ .../Prototypes/DeltaV/status_effects.yml | 9 ++ .../Prototypes/Entities/Mobs/Species/base.yml | 3 + Resources/Prototypes/Reagents/narcotics.yml | 34 ++--- .../Prototypes/_CD/Reagents/medicine.yml | 138 ++---------------- .../DeltaV/Shaders/chromatic_aberration.swsl | 32 ++++ 22 files changed, 592 insertions(+), 166 deletions(-) create mode 100644 Content.Client/DeltaV/Overlays/PainOverlay.cs create mode 100644 Content.Client/DeltaV/Overlays/PainSystem.cs create mode 100644 Content.Server/DeltaV/EntityEffects/Effects/InPain.cs create mode 100644 Content.Server/DeltaV/EntityEffects/Effects/SuppressAddiction.cs create mode 100644 Content.Server/DeltaV/EntityEffects/Effects/SuppressPain.cs create mode 100644 Content.Server/DeltaV/Pain/PainSystem.cs create mode 100644 Content.Shared/DeltaV/Pain/PainComponent.cs create mode 100644 Content.Shared/DeltaV/Pain/SharedPainSystem.cs create mode 100644 Resources/Prototypes/DeltaV/Datasets/pain.yml create mode 100644 Resources/Prototypes/DeltaV/Shaders/chromatic_aberration.yml create mode 100644 Resources/Textures/DeltaV/Shaders/chromatic_aberration.swsl diff --git a/Content.Client/DeltaV/Overlays/PainOverlay.cs b/Content.Client/DeltaV/Overlays/PainOverlay.cs new file mode 100644 index 00000000000..58b227ce777 --- /dev/null +++ b/Content.Client/DeltaV/Overlays/PainOverlay.cs @@ -0,0 +1,52 @@ +using System.Numerics; +using Content.Shared.DeltaV.Pain; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Enums; +using Robust.Shared.Prototypes; + +namespace Content.Client.DeltaV.Overlays; + +public sealed partial class PainOverlay : Overlay +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IEntityManager _entity = default!; + + public override bool RequestScreenTexture => true; + public override OverlaySpace Space => OverlaySpace.WorldSpace; + private readonly ShaderInstance _painShader; + private readonly ProtoId _shaderProto = "ChromaticAberration"; + + public PainOverlay() + { + IoCManager.InjectDependencies(this); + _painShader = _prototype.Index(_shaderProto).Instance().Duplicate(); + } + + protected override bool BeforeDraw(in OverlayDrawArgs args) + { + if (_player.LocalEntity is not { Valid: true } player + || !_entity.HasComponent(player)) + { + return false; + } + + return base.BeforeDraw(in args); + } + + protected override void Draw(in OverlayDrawArgs args) + { + if (ScreenTexture is null) + return; + + _painShader.SetParameter("SCREEN_TEXTURE", ScreenTexture); + + var worldHandle = args.WorldHandle; + var viewport = args.WorldBounds; + worldHandle.SetTransform(Matrix3x2.Identity); + worldHandle.UseShader(_painShader); + worldHandle.DrawRect(viewport, Color.White); + worldHandle.UseShader(null); + } +} diff --git a/Content.Client/DeltaV/Overlays/PainSystem.cs b/Content.Client/DeltaV/Overlays/PainSystem.cs new file mode 100644 index 00000000000..9ad436027a2 --- /dev/null +++ b/Content.Client/DeltaV/Overlays/PainSystem.cs @@ -0,0 +1,65 @@ +using Content.Shared.DeltaV.Pain; +using Robust.Client.Graphics; +using Robust.Shared.Player; + +namespace Content.Client.DeltaV.Overlays; + +public sealed partial class PainSystem : EntitySystem +{ + [Dependency] private readonly IOverlayManager _overlayMan = default!; + [Dependency] private readonly ISharedPlayerManager _playerMan = default!; + + private PainOverlay _overlay = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnPainInit); + SubscribeLocalEvent(OnPainShutdown); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + + _overlay = new(); + } + + private void OnPainInit(Entity ent, ref ComponentInit args) + { + if (ent.Owner == _playerMan.LocalEntity && !ent.Comp.Suppressed) + _overlayMan.AddOverlay(_overlay); + } + + private void OnPainShutdown(Entity ent, ref ComponentShutdown args) + { + if (ent.Owner == _playerMan.LocalEntity) + _overlayMan.RemoveOverlay(_overlay); + } + + private void OnPlayerAttached(Entity ent, ref LocalPlayerAttachedEvent args) + { + if (!ent.Comp.Suppressed) + _overlayMan.AddOverlay(_overlay); + } + + private void OnPlayerDetached(Entity ent, ref LocalPlayerDetachedEvent args) + { + _overlayMan.RemoveOverlay(_overlay); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + // Handle showing/hiding overlay based on suppression status + if (_playerMan.LocalEntity is not { } player) + return; + + if (!TryComp(player, out var comp)) + return; + + if (comp.Suppressed && _overlayMan.HasOverlay()) + _overlayMan.RemoveOverlay(_overlay); + else if (!comp.Suppressed && !_overlayMan.HasOverlay()) + _overlayMan.AddOverlay(_overlay); + } +} diff --git a/Content.Server/DeltaV/Addictions/AddictionSystem.cs b/Content.Server/DeltaV/Addictions/AddictionSystem.cs index 1df7eeecbee..791e8a466b1 100644 --- a/Content.Server/DeltaV/Addictions/AddictionSystem.cs +++ b/Content.Server/DeltaV/Addictions/AddictionSystem.cs @@ -30,6 +30,19 @@ public override void Initialize() SubscribeLocalEvent(OnInit); } + protected override void UpdateAddictionSuppression(Entity ent, float duration) + { + var curTime = _timing.CurTime; + var newEndTime = curTime + TimeSpan.FromSeconds(duration); + + // Only update if this would extend the suppression + if (newEndTime <= ent.Comp.SuppressionEndTime) + return; + + ent.Comp.SuppressionEndTime = newEndTime; + UpdateSuppressed(ent.Comp); + } + public override void Update(float frameTime) { base.Update(frameTime); diff --git a/Content.Server/DeltaV/EntityEffects/Effects/Addicted.cs b/Content.Server/DeltaV/EntityEffects/Effects/Addicted.cs index 591e51a3d62..387045b58d1 100644 --- a/Content.Server/DeltaV/EntityEffects/Effects/Addicted.cs +++ b/Content.Server/DeltaV/EntityEffects/Effects/Addicted.cs @@ -7,19 +7,20 @@ namespace Content.Server.EntityEffects.Effects; public sealed partial class Addicted : EntityEffect { /// - /// How long should each metabolism cycle make the effect last for. + /// How long should each metabolism cycle make the effect last for. /// [DataField] - public float AddictionTime = 3f; + public float AddictionTime = 5f; - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-addicted", ("chance", Probability)); public override void Effect(EntityEffectBaseArgs args) { var addictionTime = AddictionTime; - if (args is EntityEffectReagentArgs reagentArgs) { + if (args is EntityEffectReagentArgs reagentArgs) + { addictionTime *= reagentArgs.Scale.Float(); } diff --git a/Content.Server/DeltaV/EntityEffects/Effects/InPain.cs b/Content.Server/DeltaV/EntityEffects/Effects/InPain.cs new file mode 100644 index 00000000000..5d2fe4c8cd7 --- /dev/null +++ b/Content.Server/DeltaV/EntityEffects/Effects/InPain.cs @@ -0,0 +1,30 @@ +using Content.Shared.DeltaV.Pain; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +public sealed partial class InPain : EntityEffect +{ + /// + /// How long should each metabolism cycle make the effect last for. + /// + [DataField] + public float PainTime = 5f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-addicted", ("chance", Probability)); + + public override void Effect(EntityEffectBaseArgs args) + { + var painTime = PainTime; + + if (args is EntityEffectReagentArgs reagentArgs) + { + painTime *= reagentArgs.Scale.Float(); + } + + var painSystem = args.EntityManager.System(); + painSystem.TryApplyPain(args.TargetEntity, painTime); + } +} diff --git a/Content.Server/DeltaV/EntityEffects/Effects/SuppressAddiction.cs b/Content.Server/DeltaV/EntityEffects/Effects/SuppressAddiction.cs new file mode 100644 index 00000000000..d89e57eef21 --- /dev/null +++ b/Content.Server/DeltaV/EntityEffects/Effects/SuppressAddiction.cs @@ -0,0 +1,31 @@ +using Content.Shared.DeltaV.Addictions; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +public sealed partial class SuppressAddiction : EntityEffect +{ + /// + /// How long should the addiction suppression last for each metabolism cycle + /// + [DataField] + public float SuppressionTime = 30f; + + protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-addiction-suppression", + ("chance", Probability)); + + public override void Effect(EntityEffectBaseArgs args) + { + var suppressionTime = SuppressionTime; + + if (args is EntityEffectReagentArgs reagentArgs) + { + suppressionTime *= reagentArgs.Scale.Float(); + } + + var addictionSystem = args.EntityManager.System(); + addictionSystem.TrySuppressAddiction(args.TargetEntity, suppressionTime); + } +} diff --git a/Content.Server/DeltaV/EntityEffects/Effects/SuppressPain.cs b/Content.Server/DeltaV/EntityEffects/Effects/SuppressPain.cs new file mode 100644 index 00000000000..53bba259d04 --- /dev/null +++ b/Content.Server/DeltaV/EntityEffects/Effects/SuppressPain.cs @@ -0,0 +1,38 @@ +using Content.Shared.DeltaV.Pain; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +public sealed partial class SuppressPain : EntityEffect +{ + /// + /// How long should the pain suppression last for each metabolism cycle + /// + [DataField] + public float SuppressionTime = 30f; + + /// + /// The strength level of the pain suppression + /// + [DataField] + public PainSuppressionLevel SuppressionLevel = PainSuppressionLevel.Normal; + + protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-pain-suppression", + ("chance", Probability), + ("level", SuppressionLevel.ToString().ToLowerInvariant())); + + public override void Effect(EntityEffectBaseArgs args) + { + var suppressionTime = SuppressionTime; + + if (args is EntityEffectReagentArgs reagentArgs) + { + suppressionTime *= reagentArgs.Scale.Float(); + } + + var painSystem = args.EntityManager.System(); + painSystem.TrySuppressPain(args.TargetEntity, suppressionTime, SuppressionLevel); + } +} diff --git a/Content.Server/DeltaV/Pain/PainSystem.cs b/Content.Server/DeltaV/Pain/PainSystem.cs new file mode 100644 index 00000000000..52a8f172d0e --- /dev/null +++ b/Content.Server/DeltaV/Pain/PainSystem.cs @@ -0,0 +1,90 @@ +using Content.Shared.DeltaV.Pain; +using Content.Shared.Popups; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server.DeltaV.Pain; + +public sealed class PainSystem : SharedPainSystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMapInit); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.NextUpdateTime = _timing.CurTime; + ent.Comp.NextPopupTime = _timing.CurTime; + } + + protected override void UpdatePainSuppression(Entity ent, float duration, PainSuppressionLevel level) + { + var curTime = _timing.CurTime; + var newEndTime = curTime + TimeSpan.FromSeconds(duration); + + // Only update if this would extend the suppression + if (newEndTime <= ent.Comp.SuppressionEndTime) + return; + + ent.Comp.LastPainkillerTime = curTime; + ent.Comp.SuppressionEndTime = newEndTime; + UpdateSuppressed(ent); + } + + private void UpdateSuppressed(Entity ent) + { + ent.Comp.Suppressed = (_timing.CurTime < ent.Comp.SuppressionEndTime); + Dirty(ent); + } + + private void ShowPainPopup(Entity ent) + { + if (!_prototype.TryIndex(ent.Comp.DatasetPrototype, out var dataset)) + return; + + var effects = dataset.Values; + if (effects.Count == 0) + return; + + var effect = _random.Pick(effects); + _popup.PopupEntity(Loc.GetString(effect), ent.Owner); + + // Set next popup time + var delay = _random.NextFloat(ent.Comp.MinimumPopupDelay, ent.Comp.MaximumPopupDelay); + ent.Comp.NextPopupTime = _timing.CurTime + TimeSpan.FromSeconds(delay); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var curTime = _timing.CurTime; + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var component)) + { + if (curTime < component.NextUpdateTime) + continue; + + var ent = new Entity(uid, component); + + if (component.Suppressed) + { + UpdateSuppressed(ent); + } + else if (curTime >= component.NextPopupTime) + { + ShowPainPopup(ent); + } + component.NextUpdateTime = curTime + TimeSpan.FromSeconds(1); + } + } +} diff --git a/Content.Shared/DeltaV/Addictions/SharedAddictionSystem.cs b/Content.Shared/DeltaV/Addictions/SharedAddictionSystem.cs index f58534592d9..bdcfe3c39e7 100644 --- a/Content.Shared/DeltaV/Addictions/SharedAddictionSystem.cs +++ b/Content.Shared/DeltaV/Addictions/SharedAddictionSystem.cs @@ -27,4 +27,17 @@ public virtual void TryApplyAddiction(EntityUid uid, float addictionTime, Status _statusEffects.TryAddTime(uid, StatusEffectKey, TimeSpan.FromSeconds(addictionTime), status); } } + + public virtual void TrySuppressAddiction(EntityUid uid, float duration) + { + if (!TryComp(uid, out var comp)) + return; + + var ent = new Entity(uid, comp); + UpdateAddictionSuppression(ent, duration); + } + + protected virtual void UpdateAddictionSuppression(Entity ent, float duration) + { + } } diff --git a/Content.Shared/DeltaV/Pain/PainComponent.cs b/Content.Shared/DeltaV/Pain/PainComponent.cs new file mode 100644 index 00000000000..a89ea803373 --- /dev/null +++ b/Content.Shared/DeltaV/Pain/PainComponent.cs @@ -0,0 +1,69 @@ +using Content.Shared.Dataset; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.DeltaV.Pain; + +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState, AutoGenerateComponentPause] +public sealed partial class PainComponent : Component +{ + /// + /// Whether pain effects are currently suppressed by painkillers + /// + [DataField, AutoNetworkedField] + public bool Suppressed; + + /// + /// The current level of pain suppression + /// + [DataField] + public PainSuppressionLevel CurrentSuppressionLevel = PainSuppressionLevel.Normal; + + /// + /// The last time painkillers were administered + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan LastPainkillerTime; + + /// + /// When the pain suppression effect ends + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan SuppressionEndTime; + + /// + /// When to next update this component + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan NextUpdateTime; + + /// + /// When to show the next pain effect popup + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoPausedField] + public TimeSpan NextPopupTime; + + /// + /// The dataset of pain effect messages to display + /// + [DataField] + public ProtoId DatasetPrototype = "PainEffects"; + + /// + /// Minimum time between pain popups in seconds + /// + [DataField] + public float MinimumPopupDelay = 1f; + + /// + /// Maximum time between pain popups in seconds + /// + [DataField] + public float MaximumPopupDelay = 40f; +} diff --git a/Content.Shared/DeltaV/Pain/SharedPainSystem.cs b/Content.Shared/DeltaV/Pain/SharedPainSystem.cs new file mode 100644 index 00000000000..896fd1590f2 --- /dev/null +++ b/Content.Shared/DeltaV/Pain/SharedPainSystem.cs @@ -0,0 +1,44 @@ +using Content.Shared.StatusEffect; +using Robust.Shared.Prototypes; + +namespace Content.Shared.DeltaV.Pain; + +public abstract class SharedPainSystem : EntitySystem +{ + [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; + + public ProtoId StatusEffectKey = "InPain"; + + protected abstract void UpdatePainSuppression(Entity ent, float duration, PainSuppressionLevel level); + + public virtual void TryApplyPain(EntityUid uid, float painTime, StatusEffectsComponent? status = null) + { + if (!Resolve(uid, ref status, false)) + return; + + if (!_statusEffects.HasStatusEffect(uid, StatusEffectKey, status)) + { + _statusEffects.TryAddStatusEffect(uid, StatusEffectKey, TimeSpan.FromSeconds(painTime), true, status); + } + else + { + _statusEffects.TryAddTime(uid, StatusEffectKey, TimeSpan.FromSeconds(painTime), status); + } + } + + public virtual void TrySuppressPain(EntityUid uid, float duration, PainSuppressionLevel level = PainSuppressionLevel.Normal) + { + if (!TryComp(uid, out var comp)) + return; + + UpdatePainSuppression((uid, comp), duration, level); + } +} + +// Used by the StatusEffect +public enum PainSuppressionLevel : byte +{ + Mild, + Normal, + Strong, +} diff --git a/Resources/Locale/en-US/_CD/reagents/RPmeds.ftl b/Resources/Locale/en-US/_CD/reagents/RPmeds.ftl index 6d64c0c5596..be18c0ee8f8 100644 --- a/Resources/Locale/en-US/_CD/reagents/RPmeds.ftl +++ b/Resources/Locale/en-US/_CD/reagents/RPmeds.ftl @@ -1,47 +1,56 @@ ### Messages to be used with RP-based medication. -reagent-effect-antidepressant-mild1 = You feel like things aren't so bad. -reagent-effect-antidepressant-mild2 = The world seems a bit brighter. +# Mild antidepressants +reagent-effect-antidepressant-mild1 = You feel like things aren't so bad. +reagent-effect-antidepressant-mild2 = The world seems a bit brighter. reagent-effect-antidepressant-mild3 = You feel a bit better about yourself. reagent-effect-antidepressant-mild4 = You feel slightly motivated. -reagent-effect-antidepressant-normal1 = You feel pretty alright. -reagent-effect-antidepressant-normal2 = You find it hard to focus. +# Normal antidepressants +reagent-effect-antidepressant-normal1 = You feel pretty alright. +reagent-effect-antidepressant-normal2 = You find it hard to focus. reagent-effect-antidepressant-normal3 = You feel purposeful. reagent-effect-antidepressant-normal4 = You feel motivated. -reagent-effect-antidepressant-normaloverdose1 = You feel irrationally angry. +# Normal antidepresants OD +reagent-effect-antidepressant-normaloverdose1 = You feel irrationally angry. reagent-effect-antidepressant-normaloverdose2 = Everyone is out to get you! -reagent-effect-antidepressant-strong1 = You feel a sense of great joy deep down. +# Strong antidepressants +reagent-effect-antidepressant-strong1 = You feel a sense of great joy deep down. reagent-effect-antidepressant-strong2 = You space out for a moment. reagent-effect-antidepressant-strong3 = You feel good about yourself. reagent-effect-antidepressant-strong4 = You feel a sense of great purpose. -reagent-effect-antidepressant-strongoverdose1 = You're gonna die! YOU'RE GONNA DIE! -reagent-effect-antidepressant-strongoverdose2 = Run! RUN! HIDE! +# Strong antidepressants OD +reagent-effect-antidepressant-strongoverdose1 = You're gonna die! YOU'RE GONNA DIE! +reagent-effect-antidepressant-strongoverdose2 = Run! RUN! HIDE! reagent-effect-antidepressant-strongoverdose3 = They're after you. THEY'LL KILL YOU. reagent-effect-antidepressant-strongoverdose4 = They're all plotting against you. -reagent-effect-antidepressant-strongoverdose5 = Watch your back, BEHIND YOU! +reagent-effect-antidepressant-strongoverdose5 = Watch your back, BEHIND YOU! reagent-effect-antidepressant-strongoverdose6 = You won't last the shift. reagent-effect-antidepressant-strongoverdose7 = Shut up. SHUT UP. SHUT UP! reagent-effect-antidepressant-strongoverdose8 = Get away. GET AWAY! IT'S GONNA EXPLODE! reagent-effect-antidepressant-strongoverdose9 = They're all liars. LIARS! +# Antidepressant fading reagent-effect-antidepressant-fade = The antidepressant effects start to fade... +# Mild anxiety meds reagent-effect-anxietymed-mild1 = You feel a bit calmer. reagent-effect-anxietymed-mild2 = You feel a little tired. reagent-effect-anxietymed-mild3 = You feel slightly relaxed. reagent-effect-anxietymed-mild4 = You feel like it might just be okay. reagent-effect-anxietymed-mild5 = The road ahead doesn't seem so bad. +# Normal anxiety meds reagent-effect-anxietymed-normal1 = You feel somewhat relaxed reagent-effect-anxietymed-normal2 = You feel drowsy for a moment. reagent-effect-anxietymed-normal3 = You feel calm. reagent-effect-anxietymed-normal4 = You feel more confident. reagent-effect-anxietymed-normal5 = Your worries seem to drift away. +# Normal anxiety meds OD reagent-effect-anxietymed-normaloverdose1 = You feel very sleepy. reagent-effect-anxietymed-normaloverdose2 = You feel like resting your eyes for just a moment. reagent-effect-anxietymed-normaloverdose3 = You feel like lying down and napping. @@ -49,6 +58,7 @@ reagent-effect-anxietymed-normaloverdose4 = Your eyes feel heavy. reagent-effect-anxietymed-normaloverdose5 = You lose your train of thought. reagent-effect-anxietymed-normaloverdose6 = You forget what you were doing. +# Strong anxiety meds reagent-effect-anxietymed-strong1 = You feel free of worry. reagent-effect-anxietymed-strong2 = Your mind goes numb for a moment. reagent-effect-anxietymed-strong3 = It seems like everything is just fine. @@ -57,8 +67,10 @@ reagent-effect-anxietymed-strong5 = You feel very relaxed. reagent-effect-anxietymed-strong6 = You feel quite calm. reagent-effect-anxietymed-strong7 = You feel like you can take on the world! +# Anxiety meds fade reagent-effect-anxietymed-fade = The calming effects start to fade... +# Addiction popups reagent-effect-medaddiction-1 = You're yearning for another high. reagent-effect-medaddiction-2 = You really need some more drugs. reagent-effect-medaddiction-3 = You feel empty. Find another fix. @@ -68,17 +80,19 @@ reagent-effect-medaddiction-6 = You can feel your hands shaking. reagent-effect-medaddiction-7 = You could use another hit right now reagent-effect-medaddiction-8 = One more fix couldn't hurt, right? +# Mild painkillers reagent-effect-painkiller-mild1 = Your body hurts a bit less. reagent-effect-painkiller-mild2 = You feel a little bit dizzy. reagent-effect-painkiller-mild3 = You feel a tiny bit numb. reagent-effect-painkiller-mild4 = Any pain you had has faded slightly. - +# Normal painkillers reagent-effect-painkiller-normal1 = Any pain you had has faded significantly. reagent-effect-painkiller-normal2 = You feel dizzy. reagent-effect-painkiller-normal3 = Your entire body goes numb briefly. reagent-effect-painkiller-normal4 = You feel your pain fade somewhat. +# Strong painkillers reagent-effect-painkiller-strong1 = You forgot what pain feels like. reagent-effect-painkiller-strong2 = You can't see straight. reagent-effect-painkiller-strong3 = You feel a sense of deep nostalgia. @@ -86,4 +100,11 @@ reagent-effect-painkiller-strong4 = Your entire body feels numb. reagent-effect-painkiller-strong5 = You hardly feel anything at all. reagent-effect-painkiller-strong6 = Any pain you were feeling is gone. -reagent-effect-painkiller-fade = The painkiller's effects start to fade... \ No newline at end of file +# Painkiller fade +reagent-effect-painkiller-fade = The painkiller's effects start to fade... + +# Pain effects +pain-effect1 = A dull ache pulses through your body. +pain-effect2 = Sharp stabs of pain make you wince. +pain-effect3 = You feel an intense, throbbing pain that clouds your thoughts. +pain-effect4 = Waves of agonizing pain make it hard to focus on anything else. diff --git a/Resources/Locale/en-US/deltav/guidebook/chemistry/effects.ftl b/Resources/Locale/en-US/deltav/guidebook/chemistry/effects.ftl index 886e5b0c4f0..5e92f8393e4 100644 --- a/Resources/Locale/en-US/deltav/guidebook/chemistry/effects.ftl +++ b/Resources/Locale/en-US/deltav/guidebook/chemistry/effects.ftl @@ -2,4 +2,16 @@ reagent-effect-guidebook-addicted = { $chance -> [1] Causes *[other] cause - } an addiction. + } an addiction + +reagent-effect-guidebook-addiction-suppression = + { $chance -> + [1] Suppresses + *[other] suppress + } active addictions + +reagent-effect-guidebook-pain-suppression = + { $chance -> + [1] Suppresses + *[other] suppress + } pain at { $level } strength diff --git a/Resources/Locale/en-US/deltav/traits/traits.ftl b/Resources/Locale/en-US/deltav/traits/traits.ftl index 4c5444ec981..5fb2e7052bc 100644 --- a/Resources/Locale/en-US/deltav/traits/traits.ftl +++ b/Resources/Locale/en-US/deltav/traits/traits.ftl @@ -26,3 +26,9 @@ trait-hushed-desc = You are unable to speak louder than a whisper. trait-uncloneable-name = Uncloneable trait-uncloneable-desc = Cannot be cloned + +trait-inpain-name = Chronic pain +trait-inpain-desc = You’re constantly in discomfort. You need painkillers to function. + +trait-addicted-name = Addicted +trait-addicted-desc = You crave the substance, and your thoughts keep drifting back to it. Without it, you feel incomplete, anxious, and on edge. diff --git a/Resources/Prototypes/DeltaV/Datasets/pain.yml b/Resources/Prototypes/DeltaV/Datasets/pain.yml new file mode 100644 index 00000000000..3c34ba2db98 --- /dev/null +++ b/Resources/Prototypes/DeltaV/Datasets/pain.yml @@ -0,0 +1,5 @@ +- type: localizedDataset + id: PainEffects + values: + prefix: pain-effect + count: 4 diff --git a/Resources/Prototypes/DeltaV/Shaders/chromatic_aberration.yml b/Resources/Prototypes/DeltaV/Shaders/chromatic_aberration.yml new file mode 100644 index 00000000000..e292bf9c473 --- /dev/null +++ b/Resources/Prototypes/DeltaV/Shaders/chromatic_aberration.yml @@ -0,0 +1,4 @@ +- type: shader + id: ChromaticAberration + kind: source + path: "/Textures/DeltaV/Shaders/chromatic_aberration.swsl" diff --git a/Resources/Prototypes/DeltaV/Traits/disabilities.yml b/Resources/Prototypes/DeltaV/Traits/disabilities.yml index a4c83523d5f..016e7b5340b 100644 --- a/Resources/Prototypes/DeltaV/Traits/disabilities.yml +++ b/Resources/Prototypes/DeltaV/Traits/disabilities.yml @@ -5,3 +5,19 @@ category: Disabilities components: - type: Uncloneable + +- type: trait + id: Addicted + name: trait-addicted-name + description: trait-addicted-desc + category: Disabilities + components: + - type: Addicted + +- type: trait + id: InPain + name: trait-inpain-name + description: trait-inpain-desc + category: Disabilities + components: + - type: Pain diff --git a/Resources/Prototypes/DeltaV/status_effects.yml b/Resources/Prototypes/DeltaV/status_effects.yml index beb09d7addd..cf1e8e25639 100644 --- a/Resources/Prototypes/DeltaV/status_effects.yml +++ b/Resources/Prototypes/DeltaV/status_effects.yml @@ -1,2 +1,11 @@ - type: statusEffect id: Addicted + +- type: statusEffect + id: SuppressAddiction + +- type: statusEffect + id: InPain + +- type: statusEffect + id: SuppressPain diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 7265c6ff737..4c52983750a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -139,6 +139,9 @@ - PsionicsDisabled #Nyano - Summary: PCs can have psionics disabled. - PsionicallyInsulated #Nyano - Summary: PCs can be made insulated from psionic powers. - Addicted # DeltaV - Psych med addictions system + - SuppressAddiction # DeltaV - Psych med addictions system + - InPain # DeltaV - Pain system + - SuppressPain # DeltaV - Pain system - type: Body prototype: Human requiredLegs: 2 diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml index beeefcb8797..370d294f246 100644 --- a/Resources/Prototypes/Reagents/narcotics.yml +++ b/Resources/Prototypes/Reagents/narcotics.yml @@ -48,16 +48,12 @@ key: Drowsiness time: 10 type: Remove - - !type:AdjustReagent # Delta-V - Addictive + - !type:Addicted # Delta-V - Addictive probability: 0.6 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 20 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 0.25 - reagent: Addictine - amount: 0.2 + - !type:SuppressAddiction Medicine: effects: - !type:ResetNarcolepsy @@ -214,16 +210,12 @@ type: Add time: 16 refresh: false - - !type:AdjustReagent # Delta-V - Addictive + - !type:Addicted # Delta-V - Addictive probability: 0.4 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 20 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 0.25 - reagent: Addictine - amount: 0.2 + - !type:SuppressAddiction - type: reagent id: Nicotine @@ -266,16 +258,12 @@ probability: 0.05 - !type:Drunk # Headaches and slurring are major symptoms of brain damage, this is close enough boozePower: 5 - - !type:AdjustReagent # Delta-V - Addictive + - !type:Addicted # Delta-V - Addictive probability: 0.4 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 20 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 0.25 - reagent: Addictine - amount: 0.2 + - !type:SuppressAddiction - type: reagent id: SpaceDrugs @@ -294,21 +282,17 @@ type: Add time: 5 refresh: false - - !type:ChemRerollPsionic #Nyano - Summary: lets the imbiber become psionic. + - !type:ChemRerollPsionic #Nyano - Summary: lets the imbiber become psionic. conditions: - !type:ReagentThreshold reagent: SpaceDrugs min: 15 - - !type:AdjustReagent # Delta-V - Addictive + - !type:Addicted # Delta-V - Addictive probability: 0.4 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 10 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 0.25 - reagent: Addictine - amount: 0.1 + - !type:SuppressAddiction - type: reagent id: Bananadine diff --git a/Resources/Prototypes/_CD/Reagents/medicine.yml b/Resources/Prototypes/_CD/Reagents/medicine.yml index 4de928336e7..a198c7d3efa 100644 --- a/Resources/Prototypes/_CD/Reagents/medicine.yml +++ b/Resources/Prototypes/_CD/Reagents/medicine.yml @@ -118,6 +118,7 @@ Medicine: metabolismRate : 0.01 effects: + - !type:SuppressAddiction - !type:PopupMessage type: Local visualType: Large @@ -191,17 +192,12 @@ min: 10 reagent: Neurozenium amount: -7.5 - - !type:AdjustReagent + - !type:Addicted probability: 0.5 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 10 # maximum addiction severity for this reagent - !type:ReagentThreshold reagent: Blissifylovene min: 1.5 - reagent: Addictine - amount: 0.1 - !type:HealthChange conditions: - !type:ReagentThreshold @@ -450,112 +446,6 @@ - !type:ReagentThreshold max: 0.1 -- type: reagent - id: Addictine - name: reagent-name-addictine - group: Toxins - desc: reagent-desc-addictine - flavor: savory - color: "#d9d9d9" - physicalDesc: reagent-physical-desc-refreshing - metabolisms: - Poison: - metabolismRate : 0.01 - effects: - - !type:PopupMessage - type: Local - visualType: LargeCaution - messages: - - "reagent-effect-medaddiction-1" - - "reagent-effect-medaddiction-2" - - "reagent-effect-medaddiction-3" - - "reagent-effect-medaddiction-4" - - "reagent-effect-medaddiction-5" - - "reagent-effect-medaddiction-6" - - "reagent-effect-medaddiction-7" - - "reagent-effect-medaddiction-8" - probability: 0.08 - conditions: - - !type:ReagentThreshold # the following three chemicals are addictive, and thus will counteract cravings. - reagent: Blissifylovene - max: 0.01 - - !type:ReagentThreshold - reagent: Soretizone - max: 0.01 - - !type:ReagentThreshold - reagent: Agonolexyne - max: 0.01 - - !type:ReagentThreshold # Delta-V - Following four are also addictive - reagent: SpaceDrugs - max: 0.01 - - !type:ReagentThreshold - reagent: THC - max: 0.01 - - !type:ReagentThreshold - reagent: Impedrezene - max: 0.01 - - !type:ReagentThreshold - reagent: Desoxyephedrine - max: 0.01 - - !type:AdjustReagent - reagent: Charcoal # purges bloodstream cleaners - amount: -10.0 - - !type:AdjustReagent - reagent: Ipecac # purges bloodstream cleaners - amount: -10.0 - - !type:MovespeedModifier - walkSpeedModifier: 0.9 # Delta-V : Changes walk-speed modifier from 0.95 to 0.9 - sprintSpeedModifier: 0.7 - conditions: - - !type:ReagentThreshold - max: 1.0 # it gets worse before the addiction ends. - - !type:ReagentThreshold # the following three chemicals are addictive, and thus will counteract cravings. - reagent: Blissifylovene - max: 0.01 - - !type:ReagentThreshold - reagent: Soretizone - max: 0.01 - - !type:ReagentThreshold - reagent: Agonolexyne - max: 0.01 - - !type:ReagentThreshold # Delta-V - Following four are also addictive - reagent: SpaceDrugs - max: 0.01 - - !type:ReagentThreshold - reagent: THC - max: 0.01 - - !type:ReagentThreshold - reagent: Impedrezene - max: 0.01 - - !type:ReagentThreshold - reagent: Desoxyephedrine - max: 0.01 - - !type:GenericStatusEffect # Delta-V - Makes you stutter - key: Stutter - component: StutteringAccent - conditions: - - !type:ReagentThreshold - reagent: Blissifylovene - max: 0.01 - - !type:ReagentThreshold - reagent: Soretizone - max: 0.01 - - !type:ReagentThreshold - reagent: Agonolexyne - max: 0.01 - - !type:ReagentThreshold - reagent: SpaceDrugs - max: 0.01 - - !type:ReagentThreshold - reagent: THC - max: 0.01 - - !type:ReagentThreshold - reagent: Impedrezene - max: 0.01 - - !type:ReagentThreshold - reagent: Desoxyephedrine - max: 0.01 - - type: reagent id: Stubantazine name: reagent-name-stubantazine @@ -568,6 +458,8 @@ Medicine: metabolismRate : 0.02 effects: + - !type:SuppressPain + suppressionLevel: Mild - !type:PopupMessage type: Local visualType: Medium @@ -621,6 +513,9 @@ Medicine: metabolismRate : 0.01 effects: + - !type:SuppressPain + suppressionLevel: Normal + - !type:SuppressAddiction - !type:PopupMessage type: Local visualType: Large @@ -656,16 +551,11 @@ min: 20 reagent: Soretizone amount: 0.03 - - !type:AdjustReagent - probability: 0.55 # Chance of Addiction rising per tick + - !type:Addicted + probability: 0.7 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 5 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 9 - reagent: Addictine # add - amount: 0.1 - !type:PopupMessage type: Local visualType: Medium # stronger painkiller = more noticable fading @@ -688,6 +578,9 @@ Medicine: metabolismRate : 0.01 effects: + - !type:SuppressPain + suppressionLevel: Strong + - !type:SuppressAddiction - !type:PopupMessage type: Local visualType: Large @@ -726,16 +619,11 @@ min: 1 reagent: Agonolexyne amount: 0.04 - - !type:AdjustReagent + - !type:Addicted probability: 0.8 # Chance of Addiction rising per tick conditions: - - !type:ReagentThreshold - reagent: Addictine - max: 25 # maximum addiction severity for this reagent - !type:ReagentThreshold min: 0.25 - reagent: Addictine - amount: 0.2 - !type:Drunk # OD causes drunkeness conditions: - !type:ReagentThreshold diff --git a/Resources/Textures/DeltaV/Shaders/chromatic_aberration.swsl b/Resources/Textures/DeltaV/Shaders/chromatic_aberration.swsl new file mode 100644 index 00000000000..5ea6e909bd7 --- /dev/null +++ b/Resources/Textures/DeltaV/Shaders/chromatic_aberration.swsl @@ -0,0 +1,32 @@ +uniform sampler2D SCREEN_TEXTURE; + +void fragment() { + highp vec2 coord = FRAGCOORD.xy * SCREEN_PIXEL_SIZE.xy; + highp float time = TIME * 0.3; + + const highp float distortAmount = 0.003; + + highp vec2 waveOffset = vec2( + distortAmount * ( + sin(time * 0.5 + coord.y * 4.0) + // Primary wave + sin(time * 0.7 + coord.y * 8.0) * 0.5 + // Secondary faster wave + sin(time * 0.2 + coord.x * 3.0) * 0.8 // Slower cross wave + ), + distortAmount * ( + cos(time * 0.5 + coord.x * 4.0) + // Primary wave + cos(time * 0.7 + coord.x * 8.0) * 0.5 + // Secondary faster wave + cos(time * 0.2 + coord.y * 3.0) * 0.8 // Slower cross wave + ) + ); + + highp vec4 redChannel = zTextureSpec(SCREEN_TEXTURE, coord + waveOffset * 1.5 + vec2(-distortAmount * 2.0, distortAmount)); + highp vec4 greenChannel = zTextureSpec(SCREEN_TEXTURE, coord + waveOffset); + highp vec4 blueChannel = zTextureSpec(SCREEN_TEXTURE, coord + waveOffset * 1.2 + vec2(distortAmount * 2.0, -distortAmount)); + + COLOR = vec4( + redChannel.r, + greenChannel.g, + blueChannel.b, + (redChannel.a + greenChannel.a + blueChannel.a) / 3.0 + ); +}