diff --git a/Content.Client/Clothing/ClientClothingSystem.cs b/Content.Client/Clothing/ClientClothingSystem.cs index e05732ed51..1472e807e6 100644 --- a/Content.Client/Clothing/ClientClothingSystem.cs +++ b/Content.Client/Clothing/ClientClothingSystem.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Numerics; using Content.Client.DisplacementMap; using Content.Client.Inventory; +using Content.Shared._Sunrise; using Content.Shared.Clothing; using Content.Shared.Clothing.Components; using Content.Shared.Clothing.EntitySystems; @@ -11,9 +12,11 @@ using Content.Shared.Humanoid; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; using Content.Shared.Item; +using Content.Shared.Tag; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.TypeSerializers.Implementations; using Robust.Shared.Utility; @@ -55,6 +58,8 @@ public sealed class ClientClothingSystem : ClothingSystem [Dependency] private readonly IResourceCache _cache = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly DisplacementMapSystem _displacement = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly TagSystem _tagSystem = default!; public override void Initialize() { @@ -108,6 +113,12 @@ public sealed class ClientClothingSystem : ClothingSystem List? layers = null; + if (TryComp(args.Equipee, out HumanoidAppearanceComponent? humanoid)) + { + var bodyTypeName = _prototype.Index(humanoid.BodyType).Name; + item.ClothingVisuals.TryGetValue($"{args.Slot}-{bodyTypeName}", out layers); + } + // first attempt to get species specific data. if (inventory.SpeciesId != null) item.ClothingVisuals.TryGetValue($"{args.Slot}-{inventory.SpeciesId}", out layers); @@ -116,7 +127,7 @@ public sealed class ClientClothingSystem : ClothingSystem if (layers == null && !item.ClothingVisuals.TryGetValue(args.Slot, out layers)) { // No generic data either. Attempt to generate defaults from the item's RSI & item-prefixes - if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, out layers)) + if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, args.Equipee, out layers)) return; } @@ -144,6 +155,7 @@ public sealed class ClientClothingSystem : ClothingSystem /// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility. /// private bool TryGetDefaultVisuals(EntityUid uid, ClothingComponent clothing, string slot, string? speciesId, + EntityUid target, [NotNullWhen(true)] out List? layers) { layers = null; @@ -171,6 +183,13 @@ public sealed class ClientClothingSystem : ClothingSystem if (clothing.EquippedState != null) state = $"{clothing.EquippedState}"; + if (TryComp(target, out HumanoidAppearanceComponent? humanoid)) + { + var bodyTypeName = _prototype.Index(humanoid.BodyType).Name; + if (rsi.TryGetState($"{state}-{bodyTypeName}", out _)) + state = $"{state}-{bodyTypeName}"; + } + // species specific if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _)) state = $"{state}-{speciesId}"; @@ -276,18 +295,42 @@ public sealed class ClientClothingSystem : ClothingSystem // Select displacement maps var displacementData = inventory.Displacements.GetValueOrDefault(slot); //Default unsexed map - var equipeeSex = CompOrNull(equipee)?.Sex; - if (equipeeSex != null) + string? bodyTypeName = null; + if (TryComp(equipee, out HumanoidAppearanceComponent? humanoid)) { - switch (equipeeSex) + bodyTypeName = _prototype.Index(humanoid.BodyType).Name; + + var hardsuitKey = $"hardsuit-{bodyTypeName}"; + + switch (humanoid.Sex) { case Sex.Male: if (inventory.MaleDisplacements.Count > 0) - displacementData = inventory.MaleDisplacements.GetValueOrDefault(slot); + { + displacementData = inventory.MaleDisplacements.GetValueOrDefault($"{slot}-{bodyTypeName}") + ?? inventory.MaleDisplacements.GetValueOrDefault(slot); + + if (_tagSystem.HasTag(equipment, "Hardsuit")) + { + displacementData = inventory.MaleDisplacements.GetValueOrDefault(hardsuitKey) + ?? inventory.Displacements.GetValueOrDefault(slot); + } + } + break; case Sex.Female: if (inventory.FemaleDisplacements.Count > 0) - displacementData = inventory.FemaleDisplacements.GetValueOrDefault(slot); + { + displacementData = inventory.FemaleDisplacements.GetValueOrDefault($"{slot}-{bodyTypeName}") + ?? inventory.FemaleDisplacements.GetValueOrDefault(slot); + + if (_tagSystem.HasTag(equipment, "Hardsuit")) + { + displacementData = inventory.FemaleDisplacements.GetValueOrDefault(hardsuitKey) + ?? inventory.FemaleDisplacements.GetValueOrDefault(slot); + } + } + break; } } @@ -334,7 +377,8 @@ public sealed class ClientClothingSystem : ClothingSystem if (displacementData is not null) { //Checking that the state is not tied to the current race. In this case we don't need to use the displacement maps. - if (layerData.State is not null && inventory.SpeciesId is not null && layerData.State.EndsWith(inventory.SpeciesId)) + if (layerData.State is not null && (inventory.SpeciesId is not null && layerData.State.EndsWith(inventory.SpeciesId) + || bodyTypeName is not null && layerData.State.EndsWith(bodyTypeName))) continue; if (_displacement.TryAddDisplacement(displacementData, sprite, index, key, revealedLayers)) diff --git a/Content.Client/Humanoid/HumanoidAppearanceSystem.cs b/Content.Client/Humanoid/HumanoidAppearanceSystem.cs index 262bedc523..ea3a5825cc 100644 --- a/Content.Client/Humanoid/HumanoidAppearanceSystem.cs +++ b/Content.Client/Humanoid/HumanoidAppearanceSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared._Sunrise; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.Humanoid.Prototypes; @@ -41,10 +42,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem var oldLayers = new HashSet(component.BaseLayers.Keys); component.BaseLayers.Clear(); - // add default species layers - var speciesProto = _prototypeManager.Index(component.Species); - var baseSprites = _prototypeManager.Index(speciesProto.SpriteSet); - foreach (var (key, id) in baseSprites.Sprites) + var bodyTypeProto = _prototypeManager.Index(component.BodyType); + foreach (var (key, id) in bodyTypeProto.Sprites) { oldLayers.Remove(key); if (!component.CustomBaseLayers.ContainsKey(key)) @@ -194,6 +193,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem humanoid.Sex = profile.Sex; humanoid.Gender = profile.Gender; humanoid.Age = profile.Age; + humanoid.BodyType = profile.BodyType; humanoid.Species = profile.Species; humanoid.SkinColor = profile.Appearance.SkinColor; humanoid.EyeColor = profile.Appearance.EyeColor; diff --git a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml index 68bb3eb262..c59af66693 100644 --- a/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml +++ b/Content.Client/Lobby/UI/HumanoidProfileEditor.xaml @@ -61,6 +61,13 @@ ToolTip="{Loc 'humanoid-profile-editor-guidebook-button-tooltip'}"/> + + + +