using Content.Shared.Inventory;
using Content.Shared.Inventory.Events;
using Content.Shared.Item;
-using Content.Shared.Tag;
+using Robust.Shared.Containers;
using Robust.Shared.GameStates;
-using System.Linq;
namespace Content.Shared.Clothing.EntitySystems;
public abstract class ClothingSystem : EntitySystem
{
[Dependency] private readonly SharedItemSystem _itemSys = default!;
+ [Dependency] private readonly SharedContainerSystem _containerSys = default!;
[Dependency] private readonly SharedHumanoidAppearanceSystem _humanoidSystem = default!;
- [Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly InventorySystem _invSystem = default!;
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
- [ValidatePrototypeId<TagPrototype>]
- private const string HairTag = "HidesHair";
-
- [ValidatePrototypeId<TagPrototype>]
- private const string NoseTag = "HidesNose";
-
public override void Initialize()
{
base.Initialize();
}
}
- private void ToggleVisualLayer(EntityUid equipee, HumanoidVisualLayers layer, string tag)
+ private void ToggleVisualLayers(EntityUid equipee, HashSet<HumanoidVisualLayers> layers, HashSet<HumanoidVisualLayers> appearanceLayers)
{
- InventorySystem.InventorySlotEnumerator enumerator = _invSystem.GetSlotEnumerator(equipee, SlotFlags.HEAD ^ SlotFlags.MASK);
- bool shouldLayerShow = true;
-
- while (enumerator.NextItem(out EntityUid item))
+ foreach (HumanoidVisualLayers layer in layers)
{
- if (_tagSystem.HasTag(item, tag))
+ if (!appearanceLayers.Contains(layer))
+ break;
+
+ InventorySystem.InventorySlotEnumerator enumerator = _invSystem.GetSlotEnumerator(equipee);
+
+ bool shouldLayerShow = true;
+ while (enumerator.NextItem(out EntityUid item))
{
- if (tag == NoseTag) //Special check needs to be made for NoseTag, due to masks being toggleable
+ if (TryComp(item, out HideLayerClothingComponent? comp))
{
- if (TryComp(item, out MaskComponent? mask) && TryComp(item, out ClothingComponent? clothing))
+ //Checks for mask toggling. TODO: Make a generic system for this
+ if (comp.HideOnToggle && TryComp(item, out MaskComponent? mask) && TryComp(item, out ClothingComponent? clothing))
{
if (clothing.EquippedPrefix != mask.EquippedPrefix)
{
break;
}
}
- else
- {
- shouldLayerShow = false;
- break;
- }
}
+ _humanoidSystem.SetLayerVisibility(equipee, layer, shouldLayerShow);
}
- _humanoidSystem.SetLayerVisibility(equipee, layer, shouldLayerShow);
}
protected virtual void OnGotEquipped(EntityUid uid, ClothingComponent component, GotEquippedEvent args)
{
component.InSlot = args.Slot;
- if ((new string[] { "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, HairTag))
- ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag);
- if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag))
- ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag);
+ CheckEquipmentForLayerHide(args.Equipment, args.Equipee);
}
protected virtual void OnGotUnequipped(EntityUid uid, ClothingComponent component, GotUnequippedEvent args)
{
component.InSlot = null;
- if ((new string[] { "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, HairTag))
- ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Hair, HairTag);
- if ((new string[] { "mask", "head" }).Contains(args.Slot) && _tagSystem.HasTag(args.Equipment, NoseTag))
- ToggleVisualLayer(args.Equipee, HumanoidVisualLayers.Snout, NoseTag);
+ CheckEquipmentForLayerHide(args.Equipment, args.Equipee);
}
private void OnGetState(EntityUid uid, ClothingComponent component, ref ComponentGetState args)
{
args.State = new ClothingComponentState(component.EquippedPrefix);
+ if (component.InSlot != null && _containerSys.TryGetContainingContainer(uid, out var container))
+ {
+ CheckEquipmentForLayerHide(uid, container.Owner);
+ }
}
private void OnHandleState(EntityUid uid, ClothingComponent component, ref ComponentHandleState args)
{
if (args.Current is ClothingComponentState state)
+ {
SetEquippedPrefix(uid, state.EquippedPrefix, component);
+ if (component.InSlot != null && _containerSys.TryGetContainingContainer(uid, out var container))
+ {
+ CheckEquipmentForLayerHide(uid, container.Owner);
+ }
+ }
}
private void OnMaskToggled(Entity<ClothingComponent> ent, ref ItemMaskToggledEvent args)
{
//TODO: sprites for 'pulled down' state. defaults to invisible due to no sprite with this prefix
SetEquippedPrefix(ent, args.IsToggled ? args.equippedPrefix : null, ent);
- ToggleVisualLayer(args.Wearer, HumanoidVisualLayers.Snout, NoseTag);
+ CheckEquipmentForLayerHide(ent.Owner, args.Wearer);
}
private void OnEquipDoAfter(Entity<ClothingComponent> ent, ref ClothingEquipDoAfterEvent args)
_handsSystem.TryPickup(args.User, ent);
}
+ private void CheckEquipmentForLayerHide(EntityUid equipment, EntityUid equipee)
+ {
+ if (TryComp(equipment, out HideLayerClothingComponent? clothesComp) && TryComp(equipee, out HumanoidAppearanceComponent? appearanceComp))
+ ToggleVisualLayers(equipee, clothesComp.Slots, appearanceComp.HideLayersOnEquip);
+ }
+
#region Public API
public void SetEquippedPrefix(EntityUid uid, string? prefix, ClothingComponent? clothing = null)
tags:
- HamsterWearable
- WhitelistChameleon
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
+ hideOnToggle: true
- type: entity
parent: ClothingMaskGas
tags:
- ClownMask
- WhitelistChameleon
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskClownBase
- ClownMask
- HamsterWearable
- WhitelistChameleon
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskClown
sprite: Clothing/Mask/joy.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
tags:
- HamsterWearable
- WhitelistChameleon
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskPullableBase
- type: BreathMask
- type: IngestionBlocker
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
+ hideOnToggle: true
- type: entity
parent: ClothingMaskClownBase
- type: Tag
tags:
- WhitelistChameleon
- - HidesHair
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Hair
+ - Snout
+ hideOnToggle: true
- type: entity
parent: ClothingMaskGasExplorer
- type: Tag
tags:
- WhitelistChameleon
- - HidesHair
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Hair
+ - Snout
+ hideOnToggle: true
- type: entity
parent: ClothingMaskGasERT
tags:
- HamsterWearable
- WhitelistChameleon
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: IdentityBlocker
- type: entity
sprite: Clothing/Mask/fox.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
sprite: Clothing/Mask/bee.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
sprite: Clothing/Mask/bear.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
sprite: Clothing/Mask/raven.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
sprite: Clothing/Mask/jackal.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase
sprite: Clothing/Mask/bat.rsi
- type: BreathMask
- type: IdentityBlocker
- - type: Tag
- tags:
- - HidesNose
+ - type: HideLayerClothing
+ slots:
+ - Snout
- type: entity
parent: ClothingMaskBase