diff --git a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs index 5fcefa170f5..08e7dc47f0b 100644 --- a/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs +++ b/Content.Shared/Body/Systems/SharedBodySystem.Parts.cs @@ -19,8 +19,6 @@ namespace Content.Shared.Body.Systems; public partial class SharedBodySystem { - [Dependency] private readonly SharedContainerSystem _containerSystem = default!; - [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly RandomHelperSystem _randomHelper = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; private void InitializeParts() @@ -40,6 +38,9 @@ private void OnMapInit(Entity ent, ref MapInitEvent args) { if (ent.Comp.PartType == BodyPartType.Torso) { + // For whatever reason this slot is initialized properly on the server, but not on the client. + // This seems to be an issue due to wiz-merge, on my old branch it was properly instantiating + // ItemInsertionSlot's container on both ends. It does show up properly on ItemSlotsComponent though. _slots.AddItemSlot(ent, ent.Comp.ContainerName, ent.Comp.ItemInsertionSlot); Dirty(ent, ent.Comp); } @@ -146,7 +147,7 @@ protected virtual void AddPart( var ev = new BodyPartAddedEvent(slotId, partEnt); RaiseLocalEvent(bodyEnt, ref ev); - + Logger.Debug($"Attempting to readd slot to {bodyEnt}"); AddLeg(partEnt, bodyEnt); } @@ -169,19 +170,7 @@ protected virtual void RemovePart( protected virtual void DropPart(Entity partEnt) { - // We check for whether or not the arm, leg or head is being dropped, in which case - // If theres just one, that means we'll remove the container slots. - if (partEnt.Comp.Body is not null - && TryGetPartSlotContainerName(partEnt.Comp.PartType, out var containerNames) - && GetBodyPartCount(partEnt.Comp.Body.Value, partEnt.Comp.PartType) == 1) - { - foreach (var containerName in containerNames) - { - _inventorySystem.SetSlotStatus(partEnt.Comp.Body.Value, containerName, true); - var ev = new RefreshInventorySlotsEvent(containerName); - RaiseLocalEvent(partEnt.Comp.Body.Value, ev); - } - } + ChangeSlotState(partEnt, true); // We then detach the part, which will kickstart EntRemovedFromContainer events. if (TryComp(partEnt, out TransformComponent? transform) && _gameTiming.IsFirstTimePredicted) @@ -232,7 +221,7 @@ private void RemovePartEffect(Entity partEnt, Entity partEnt) } } + /// + /// This function handles disabling or enabling equipment slots when an entity is + /// missing all of a given part type, or they get one added to them. + /// It is called right before dropping a part, or right after adding one. + /// + public void ChangeSlotState(Entity partEnt, bool disable) + { + if (partEnt.Comp.Body is not null) + Logger.Debug($"Attempting to change slot state to {disable} for {partEnt.Comp.PartType}. Number of parts: {GetBodyPartCount(partEnt.Comp.Body.Value, partEnt.Comp.PartType)}"); + if (partEnt.Comp.Body is not null + && GetBodyPartCount(partEnt.Comp.Body.Value, partEnt.Comp.PartType) == 1 + && TryGetPartSlotContainerName(partEnt.Comp.PartType, out var containerNames)) + { + Logger.Debug($"Found container names {containerNames}, with a number of {containerNames.Count}"); + foreach (var containerName in containerNames) + { + Logger.Debug($"Setting slot state to {disable} for {containerName}"); + _inventorySystem.SetSlotStatus(partEnt.Comp.Body.Value, containerName, disable); + var ev = new RefreshInventorySlotsEvent(containerName); + RaiseLocalEvent(partEnt.Comp.Body.Value, ev); + } + } + + } + private void DisablePart(Entity partEnt) { if (!TryComp(partEnt.Comp.Body, out BodyComponent? body)) @@ -881,10 +895,11 @@ public bool TryGetBodyPartOrganComponents( /// The part entity id to check on. /// The type of component to check for. /// The part to check for organs on. + /// The organs found on the body part. /// Whether any were found. /// /// This method is somewhat of a copout to the fact that we can't use reflection to generically - /// get the type of a component on runtime due to sandboxing. So we simply do a HasComp check for each organ. + /// get the type of component on runtime due to sandboxing. So we simply do a HasComp check for each organ. /// public bool TryGetBodyPartOrgans( EntityUid uid, diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index 014d6a869d4..1f685011e16 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -184,24 +184,26 @@ public void SetSlotStatus(EntityUid uid, string slotName, bool isDisabled, Inven { if (slot.Name != slotName) continue; - - - if (!TryGetSlotContainer(uid, slotName, out var container, out _, inventory)) - break; + Logger.Debug($"Found slot {slotName}, setting disabled to {isDisabled}"); if (isDisabled) { + if (!TryGetSlotContainer(uid, slotName, out var container, out _, inventory)) + break; + + Logger.Debug($"Dropping contents."); if (container.ContainedEntity is { } entityUid && TryComp(entityUid, out TransformComponent? transform) && _gameTiming.IsFirstTimePredicted) { _transform.AttachToGridOrMap(entityUid, transform); _randomHelper.RandomOffset(entityUid, 0.5f); } - _containerSystem.ShutdownContainer(container); + //_containerSystem.ShutdownContainer(container); } - else - _containerSystem.EnsureContainer(uid, slotName); - + //else + //_containerSystem.EnsureContainer(uid, slotName); + Logger.Debug($"Slot state before {slot.Disabled}"); slot.Disabled = isDisabled; + Logger.Debug($"Slot state after {slot.Disabled}"); break; } @@ -220,12 +222,12 @@ public struct InventorySlotEnumerator private int _nextIdx = 0; public static InventorySlotEnumerator Empty = new(Array.Empty(), Array.Empty()); - public InventorySlotEnumerator(InventoryComponent inventory, SlotFlags flags = SlotFlags.All) + public InventorySlotEnumerator(InventoryComponent inventory, SlotFlags flags = SlotFlags.All) : this(inventory.Slots, inventory.Containers, flags) { } - public InventorySlotEnumerator(SlotDefinition[] slots, ContainerSlot[] containers, SlotFlags flags = SlotFlags.All) + public InventorySlotEnumerator(SlotDefinition[] slots, ContainerSlot[] containers, SlotFlags flags = SlotFlags.All) { DebugTools.Assert(flags != SlotFlags.NONE); DebugTools.AssertEqual(slots.Length, containers.Length); diff --git a/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs b/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs index 6fe092eb7d8..f620dc9bd5c 100644 --- a/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs +++ b/Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs @@ -282,11 +282,14 @@ private void OnCavityStep(Entity ent, ref Surg private void OnCavityCheck(Entity ent, ref SurgeryStepCompleteCheckEvent args) { + // Normally this check would simply be partComp.ItemInsertionSlot.HasItem, but as mentioned before, + // For whatever reason it's not instantiating the field on the clientside after the wizmerge. if (!TryComp(args.Part, out BodyPartComponent? partComp) + || !TryComp(args.Part, out ItemSlotsComponent? itemComp) || ent.Comp.Action == "Insert" - && !partComp.ItemInsertionSlot.HasItem + && !itemComp.Slots[partComp.ContainerName].HasItem || ent.Comp.Action == "Remove" - && partComp.ItemInsertionSlot.HasItem) + && itemComp.Slots[partComp.ContainerName].HasItem) args.Cancelled = true; } @@ -306,6 +309,7 @@ private void OnAddPartStep(Entity ent, ref SurgeryS : removedComp.Part.ToString().ToLower(); _body.TryCreatePartSlot(args.Part, slotName, partComp.PartType, out var _); _body.AttachPart(args.Part, slotName, tool); + _body.ChangeSlotState((tool, partComp), false); } } } diff --git a/Resources/Prototypes/Entities/Debugging/debug_sweps.yml b/Resources/Prototypes/Entities/Debugging/debug_sweps.yml index e3289569a29..0430dbf427e 100644 --- a/Resources/Prototypes/Entities/Debugging/debug_sweps.yml +++ b/Resources/Prototypes/Entities/Debugging/debug_sweps.yml @@ -129,3 +129,51 @@ damage: types: Blunt: 200 + +- type: entity + name: bang severer + parent: BaseItem + id: MeleeDebugSever + description: sever yer parts a week from now + suffix: DEBUG + components: + - type: Tag + tags: + - Debug + - type: Sprite + sprite: Objects/Weapons/Melee/debug.rsi + state: icon + - type: MeleeWeapon + damage: + types: + Slash: 20000 + clickPartDamageMultiplier: 10 + - type: Item + size: Tiny + sprite: Objects/Weapons/Melee/debug.rsi + +- type: entity + name: bang severer 100dmg + parent: MeleeDebugSever + id: MeleeDebugSever100 + components: + - type: Tag + tags: + - Debug + - type: MeleeWeapon + damage: + types: + Slash: 100 + +- type: entity + name: bang severer 200dmg + parent: MeleeDebugSever + id: MeleeDebugSever200 + components: + - type: Tag + tags: + - Debug + - type: MeleeWeapon + damage: + types: + Slash: 200