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:
@@ -46,6 +46,8 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
var query = EntityQueryEnumerator<StatusEffectComponent>();
|
||||
while (query.MoveNext(out var ent, out var effect))
|
||||
{
|
||||
TryApplyStatusEffect((ent, effect));
|
||||
|
||||
if (effect.EndEffectTime is null)
|
||||
continue;
|
||||
|
||||
@@ -88,9 +90,6 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
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)
|
||||
@@ -121,6 +120,29 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
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)
|
||||
{
|
||||
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="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="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>
|
||||
private bool TryAddStatusEffect(
|
||||
EntityUid target,
|
||||
EntProtoId effectProto,
|
||||
[NotNullWhen(true)] out EntityUid? statusEffect,
|
||||
TimeSpan? duration = null
|
||||
TimeSpan? duration = null,
|
||||
TimeSpan? delay = null
|
||||
)
|
||||
{
|
||||
statusEffect = null;
|
||||
@@ -177,7 +201,13 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -204,6 +234,28 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
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)
|
||||
{
|
||||
if (!_effectQuery.Resolve(effect, ref effect.Comp))
|
||||
@@ -233,7 +285,26 @@ public sealed partial class StatusEffectsSystem : EntitySystem
|
||||
var ev = new StatusEffectEndTimeUpdatedEvent(appliedTo, endTime);
|
||||
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>
|
||||
[ByRefEvent]
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user