using System.Diagnostics.CodeAnalysis; using Content.Server.Body.Components; using Content.Server.GameTicking; using Content.Server.Kitchen.Components; using Content.Server.Mind.Components; using Content.Shared.Body.Components; using Content.Shared.MobState.Components; using Content.Shared.Movement.Events; using Robust.Shared.Timing; namespace Content.Server.Body.Systems { public sealed class BodySystem : EntitySystem { [Dependency] private readonly GameTicker _ticker = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnRelayMoveInput); SubscribeLocalEvent(OnApplyMetabolicMultiplier); SubscribeLocalEvent(OnBeingMicrowaved); SubscribeLocalEvent((_, c, _) => c.MapInitialize()); } private void OnRelayMoveInput(EntityUid uid, BodyComponent component, ref MoveInputEvent args) { if (EntityManager.TryGetComponent(uid, out var mobState) && mobState.IsDead() && EntityManager.TryGetComponent(uid, out var mind) && mind.HasMind) { if (!mind.Mind!.TimeOfDeath.HasValue) { mind.Mind.TimeOfDeath = _gameTiming.RealTime; } _ticker.OnGhostAttempt(mind.Mind!, true); } } private void OnApplyMetabolicMultiplier(EntityUid uid, BodyComponent component, ApplyMetabolicMultiplierEvent args) { foreach (var (part, _) in component.Parts) foreach (var mechanism in part.Mechanisms) { RaiseLocalEvent(mechanism.Owner, args, false); } } private void OnBeingMicrowaved(EntityUid uid, BodyComponent component, BeingMicrowavedEvent args) { if (args.Handled) return; // Don't microwave animals, kids Transform(uid).AttachToGridOrMap(); component.Gib(); args.Handled = true; } /// /// Returns a list of ValueTuples of and MechanismComponent on each mechanism /// in the given body. /// /// The entity to check for the component on. /// The body to check for mechanisms on. /// The component to check for. public List<(T Comp, MechanismComponent Mech)> GetComponentsOnMechanisms(EntityUid uid, SharedBodyComponent? body=null) where T : Component { if (!Resolve(uid, ref body)) return new(); var query = EntityManager.GetEntityQuery(); var list = new List<(T Comp, MechanismComponent Mech)>(3); foreach (var (part, _) in body.Parts) foreach (var mechanism in part.Mechanisms) { if (query.TryGetComponent(mechanism.Owner, out var comp)) list.Add((comp, mechanism)); } return list; } /// /// Tries to get a list of ValueTuples of and MechanismComponent on each mechanism /// in the given body. /// /// The entity to check for the component on. /// The list of components. /// The body to check for mechanisms on. /// The component to check for. /// Whether any were found. public bool TryGetComponentsOnMechanisms(EntityUid uid, [NotNullWhen(true)] out List<(T Comp, MechanismComponent Mech)>? comps, SharedBodyComponent? body=null) where T: Component { if (!Resolve(uid, ref body)) { comps = null; return false; } comps = GetComponentsOnMechanisms(uid, body); if (comps.Count == 0) { comps = null; return false; } return true; } } }