`NarcolepsySystem` refactor (#40305)

* Refactor

* Update

* Update
This commit is contained in:
Winkarst-cpu
2025-09-16 21:29:48 +03:00
committed by GitHub
parent 138ea68076
commit 972adcee21
7 changed files with 119 additions and 87 deletions

View File

@@ -18,7 +18,6 @@ using Content.Server.Speech.Components;
using Content.Server.Spreader; using Content.Server.Spreader;
using Content.Server.Temperature.Components; using Content.Server.Temperature.Components;
using Content.Server.Temperature.Systems; using Content.Server.Temperature.Systems;
using Content.Server.Traits.Assorted;
using Content.Server.Zombies; using Content.Server.Zombies;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Components; using Content.Shared.Atmos.Components;
@@ -33,6 +32,7 @@ using Content.Shared.Maps;
using Content.Shared.Mind.Components; using Content.Shared.Mind.Components;
using Content.Shared.Popups; using Content.Shared.Popups;
using Content.Shared.Random; using Content.Shared.Random;
using Content.Shared.Traits.Assorted;
using Content.Shared.Zombies; using Content.Shared.Zombies;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Audio; using Robust.Shared.Audio;

View File

@@ -1,24 +0,0 @@
using System.Numerics;
namespace Content.Server.Traits.Assorted;
/// <summary>
/// This is used for the narcolepsy trait.
/// </summary>
[RegisterComponent, Access(typeof(NarcolepsySystem))]
public sealed partial class NarcolepsyComponent : Component
{
/// <summary>
/// The random time between incidents, (min, max).
/// </summary>
[DataField("timeBetweenIncidents", required: true)]
public Vector2 TimeBetweenIncidents { get; private set; }
/// <summary>
/// The duration of incidents, (min, max).
/// </summary>
[DataField("durationOfIncident", required: true)]
public Vector2 DurationOfIncident { get; private set; }
public float NextIncidentTime;
}

View File

@@ -1,59 +0,0 @@
using Content.Shared.Bed.Sleep;
using Content.Shared.StatusEffectNew;
using Robust.Shared.Random;
namespace Content.Server.Traits.Assorted;
/// <summary>
/// This handles narcolepsy, causing the affected to fall asleep uncontrollably at a random interval.
/// </summary>
public sealed class NarcolepsySystem : EntitySystem
{
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly IRobustRandom _random = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<NarcolepsyComponent, ComponentStartup>(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<NarcolepsyComponent>();
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));
}
}
}

View File

@@ -12,7 +12,7 @@ public sealed partial class ResetNarcolepsy : EventEntityEffect<ResetNarcolepsy>
/// The # of seconds the effect resets the narcolepsy timer to /// The # of seconds the effect resets the narcolepsy timer to
/// </summary> /// </summary>
[DataField("TimerReset")] [DataField("TimerReset")]
public int TimerReset = 600; public TimeSpan TimerReset = TimeSpan.FromSeconds(600);
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
=> Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability)); => Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability));

View File

@@ -0,0 +1,44 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Traits.Assorted;
/// <summary>
/// This is used for the narcolepsy trait.
/// </summary>
[RegisterComponent, NetworkedComponent]
[AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause]
[Access(typeof(NarcolepsySystem))]
public sealed partial class NarcolepsyComponent : Component
{
/// <summary>
/// The maximum time between incidents.
/// </summary>
[DataField(required: true), AutoNetworkedField]
public TimeSpan MaxTimeBetweenIncidents;
/// <summary>
/// The minimum time between incidents.
/// </summary>
[DataField(required: true), AutoNetworkedField]
public TimeSpan MinTimeBetweenIncidents;
/// <summary>
/// The maximum duration of incidents.
/// </summary>
[DataField(required: true), AutoNetworkedField]
public TimeSpan MaxDurationOfIncident;
/// <summary>
/// The minimum duration of incidents.
/// </summary>
[DataField(required: true), AutoNetworkedField]
public TimeSpan MinDurationOfIncident;
/// <summary>
/// Next time indcident happens.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoNetworkedField, AutoPausedField]
public TimeSpan NextIncidentTime = TimeSpan.Zero;
}

View File

@@ -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;
/// <summary>
/// This handles narcolepsy, causing the affected to fall asleep uncontrollably at a random interval.
/// </summary>
public sealed class NarcolepsySystem : EntitySystem
{
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IGameTiming _timing = default!;
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<NarcolepsyComponent, MapInitEvent>(OnMapInit);
}
private void OnMapInit(Entity<NarcolepsyComponent> 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));
}
/// <summary>
/// Changes the time until the next incident.
/// </summary>
public void AdjustNarcolepsyTimer(Entity<NarcolepsyComponent?> 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<NarcolepsyComponent>();
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);
}
}
}

View File

@@ -32,8 +32,10 @@
category: Disabilities category: Disabilities
components: components:
- type: Narcolepsy - type: Narcolepsy
timeBetweenIncidents: 300, 600 maxTimeBetweenIncidents: 600
durationOfIncident: 10, 30 minTimeBetweenIncidents: 300
maxDurationOfIncident: 30
minDurationOfIncident: 10
- type: trait - type: trait
id: Unrevivable id: Unrevivable