+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;
{
[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)
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);
// 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)
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,
<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'}" />
<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" />
Control.AddOptionPercentSlider(CCVars.SpeechBubbleSpeakerOpacity, SpeechBubbleSpeakerOpacitySlider);
Control.AddOptionPercentSlider(CCVars.SpeechBubbleBackgroundOpacity, SpeechBubbleBackgroundOpacitySlider);
+ Control.AddOptionCheckBox(CCVars.AccessibilityClientCensorNudity, CensorNudityCheckBox);
+
Control.Initialize();
}
}
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);
}
/// </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]
Tail,
Hair,
FacialHair,
+ UndergarmentTop,
+ UndergarmentBottom,
Chest,
Head,
Snout,
RArm,
LArm,
RHand,
-
LHand,
RLeg,
LLeg,
HeadSide,
Snout,
Chest,
+ UndergarmentTop,
+ UndergarmentBottom,
Arms,
Legs,
Tail,
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,
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
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)
## 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
--- /dev/null
+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
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
--- /dev/null
+# 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
- 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"]
- 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.LHand" ]
- map: [ "enum.HumanoidVisualLayers.RHand" ]
- Snout
- HeadTop
- HeadSide
+ undergarmentBottom: UndergarmentBottomBoxersReptilian
- type: Hunger
- type: Puller
needsHands: false
- Snout
- HeadTop
- HeadSide
+ undergarmentBottom: UndergarmentBottomBoxersReptilian
- type: Inventory
speciesId: reptilian
femaleDisplacements:
- 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
- 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
sprites:
Head: MobArachnidHead
Snout: MobHumanoidAnyMarking
+ UndergarmentTop: MobHumanoidAnyMarking
+ UndergarmentBottom: MobHumanoidAnyMarking
Chest: MobArachnidTorso
HeadTop: MobHumanoidAnyMarking
HeadSide: MobHumanoidAnyMarking
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
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
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
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
Head: MobSlimeHead
Hair: MobSlimeMarkingFollowSkin
FacialHair: MobSlimeMarkingFollowSkin
+ UndergarmentTop: MobHumanoidAnyMarking
+ UndergarmentBottom: MobHumanoidAnyMarking
Chest: MobSlimeTorso
Eyes: MobHumanoidEyes
LArm: MobSlimeLArm
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
--- /dev/null
+{
+ "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