using System.Diagnostics.CodeAnalysis; using Content.Shared.Body.Components; using Content.Shared.Body.Events; using Content.Shared.Body.Organ; using Content.Shared.Body.Part; using Robust.Shared.Containers; namespace Content.Shared.Body.Systems; public partial class SharedBodySystem { private void AddOrgan(EntityUid uid, EntityUid bodyUid, EntityUid parentPartUid, OrganComponent component) { component.Body = bodyUid; RaiseLocalEvent(uid, new AddedToPartEvent(bodyUid)); if (component.Body != null) RaiseLocalEvent(uid, new AddedToPartInBodyEvent(component.Body.Value, parentPartUid)); Dirty(uid, component); } private void RemoveOrgan(EntityUid uid, EntityUid bodyUid, EntityUid parentPartUid, OrganComponent component) { RaiseLocalEvent(uid, new RemovedFromPartEvent(bodyUid)); if (component.Body != null) RaiseLocalEvent(uid, new RemovedFromPartInBodyEvent(component.Body.Value, parentPartUid)); component.Body = null; Dirty(uid, component); } /// /// Creates the specified organ slot on the parent entity. /// private OrganSlot? CreateOrganSlot(string slotId, EntityUid parent, BodyPartComponent? part = null) { if (!Resolve(parent, ref part, false)) return null; Containers.EnsureContainer(parent, GetOrganContainerId(slotId)); var slot = new OrganSlot(slotId); part.Organs.Add(slotId, slot); return slot; } /// /// Attempts to create the specified organ slot on the specified parent if it exists. /// public bool TryCreateOrganSlot( EntityUid? parent, string slotId, [NotNullWhen(true)] out OrganSlot? slot, BodyPartComponent? part = null) { slot = null; if (parent == null || !Resolve(parent.Value, ref part, false)) { return false; } Containers.EnsureContainer(parent.Value, GetOrganContainerId(slotId)); slot = new OrganSlot(slotId); return part.Organs.TryAdd(slotId,slot.Value); } /// /// Returns whether the slotId exists on the partId. /// public bool CanInsertOrgan(EntityUid partId, string slotId, BodyPartComponent? part = null) { return Resolve(partId, ref part) && part.Organs.ContainsKey(slotId); } /// /// Returns whether the specified organ slot exists on the partId. /// public bool CanInsertOrgan(EntityUid partId, OrganSlot slot, BodyPartComponent? part = null) { return CanInsertOrgan(partId, slot.Id, part); } public bool InsertOrgan(EntityUid partId, EntityUid organId, string slotId, BodyPartComponent? part = null, OrganComponent? organ = null) { if (!Resolve(organId, ref organ, false) || !Resolve(partId, ref part, false) || !CanInsertOrgan(partId, slotId, part)) { return false; } var containerId = GetOrganContainerId(slotId); if (!Containers.TryGetContainer(partId, containerId, out var container)) return false; return container.Insert(organId); } /// /// Removes the organ if it is inside of a body part. /// public bool RemoveOrgan(EntityUid organId, OrganComponent? organ = null) { if (!Containers.TryGetContainingContainer(organId, out var container)) return false; var parent = container.Owner; if (!HasComp(parent)) return false; return container.Remove(organId); } /// /// Tries to add this organ to any matching slot on this body part. /// public bool AddOrganToFirstValidSlot( EntityUid partId, EntityUid organId, BodyPartComponent? part = null, OrganComponent? organ = null) { if (!Resolve(partId, ref part, false) || !Resolve(organId, ref organ, false)) { return false; } foreach (var slotId in part.Organs.Keys) { InsertOrgan(partId, organId, slotId, part, organ); return true; } return false; } /// /// Returns a list of ValueTuples of and OrganComponent on each organ /// in the given body. /// /// The body entity id to check on. /// The body to check for organs on. /// The component to check for. public List<(T Comp, OrganComponent Organ)> GetBodyOrganComponents( EntityUid uid, BodyComponent? body = null) where T : Component { if (!Resolve(uid, ref body)) return new List<(T Comp, OrganComponent Organ)>(); var query = GetEntityQuery(); var list = new List<(T Comp, OrganComponent Organ)>(3); foreach (var organ in GetBodyOrgans(uid, body)) { if (query.TryGetComponent(organ.Id, out var comp)) list.Add((comp, organ.Component)); } return list; } /// /// Tries to get a list of ValueTuples of and OrganComponent on each organs /// in the given body. /// /// The body entity id to check on. /// The list of components. /// The body to check for organs on. /// The component to check for. /// Whether any were found. public bool TryGetBodyOrganComponents( EntityUid uid, [NotNullWhen(true)] out List<(T Comp, OrganComponent Organ)>? comps, BodyComponent? body = null) where T : Component { if (!Resolve(uid, ref body)) { comps = null; return false; } comps = GetBodyOrganComponents(uid, body); if (comps.Count != 0) return true; comps = null; return false; } }