From 972adcee21d9b25c2ca63b90c2649bd564fb6f9a Mon Sep 17 00:00:00 2001 From: Winkarst-cpu <74284083+Winkarst-cpu@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:29:48 +0300 Subject: [PATCH] ``NarcolepsySystem`` refactor (#40305) * Refactor * Update * Update --- .../EntityEffects/EntityEffectSystem.cs | 2 +- .../Traits/Assorted/NarcolepsyComponent.cs | 24 ------- .../Traits/Assorted/NarcolepsySystem.cs | 59 ---------------- .../EntityEffects/Effects/ResetNarcolepsy.cs | 2 +- .../Traits/Assorted/NarcolepsyComponent.cs | 44 ++++++++++++ .../Traits/Assorted/NarcolepsySystem.cs | 69 +++++++++++++++++++ Resources/Prototypes/Traits/disabilities.yml | 6 +- 7 files changed, 119 insertions(+), 87 deletions(-) delete mode 100644 Content.Server/Traits/Assorted/NarcolepsyComponent.cs delete mode 100644 Content.Server/Traits/Assorted/NarcolepsySystem.cs create mode 100644 Content.Shared/Traits/Assorted/NarcolepsyComponent.cs create mode 100644 Content.Shared/Traits/Assorted/NarcolepsySystem.cs diff --git a/Content.Server/EntityEffects/EntityEffectSystem.cs b/Content.Server/EntityEffects/EntityEffectSystem.cs index 4e447c7fab..3a86941a34 100644 --- a/Content.Server/EntityEffects/EntityEffectSystem.cs +++ b/Content.Server/EntityEffects/EntityEffectSystem.cs @@ -18,7 +18,6 @@ using Content.Server.Speech.Components; using Content.Server.Spreader; using Content.Server.Temperature.Components; using Content.Server.Temperature.Systems; -using Content.Server.Traits.Assorted; using Content.Server.Zombies; using Content.Shared.Atmos; using Content.Shared.Atmos.Components; @@ -33,6 +32,7 @@ using Content.Shared.Maps; using Content.Shared.Mind.Components; using Content.Shared.Popups; using Content.Shared.Random; +using Content.Shared.Traits.Assorted; using Content.Shared.Zombies; using Robust.Server.GameObjects; using Robust.Shared.Audio; diff --git a/Content.Server/Traits/Assorted/NarcolepsyComponent.cs b/Content.Server/Traits/Assorted/NarcolepsyComponent.cs deleted file mode 100644 index efa3458495..0000000000 --- a/Content.Server/Traits/Assorted/NarcolepsyComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Numerics; - -namespace Content.Server.Traits.Assorted; - -/// -/// This is used for the narcolepsy trait. -/// -[RegisterComponent, Access(typeof(NarcolepsySystem))] -public sealed partial class NarcolepsyComponent : Component -{ - /// - /// The random time between incidents, (min, max). - /// - [DataField("timeBetweenIncidents", required: true)] - public Vector2 TimeBetweenIncidents { get; private set; } - - /// - /// The duration of incidents, (min, max). - /// - [DataField("durationOfIncident", required: true)] - public Vector2 DurationOfIncident { get; private set; } - - public float NextIncidentTime; -} diff --git a/Content.Server/Traits/Assorted/NarcolepsySystem.cs b/Content.Server/Traits/Assorted/NarcolepsySystem.cs deleted file mode 100644 index 159e953369..0000000000 --- a/Content.Server/Traits/Assorted/NarcolepsySystem.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Content.Shared.Bed.Sleep; -using Content.Shared.StatusEffectNew; -using Robust.Shared.Random; - -namespace Content.Server.Traits.Assorted; - -/// -/// This handles narcolepsy, causing the affected to fall asleep uncontrollably at a random interval. -/// -public sealed class NarcolepsySystem : EntitySystem -{ - [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; - [Dependency] private readonly IRobustRandom _random = default!; - - /// - public override void Initialize() - { - SubscribeLocalEvent(SetupNarcolepsy); - } - - private void SetupNarcolepsy(EntityUid uid, NarcolepsyComponent component, ComponentStartup args) - { - component.NextIncidentTime = - _random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y); - } - - public void AdjustNarcolepsyTimer(EntityUid uid, int TimerReset, NarcolepsyComponent? narcolepsy = null) - { - if (!Resolve(uid, ref narcolepsy, false)) - return; - - narcolepsy.NextIncidentTime = TimerReset; - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var uid, out var narcolepsy)) - { - narcolepsy.NextIncidentTime -= frameTime; - - if (narcolepsy.NextIncidentTime >= 0) - continue; - - // Set the new time. - narcolepsy.NextIncidentTime += - _random.NextFloat(narcolepsy.TimeBetweenIncidents.X, narcolepsy.TimeBetweenIncidents.Y); - - var duration = _random.NextFloat(narcolepsy.DurationOfIncident.X, narcolepsy.DurationOfIncident.Y); - - // Make sure the sleep time doesn't cut into the time to next incident. - narcolepsy.NextIncidentTime += duration; - - _statusEffects.TryAddStatusEffectDuration(uid, SleepingSystem.StatusEffectForcedSleeping, TimeSpan.FromSeconds(duration)); - } - } -} diff --git a/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs b/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs index 71d228aece..009cf914d5 100644 --- a/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs +++ b/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs @@ -12,7 +12,7 @@ public sealed partial class ResetNarcolepsy : EventEntityEffect /// The # of seconds the effect resets the narcolepsy timer to /// [DataField("TimerReset")] - public int TimerReset = 600; + public TimeSpan TimerReset = TimeSpan.FromSeconds(600); protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability)); diff --git a/Content.Shared/Traits/Assorted/NarcolepsyComponent.cs b/Content.Shared/Traits/Assorted/NarcolepsyComponent.cs new file mode 100644 index 0000000000..ae94908925 --- /dev/null +++ b/Content.Shared/Traits/Assorted/NarcolepsyComponent.cs @@ -0,0 +1,44 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; + +namespace Content.Shared.Traits.Assorted; + +/// +/// This is used for the narcolepsy trait. +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause] +[Access(typeof(NarcolepsySystem))] +public sealed partial class NarcolepsyComponent : Component +{ + /// + /// The maximum time between incidents. + /// + [DataField(required: true), AutoNetworkedField] + public TimeSpan MaxTimeBetweenIncidents; + + /// + /// The minimum time between incidents. + /// + [DataField(required: true), AutoNetworkedField] + public TimeSpan MinTimeBetweenIncidents; + + /// + /// The maximum duration of incidents. + /// + [DataField(required: true), AutoNetworkedField] + public TimeSpan MaxDurationOfIncident; + + /// + /// The minimum duration of incidents. + /// + [DataField(required: true), AutoNetworkedField] + public TimeSpan MinDurationOfIncident; + + /// + /// Next time indcident happens. + /// + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] + [AutoNetworkedField, AutoPausedField] + public TimeSpan NextIncidentTime = TimeSpan.Zero; +} diff --git a/Content.Shared/Traits/Assorted/NarcolepsySystem.cs b/Content.Shared/Traits/Assorted/NarcolepsySystem.cs new file mode 100644 index 0000000000..7bce80c703 --- /dev/null +++ b/Content.Shared/Traits/Assorted/NarcolepsySystem.cs @@ -0,0 +1,69 @@ +using Content.Shared.Bed.Sleep; +using Content.Shared.Random.Helpers; +using Content.Shared.StatusEffectNew; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared.Traits.Assorted; + +/// +/// This handles narcolepsy, causing the affected to fall asleep uncontrollably at a random interval. +/// +public sealed class NarcolepsySystem : EntitySystem +{ + [Dependency] private readonly StatusEffectsSystem _statusEffects = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.NextIncidentTime = _timing.CurTime + _random.Next(ent.Comp.MinTimeBetweenIncidents, ent.Comp.MaxTimeBetweenIncidents); + DirtyField(ent, ent.Comp, nameof(ent.Comp.NextIncidentTime)); + } + + /// + /// Changes the time until the next incident. + /// + public void AdjustNarcolepsyTimer(Entity ent, TimeSpan time) + { + if (!Resolve(ent, ref ent.Comp, false)) + return; + + ent.Comp.NextIncidentTime = _timing.CurTime + time; + DirtyField(ent, ent.Comp, nameof(ent.Comp.NextIncidentTime)); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var narcolepsy)) + { + if (narcolepsy.NextIncidentTime > _timing.CurTime) + continue; + + // TODO: Replace with RandomPredicted once the engine PR is merged + var seed = SharedRandomExtensions.HashCodeCombine(new() { (int)_timing.CurTick.Value, GetNetEntity(uid).Id }); + var rand = new System.Random(seed); + + var duration = narcolepsy.MinDurationOfIncident + (narcolepsy.MaxDurationOfIncident - narcolepsy.MinDurationOfIncident) * rand.NextDouble(); + + // Set the new time. + narcolepsy.NextIncidentTime += + narcolepsy.MinTimeBetweenIncidents + (narcolepsy.MaxTimeBetweenIncidents - narcolepsy.MinTimeBetweenIncidents) * rand.NextDouble() + duration; + DirtyField(uid, narcolepsy, nameof(narcolepsy.NextIncidentTime)); + + _statusEffects.TryAddStatusEffectDuration(uid, SleepingSystem.StatusEffectForcedSleeping, duration); + } + } +} diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml index c5356149f2..51993d3dd1 100644 --- a/Resources/Prototypes/Traits/disabilities.yml +++ b/Resources/Prototypes/Traits/disabilities.yml @@ -32,8 +32,10 @@ category: Disabilities components: - type: Narcolepsy - timeBetweenIncidents: 300, 600 - durationOfIncident: 10, 30 + maxTimeBetweenIncidents: 600 + minTimeBetweenIncidents: 300 + maxDurationOfIncident: 30 + minDurationOfIncident: 10 - type: trait id: Unrevivable