Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
591fd9b
Merge pull request #223 from LandsharkRAWR/More_Vox_Markings
formlessnameless Sep 7, 2024
f5c308e
Merge pull request #548 from hivehum/scars
formlessnameless Oct 26, 2024
fbbbaf6
Merge pull request #563 from Sha-Seng/slime-upgrades-and-markings
formlessnameless Oct 28, 2024
b03aac6
Merge pull request #591 from hivehum/scars3
formlessnameless Nov 3, 2024
1ed125c
Merge pull request #765 from hivehum/markingss
starlighthowls Nov 21, 2024
44fcdca
Merge pull request #833 from Sha-Seng/a-slime-marking
widgetbeck Nov 29, 2024
c74fbc2
Merge pull request #842 from widgetbeck/markings
TGRCdev Dec 1, 2024
a4ea605
Merge pull request #1181 from hivehum/markings
formlessnameless Jan 1, 2025
d849342
Merge pull request #1204 from hivehum/markings
Darkmajia Jan 6, 2025
95a87ed
Merge pull request #1234 from Sha-Seng/doll-tattoos
hivehum Jan 6, 2025
a85de81
Merge pull request #1240 from Sha-Seng/prosthetic-legs-show-backgroun…
mqole Jan 11, 2025
3697557
Merge pull request #1248 from hivehum/head-coverings
Darkmajia Jan 7, 2025
0ba71b3
Merge pull request #1541 from hivehum/sparklechicken
formlessnameless Feb 2, 2025
3489178
Fixed some duplications
Sage-Jones Sep 26, 2025
28cab8c
Merge pull request #1658 from hivehum/big-tail-gaming
formlessnameless Feb 11, 2025
b09df3f
Merge pull request #1740 from Sha-Seng/thaven-glowy-eyes
mqole Feb 21, 2025
477e249
Merge pull request #1763 from ATDoop/diona-markings-update
hivehum Feb 23, 2025
1a8d01f
Merge pull request #1770 from rainyatrium/pointy-lizard-markings
mqole Feb 23, 2025
628a9a0
Merge pull request #1847 from Sha-Seng/spider-cosmetics
AftrLite Mar 7, 2025
3bc9aad
Merge pull request #1483 from hivehum/markings-edits
mqole Jan 25, 2025
2a41acd
Merge pull request #1856 from Sha-Seng/spider-fuzz-colorable
hivehum Mar 10, 2025
2c6c5b2
Merge pull request #1876 from hivehum/markings-bundle-2
kipdotnet Mar 9, 2025
054ee95
Merge pull request #1957 from Sha-Seng/thaven-sharkminnow-eyes
mqole Mar 15, 2025
906b30d
tattoos and jewelry (#2059)
Sha-Seng Mar 24, 2025
d8d45e8
human/dwarf ears are now headside markings (#2083)
Sha-Seng Apr 1, 2025
f229381
vox tails are tails, not torsos!! (#2210)
mousesweater Apr 6, 2025
04e863b
markings standardization and reorganization (#2374)
hivehum May 4, 2025
61507a6
I broke so many things but I fixed them I think
Sage-Jones Sep 27, 2025
bce8d07
Begone duplicate ids
Sage-Jones Sep 27, 2025
8efcd88
No more duplicate ids! (For real!)
Sage-Jones Sep 27, 2025
8311978
Merge branch 'master' of https://github.com/QuantumBlueSS14/Quantum-B…
Sage-Jones Sep 27, 2025
7b482ce
april markings update (#2412)
hivehum May 8, 2025
8674a7a
those don't go there
Sage-Jones Sep 27, 2025
7287e63
fixing jank from #2059 (#2464)
crocodilecarousel May 12, 2025
4464932
more moth markings (mmm) (#2504)
crocodilecarousel May 15, 2025
0df01f3
PORT: Allows Markings to Set Custom Layers for Specific Sprites (#2516)
hivehum May 26, 2025
2d078d8
little thaven marking bundle (#2562)
Sha-Seng May 28, 2025
3858a73
lizard and thaven tail adjustment (#2613)
crocodilecarousel Jun 17, 2025
106dd4c
New Diona Marking: Sunflower! (#3320)
ATDoop Aug 22, 2025
ecce0c4
ive been saying i should do this for months (#3394)
Kandiyaki Sep 11, 2025
83a22d1
Fixed humanoid appearance system
Sage-Jones Sep 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
126 changes: 98 additions & 28 deletions Content.Client/Humanoid/HumanoidAppearanceSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public override void LoadProfile(EntityUid uid, HumanoidCharacterProfile? profil

var customBaseLayers = new Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo>();

var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(profile.Species);
var speciesPrototype = _prototypeManager.Index(profile.Species); // Floof
var markings = new MarkingSet(speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);

// Add markings that doesn't need coloring. We store them until we add all other markings that doesn't need it.
Expand Down Expand Up @@ -357,34 +357,106 @@ private void ApplyMarking(MarkingPrototype markingPrototype,
var humanoid = entity.Comp1;
var sprite = entity.Comp2;

if (!_sprite.LayerMapTryGet((entity.Owner, sprite), markingPrototype.BodyPart, out var targetLayer, false))
// FLOOF ADD START
// make a handy dict of filename -> colors
// cus we might need to access it by filename to link
// one sprite's colors to another
var colorDict = new Dictionary<string, Color>();
for (var i = 0; i < markingPrototype.Sprites.Count; i++)
{
return;
}

visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
&& setting.AllowsMarkings;
var spriteName = markingPrototype.Sprites[i] switch
{
SpriteSpecifier.Rsi rsi => rsi.RsiState,
SpriteSpecifier.Texture texture => texture.TexturePath.Filename,
_ => null
};

if (spriteName != null)
{
if (colors != null && i < colors.Count)
colorDict.Add(spriteName, colors[i]);
else
colorDict.Add(spriteName, Color.White);
}
}
// now, rearrange them, copying any parented colors to children set to
// inherit them
if (markingPrototype.ColorLinks != null)
{
foreach (var (child, parent) in markingPrototype.ColorLinks)
{
if (colorDict.TryGetValue(parent, out var color))
{
colorDict[child] = color;
}
}
}
// and, since we can't rely on the iterator knowing where the heck to put
// each sprite when we have one marking setting multiple layers,
// lets just kinda sorta do that ourselves
var layerDict = new Dictionary<string, int>();
// FLOOF ADD END
for (var j = 0; j < markingPrototype.Sprites.Count; j++)
{
// FLOOF CHANGE START
var markingSprite = markingPrototype.Sprites[j];

if (markingSprite is not SpriteSpecifier.Rsi rsi)
{
continue;
}

var layerSlot = markingPrototype.BodyPart;
// first, try to see if there are any custom layers for this marking
if (markingPrototype.Layering != null)
{
var name = rsi.RsiState;
if (markingPrototype.Layering.TryGetValue(name, out var layerName))
{
layerSlot = Enum.Parse<HumanoidVisualLayers>(layerName);
}
}
// update the layerDict
// if it doesnt have this, add it at 0, otherwise increment it
if (layerDict.TryGetValue(layerSlot.ToString(), out var layerIndex))
{
layerDict[layerSlot.ToString()] = layerIndex + 1;
}
else
{
layerDict.Add(layerSlot.ToString(), 0);
}

if (!sprite.LayerMapTryGet(layerSlot, out var targetLayer))
{
continue;
}

visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
&& setting.AllowsMarkings;

var layerId = $"{markingPrototype.ID}-{rsi.RsiState}";
// FLOOF CHANGE END

if (!_sprite.LayerMapTryGet((entity.Owner, sprite), layerId, out _, false))
{
var layer = _sprite.AddLayer((entity.Owner, sprite), markingSprite, targetLayer + j + 1);
_sprite.LayerMapSet((entity.Owner, sprite), layerId, layer);
_sprite.LayerSetSprite((entity.Owner, sprite), layerId, rsi);
// for layers that are supposed to be behind everything,
// adding 1 to the layer index makes it not be behind
// everything. fun! FLOOF ADD =3
// var targLayerAdj = targetLayer == 0 ? 0 + j : targetLayer + j + 1;
var targLayerAdj = targetLayer + layerDict[layerSlot.ToString()] + 1;
var layer = sprite.AddLayer(markingSprite, targLayerAdj);
sprite.LayerMapSet(layerId, layer);
sprite.LayerSetSprite(layerId, rsi);
}

_sprite.LayerSetVisible((entity.Owner, sprite), layerId, visible);
// imp special via beck. check if there's a shader defined in the markingPrototype's shader datafield, and if there is...
if (markingPrototype.Shader != null)
{
// use spriteComponent's layersetshader function to set the layer's shader to that which is specified.
sprite.LayerSetShader(layerId, markingPrototype.Shader);
}
// end imp special
sprite.LayerSetVisible(layerId, visible);

if (!visible || setting == null) // this is kinda implied
{
Expand All @@ -394,19 +466,18 @@ private void ApplyMarking(MarkingPrototype markingPrototype,
// Okay so if the marking prototype is modified but we load old marking data this may no longer be valid
// and we need to check the index is correct.
// So if that happens just default to white?
if (colors != null && j < colors.Count)
{
_sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
}
else
{
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
}

if (humanoid.MarkingsDisplacement.TryGetValue(markingPrototype.BodyPart, out var displacementData) && markingPrototype.CanBeDisplaced)
{
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _);
}
// FLOOF ADD =3
sprite.LayerSetColor(layerId, colorDict.TryGetValue(rsi.RsiState, out var color) ? color : Color.White);

// FLOOF CHANGE
// if (colors != null && j < colors.Count)
// {
// sprite.LayerSetColor(layerId, colors[j]);
// }
// else
// {
// sprite.LayerSetColor(layerId, Color.White);
// }
}
}

Expand Down Expand Up @@ -454,7 +525,6 @@ public override void SetLayerVisibility(
spriteLayer.Visible = visible;

// I fucking hate this. I'll get around to refactoring sprite layers eventually I swear
// Just a week away...

foreach (var markingList in ent.Comp.MarkingSet.Markings.Values)
{
Expand Down
27 changes: 26 additions & 1 deletion Content.Client/Humanoid/MarkingPicker.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,12 +408,37 @@ private void OnUsedMarkingSelected(ItemList.ItemListSelectedEventArgs item)
List<ColorSelectorSliders> colorSliders = new();
for (int i = 0; i < prototype.Sprites.Count; i++)
{
// first, check if the coloration is parented to another marking
// and if so, just kinda sorta dont display it
var skipdraw = false;
if (prototype.ColorLinks?.Count > 0)
{
var name = prototype.Sprites[i] switch
{
SpriteSpecifier.Rsi rsi => rsi.RsiState,
SpriteSpecifier.Texture texture => texture.TexturePath.Filename,
_ => null
};

if (name != null && prototype.ColorLinks.ContainsKey(name))
{
// dont show it, cus its parented to another marking
skipdraw = true;
}
}
var colorContainer = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
};

CMarkingColors.AddChild(colorContainer);
// so.
// the color selector sliders decide which destination color to modify
// based on its index in the list of color selectors.
// this is a problem if we, say, want to *not* show a certain slider
// cus then it'll modify the wrong color, unless the color happened to
// be in index 0.
if(!skipdraw)
CMarkingColors.AddChild(colorContainer);

ColorSelectorSliders colorSelector = new ColorSelectorSliders();
colorSliders.Add(colorSelector);
Expand Down
44 changes: 44 additions & 0 deletions Content.Shared/Humanoid/HumanoidVisualLayers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

namespace Content.Shared.Humanoid
{
/// <summary>
/// These are the layer defines for the humanoid sprite system.
/// If you want to add a new layer slot to species? Scroll down~
/// </summary>
[Serializable, NetSerializable]
public enum HumanoidVisualLayers : byte
{
Expand All @@ -17,6 +21,10 @@ public enum HumanoidVisualLayers : byte
Snout,
HeadSide, // side parts (i.e., frills)
HeadTop, // top parts (i.e., ears)
TailBehind, // FLOOF - add tails that dont have to go through a brutal cookiecutter to work
TailBehindBackpack, // imp - to layer behind backpacks, treat this like an oversuit
TailOversuit, // FLOOF - add tails that dont have to go through a brutal cookiecutter to work
TailUnderlay, // imp - temporary until i have a better way to do two part tails
Eyes,
RArm,
LArm,
Expand All @@ -33,3 +41,39 @@ public enum HumanoidVisualLayers : byte

}
}

/* * * * * * * * * * * * * * * * * * * * * * * * *
* HOW 2 ADD A NEW LAYER FOR MOB NON-EQUIPMENT APPEARANCE STUFF
* by Dank Elly
* Lets say you want to add something like socks to be selectable through markings
* Since people tend to have two feet, you'll actually need two new layers! one for each foot.
* First, add in the enum above a new layer slot, like so:
* LSock,
* RSock,
* Easy huh? Note that this enum does *not* define which layer in relation to other layers it will be layered!
* Next, since these'll be a whole new marking type, we'll need to add in a new marking category.
* in Content.Shared/Humanoid/Markings/MarkingCategories.cs, add in a new category for the socks
* lets assume we'll let the player pick two different socks, which means two different categories
* Its done the same way as this enum here
* Next, go to Content.Shared/Humanoid/HumanoidVisualLayersExtension.cs
* In here, find Sublayers() and add in the new layers to the switch statement
* case HumanoidVisualLayers.LFoot:
* yield return HumanoidVisualLayers.LSock;
* and so on. This will make it so if your leg/foot stops being visible, the sock will vanish as well! i think
* Next, we'll have to go through a lot of species files, to change a few things:
* speciesBaseSprites
* I'm not sure what this does, but you'll want to add in an entry under sprites for the new layer
* LSock: MobHumanoidAnyMarking <- I think this makes it selectable in the editor, and blank by default?
* RSock: MobHumanoidAnyMarking
* layers
* This is part of the species entity prototype, and this is where the sprite layering is defined.
* Note that this includes equipment layers, which means you can totally, say, have a tail sit between your suit and your backpack!
* - map: [ "enum.HumanoidVisualLayers.LFoot" ]
* - map: [ "enum.HumanoidVisualLayers.LSock" ]
* - map: [ "enum.HumanoidVisualLayers.RFoot" ]
* - map: [ "enum.HumanoidVisualLayers.RSock" ]
* This will make it so the socks are drawn on top of the feet, and not behind them.
* I'd list which files these are in, but there are a million different species files, all with the same name, in different folders
* So just search for "speciesBaseSprites" and "enum.HumanoidVisualLayers.Chest" and you'll find them all
* If you miss some, dont sweat it, someone'll point it out and then you can fix it! Hotties like you make the hottest hotfixes~
*/
4 changes: 4 additions & 0 deletions Content.Shared/Humanoid/HumanoidVisualLayersExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ public static IEnumerable<HumanoidVisualLayers> Sublayers(HumanoidVisualLayers l
case HumanoidVisualLayers.Chest:
yield return HumanoidVisualLayers.Chest;
yield return HumanoidVisualLayers.Tail;
yield return HumanoidVisualLayers.TailUnderlay;
yield return HumanoidVisualLayers.TailBehind;
yield return HumanoidVisualLayers.TailBehindBackpack;
yield return HumanoidVisualLayers.TailOversuit;
break;
// Shitmed Change Start
case HumanoidVisualLayers.LHand:
Expand Down
6 changes: 3 additions & 3 deletions Content.Shared/Humanoid/Markings/MarkingColoring.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ public static class MarkingColoring
/// <summary>
/// Returns list of colors for marking layers
/// </summary>
public static List<Color> GetMarkingLayerColors
(
public static List<Color> GetMarkingLayerColors(
MarkingPrototype prototype,
Color? skinColor,
Color? eyeColor,
MarkingSet markingSet
MarkingSet markingSet,
List<string>? ignores = null // Floof
)
{
var colors = new List<Color>();
Expand Down
Loading
Loading