1
0

CrematoriumSystem.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using Content.Server.Ghost;
  2. using Content.Server.Morgue.Components;
  3. using Content.Server.Storage.Components;
  4. using Content.Server.Storage.EntitySystems;
  5. using Content.Shared.Database;
  6. using Content.Shared.Examine;
  7. using Content.Shared.IdentityManagement;
  8. using Content.Shared.Interaction.Events;
  9. using Content.Shared.Mind;
  10. using Content.Shared.Morgue;
  11. using Content.Shared.Popups;
  12. using Content.Shared.Standing;
  13. using Content.Shared.Storage;
  14. using Content.Shared.Storage.Components;
  15. using Content.Shared.Verbs;
  16. using Robust.Shared.Audio.Systems;
  17. using Robust.Shared.Containers;
  18. using Robust.Shared.Player;
  19. namespace Content.Server.Morgue;
  20. public sealed class CrematoriumSystem : EntitySystem
  21. {
  22. [Dependency] private readonly SharedAudioSystem _audio = default!;
  23. [Dependency] private readonly SharedAppearanceSystem _appearance = default!;
  24. [Dependency] private readonly GhostSystem _ghostSystem = default!;
  25. [Dependency] private readonly EntityStorageSystem _entityStorage = default!;
  26. [Dependency] private readonly SharedPopupSystem _popup = default!;
  27. [Dependency] private readonly StandingStateSystem _standing = default!;
  28. [Dependency] private readonly SharedMindSystem _minds = default!;
  29. [Dependency] private readonly SharedContainerSystem _containers = default!;
  30. public override void Initialize()
  31. {
  32. base.Initialize();
  33. SubscribeLocalEvent<CrematoriumComponent, ExaminedEvent>(OnExamine);
  34. SubscribeLocalEvent<CrematoriumComponent, GetVerbsEvent<AlternativeVerb>>(AddCremateVerb);
  35. SubscribeLocalEvent<CrematoriumComponent, SuicideByEnvironmentEvent>(OnSuicideByEnvironment);
  36. SubscribeLocalEvent<ActiveCrematoriumComponent, StorageOpenAttemptEvent>(OnAttemptOpen);
  37. }
  38. private void OnExamine(EntityUid uid, CrematoriumComponent component, ExaminedEvent args)
  39. {
  40. if (!TryComp<AppearanceComponent>(uid, out var appearance))
  41. return;
  42. using (args.PushGroup(nameof(CrematoriumComponent)))
  43. {
  44. if (_appearance.TryGetData<bool>(uid, CrematoriumVisuals.Burning, out var isBurning, appearance) &&
  45. isBurning)
  46. {
  47. args.PushMarkup(Loc.GetString("crematorium-entity-storage-component-on-examine-details-is-burning",
  48. ("owner", uid)));
  49. }
  50. if (_appearance.TryGetData<bool>(uid, StorageVisuals.HasContents, out var hasContents, appearance) &&
  51. hasContents)
  52. {
  53. args.PushMarkup(Loc.GetString("crematorium-entity-storage-component-on-examine-details-has-contents"));
  54. }
  55. else
  56. {
  57. args.PushMarkup(Loc.GetString("crematorium-entity-storage-component-on-examine-details-empty"));
  58. }
  59. }
  60. }
  61. private void OnAttemptOpen(EntityUid uid, ActiveCrematoriumComponent component, ref StorageOpenAttemptEvent args)
  62. {
  63. args.Cancelled = true;
  64. }
  65. private void AddCremateVerb(EntityUid uid, CrematoriumComponent component, GetVerbsEvent<AlternativeVerb> args)
  66. {
  67. if (!TryComp<EntityStorageComponent>(uid, out var storage))
  68. return;
  69. if (!args.CanAccess || !args.CanInteract || args.Hands == null || storage.Open)
  70. return;
  71. if (HasComp<ActiveCrematoriumComponent>(uid))
  72. return;
  73. AlternativeVerb verb = new()
  74. {
  75. Text = Loc.GetString("cremate-verb-get-data-text"),
  76. // TODO VERB ICON add flame/burn symbol?
  77. Act = () => TryCremate(uid, component, storage),
  78. Impact = LogImpact.Medium // could be a body? or evidence? I dunno.
  79. };
  80. args.Verbs.Add(verb);
  81. }
  82. public bool Cremate(EntityUid uid, CrematoriumComponent? component = null, EntityStorageComponent? storage = null)
  83. {
  84. if (!Resolve(uid, ref component, ref storage))
  85. return false;
  86. if (HasComp<ActiveCrematoriumComponent>(uid))
  87. return false;
  88. _audio.PlayPvs(component.CremateStartSound, uid);
  89. _appearance.SetData(uid, CrematoriumVisuals.Burning, true);
  90. _audio.PlayPvs(component.CrematingSound, uid);
  91. AddComp<ActiveCrematoriumComponent>(uid);
  92. return true;
  93. }
  94. public bool TryCremate(EntityUid uid, CrematoriumComponent? component = null, EntityStorageComponent? storage = null)
  95. {
  96. if (!Resolve(uid, ref component, ref storage))
  97. return false;
  98. if (storage.Open || storage.Contents.ContainedEntities.Count < 1)
  99. return false;
  100. return Cremate(uid, component, storage);
  101. }
  102. private void FinishCooking(EntityUid uid, CrematoriumComponent component, EntityStorageComponent? storage = null)
  103. {
  104. if (!Resolve(uid, ref storage))
  105. return;
  106. _appearance.SetData(uid, CrematoriumVisuals.Burning, false);
  107. RemComp<ActiveCrematoriumComponent>(uid);
  108. if (storage.Contents.ContainedEntities.Count > 0)
  109. {
  110. for (var i = storage.Contents.ContainedEntities.Count - 1; i >= 0; i--)
  111. {
  112. var item = storage.Contents.ContainedEntities[i];
  113. _containers.Remove(item, storage.Contents);
  114. EntityManager.DeleteEntity(item);
  115. }
  116. var ash = Spawn("Ash", Transform(uid).Coordinates);
  117. _containers.Insert(ash, storage.Contents);
  118. }
  119. _entityStorage.OpenStorage(uid, storage);
  120. _audio.PlayPvs(component.CremateFinishSound, uid);
  121. }
  122. private void OnSuicideByEnvironment(EntityUid uid, CrematoriumComponent component, SuicideByEnvironmentEvent args)
  123. {
  124. if (args.Handled)
  125. return;
  126. var victim = args.Victim;
  127. if (TryComp(victim, out ActorComponent? actor) && _minds.TryGetMind(victim, out var mindId, out var mind))
  128. {
  129. _ghostSystem.OnGhostAttempt(mindId, false, mind: mind);
  130. if (mind.OwnedEntity is { Valid: true } entity)
  131. {
  132. _popup.PopupEntity(Loc.GetString("crematorium-entity-storage-component-suicide-message"), entity);
  133. }
  134. }
  135. _popup.PopupEntity(Loc.GetString("crematorium-entity-storage-component-suicide-message-others",
  136. ("victim", Identity.Entity(victim, EntityManager))),
  137. victim, Filter.PvsExcept(victim), true, PopupType.LargeCaution);
  138. if (_entityStorage.CanInsert(victim, uid))
  139. {
  140. _entityStorage.CloseStorage(uid);
  141. _standing.Down(victim, false);
  142. _entityStorage.Insert(victim, uid);
  143. }
  144. else
  145. {
  146. EntityManager.DeleteEntity(victim);
  147. }
  148. _entityStorage.CloseStorage(uid);
  149. Cremate(uid, component);
  150. args.Handled = true;
  151. }
  152. public override void Update(float frameTime)
  153. {
  154. base.Update(frameTime);
  155. var query = EntityQueryEnumerator<ActiveCrematoriumComponent, CrematoriumComponent>();
  156. while (query.MoveNext(out var uid, out var act, out var crem))
  157. {
  158. act.Accumulator += frameTime;
  159. if (act.Accumulator >= crem.CookTime)
  160. FinishCooking(uid, crem);
  161. }
  162. }
  163. }