Skip to content

Commit

Permalink
fixed part reattachment slots and cavity implant surgery
Browse files Browse the repository at this point in the history
  • Loading branch information
gluesniffler committed Oct 29, 2024
1 parent 57563a9 commit 3ea0335
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 30 deletions.
51 changes: 33 additions & 18 deletions Content.Shared/Body/Systems/SharedBodySystem.Parts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -40,6 +38,9 @@ private void OnMapInit(Entity<BodyPartComponent> 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);
}
Expand Down Expand Up @@ -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);
}

Expand All @@ -169,19 +170,7 @@ protected virtual void RemovePart(

protected virtual void DropPart(Entity<BodyPartComponent> 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)
Expand Down Expand Up @@ -232,7 +221,7 @@ private void RemovePartEffect(Entity<BodyPartComponent> partEnt, Entity<BodyComp
if (!Resolve(bodyEnt, ref bodyEnt.Comp, logMissing: false))
return;

if (partEnt.Comp.Children.Any())
if (partEnt.Comp.Children.Any())
{
foreach (var slotId in partEnt.Comp.Children.Keys)
{
Expand Down Expand Up @@ -305,6 +294,31 @@ private void EnablePart(Entity<BodyPartComponent> partEnt)
}
}

/// <summary>
/// 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.
/// </summary>
public void ChangeSlotState(Entity<BodyPartComponent> 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<BodyPartComponent> partEnt)
{
if (!TryComp(partEnt.Comp.Body, out BodyComponent? body))
Expand Down Expand Up @@ -881,10 +895,11 @@ public bool TryGetBodyPartOrganComponents<T>(
/// <param name="uid">The part entity id to check on.</param>
/// <param name="type">The type of component to check for.</param>
/// <param name="part">The part to check for organs on.</param>
/// <param name="organs">The organs found on the body part.</param>
/// <returns>Whether any were found.</returns>
/// <remarks>
/// 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.
/// </remarks>
public bool TryGetBodyPartOrgans(
EntityUid uid,
Expand Down
22 changes: 12 additions & 10 deletions Content.Shared/Inventory/InventorySystem.Slots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ContainerSlot>(uid, slotName);

//else
//_containerSystem.EnsureContainer<ContainerSlot>(uid, slotName);
Logger.Debug($"Slot state before {slot.Disabled}");
slot.Disabled = isDisabled;
Logger.Debug($"Slot state after {slot.Disabled}");
break;
}

Expand All @@ -220,12 +222,12 @@ public struct InventorySlotEnumerator
private int _nextIdx = 0;
public static InventorySlotEnumerator Empty = new(Array.Empty<SlotDefinition>(), Array.Empty<ContainerSlot>());

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);
Expand Down
8 changes: 6 additions & 2 deletions Content.Shared/Medical/Surgery/SharedSurgerySystem.Steps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,14 @@ private void OnCavityStep(Entity<SurgeryStepCavityEffectComponent> ent, ref Surg

private void OnCavityCheck(Entity<SurgeryStepCavityEffectComponent> 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;
}

Expand All @@ -306,6 +309,7 @@ private void OnAddPartStep(Entity<SurgeryAddPartStepComponent> 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);
}
}
}
Expand Down
48 changes: 48 additions & 0 deletions Resources/Prototypes/Entities/Debugging/debug_sweps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 3ea0335

Please sign in to comment.