refactor: rework the new status effect system to use containers (#38915)
This commit is contained in:
@@ -17,7 +17,7 @@ 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!;
|
private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
public override bool RequestScreenTexture => true;
|
public override bool RequestScreenTexture => true;
|
||||||
@@ -33,7 +33,7 @@ public sealed class DrowsinessOverlay : Overlay
|
|||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
_statusEffects = _sysMan.GetEntitySystem<SharedStatusEffectsSystem>();
|
_statusEffects = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||||
|
|
||||||
_drowsinessShader = _prototypeManager.Index(Shader).InstanceUnique();
|
_drowsinessShader = _prototypeManager.Index(Shader).InstanceUnique();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,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!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
private DrowsinessOverlay _overlay = default!;
|
private DrowsinessOverlay _overlay = default!;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public sealed class RainbowOverlay : 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!;
|
private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
public override bool RequestScreenTexture => true;
|
public override bool RequestScreenTexture => true;
|
||||||
@@ -41,7 +41,7 @@ public sealed class RainbowOverlay : Overlay
|
|||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
_statusEffects = _sysMan.GetEntitySystem<SharedStatusEffectsSystem>();
|
_statusEffects = _sysMan.GetEntitySystem<StatusEffectsSystem>();
|
||||||
|
|
||||||
_rainbowShader = _prototypeManager.Index(Shader).InstanceUnique();
|
_rainbowShader = _prototypeManager.Index(Shader).InstanceUnique();
|
||||||
_config.OnValueChanged(CCVars.ReducedMotion, OnReducedMotionChanged, invokeImmediately: true);
|
_config.OnValueChanged(CCVars.ReducedMotion, OnReducedMotionChanged, invokeImmediately: true);
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
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,4 +1,3 @@
|
|||||||
using Content.Server.StatusEffectNew;
|
|
||||||
using Content.Shared.Bed.Sleep;
|
using Content.Shared.Bed.Sleep;
|
||||||
using Content.Shared.Drowsiness;
|
using Content.Shared.Drowsiness;
|
||||||
using Content.Shared.StatusEffectNew;
|
using Content.Shared.StatusEffectNew;
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
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.StatusEffectNew;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Traits.Assorted;
|
namespace Content.Server.Traits.Assorted;
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ 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 _statusEffectOld = default!;
|
[Dependency] private readonly StatusEffect.StatusEffectsSystem _statusEffectOld = default!;
|
||||||
[Dependency] private readonly SharedStatusEffectsSystem _statusEffectNew = default!;
|
[Dependency] private readonly StatusEffectNew.StatusEffectsSystem _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";
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public sealed partial class ModifyStatusEffect : EntityEffect
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Effect(EntityEffectBaseArgs args)
|
public override void Effect(EntityEffectBaseArgs args)
|
||||||
{
|
{
|
||||||
var statusSys = args.EntityManager.EntitySysManager.GetEntitySystem<SharedStatusEffectsSystem>();
|
var statusSys = args.EntityManager.EntitySysManager.GetEntitySystem<StatusEffectsSystem>();
|
||||||
|
|
||||||
var time = Time;
|
var time = Time;
|
||||||
if (args is EntityEffectReagentArgs reagentArgs)
|
if (args is EntityEffectReagentArgs reagentArgs)
|
||||||
|
|||||||
@@ -16,7 +16,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!;
|
[Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
|
||||||
|
|
||||||
private bool _icSsdSleep;
|
private bool _icSsdSleep;
|
||||||
private float _icSsdSleepTime;
|
private float _icSsdSleepTime;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Robust.Shared.Utility;
|
|||||||
|
|
||||||
namespace Content.Shared.StatusEffect
|
namespace Content.Shared.StatusEffect
|
||||||
{
|
{
|
||||||
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem is required")]
|
||||||
public sealed class StatusEffectsSystem : EntitySystem
|
public sealed class StatusEffectsSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
@@ -106,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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()
|
||||||
@@ -126,7 +126,7 @@ namespace Content.Shared.StatusEffect
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Migration to Content.Shared.StatusEffectNew.SharedStatusEffectsSystem is required")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
{
|
{
|
||||||
@@ -166,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem is required")]
|
||||||
public bool TryAddStatusEffect(EntityUid uid,
|
public bool TryAddStatusEffect(EntityUid uid,
|
||||||
string key,
|
string key,
|
||||||
TimeSpan time,
|
TimeSpan time,
|
||||||
@@ -260,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
{
|
{
|
||||||
@@ -304,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem is required")]
|
||||||
public bool TryRemoveAllStatusEffects(EntityUid uid,
|
public bool TryRemoveAllStatusEffects(EntityUid uid,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -328,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem is required")]
|
||||||
public bool HasStatusEffect(EntityUid uid, string key,
|
public bool HasStatusEffect(EntityUid uid, string key,
|
||||||
StatusEffectsComponent? status = null)
|
StatusEffectsComponent? status = null)
|
||||||
{
|
{
|
||||||
@@ -346,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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
|
||||||
@@ -373,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
{
|
{
|
||||||
@@ -405,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
{
|
{
|
||||||
@@ -441,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
{
|
{
|
||||||
@@ -465,7 +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")]
|
[Obsolete("Migration to Content.Shared.StatusEffectNew.StatusEffectsSystem 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)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Content.Shared.Alert;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used in conjunction with <see cref="StatusEffectComponent"/> to display an alert when the status effect is present.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[EntityCategory("StatusEffects")]
|
||||||
|
public sealed partial class StatusEffectAlertComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Status effect indication for the player.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public ProtoId<AlertPrototype> Alert;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the status effect has a set end time and this is true, a duration
|
||||||
|
/// indicator will be displayed with the alert.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public bool ShowDuration = true;
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ namespace Content.Shared.StatusEffectNew.Components;
|
|||||||
/// Provides a link between the effect and the affected entity, and some data common to all status effects.
|
/// Provides a link between the effect and the affected entity, and some data common to all status effects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||||
[Access(typeof(SharedStatusEffectsSystem))]
|
[Access(typeof(StatusEffectsSystem))]
|
||||||
[EntityCategory("StatusEffects")]
|
[EntityCategory("StatusEffects")]
|
||||||
public sealed partial class StatusEffectComponent : Component
|
public sealed partial class StatusEffectComponent : Component
|
||||||
{
|
{
|
||||||
@@ -21,12 +21,6 @@ public sealed partial class StatusEffectComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntityUid? AppliedTo;
|
public EntityUid? AppliedTo;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Status effect indication for the player. If Null, no Alert will be displayed.
|
|
||||||
/// </summary>
|
|
||||||
[DataField]
|
|
||||||
public ProtoId<AlertPrototype>? Alert;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When this effect will end. If Null, the effect lasts indefinitely.
|
/// When this effect will end. If Null, the effect lasts indefinitely.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.StatusEffectNew.Components;
|
namespace Content.Shared.StatusEffectNew.Components;
|
||||||
|
|
||||||
@@ -9,15 +9,14 @@ namespace Content.Shared.StatusEffectNew.Components;
|
|||||||
/// Can be used for tracking currently applied status effects.
|
/// Can be used for tracking currently applied status effects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent, NetworkedComponent]
|
[RegisterComponent, NetworkedComponent]
|
||||||
[Access(typeof(SharedStatusEffectsSystem))]
|
[Access(typeof(StatusEffectsSystem))]
|
||||||
public sealed partial class StatusEffectContainerComponent : Component
|
public sealed partial class StatusEffectContainerComponent : Component
|
||||||
{
|
{
|
||||||
[DataField]
|
public const string ContainerId = "status-effects";
|
||||||
public HashSet<EntityUid> ActiveStatusEffects = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
/// <summary>
|
||||||
public sealed class StatusEffectContainerComponentState(HashSet<NetEntity> activeStatusEffects) : ComponentState
|
/// The actual container holding references to the active status effects
|
||||||
{
|
/// </summary>
|
||||||
public readonly HashSet<NetEntity> ActiveStatusEffects = activeStatusEffects;
|
[ViewVariables]
|
||||||
|
public Container? ActiveStatusEffects;
|
||||||
}
|
}
|
||||||
|
|||||||
62
Content.Shared/StatusEffectNew/StatusEffectAlertSystem.cs
Normal file
62
Content.Shared/StatusEffectNew/StatusEffectAlertSystem.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using Content.Shared.Alert;
|
||||||
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles displaying status effects that should show an alert, optionally with a duration.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class StatusEffectAlertSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||||
|
|
||||||
|
private EntityQuery<StatusEffectComponent> _effectQuery;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<StatusEffectAlertComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
|
SubscribeLocalEvent<StatusEffectAlertComponent, StatusEffectRemovedEvent>(OnStatusEffectRemoved);
|
||||||
|
SubscribeLocalEvent<StatusEffectAlertComponent, StatusEffectEndTimeUpdatedEvent>(OnEndTimeUpdated);
|
||||||
|
|
||||||
|
_effectQuery = GetEntityQuery<StatusEffectComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectApplied(Entity<StatusEffectAlertComponent> ent, ref StatusEffectAppliedEvent args)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.TryComp(ent, out var effectComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RefreshAlert(ent, args.Target, effectComp.EndEffectTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusEffectRemoved(Entity<StatusEffectAlertComponent> ent, ref StatusEffectRemovedEvent args)
|
||||||
|
{
|
||||||
|
_alerts.ClearAlert(args.Target, ent.Comp.Alert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEndTimeUpdated(Entity<StatusEffectAlertComponent> ent, ref StatusEffectEndTimeUpdatedEvent args)
|
||||||
|
{
|
||||||
|
RefreshAlert(ent, args.Target, args.EndTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshAlert(Entity<StatusEffectAlertComponent> ent, EntityUid target, TimeSpan? endTime)
|
||||||
|
{
|
||||||
|
(TimeSpan Start, TimeSpan End)? cooldown = null;
|
||||||
|
|
||||||
|
// Make sure the start time of the alert cooldown is still accurate
|
||||||
|
// This ensures the progress wheel doesn't "reset" every duration change.
|
||||||
|
if (ent.Comp.ShowDuration
|
||||||
|
&& endTime is not null
|
||||||
|
&& _alerts.TryGet(ent.Comp.Alert, out var alert))
|
||||||
|
{
|
||||||
|
_alerts.TryGetAlertState(target, alert.AlertKey, out var alertState);
|
||||||
|
cooldown = (alertState.Cooldown?.Item1 ?? _timing.CurTime, endTime.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_alerts.ShowAlert(target, ent.Comp.Alert, cooldown: cooldown);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ using Robust.Shared.Prototypes;
|
|||||||
|
|
||||||
namespace Content.Shared.StatusEffectNew;
|
namespace Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
public abstract partial class SharedStatusEffectsSystem
|
public sealed partial class StatusEffectsSystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Increments duration of status effect by <see cref="duration"/>.
|
/// Increments duration of status effect by <see cref="duration"/>.
|
||||||
@@ -103,29 +103,23 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool TryRemoveStatusEffect(EntityUid target, EntProtoId effectProto)
|
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))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(effect);
|
var meta = MetaData(effect);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
|
||||||
{
|
if (meta.EntityPrototype is null
|
||||||
if (!_effectQuery.TryComp(effect, out var effectComp))
|
|| meta.EntityPrototype != effectProto)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_effectQuery.HasComp(effect))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var ev = new StatusEffectRemovedEvent(target);
|
PredictedQueueDel(effect);
|
||||||
RaiseLocalEvent(effect, ref ev);
|
|
||||||
|
|
||||||
QueueDel(effect);
|
|
||||||
container.ActiveStatusEffects.Remove(effect);
|
|
||||||
Dirty(target, container);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -138,7 +132,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(target, out var container))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(effect);
|
var meta = MetaData(effect);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
@@ -157,7 +151,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(target, out var container))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var e in container.ActiveStatusEffects)
|
foreach (var e in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(e);
|
var meta = MetaData(e);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
@@ -188,7 +182,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!Resolve(uid, ref container))
|
if (!Resolve(uid, ref container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(effect);
|
var meta = MetaData(effect);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
@@ -218,7 +212,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!TryEffectsWithComp<T>(uid, out var status))
|
if (!TryEffectsWithComp<T>(uid, out var status))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
time.Item2 = TimeSpan.Zero;
|
time.EndEffectTime = TimeSpan.Zero;
|
||||||
|
|
||||||
foreach (var effect in status)
|
foreach (var effect in status)
|
||||||
{
|
{
|
||||||
@@ -228,7 +222,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effect.Comp2.EndEffectTime > time.Item2)
|
if (effect.Comp2.EndEffectTime > time.EndEffectTime)
|
||||||
time = (effect.Owner, effect.Comp2.EndEffectTime);
|
time = (effect.Owner, effect.Comp2.EndEffectTime);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -249,7 +243,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(uid, out var container))
|
if (!_containerQuery.TryComp(uid, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(effect);
|
var meta = MetaData(effect);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
@@ -273,7 +267,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(uid, out var container))
|
if (!_containerQuery.TryComp(uid, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
var meta = MetaData(effect);
|
var meta = MetaData(effect);
|
||||||
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
if (meta.EntityPrototype is not null && meta.EntityPrototype == effectProto)
|
||||||
@@ -293,7 +287,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(target, out var container))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
if (HasComp<T>(effect))
|
if (HasComp<T>(effect))
|
||||||
return true;
|
return true;
|
||||||
@@ -311,7 +305,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(target, out var container))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
if (!_effectQuery.TryComp(effect, out var statusComp))
|
if (!_effectQuery.TryComp(effect, out var statusComp))
|
||||||
continue;
|
continue;
|
||||||
@@ -338,7 +332,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
if (!_containerQuery.TryComp(target, out var container))
|
if (!_containerQuery.TryComp(target, out var container))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (var effect in container.ActiveStatusEffects)
|
foreach (var effect in container.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
if (!HasComp<T>(effect))
|
if (!HasComp<T>(effect))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ using Robust.Shared.Player;
|
|||||||
|
|
||||||
namespace Content.Shared.StatusEffectNew;
|
namespace Content.Shared.StatusEffectNew;
|
||||||
|
|
||||||
public abstract partial class SharedStatusEffectsSystem
|
public sealed partial class StatusEffectsSystem
|
||||||
{
|
{
|
||||||
protected void InitializeRelay()
|
private void InitializeRelay()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerAttachedEvent>(RelayStatusEffectEvent);
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
|
SubscribeLocalEvent<StatusEffectContainerComponent, LocalPlayerDetachedEvent>(RelayStatusEffectEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
|
private void RefRelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, ref T args) where T : struct
|
||||||
{
|
{
|
||||||
RelayEvent((uid, component), ref args);
|
RelayEvent((uid, component), ref args);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, T args) where T : class
|
private void RelayStatusEffectEvent<T>(EntityUid uid, StatusEffectContainerComponent component, T args) where T : class
|
||||||
{
|
{
|
||||||
RelayEvent((uid, component), args);
|
RelayEvent((uid, component), args);
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
{
|
{
|
||||||
// this copies the by-ref event if it is a struct
|
// this copies the by-ref event if it is a struct
|
||||||
var ev = new StatusEffectRelayedEvent<T>(args);
|
var ev = new StatusEffectRelayedEvent<T>(args);
|
||||||
foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects)
|
foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(activeEffect, ref ev);
|
RaiseLocalEvent(activeEffect, ref ev);
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ public abstract partial class SharedStatusEffectsSystem
|
|||||||
{
|
{
|
||||||
// this copies the by-ref event if it is a struct
|
// this copies the by-ref event if it is a struct
|
||||||
var ev = new StatusEffectRelayedEvent<T>(args);
|
var ev = new StatusEffectRelayedEvent<T>(args);
|
||||||
foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects)
|
foreach (var activeEffect in statusEffect.Comp.ActiveStatusEffects?.ContainedEntities ?? [])
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(activeEffect, ref ev);
|
RaiseLocalEvent(activeEffect, ref ev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Shared.Alert;
|
|
||||||
using Content.Shared.StatusEffectNew.Components;
|
using Content.Shared.StatusEffectNew.Components;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Network;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
@@ -13,15 +11,12 @@ namespace Content.Shared.StatusEffectNew;
|
|||||||
/// This system controls status effects, their lifetime, and provides an API for adding them to entities,
|
/// 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.
|
/// removing them from entities, or getting information about current effects on entities.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
public sealed partial class StatusEffectsSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _timing = default!;
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _proto = 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<StatusEffectContainerComponent> _containerQuery;
|
||||||
private EntityQuery<StatusEffectComponent> _effectQuery;
|
private EntityQuery<StatusEffectComponent> _effectQuery;
|
||||||
@@ -32,20 +27,15 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
|
|
||||||
InitializeRelay();
|
InitializeRelay();
|
||||||
|
|
||||||
SubscribeLocalEvent<StatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentInit>(OnStatusContainerInit);
|
||||||
SubscribeLocalEvent<StatusEffectComponent, StatusEffectRemovedEvent>(OnStatusEffectRemoved);
|
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentShutdown>(OnStatusContainerShutdown);
|
||||||
|
SubscribeLocalEvent<StatusEffectContainerComponent, EntInsertedIntoContainerMessage>(OnEntityInserted);
|
||||||
SubscribeLocalEvent<StatusEffectContainerComponent, ComponentGetState>(OnGetState);
|
SubscribeLocalEvent<StatusEffectContainerComponent, EntRemovedFromContainerMessage>(OnEntityRemoved);
|
||||||
|
|
||||||
_containerQuery = GetEntityQuery<StatusEffectContainerComponent>();
|
_containerQuery = GetEntityQuery<StatusEffectContainerComponent>();
|
||||||
_effectQuery = GetEntityQuery<StatusEffectComponent>();
|
_effectQuery = GetEntityQuery<StatusEffectComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGetState(Entity<StatusEffectContainerComponent> ent, ref ComponentGetState args)
|
|
||||||
{
|
|
||||||
args.State = new StatusEffectContainerComponentState(GetNetEntitySet(ent.Comp.ActiveStatusEffects));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
base.Update(frameTime);
|
||||||
@@ -70,15 +60,59 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddStatusEffectTime(EntityUid effect, TimeSpan delta)
|
private void OnStatusContainerInit(Entity<StatusEffectContainerComponent> ent, ref ComponentInit args)
|
||||||
{
|
{
|
||||||
if (!_effectQuery.TryComp(effect, out var effectComp))
|
ent.Comp.ActiveStatusEffects =
|
||||||
|
_container.EnsureContainer<Container>(ent, StatusEffectContainerComponent.ContainerId);
|
||||||
|
// We show the contents of the container to allow status effects to have visible sprites.
|
||||||
|
ent.Comp.ActiveStatusEffects.ShowContents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStatusContainerShutdown(Entity<StatusEffectContainerComponent> ent, ref ComponentShutdown args)
|
||||||
|
{
|
||||||
|
if (ent.Comp.ActiveStatusEffects is { } container)
|
||||||
|
_container.ShutdownContainer(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEntityInserted(Entity<StatusEffectContainerComponent> ent, ref EntInsertedIntoContainerMessage args)
|
||||||
|
{
|
||||||
|
if (args.Container.ID != StatusEffectContainerComponent.ContainerId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
effectComp.EndEffectTime += delta;
|
if (!TryComp<StatusEffectComponent>(args.Entity, out var statusComp))
|
||||||
Dirty(effect, effectComp);
|
return;
|
||||||
|
|
||||||
ShowAlertIfNeeded(effectComp);
|
// Make sure AppliedTo is set correctly so events can rely on it
|
||||||
|
if (statusComp.AppliedTo != ent)
|
||||||
|
{
|
||||||
|
statusComp.AppliedTo = ent;
|
||||||
|
Dirty(args.Entity, statusComp);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ev = new StatusEffectAppliedEvent(ent);
|
||||||
|
RaiseLocalEvent(args.Entity, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEntityRemoved(Entity<StatusEffectContainerComponent> ent, ref EntRemovedFromContainerMessage args)
|
||||||
|
{
|
||||||
|
if (args.Container.ID != StatusEffectContainerComponent.ContainerId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp<StatusEffectComponent>(args.Entity, out var statusComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ev = new StatusEffectRemovedEvent(ent);
|
||||||
|
RaiseLocalEvent(args.Entity, ref ev);
|
||||||
|
|
||||||
|
// Clear AppliedTo after events are handled so event handlers can use it.
|
||||||
|
if (statusComp.AppliedTo == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Why not just delete it? Well, that might end up being best, but this
|
||||||
|
// could theoretically allow for moving status effects from one entity
|
||||||
|
// to another. That might be good to have for polymorphs or something.
|
||||||
|
statusComp.AppliedTo = null;
|
||||||
|
Dirty(args.Entity, statusComp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetStatusEffectTime(EntityUid effect, TimeSpan? duration)
|
private void SetStatusEffectTime(EntityUid effect, TimeSpan? duration)
|
||||||
@@ -97,8 +131,6 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
effectComp.EndEffectTime = _timing.CurTime + duration;
|
effectComp.EndEffectTime = _timing.CurTime + duration;
|
||||||
|
|
||||||
Dirty(effect, effectComp);
|
Dirty(effect, effectComp);
|
||||||
|
|
||||||
ShowAlertIfNeeded(effectComp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateStatusEffectTime(EntityUid effect, TimeSpan? duration)
|
private void UpdateStatusEffectTime(EntityUid effect, TimeSpan? duration)
|
||||||
@@ -122,24 +154,6 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dirty(effect, effectComp);
|
Dirty(effect, effectComp);
|
||||||
|
|
||||||
ShowAlertIfNeeded(effectComp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void OnStatusEffectApplied(Entity<StatusEffectComponent> ent, ref StatusEffectAppliedEvent args)
|
|
||||||
{
|
|
||||||
StatusEffectComponent statusEffect = ent;
|
|
||||||
ShowAlertIfNeeded(statusEffect);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
private bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
||||||
@@ -147,7 +161,7 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
if (!_proto.TryIndex(effectProto, out var effectProtoData))
|
if (!_proto.TryIndex(effectProto, out var effectProtoData))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!effectProtoData.TryGetComponent<StatusEffectComponent>(out var effectProtoComp, _compFactory))
|
if (!effectProtoData.TryGetComponent<StatusEffectComponent>(out var effectProtoComp, Factory))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_whitelist.CheckBoth(uid, effectProtoComp.Blacklist, effectProtoComp.Whitelist))
|
if (!_whitelist.CheckBoth(uid, effectProtoComp.Blacklist, effectProtoComp.Whitelist))
|
||||||
@@ -181,43 +195,50 @@ public abstract partial class SharedStatusEffectsSystem : EntitySystem
|
|||||||
if (!CanAddStatusEffect(target, effectProto))
|
if (!CanAddStatusEffect(target, effectProto))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var container = EnsureComp<StatusEffectContainerComponent>(target);
|
EnsureComp<StatusEffectContainerComponent>(target);
|
||||||
|
|
||||||
|
// And only if all checks passed we spawn the effect
|
||||||
|
if (!PredictedTrySpawnInContainer(effectProto,
|
||||||
|
target,
|
||||||
|
StatusEffectContainerComponent.ContainerId,
|
||||||
|
out var effect))
|
||||||
|
return false;
|
||||||
|
|
||||||
//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))
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
statusEffect = effect;
|
statusEffect = effect;
|
||||||
|
SetStatusEffectEndTime((effect.Value, effectComp), _timing.CurTime + duration);
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowAlertIfNeeded(StatusEffectComponent effectComp)
|
private void AddStatusEffectTime(EntityUid effect, TimeSpan delta)
|
||||||
{
|
{
|
||||||
if (effectComp is { AppliedTo: not null, Alert: not null })
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
{
|
return;
|
||||||
(TimeSpan, TimeSpan)? cooldown = effectComp.EndEffectTime is null
|
|
||||||
? null
|
// If we don't have an end time set, we want to just make the status effect end in delta time from now.
|
||||||
: (_timing.CurTime, effectComp.EndEffectTime.Value);
|
SetStatusEffectEndTime((effect, effectComp), (effectComp.EndEffectTime ?? _timing.CurTime) + delta);
|
||||||
_alerts.ShowAlert(
|
|
||||||
effectComp.AppliedTo.Value,
|
|
||||||
effectComp.Alert.Value,
|
|
||||||
cooldown: cooldown
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetStatusEffectEndTime(Entity<StatusEffectComponent?> ent, TimeSpan? endTime)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.Resolve(ent, ref ent.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.EndEffectTime == endTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.EndEffectTime = endTime;
|
||||||
|
|
||||||
|
if (ent.Comp.AppliedTo is not { } appliedTo)
|
||||||
|
return; // Not much we can do!
|
||||||
|
|
||||||
|
var ev = new StatusEffectEndTimeUpdatedEvent(appliedTo, endTime);
|
||||||
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
|
Dirty(ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,3 +259,11 @@ public readonly record struct StatusEffectRemovedEvent(EntityUid Target);
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct BeforeStatusEffectAddedEvent(EntProtoId Effect, bool Cancelled = false);
|
public record struct BeforeStatusEffectAddedEvent(EntProtoId Effect, bool Cancelled = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on an effect entity when its <see cref="StatusEffectComponent.EndEffectTime"/> is updated in any way.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Target">The entity the effect is attached to.</param>
|
||||||
|
/// <param name="EndTime">The new end time of the status effect, included for convenience.</param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct StatusEffectEndTimeUpdatedEvent(EntityUid Target, TimeSpan? EndTime);
|
||||||
Reference in New Issue
Block a user