using Content.Server.Storage.Components; using Content.Shared.Body.Components; using Content.Shared.Examine; using Content.Shared.Morgue; using Content.Shared.Morgue.Components; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; namespace Content.Server.Morgue; public sealed class MorgueSystem : EntitySystem { [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnExamine); } /// /// Handles the examination text for looking at a morgue. /// private void OnExamine(Entity ent, ref ExaminedEvent args) { if (!args.IsInDetailsRange) return; _appearance.TryGetData(ent.Owner, MorgueVisuals.Contents, out var contents); var text = contents switch { MorgueContents.HasSoul => "morgue-entity-storage-component-on-examine-details-body-has-soul", MorgueContents.HasContents => "morgue-entity-storage-component-on-examine-details-has-contents", MorgueContents.HasMob => "morgue-entity-storage-component-on-examine-details-body-has-no-soul", _ => "morgue-entity-storage-component-on-examine-details-empty" }; args.PushMarkup(Loc.GetString(text)); } /// /// Updates data periodically in case something died/got deleted in the morgue. /// private void CheckContents(EntityUid uid, MorgueComponent? morgue = null, EntityStorageComponent? storage = null, AppearanceComponent? app = null) { if (!Resolve(uid, ref morgue, ref storage, ref app)) return; if (storage.Contents.ContainedEntities.Count == 0) { _appearance.SetData(uid, MorgueVisuals.Contents, MorgueContents.Empty); return; } var hasMob = false; foreach (var ent in storage.Contents.ContainedEntities) { if (!hasMob && HasComp(ent)) hasMob = true; if (HasComp(ent)) { _appearance.SetData(uid, MorgueVisuals.Contents, MorgueContents.HasSoul, app); return; } } _appearance.SetData(uid, MorgueVisuals.Contents, hasMob ? MorgueContents.HasMob : MorgueContents.HasContents, app); } /// /// Handles the periodic beeping that morgues do when a live body is inside. /// public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp, out var storage, out var appearance)) { comp.AccumulatedFrameTime += frameTime; CheckContents(uid, comp, storage); if (comp.AccumulatedFrameTime < comp.BeepTime) continue; comp.AccumulatedFrameTime -= comp.BeepTime; if (comp.DoSoulBeep && _appearance.TryGetData(uid, MorgueVisuals.Contents, out var contents, appearance) && contents == MorgueContents.HasSoul) { _audio.PlayPvs(comp.OccupantHasSoulAlarmSound, uid); } } } }