using System.Linq; using Content.Server.Body.Systems; using Content.Server.Hands.Systems; using Content.Server.Humanoid; using Content.Shared._Starlight.Medical.Body; using Content.Shared._Starlight.Medical.Limbs; using Content.Shared.Body.Components; using Content.Shared.Body.Part; using Content.Shared.Hands.Components; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Prototypes; using Content.Shared.Interaction.Components; using Content.Shared.Starlight; using Content.Shared.Starlight.Medical.Surgery; using Robust.Server.Containers; using Robust.Shared.Prototypes; namespace Content.Server._Starlight.Medical.Limbs; public sealed partial class LimbSystem : SharedLimbSystem { [Dependency] private readonly ContainerSystem _containers = default!; [Dependency] private readonly BodySystem _body = default!; [Dependency] private readonly HandsSystem _hands = default!; [Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearanceSystem = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; private readonly EntProtoId _virtual = "PartVirtual"; public override void Initialize() { base.Initialize(); } public bool AttachLimb(Entity body, string slot, Entity part, Entity limb) { if (!_body.AttachPart(part, slot, limb, part.Comp, limb.Comp)) return false; AddLimbVisual(body, limb); AddLimb(body, slot, limb); return true; } public bool AttachItem(EntityUid body, string slot, Entity part, Entity item) { var marker = EnsureComp(item); var virtualItem = Spawn(_virtual); var virtualBodyPart = EnsureComp(virtualItem); var virtualCustomLimb = EnsureComp(virtualItem); _metadata.SetEntityName(virtualItem, item.Comp.EntityName); marker.VirtualPart = virtualItem; virtualCustomLimb.Item = item; virtualBodyPart.PartType = BodyParts.GetBodyPart(slot); if (!_body.AttachPart(part, slot, virtualItem, part.Comp, virtualBodyPart)) { QueueDel(virtualItem); return false; } AddItemLimb(body, slot, item); AddItemHand(body, item, BodySystem.GetPartSlotContainerId(slot)); return true; } public void Amputatate(Entity body, Entity limb) { if (!_containers.TryGetContainingContainer((limb.Owner, limb.Comp1, limb.Comp2), out var container) || _body.GetParentPartAndSlotOrNull(limb.Owner) is not var (_, slotId) || !_containers.Remove(limb.Owner, container, destination: body.Comp1.Coordinates)) return; if (TryComp(limb, out var virtualLimb)) AmputateItemLimb((body, body.Comp1, body.Comp3), limb, slotId, virtualLimb); else { RemoveLimbVisual(body, limb); RemoveLimb(body, limb); } } private void AddItemLimb(EntityUid body, string slot, Entity item) { var layer = VisualLayers.GetLayer(slot); var vizualizer = EnsureComp(body); vizualizer.Layers[layer] = GetNetEntity(item); Dirty(body, vizualizer); } private void AmputateItemLimb(Entity body, Entity limb, string slotId, CustomLimbComponent virtualLimb) { RemoveItemLimb(body, virtualLimb.Item, BodySystem.GetPartSlotContainerId(slotId)); var vizualizer = EnsureComp(body); var layer = VisualLayers.GetLayer(slotId); vizualizer.Layers.Remove(layer); Dirty(body, vizualizer); QueueDel(limb.Owner); } private void AddItemHand(EntityUid bodyId, EntityUid itemId, string handId) { if (!TryComp(bodyId, out var hands)) return; if (!itemId.IsValid()) { Log.Debug("no valid item"); return; } _hands.AddHand((bodyId, hands), handId, HandLocation.Middle); _hands.DoPickup(bodyId, handId, itemId); EnsureComp(itemId); } private void RemoveItemLimb(EntityUid bodyId, EntityUid itemId, string handId) { if (!bodyId.IsValid() || !itemId.IsValid()) return; if (!TryComp(bodyId, out var hands) || !_hands.TryGetHand((bodyId, hands), handId, out var hand)) return; RemComp(itemId); _hands.DoDrop(itemId, handId); _hands.RemoveHand(bodyId, handId); } }