Fix broken layer hiding on clothes with multiple equipment slots (#34080)

* Fix broken layer hiding on clothes with multiple equipment slots

* Refactor ToggleVisualLayers, HideLayerClothingComponent, and ClothingComponent to allow more
precise layer hide behavior and more CPU efficient layer toggling.

* Adjust HumanoidAppearaceSystem to track which slots are hiding a given layer (e.g. gas mask and welding mask)
Add documentation
Change gas masks to use the new HideLayerClothingComponent structure as an example of its usage

* Fix the delayed snout bug

* Misc cleanup

* Make `bool permanent` implicit from SlotFlags

any non-permanent visibility toggle with `SlotFlags.None` isn't supported with how its set up. And similarly, the slot flags argument does nothing if permanent = true. So IMO it makes more sense to infer it from a nullable arg.

* Split into separate system

Too much pasta

* Remove (hopefully unnecessary) refresh

* Fisk mask networking

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* Keep old behaviour, use clearer names?

I'm just guessing at what this was meant to do

* english

* Separate slot name & flag

* dirty = true

* fix comment

* Improved SetLayerVisibility with dirtying logic suggested by @ElectroJr

* Only set mask toggled if DisableOnFold is true

* FoldableClothingSystem fixes

* fix bandana state

* Better comment

---------

Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
This commit is contained in:
paige404
2025-03-20 09:30:47 -04:00
committed by GitHub
parent 65f393bb14
commit 2e7f01b99e
20 changed files with 370 additions and 184 deletions

View File

@@ -16,7 +16,8 @@ public sealed class FoldableClothingSystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<FoldableClothingComponent, FoldAttemptEvent>(OnFoldAttempt);
SubscribeLocalEvent<FoldableClothingComponent, FoldedEvent>(OnFolded);
SubscribeLocalEvent<FoldableClothingComponent, FoldedEvent>(OnFolded,
after: [typeof(MaskSystem)]); // Mask system also modifies clothing / equipment RSI state prefixes.
}
private void OnFoldAttempt(Entity<FoldableClothingComponent> ent, ref FoldAttemptEvent args)
@@ -24,10 +25,19 @@ public sealed class FoldableClothingSystem : EntitySystem
if (args.Cancelled)
return;
// allow folding while equipped if allowed slots are the same:
// e.g. flip a hat backwards while on your head
if (_inventorySystem.TryGetContainingSlot(ent.Owner, out var slot) &&
!ent.Comp.FoldedSlots.Equals(ent.Comp.UnfoldedSlots))
if (!_inventorySystem.TryGetContainingSlot(ent.Owner, out var slot))
return;
// Cannot fold clothing equipped to a slot if the slot becomes disallowed
var newSlots = args.Comp.IsFolded ? ent.Comp.UnfoldedSlots : ent.Comp.FoldedSlots;
if (newSlots != null && (newSlots.Value & slot.SlotFlags) != slot.SlotFlags)
{
args.Cancelled = true;
return;
}
// Setting hidden layers while equipped is not currently supported.
if (ent.Comp.FoldedHideLayers != null || ent.Comp.UnfoldedHideLayers != null)
args.Cancelled = true;
}
@@ -48,7 +58,14 @@ public sealed class FoldableClothingSystem : EntitySystem
if (ent.Comp.FoldedHeldPrefix != null)
_itemSystem.SetHeldPrefix(ent.Owner, ent.Comp.FoldedHeldPrefix, false, itemComp);
if (TryComp<HideLayerClothingComponent>(ent.Owner, out var hideLayerComp))
// This is janky and likely to lead to bugs.
// I.e., overriding this and resetting it again later will lead to bugs if someone tries to modify clothing
// in yaml, but doesn't realise theres actually two other fields on an unrelated component that they also need
// to modify.
// This should instead work via an event or something that gets raised to optionally modify the currently hidden layers.
// Or at the very least it should stash the old layers and restore them when unfolded.
// TODO CLOTHING fix this.
if (ent.Comp.FoldedHideLayers != null && TryComp<HideLayerClothingComponent>(ent.Owner, out var hideLayerComp))
hideLayerComp.Slots = ent.Comp.FoldedHideLayers;
}
@@ -63,7 +80,8 @@ public sealed class FoldableClothingSystem : EntitySystem
if (ent.Comp.FoldedHeldPrefix != null)
_itemSystem.SetHeldPrefix(ent.Owner, null, false, itemComp);
if (TryComp<HideLayerClothingComponent>(ent.Owner, out var hideLayerComp))
// TODO CLOTHING fix this.
if (ent.Comp.UnfoldedHideLayers != null && TryComp<HideLayerClothingComponent>(ent.Owner, out var hideLayerComp))
hideLayerComp.Slots = ent.Comp.UnfoldedHideLayers;
}