Files
wwdpublic/Content.Shared/_Shitmed/Body/Systems/SharedBodySystem.PartAppearance.cs
Spatison 2549ec061e [Feature] Body Types (#180)
* feature: body types

# Conflicts:
#	Content.Shared/Humanoid/Markings/MarkingManager.cs
#	Resources/Prototypes/Nyanotrasen/Species/Oni.yml
#	Resources/Prototypes/Nyanotrasen/Species/felinid.yml
#	Resources/Prototypes/Species/arachne.yml
#	Resources/Prototypes/Species/dwarf.yml
#	Resources/Prototypes/Species/harpy.yml
#	Resources/Prototypes/Species/human.yml
#	Resources/Prototypes/Species/ipc.yml
#	Resources/Textures/Clothing/OuterClothing/Armor/armor_reflec.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/bulletproof.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/cult_armour.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/heavy.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/heavygreen.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/heavyred.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/lingarmor.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/magusblue.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/magusred.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/riot.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/security.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Armor/security_slim.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Bio/virology.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/bomber.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/brigmedic.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/detective.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/gentlecoat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/jensencoat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_gene.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/labcoat_robo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/pirate.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Coats/windbreaker_paramedic.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/ERTSuits/ertengineer.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/ERTSuits/ertjanitor.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/ERTSuits/ertleader.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/ERTSuits/ertmedical.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/ERTSuits/ertsecurity.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/basic.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/capspace.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/cburn.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/cybersun.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/lingspacesuit.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/luxury.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/medical.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/paramed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/rd.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/salvage.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/spatio.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/syndicate.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/syndiecommander.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/syndieelite.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/wizard.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/apron.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/apronbotanist.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/apronchef.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/cardborg.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/chaplain_hoodie.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/chef.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/classicponcho.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/cultrobes.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/grey_hoodie.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/judge.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/plaguedoctorsuit.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/redwizard.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/santa.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/skubbody.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/straight_jacket.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/violetwizard.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Misc/wizard.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/atmos_firesuit.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/bombsuit.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/chicken.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/fire.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/monkey.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/rad.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/shrine-maiden.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Vests/mercwebvest.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Vests/vest.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Vests/webvest.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coat.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatatmos.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatbar.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcap.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcargo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatce.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcentcom.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatchef.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatchem.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatcmo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatengi.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatgen.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathop.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathos.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coathydro.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatjani.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatmime.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatminer.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatnomi.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatparamed.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatqm.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrd.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatrobo.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsci.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatsec.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatviro.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatwarden.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/WinterCoats/coatwardenarmored.rsi/meta.json

* feature: body types: 2

* add: loc

* fix: rsi validate

* tweak: displasment jumpsuit

* tweak: clean up

* tweak: displasment shoes

* tweak: displasment gloves

* tweak: clean up

* tweak: displasment outerClothing

* Revert "tweak: displasment outerClothing"

This reverts commit 698fd688591a6c00a4cd19eebac7a204dce18e98.

* fix

* fix

* fix

* fix

* tweak: dwarf, Oni and Felenid now can choose slim body type

* add: outer displacement

* some fix

* some fix

* no more tags shitcode

* Reptilian body type

* harpy body type

* some fix

* rsi validator fix

* Update ClientClothingSystem.cs

* Update Model.cs

* Update MarkingManager.cs

* Update ClientClothingSystem.cs

* Update reptilian.yml
2025-03-03 18:03:18 +02:00

208 lines
8.1 KiB
C#

using System.Diagnostics;
using System.Linq;
using Content.Shared._White.Humanoid.Prototypes;
using Content.Shared.Body.Components;
using Content.Shared.Body.Part;
using Content.Shared._Shitmed.Body.Events;
using Content.Shared._Shitmed.Body.Part;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Humanoid.Prototypes;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
namespace Content.Shared.Body.Systems;
public partial class SharedBodySystem
{
[Dependency] private readonly SharedHumanoidAppearanceSystem _humanoid = default!;
[Dependency] private readonly MarkingManager _markingManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private void InitializePartAppearances()
{
base.Initialize();
SubscribeLocalEvent<BodyPartAppearanceComponent, ComponentStartup>(OnPartAppearanceStartup);
SubscribeLocalEvent<BodyPartAppearanceComponent, AfterAutoHandleStateEvent>(HandleState);
SubscribeLocalEvent<BodyComponent, BodyPartAddedEvent>(OnPartAttachedToBody);
SubscribeLocalEvent<BodyComponent, BodyPartRemovedEvent>(OnPartDroppedFromBody);
}
private void OnPartAppearanceStartup(EntityUid uid, BodyPartAppearanceComponent component, ComponentStartup args)
{
if (!TryComp(uid, out BodyPartComponent? part)
|| part.ToHumanoidLayers() is not { } relevantLayer)
return;
if (part.BaseLayerId != null)
{
component.ID = part.BaseLayerId;
component.Type = relevantLayer;
return;
}
if (part.Body is not { Valid: true } body
|| !TryComp(body, out HumanoidAppearanceComponent? bodyAppearance))
return;
var customLayers = bodyAppearance.CustomBaseLayers;
var spriteLayers = bodyAppearance.BaseLayers;
component.Type = relevantLayer;
part.Species = bodyAppearance.Species;
if (customLayers.ContainsKey(component.Type))
{
component.ID = customLayers[component.Type].Id;
component.Color = customLayers[component.Type].Color;
}
else if (spriteLayers.ContainsKey(component.Type))
{
component.ID = spriteLayers[component.Type].ID;
component.Color = bodyAppearance.SkinColor;
}
else
{
component.ID = CreateIdFromPart(bodyAppearance, relevantLayer);
component.Color = bodyAppearance.SkinColor;
}
// I HATE HARDCODED CHECKS I HATE HARDCODED CHECKS I HATE HARDCODED CHECKS
if (part.PartType == BodyPartType.Head)
component.EyeColor = bodyAppearance.EyeColor;
var markingsByLayer = new Dictionary<HumanoidVisualLayers, List<Marking>>();
foreach (var layer in HumanoidVisualLayersExtension.Sublayers(relevantLayer))
{
var category = MarkingCategoriesConversion.FromHumanoidVisualLayers(layer);
if (bodyAppearance.MarkingSet.Markings.TryGetValue(category, out var markingList))
markingsByLayer[layer] = markingList.Select(m => new Marking(m.MarkingId, m.MarkingColors.ToList())).ToList();
}
component.Markings = markingsByLayer;
}
private string? CreateIdFromPart(HumanoidAppearanceComponent bodyAppearance, HumanoidVisualLayers part)
{
var bodyType = _prototypeManager.Index<BodyTypePrototype>(bodyAppearance.BodyType); // WD EDIT
if (!bodyType.Sprites.ContainsKey(part)) // WD EDIT
return null;
return HumanoidVisualLayersExtension.GetSexMorph(part, bodyAppearance.Sex, bodyType.Sprites[part]); // WD EDIT
}
public void ModifyMarkings(EntityUid uid,
Entity<BodyPartAppearanceComponent?> partAppearance,
HumanoidAppearanceComponent bodyAppearance,
HumanoidVisualLayers targetLayer,
string markingId,
bool remove = false)
{
if (!Resolve(partAppearance, ref partAppearance.Comp))
return;
if (!remove)
{
if (!_markingManager.Markings.TryGetValue(markingId, out var prototype))
return;
var markingColors = MarkingColoring.GetMarkingLayerColors(
prototype,
bodyAppearance.SkinColor,
bodyAppearance.EyeColor,
bodyAppearance.MarkingSet
);
var marking = new Marking(markingId, markingColors);
_humanoid.SetLayerVisibility(uid, targetLayer, true, true, bodyAppearance);
_humanoid.AddMarking(uid, markingId, markingColors, true, true, bodyAppearance);
if (!partAppearance.Comp.Markings.ContainsKey(targetLayer))
partAppearance.Comp.Markings[targetLayer] = new List<Marking>();
partAppearance.Comp.Markings[targetLayer].Add(marking);
}
//else
//RemovePartMarkings(uid, component, bodyAppearance);
}
private void HandleState(EntityUid uid, BodyPartAppearanceComponent component, ref AfterAutoHandleStateEvent args) =>
ApplyPartMarkings(uid, component);
private void OnPartAttachedToBody(EntityUid uid, BodyComponent component, ref BodyPartAddedEvent args)
{
if (!TryComp(args.Part, out BodyPartAppearanceComponent? partAppearance)
|| !TryComp(uid, out HumanoidAppearanceComponent? bodyAppearance))
return;
if (partAppearance.ID != null)
_humanoid.SetBaseLayerId(uid, partAppearance.Type, partAppearance.ID, sync: true, bodyAppearance);
UpdateAppearance(uid, partAppearance);
}
private void OnPartDroppedFromBody(EntityUid uid, BodyComponent component, ref BodyPartRemovedEvent args)
{
if (TerminatingOrDeleted(uid)
|| TerminatingOrDeleted(args.Part)
|| !TryComp(uid, out HumanoidAppearanceComponent? bodyAppearance))
return;
// We check for this conditional here since some entities may not have a profile... If they dont
// have one, and their part is gibbed, the markings will not be removed or applied properly.
if (!HasComp<BodyPartAppearanceComponent>(args.Part))
EnsureComp<BodyPartAppearanceComponent>(args.Part);
if (TryComp<BodyPartAppearanceComponent>(args.Part, out var partAppearance))
RemoveAppearance(uid, partAppearance, args.Part);
}
protected void UpdateAppearance(EntityUid target,
BodyPartAppearanceComponent component)
{
if (!TryComp(target, out HumanoidAppearanceComponent? bodyAppearance))
return;
if (component.EyeColor != null)
{
bodyAppearance.EyeColor = component.EyeColor.Value;
_humanoid.SetLayerVisibility(target, HumanoidVisualLayers.Eyes, true, true, bodyAppearance);
}
if (component.Color != null)
_humanoid.SetBaseLayerColor(target, component.Type, component.Color, true, bodyAppearance);
_humanoid.SetLayerVisibility(target, component.Type, true, true, bodyAppearance);
foreach (var (visualLayer, markingList) in component.Markings)
{
_humanoid.SetLayerVisibility(target, visualLayer, true, true, bodyAppearance);
foreach (var marking in markingList)
{
_humanoid.AddMarking(target, marking.MarkingId, marking.MarkingColors, true, true, bodyAppearance);
}
}
Dirty(target, bodyAppearance);
}
protected void RemoveAppearance(EntityUid entity, BodyPartAppearanceComponent component, EntityUid partEntity)
{
if (!TryComp(entity, out HumanoidAppearanceComponent? bodyAppearance))
return;
foreach (var (visualLayer, markingList) in component.Markings)
{
_humanoid.SetLayerVisibility(entity, visualLayer, false, true, bodyAppearance);
}
RemoveBodyMarkings(entity, component, bodyAppearance);
}
protected abstract void ApplyPartMarkings(EntityUid target, BodyPartAppearanceComponent component);
protected abstract void RemoveBodyMarkings(EntityUid target, BodyPartAppearanceComponent partAppearance, HumanoidAppearanceComponent bodyAppearance);
}