Add a sleep delay to Nocturine (NewStatusEffect version) (#40231)
* Initial commit * Minor fix * Why is this uncommented here? Hmmm * No wait this can't be here, oops * Do better time * Also guidebook * Review changes * Add rejuvination, fix mispredicts
This commit is contained in:
@@ -14,6 +14,7 @@ using Content.Shared.Mobs;
|
|||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Pointing;
|
using Content.Shared.Pointing;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Rejuvenate;
|
||||||
using Content.Shared.Slippery;
|
using Content.Shared.Slippery;
|
||||||
using Content.Shared.Sound;
|
using Content.Shared.Sound;
|
||||||
using Content.Shared.Sound.Components;
|
using Content.Shared.Sound.Components;
|
||||||
@@ -57,7 +58,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, DamageChangedEvent>(OnDamageChanged);
|
SubscribeLocalEvent<SleepingComponent, DamageChangedEvent>(OnDamageChanged);
|
||||||
SubscribeLocalEvent<SleepingComponent, EntityZombifiedEvent>(OnZombified);
|
SubscribeLocalEvent<SleepingComponent, EntityZombifiedEvent>(OnZombified);
|
||||||
SubscribeLocalEvent<SleepingComponent, MobStateChangedEvent>(OnMobStateChanged);
|
SubscribeLocalEvent<SleepingComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||||
SubscribeLocalEvent<SleepingComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<SleepingComponent, ComponentInit>(OnCompInit);
|
||||||
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, PointAttemptEvent>(OnPointAttempt);
|
SubscribeLocalEvent<SleepingComponent, PointAttemptEvent>(OnPointAttempt);
|
||||||
@@ -68,6 +69,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<SleepingComponent, InteractHandEvent>(OnInteractHand);
|
||||||
SubscribeLocalEvent<SleepingComponent, StunEndAttemptEvent>(OnStunEndAttempt);
|
SubscribeLocalEvent<SleepingComponent, StunEndAttemptEvent>(OnStunEndAttempt);
|
||||||
SubscribeLocalEvent<SleepingComponent, StandUpAttemptEvent>(OnStandUpAttempt);
|
SubscribeLocalEvent<SleepingComponent, StandUpAttemptEvent>(OnStandUpAttempt);
|
||||||
|
SubscribeLocalEvent<SleepingComponent, RejuvenateEvent>(OnRejuvenate);
|
||||||
|
|
||||||
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
SubscribeLocalEvent<ForcedSleepingStatusEffectComponent, StatusEffectAppliedEvent>(OnStatusEffectApplied);
|
||||||
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
SubscribeLocalEvent<SleepingComponent, UnbuckleAttemptEvent>(OnUnbuckleAttempt);
|
||||||
@@ -133,7 +135,7 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
RemComp<SpamEmitSoundComponent>(ent);
|
RemComp<SpamEmitSoundComponent>(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(Entity<SleepingComponent> ent, ref MapInitEvent args)
|
private void OnCompInit(Entity<SleepingComponent> ent, ref ComponentInit args)
|
||||||
{
|
{
|
||||||
var ev = new SleepStateChangedEvent(true);
|
var ev = new SleepStateChangedEvent(true);
|
||||||
RaiseLocalEvent(ent, ref ev);
|
RaiseLocalEvent(ent, ref ev);
|
||||||
@@ -185,6 +187,11 @@ public sealed partial class SleepingSystem : EntitySystem
|
|||||||
args.Cancelled = true;
|
args.Cancelled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRejuvenate(Entity<SleepingComponent> ent, ref RejuvenateEvent args)
|
||||||
|
{
|
||||||
|
TryWaking((ent.Owner, ent.Comp), true);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
private void OnExamined(Entity<SleepingComponent> ent, ref ExaminedEvent args)
|
||||||
{
|
{
|
||||||
if (args.IsInDetailsRange)
|
if (args.IsInDetailsRange)
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ public sealed partial class ModifyStatusEffect : EntityEffect
|
|||||||
[DataField]
|
[DataField]
|
||||||
public float Time = 2.0f;
|
public float Time = 2.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay before the effect starts. If another effect is added with a shorter delay, it takes precedence.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public float Delay = 0f;
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// true - refresh status effect time (update to greater value), false - accumulate status effect time.
|
/// true - refresh status effect time (update to greater value), false - accumulate status effect time.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
@@ -45,22 +51,30 @@ public sealed partial class ModifyStatusEffect : EntityEffect
|
|||||||
{
|
{
|
||||||
case StatusEffectMetabolismType.Add:
|
case StatusEffectMetabolismType.Add:
|
||||||
if (Refresh)
|
if (Refresh)
|
||||||
statusSys.TryUpdateStatusEffectDuration(args.TargetEntity, EffectProto, duration);
|
statusSys.TryUpdateStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
|
||||||
else
|
else
|
||||||
statusSys.TryAddStatusEffectDuration(args.TargetEntity, EffectProto, duration);
|
statusSys.TryAddStatusEffectDuration(args.TargetEntity, EffectProto, duration, Delay > 0 ? TimeSpan.FromSeconds(Delay) : null);
|
||||||
break;
|
break;
|
||||||
case StatusEffectMetabolismType.Remove:
|
case StatusEffectMetabolismType.Remove:
|
||||||
statusSys.TryAddTime(args.TargetEntity, EffectProto, -duration);
|
statusSys.TryAddTime(args.TargetEntity, EffectProto, -duration);
|
||||||
break;
|
break;
|
||||||
case StatusEffectMetabolismType.Set:
|
case StatusEffectMetabolismType.Set:
|
||||||
statusSys.TrySetStatusEffectDuration(args.TargetEntity, EffectProto, duration);
|
statusSys.TrySetStatusEffectDuration(args.TargetEntity, EffectProto, duration, TimeSpan.FromSeconds(Delay));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) =>
|
||||||
=> Loc.GetString(
|
Delay > 0
|
||||||
|
? Loc.GetString(
|
||||||
|
"reagent-effect-guidebook-status-effect-delay",
|
||||||
|
("chance", Probability),
|
||||||
|
("type", Type),
|
||||||
|
("time", Time),
|
||||||
|
("key", prototype.Index(EffectProto).Name),
|
||||||
|
("delay", Delay))
|
||||||
|
: Loc.GetString(
|
||||||
"reagent-effect-guidebook-status-effect",
|
"reagent-effect-guidebook-status-effect",
|
||||||
("chance", Probability),
|
("chance", Probability),
|
||||||
("type", Type),
|
("type", Type),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Content.Shared.StatusEffectNew.Components;
|
|||||||
/// Marker component for all status effects - every status effect entity should have it.
|
/// 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.
|
/// 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(fieldDeltas: true), AutoGenerateComponentPause]
|
||||||
[Access(typeof(StatusEffectsSystem))]
|
[Access(typeof(StatusEffectsSystem))]
|
||||||
[EntityCategory("StatusEffects")]
|
[EntityCategory("StatusEffects")]
|
||||||
public sealed partial class StatusEffectComponent : Component
|
public sealed partial class StatusEffectComponent : Component
|
||||||
@@ -20,12 +20,24 @@ public sealed partial class StatusEffectComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public EntityUid? AppliedTo;
|
public EntityUid? AppliedTo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When this effect will start. Set to Timespan.Zero to start the effect immediately.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
|
||||||
|
public TimeSpan StartEffectTime;
|
||||||
|
|
||||||
/// <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>
|
||||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField, AutoNetworkedField]
|
||||||
public TimeSpan? EndEffectTime;
|
public TimeSpan? EndEffectTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, this status effect has been applied. Used to ensure that <see cref="StatusEffectAppliedEvent"/> only fires once.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool Applied;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whitelist, by which it is determined whether this status effect can be imposed on a particular entity.
|
/// Whitelist, by which it is determined whether this status effect can be imposed on a particular entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ public sealed partial class StatusEffectsSystem
|
|||||||
/// <param name="target">The target entity to which the effect should be added.</param>
|
/// <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="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="duration">Duration of status effect. Leave null and the effect will be permanent until it is removed using <c>TryRemoveStatusEffect</c>.</param>
|
||||||
|
/// <param name="delay">The delay of the effect. If a start time already exists, the closest time takes precedence. Leave null for the effect to be instant.</param>
|
||||||
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
||||||
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
||||||
public bool TryAddStatusEffectDuration(
|
public bool TryAddStatusEffectDuration(
|
||||||
EntityUid target,
|
EntityUid target,
|
||||||
EntProtoId effectProto,
|
EntProtoId effectProto,
|
||||||
[NotNullWhen(true)] out EntityUid? statusEffect,
|
[NotNullWhen(true)] out EntityUid? statusEffect,
|
||||||
TimeSpan duration
|
TimeSpan duration,
|
||||||
|
TimeSpan? delay = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (duration == TimeSpan.Zero)
|
if (duration == TimeSpan.Zero)
|
||||||
@@ -30,18 +32,19 @@ public sealed partial class StatusEffectsSystem
|
|||||||
|
|
||||||
// We check to make sure time is greater than zero here because sometimes you want to use TryAddStatusEffect to remove duration instead...
|
// We check to make sure time is greater than zero here because sometimes you want to use TryAddStatusEffect to remove duration instead...
|
||||||
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
||||||
return TryAddStatusEffect(target, effectProto, out statusEffect, duration);
|
return TryAddStatusEffect(target, effectProto, out statusEffect, duration, delay);
|
||||||
|
|
||||||
AddStatusEffectTime(statusEffect.Value, duration);
|
AddStatusEffectTime(statusEffect.Value, duration);
|
||||||
|
UpdateStatusEffectDelay(statusEffect.Value, delay);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///<inheritdoc cref="TryAddStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan)"/>
|
///<inheritdoc cref="TryAddStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan,TimeSpan?)"/>
|
||||||
public bool TryAddStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan duration)
|
public bool TryAddStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan duration, TimeSpan? delay = null)
|
||||||
{
|
{
|
||||||
return TryAddStatusEffectDuration(target, effectProto, out _, duration);
|
return TryAddStatusEffectDuration(target, effectProto, out _, duration, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,13 +54,15 @@ public sealed partial class StatusEffectsSystem
|
|||||||
/// <param name="target">The target entity to which the effect should be added.</param>
|
/// <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="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="duration">Duration of status effect. Leave null and the effect will be permanent until it is removed using <c>TryRemoveStatusEffect</c>.</param>
|
||||||
|
/// <param name="delay">The delay of the effect. If a start time already exists, the closest time takes precedence. Leave null for the effect to be instant.</param>
|
||||||
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
||||||
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
||||||
public bool TrySetStatusEffectDuration(
|
public bool TrySetStatusEffectDuration(
|
||||||
EntityUid target,
|
EntityUid target,
|
||||||
EntProtoId effectProto,
|
EntProtoId effectProto,
|
||||||
[NotNullWhen(true)] out EntityUid? statusEffect,
|
[NotNullWhen(true)] out EntityUid? statusEffect,
|
||||||
TimeSpan? duration = null
|
TimeSpan? duration = null,
|
||||||
|
TimeSpan? delay = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (duration <= TimeSpan.Zero)
|
if (duration <= TimeSpan.Zero)
|
||||||
@@ -67,17 +72,22 @@ public sealed partial class StatusEffectsSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
||||||
return TryAddStatusEffect(target, effectProto, out statusEffect, duration);
|
return TryAddStatusEffect(target, effectProto, out statusEffect, duration, delay);
|
||||||
|
|
||||||
SetStatusEffectEndTime(statusEffect.Value, duration);
|
if (!_effectQuery.TryComp(statusEffect, out var statusEffectComponent))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var endTime = delay == null || statusEffectComponent.Applied ? _timing.CurTime + duration : _timing.CurTime + delay + duration;
|
||||||
|
SetStatusEffectEndTime(statusEffect.Value, endTime);
|
||||||
|
UpdateStatusEffectDelay(statusEffect.Value, delay);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="TrySetStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?)"/>
|
/// <inheritdoc cref="TrySetStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?,TimeSpan?)"/>
|
||||||
public bool TrySetStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
public bool TrySetStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null, TimeSpan? delay = null)
|
||||||
{
|
{
|
||||||
return TrySetStatusEffectDuration(target, effectProto, out _, duration);
|
return TrySetStatusEffectDuration(target, effectProto, out _, duration, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -87,13 +97,15 @@ public sealed partial class StatusEffectsSystem
|
|||||||
/// <param name="target">The target entity to which the effect should be added.</param>
|
/// <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="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="duration">Duration of status effect. Leave null and the effect will be permanent until it is removed using <c>TryRemoveStatusEffect</c>.</param>
|
||||||
|
/// <param name="delay">The delay of the effect. If a start time already exists, the closest time takes precedence. Leave null for the effect to be instant.</param>
|
||||||
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if it doesn't exist.</param>
|
||||||
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
/// <returns>True if effect exists and its duration is set properly, false in case effect cannot be applied.</returns>
|
||||||
public bool TryUpdateStatusEffectDuration(
|
public bool TryUpdateStatusEffectDuration(
|
||||||
EntityUid target,
|
EntityUid target,
|
||||||
EntProtoId effectProto,
|
EntProtoId effectProto,
|
||||||
[NotNullWhen(true)] out EntityUid? statusEffect,
|
[NotNullWhen(true)] out EntityUid? statusEffect,
|
||||||
TimeSpan? duration = null
|
TimeSpan? duration = null,
|
||||||
|
TimeSpan? delay = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (duration <= TimeSpan.Zero)
|
if (duration <= TimeSpan.Zero)
|
||||||
@@ -103,17 +115,22 @@ public sealed partial class StatusEffectsSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
if (!TryGetStatusEffect(target, effectProto, out statusEffect))
|
||||||
return TryAddStatusEffect(target, effectProto, out statusEffect, duration);
|
return TryAddStatusEffect(target, effectProto, out statusEffect, duration, delay);
|
||||||
|
|
||||||
UpdateStatusEffectTime(statusEffect.Value, duration);
|
if (!_effectQuery.TryComp(statusEffect, out var statusEffectComponent))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var endTime = delay == null || statusEffectComponent.Applied ? duration : delay + duration;
|
||||||
|
UpdateStatusEffectTime(statusEffect.Value, endTime);
|
||||||
|
UpdateStatusEffectDelay(statusEffect.Value, delay);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="TryUpdateStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?)"/>
|
/// <inheritdoc cref="TryUpdateStatusEffectDuration(EntityUid,EntProtoId,out EntityUid?,TimeSpan?,TimeSpan?)"/>
|
||||||
public bool TryUpdateStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null)
|
public bool TryUpdateStatusEffectDuration(EntityUid target, EntProtoId effectProto, TimeSpan? duration = null, TimeSpan? delay = null)
|
||||||
{
|
{
|
||||||
return TryUpdateStatusEffectDuration(target, effectProto, out _, duration);
|
return TryUpdateStatusEffectDuration(target, effectProto, out _, duration, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -193,7 +210,7 @@ public sealed partial class StatusEffectsSystem
|
|||||||
public bool TryGetTime(
|
public bool TryGetTime(
|
||||||
EntityUid uid,
|
EntityUid uid,
|
||||||
EntProtoId effectProto,
|
EntProtoId effectProto,
|
||||||
out (EntityUid EffectEnt, TimeSpan? EndEffectTime) time,
|
out (EntityUid EffectEnt, TimeSpan? EndEffectTime, TimeSpan? StartEffectTime) time,
|
||||||
StatusEffectContainerComponent? container = null
|
StatusEffectContainerComponent? container = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -209,7 +226,7 @@ public sealed partial class StatusEffectsSystem
|
|||||||
if (!_effectQuery.TryComp(effect, out var effectComp))
|
if (!_effectQuery.TryComp(effect, out var effectComp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
time = (effect, effectComp.EndEffectTime);
|
time = (effect, effectComp.EndEffectTime, effectComp.StartEffectTime);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
var query = EntityQueryEnumerator<StatusEffectComponent>();
|
var query = EntityQueryEnumerator<StatusEffectComponent>();
|
||||||
while (query.MoveNext(out var ent, out var effect))
|
while (query.MoveNext(out var ent, out var effect))
|
||||||
{
|
{
|
||||||
|
TryApplyStatusEffect((ent, effect));
|
||||||
|
|
||||||
if (effect.EndEffectTime is null)
|
if (effect.EndEffectTime is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -88,9 +90,6 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
statusComp.AppliedTo = ent;
|
statusComp.AppliedTo = ent;
|
||||||
Dirty(args.Entity, statusComp);
|
Dirty(args.Entity, statusComp);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ev = new StatusEffectAppliedEvent(ent);
|
|
||||||
RaiseLocalEvent(args.Entity, ref ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEntityRemoved(Entity<StatusEffectContainerComponent> ent, ref EntRemovedFromContainerMessage args)
|
private void OnEntityRemoved(Entity<StatusEffectContainerComponent> ent, ref EntRemovedFromContainerMessage args)
|
||||||
@@ -121,6 +120,29 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
PredictedQueueDel(ent.Owner);
|
PredictedQueueDel(ent.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the status effect, i.e. starts it after it has been added. Ensures delayed start times trigger when they should.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="statusEffectEnt">The status effect entity.</param>
|
||||||
|
/// <returns>Returns true if the effect is applied.</returns>
|
||||||
|
private bool TryApplyStatusEffect(Entity<StatusEffectComponent> statusEffectEnt)
|
||||||
|
{
|
||||||
|
if (!statusEffectEnt.Comp.Applied &&
|
||||||
|
statusEffectEnt.Comp.AppliedTo != null &&
|
||||||
|
_timing.CurTime >= statusEffectEnt.Comp.StartEffectTime)
|
||||||
|
{
|
||||||
|
var ev = new StatusEffectAppliedEvent(statusEffectEnt.Comp.AppliedTo.Value);
|
||||||
|
RaiseLocalEvent(statusEffectEnt, ref ev);
|
||||||
|
|
||||||
|
statusEffectEnt.Comp.Applied = true;
|
||||||
|
|
||||||
|
DirtyField(statusEffectEnt, statusEffectEnt.Comp, nameof(StatusEffectComponent.StartEffectTime));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
public bool CanAddStatusEffect(EntityUid uid, EntProtoId effectProto)
|
||||||
{
|
{
|
||||||
if (!_proto.Resolve(effectProto, out var effectProtoData))
|
if (!_proto.Resolve(effectProto, out var effectProtoData))
|
||||||
@@ -148,12 +170,14 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
/// <param name="target">The target entity to which the effect should be added.</param>
|
/// <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="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="duration">Duration of status effect. Leave null and the effect will be permanent until it is removed using <c>TryRemoveStatusEffect</c>.</param>
|
||||||
|
/// <param name="delay">The delay of the effect. Leave null and the effect will be immediate.</param>
|
||||||
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if we couldn't create one.</param>
|
/// <param name="statusEffect">The EntityUid of the status effect we have just created or null if we couldn't create one.</param>
|
||||||
private bool TryAddStatusEffect(
|
private bool TryAddStatusEffect(
|
||||||
EntityUid target,
|
EntityUid target,
|
||||||
EntProtoId effectProto,
|
EntProtoId effectProto,
|
||||||
[NotNullWhen(true)] out EntityUid? statusEffect,
|
[NotNullWhen(true)] out EntityUid? statusEffect,
|
||||||
TimeSpan? duration = null
|
TimeSpan? duration = null,
|
||||||
|
TimeSpan? delay = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
statusEffect = null;
|
statusEffect = null;
|
||||||
@@ -177,7 +201,13 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
statusEffect = effect;
|
statusEffect = effect;
|
||||||
SetStatusEffectEndTime((effect.Value, effectComp), _timing.CurTime + duration);
|
|
||||||
|
var endTime = delay == null ? _timing.CurTime + duration : _timing.CurTime + delay + duration;
|
||||||
|
SetStatusEffectEndTime((effect.Value, effectComp), endTime);
|
||||||
|
var startTime = delay == null ? TimeSpan.Zero : _timing.CurTime + delay.Value;
|
||||||
|
SetStatusEffectStartTime(effect.Value, startTime);
|
||||||
|
|
||||||
|
TryApplyStatusEffect((effect.Value, effectComp));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -204,6 +234,28 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
SetStatusEffectEndTime(effect, newEndTime);
|
SetStatusEffectEndTime(effect, newEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateStatusEffectDelay(Entity<StatusEffectComponent?> effect, TimeSpan? delay)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.Resolve(effect, ref effect.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// It's already started!
|
||||||
|
if (_timing.CurTime >= effect.Comp.StartEffectTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var newStartTime = TimeSpan.Zero;
|
||||||
|
|
||||||
|
if (delay is not null)
|
||||||
|
{
|
||||||
|
// Don't update time to a smaller timespan...
|
||||||
|
newStartTime = _timing.CurTime + delay.Value;
|
||||||
|
if (effect.Comp.StartEffectTime < newStartTime)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetStatusEffectStartTime(effect, newStartTime);
|
||||||
|
}
|
||||||
|
|
||||||
private void AddStatusEffectTime(Entity<StatusEffectComponent?> effect, TimeSpan delta)
|
private void AddStatusEffectTime(Entity<StatusEffectComponent?> effect, TimeSpan delta)
|
||||||
{
|
{
|
||||||
if (!_effectQuery.Resolve(effect, ref effect.Comp))
|
if (!_effectQuery.Resolve(effect, ref effect.Comp))
|
||||||
@@ -233,7 +285,26 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
|||||||
var ev = new StatusEffectEndTimeUpdatedEvent(appliedTo, endTime);
|
var ev = new StatusEffectEndTimeUpdatedEvent(appliedTo, endTime);
|
||||||
RaiseLocalEvent(ent, ref ev);
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
Dirty(ent);
|
DirtyField(ent, ent.Comp, nameof(StatusEffectComponent.EndEffectTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStatusEffectStartTime(Entity<StatusEffectComponent?> ent, TimeSpan startTime)
|
||||||
|
{
|
||||||
|
if (!_effectQuery.Resolve(ent, ref ent.Comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.StartEffectTime == startTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.StartEffectTime = startTime;
|
||||||
|
|
||||||
|
if (ent.Comp.AppliedTo is not { } appliedTo)
|
||||||
|
return; // Not much we can do!
|
||||||
|
|
||||||
|
var ev = new StatusEffectStartTimeUpdatedEvent(appliedTo, startTime);
|
||||||
|
RaiseLocalEvent(ent, ref ev);
|
||||||
|
|
||||||
|
DirtyField(ent, ent.Comp, nameof(StatusEffectComponent.StartEffectTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,3 +333,11 @@ public record struct BeforeStatusEffectAddedEvent(EntProtoId Effect, bool Cancel
|
|||||||
/// <param name="EndTime">The new end time of the status effect, included for convenience.</param>
|
/// <param name="EndTime">The new end time of the status effect, included for convenience.</param>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct StatusEffectEndTimeUpdatedEvent(EntityUid Target, TimeSpan? EndTime);
|
public record struct StatusEffectEndTimeUpdatedEvent(EntityUid Target, TimeSpan? EndTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on an effect entity when its <see cref="StatusEffectComponent.StartEffectTime"/> is updated in any way.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Target">The entity the effect is attached to.</param>
|
||||||
|
/// <param name="StartTime">The new start time of the status effect, included for convenience.</param>
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct StatusEffectStartTimeUpdatedEvent(EntityUid Target, TimeSpan? StartTime);
|
||||||
|
|||||||
@@ -118,6 +118,22 @@ reagent-effect-guidebook-status-effect =
|
|||||||
} {NATURALFIXED($time, 3)} {MANY("second", $time)} of {LOC($key)}
|
} {NATURALFIXED($time, 3)} {MANY("second", $time)} of {LOC($key)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reagent-effect-guidebook-status-effect-delay =
|
||||||
|
{ $type ->
|
||||||
|
[add] { $chance ->
|
||||||
|
[1] Causes
|
||||||
|
*[other] cause
|
||||||
|
} {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} with accumulation
|
||||||
|
*[set] { $chance ->
|
||||||
|
[1] Causes
|
||||||
|
*[other] cause
|
||||||
|
} {LOC($key)} for at least {NATURALFIXED($time, 3)} {MANY("second", $time)} without accumulation
|
||||||
|
[remove]{ $chance ->
|
||||||
|
[1] Removes
|
||||||
|
*[other] remove
|
||||||
|
} {NATURALFIXED($time, 3)} {MANY("second", $time)} of {LOC($key)}
|
||||||
|
} after a {NATURALFIXED($delay, 3)} second delay
|
||||||
|
|
||||||
reagent-effect-guidebook-set-solution-temperature-effect =
|
reagent-effect-guidebook-set-solution-temperature-effect =
|
||||||
{ $chance ->
|
{ $chance ->
|
||||||
[1] Sets
|
[1] Sets
|
||||||
|
|||||||
@@ -304,6 +304,7 @@
|
|||||||
min: 8
|
min: 8
|
||||||
effectProto: StatusEffectForcedSleeping
|
effectProto: StatusEffectForcedSleeping
|
||||||
time: 3
|
time: 3
|
||||||
|
delay: 6
|
||||||
type: Add
|
type: Add
|
||||||
|
|
||||||
- type: reagent
|
- type: reagent
|
||||||
|
|||||||
Reference in New Issue
Block a user