From 24485c39eeb41a30e6d7c8ec2a0fe69dfc20e021 Mon Sep 17 00:00:00 2001 From: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Date: Mon, 6 Jul 2026 00:17:17 +0200 Subject: [PATCH] Change dwarves to use displacement maps instead of sprite scaling (#43816) * ach, ye initial commit * Review changes...? * Change parentage * Widen the dwarf sprite * Widen the dwarf sprite * Solve the murder at the Portermeister Estate * The rest of the fucking owl * Fix female displacement, fix the displacement error * Review changes * Review fixes * IPrototypeManager to ProtoMan * Review changes --- .../Anomaly/Effects/ClientInnerBodySystem.cs | 22 ++ .../Atmos/Components/FireVisualsComponent.cs | 9 + .../EntitySystems/FireVisualizerSystem.cs | 14 + Content.Client/Body/VisualBodySystem.cs | 13 + .../Damage/DamageVisualsComponent.cs | 9 + Content.Client/Damage/DamageVisualsSystem.cs | 57 ++- .../DisplacementMap/DisplacementMapSystem.cs | 30 +- .../Nutrition/EntitySystems/CreamPieSystem.cs | 10 + .../Atmos/EntitySystems/FlammableSystem.cs | 5 + .../InnerBodyAnomalyVisualsComponent.cs | 18 + .../Atmos/Components/FlammableComponent.cs | 7 + Content.Shared/Atmos/FireVisuals.cs | 1 + Content.Shared/Body/VisualOrganComponent.cs | 8 + .../Damage/Components/DamageableComponent.cs | 8 + Content.Shared/Damage/DamageVisualizerKeys.cs | 3 +- .../Damage/Systems/DamageableSystem.cs | 14 + .../DisplacementDataPrototype.cs | 20 ++ .../Components/CreamPiedComponent.cs | 8 + Resources/Prototypes/Body/Species/dwarf.yml | 324 +++++++++++++++++- .../Human/displacement.rsi/dwarfism.png | Bin 0 -> 15919 bytes .../displacement.rsi/dwarfism_hand_left.png | Bin 0 -> 15888 bytes .../displacement.rsi/dwarfism_hand_right.png | Bin 0 -> 15891 bytes .../displacement.rsi/dwarfism_vertical.png | Bin 0 -> 17995 bytes .../Species/Human/displacement.rsi/meta.json | 18 +- 24 files changed, 560 insertions(+), 38 deletions(-) create mode 100644 Content.Shared/Anomaly/Components/InnerBodyAnomalyVisualsComponent.cs create mode 100644 Content.Shared/DisplacementMap/DisplacementDataPrototype.cs create mode 100644 Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism.png create mode 100644 Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism_hand_left.png create mode 100644 Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism_hand_right.png create mode 100644 Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism_vertical.png diff --git a/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs b/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs index 6d48254c19..173aca24bf 100644 --- a/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs +++ b/Content.Client/Anomaly/Effects/ClientInnerBodySystem.cs @@ -1,3 +1,4 @@ +using Content.Client.DisplacementMap; using Content.Shared.Anomaly.Components; using Content.Shared.Anomaly.Effects; using Content.Shared.Humanoid; @@ -8,6 +9,9 @@ namespace Content.Client.Anomaly.Effects; public sealed partial class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomalySystem { [Dependency] private SpriteSystem _sprite = default!; + [Dependency] private DisplacementMapSystem _displacement = default!; + + [Dependency] private EntityQuery _visualsQuery = default!; public override void Initialize() { @@ -37,6 +41,22 @@ public sealed partial class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomal _sprite.LayerSetVisible((ent.Owner, sprite), index, true); sprite.LayerSetShader(index, "unshaded"); + + if (_visualsQuery.TryGetComponent(ent, out var visuals) && visuals.Displacement != null) + { + if (ProtoMan.Resolve(visuals.Displacement, out var displacement)) + { + _displacement.TryAddDisplacement(displacement.Displacement, + (ent.Owner, sprite), + index, + ent.Comp.LayerMap, + out _); + } + else + { + _displacement.EnsureDisplacementIsNotOnSprite((ent.Owner, sprite), ent.Comp.LayerMap); + } + } } private void OnCompShutdown(Entity ent, ref ComponentShutdown args) @@ -46,5 +66,7 @@ public sealed partial class ClientInnerBodyAnomalySystem : SharedInnerBodyAnomal var index = _sprite.LayerMapGet((ent.Owner, sprite), ent.Comp.LayerMap); _sprite.LayerSetVisible((ent.Owner, sprite), index, false); + + _displacement.EnsureDisplacementIsNotOnSprite((ent.Owner, sprite), ent.Comp.LayerMap); } } diff --git a/Content.Client/Atmos/Components/FireVisualsComponent.cs b/Content.Client/Atmos/Components/FireVisualsComponent.cs index 02278e9479..ac7a78edcf 100644 --- a/Content.Client/Atmos/Components/FireVisualsComponent.cs +++ b/Content.Client/Atmos/Components/FireVisualsComponent.cs @@ -1,3 +1,6 @@ +using Content.Shared.DisplacementMap; +using Robust.Shared.Prototypes; + namespace Content.Client.Atmos.Components; /// @@ -39,4 +42,10 @@ public sealed partial class FireVisualsComponent : Component /// the burning entity as entities don't support having multiple point-lights. /// public EntityUid? LightEntity; + + /// + /// Tracks the currently applied displacement, so that only new changes update the layer. + /// + [DataField] + public ProtoId? CurrentDisplacement; } diff --git a/Content.Client/Atmos/EntitySystems/FireVisualizerSystem.cs b/Content.Client/Atmos/EntitySystems/FireVisualizerSystem.cs index ec4500935c..f308e0da03 100644 --- a/Content.Client/Atmos/EntitySystems/FireVisualizerSystem.cs +++ b/Content.Client/Atmos/EntitySystems/FireVisualizerSystem.cs @@ -1,5 +1,7 @@ using Content.Client.Atmos.Components; +using Content.Client.DisplacementMap; using Content.Shared.Atmos; +using Content.Shared.DisplacementMap; using Robust.Client.GameObjects; using Robust.Shared.Map; using Robust.Shared.Utility; @@ -12,6 +14,7 @@ namespace Content.Client.Atmos.EntitySystems; public sealed partial class FireVisualizerSystem : VisualizerSystem { [Dependency] private PointLightSystem _lights = default!; + [Dependency] private DisplacementMapSystem _displacement = default!; public override void Initialize() { @@ -65,6 +68,7 @@ public sealed partial class FireVisualizerSystem : VisualizerSystem(uid, FireVisuals.OnFire, out var onFire, appearance); AppearanceSystem.TryGetData(uid, FireVisuals.FireStacks, out var fireStacks, appearance); + AppearanceSystem.TryGetData(uid, FireVisuals.FireDisplacement, out var fireDisplacement, appearance); SpriteSystem.LayerSetVisible((uid, sprite), index, onFire); if (!onFire) @@ -83,6 +87,16 @@ public sealed partial class FireVisualizerSystem : VisualizerSystem(fireDisplacement, out var displacementProto)) + _displacement.TryAddDisplacement(displacementProto.Displacement, (uid, sprite), index, FireVisualLayers.Fire, out _); + else + _displacement.EnsureDisplacementIsNotOnSprite((uid, sprite), FireVisualLayers.Fire); + + component.CurrentDisplacement = fireDisplacement; + } + component.LightEntity ??= Spawn(null, new EntityCoordinates(uid, default)); var light = EnsureComp(component.LightEntity.Value); diff --git a/Content.Client/Body/VisualBodySystem.cs b/Content.Client/Body/VisualBodySystem.cs index c29a60cc97..cf2cbd0c49 100644 --- a/Content.Client/Body/VisualBodySystem.cs +++ b/Content.Client/Body/VisualBodySystem.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Client.DisplacementMap; using Content.Shared.Body; using Content.Shared.CCVar; +using Content.Shared.DisplacementMap; using Content.Shared.Humanoid.Markings; using Content.Shared.Humanoid; using Robust.Client.GameObjects; @@ -73,6 +74,16 @@ public sealed partial class VisualBodySystem : SharedVisualBodySystem return; _sprite.LayerSetData(target, index, ent.Comp.Data); + + var displacement = ent.Comp.Displacement; + if (displacement != null && ProtoMan.Resolve(displacement, out var displacementProto)) + { + _displacement.TryAddDisplacement(displacementProto.Displacement, + (target, Comp(target)), + index, + ent.Comp.Layer, + out _); + } } private void RemoveVisual(Entity ent, EntityUid target) @@ -81,6 +92,8 @@ public sealed partial class VisualBodySystem : SharedVisualBodySystem return; _sprite.LayerSetRsiState(target, index, RSI.StateId.Invalid); + + _displacement.EnsureDisplacementIsNotOnSprite((target, Comp(target)), ent.Comp.Layer); } private void OnMarkingsGotInserted(Entity ent, ref OrganGotInsertedEvent args) diff --git a/Content.Client/Damage/DamageVisualsComponent.cs b/Content.Client/Damage/DamageVisualsComponent.cs index 26356496bb..a092e30337 100644 --- a/Content.Client/Damage/DamageVisualsComponent.cs +++ b/Content.Client/Damage/DamageVisualsComponent.cs @@ -1,4 +1,6 @@ +using Content.Shared.Damage.Components; using Content.Shared.Damage.Prototypes; +using Content.Shared.DisplacementMap; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; @@ -117,6 +119,13 @@ public sealed partial class DamageVisualsComponent : Component /// [DataField("damageOverlay")] public DamageVisualizerSprite? DamageOverlay; + /// + /// Applies a displacement map to the damage visuals. + /// Is set via . + /// + [DataField] + public DisplacementData? Displacement; + public readonly List TargetLayerMapKeys = new(); public bool Disabled = false; public bool Valid = true; diff --git a/Content.Client/Damage/DamageVisualsSystem.cs b/Content.Client/Damage/DamageVisualsSystem.cs index b374831059..13ff8a0137 100644 --- a/Content.Client/Damage/DamageVisualsSystem.cs +++ b/Content.Client/Damage/DamageVisualsSystem.cs @@ -1,8 +1,10 @@ using System.Linq; +using Content.Client.DisplacementMap; using Content.Shared.Damage; using Content.Shared.Damage.Components; using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Systems; +using Content.Shared.DisplacementMap; using Content.Shared.FixedPoint; using Robust.Client.GameObjects; using Robust.Shared.Prototypes; @@ -29,6 +31,7 @@ namespace Content.Client.Damage; public sealed partial class DamageVisualsSystem : VisualizerSystem { [Dependency] private DamageableSystem _damageable = default!; + [Dependency] private DisplacementMapSystem _displacement = default!; public override void Initialize() { @@ -326,10 +329,14 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem private void AddDamageLayerToSprite(Entity spriteEnt, DamageVisualizerSprite sprite, string state, string mapKey, int? index = null) { + if (!Resolve(spriteEnt, ref spriteEnt.Comp)) + return; + var newLayer = SpriteSystem.AddLayer( spriteEnt, new SpriteSpecifier.Rsi( - new(sprite.Sprite), state + new(sprite.Sprite), + state ), index ); @@ -354,6 +361,12 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem(uid, DamageVisualizerKeys.Displacement, out var displacement, args.Component) && + ProtoMan.Resolve(displacement, out var displacementProto)) + damageVisComp.Displacement = displacementProto.Displacement; + else + damageVisComp.Displacement = null; + HandleDamage(uid, args.Component, damageVisComp); } @@ -503,7 +516,7 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem /// Updates an overlay that is tracking all damage. /// - private void UpdateOverlay(Entity spriteEnt, FixedPoint2 threshold) + private void UpdateOverlay(Entity spriteEnt, FixedPoint2 threshold, DisplacementData? displacement = null) { SpriteSystem.LayerMapTryGet(spriteEnt.AsNullable(), $"DamageOverlay", out var spriteLayer, false); UpdateDamageLayerState(spriteEnt, spriteLayer, $"DamageOverlay", - threshold); + threshold, + $"DamageOverlay", + displacement); } /// /// Updates an overlay based on damage group. /// - private void UpdateOverlay(Entity entity, string damageGroup, FixedPoint2 threshold) + private void UpdateOverlay(Entity entity, string damageGroup, FixedPoint2 threshold, DisplacementData? displacement = null) { var spriteComponent = entity.Comp1; var damageVisComp = entity.Comp2; @@ -695,7 +718,9 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem - private void UpdateDamageLayerState(Entity spriteEnt, int spriteLayer, string statePrefix, FixedPoint2 threshold) + private void UpdateDamageLayerState(Entity spriteEnt, int spriteLayer, string statePrefix, FixedPoint2 threshold, string layerKey, DisplacementData? displacement) { if (threshold == 0) { @@ -719,6 +744,14 @@ public sealed partial class DamageVisualsSystem : VisualizerSystem /// The sprite to remove the displacement layer from. /// The key of the layer that is referenced by the displacement layer we want to remove. - /// Whether to report an error if the displacement map isn't on the sprite. - public void EnsureDisplacementIsNotOnSprite(Entity sprite, object key) + /// Returns true if the displacement existed and was removed. + public bool EnsureDisplacementIsNotOnSprite(Entity sprite, object key) { var displacementLayerKey = BuildDisplacementLayerKey(key); if (displacementLayerKey is null) - return; + return false; - _sprite.RemoveLayer(sprite.AsNullable(), displacementLayerKey, false); + return _sprite.RemoveLayer(sprite.AsNullable(), displacementLayerKey, false); } } diff --git a/Content.Client/Nutrition/EntitySystems/CreamPieSystem.cs b/Content.Client/Nutrition/EntitySystems/CreamPieSystem.cs index 5dd5192537..2d03abc843 100644 --- a/Content.Client/Nutrition/EntitySystems/CreamPieSystem.cs +++ b/Content.Client/Nutrition/EntitySystems/CreamPieSystem.cs @@ -1,6 +1,8 @@ +using Content.Client.DisplacementMap; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Robust.Client.GameObjects; +using Robust.Shared.Prototypes; namespace Content.Client.Nutrition.EntitySystems; @@ -8,6 +10,7 @@ public sealed partial class CreamPieSystem : SharedCreamPieSystem { [Dependency] private SpriteSystem _sprite = default!; [Dependency] private AppearanceSystem _appearance = default!; + [Dependency] private DisplacementMapSystem _displacement = default!; public override void Initialize() { @@ -27,6 +30,7 @@ public sealed partial class CreamPieSystem : SharedCreamPieSystem private void OnComponentShutdown(Entity ent, ref ComponentShutdown args) { _sprite.RemoveLayer(ent.Owner, CreamPiedVisualLayer.Key); + _displacement.EnsureDisplacementIsNotOnSprite((ent, Comp(ent)), CreamPiedVisualLayer.Key); } private void OnAppearanceChange(Entity ent, ref AppearanceChangeEvent args) @@ -54,6 +58,7 @@ public sealed partial class CreamPieSystem : SharedCreamPieSystem if (creamPied.Sprite == null) { _sprite.RemoveLayer((ent.Owner, sprite), CreamPiedVisualLayer.Key); + _displacement.EnsureDisplacementIsNotOnSprite((ent.Owner, sprite), CreamPiedVisualLayer.Key); return; } @@ -62,5 +67,10 @@ public sealed partial class CreamPieSystem : SharedCreamPieSystem _appearance.TryGetData(ent.Owner, CreamPiedVisuals.Creamed, out var isCreamPied, appearance); _sprite.LayerSetSprite((ent.Owner, sprite), index, creamPied.Sprite); _sprite.LayerSetVisible((ent.Owner, sprite), index, isCreamPied); + + if (ProtoMan.Resolve(ent.Comp1.Displacement, out var displacementProto)) + { + _displacement.TryAddDisplacement(displacementProto.Displacement, (ent.Owner, sprite), index, CreamPiedVisualLayer.Key, out _); + } } } diff --git a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs index bb282bf25d..137da5f10d 100644 --- a/Content.Server/Atmos/EntitySystems/FlammableSystem.cs +++ b/Content.Server/Atmos/EntitySystems/FlammableSystem.cs @@ -269,6 +269,11 @@ namespace Content.Server.Atmos.EntitySystems _appearance.SetData(uid, FireVisuals.OnFire, flammable.OnFire, appearance); _appearance.SetData(uid, FireVisuals.FireStacks, flammable.FireStacks, appearance); + if (flammable.Displacement != null) + _appearance.SetData(uid, FireVisuals.FireDisplacement, flammable.Displacement.Value.Id, appearance); + else + _appearance.RemoveData(uid, FireVisuals.FireDisplacement); + // Also enable toggleable-light visuals // This is intended so that matches & candles can re-use code for un-shaded layers on in-hand sprites. // However, this could cause conflicts if something is ACTUALLY both a toggleable light and flammable. diff --git a/Content.Shared/Anomaly/Components/InnerBodyAnomalyVisualsComponent.cs b/Content.Shared/Anomaly/Components/InnerBodyAnomalyVisualsComponent.cs new file mode 100644 index 0000000000..5298bce4f7 --- /dev/null +++ b/Content.Shared/Anomaly/Components/InnerBodyAnomalyVisualsComponent.cs @@ -0,0 +1,18 @@ +using Content.Shared.DisplacementMap; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Anomaly.Components; + +/// +/// Complementary visuals component to . +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class InnerBodyAnomalyVisualsComponent : Component +{ + /// + /// If set, applies a displacement map to the anomaly sprites. + /// + [DataField, AutoNetworkedField] + public ProtoId? Displacement; +} diff --git a/Content.Shared/Atmos/Components/FlammableComponent.cs b/Content.Shared/Atmos/Components/FlammableComponent.cs index aa1d361fa0..7bf9b4363a 100644 --- a/Content.Shared/Atmos/Components/FlammableComponent.cs +++ b/Content.Shared/Atmos/Components/FlammableComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Alert; using Content.Shared.Damage; +using Content.Shared.DisplacementMap; using Robust.Shared.GameStates; using Robust.Shared.Physics.Collision.Shapes; using Robust.Shared.Prototypes; @@ -109,5 +110,11 @@ namespace Content.Shared.Atmos.Components [DataField] public ProtoId FireAlert = "Fire"; + + /// + /// If set, applies the displacement map associated with the . + /// + [DataField] + public ProtoId? Displacement; } } diff --git a/Content.Shared/Atmos/FireVisuals.cs b/Content.Shared/Atmos/FireVisuals.cs index aeab858a35..6758a95fd8 100644 --- a/Content.Shared/Atmos/FireVisuals.cs +++ b/Content.Shared/Atmos/FireVisuals.cs @@ -7,5 +7,6 @@ namespace Content.Shared.Atmos { OnFire, FireStacks, + FireDisplacement, } } diff --git a/Content.Shared/Body/VisualOrganComponent.cs b/Content.Shared/Body/VisualOrganComponent.cs index 6427c8f0e3..80525e35a6 100644 --- a/Content.Shared/Body/VisualOrganComponent.cs +++ b/Content.Shared/Body/VisualOrganComponent.cs @@ -1,5 +1,7 @@ +using Content.Shared.DisplacementMap; using Content.Shared.Humanoid; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Body; @@ -35,6 +37,12 @@ public sealed partial class VisualOrganComponent : Component /// [DataField, AutoNetworkedField] public OrganProfileData Profile = new(); + + /// + /// Displacement data prototype applied to the organ's visualization. + /// + [DataField, AutoNetworkedField] + public ProtoId? Displacement; } /// diff --git a/Content.Shared/Damage/Components/DamageableComponent.cs b/Content.Shared/Damage/Components/DamageableComponent.cs index 7476199829..aa395a4460 100644 --- a/Content.Shared/Damage/Components/DamageableComponent.cs +++ b/Content.Shared/Damage/Components/DamageableComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Damage.Prototypes; using Content.Shared.Damage.Systems; +using Content.Shared.DisplacementMap; using Content.Shared.FixedPoint; using Content.Shared.Mobs; using Content.Shared.StatusIcon; @@ -63,6 +64,13 @@ public sealed partial class DamageableComponent : Component [DataField("radiationDamageTypes")] // ReSharper disable once UseCollectionExpression - Cannot refactor this as it's a potential sandbox violation. public List> RadiationDamageTypeIDs = new() { "Radiation" }; + + /// + /// Sets the displacement map used for any of the DamageVisuals sprites for this entity. + /// TODO: The entirety of DamageVisualsSystem needs to be rewritten. + /// + [DataField] + public ProtoId? Displacement; } [Serializable, NetSerializable] diff --git a/Content.Shared/Damage/DamageVisualizerKeys.cs b/Content.Shared/Damage/DamageVisualizerKeys.cs index 9719b96fe7..b142ec1c9e 100644 --- a/Content.Shared/Damage/DamageVisualizerKeys.cs +++ b/Content.Shared/Damage/DamageVisualizerKeys.cs @@ -10,7 +10,8 @@ namespace Content.Shared.Damage Disabled, DamageSpecifierDelta, DamageUpdateGroups, - ForceUpdate + ForceUpdate, + Displacement, } [Serializable, NetSerializable] diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index 2fba073b71..5c7a8a73cb 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -66,6 +66,20 @@ public sealed partial class DamageableSystem : EntitySystem new DamageVisualizerGroupData(ent.Comp.DamagePerGroup.Keys.ToList()), appearance ); + + if (ent.Comp.Displacement != null) + { + _appearance.SetData( + ent, + DamageVisualizerKeys.Displacement, + ent.Comp.Displacement.Value.Id, + appearance + ); + } + else + { + _appearance.RemoveData(ent, DamageVisualizerKeys.Displacement); + } } // TODO DAMAGE diff --git a/Content.Shared/DisplacementMap/DisplacementDataPrototype.cs b/Content.Shared/DisplacementMap/DisplacementDataPrototype.cs new file mode 100644 index 0000000000..46d1b10433 --- /dev/null +++ b/Content.Shared/DisplacementMap/DisplacementDataPrototype.cs @@ -0,0 +1,20 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.DisplacementMap; + +/// +/// Prototype wrapper for displacement maps, making it easier to network displacements from server to client. +/// +[Prototype] +public sealed partial class DisplacementDataPrototype : IPrototype +{ + /// + [IdDataField] + public string ID { get; private set; } = default!; + + /// + /// The displacement map this prototype is referencing. + /// + [DataField(required: true)] + public DisplacementData Displacement = default!; +} diff --git a/Content.Shared/Nutrition/Components/CreamPiedComponent.cs b/Content.Shared/Nutrition/Components/CreamPiedComponent.cs index 08c583ff7b..a050d0884f 100644 --- a/Content.Shared/Nutrition/Components/CreamPiedComponent.cs +++ b/Content.Shared/Nutrition/Components/CreamPiedComponent.cs @@ -1,5 +1,7 @@ +using Content.Shared.DisplacementMap; using Content.Shared.Nutrition.EntitySystems; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Utility; @@ -26,6 +28,12 @@ public sealed partial class CreamPiedComponent : Component /// [DataField, AutoNetworkedField] public SpriteSpecifier? Sprite; + + /// + /// If set, applies a displacement map to the pie sprite. + /// + [DataField, AutoNetworkedField] + public ProtoId? Displacement; } /// diff --git a/Resources/Prototypes/Body/Species/dwarf.yml b/Resources/Prototypes/Body/Species/dwarf.yml index 1759ffd61f..0ad6857b60 100644 --- a/Resources/Prototypes/Body/Species/dwarf.yml +++ b/Resources/Prototypes/Body/Species/dwarf.yml @@ -5,26 +5,87 @@ name: dwarf appearance components: - type: Inventory - femaleDisplacements: + femaleDisplacements: { } # Necessary due to MobHuman inheritance for MobDwarf + displacements: jumpsuit: sizeMaps: 32: sprite: Mobs/Species/Human/displacement.rsi - state: jumpsuit-female + state: dwarfism + outerClothing: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + suitstorage: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + id: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + mask: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + belt: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + eyes: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + gloves: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + head: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + neck: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + back: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + ears: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + shoes: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism - type: InitialBody organs: - Torso: OrganHumanTorso - Head: OrganHumanHead - ArmLeft: OrganHumanArmLeft - ArmRight: OrganHumanArmRight - HandRight: OrganHumanHandRight - HandLeft: OrganHumanHandLeft - LegLeft: OrganHumanLegLeft - LegRight: OrganHumanLegRight - FootLeft: OrganHumanFootLeft - FootRight: OrganHumanFootRight + Torso: OrganDwarfTorso + Head: OrganDwarfHead + ArmLeft: OrganDwarfArmLeft + ArmRight: OrganDwarfArmRight + HandRight: OrganDwarfHandRight + HandLeft: OrganDwarfHandLeft + LegLeft: OrganDwarfLegLeft + LegRight: OrganDwarfLegRight + FootLeft: OrganDwarfFootLeft + FootRight: OrganDwarfFootRight Brain: OrganHumanBrain - Eyes: OrganHumanEyes + Eyes: OrganDwarfEyes Tongue: OrganHumanTongue Appendix: OrganHumanAppendix Ears: OrganHumanEars @@ -33,10 +94,27 @@ Stomach: OrganDwarfStomach Liver: OrganDwarfLiver Kidneys: OrganHumanKidneys + - type: Hands + leftHandDisplacement: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism_hand_left + rightHandDisplacement: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism_hand_right - type: HumanoidProfile species: Dwarf - - type: ScaleVisuals - scale: 1, 0.8 + +- type: displacementData + id: Dwarfism + displacement: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism - type: entity parent: @@ -64,6 +142,14 @@ accent: scottish - type: Speech speechSounds: Bass + - type: CreamPied + displacement: Dwarfism + - type: Damageable + displacement: Dwarfism + - type: Flammable + displacement: Dwarfism + - type: InnerBodyAnomalyVisuals + displacement: Dwarfism - type: entity parent: OrganBaseOrganic @@ -72,12 +158,220 @@ suffix: Dwarf - type: entity + parent: OrganDwarf + id: OrganDwarfAppearance + abstract: true + suffix: Dwarf + components: + - type: VisualOrgan + data: + sprite: Mobs/Species/Human/parts.rsi + displacement: Dwarfism + +- type: entity + parent: OrganDwarf id: OrganDwarfMetabolizer abstract: true components: - type: Metabolizer metabolizerTypes: [ Dwarf ] +- type: entity + parent: [ OrganHumanTorso, OrganDwarfAppearance ] + id: OrganDwarfTorso + components: + - type: VisualOrganMarkings + markingsDisplacement: + Chest: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + Tail: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + Overlay: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + TailOverlay: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + UndergarmentTop: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + UndergarmentBottom: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + Special: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanHead, OrganDwarfAppearance ] + id: OrganDwarfHead + components: + - type: VisualOrganMarkings + markingsDisplacement: + Head: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + Hair: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + FacialHair: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + Snout: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + SnoutCover: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + HeadSide: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + HeadTop: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanArmLeft, OrganDwarfAppearance ] + id: OrganDwarfArmLeft + components: + - type: VisualOrganMarkings + markingsDisplacement: + LArm: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanArmRight, OrganDwarfAppearance ] + id: OrganDwarfArmRight + components: + - type: VisualOrganMarkings + markingsDisplacement: + RArm: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanHandRight, OrganDwarfAppearance ] + id: OrganDwarfHandRight + components: + - type: VisualOrganMarkings + markingsDisplacement: + RHand: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanHandLeft, OrganDwarfAppearance ] + id: OrganDwarfHandLeft + components: + - type: VisualOrganMarkings + markingsDisplacement: + LHand: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanLegLeft, OrganDwarfAppearance ] + id: OrganDwarfLegLeft + components: + - type: VisualOrganMarkings + markingsDisplacement: + LLeg: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanLegRight, OrganDwarfAppearance ] + id: OrganDwarfLegRight + components: + - type: VisualOrganMarkings + markingsDisplacement: + RLeg: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanFootLeft, OrganDwarfAppearance ] + id: OrganDwarfFootLeft + components: + - type: VisualOrganMarkings + markingsDisplacement: + LFoot: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanFootRight, OrganDwarfAppearance ] + id: OrganDwarfFootRight + components: + - type: VisualOrganMarkings + markingsDisplacement: + RFoot: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + +- type: entity + parent: [ OrganHumanEyes, OrganDwarfAppearance ] + id: OrganDwarfEyes + components: + - type: VisualOrgan + data: + sprite: Mobs/Customization/eyes.rsi + displacement: Dwarfism + - type: VisualOrganMarkings + markingsDisplacement: + Eyes: + sizeMaps: + 32: + sprite: Mobs/Species/Human/displacement.rsi + state: dwarfism + - type: entity parent: [ OrganDwarfMetabolizer, OrganHumanStomach ] id: OrganDwarfStomach diff --git a/Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism.png b/Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism.png new file mode 100644 index 0000000000000000000000000000000000000000..86d57009d08fdb035ae63d751ac372c8a1adbe6d GIT binary patch literal 15919 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 O&+VSizqRYg6Mq3iKPt8W literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism_hand_right.png b/Resources/Textures/Mobs/Species/Human/displacement.rsi/dwarfism_hand_right.png new file mode 100644 index 0000000000000000000000000000000000000000..7f8da85c121c8ef3b0ddabcd8fc95e12177dbf70 GIT binary patch literal 15891 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Species/Human/displacement.rsi/meta.json b/Resources/Textures/Mobs/Species/Human/displacement.rsi/meta.json index 7ac587cad7..d4d637bd08 100644 --- a/Resources/Textures/Mobs/Species/Human/displacement.rsi/meta.json +++ b/Resources/Textures/Mobs/Species/Human/displacement.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Made by TheShuEd", + "copyright": "jumpsuit-female made by TheShuEd, dwarfism sprites made by SlamBamActionman (Github)", "size": { "x": 32, "y": 32 @@ -13,6 +13,22 @@ { "name": "jumpsuit-female", "directions": 4 + }, + { + "name": "dwarfism", + "directions": 4 + }, + { + "name": "dwarfism_hand_left", + "directions": 4 + }, + { + "name": "dwarfism_hand_right", + "directions": 4 + }, + { + "name": "dwarfism_vertical", + "directions": 1 } ] }