diff --git a/Content.Client/Drowsiness/DrowsinessOverlay.cs b/Content.Client/Drowsiness/DrowsinessOverlay.cs index 9705aa7313..1687216b3e 100644 --- a/Content.Client/Drowsiness/DrowsinessOverlay.cs +++ b/Content.Client/Drowsiness/DrowsinessOverlay.cs @@ -1,7 +1,5 @@ -using Content.Shared.Bed.Sleep; using Content.Shared.Drowsiness; using Content.Shared.StatusEffectNew; -using Content.Shared.StatusEffectNew.Components; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Shared.Enums; @@ -23,8 +21,6 @@ public sealed class DrowsinessOverlay : Overlay public override bool RequestScreenTexture => true; private readonly ShaderInstance _drowsinessShader; - private EntityQuery _statusQuery; - public float CurrentPower = 0.0f; private const float PowerDivisor = 250.0f; @@ -34,9 +30,9 @@ public sealed class DrowsinessOverlay : Overlay public DrowsinessOverlay() { IoCManager.InjectDependencies(this); + _statusEffects = _sysMan.GetEntitySystem(); - _statusQuery = _entityManager.GetEntityQuery(); _drowsinessShader = _prototypeManager.Index("Drowsiness").InstanceUnique(); } @@ -47,22 +43,11 @@ public sealed class DrowsinessOverlay : Overlay if (playerEntity == null) return; - if (!_statusEffects.TryEffectsWithComp(playerEntity, out var drowsinessEffects)) + if (!_statusEffects.TryGetEffectsEndTimeWithComp(playerEntity, out var endTime)) return; - TimeSpan? remainingTime = TimeSpan.Zero; - foreach (var (_, _, statusEffectComp) in drowsinessEffects) - { - if (statusEffectComp.EndEffectTime > remainingTime) - remainingTime = statusEffectComp.EndEffectTime; - } - - if (remainingTime is null) - return; - - var curTime = _timing.CurTime; - var timeLeft = (float)(remainingTime - curTime).Value.TotalSeconds; - + endTime ??= TimeSpan.MaxValue; + var timeLeft = (float)(endTime - _timing.CurTime).Value.TotalSeconds; CurrentPower += 8f * (0.5f * timeLeft - CurrentPower) * args.DeltaSeconds / (timeLeft + 1); } diff --git a/Content.Client/Drugs/DrugOverlaySystem.cs b/Content.Client/Drugs/DrugOverlaySystem.cs index 608ae02842..e156e616b8 100644 --- a/Content.Client/Drugs/DrugOverlaySystem.cs +++ b/Content.Client/Drugs/DrugOverlaySystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Drugs; +using Content.Shared.StatusEffectNew; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Shared.Player; @@ -17,49 +18,47 @@ public sealed class DrugOverlaySystem : EntitySystem private RainbowOverlay _overlay = default!; - public static string RainbowKey = "SeeingRainbows"; - public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnInit); - SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnApplied); + SubscribeLocalEvent(OnRemoved); - SubscribeLocalEvent(OnPlayerAttached); - SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent>(OnPlayerAttached); + SubscribeLocalEvent>(OnPlayerDetached); _overlay = new(); } - private void OnPlayerAttached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerAttachedEvent args) + private void OnRemoved(Entity ent, ref StatusEffectRemovedEvent args) { - _overlayMan.AddOverlay(_overlay); - } + if (_player.LocalEntity != args.Target) + return; - private void OnPlayerDetached(EntityUid uid, SeeingRainbowsComponent component, LocalPlayerDetachedEvent args) - { _overlay.Intoxication = 0; _overlay.TimeTicker = 0; _overlayMan.RemoveOverlay(_overlay); } - private void OnInit(EntityUid uid, SeeingRainbowsComponent component, ComponentInit args) + private void OnApplied(Entity ent, ref StatusEffectAppliedEvent args) { - if (_player.LocalEntity == uid) - { - _overlay.Phase = _random.NextFloat(MathF.Tau); // random starting phase for movement effect - _overlayMan.AddOverlay(_overlay); - } + if (_player.LocalEntity != args.Target) + return; + + _overlay.Phase = _random.NextFloat(MathF.Tau); // random starting phase for movement effect + _overlayMan.AddOverlay(_overlay); } - private void OnShutdown(EntityUid uid, SeeingRainbowsComponent component, ComponentShutdown args) + private void OnPlayerAttached(Entity ent, ref StatusEffectRelayedEvent args) { - if (_player.LocalEntity == uid) - { - _overlay.Intoxication = 0; - _overlay.TimeTicker = 0; - _overlayMan.RemoveOverlay(_overlay); - } + _overlayMan.AddOverlay(_overlay); + } + + private void OnPlayerDetached(Entity ent, ref StatusEffectRelayedEvent args) + { + _overlay.Intoxication = 0; + _overlay.TimeTicker = 0; + _overlayMan.RemoveOverlay(_overlay); } } diff --git a/Content.Client/Drugs/RainbowOverlay.cs b/Content.Client/Drugs/RainbowOverlay.cs index 4e0bed1264..bfb3815649 100644 --- a/Content.Client/Drugs/RainbowOverlay.cs +++ b/Content.Client/Drugs/RainbowOverlay.cs @@ -1,6 +1,6 @@ using Content.Shared.CCVar; using Content.Shared.Drugs; -using Content.Shared.StatusEffect; +using Content.Shared.StatusEffectNew; using Robust.Client.Graphics; using Robust.Client.Player; using Robust.Shared.Configuration; @@ -17,6 +17,8 @@ public sealed class RainbowOverlay : Overlay [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IEntitySystemManager _sysMan = default!; + [Dependency] private readonly IGameTiming _timing = default!; + private readonly SharedStatusEffectsSystem _statusEffects = default!; public override OverlaySpace Space => OverlaySpace.WorldSpace; public override bool RequestScreenTexture => true; @@ -37,6 +39,8 @@ public sealed class RainbowOverlay : Overlay { IoCManager.InjectDependencies(this); + _statusEffects = _sysMan.GetEntitySystem(); + _rainbowShader = _prototypeManager.Index("Rainbow").InstanceUnique(); _config.OnValueChanged(CCVars.ReducedMotion, OnReducedMotionChanged, invokeImmediately: true); } @@ -54,18 +58,13 @@ public sealed class RainbowOverlay : Overlay if (playerEntity == null) return; - if (!_entityManager.HasComponent(playerEntity) - || !_entityManager.TryGetComponent(playerEntity, out var status)) + if (!_statusEffects.TryGetEffectsEndTimeWithComp(playerEntity, out var endTime)) return; - var statusSys = _sysMan.GetEntitySystem(); - if (!statusSys.TryGetTime(playerEntity.Value, DrugOverlaySystem.RainbowKey, out var time, status)) - return; - - var timeLeft = (float)(time.Value.Item2 - time.Value.Item1).TotalSeconds; + endTime ??= TimeSpan.MaxValue; + var timeLeft = (float)(endTime - _timing.CurTime).Value.TotalSeconds; TimeTicker += args.DeltaSeconds; - if (timeLeft - TimeTicker > timeLeft / 16f) { Intoxication += (timeLeft - Intoxication) * args.DeltaSeconds / 16f; diff --git a/Content.Shared/Drugs/SeeingRainbowsComponent.cs b/Content.Shared/Drugs/SeeingRainbowsComponent.cs index 221599c26e..2f22b1dc6a 100644 --- a/Content.Shared/Drugs/SeeingRainbowsComponent.cs +++ b/Content.Shared/Drugs/SeeingRainbowsComponent.cs @@ -3,7 +3,8 @@ using Robust.Shared.GameStates; namespace Content.Shared.Drugs; /// -/// Exists for use as a status effect. Adds a shader to the client that scales with the effect duration. +/// Adds a shader to the client that scales with the effect duration. +/// Use only in conjunction with , on the status effect entity. /// [RegisterComponent, NetworkedComponent] -public sealed partial class SeeingRainbowsComponent : Component { } +public sealed partial class SeeingRainbowsStatusEffectComponent : Component; diff --git a/Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs b/Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs index 14b02dd9db..2d1ec89c9d 100644 --- a/Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs +++ b/Content.Shared/StatusEffectNew/StatusEffectSystem.API.cs @@ -269,7 +269,7 @@ public abstract partial class SharedStatusEffectsSystem foreach (var effect in container.ActiveStatusEffects) { - if (!TryComp(effect, out var statusComp)) + if (!_effectQuery.TryComp(effect, out var statusComp)) continue; if (TryComp(effect, out var comp)) @@ -279,6 +279,39 @@ public abstract partial class SharedStatusEffectsSystem } } - return effects != null; + return effects is not null; + } + + /// + /// Helper function for calculating how long it takes for all effects with a particular component to disappear. Useful for overlays. + /// + /// An entity from which status effects are checked. + /// The farthest end time of effects with this component is returned. Can be null if one of the effects is infinite. + /// True if effects with the specified component were found, or False if there are no such effects. + public bool TryGetEffectsEndTimeWithComp(EntityUid? target, out TimeSpan? endTime) where T : IComponent + { + endTime = _timing.CurTime; + if (!_containerQuery.TryComp(target, out var container)) + return false; + + foreach (var effect in container.ActiveStatusEffects) + { + if (!HasComp(effect)) + continue; + + if (!_effectQuery.TryComp(effect, out var statusComp)) + continue; + + if (statusComp.EndEffectTime is null) + { + endTime = null; + return true; //This effect never ends, so we return null at endTime, but return true that there is time. + } + + if (statusComp.EndEffectTime > endTime) + endTime = statusComp.EndEffectTime; + } + + return endTime is not null; } } diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index b93ed915e2..5bf9a9ede0 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -123,7 +123,6 @@ - KnockedDown - SlowedDown - Stutter - - SeeingRainbows - Electrocution - Drunk - SlurredSpeech diff --git a/Resources/Prototypes/Entities/StatusEffects/misc.yml b/Resources/Prototypes/Entities/StatusEffects/misc.yml index bccdea773f..bb2aa9de93 100644 --- a/Resources/Prototypes/Entities/StatusEffects/misc.yml +++ b/Resources/Prototypes/Entities/StatusEffects/misc.yml @@ -42,3 +42,11 @@ name: drowsiness components: - type: DrowsinessStatusEffect + +# Adds drugs overlay +- type: entity + parent: MobStatusEffectBase + id: StatusEffectSeeingRainbow + name: hallucinations + components: + - type: SeeingRainbowsStatusEffect \ No newline at end of file diff --git a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml index adb9aa28e4..741108cca1 100644 --- a/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml +++ b/Resources/Prototypes/Reagents/Consumable/Drink/alcohol.yml @@ -27,12 +27,11 @@ - !type:AdjustReagent reagent: Ethanol amount: 0.05 - - !type:GenericStatusEffect + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow conditions: - !type:ReagentThreshold min: 10 - key: SeeingRainbows - component: SeeingRainbows type: Add time: 5 refresh: false diff --git a/Resources/Prototypes/Reagents/cleaning.yml b/Resources/Prototypes/Reagents/cleaning.yml index b9a0af01de..33c0a0e86f 100644 --- a/Resources/Prototypes/Reagents/cleaning.yml +++ b/Resources/Prototypes/Reagents/cleaning.yml @@ -107,11 +107,10 @@ metabolisms: Narcotic: effects: - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows - type: Add + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow time: 5 + type: Add refresh: false Drink: effects: diff --git a/Resources/Prototypes/Reagents/gases.yml b/Resources/Prototypes/Reagents/gases.yml index 1087d7bad4..4a97cb8b16 100644 --- a/Resources/Prototypes/Reagents/gases.yml +++ b/Resources/Prototypes/Reagents/gases.yml @@ -402,9 +402,8 @@ damage: types: Cellular: 1 - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow type: Add time: 15 refresh: false @@ -439,13 +438,12 @@ damage: types: Cellular: 0.5 - - !type:GenericStatusEffect + - !type:ModifyStatusEffect conditions: - !type:ReagentThreshold reagent: Frezon min: 1 - key: SeeingRainbows - component: SeeingRainbows + effectProto: StatusEffectSeeingRainbow type: Add time: 500 refresh: false diff --git a/Resources/Prototypes/Reagents/medicine.yml b/Resources/Prototypes/Reagents/medicine.yml index 2873372b52..dfecb112d5 100644 --- a/Resources/Prototypes/Reagents/medicine.yml +++ b/Resources/Prototypes/Reagents/medicine.yml @@ -749,8 +749,8 @@ key: KnockedDown time: 3.0 type: Remove - - !type:GenericStatusEffect - key: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow time: 15.0 type: Remove @@ -1323,12 +1323,11 @@ damage: types: Poison: 2 - - !type:GenericStatusEffect + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow conditions: - !type:ReagentThreshold min: 30 - key: SeeingRainbows - component: SeeingRainbows type: Add time: 8 refresh: false @@ -1398,8 +1397,8 @@ key: Jitter time: 4.0 type: Remove - - !type:GenericStatusEffect - key: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow time: 10.0 type: Remove - !type:AdjustReagent diff --git a/Resources/Prototypes/Reagents/narcotics.yml b/Resources/Prototypes/Reagents/narcotics.yml index aff87479b1..ed8b8acc65 100644 --- a/Resources/Prototypes/Reagents/narcotics.yml +++ b/Resources/Prototypes/Reagents/narcotics.yml @@ -198,11 +198,10 @@ metabolisms: Narcotic: effects: - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows - type: Add + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow time: 16 + type: Add refresh: false - type: reagent @@ -236,11 +235,10 @@ damage: types: Poison: 2 - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows - type: Add + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow time: 10 + type: Add refresh: false - !type:ChemVomit # Vomiting is a symptom of brain damage probability: 0.05 @@ -258,9 +256,8 @@ metabolisms: Narcotic: effects: - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow type: Add time: 5 refresh: false @@ -276,9 +273,8 @@ metabolisms: Narcotic: effects: - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow type: Add time: 5 refresh: false @@ -467,9 +463,8 @@ conditions: - !type:ReagentThreshold max: 20 - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow type: Add time: 5 refresh: false diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index 6560f05995..96761ae778 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -339,9 +339,8 @@ metabolisms: Poison: effects: - - !type:GenericStatusEffect - key: SeeingRainbows - component: SeeingRainbows + - !type:ModifyStatusEffect + effectProto: StatusEffectSeeingRainbow type: Add time: 10 refresh: false diff --git a/Resources/Prototypes/status_effects.yml b/Resources/Prototypes/status_effects.yml index e98dd4df02..7c96b88c22 100644 --- a/Resources/Prototypes/status_effects.yml +++ b/Resources/Prototypes/status_effects.yml @@ -25,9 +25,6 @@ - type: statusEffect id: AllCaps -- type: statusEffect - id: SeeingRainbows - - type: statusEffect id: Electrocution