New status effect system (#37238)
* spectra * documentation * added into liquid anomaly * Update TemporaryStealthComponent.cs * Update TemporaryStealthComponent.cs * integrated * new system * mark old status effect system as obsolete * ForcedSleeping new status effect * work with reagents * networking??? * Revert "integrated" This reverts commit bca02b82bae18ae131af593d7eb86e6de2745157. * Revert "Update TemporaryStealthComponent.cs" This reverts commit 4a5be8c4b704a0d1ff9544b2e245d8b2701ec580. * Revert "Update TemporaryStealthComponent.cs" This reverts commit a4875bcb41347638854bd723d96a51c3e6d38034. * Revert "added into liquid anomaly" This reverts commit df5086b14bb35f1467158a36807c0f2163a16d99. * Revert "documentation" This reverts commit 3629b9466758cbdfa4dd5e67ece122fa2f181138. * Revert "spectra" This reverts commit 2d03d88c16d16ad6831c19a7921b84600daeb284. * drowsiness status effect remove * reagents work * polish, remove test changes * first Fildrance review part * Update misc.yml * more fildrance review * final part * fix trailing spaces * sleeping status effect * drowsiness status effect * Create ModifyStatusEffect.cs * some tweak * Yay!!! Manual networking * minor nitpick * oopsie * refactor: xml-docs, notnullwhen attributes, whitespaces * fildrance and emo review * refactor: simplify check in SharedStatusEffectsSystem by using pattern matching, TryEffectsWithComp now returns set of Entity<T, StatusEffectComponent> --------- Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.Drowsiness;
|
using Content.Shared.Drowsiness;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffectNew;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
@@ -15,11 +17,14 @@ public sealed class DrowsinessOverlay : Overlay
|
|||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
[Dependency] private readonly IEntitySystemManager _sysMan = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
private readonly SharedStatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
public override bool RequestScreenTexture => true;
|
public override bool RequestScreenTexture => true;
|
||||||
private readonly ShaderInstance _drowsinessShader;
|
private readonly ShaderInstance _drowsinessShader;
|
||||||
|
|
||||||
|
private EntityQuery<StatusEffectComponent> _statusQuery;
|
||||||
|
|
||||||
public float CurrentPower = 0.0f;
|
public float CurrentPower = 0.0f;
|
||||||
|
|
||||||
private const float PowerDivisor = 250.0f;
|
private const float PowerDivisor = 250.0f;
|
||||||
@@ -29,6 +34,9 @@ public sealed class DrowsinessOverlay : Overlay
|
|||||||
public DrowsinessOverlay()
|
public DrowsinessOverlay()
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
_statusEffects = _sysMan.GetEntitySystem<SharedStatusEffectsSystem>();
|
||||||
|
|
||||||
|
_statusQuery = _entityManager.GetEntityQuery<StatusEffectComponent>();
|
||||||
_drowsinessShader = _prototypeManager.Index<ShaderPrototype>("Drowsiness").InstanceUnique();
|
_drowsinessShader = _prototypeManager.Index<ShaderPrototype>("Drowsiness").InstanceUnique();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,16 +47,21 @@ public sealed class DrowsinessOverlay : Overlay
|
|||||||
if (playerEntity == null)
|
if (playerEntity == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_entityManager.HasComponent<DrowsinessComponent>(playerEntity)
|
if (!_statusEffects.TryEffectsWithComp<DrowsinessStatusEffectComponent>(playerEntity, out var drowsinessEffects))
|
||||||
|| !_entityManager.TryGetComponent<StatusEffectsComponent>(playerEntity, out var status))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var statusSys = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
TimeSpan? remainingTime = TimeSpan.Zero;
|
||||||
if (!statusSys.TryGetTime(playerEntity.Value, SharedDrowsinessSystem.DrowsinessKey, out var time, status))
|
foreach (var (_, _, statusEffectComp) in drowsinessEffects)
|
||||||
|
{
|
||||||
|
if (statusEffectComp.EndEffectTime > remainingTime)
|
||||||
|
remainingTime = statusEffectComp.EndEffectTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingTime is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var curTime = _timing.CurTime;
|
var curTime = _timing.CurTime;
|
||||||
var timeLeft = (float)(time.Value.Item2 - curTime).TotalSeconds;
|
var timeLeft = (float)(remainingTime - curTime).Value.TotalSeconds;
|
||||||
|
|
||||||
CurrentPower += 8f * (0.5f * timeLeft - CurrentPower) * args.DeltaSeconds / (timeLeft + 1);
|
CurrentPower += 8f * (0.5f * timeLeft - CurrentPower) * args.DeltaSeconds / (timeLeft + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Shared.Drowsiness;
|
using Content.Shared.Drowsiness;
|
||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
using Robust.Shared.Player;
|
|
||||||
|
|
||||||
namespace Content.Client.Drowsiness;
|
namespace Content.Client.Drowsiness;
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IPlayerManager _player = default!;
|
[Dependency] private readonly IPlayerManager _player = default!;
|
||||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||||
|
[Dependency] private readonly SharedStatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
private DrowsinessOverlay _overlay = default!;
|
private DrowsinessOverlay _overlay = default!;
|
||||||
|
|
||||||
@@ -16,35 +17,47 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<DrowsinessComponent, ComponentInit>(OnDrowsinessInit);
|
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectAppliedEvent>(OnDrowsinessApply);
|
||||||
SubscribeLocalEvent<DrowsinessComponent, ComponentShutdown>(OnDrowsinessShutdown);
|
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectRemovedEvent>(OnDrowsinessShutdown);
|
||||||
|
|
||||||
SubscribeLocalEvent<DrowsinessComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectPlayerAttachedEvent>(OnStatusEffectPlayerAttached);
|
||||||
SubscribeLocalEvent<DrowsinessComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectPlayerDetachedEvent>(OnStatusEffectPlayerDetached);
|
||||||
|
|
||||||
_overlay = new();
|
_overlay = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerAttached(EntityUid uid, DrowsinessComponent component, LocalPlayerAttachedEvent args)
|
private void OnDrowsinessApply(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||||
{
|
{
|
||||||
|
if (_player.LocalEntity == args.Target)
|
||||||
_overlayMan.AddOverlay(_overlay);
|
_overlayMan.AddOverlay(_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerDetached(EntityUid uid, DrowsinessComponent component, LocalPlayerDetachedEvent args)
|
private void OnDrowsinessShutdown(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
if (_player.LocalEntity != args.Target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_statusEffects.HasEffectComp<DrowsinessStatusEffectComponent>(_player.LocalEntity.Value))
|
||||||
{
|
{
|
||||||
_overlay.CurrentPower = 0;
|
_overlay.CurrentPower = 0;
|
||||||
_overlayMan.RemoveOverlay(_overlay);
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnDrowsinessInit(EntityUid uid, DrowsinessComponent component, ComponentInit args)
|
private void OnStatusEffectPlayerAttached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectPlayerAttachedEvent args)
|
||||||
{
|
{
|
||||||
if (_player.LocalEntity == uid)
|
if (_player.LocalEntity != args.Target)
|
||||||
|
return;
|
||||||
|
|
||||||
_overlayMan.AddOverlay(_overlay);
|
_overlayMan.AddOverlay(_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDrowsinessShutdown(EntityUid uid, DrowsinessComponent component, ComponentShutdown args)
|
private void OnStatusEffectPlayerDetached(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectPlayerDetachedEvent args)
|
||||||
{
|
{
|
||||||
if (_player.LocalEntity == uid)
|
if (_player.LocalEntity != args.Target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_statusEffects.HasEffectComp<DrowsinessStatusEffectComponent>(_player.LocalEntity.Value))
|
||||||
{
|
{
|
||||||
_overlay.CurrentPower = 0;
|
_overlay.CurrentPower = 0;
|
||||||
_overlayMan.RemoveOverlay(_overlay);
|
_overlayMan.RemoveOverlay(_overlay);
|
||||||
|
|||||||
50
Content.Client/StatusEffectNew/ClientStatusEffectsSystem.cs
Normal file
50
Content.Client/StatusEffectNew/ClientStatusEffectsSystem.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Robust.Shared.Collections;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Client.StatusEffectNew;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public sealed partial class ClientStatusEffectsSystem : SharedStatusEffectsSystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentHandleState>(OnHandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHandleState(Entity<StatusEffectContainerComponent> ent, ref ComponentHandleState args)
|
||||||
|
{
|
||||||
|
if (args.Current is not StatusEffectContainerComponentState state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var toRemove = new ValueList<EntityUid>();
|
||||||
|
foreach (var effect in ent.Comp.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
if (state.ActiveStatusEffects.Contains(GetNetEntity(effect)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
toRemove.Add(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var effect in toRemove)
|
||||||
|
{
|
||||||
|
ent.Comp.ActiveStatusEffects.Remove(effect);
|
||||||
|
var ev = new StatusEffectRemovedEvent(ent);
|
||||||
|
RaiseLocalEvent(effect, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var effect in state.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var effectUid = GetEntity(effect);
|
||||||
|
if (ent.Comp.ActiveStatusEffects.Contains(effectUid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ent.Comp.ActiveStatusEffects.Add(effectUid);
|
||||||
|
var ev = new StatusEffectAppliedEvent(ent);
|
||||||
|
RaiseLocalEvent(effectUid, ref ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using Content.Shared.Bed.Sleep;
|
using Content.Server.StatusEffectNew;
|
||||||
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.Drowsiness;
|
using Content.Shared.Drowsiness;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffectNew;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
@@ -8,9 +10,6 @@ namespace Content.Server.Drowsiness;
|
|||||||
|
|
||||||
public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
||||||
{
|
{
|
||||||
[ValidatePrototypeId<StatusEffectPrototype>]
|
|
||||||
private const string SleepKey = "ForcedSleep"; // Same one used by N2O and other sleep chems.
|
|
||||||
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
@@ -18,33 +17,37 @@ public sealed class DrowsinessSystem : SharedDrowsinessSystem
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<DrowsinessComponent, ComponentStartup>(OnInit);
|
SubscribeLocalEvent<DrowsinessStatusEffectComponent, StatusEffectAppliedEvent>(OnEffectApplied);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, DrowsinessComponent component, ComponentStartup args)
|
private void OnEffectApplied(Entity<DrowsinessStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||||
{
|
{
|
||||||
component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y));
|
ent.Comp.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(ent.Comp.TimeBetweenIncidents.X, ent.Comp.TimeBetweenIncidents.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
|
|
||||||
var query = EntityQueryEnumerator<DrowsinessComponent>();
|
var query = EntityQueryEnumerator<DrowsinessStatusEffectComponent, StatusEffectComponent>();
|
||||||
while (query.MoveNext(out var uid, out var component))
|
while (query.MoveNext(out var uid, out var drowsiness, out var statusEffect))
|
||||||
{
|
{
|
||||||
if (_timing.CurTime < component.NextIncidentTime)
|
if (_timing.CurTime < drowsiness.NextIncidentTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (statusEffect.AppliedTo is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Set the new time.
|
// Set the new time.
|
||||||
component.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(component.TimeBetweenIncidents.X, component.TimeBetweenIncidents.Y));
|
drowsiness.NextIncidentTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(drowsiness.TimeBetweenIncidents.X, drowsiness.TimeBetweenIncidents.Y));
|
||||||
|
|
||||||
// sleep duration
|
// sleep duration
|
||||||
var duration = TimeSpan.FromSeconds(_random.NextFloat(component.DurationOfIncident.X, component.DurationOfIncident.Y));
|
var duration = TimeSpan.FromSeconds(_random.NextFloat(drowsiness.DurationOfIncident.X, drowsiness.DurationOfIncident.Y));
|
||||||
|
|
||||||
// Make sure the sleep time doesn't cut into the time to next incident.
|
// Make sure the sleep time doesn't cut into the time to next incident.
|
||||||
component.NextIncidentTime += duration;
|
drowsiness.NextIncidentTime += duration;
|
||||||
|
|
||||||
_statusEffects.TryAddStatusEffect<ForcedSleepingComponent>(uid, SleepKey, duration, false);
|
_statusEffects.TryAddStatusEffect(statusEffect.AppliedTo.Value, SleepingSystem.StatusEffectForcedSleeping, duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
Content.Server/StatusEffectNew/StatusEffectsSystem.cs
Normal file
23
Content.Server/StatusEffectNew/StatusEffectsSystem.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.StatusEffectNew;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public sealed partial class StatusEffectsSystem : SharedStatusEffectsSystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentShutdown>(OnContainerShutdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnContainerShutdown(Entity<StatusEffectContainerComponent> ent, ref ComponentShutdown args)
|
||||||
|
{
|
||||||
|
foreach (var effect in ent.Comp.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
QueueDel(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using Content.Server.StatusEffectNew;
|
||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.StatusEffect;
|
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Traits.Assorted;
|
namespace Content.Server.Traits.Assorted;
|
||||||
@@ -9,9 +9,6 @@ namespace Content.Server.Traits.Assorted;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class NarcolepsySystem : EntitySystem
|
public sealed class NarcolepsySystem : EntitySystem
|
||||||
{
|
{
|
||||||
[ValidatePrototypeId<StatusEffectPrototype>]
|
|
||||||
private const string StatusEffectKey = "ForcedSleep"; // Same one used by N2O and other sleep chems.
|
|
||||||
|
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
@@ -56,8 +53,7 @@ public sealed class NarcolepsySystem : EntitySystem
|
|||||||
// Make sure the sleep time doesn't cut into the time to next incident.
|
// Make sure the sleep time doesn't cut into the time to next incident.
|
||||||
narcolepsy.NextIncidentTime += duration;
|
narcolepsy.NextIncidentTime += duration;
|
||||||
|
|
||||||
_statusEffects.TryAddStatusEffect<ForcedSleepingComponent>(uid, StatusEffectKey,
|
_statusEffects.TryAddStatusEffect(uid, SleepingSystem.StatusEffectForcedSleeping, TimeSpan.FromSeconds(duration));
|
||||||
TimeSpan.FromSeconds(duration), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
|
|
||||||
namespace Content.Shared.Bed.Sleep
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Prevents waking up. Use as a status effect.
|
|
||||||
/// </summary>
|
|
||||||
[NetworkedComponent, RegisterComponent]
|
|
||||||
public sealed partial class ForcedSleepingComponent : Component
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Bed.Sleep;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prevents waking up. Use only in conjunction with <see cref="StatusEffectComponent"/>, on the status effect entity.
|
||||||
|
/// </summary>
|
||||||
|
[NetworkedComponent, RegisterComponent]
|
||||||
|
public sealed partial class ForcedSleepingStatusEffectComponent : Component;
|
||||||
@@ -19,6 +19,7 @@ using Content.Shared.Sound;
|
|||||||
using Content.Shared.Sound.Components;
|
using Content.Shared.Sound.Components;
|
||||||
using Content.Shared.Speech;
|
using Content.Shared.Speech;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffect;
|
||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
using Content.Shared.Stunnable;
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Traits.Assorted;
|
using Content.Shared.Traits.Assorted;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
@@ -37,10 +38,12 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedEmitSoundSystem _emitSound = default!;
|
[Dependency] private readonly SharedEmitSoundSystem _emitSound = default!;
|
||||||
[Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffectOld = default!;
|
||||||
|
[Dependency] private readonly SharedStatusEffectsSystem _statusEffectNew = default!;
|
||||||
|
|
||||||
public static readonly EntProtoId SleepActionId = "ActionSleep";
|
public static readonly EntProtoId SleepActionId = "ActionSleep";
|
||||||
public static readonly EntProtoId WakeActionId = "ActionWake";
|
public static readonly EntProtoId WakeActionId = "ActionWake";
|
||||||
|
public static readonly EntProtoId StatusEffectForcedSleeping = "StatusEffectForcedSleeping";
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -65,7 +68,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, GetVerbsEvent<AlternativeVerb>>(AddWakeVerb);
|
SubscribeLocalEvent<SleepingComponent, GetVerbsEvent<AlternativeVerb>>(AddWakeVerb);
|
||||||
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
||||||
|
|
||||||
SubscribeLocalEvent<ForcedSleepingComponent, ComponentInit>(OnInit);
|
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, EmoteAttemptEvent>(OnEmoteAttempt);
|
SubscribeLocalEvent<SleepingComponent, EmoteAttemptEvent>(OnEmoteAttempt);
|
||||||
|
|
||||||
@@ -104,8 +107,8 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
if (args.FellAsleep)
|
if (args.FellAsleep)
|
||||||
{
|
{
|
||||||
// Expiring status effects would remove the components needed for sleeping
|
// Expiring status effects would remove the components needed for sleeping
|
||||||
_statusEffectsSystem.TryRemoveStatusEffect(ent.Owner, "Stun");
|
_statusEffectOld.TryRemoveStatusEffect(ent.Owner, "Stun");
|
||||||
_statusEffectsSystem.TryRemoveStatusEffect(ent.Owner, "KnockedDown");
|
_statusEffectOld.TryRemoveStatusEffect(ent.Owner, "KnockedDown");
|
||||||
|
|
||||||
EnsureComp<StunnedComponent>(ent);
|
EnsureComp<StunnedComponent>(ent);
|
||||||
EnsureComp<KnockedDownComponent>(ent);
|
EnsureComp<KnockedDownComponent>(ent);
|
||||||
@@ -248,9 +251,9 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
_emitSound.SetEnabled((ent, spam), args.NewMobState == MobState.Alive);
|
_emitSound.SetEnabled((ent, spam), args.NewMobState == MobState.Alive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(Entity<ForcedSleepingComponent> ent, ref ComponentInit args)
|
private void OnStatusEffectApplied(Entity<ForcedSleepingStatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||||
{
|
{
|
||||||
TrySleeping(ent.Owner);
|
TrySleeping(args.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Wake(Entity<SleepingComponent> ent)
|
private void Wake(Entity<SleepingComponent> ent)
|
||||||
@@ -307,7 +310,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
if (!Resolve(ent, ref ent.Comp, false))
|
if (!Resolve(ent, ref ent.Comp, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!force && HasComp<ForcedSleepingComponent>(ent))
|
if (!force && _statusEffectNew.HasEffectComp<ForcedSleepingStatusEffectComponent>(ent))
|
||||||
{
|
{
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using Content.Shared.Damage.Events;
|
|||||||
using Content.Shared.Destructible;
|
using Content.Shared.Destructible;
|
||||||
using Content.Shared.Rejuvenate;
|
using Content.Shared.Rejuvenate;
|
||||||
using Content.Shared.Slippery;
|
using Content.Shared.Slippery;
|
||||||
using Content.Shared.StatusEffect;
|
using Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
namespace Content.Shared.Damage.Systems;
|
namespace Content.Shared.Damage.Systems;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
@@ -6,21 +7,22 @@ namespace Content.Shared.Drowsiness;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exists for use as a status effect. Adds a shader to the client that scales with the effect duration.
|
/// Exists for use as a status effect. Adds a shader to the client that scales with the effect duration.
|
||||||
|
/// Use only in conjunction with <see cref="StatusEffectComponent"/>, on the status effect entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentPause]
|
||||||
public sealed partial class DrowsinessComponent : Component
|
public sealed partial class DrowsinessStatusEffectComponent : Component
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The random time between sleeping incidents, (min, max).
|
/// The random time between sleeping incidents, (min, max).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField]
|
||||||
public Vector2 TimeBetweenIncidents = new Vector2(5f, 60f);
|
public Vector2 TimeBetweenIncidents = new(5f, 60f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The duration of sleeping incidents, (min, max).
|
/// The duration of sleeping incidents, (min, max).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField(required: true)]
|
[DataField]
|
||||||
public Vector2 DurationOfIncident = new Vector2(2, 5);
|
public Vector2 DurationOfIncident = new(2, 5);
|
||||||
|
|
||||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
[AutoPausedField]
|
[AutoPausedField]
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
using Content.Shared.StatusEffect;
|
|
||||||
|
|
||||||
namespace Content.Shared.Drowsiness;
|
namespace Content.Shared.Drowsiness;
|
||||||
|
|
||||||
public abstract class SharedDrowsinessSystem : EntitySystem
|
public abstract class SharedDrowsinessSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[ValidatePrototypeId<StatusEffectPrototype>]
|
|
||||||
public const string DrowsinessKey = "Drowsiness";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Content.Shared.EntityEffects.Effects.StatusEffects;
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Can be used for things like adding accents or something. I don't know. Go wild.
|
/// Can be used for things like adding accents or something. I don't know. Go wild.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
[Obsolete("Use ModifyStatusEffect with StatusEffectNewSystem instead")]
|
||||||
public sealed partial class GenericStatusEffect : EntityEffect
|
public sealed partial class GenericStatusEffect : EntityEffect
|
||||||
{
|
{
|
||||||
[DataField(required: true)]
|
[DataField(required: true)]
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.EntityEffects.Effects.StatusEffects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes status effects on entities: Adds, removes or sets time.
|
||||||
|
/// </summary>
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed partial class ModifyStatusEffect : EntityEffect
|
||||||
|
{
|
||||||
|
[DataField(required: true)]
|
||||||
|
public EntProtoId EffectProto;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Time for which status effect should be applied. Behaviour changes according to <see cref="Refresh" />.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float Time = 2.0f;
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// true - refresh status effect time, false - accumulate status effect time.
|
||||||
|
/// </remarks>
|
||||||
|
[DataField]
|
||||||
|
public bool Refresh = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should this effect add the status effect, remove time from it, or set its cooldown?
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public StatusEffectMetabolismType Type = StatusEffectMetabolismType.Add;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Effect(EntityEffectBaseArgs args)
|
||||||
|
{
|
||||||
|
var statusSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedStatusEffectsSystem>();
|
||||||
|
|
||||||
|
var time = Time;
|
||||||
|
if (args is EntityEffectReagentArgs reagentArgs)
|
||||||
|
time *= reagentArgs.Scale.Float();
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case StatusEffectMetabolismType.Add:
|
||||||
|
statusSys.TryAddStatusEffect(args.TargetEntity, EffectProto, TimeSpan.FromSeconds(time), Refresh);
|
||||||
|
break;
|
||||||
|
case StatusEffectMetabolismType.Remove:
|
||||||
|
statusSys.TryAddTime(args.TargetEntity, EffectProto, -TimeSpan.FromSeconds(time));
|
||||||
|
break;
|
||||||
|
case StatusEffectMetabolismType.Set:
|
||||||
|
statusSys.TrySetTime(args.TargetEntity, EffectProto, TimeSpan.FromSeconds(time));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||||
|
=> Loc.GetString(
|
||||||
|
"reagent-effect-guidebook-status-effect",
|
||||||
|
("chance", Probability),
|
||||||
|
("type", Type),
|
||||||
|
("time", Time),
|
||||||
|
("key", prototype.Index(EffectProto).Name)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -13,6 +14,7 @@ public sealed class SSDIndicatorSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly SharedStatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
private bool _icSsdSleep;
|
private bool _icSsdSleep;
|
||||||
private float _icSsdSleepTime;
|
private float _icSsdSleepTime;
|
||||||
@@ -37,10 +39,11 @@ public sealed class SSDIndicatorSystem : EntitySystem
|
|||||||
component.FallAsleepTime = TimeSpan.Zero;
|
component.FallAsleepTime = TimeSpan.Zero;
|
||||||
if (component.ForcedSleepAdded) // Remove component only if it has been added by this system
|
if (component.ForcedSleepAdded) // Remove component only if it has been added by this system
|
||||||
{
|
{
|
||||||
EntityManager.RemoveComponent<ForcedSleepingComponent>(uid);
|
_statusEffects.TryRemoveStatusEffect(uid, SleepingSystem.StatusEffectForcedSleeping);
|
||||||
component.ForcedSleepAdded = false;
|
component.ForcedSleepAdded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty(uid, component);
|
Dirty(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +56,7 @@ public sealed class SSDIndicatorSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime);
|
component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty(uid, component);
|
Dirty(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,12 +83,11 @@ public sealed class SSDIndicatorSystem : EntitySystem
|
|||||||
while (query.MoveNext(out var uid, out var ssd))
|
while (query.MoveNext(out var uid, out var ssd))
|
||||||
{
|
{
|
||||||
// Forces the entity to sleep when the time has come
|
// Forces the entity to sleep when the time has come
|
||||||
if(ssd.IsSSD &&
|
if (ssd.IsSSD &&
|
||||||
ssd.FallAsleepTime <= _timing.CurTime &&
|
ssd.FallAsleepTime <= _timing.CurTime &&
|
||||||
!TerminatingOrDeleted(uid) &&
|
!TerminatingOrDeleted(uid))
|
||||||
!HasComp<ForcedSleepingComponent>(uid)) // Don't add the component if the entity has it from another sources
|
|
||||||
{
|
{
|
||||||
EnsureComp<ForcedSleepingComponent>(uid);
|
_statusEffects.TryAddStatusEffect(uid, SleepingSystem.StatusEffectForcedSleeping);
|
||||||
ssd.ForcedSleepAdded = true;
|
ssd.ForcedSleepAdded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Rejuvenate;
|
using Content.Shared.Rejuvenate;
|
||||||
|
using Content.Shared.StatusEffectNew;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -8,6 +9,7 @@ using Robust.Shared.Utility;
|
|||||||
|
|
||||||
namespace Content.Shared.StatusEffect
|
namespace Content.Shared.StatusEffect
|
||||||
{
|
{
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public sealed class StatusEffectsSystem : EntitySystem
|
public sealed class StatusEffectsSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
@@ -104,6 +106,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="status">The status effects component to change, if you already have it.</param>
|
/// <param name="status">The status effects component to change, if you already have it.</param>
|
||||||
/// <returns>False if the effect could not be added or the component already exists, true otherwise.</returns>
|
/// <returns>False if the effect could not be added or the component already exists, true otherwise.</returns>
|
||||||
/// <typeparam name="T">The component type to add and remove from the entity.</typeparam>
|
/// <typeparam name="T">The component type to add and remove from the entity.</typeparam>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryAddStatusEffect<T>(EntityUid uid, string key, TimeSpan time, bool refresh,
|
public bool TryAddStatusEffect<T>(EntityUid uid, string key, TimeSpan time, bool refresh,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
where T : IComponent, new()
|
where T : IComponent, new()
|
||||||
@@ -123,6 +126,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh, string component,
|
public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh, string component,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -162,6 +166,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// If the effect already exists, it will simply replace the cooldown with the new one given.
|
/// If the effect already exists, it will simply replace the cooldown with the new one given.
|
||||||
/// If you want special 'effect merging' behavior, do it your own damn self!
|
/// If you want special 'effect merging' behavior, do it your own damn self!
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryAddStatusEffect(EntityUid uid,
|
public bool TryAddStatusEffect(EntityUid uid,
|
||||||
string key,
|
string key,
|
||||||
TimeSpan time,
|
TimeSpan time,
|
||||||
@@ -255,6 +260,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// Obviously this doesn't automatically clear any effects a status effect might have.
|
/// Obviously this doesn't automatically clear any effects a status effect might have.
|
||||||
/// That's up to the removed component to handle itself when it's removed.
|
/// That's up to the removed component to handle itself when it's removed.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryRemoveStatusEffect(EntityUid uid, string key,
|
public bool TryRemoveStatusEffect(EntityUid uid, string key,
|
||||||
StatusEffectsComponent? status = null, bool remComp = true)
|
StatusEffectsComponent? status = null, bool remComp = true)
|
||||||
{
|
{
|
||||||
@@ -298,6 +304,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="uid">The entity to remove effects from.</param>
|
/// <param name="uid">The entity to remove effects from.</param>
|
||||||
/// <param name="status">The status effects component to change, if you already have it.</param>
|
/// <param name="status">The status effects component to change, if you already have it.</param>
|
||||||
/// <returns>False if any status effects failed to be removed, true if they all did.</returns>
|
/// <returns>False if any status effects failed to be removed, true if they all did.</returns>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryRemoveAllStatusEffects(EntityUid uid,
|
public bool TryRemoveAllStatusEffects(EntityUid uid,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -321,6 +328,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="uid">The entity to check on.</param>
|
/// <param name="uid">The entity to check on.</param>
|
||||||
/// <param name="key">The status effect ID to check for</param>
|
/// <param name="key">The status effect ID to check for</param>
|
||||||
/// <param name="status">The status effect component, should you already have it.</param>
|
/// <param name="status">The status effect component, should you already have it.</param>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool HasStatusEffect(EntityUid uid, string key,
|
public bool HasStatusEffect(EntityUid uid, string key,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -338,6 +346,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="uid">The entity to check on.</param>
|
/// <param name="uid">The entity to check on.</param>
|
||||||
/// <param name="key">The status effect ID to check for</param>
|
/// <param name="key">The status effect ID to check for</param>
|
||||||
/// <param name="status">The status effect component, should you already have it.</param>
|
/// <param name="status">The status effect component, should you already have it.</param>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool CanApplyEffect(EntityUid uid, string key, StatusEffectsComponent? status = null)
|
public bool CanApplyEffect(EntityUid uid, string key, StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
// don't log since stuff calling this prolly doesn't care if we don't actually have it
|
// don't log since stuff calling this prolly doesn't care if we don't actually have it
|
||||||
@@ -364,6 +373,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="key">The status effect to add time to.</param>
|
/// <param name="key">The status effect to add time to.</param>
|
||||||
/// <param name="time">The amount of time to add.</param>
|
/// <param name="time">The amount of time to add.</param>
|
||||||
/// <param name="status">The status effect component, should you already have it.</param>
|
/// <param name="status">The status effect component, should you already have it.</param>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryAddTime(EntityUid uid, string key, TimeSpan time,
|
public bool TryAddTime(EntityUid uid, string key, TimeSpan time,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -395,6 +405,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="key">The status effect to remove time from.</param>
|
/// <param name="key">The status effect to remove time from.</param>
|
||||||
/// <param name="time">The amount of time to add.</param>
|
/// <param name="time">The amount of time to add.</param>
|
||||||
/// <param name="status">The status effect component, should you already have it.</param>
|
/// <param name="status">The status effect component, should you already have it.</param>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryRemoveTime(EntityUid uid, string key, TimeSpan time,
|
public bool TryRemoveTime(EntityUid uid, string key, TimeSpan time,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -430,6 +441,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Not used internally; just sets it itself.
|
/// Not used internally; just sets it itself.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TrySetTime(EntityUid uid, string key, TimeSpan time,
|
public bool TrySetTime(EntityUid uid, string key, TimeSpan time,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -453,6 +465,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
/// <param name="time">Out var for the time, if it exists.</param>
|
/// <param name="time">Out var for the time, if it exists.</param>
|
||||||
/// <param name="status">The status effects component to use, if any.</param>
|
/// <param name="status">The status effects component to use, if any.</param>
|
||||||
/// <returns>False if the status effect was not active, true otherwise.</returns>
|
/// <returns>False if the status effect was not active, true otherwise.</returns>
|
||||||
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
||||||
public bool TryGetTime(EntityUid uid, string key,
|
public bool TryGetTime(EntityUid uid, string key,
|
||||||
[NotNullWhen(true)] out (TimeSpan, TimeSpan)? time,
|
[NotNullWhen(true)] out (TimeSpan, TimeSpan)? time,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
@@ -468,12 +481,6 @@ namespace Content.Shared.StatusEffect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raised on an entity before a status effect is added to determine if adding it should be cancelled.
|
|
||||||
/// </summary>
|
|
||||||
[ByRefEvent]
|
|
||||||
public record struct BeforeStatusEffectAddedEvent(string Key, bool Cancelled=false);
|
|
||||||
|
|
||||||
public readonly struct StatusEffectAddedEvent
|
public readonly struct StatusEffectAddedEvent
|
||||||
{
|
{
|
||||||
public readonly EntityUid Uid;
|
public readonly EntityUid Uid;
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marker component for all status effects - every status effect entity should have it.
|
||||||
|
/// Provides a link between the effect and the affected entity, and some data common to all status effects.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||||
|
[Access(typeof(SharedStatusEffectsSystem))]
|
||||||
|
[EntityCategory("StatusEffects")]
|
||||||
|
public sealed partial class StatusEffectComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The entity that this status effect is applied to.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid? AppliedTo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Status effect indication for the player. If Null, no Alert will be displayed.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<AlertPrototype>? Alert;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When this effect will end. If Null, the effect lasts indefinitely.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
|
||||||
|
public TimeSpan? EndEffectTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whitelist, by which it is determined whether this status effect can be imposed on a particular entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntityWhitelist? Whitelist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blacklist, by which it is determined whether this status effect can be imposed on a particular entity.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntityWhitelist? Blacklist;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds container for status effect entities that are applied to entity.
|
||||||
|
/// Is applied automatically upon adding any status effect.
|
||||||
|
/// Can be used for tracking currently applied status effects.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[Access(typeof(SharedStatusEffectsSystem))]
|
||||||
|
public sealed partial class StatusEffectContainerComponent : Component
|
||||||
|
{
|
||||||
|
[DataField]
|
||||||
|
public HashSet<EntityUid> ActiveStatusEffects = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class StatusEffectContainerComponentState(HashSet<NetEntity> activeStatusEffects) : ComponentState
|
||||||
|
{
|
||||||
|
public readonly HashSet<NetEntity> ActiveStatusEffects = activeStatusEffects;
|
||||||
|
}
|
||||||
208
Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs
Normal file
208
Content.Shared/StatusEffectNew/SharedStatusEffectsSystem.cs
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Network;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This system controls status effects, their lifetime, and provides an API for adding them to entities,
|
||||||
|
/// removing them from entities, or getting information about current effects on entities.
|
||||||
|
/// </summary>
|
||||||
|
public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly IComponentFactory _compFactory = default!;
|
||||||
|
[Dependency] private readonly INetManager _net = default!;
|
||||||
|
|
||||||
|
private EntityQuery<StatusEffectContainerComponent> _containerQuery;
|
||||||
|
private EntityQuery<StatusEffectComponent> _effectQuery;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
|
SubscribeLocalEvent<StatusEffectComponent, StatusEffectRemovedEvent>(OnStatusEffectRemoved);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(OnStatusEffectContainerAttached);
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(OnStatusEffectContainerDetached);
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentGetState>(OnGetState);
|
||||||
|
|
||||||
|
_containerQuery = GetEntityQuery<StatusEffectContainerComponent>();
|
||||||
|
_effectQuery = GetEntityQuery<StatusEffectComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGetState(Entity<StatusEffectContainerComponent> ent, ref ComponentGetState args)
|
||||||
|
{
|
||||||
|
args.State = new StatusEffectContainerComponentState(GetNetEntitySet(ent.Comp.ActiveStatusEffects));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectContainerAttached(Entity<StatusEffectContainerComponent> ent, ref LocalPlayerAttachedEvent args)
|
||||||
|
{
|
||||||
|
foreach (var effect in ent.Comp.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var ev = new StatusEffectPlayerAttachedEvent(ent);
|
||||||
|
RaiseLocalEvent(effect, ref ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectContainerDetached(Entity<StatusEffectContainerComponent> ent, ref LocalPlayerDetachedEvent args)
|
||||||
|
{
|
||||||
|
foreach (var effect in ent.Comp.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var ev = new StatusEffectPlayerDetachedEvent(ent);
|
||||||
|
RaiseLocalEvent(effect, ref ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
var query = EntityQueryEnumerator<StatusEffectComponent>();
|
||||||
|
while (query.MoveNext(out var ent, out var effect))
|
||||||
|
{
|
||||||
|
if (effect.EndEffectTime is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(_timing.CurTime >= effect.EndEffectTime))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (effect.AppliedTo is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var meta = MetaData(ent);
|
||||||
|
if (meta.EntityPrototype is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TryRemoveStatusEffect(effect.AppliedTo.Value, meta.EntityPrototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddStatusEffectTime(EntityUid effect, TimeSpan delta)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
effectComp.EndEffectTime += delta;
|
||||||
|
Dirty(effect, effectComp);
|
||||||
|
|
||||||
|
if (effectComp is { AppliedTo: not null, Alert: not null })
|
||||||
|
{
|
||||||
|
(TimeSpan Start, TimeSpan End)? cooldown = effectComp.EndEffectTime is null
|
||||||
|
? null
|
||||||
|
: (_timing.CurTime, effectComp.EndEffectTime.Value);
|
||||||
|
_alerts.ShowAlert(
|
||||||
|
effectComp.AppliedTo.Value,
|
||||||
|
effectComp.Alert.Value,
|
||||||
|
cooldown: cooldown
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStatusEffectTime(EntityUid effect, TimeSpan duration)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
effectComp.EndEffectTime = _timing.CurTime + duration;
|
||||||
|
Dirty(effect, effectComp);
|
||||||
|
|
||||||
|
if (effectComp is { AppliedTo: not null, Alert: not null })
|
||||||
|
{
|
||||||
|
(TimeSpan, TimeSpan)? cooldown = effectComp.EndEffectTime is null
|
||||||
|
? null
|
||||||
|
: (_timing.CurTime, effectComp.EndEffectTime.Value);
|
||||||
|
_alerts.ShowAlert(
|
||||||
|
effectComp.AppliedTo.Value,
|
||||||
|
effectComp.Alert.Value,
|
||||||
|
cooldown: cooldown
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectApplied(Entity<StatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
||||||
|
{
|
||||||
|
if (ent.Comp is { AppliedTo: not null, Alert: not null })
|
||||||
|
{
|
||||||
|
(TimeSpan, TimeSpan)? cooldown = ent.Comp.EndEffectTime is null
|
||||||
|
? null
|
||||||
|
: (_timing.CurTime, ent.Comp.EndEffectTime.Value);
|
||||||
|
_alerts.ShowAlert(
|
||||||
|
ent.Comp.AppliedTo.Value,
|
||||||
|
ent.Comp.Alert.Value,
|
||||||
|
cooldown: cooldown
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectRemoved(Entity<StatusEffectComponent> ent, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
if (ent.Comp.AppliedTo is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp is { AppliedTo: not null, Alert: not null })
|
||||||
|
_alerts.ClearAlert(ent.Comp.AppliedTo.Value, ent.Comp.Alert.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
||||||
|
{
|
||||||
|
if (!_proto.TryIndex(effectProto, out var effectProtoData))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!effectProtoData.TryGetComponent<StatusEffectComponent>(out var effectProtoComp, _compFactory))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_whitelist.CheckBoth(uid, effectProtoComp.Blacklist, effectProtoComp.Whitelist))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var ev = new BeforeStatusEffectAddedEvent(effectProto);
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
|
||||||
|
if (ev.Cancelled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls on effect entity, when a status effect is applied.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct StatusEffectAppliedEvent(EntityUid Target);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls on effect entity, when a status effect is removed.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct StatusEffectRemovedEvent(EntityUid Target);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called on a status effect entity inside <see cref="StatusEffectContainerComponent"/>
|
||||||
|
/// after a player has been <see cref="LocalPlayerAttachedEvent"/> to this container entity.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct StatusEffectPlayerAttachedEvent(EntityUid Target);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called on a status effect entity inside <see cref="StatusEffectContainerComponent"/>
|
||||||
|
/// after a player has been <see cref="LocalPlayerDetachedEvent"/> to this container entity.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct StatusEffectPlayerDetachedEvent(EntityUid Target);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on an entity before a status effect is added to determine if adding it should be cancelled.
|
||||||
|
/// </summary>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct BeforeStatusEffectAddedEvent(EntProtoId Effect, bool Cancelled = false);
|
||||||
265
Content.Shared/StatusEffectNew/StatusEffectNewSystem.API.cs
Normal file
265
Content.Shared/StatusEffectNew/StatusEffectNewSystem.API.cs
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
|
public abstract partial class SharedStatusEffectsSystem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to add a status effect to the specified entity. Returns True if the effect is added or it already exists
|
||||||
|
/// and has been successfully extended in time, returns False if the status effect cannot be applied to this entity,
|
||||||
|
/// or for any other reason.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">The target entity to which the effect should be added.</param>
|
||||||
|
/// <param name="effectProto">ProtoId of the status effect entity. Make sure it has StatusEffectComponent on it.</param>
|
||||||
|
/// <param name="duration">Duration of status effect. Leave null and the effect will be permanent until it is removed using <c>TryRemoveStatusEffect</c>.</param>
|
||||||
|
/// <param name="resetCooldown">
|
||||||
|
/// If True, the effect duration time will be reset and reapplied. If False, the effect duration time will be overlaid with the existing one.
|
||||||
|
/// In the other case, the effect will either be added for the specified time or its time will be extended for the specified time.
|
||||||
|
/// </param>
|
||||||
|
public bool TryAddStatusEffect(
|
||||||
|
EntityUid target,
|
||||||
|
EntProtoId effectProto,
|
||||||
|
TimeSpan? duration = null,
|
||||||
|
bool resetCooldown = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (TryGetStatusEffect(target, effectProto, out var existedEffect))
|
||||||
|
{
|
||||||
|
//We don't need to add the effect if it already exists
|
||||||
|
if (duration is null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (resetCooldown)
|
||||||
|
SetStatusEffectTime(existedEffect.Value, duration.Value);
|
||||||
|
else
|
||||||
|
AddStatusEffectTime(existedEffect.Value, duration.Value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CanAddStatusEffect(target, effectProto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var container = EnsureComp<StatusEffectContainerComponent>(target);
|
||||||
|
|
||||||
|
//And only if all checks passed we spawn the effect
|
||||||
|
var effect = PredictedSpawnAttachedTo(effectProto, Transform(target).Coordinates);
|
||||||
|
_transform.SetParent(effect, target);
|
||||||
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (duration != null)
|
||||||
|
effectComp.EndEffectTime = _timing.CurTime + duration;
|
||||||
|
|
||||||
|
container.ActiveStatusEffects.Add(effect);
|
||||||
|
effectComp.AppliedTo = target;
|
||||||
|
Dirty(target, container);
|
||||||
|
Dirty(effect, effectComp);
|
||||||
|
|
||||||
|
var ev = new StatusEffectAppliedEvent(target);
|
||||||
|
RaiseLocalEvent(effect, ref ev);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempting to remove a status effect from an entity.
|
||||||
|
/// Returns True if the status effect existed on the entity and was successfully removed, and False in otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryRemoveStatusEffect(EntityUid target, EntProtoId effectProto)
|
||||||
|
{
|
||||||
|
if (_net.IsClient) //We cant remove the effect on the client (we need someone more robust at networking than me)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(effect);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var ev = new StatusEffectRemovedEvent(target);
|
||||||
|
RaiseLocalEvent(effect, ref ev);
|
||||||
|
|
||||||
|
QueueDel(effect);
|
||||||
|
container.ActiveStatusEffects.Remove(effect);
|
||||||
|
Dirty(target, container);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the specified entity is under a specific status effect.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasStatusEffect(EntityUid target, EntProtoId effectProto)
|
||||||
|
{
|
||||||
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(effect);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempting to retrieve the EntityUid of a status effect from an entity.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryGetStatusEffect(EntityUid target, EntProtoId effectProto, [NotNullWhen(true)] out EntityUid? effect)
|
||||||
|
{
|
||||||
|
effect = null;
|
||||||
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var e in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(e);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
{
|
||||||
|
effect = e;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempting to retrieve the time of a status effect from an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The target entity on which the effect is applied.</param>
|
||||||
|
/// <param name="effectProto">The prototype ID of the status effect to retrieve.</param>
|
||||||
|
/// <param name="time">The output tuple containing the effect entity and its remaining time.</param>
|
||||||
|
/// <param name="container">Optional. The status effect container component of the entity.</param>
|
||||||
|
public bool TryGetTime(
|
||||||
|
EntityUid uid,
|
||||||
|
EntProtoId effectProto,
|
||||||
|
out (EntityUid EffectEnt, TimeSpan? EndEffectTime) time,
|
||||||
|
StatusEffectContainerComponent? container = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
time = default;
|
||||||
|
if (!Resolve(uid, ref container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(effect);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
time = (effect, effectComp.EndEffectTime);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to edit the remaining time for a status effect on an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The target entity on which the effect is applied.</param>
|
||||||
|
/// <param name="effectProto">The prototype ID of the status effect to modify.</param>
|
||||||
|
/// <param name="time">
|
||||||
|
/// The time adjustment to apply to the status effect. Positive values extend the duration,
|
||||||
|
/// while negative values reduce it.
|
||||||
|
/// </param>
|
||||||
|
/// <returns> True if duration was edited successfully, false otherwise.</returns>
|
||||||
|
public bool TryAddTime(EntityUid uid, EntProtoId effectProto, TimeSpan time)
|
||||||
|
{
|
||||||
|
if (!_containerQuery.TryComp(uid, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(effect);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
{
|
||||||
|
AddStatusEffectTime(effect, time);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to set the remaining time for a status effect on an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The target entity on which the effect is applied.</param>
|
||||||
|
/// <param name="effectProto">The prototype ID of the status effect to modify.</param>
|
||||||
|
/// <param name="time">The new duration for the status effect.</param>
|
||||||
|
/// <returns> True if duration was set successfully, false otherwise.</returns>
|
||||||
|
public bool TrySetTime(EntityUid uid, EntProtoId effectProto, TimeSpan time)
|
||||||
|
{
|
||||||
|
if (!_containerQuery.TryComp(uid, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
var meta = MetaData(effect);
|
||||||
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
|
{
|
||||||
|
SetStatusEffectTime(effect, time);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the specified component is present on any of the entity's status effects.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasEffectComp<T>(EntityUid? target) where T : IComponent
|
||||||
|
{
|
||||||
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
if (HasComp<T>(effect))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all status effects that have the specified component.
|
||||||
|
/// </summary>
|
||||||
|
public bool TryEffectsWithComp<T>(EntityUid? target, [NotNullWhen(true)] out HashSet<Entity<T, StatusEffectComponent>>? effects) where T : IComponent
|
||||||
|
{
|
||||||
|
effects = null;
|
||||||
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var effect in container.ActiveStatusEffects)
|
||||||
|
{
|
||||||
|
if (!TryComp<StatusEffectComponent>(effect, out var statusComp))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (TryComp<T>(effect, out var comp))
|
||||||
|
{
|
||||||
|
effects ??= [];
|
||||||
|
effects.Add((effect, comp, statusComp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return effects != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,5 +4,6 @@ entity-category-name-objectives = Objectives
|
|||||||
entity-category-name-roles = Mind Roles
|
entity-category-name-roles = Mind Roles
|
||||||
entity-category-name-mapping = Mapping
|
entity-category-name-mapping = Mapping
|
||||||
entity-category-name-donotmap = Do not map
|
entity-category-name-donotmap = Do not map
|
||||||
|
entity-category-name-status-effects = Status Effects
|
||||||
|
|
||||||
entity-category-suffix-donotmap = DO NOT MAP
|
entity-category-suffix-donotmap = DO NOT MAP
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
- Electrocution
|
- Electrocution
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
- Drowsiness
|
|
||||||
- Adrenaline
|
- Adrenaline
|
||||||
- type: StandingState
|
- type: StandingState
|
||||||
- type: Tag
|
- type: Tag
|
||||||
|
|||||||
@@ -22,12 +22,10 @@
|
|||||||
- SlowedDown
|
- SlowedDown
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- ForcedSleep
|
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- Pacified
|
- Pacified
|
||||||
- Flashed
|
- Flashed
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
- Drowsiness
|
|
||||||
- Adrenaline
|
- Adrenaline
|
||||||
- type: Buckle
|
- type: Buckle
|
||||||
- type: StandingState
|
- type: StandingState
|
||||||
@@ -100,13 +98,11 @@
|
|||||||
- SlowedDown
|
- SlowedDown
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- ForcedSleep
|
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- Pacified
|
- Pacified
|
||||||
- StaminaModifier
|
- StaminaModifier
|
||||||
- Flashed
|
- Flashed
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
- Drowsiness
|
|
||||||
- Adrenaline
|
- Adrenaline
|
||||||
- type: Bloodstream
|
- type: Bloodstream
|
||||||
bloodMaxVolume: 150
|
bloodMaxVolume: 150
|
||||||
|
|||||||
@@ -103,11 +103,9 @@
|
|||||||
- SlowedDown
|
- SlowedDown
|
||||||
- Stutter
|
- Stutter
|
||||||
- Electrocution
|
- Electrocution
|
||||||
- ForcedSleep
|
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- Pacified
|
- Pacified
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
- Drowsiness
|
|
||||||
- Adrenaline
|
- Adrenaline
|
||||||
- type: Temperature
|
- type: Temperature
|
||||||
heatDamageThreshold: 800
|
heatDamageThreshold: 800
|
||||||
|
|||||||
@@ -130,13 +130,11 @@
|
|||||||
- RatvarianLanguage
|
- RatvarianLanguage
|
||||||
- PressureImmunity
|
- PressureImmunity
|
||||||
- Muted
|
- Muted
|
||||||
- ForcedSleep
|
|
||||||
- TemporaryBlindness
|
- TemporaryBlindness
|
||||||
- Pacified
|
- Pacified
|
||||||
- StaminaModifier
|
- StaminaModifier
|
||||||
- Flashed
|
- Flashed
|
||||||
- RadiationProtection
|
- RadiationProtection
|
||||||
- Drowsiness
|
|
||||||
- Adrenaline
|
- Adrenaline
|
||||||
- type: Body
|
- type: Body
|
||||||
prototype: Human
|
prototype: Human
|
||||||
|
|||||||
36
Resources/Prototypes/Entities/StatusEffects/misc.yml
Normal file
36
Resources/Prototypes/Entities/StatusEffects/misc.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
- type: entity
|
||||||
|
id: StatusEffectBase
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: StatusEffect
|
||||||
|
- type: Sprite
|
||||||
|
drawdepth: Effects
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HideContextMenu
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: StatusEffectBase
|
||||||
|
id: MobStatusEffectBase
|
||||||
|
abstract: true
|
||||||
|
components:
|
||||||
|
- type: StatusEffect
|
||||||
|
whitelist:
|
||||||
|
components:
|
||||||
|
- MobState
|
||||||
|
|
||||||
|
# The creature sleeps so heavily that nothing can wake him up. Not even its own death.
|
||||||
|
- type: entity
|
||||||
|
parent: MobStatusEffectBase
|
||||||
|
id: StatusEffectForcedSleeping
|
||||||
|
name: forced sleep
|
||||||
|
components:
|
||||||
|
- type: ForcedSleepingStatusEffect
|
||||||
|
|
||||||
|
# Blurs your vision and makes you randomly fall asleep
|
||||||
|
- type: entity
|
||||||
|
parent: MobStatusEffectBase
|
||||||
|
id: StatusEffectDrowsiness
|
||||||
|
name: drowsiness
|
||||||
|
components:
|
||||||
|
- type: DrowsinessStatusEffect
|
||||||
@@ -27,3 +27,8 @@
|
|||||||
id: DoNotMap
|
id: DoNotMap
|
||||||
name: entity-category-name-donotmap
|
name: entity-category-name-donotmap
|
||||||
suffix: entity-category-suffix-donotmap
|
suffix: entity-category-suffix-donotmap
|
||||||
|
|
||||||
|
- type: entityCategory
|
||||||
|
id: StatusEffects
|
||||||
|
name: entity-category-name-status-effects
|
||||||
|
hideSpawnMenu: true
|
||||||
@@ -2018,9 +2018,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.25
|
fizziness: 0.25
|
||||||
|
|
||||||
@@ -2049,9 +2049,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.15
|
fizziness: 0.15
|
||||||
|
|
||||||
@@ -2080,9 +2080,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.15
|
fizziness: 0.15
|
||||||
|
|
||||||
@@ -2111,9 +2111,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.25
|
fizziness: 0.25
|
||||||
|
|
||||||
@@ -2142,9 +2142,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.15
|
fizziness: 0.15
|
||||||
|
|
||||||
@@ -2173,9 +2173,9 @@
|
|||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
amount: 0.05
|
amount: 0.05
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
fizziness: 0.25
|
fizziness: 0.25
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 2.0
|
time: 2
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
@@ -105,9 +105,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 2.0
|
time: 2
|
||||||
type: Remove
|
type: Remove
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
@@ -161,9 +161,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 2.0
|
time: 2
|
||||||
type: Remove
|
type: Remove
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
@@ -342,9 +342,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 6
|
factor: 6
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 3.0
|
time: 3
|
||||||
type: Remove
|
type: Remove
|
||||||
Poison:
|
Poison:
|
||||||
effects:
|
effects:
|
||||||
@@ -383,9 +383,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 2.0
|
time: 2
|
||||||
type: Remove
|
type: Remove
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 1.0
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
@@ -80,9 +80,9 @@
|
|||||||
effects:
|
effects:
|
||||||
- !type:SatiateThirst
|
- !type:SatiateThirst
|
||||||
factor: 2
|
factor: 2
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 2.0
|
time: 2
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:AdjustReagent
|
- !type:AdjustReagent
|
||||||
reagent: Theobromine
|
reagent: Theobromine
|
||||||
|
|||||||
@@ -360,7 +360,7 @@
|
|||||||
shouldHave: false
|
shouldHave: false
|
||||||
walkSpeedModifier: 0.65
|
walkSpeedModifier: 0.65
|
||||||
sprintSpeedModifier: 0.65
|
sprintSpeedModifier: 0.65
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: NitrousOxide
|
reagent: NitrousOxide
|
||||||
@@ -368,8 +368,7 @@
|
|||||||
- !type:OrganType
|
- !type:OrganType
|
||||||
type: Slime
|
type: Slime
|
||||||
shouldHave: false
|
shouldHave: false
|
||||||
key: ForcedSleep
|
effectProto: StatusEffectForcedSleeping
|
||||||
component: ForcedSleeping
|
|
||||||
time: 3
|
time: 3
|
||||||
type: Add
|
type: Add
|
||||||
- !type:HealthChange
|
- !type:HealthChange
|
||||||
|
|||||||
@@ -83,9 +83,8 @@
|
|||||||
key: Jitter
|
key: Jitter
|
||||||
time: 3.0
|
time: 3.0
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
component: Drowsiness
|
|
||||||
time: 1.5
|
time: 1.5
|
||||||
type: Add
|
type: Add
|
||||||
refresh: false
|
refresh: false
|
||||||
@@ -923,8 +922,8 @@
|
|||||||
- !type:GenericStatusEffect
|
- !type:GenericStatusEffect
|
||||||
key: Stutter
|
key: Stutter
|
||||||
component: StutteringAccent
|
component: StutteringAccent
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 10
|
time: 10
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:ResetNarcolepsy
|
- !type:ResetNarcolepsy
|
||||||
@@ -948,8 +947,8 @@
|
|||||||
metabolisms:
|
metabolisms:
|
||||||
Medicine:
|
Medicine:
|
||||||
effects:
|
effects:
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 10
|
time: 10
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:ResetNarcolepsy
|
- !type:ResetNarcolepsy
|
||||||
@@ -1390,9 +1389,8 @@
|
|||||||
emote: Yawn
|
emote: Yawn
|
||||||
showInChat: true
|
showInChat: true
|
||||||
probability: 0.1
|
probability: 0.1
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
component: Drowsiness
|
|
||||||
time: 4
|
time: 4
|
||||||
type: Add
|
type: Add
|
||||||
refresh: false
|
refresh: false
|
||||||
|
|||||||
@@ -40,12 +40,12 @@
|
|||||||
key: KnockedDown
|
key: KnockedDown
|
||||||
time: 3
|
time: 3
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: Haloperidol
|
reagent: Haloperidol
|
||||||
max: 0.01
|
max: 0.01
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 10
|
time: 10
|
||||||
type: Remove
|
type: Remove
|
||||||
Medicine:
|
Medicine:
|
||||||
@@ -88,12 +88,12 @@
|
|||||||
key: KnockedDown
|
key: KnockedDown
|
||||||
time: 1
|
time: 1
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: Haloperidol
|
reagent: Haloperidol
|
||||||
max: 0.01
|
max: 0.01
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 10
|
time: 10
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:PopupMessage
|
- !type:PopupMessage
|
||||||
@@ -152,16 +152,16 @@
|
|||||||
component: StaminaModifier
|
component: StaminaModifier
|
||||||
time: 3
|
time: 3
|
||||||
type: Add
|
type: Add
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: ForcedSleep
|
effectProto: StatusEffectForcedSleeping
|
||||||
time: 3
|
time: 3
|
||||||
type: Remove
|
type: Remove
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: Haloperidol
|
reagent: Haloperidol
|
||||||
max: 0.01
|
max: 0.01
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
time: 10
|
time: 10
|
||||||
type: Remove
|
type: Remove
|
||||||
Medicine:
|
Medicine:
|
||||||
@@ -296,14 +296,13 @@
|
|||||||
metabolisms:
|
metabolisms:
|
||||||
Narcotic:
|
Narcotic:
|
||||||
effects:
|
effects:
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
conditions:
|
conditions:
|
||||||
- !type:ReagentThreshold
|
- !type:ReagentThreshold
|
||||||
reagent: Nocturine
|
reagent: Nocturine
|
||||||
min: 8
|
min: 8
|
||||||
key: ForcedSleep
|
effectProto: StatusEffectForcedSleeping
|
||||||
component: ForcedSleeping
|
time: 3
|
||||||
refresh: false
|
|
||||||
type: Add
|
type: Add
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
|
|||||||
@@ -63,9 +63,8 @@
|
|||||||
- !type:MovespeedModifier
|
- !type:MovespeedModifier
|
||||||
walkSpeedModifier: 0.65
|
walkSpeedModifier: 0.65
|
||||||
sprintSpeedModifier: 0.65
|
sprintSpeedModifier: 0.65
|
||||||
- !type:GenericStatusEffect
|
- !type:ModifyStatusEffect
|
||||||
key: Drowsiness
|
effectProto: StatusEffectDrowsiness
|
||||||
component: Drowsiness
|
|
||||||
time: 4
|
time: 4
|
||||||
type: Add
|
type: Add
|
||||||
refresh: false
|
refresh: false
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# Status effect prototypes.
|
# Status effect prototypes.
|
||||||
# Holds no actual logic, just some basic data about the effect.
|
# Holds no actual logic, just some basic data about the effect.
|
||||||
|
|
||||||
|
# Note: We have a new status effect system that needs all of these status effects to be fully ported to.
|
||||||
|
# Adding new status effects under the old system is NOT RECOMMENDED.
|
||||||
|
|
||||||
- type: statusEffect
|
- type: statusEffect
|
||||||
id: Stun
|
id: Stun
|
||||||
alert: Stun
|
alert: Stun
|
||||||
@@ -45,9 +48,6 @@
|
|||||||
id: Corporeal
|
id: Corporeal
|
||||||
alert: Corporeal
|
alert: Corporeal
|
||||||
|
|
||||||
- type: statusEffect
|
|
||||||
id: ForcedSleep #I.e., they will not wake on damage or similar
|
|
||||||
|
|
||||||
- type: statusEffect
|
- type: statusEffect
|
||||||
id: TemporaryBlindness
|
id: TemporaryBlindness
|
||||||
|
|
||||||
@@ -66,9 +66,6 @@
|
|||||||
- type: statusEffect
|
- type: statusEffect
|
||||||
id: RadiationProtection
|
id: RadiationProtection
|
||||||
|
|
||||||
- type: statusEffect
|
|
||||||
id: Drowsiness #blurs your vision and makes you randomly fall asleep
|
|
||||||
|
|
||||||
- type: statusEffect
|
- type: statusEffect
|
||||||
id: Adrenaline
|
id: Adrenaline
|
||||||
alert: Adrenaline
|
alert: Adrenaline
|
||||||
|
|||||||
Reference in New Issue
Block a user