]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add undergarments & "Censor Nudity" toggle to options (#33185)
authorSlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Wed, 5 Mar 2025 09:14:01 +0000 (10:14 +0100)
committerGitHub <noreply@github.com>
Wed, 5 Mar 2025 09:14:01 +0000 (10:14 +0100)
* Initial commit

* Attribution

* Review changes

* Added comment for upstream

42 files changed:
Content.Client/Humanoid/HumanoidAppearanceSystem.cs
Content.Client/Options/UI/Tabs/AccessibilityTab.xaml
Content.Client/Options/UI/Tabs/AccessibilityTab.xaml.cs
Content.Shared/CCVar/CCVars.Accessibility.cs
Content.Shared/Humanoid/HumanoidAppearanceComponent.cs
Content.Shared/Humanoid/HumanoidVisualLayers.cs
Content.Shared/Humanoid/Markings/MarkingCategories.cs
Content.Shared/Humanoid/Markings/MarkingColoring.cs
Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
Resources/Locale/en-US/markings/undergarment.ftl [new file with mode: 0644]
Resources/Locale/en-US/preferences/ui/markings-picker.ftl
Resources/Prototypes/Entities/Mobs/Customization/Markings/undergarments.yml [new file with mode: 0644]
Resources/Prototypes/Entities/Mobs/Species/arachnid.yml
Resources/Prototypes/Entities/Mobs/Species/base.yml
Resources/Prototypes/Entities/Mobs/Species/moth.yml
Resources/Prototypes/Entities/Mobs/Species/reptilian.yml
Resources/Prototypes/Entities/Mobs/Species/vox.yml
Resources/Prototypes/Species/arachnid.yml
Resources/Prototypes/Species/diona.yml
Resources/Prototypes/Species/human.yml
Resources/Prototypes/Species/moth.yml
Resources/Prototypes/Species/reptilian.yml
Resources/Prototypes/Species/slime.yml
Resources/Prototypes/Species/vox.yml
Resources/Textures/Mobs/Customization/undergarments.rsi/binder.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/binder_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/boxers.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_reptilian.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/briefs.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_reptilian.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/classic.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/classic_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/satin.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/satin_reptilian.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/satin_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/sports.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/sports_vox.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop.png [new file with mode: 0644]
Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop_vox.png [new file with mode: 0644]

index 6eb5dd9ec987ffa3243c07a4ebf52021e3bf81c5..2d532968de0f1df05fea2564ce861b07d7f7e410 100644 (file)
@@ -1,8 +1,10 @@
+using Content.Shared.CCVar;
 using Content.Shared.Humanoid;
 using Content.Shared.Humanoid.Markings;
 using Content.Shared.Humanoid.Prototypes;
 using Content.Shared.Preferences;
 using Robust.Client.GameObjects;
+using Robust.Shared.Configuration;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Utility;
 
@@ -12,12 +14,15 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
 {
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
     [Dependency] private readonly MarkingManager _markingManager = default!;
+    [Dependency] private readonly IConfigurationManager _configurationManager = default!;
 
     public override void Initialize()
     {
         base.Initialize();
 
         SubscribeLocalEvent<HumanoidAppearanceComponent, AfterAutoHandleStateEvent>(OnHandleState);
+        Subs.CVar(_configurationManager, CCVars.AccessibilityClientCensorNudity, OnCvarChanged, true);
+        Subs.CVar(_configurationManager, CCVars.AccessibilityServerCensorNudity, OnCvarChanged, true);
     }
 
     private void OnHandleState(EntityUid uid, HumanoidAppearanceComponent component, ref AfterAutoHandleStateEvent args)
@@ -25,6 +30,15 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
         UpdateSprite(component, Comp<SpriteComponent>(uid));
     }
 
+    private void OnCvarChanged(bool value)
+    {
+        var humanoidQuery = EntityManager.AllEntityQueryEnumerator<HumanoidAppearanceComponent, SpriteComponent>();
+        while (humanoidQuery.MoveNext(out var _, out var humanoidComp, out var spriteComp))
+        {
+            UpdateSprite(humanoidComp, spriteComp);
+        }
+    }
+
     private void UpdateSprite(HumanoidAppearanceComponent component, SpriteComponent sprite)
     {
         UpdateLayers(component, sprite);
@@ -207,16 +221,30 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
         // Really, markings should probably be a separate component altogether.
         ClearAllMarkings(humanoid, sprite);
 
+        var censorNudity = _configurationManager.GetCVar(CCVars.AccessibilityClientCensorNudity) ||
+                           _configurationManager.GetCVar(CCVars.AccessibilityServerCensorNudity);
+        // The reason we're splitting this up is in case the character already has undergarment equipped in that slot.
+        var applyUndergarmentTop = censorNudity;
+        var applyUndergarmentBottom = censorNudity;
+
         foreach (var markingList in humanoid.MarkingSet.Markings.Values)
         {
             foreach (var marking in markingList)
             {
                 if (_markingManager.TryGetMarking(marking, out var markingPrototype))
+                {
                     ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, humanoid, sprite);
+                    if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentTop)
+                        applyUndergarmentTop = false;
+                    else if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentBottom)
+                        applyUndergarmentBottom = false;
+                }
             }
         }
 
         humanoid.ClientOldMarkings = new MarkingSet(humanoid.MarkingSet);
+
+        AddUndergarments(humanoid, sprite, applyUndergarmentTop, applyUndergarmentBottom);
     }
 
     private void ClearAllMarkings(HumanoidAppearanceComponent humanoid, SpriteComponent sprite)
@@ -264,6 +292,31 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
             spriteComp.RemoveLayer(index);
         }
     }
+
+    private void AddUndergarments(HumanoidAppearanceComponent humanoid, SpriteComponent sprite, bool undergarmentTop, bool undergarmentBottom)
+    {
+        if (undergarmentTop && humanoid.UndergarmentTop != null)
+        {
+            var marking = new Marking(humanoid.UndergarmentTop, new List<Color> { new Color() });
+            if (_markingManager.TryGetMarking(marking, out var prototype))
+            {
+                // Markings are added to ClientOldMarkings because otherwise it causes issues when toggling the feature on/off.
+                humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentTop, new List<Marking>{ marking });
+                ApplyMarking(prototype, null, true, humanoid, sprite);
+            }
+        }
+
+        if (undergarmentBottom && humanoid.UndergarmentBottom != null)
+        {
+            var marking = new Marking(humanoid.UndergarmentBottom, new List<Color> { new Color() });
+            if (_markingManager.TryGetMarking(marking, out var prototype))
+            {
+                humanoid.ClientOldMarkings.Markings.Add(MarkingCategories.UndergarmentBottom, new List<Marking>{ marking });
+                ApplyMarking(prototype, null, true, humanoid, sprite);
+            }
+        }
+    }
+
     private void ApplyMarking(MarkingPrototype markingPrototype,
         IReadOnlyList<Color>? colors,
         bool visible,
index 763fd995ca80328a0d856e9e778d039283f6f593..5041b498a0bcb8277907e6a019fa55a541085c7d 100644 (file)
@@ -4,6 +4,8 @@
     <BoxContainer Orientation="Vertical">
         <ScrollContainer VerticalExpand="True" HScrollEnabled="False">
             <BoxContainer Orientation="Vertical" Margin="8">
+                <Label Text="{Loc 'ui-options-accessability-header-visuals'}"
+                       StyleClasses="LabelKeyText"/>
                 <CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
                 <CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
                 <CheckBox Name="ColorblindFriendlyCheckBox" Text="{Loc 'ui-options-colorblind-friendly'}" />
@@ -12,6 +14,9 @@
                 <ui:OptionSlider Name="SpeechBubbleTextOpacitySlider" Title="{Loc 'ui-options-speech-bubble-text-opacity'}" />
                 <ui:OptionSlider Name="SpeechBubbleSpeakerOpacitySlider" Title="{Loc 'ui-options-speech-bubble-speaker-opacity'}" />
                 <ui:OptionSlider Name="SpeechBubbleBackgroundOpacitySlider" Title="{Loc 'ui-options-speech-bubble-background-opacity'}" />
+                <Label Text="{Loc 'ui-options-accessability-header-content'}"
+                       StyleClasses="LabelKeyText"/>
+                <CheckBox Name="CensorNudityCheckBox" Text="{Loc 'ui-options-censor-nudity'}" />
             </BoxContainer>
         </ScrollContainer>
         <ui:OptionsTabControlRow Name="Control" Access="Public" />
index e1dead0b0e68e724fda03e25aebfd1808252b499..f87cda746c1eac3b68096faf3dc632138315d6b6 100644 (file)
@@ -21,6 +21,8 @@ public sealed partial class AccessibilityTab : Control
         Control.AddOptionPercentSlider(CCVars.SpeechBubbleSpeakerOpacity, SpeechBubbleSpeakerOpacitySlider);
         Control.AddOptionPercentSlider(CCVars.SpeechBubbleBackgroundOpacity, SpeechBubbleBackgroundOpacitySlider);
 
+        Control.AddOptionCheckBox(CCVars.AccessibilityClientCensorNudity, CensorNudityCheckBox);
+
         Control.Initialize();
     }
 }
index 14312363a1072f639756993a45ac11fa51559afc..3f752cbeea690767f095a2be879a1169a5c515e7 100644 (file)
@@ -60,5 +60,17 @@ public sealed partial class CCVars
     public static readonly CVarDef<float> SpeechBubbleBackgroundOpacity =
         CVarDef.Create("accessibility.speech_bubble_background_opacity", 0.75f, CVar.CLIENTONLY | CVar.ARCHIVE);
 
+    /// <summary>
+    /// If enabled, censors character nudity by forcing clothes markings on characters, selected by the client.
+    /// Both this and AccessibilityServerCensorNudity must be false to display nudity on the client.
+    /// </summary>
+    public static readonly CVarDef<bool> AccessibilityClientCensorNudity =
+        CVarDef.Create("accessibility.censor_nudity", false, CVar.CLIENTONLY | CVar.ARCHIVE);
 
+    /// <summary>
+    /// If enabled, censors character nudity by forcing clothes markings on characters, selected by the server.
+    /// Both this and AccessibilityClientCensorNudity must be false to display nudity on the client.
+    /// </summary>
+    public static readonly CVarDef<bool> AccessibilityServerCensorNudity =
+            CVarDef.Create("accessibility.server_censor_nudity", false, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
 }
index 016ab64f1a7b05c219224b6de2ce2c44d3a968a6..0bf11f5762a8edf54433d5fdfc1058712bdf93d9 100644 (file)
@@ -88,6 +88,15 @@ public sealed partial class HumanoidAppearanceComponent : Component
     /// </summary>
     [DataField]
     public HashSet<HumanoidVisualLayers> HideLayersOnEquip = [HumanoidVisualLayers.Hair];
+
+    /// <summary>
+    ///     Which markings the humanoid defaults to when nudity is toggled off.
+    /// </summary>
+    [DataField]
+    public ProtoId<MarkingPrototype>? UndergarmentTop = new ProtoId<MarkingPrototype>("UndergarmentTopTanktop");
+
+    [DataField]
+    public ProtoId<MarkingPrototype>? UndergarmentBottom = new ProtoId<MarkingPrototype>("UndergarmentBottomBoxers");
 }
 
 [DataDefinition]
index cecd8a1c13e2e3045964b0dec28fb9e501e12f4e..ca78564bfdf65b49ffa6a7835d92afa80e8252ad 100644 (file)
@@ -10,6 +10,8 @@ namespace Content.Shared.Humanoid
         Tail,
         Hair,
         FacialHair,
+        UndergarmentTop,
+        UndergarmentBottom,
         Chest,
         Head,
         Snout,
@@ -19,7 +21,6 @@ namespace Content.Shared.Humanoid
         RArm,
         LArm,
         RHand,
-
         LHand,
         RLeg,
         LLeg,
index db82fb1fd3d2682068e373b640d98bfc554b6d93..25511750966b758bde80ec5fe9b7f9220f52fcff 100644 (file)
@@ -13,6 +13,8 @@ namespace Content.Shared.Humanoid.Markings
         HeadSide,
         Snout,
         Chest,
+        UndergarmentTop,
+        UndergarmentBottom,
         Arms,
         Legs,
         Tail,
@@ -33,6 +35,8 @@ namespace Content.Shared.Humanoid.Markings
                 HumanoidVisualLayers.HeadSide => MarkingCategories.HeadSide,
                 HumanoidVisualLayers.Snout => MarkingCategories.Snout,
                 HumanoidVisualLayers.Chest => MarkingCategories.Chest,
+                HumanoidVisualLayers.UndergarmentTop => MarkingCategories.UndergarmentTop,
+                HumanoidVisualLayers.UndergarmentBottom => MarkingCategories.UndergarmentBottom,
                 HumanoidVisualLayers.RArm => MarkingCategories.Arms,
                 HumanoidVisualLayers.LArm => MarkingCategories.Arms,
                 HumanoidVisualLayers.RHand => MarkingCategories.Arms,
index a13481debfca965b785d3cfe9122a16bc1e437e7..fa47475a232b75666e647e967e9fd87df0f3ac3e 100644 (file)
@@ -89,7 +89,7 @@ public static class MarkingColoring
 public sealed partial class LayerColoringDefinition
 {
     [DataField("type")]
-    public LayerColoringType Type = new SkinColoring();
+    public LayerColoringType? Type = new SkinColoring();
 
     /// <summary>
     ///     Coloring types that will be used if main coloring type will return nil
@@ -105,7 +105,9 @@ public sealed partial class LayerColoringDefinition
 
     public Color GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
     {
-        var color = Type.GetColor(skin, eyes, markingSet);
+        Color? color = null;
+        if (Type != null)
+            color = Type.GetColor(skin, eyes, markingSet);
         if (color == null)
         {
             foreach (var type in FallbackTypes)
index e6b6a5250a35242b33fe4c69756acafb903fb35c..32a77f8b6bb42c4293f6f46c58fbacdc41ef32ff 100644 (file)
@@ -279,15 +279,21 @@ cmd-options-help = Usage: options [tab]
 
 ## Accessibility menu
 
+ui-options-accessability-header-visuals = Visuals
+ui-options-accessability-header-content = Content
+
 ui-options-enable-color-name = Add colors to character names
 ui-options-colorblind-friendly = Colorblind friendly mode
 ui-options-reduced-motion = Reduce motion of visual effects
 ui-options-screen-shake-intensity = Screen shake intensity
+
 ui-options-chat-window-opacity = Chat window opacity
 ui-options-speech-bubble-text-opacity = Speech bubble text opacity
 ui-options-speech-bubble-speaker-opacity = Speech bubble speaker opacity
 ui-options-speech-bubble-background-opacity = Speech bubble background opacity
 
+ui-options-censor-nudity = Censor character nudity
+
 ## Admin menu
 
 ui-options-enable-classic-overlay = Revert antag overlay to classic mode
diff --git a/Resources/Locale/en-US/markings/undergarment.ftl b/Resources/Locale/en-US/markings/undergarment.ftl
new file mode 100644 (file)
index 0000000..3740d05
--- /dev/null
@@ -0,0 +1,21 @@
+marking-UndergarmentTopTanktop = Tanktop
+marking-UndergarmentTopBinder = Binder
+marking-UndergarmentTopBra = Classic Bra
+marking-UndergarmentTopSportsbra = Sports Bra
+
+marking-UndergarmentBottomBoxers = Boxers
+marking-UndergarmentBottomBriefs = Briefs
+marking-UndergarmentBottomSatin = Satin
+
+marking-UndergarmentTopTanktopVox = Tanktop
+marking-UndergarmentTopBinderVox = Binder
+marking-UndergarmentTopBraVox = Classic Bra
+marking-UndergarmentTopSportsbraVox = Sports Bra
+
+marking-UndergarmentBottomBoxersVox = Boxers
+marking-UndergarmentBottomBriefsVox = Briefs
+marking-UndergarmentBottomSatinVox = Satin
+
+marking-UndergarmentBottomBoxersReptilian = Boxers
+marking-UndergarmentBottomBriefsReptilian = Briefs
+marking-UndergarmentBottomSatinReptilian = Satin
index ba274ec9cacc5c0298593a406d113ae85ed24009..af2e81ce3baac344ea49e38211e5050b5b7c476a 100644 (file)
@@ -21,6 +21,8 @@ markings-category-Head = Head
 markings-category-HeadTop = Head (Top)
 markings-category-HeadSide = Head (Side)
 markings-category-Snout = Snout
+markings-category-UndergarmentTop = Undergarment (Top)
+markings-category-UndergarmentBottom = Undergarment (Bottom)
 markings-category-Chest = Chest
 markings-category-Arms = Arms
 markings-category-Legs = Legs
diff --git a/Resources/Prototypes/Entities/Mobs/Customization/Markings/undergarments.yml b/Resources/Prototypes/Entities/Mobs/Customization/Markings/undergarments.yml
new file mode 100644 (file)
index 0000000..b7f6229
--- /dev/null
@@ -0,0 +1,223 @@
+# These options are kept very sparse to not put emphasis on nudity, and to provide a base for players to feel comfortable with.
+# It's unlikely more will be added to upstream for cosmetic reasons. 
+
+- type: marking
+  id: UndergarmentBottomBoxers
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: boxers
+
+- type: marking
+  id: UndergarmentBottomBriefs
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: briefs
+
+- type: marking
+  id: UndergarmentBottomSatin
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: satin
+
+- type: marking
+  id: UndergarmentTopBra
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, Reptilian, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: classic
+
+- type: marking
+  id: UndergarmentTopSportsbra
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, Reptilian, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: sports
+
+- type: marking
+  id: UndergarmentTopBinder
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, Reptilian, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: binder
+
+- type: marking
+  id: UndergarmentTopTanktop
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Arachnid, Diona, Human, Dwarf, Moth, Reptilian, SlimePerson]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: tanktop
+
+- type: marking
+  id: UndergarmentBottomBoxersVox # Voxers.
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: boxers_vox
+
+- type: marking
+  id: UndergarmentBottomBriefsVox
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: briefs_vox
+
+- type: marking
+  id: UndergarmentBottomSatinVox
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: satin_vox
+
+- type: marking
+  id: UndergarmentTopBraVox
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: classic_vox
+
+- type: marking
+  id: UndergarmentTopSportsbraVox
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: sports_vox
+
+- type: marking
+  id: UndergarmentTopBinderVox
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: binder_vox
+
+- type: marking
+  id: UndergarmentTopTanktopVox
+  bodyPart: UndergarmentTop
+  markingCategory: UndergarmentTop
+  speciesRestriction: [Vox]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: tanktop_vox
+
+- type: marking
+  id: UndergarmentBottomBoxersReptilian
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Reptilian]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: boxers_reptilian
+
+- type: marking
+  id: UndergarmentBottomBriefsReptilian
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Reptilian]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: briefs_reptilian
+
+- type: marking
+  id: UndergarmentBottomSatinReptilian
+  bodyPart: UndergarmentBottom
+  markingCategory: UndergarmentBottom
+  speciesRestriction: [Reptilian]
+  coloring:
+    default:
+      type: null
+      fallbackColor: '#FFFFFF'
+  sprites:
+  - sprite: Mobs/Customization/undergarments.rsi
+    state: satin_reptilian
index 66cf7ccfabd7b5f3867b2547299a506ea4491ff8..5391aec03f21722dc8a7073eee03ccd6cf77b5d3 100644 (file)
@@ -81,6 +81,8 @@
       - map: [ "enum.HumanoidVisualLayers.LArm" ]
       - map: [ "enum.HumanoidVisualLayers.RLeg" ]
       - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+      - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+      - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
       - map: ["jumpsuit"]
       - map: ["enum.HumanoidVisualLayers.LFoot"]
       - map: ["enum.HumanoidVisualLayers.RFoot"]
index 67fb5f2303de539e8f8eff744932f6eadc498fef..364bd743d9928fcf85678c3bfabdf7e27dbbfab4 100644 (file)
@@ -19,6 +19,8 @@
     - map: [ "enum.HumanoidVisualLayers.LArm" ]
     - map: [ "enum.HumanoidVisualLayers.RLeg" ]
     - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
     - map: ["jumpsuit"]
     - map: ["enum.HumanoidVisualLayers.LFoot"]
     - map: ["enum.HumanoidVisualLayers.RFoot"]
     - map: [ "enum.HumanoidVisualLayers.LArm" ]
     - map: [ "enum.HumanoidVisualLayers.RLeg" ]
     - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
     - map: ["jumpsuit"]
     - map: ["enum.HumanoidVisualLayers.LFoot"]
     - map: ["enum.HumanoidVisualLayers.RFoot"]
index 6d55596859668a7ff8a8133b2acd260fd81dc859..59e3d6a7a5ece1ddb7d6b57996ffefc6fe49690d 100644 (file)
@@ -83,6 +83,8 @@
       - map: [ "enum.HumanoidVisualLayers.LArm" ]
       - map: [ "enum.HumanoidVisualLayers.RLeg" ]
       - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+      - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+      - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
       - map: [ "jumpsuit" ]
       - map: [ "enum.HumanoidVisualLayers.LHand" ]
       - map: [ "enum.HumanoidVisualLayers.RHand" ]
index f172f631c1def3aeb4529d52f309445df4afef09..efa4660032c2780e72bb2d623ee7d4ca0782c4d9 100644 (file)
@@ -11,6 +11,7 @@
     - Snout
     - HeadTop
     - HeadSide
+    undergarmentBottom: UndergarmentBottomBoxersReptilian
   - type: Hunger
   - type: Puller
     needsHands: false
@@ -90,6 +91,7 @@
     - Snout
     - HeadTop
     - HeadSide
+    undergarmentBottom: UndergarmentBottomBoxersReptilian
   - type: Inventory
     speciesId: reptilian
     femaleDisplacements:
index 50d224ec3b9a39e01c4d5b8e487663f5e861e989..8967e1757430a63dfab8524f31d08fcf5a7a2c28 100644 (file)
   - type: Body
     prototype: Vox
     requiredLegs: 2
-  - type:  HumanoidAppearance
+  - type: HumanoidAppearance
     species: Vox
+    undergarmentTop: UndergarmentTopTanktopVox
+    undergarmentBottom: UndergarmentBottomBoxersVox
     #- type: VoxAccent # Not yet coded
   - type: Speech
     speechVerb: Vox
@@ -71,6 +73,8 @@
     - map: [ "enum.HumanoidVisualLayers.LArm" ]
     - map: [ "enum.HumanoidVisualLayers.RLeg" ]
     - map: [ "enum.HumanoidVisualLayers.LLeg" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentBottom" ]
+    - map: [ "enum.HumanoidVisualLayers.UndergarmentTop" ]
     - map: [ "jumpsuit" ]
     - map: [ "enum.HumanoidVisualLayers.LFoot" ]
     - map: [ "enum.HumanoidVisualLayers.RFoot" ]
   components:
   - type: HumanoidAppearance
     species: Vox
+    undergarmentTop: UndergarmentTopTanktopVox
+    undergarmentBottom: UndergarmentBottomBoxersVox
   - type: Body
     prototype: Vox
   - type: Inventory
index 07a72cda17681470123f473a5f8f677fda68ec93..9786b1da2ef8f219560596f4311246cc85b00f45 100644 (file)
@@ -19,6 +19,8 @@
   sprites:
     Head: MobArachnidHead
     Snout: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobArachnidTorso
     HeadTop: MobHumanoidAnyMarking
     HeadSide: MobHumanoidAnyMarking
index 19fafaa3e1b794a972f5464be7124b7a19f073dc..e0ba53e99c3c45a887462f5e1960a3ff600ad73f 100644 (file)
@@ -19,6 +19,8 @@
     Head: MobDionaHead
     HeadTop: MobHumanoidAnyMarking
     HeadSide: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobDionaTorso
     Eyes: MobDionaEyes
     LArm: MobDionaLArm
     HeadSide:
       points: 1
       required: false
+    UndergarmentTop:
+      points: 1
+      required: false
+    UndergarmentBottom:
+      points: 1
+      required: false
     Chest:
       points: 1
       required: false
index 25495296060a7943083c8b8a34a4eb6815cf59d0..9c95d87dcf3a4f7ec5ae0a427757d48d494ed45b 100644 (file)
@@ -22,6 +22,8 @@
     Hair: MobHumanoidAnyMarking
     FacialHair: MobHumanoidAnyMarking
     Snout: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobHumanTorso
     Eyes: MobHumanoidEyes
     HeadTop: MobHumanoidAnyMarking
     HeadTop:
       points: 1
       required: false
+    UndergarmentTop:
+      points: 1
+      required: false
+    UndergarmentBottom:
+      points: 1
+      required: false
     Chest:
       points: 1
       required: false
index 4f587eb40e0969db928e602075c02436d220d668..22a5b978f1c4d794d1ecbfbf6be95552346e3fa8 100644 (file)
@@ -17,6 +17,8 @@
   sprites:
     Head: MobMothHead
     Snout: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobMothTorso
     HeadTop: MobHumanoidAnyMarking
     HeadSide: MobHumanoidAnyMarking
     Head:
       points: 1
       required: false
+    UndergarmentTop:
+      points: 1
+      required: false
+    UndergarmentBottom:
+      points: 1
+      required: false
     Chest:
       points: 1
       required: false
index 321e01cfe73ad64e0cc0ee7eae40df33c8da73e1..18d43a5906a3de2d6bc35dd7a0669e1656fcdd11 100644 (file)
@@ -17,6 +17,8 @@
   sprites:
     Head: MobReptilianHead
     Snout: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobReptilianTorso
     HeadTop: MobHumanoidAnyMarking
     HeadSide: MobHumanoidAnyMarking
     HeadSide:
       points: 1
       required: false
+    UndergarmentTop:
+      points: 1
+      required: false
+    UndergarmentBottom:
+      points: 1
+      required: false
     Chest:
       points: 3
       required: false
index 8c42b4d7bfd92a912429eedad51f7785ba7b0d9d..5fd4a0f81e111433669c33ebb6d1bb27ad1e8402 100644 (file)
@@ -15,6 +15,8 @@
     Head: MobSlimeHead
     Hair: MobSlimeMarkingFollowSkin
     FacialHair: MobSlimeMarkingFollowSkin
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobSlimeTorso
     Eyes: MobHumanoidEyes
     LArm: MobSlimeLArm
index 7419f3f277e9fb16b2b48da69e551329ebb5be70..29cc0583fc1132c90cee2b6c501d36286c4a4756 100644 (file)
@@ -21,6 +21,8 @@
     Snout: MobHumanoidAnyMarking
     Hair: MobHumanoidAnyMarking
     FacialHair: MobHumanoidAnyMarking
+    UndergarmentTop: MobHumanoidAnyMarking
+    UndergarmentBottom: MobHumanoidAnyMarking
     Chest: MobVoxTorso
     Eyes: MobVoxEyes
     LArm: MobVoxLArm
       points: 4
       required: true
       defaultMarkings: [ VoxLLegScales, VoxRLegScales, VoxRFootScales, VoxLFootScales ]
+    UndergarmentTop:
+      points: 1
+      required: false
+    UndergarmentBottom:
+      points: 1
+      required: false
     Chest:
       points: 1
       required: false
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/binder.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/binder.png
new file mode 100644 (file)
index 0000000..e5a5a6c
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/binder.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/binder_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/binder_vox.png
new file mode 100644 (file)
index 0000000..e318b99
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/binder_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers.png
new file mode 100644 (file)
index 0000000..f7aadbe
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_reptilian.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_reptilian.png
new file mode 100644 (file)
index 0000000..2b851f4
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_reptilian.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_vox.png
new file mode 100644 (file)
index 0000000..c838e8f
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/boxers_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs.png
new file mode 100644 (file)
index 0000000..4874810
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_reptilian.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_reptilian.png
new file mode 100644 (file)
index 0000000..09e9d5f
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_reptilian.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_vox.png
new file mode 100644 (file)
index 0000000..11e2744
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/briefs_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/classic.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/classic.png
new file mode 100644 (file)
index 0000000..d6b987b
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/classic.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/classic_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/classic_vox.png
new file mode 100644 (file)
index 0000000..2323e31
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/classic_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/meta.json b/Resources/Textures/Mobs/Customization/undergarments.rsi/meta.json
new file mode 100644 (file)
index 0000000..345c141
--- /dev/null
@@ -0,0 +1,79 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "sprites taken from https://github.com/cmss13-devs/cmss13/blob/884ab172389b6fc54ef063f5fbea5e8b0a0a2235/icons/mob/humans/underwear.dmi and https://github.com/cmss13-devs/cmss13/blob/884ab172389b6fc54ef063f5fbea5e8b0a0a2235/icons/mob/humans/undershirt.dmi, edited by SlamBamActionman",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "briefs",
+      "directions": 4
+    },
+    {
+      "name": "satin",
+      "directions": 4
+    },
+    {
+      "name": "boxers",
+      "directions": 4
+    },
+    {
+      "name": "classic",
+      "directions": 4
+    },
+    {
+      "name": "sports",
+      "directions": 4
+    },
+    {
+      "name": "binder",
+      "directions": 4
+    },
+    {
+      "name": "tanktop",
+      "directions": 4
+    },
+    {
+      "name": "briefs_vox",
+      "directions": 4
+    },
+    {
+      "name": "satin_vox",
+      "directions": 4
+    },
+    {
+      "name": "boxers_vox",
+      "directions": 4
+    },
+    {
+      "name": "classic_vox",
+      "directions": 4
+    },
+    {
+      "name": "sports_vox",
+      "directions": 4
+    },
+    {
+      "name": "binder_vox",
+      "directions": 4
+    },
+    {
+      "name": "tanktop_vox",
+      "directions": 4
+    },
+    {
+      "name": "briefs_reptilian",
+      "directions": 4
+    },
+    {
+      "name": "satin_reptilian",
+      "directions": 4
+    },
+    {
+      "name": "boxers_reptilian",
+      "directions": 4
+    }
+  ]
+}
\ No newline at end of file
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/satin.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin.png
new file mode 100644 (file)
index 0000000..3e1e6ec
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_reptilian.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_reptilian.png
new file mode 100644 (file)
index 0000000..0bf4b58
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_reptilian.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_vox.png
new file mode 100644 (file)
index 0000000..e4c1178
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/satin_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/sports.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/sports.png
new file mode 100644 (file)
index 0000000..529565f
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/sports.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/sports_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/sports_vox.png
new file mode 100644 (file)
index 0000000..f95ec11
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/sports_vox.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop.png
new file mode 100644 (file)
index 0000000..2e4e4d4
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop.png differ
diff --git a/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop_vox.png b/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop_vox.png
new file mode 100644 (file)
index 0000000..0a7c4e1
Binary files /dev/null and b/Resources/Textures/Mobs/Customization/undergarments.rsi/tanktop_vox.png differ