BedSystem.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using Content.Server.Actions;
  2. using Content.Server.Bed.Components;
  3. using Content.Server.Body.Systems;
  4. using Content.Server.Power.Components;
  5. using Content.Server.Power.EntitySystems;
  6. using Content.Shared.Bed;
  7. using Content.Shared.Bed.Sleep;
  8. using Content.Shared.Body.Components;
  9. using Content.Shared.Buckle.Components;
  10. using Content.Shared.Damage;
  11. using Content.Shared.Emag.Systems;
  12. using Content.Shared.Mobs.Systems;
  13. using Content.Shared.Power;
  14. using Robust.Shared.Timing;
  15. using Robust.Shared.Utility;
  16. namespace Content.Server.Bed
  17. {
  18. public sealed class BedSystem : EntitySystem
  19. {
  20. [Dependency] private readonly DamageableSystem _damageableSystem = default!;
  21. [Dependency] private readonly ActionsSystem _actionsSystem = default!;
  22. [Dependency] private readonly EmagSystem _emag = default!;
  23. [Dependency] private readonly SleepingSystem _sleepingSystem = default!;
  24. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  25. [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
  26. [Dependency] private readonly IGameTiming _timing = default!;
  27. public override void Initialize()
  28. {
  29. base.Initialize();
  30. SubscribeLocalEvent<HealOnBuckleComponent, StrappedEvent>(OnStrapped);
  31. SubscribeLocalEvent<HealOnBuckleComponent, UnstrappedEvent>(OnUnstrapped);
  32. SubscribeLocalEvent<StasisBedComponent, StrappedEvent>(OnStasisStrapped);
  33. SubscribeLocalEvent<StasisBedComponent, UnstrappedEvent>(OnStasisUnstrapped);
  34. SubscribeLocalEvent<StasisBedComponent, PowerChangedEvent>(OnPowerChanged);
  35. SubscribeLocalEvent<StasisBedComponent, GotEmaggedEvent>(OnEmagged);
  36. }
  37. private void OnStrapped(Entity<HealOnBuckleComponent> bed, ref StrappedEvent args)
  38. {
  39. EnsureComp<HealOnBuckleHealingComponent>(bed);
  40. bed.Comp.NextHealTime = _timing.CurTime + TimeSpan.FromSeconds(bed.Comp.HealTime);
  41. _actionsSystem.AddAction(args.Buckle, ref bed.Comp.SleepAction, SleepingSystem.SleepActionId, bed);
  42. // Single action entity, cannot strap multiple entities to the same bed.
  43. DebugTools.AssertEqual(args.Strap.Comp.BuckledEntities.Count, 1);
  44. }
  45. private void OnUnstrapped(Entity<HealOnBuckleComponent> bed, ref UnstrappedEvent args)
  46. {
  47. _actionsSystem.RemoveAction(args.Buckle, bed.Comp.SleepAction);
  48. _sleepingSystem.TryWaking(args.Buckle.Owner);
  49. RemComp<HealOnBuckleHealingComponent>(bed);
  50. }
  51. public override void Update(float frameTime)
  52. {
  53. base.Update(frameTime);
  54. var query = EntityQueryEnumerator<HealOnBuckleHealingComponent, HealOnBuckleComponent, StrapComponent>();
  55. while (query.MoveNext(out var uid, out _, out var bedComponent, out var strapComponent))
  56. {
  57. if (_timing.CurTime < bedComponent.NextHealTime)
  58. continue;
  59. bedComponent.NextHealTime += TimeSpan.FromSeconds(bedComponent.HealTime);
  60. if (strapComponent.BuckledEntities.Count == 0)
  61. continue;
  62. foreach (var healedEntity in strapComponent.BuckledEntities)
  63. {
  64. if (_mobStateSystem.IsDead(healedEntity))
  65. continue;
  66. var damage = bedComponent.Damage;
  67. if (HasComp<SleepingComponent>(healedEntity))
  68. damage *= bedComponent.SleepMultiplier;
  69. _damageableSystem.TryChangeDamage(healedEntity, damage, true, origin: uid);
  70. }
  71. }
  72. }
  73. private void UpdateAppearance(EntityUid uid, bool isOn)
  74. {
  75. _appearance.SetData(uid, StasisBedVisuals.IsOn, isOn);
  76. }
  77. private void OnStasisStrapped(Entity<StasisBedComponent> bed, ref StrappedEvent args)
  78. {
  79. if (!HasComp<BodyComponent>(args.Buckle) || !this.IsPowered(bed, EntityManager))
  80. return;
  81. var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.Buckle, bed.Comp.Multiplier, true);
  82. RaiseLocalEvent(args.Buckle, ref metabolicEvent);
  83. }
  84. private void OnStasisUnstrapped(Entity<StasisBedComponent> bed, ref UnstrappedEvent args)
  85. {
  86. if (!HasComp<BodyComponent>(args.Buckle) || !this.IsPowered(bed, EntityManager))
  87. return;
  88. var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.Buckle, bed.Comp.Multiplier, false);
  89. RaiseLocalEvent(args.Buckle, ref metabolicEvent);
  90. }
  91. private void OnPowerChanged(EntityUid uid, StasisBedComponent component, ref PowerChangedEvent args)
  92. {
  93. UpdateAppearance(uid, args.Powered);
  94. UpdateMetabolisms(uid, component, args.Powered);
  95. }
  96. private void OnEmagged(EntityUid uid, StasisBedComponent component, ref GotEmaggedEvent args)
  97. {
  98. if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
  99. return;
  100. if (_emag.CheckFlag(uid, EmagType.Interaction))
  101. return;
  102. // Reset any metabolisms first so they receive the multiplier correctly
  103. UpdateMetabolisms(uid, component, false);
  104. component.Multiplier = 1 / component.Multiplier;
  105. UpdateMetabolisms(uid, component, true);
  106. args.Handled = true;
  107. }
  108. private void UpdateMetabolisms(EntityUid uid, StasisBedComponent component, bool shouldApply)
  109. {
  110. if (!TryComp<StrapComponent>(uid, out var strap) || strap.BuckledEntities.Count == 0)
  111. return;
  112. foreach (var buckledEntity in strap.BuckledEntities)
  113. {
  114. var metabolicEvent = new ApplyMetabolicMultiplierEvent(buckledEntity, component.Multiplier, shouldApply);
  115. RaiseLocalEvent(buckledEntity, ref metabolicEvent);
  116. }
  117. }
  118. }
  119. }