using Content.Shared.Actions; using Content.Shared.Bed.Components; using Content.Shared.Bed.Sleep; using Content.Shared.Body.Events; using Content.Shared.Body.Systems; using Content.Shared.Buckle.Components; using Content.Shared.Emag.Systems; using Content.Shared.Power; using Content.Shared.Power.EntitySystems; using Robust.Shared.Timing; using Robust.Shared.Utility; namespace Content.Shared.Bed; public abstract class SharedBedSystem : EntitySystem { [Dependency] protected readonly IGameTiming Timing = default!; [Dependency] private readonly ActionContainerSystem _actConts = default!; [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; [Dependency] private readonly EmagSystem _emag = default!; [Dependency] private readonly SharedMetabolizerSystem _metabolizer = default!; [Dependency] private readonly SharedPowerReceiverSystem _powerReceiver = default!; [Dependency] private readonly SleepingSystem _sleepingSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnHealMapInit); SubscribeLocalEvent(OnStrapped); SubscribeLocalEvent(OnUnstrapped); SubscribeLocalEvent(OnStasisStrapped); SubscribeLocalEvent(OnStasisUnstrapped); SubscribeLocalEvent(OnStasisEmagged); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnStasisGetMetabolicMultiplier); } private void OnHealMapInit(Entity ent, ref MapInitEvent args) { _actConts.EnsureAction(ent.Owner, ref ent.Comp.SleepAction, SleepingSystem.SleepActionId); Dirty(ent); } private void OnStrapped(Entity bed, ref StrappedEvent args) { EnsureComp(bed); bed.Comp.NextHealTime = Timing.CurTime + TimeSpan.FromSeconds(bed.Comp.HealTime); _actionsSystem.AddAction(args.Buckle, ref bed.Comp.SleepAction, SleepingSystem.SleepActionId, bed); Dirty(bed); // Single action entity, cannot strap multiple entities to the same bed. DebugTools.AssertEqual(args.Strap.Comp.BuckledEntities.Count, 1); } private void OnUnstrapped(Entity bed, ref UnstrappedEvent args) { // If the entity being unbuckled is terminating, we shouldn't try to act upon it, as some components may be gone if (!Terminating(args.Buckle.Owner)) { _actionsSystem.RemoveAction(args.Buckle.Owner, bed.Comp.SleepAction); _sleepingSystem.TryWaking(args.Buckle.Owner); } RemComp(bed); } private void OnStasisStrapped(Entity ent, ref StrappedEvent args) { EnsureComp(args.Buckle); _metabolizer.UpdateMetabolicMultiplier(args.Buckle); } private void OnStasisUnstrapped(Entity ent, ref UnstrappedEvent args) { RemComp(ent); _metabolizer.UpdateMetabolicMultiplier(args.Buckle); } private void OnStasisEmagged(Entity ent, ref GotEmaggedEvent args) { if (!_emag.CompareFlag(args.Type, EmagType.Interaction)) return; if (_emag.CheckFlag(ent, EmagType.Interaction)) return; ent.Comp.Multiplier = 1f / ent.Comp.Multiplier; UpdateMetabolisms(ent.Owner); Dirty(ent); args.Handled = true; } private void OnPowerChanged(Entity ent, ref PowerChangedEvent args) { UpdateMetabolisms(ent.Owner); } private void OnStasisGetMetabolicMultiplier(Entity ent, ref GetMetabolicMultiplierEvent args) { if (!TryComp(ent, out var buckle) || buckle.BuckledTo is not { } buckledTo) return; if (!TryComp(buckledTo, out var stasis)) return; if (!_powerReceiver.IsPowered(buckledTo)) return; args.Multiplier *= stasis.Multiplier; } protected void UpdateMetabolisms(Entity ent) { if (!Resolve(ent, ref ent.Comp, false)) return; foreach (var buckledEntity in ent.Comp.BuckledEntities) { _metabolizer.UpdateMetabolicMultiplier(buckledEntity); } } }