/// </summary>
public static readonly CVarDef<bool> ICShowSSDIndicator =
CVarDef.Create("ic.show_ssd_indicator", true, CVar.CLIENTONLY);
+
+ /// <summary>
+ /// Forces SSD characters to sleep after ICSSDSleepTime seconds
+ /// </summary>
+ public static readonly CVarDef<bool> ICSSDSleep =
+ CVarDef.Create("ic.ssd_sleep", true, CVar.SERVER);
+
+ /// <summary>
+ /// Time between character getting SSD status and falling asleep
+ /// Won't work without ICSSDSleep
+ /// </summary>
+ public static readonly CVarDef<float> ICSSDSleepTime =
+ CVarDef.Create("ic.ssd_sleep_time", 600f, CVar.SERVER);
}
-using Content.Shared.StatusIcon;
+using Content.Shared.StatusIcon;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
/// Shows status icon when player in SSD
/// </summary>
[RegisterComponent, NetworkedComponent]
-[AutoGenerateComponentState]
+[AutoGenerateComponentState, AutoGenerateComponentPause]
public sealed partial class SSDIndicatorComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public ProtoId<SsdIconPrototype> Icon = "SSDIcon";
+
+ /// <summary>
+ /// When the entity should fall asleep
+ /// </summary>
+ [DataField, AutoPausedField, Access(typeof(SSDIndicatorSystem))]
+ public TimeSpan FallAsleepTime = TimeSpan.Zero;
+
+ /// <summary>
+ /// Required to don't remove forced sleep from other sources
+ /// </summary>
+ [ViewVariables(VVAccess.ReadWrite)]
+ [AutoNetworkedField]
+ public bool ForcedSleepAdded = false;
}
-using Robust.Shared.Player;
+using Content.Shared.Bed.Sleep;
+using Content.Shared.CCVar;
+using Robust.Shared.Configuration;
+using Robust.Shared.Player;
+using Robust.Shared.Timing;
namespace Content.Shared.SSDIndicator;
/// </summary>
public sealed class SSDIndicatorSystem : EntitySystem
{
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+
+ private bool _icSsdSleep;
+ private float _icSsdSleepTime;
+
public override void Initialize()
{
SubscribeLocalEvent<SSDIndicatorComponent, PlayerAttachedEvent>(OnPlayerAttached);
SubscribeLocalEvent<SSDIndicatorComponent, PlayerDetachedEvent>(OnPlayerDetached);
+ SubscribeLocalEvent<SSDIndicatorComponent, MapInitEvent>(OnMapInit);
+
+ _cfg.OnValueChanged(CCVars.ICSSDSleep, obj => _icSsdSleep = obj, true);
+ _cfg.OnValueChanged(CCVars.ICSSDSleepTime, obj => _icSsdSleepTime = obj, true);
}
private void OnPlayerAttached(EntityUid uid, SSDIndicatorComponent component, PlayerAttachedEvent args)
{
component.IsSSD = false;
+
+ // Removes force sleep and resets the time to zero
+ if (_icSsdSleep)
+ {
+ component.FallAsleepTime = TimeSpan.Zero;
+ if (component.ForcedSleepAdded) // Remove component only if it has been added by this system
+ {
+ EntityManager.RemoveComponent<ForcedSleepingComponent>(uid);
+ component.ForcedSleepAdded = false;
+ }
+ }
Dirty(uid, component);
}
private void OnPlayerDetached(EntityUid uid, SSDIndicatorComponent component, PlayerDetachedEvent args)
{
component.IsSSD = true;
+
+ // Sets the time when the entity should fall asleep
+ if (_icSsdSleep)
+ {
+ component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime);
+ }
Dirty(uid, component);
}
+
+ // Prevents mapped mobs to go to sleep immediately
+ private void OnMapInit(EntityUid uid, SSDIndicatorComponent component, MapInitEvent args)
+ {
+ if (_icSsdSleep &&
+ component.IsSSD &&
+ component.FallAsleepTime == TimeSpan.Zero)
+ {
+ component.FallAsleepTime = _timing.CurTime + TimeSpan.FromSeconds(_icSsdSleepTime);
+ }
+ }
+
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ if (!_icSsdSleep)
+ return;
+
+ var query = EntityQueryEnumerator<SSDIndicatorComponent>();
+
+ while (query.MoveNext(out var uid, out var ssd))
+ {
+ // Forces the entity to sleep when the time has come
+ if(ssd.IsSSD &&
+ ssd.FallAsleepTime <= _timing.CurTime &&
+ !TerminatingOrDeleted(uid) &&
+ !HasComp<ForcedSleepingComponent>(uid)) // Don't add the component if the entity has it from another sources
+ {
+ EnsureComp<ForcedSleepingComponent>(uid);
+ ssd.ForcedSleepAdded = true;
+ }
+ }
+ }
}