Marking default coloring (#13039)
* Marking coloring WIP * EnsureDefault now supports coloring! * Now markings have coloring when they get added * Many things * yml files * cleanup * Some requested changes * Nullable type and WIP caching * Time to resolve that thing with deprecated hair fields * Latest reviews + im still trying to use these hair markings * FirstOrDefault thing and Tattoo docs * IDK * It's now works a bit more properly in preferences GUI * THEY SYNCING! However preferences GUI still broken and doesn't work properly * Markings now updating when changing in GUI. However they still don't work properly with bald humanoids * Forgor... * Default hair-colored markings will not color to hair if there is no hair * Fixed default colors for customizable markings * Fixed bug in prefs GUI that set current hair to null * Now markings that must match skin color because of limb (e.x. Slimes) - will match skin color * final tweaks: if hair uses skin color then markings will use skin color as hair color (slimes) * fix * fixed dirty. no more funni invis bug * Mirrors and client profile loading * default colors soon TM * review + better coloring * Hardcode is gone * diona markings * oh my god * fixed CategoryColoring * cool fallback, clean up and some other tweaks * code style * more style * a
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using Content.Shared.Ghost;
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Markings;
|
using Content.Shared.Humanoid.Markings;
|
||||||
@@ -42,6 +43,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
component.PermanentlyHidden = new(state.PermanentlyHidden);
|
component.PermanentlyHidden = new(state.PermanentlyHidden);
|
||||||
|
|
||||||
component.CustomBaseLayers = state.CustomBaseLayers.ShallowClone();
|
component.CustomBaseLayers = state.CustomBaseLayers.ShallowClone();
|
||||||
|
|
||||||
UpdateLayers(component, sprite);
|
UpdateLayers(component, sprite);
|
||||||
|
|
||||||
ApplyMarkingSet(uid, state.Markings, component, sprite);
|
ApplyMarkingSet(uid, state.Markings, component, sprite);
|
||||||
@@ -134,22 +136,66 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
var customBaseLayers = new Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo>();
|
var customBaseLayers = new Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo>();
|
||||||
|
|
||||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(profile.Species);
|
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(profile.Species);
|
||||||
var markings = new MarkingSet(profile.Appearance.Markings, speciesPrototype.MarkingPoints, _markingManager,
|
var markings = new MarkingSet(speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||||
_prototypeManager);
|
|
||||||
markings.EnsureDefault(profile.Appearance.SkinColor, _markingManager);
|
// Add markings that doesn't need coloring. We store them until we add all other markings that doesn't need it.
|
||||||
|
var markingFColored = new Dictionary<Marking, MarkingPrototype>();
|
||||||
|
foreach (var marking in profile.Appearance.Markings)
|
||||||
|
{
|
||||||
|
if (_markingManager.TryGetMarking(marking, out var prototype))
|
||||||
|
{
|
||||||
|
if (!prototype.ForcedColoring)
|
||||||
|
{
|
||||||
|
markings.AddBack(prototype.MarkingCategory, marking);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
markingFColored.Add(marking, prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// legacy: remove in the future?
|
// legacy: remove in the future?
|
||||||
markings.RemoveCategory(MarkingCategories.Hair);
|
//markings.RemoveCategory(MarkingCategories.Hair);
|
||||||
markings.RemoveCategory(MarkingCategories.FacialHair);
|
//markings.RemoveCategory(MarkingCategories.FacialHair);
|
||||||
|
|
||||||
var hair = new Marking(profile.Appearance.HairStyleId, new[] { profile.Appearance.HairColor });
|
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||||
markings.AddBack(MarkingCategories.Hair, hair);
|
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, _prototypeManager)
|
||||||
|
? profile.Appearance.SkinColor : profile.Appearance.HairColor;
|
||||||
|
var hair = new Marking(profile.Appearance.HairStyleId,
|
||||||
|
new[] { hairColor });
|
||||||
|
|
||||||
|
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, _prototypeManager)
|
||||||
|
? profile.Appearance.SkinColor : profile.Appearance.FacialHairColor;
|
||||||
var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
|
var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
|
||||||
new[] { profile.Appearance.FacialHairColor });
|
new[] { facialHairColor });
|
||||||
markings.AddBack(MarkingCategories.FacialHair, facialHair);
|
|
||||||
|
|
||||||
markings.FilterSpecies(profile.Species, _markingManager, _prototypeManager);
|
if (_markingManager.CanBeApplied(profile.Species, hair, _prototypeManager))
|
||||||
|
{
|
||||||
|
markings.AddBack(MarkingCategories.Hair, hair);
|
||||||
|
}
|
||||||
|
if (_markingManager.CanBeApplied(profile.Species, facialHair, _prototypeManager))
|
||||||
|
{
|
||||||
|
markings.AddBack(MarkingCategories.FacialHair, facialHair);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally adding marking with forced colors
|
||||||
|
foreach (var (marking, prototype) in markingFColored)
|
||||||
|
{
|
||||||
|
var markingColors = MarkingColoring.GetMarkingLayerColors(
|
||||||
|
prototype,
|
||||||
|
profile.Appearance.SkinColor,
|
||||||
|
profile.Appearance.EyeColor,
|
||||||
|
markings
|
||||||
|
);
|
||||||
|
markings.AddBack(prototype.MarkingCategory, new Marking(marking.MarkingId, markingColors));
|
||||||
|
}
|
||||||
|
|
||||||
|
markings.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||||
|
markings.EnsureDefault(
|
||||||
|
profile.Appearance.SkinColor,
|
||||||
|
profile.Appearance.EyeColor,
|
||||||
|
_markingManager);
|
||||||
|
|
||||||
DebugTools.Assert(uid.IsClientSide());
|
DebugTools.Assert(uid.IsClientSide());
|
||||||
|
|
||||||
@@ -239,7 +285,6 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
spriteComp.RemoveLayer(index);
|
spriteComp.RemoveLayer(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyMarking(EntityUid uid,
|
private void ApplyMarking(EntityUid uid,
|
||||||
MarkingPrototype markingPrototype,
|
MarkingPrototype markingPrototype,
|
||||||
IReadOnlyList<Color>? colors,
|
IReadOnlyList<Color>? colors,
|
||||||
@@ -279,16 +324,13 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markingPrototype.FollowSkinColor || colors == null || setting.MarkingsMatchSkin)
|
if (colors != null)
|
||||||
{
|
{
|
||||||
var skinColor = humanoid.SkinColor;
|
sprite.LayerSetColor(layerId, colors[j]);
|
||||||
skinColor.A = setting.LayerAlpha;
|
|
||||||
|
|
||||||
sprite.LayerSetColor(layerId, skinColor);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite.LayerSetColor(layerId, colors[j]);
|
sprite.LayerSetColor(layerId, Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,11 +60,13 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
string? state = _protoMan.HasIndex<HumanoidSpeciesSpriteLayer>(modifier.Text) ? modifier.Text : null;
|
string? state = _protoMan.HasIndex<HumanoidSpeciesSpriteLayer>(modifier.Text) ? modifier.Text : null;
|
||||||
OnLayerInfoModified?.Invoke(layer, new CustomBaseLayerInfo(state, modifier.Color));
|
OnLayerInfoModified?.Invoke(layer, new CustomBaseLayerInfo(state, modifier.Color));
|
||||||
}
|
}
|
||||||
|
public void SetState(
|
||||||
public void SetState(MarkingSet markings, string species, Color skinColor, Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info)
|
MarkingSet markings,
|
||||||
|
string species,
|
||||||
|
Color skinColor,
|
||||||
|
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info
|
||||||
|
)
|
||||||
{
|
{
|
||||||
MarkingPickerWidget.SetData(markings, species, skinColor);
|
|
||||||
|
|
||||||
foreach (var (layer, modifier) in _modifiers)
|
foreach (var (layer, modifier) in _modifiers)
|
||||||
{
|
{
|
||||||
if (!info.TryGetValue(layer, out var layerInfo))
|
if (!info.TryGetValue(layer, out var layerInfo))
|
||||||
@@ -75,6 +77,14 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
|
|
||||||
modifier.SetState(true, layerInfo.ID ?? string.Empty, layerInfo.Color ?? Color.White);
|
modifier.SetState(true, layerInfo.ID ?? string.Empty, layerInfo.Color ?? Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var eyesColor = Color.White;
|
||||||
|
if (info.TryGetValue(HumanoidVisualLayers.Eyes, out var eyes) && eyes.Color != null)
|
||||||
|
{
|
||||||
|
eyesColor = eyes.Color.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkingPickerWidget.SetData(markings, species, skinColor, eyesColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class HumanoidBaseLayerModifier : BoxContainer
|
private sealed class HumanoidBaseLayerModifier : BoxContainer
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public sealed partial class MarkingPicker : Control
|
|||||||
|
|
||||||
private string _currentSpecies = SharedHumanoidAppearanceSystem.DefaultSpecies;
|
private string _currentSpecies = SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||||
public Color CurrentSkinColor = Color.White;
|
public Color CurrentSkinColor = Color.White;
|
||||||
|
public Color CurrentEyeColor = Color.Black;
|
||||||
|
public Marking? HairMarking;
|
||||||
|
public Marking? FacialHairMarking;
|
||||||
|
|
||||||
private readonly HashSet<MarkingCategories> _ignoreCategories = new();
|
private readonly HashSet<MarkingCategories> _ignoreCategories = new();
|
||||||
|
|
||||||
@@ -74,7 +77,7 @@ public sealed partial class MarkingPicker : Control
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(List<Marking> newMarkings, string species, Color skinColor)
|
public void SetData(List<Marking> newMarkings, string species, Color skinColor, Color eyeColor)
|
||||||
{
|
{
|
||||||
var pointsProto = _prototypeManager
|
var pointsProto = _prototypeManager
|
||||||
.Index<SpeciesPrototype>(species).MarkingPoints;
|
.Index<SpeciesPrototype>(species).MarkingPoints;
|
||||||
@@ -82,33 +85,36 @@ public sealed partial class MarkingPicker : Control
|
|||||||
|
|
||||||
if (!IgnoreSpecies)
|
if (!IgnoreSpecies)
|
||||||
{
|
{
|
||||||
_currentMarkings.FilterSpecies(species); // should be validated server-side but it can't hurt
|
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSpecies = species;
|
_currentSpecies = species;
|
||||||
CurrentSkinColor = skinColor;
|
CurrentSkinColor = skinColor;
|
||||||
|
CurrentEyeColor = eyeColor;
|
||||||
|
|
||||||
Populate();
|
Populate();
|
||||||
PopulateUsed();
|
PopulateUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(MarkingSet set, string species, Color skinColor)
|
public void SetData(MarkingSet set, string species, Color skinColor, Color eyeColor)
|
||||||
{
|
{
|
||||||
_currentMarkings = set;
|
_currentMarkings = set;
|
||||||
|
|
||||||
if (!IgnoreSpecies)
|
if (!IgnoreSpecies)
|
||||||
{
|
{
|
||||||
_currentMarkings.FilterSpecies(species); // should be validated server-side but it can't hurt
|
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentSpecies = species;
|
_currentSpecies = species;
|
||||||
CurrentSkinColor = skinColor;
|
CurrentSkinColor = skinColor;
|
||||||
|
CurrentEyeColor = eyeColor;
|
||||||
|
|
||||||
Populate();
|
Populate();
|
||||||
PopulateUsed();
|
PopulateUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSkinColor(Color color) => CurrentSkinColor = color;
|
public void SetSkinColor(Color color) => CurrentSkinColor = color;
|
||||||
|
public void SetEyeColor(Color color) => CurrentEyeColor = color;
|
||||||
|
|
||||||
public MarkingPicker()
|
public MarkingPicker()
|
||||||
{
|
{
|
||||||
@@ -201,7 +207,7 @@ public sealed partial class MarkingPicker : Control
|
|||||||
|
|
||||||
if (!IgnoreSpecies)
|
if (!IgnoreSpecies)
|
||||||
{
|
{
|
||||||
_currentMarkings.FilterSpecies(_currentSpecies, _markingManager);
|
_currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk backwards through the list for visual purposes
|
// walk backwards through the list for visual purposes
|
||||||
@@ -305,7 +311,7 @@ public sealed partial class MarkingPicker : Control
|
|||||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(species);
|
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(species);
|
||||||
|
|
||||||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||||
_currentMarkings.FilterSpecies(species);
|
_currentMarkings.EnsureSpecies(species, null, _markingManager);
|
||||||
|
|
||||||
Populate();
|
Populate();
|
||||||
PopulateUsed();
|
PopulateUsed();
|
||||||
@@ -335,7 +341,7 @@ public sealed partial class MarkingPicker : Control
|
|||||||
_selectedMarking = CMarkingsUsed[item.ItemIndex];
|
_selectedMarking = CMarkingsUsed[item.ItemIndex];
|
||||||
var prototype = (MarkingPrototype) _selectedMarking.Metadata!;
|
var prototype = (MarkingPrototype) _selectedMarking.Metadata!;
|
||||||
|
|
||||||
if (prototype.FollowSkinColor)
|
if (prototype.ForcedColoring)
|
||||||
{
|
{
|
||||||
CMarkingColors.Visible = false;
|
CMarkingColors.Visible = false;
|
||||||
|
|
||||||
@@ -412,12 +418,40 @@ public sealed partial class MarkingPicker : Control
|
|||||||
}
|
}
|
||||||
|
|
||||||
var marking = (MarkingPrototype) _selectedUnusedMarking.Metadata!;
|
var marking = (MarkingPrototype) _selectedUnusedMarking.Metadata!;
|
||||||
|
|
||||||
|
|
||||||
var markingObject = marking.AsMarking();
|
var markingObject = marking.AsMarking();
|
||||||
for (var i = 0; i < markingObject.MarkingColors.Count; i++)
|
|
||||||
|
// We need add hair markings in cloned set manually because _currentMarkings doesn't have it
|
||||||
|
var markingSet = new MarkingSet(_currentMarkings);
|
||||||
|
if (HairMarking != null)
|
||||||
{
|
{
|
||||||
markingObject.SetColor(i, CurrentSkinColor);
|
markingSet.AddBack(MarkingCategories.Hair, HairMarking);
|
||||||
|
}
|
||||||
|
if (FacialHairMarking != null)
|
||||||
|
{
|
||||||
|
markingSet.AddBack(MarkingCategories.FacialHair, FacialHairMarking);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_markingManager.MustMatchSkin(_currentSpecies, marking.BodyPart, _prototypeManager))
|
||||||
|
{
|
||||||
|
// Do default coloring
|
||||||
|
var colors = MarkingColoring.GetMarkingLayerColors(
|
||||||
|
marking,
|
||||||
|
CurrentSkinColor,
|
||||||
|
CurrentEyeColor,
|
||||||
|
markingSet
|
||||||
|
);
|
||||||
|
for (var i = 0; i < colors.Count; i++)
|
||||||
|
{
|
||||||
|
markingObject.SetColor(i, colors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Color everything in skin color
|
||||||
|
for (var i = 0; i < marking.Sprites.Count; i++)
|
||||||
|
{
|
||||||
|
markingObject.SetColor(i, CurrentSkinColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
markingObject.Forced = Forced;
|
markingObject.Forced = Forced;
|
||||||
|
|||||||
@@ -223,6 +223,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
return;
|
return;
|
||||||
Profile = Profile.WithCharacterAppearance(
|
Profile = Profile.WithCharacterAppearance(
|
||||||
Profile.Appearance.WithHairColor(newColor.marking.MarkingColors[0]));
|
Profile.Appearance.WithHairColor(newColor.marking.MarkingColors[0]));
|
||||||
|
UpdateCMarkingsHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -241,6 +242,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
return;
|
return;
|
||||||
Profile = Profile.WithCharacterAppearance(
|
Profile = Profile.WithCharacterAppearance(
|
||||||
Profile.Appearance.WithFacialHairColor(newColor.marking.MarkingColors[0]));
|
Profile.Appearance.WithFacialHairColor(newColor.marking.MarkingColors[0]));
|
||||||
|
UpdateCMarkingsFacialHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -252,6 +254,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
Profile.Appearance.WithHairStyleName(HairStyles.DefaultHairStyle)
|
Profile.Appearance.WithHairStyleName(HairStyles.DefaultHairStyle)
|
||||||
);
|
);
|
||||||
UpdateHairPickers();
|
UpdateHairPickers();
|
||||||
|
UpdateCMarkingsHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -263,6 +266,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
Profile.Appearance.WithFacialHairStyleName(HairStyles.DefaultFacialHairStyle)
|
Profile.Appearance.WithFacialHairStyleName(HairStyles.DefaultFacialHairStyle)
|
||||||
);
|
);
|
||||||
UpdateHairPickers();
|
UpdateHairPickers();
|
||||||
|
UpdateCMarkingsFacialHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -282,7 +286,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
);
|
);
|
||||||
|
|
||||||
UpdateHairPickers();
|
UpdateHairPickers();
|
||||||
|
UpdateCMarkingsHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -302,7 +306,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
);
|
);
|
||||||
|
|
||||||
UpdateHairPickers();
|
UpdateHairPickers();
|
||||||
|
UpdateCMarkingsFacialHair();
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -343,6 +347,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
return;
|
return;
|
||||||
Profile = Profile.WithCharacterAppearance(
|
Profile = Profile.WithCharacterAppearance(
|
||||||
Profile.Appearance.WithEyeColor(newColor));
|
Profile.Appearance.WithEyeColor(newColor));
|
||||||
|
CMarkings.CurrentEyeColor = Profile.Appearance.EyeColor;
|
||||||
IsDirty = true;
|
IsDirty = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -646,7 +651,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
var color = SkinColor.HumanSkinTone((int) _skinColor.Value);
|
var color = SkinColor.HumanSkinTone((int) _skinColor.Value);
|
||||||
|
|
||||||
CMarkings.CurrentSkinColor = color;
|
CMarkings.CurrentSkinColor = color;
|
||||||
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));
|
Profile = Profile.WithCharacterAppearance(Profile.Appearance.WithSkinColor(color));//
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HumanoidSkinColor.Hues:
|
case HumanoidSkinColor.Hues:
|
||||||
@@ -746,8 +751,8 @@ namespace Content.Client.Preferences.UI
|
|||||||
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences!.SelectedCharacter;
|
Profile = (HumanoidCharacterProfile) _preferencesManager.Preferences!.SelectedCharacter;
|
||||||
CharacterSlot = _preferencesManager.Preferences.SelectedCharacterIndex;
|
CharacterSlot = _preferencesManager.Preferences.SelectedCharacterIndex;
|
||||||
|
|
||||||
_needUpdatePreview = true;
|
|
||||||
UpdateControls();
|
UpdateControls();
|
||||||
|
_needUpdatePreview = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetAge(int newAge)
|
private void SetAge(int newAge)
|
||||||
@@ -941,7 +946,9 @@ namespace Content.Client.Preferences.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMarkings.SetData(Profile.Appearance.Markings, Profile.Species, Profile.Appearance.SkinColor);
|
CMarkings.SetData(Profile.Appearance.Markings, Profile.Species,
|
||||||
|
Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSpecies()
|
private void UpdateSpecies()
|
||||||
@@ -990,7 +997,6 @@ namespace Content.Client.Preferences.UI
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hairMarking = Profile.Appearance.HairStyleId switch
|
var hairMarking = Profile.Appearance.HairStyleId switch
|
||||||
{
|
{
|
||||||
HairStyles.DefaultHairStyle => new List<Marking>(),
|
HairStyles.DefaultHairStyle => new List<Marking>(),
|
||||||
@@ -1013,6 +1019,76 @@ namespace Content.Client.Preferences.UI
|
|||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateCMarkingsHair()
|
||||||
|
{
|
||||||
|
if (Profile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hair color
|
||||||
|
Color? hairColor = null;
|
||||||
|
if ( Profile.Appearance.HairStyleId != HairStyles.DefaultHairStyle &&
|
||||||
|
_markingManager.Markings.TryGetValue(Profile.Appearance.HairStyleId, out var hairProto)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (_markingManager.CanBeApplied(Profile.Species, hairProto, _prototypeManager))
|
||||||
|
{
|
||||||
|
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, _prototypeManager))
|
||||||
|
{
|
||||||
|
hairColor = Profile.Appearance.SkinColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hairColor = Profile.Appearance.HairColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hairColor != null)
|
||||||
|
{
|
||||||
|
CMarkings.HairMarking = new (Profile.Appearance.HairStyleId, new List<Color>() { hairColor.Value });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CMarkings.HairMarking = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCMarkingsFacialHair()
|
||||||
|
{
|
||||||
|
if (Profile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// facial hair color
|
||||||
|
Color? facialHairColor = null;
|
||||||
|
if ( Profile.Appearance.FacialHairStyleId != HairStyles.DefaultFacialHairStyle &&
|
||||||
|
_markingManager.Markings.TryGetValue(Profile.Appearance.FacialHairStyleId, out var facialHairProto)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (_markingManager.CanBeApplied(Profile.Species, facialHairProto, _prototypeManager))
|
||||||
|
{
|
||||||
|
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, _prototypeManager))
|
||||||
|
{
|
||||||
|
facialHairColor = Profile.Appearance.SkinColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facialHairColor = Profile.Appearance.FacialHairColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (facialHairColor != null)
|
||||||
|
{
|
||||||
|
CMarkings.FacialHairMarking = new (Profile.Appearance.FacialHairStyleId, new List<Color>() { facialHairColor.Value });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CMarkings.FacialHairMarking = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateEyePickers()
|
private void UpdateEyePickers()
|
||||||
{
|
{
|
||||||
if (Profile == null)
|
if (Profile == null)
|
||||||
@@ -1020,6 +1096,7 @@ namespace Content.Client.Preferences.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMarkings.CurrentEyeColor = Profile.Appearance.EyeColor;
|
||||||
_eyesPicker.SetData(Profile.Appearance.EyeColor);
|
_eyesPicker.SetData(Profile.Appearance.EyeColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,7 +1126,6 @@ namespace Content.Client.Preferences.UI
|
|||||||
UpdateClothingControls();
|
UpdateClothingControls();
|
||||||
UpdateBackpackControls();
|
UpdateBackpackControls();
|
||||||
UpdateAgeEdit();
|
UpdateAgeEdit();
|
||||||
UpdateHairPickers();
|
|
||||||
UpdateEyePickers();
|
UpdateEyePickers();
|
||||||
UpdateSaveButton();
|
UpdateSaveButton();
|
||||||
UpdateJobPriorities();
|
UpdateJobPriorities();
|
||||||
@@ -1057,6 +1133,9 @@ namespace Content.Client.Preferences.UI
|
|||||||
UpdateTraitPreferences();
|
UpdateTraitPreferences();
|
||||||
UpdateMarkings();
|
UpdateMarkings();
|
||||||
RebuildSpriteView();
|
RebuildSpriteView();
|
||||||
|
UpdateHairPickers();
|
||||||
|
UpdateCMarkingsHair();
|
||||||
|
UpdateCMarkingsFacialHair();
|
||||||
|
|
||||||
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadProfile(uid, startingSet.Profile, humanoid);
|
LoadProfile(uid, startingSet.Profile, humanoid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
|
private void OnExamined(EntityUid uid, HumanoidAppearanceComponent component, ExaminedEvent args)
|
||||||
@@ -79,14 +80,54 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
|||||||
|
|
||||||
humanoid.MarkingSet.Clear();
|
humanoid.MarkingSet.Clear();
|
||||||
|
|
||||||
// Hair/facial hair - this may eventually be deprecated.
|
// Add markings that doesn't need coloring. We store them until we add all other markings that doesn't need it.
|
||||||
|
var markingFColored = new Dictionary<Marking, MarkingPrototype>();
|
||||||
AddMarking(uid, profile.Appearance.HairStyleId, profile.Appearance.HairColor, false);
|
|
||||||
AddMarking(uid, profile.Appearance.FacialHairStyleId, profile.Appearance.FacialHairColor, false);
|
|
||||||
|
|
||||||
foreach (var marking in profile.Appearance.Markings)
|
foreach (var marking in profile.Appearance.Markings)
|
||||||
{
|
{
|
||||||
AddMarking(uid, marking.MarkingId, marking.MarkingColors, false);
|
if (_markingManager.TryGetMarking(marking, out var prototype))
|
||||||
|
{
|
||||||
|
if (!prototype.ForcedColoring)
|
||||||
|
{
|
||||||
|
AddMarking(uid, marking.MarkingId, marking.MarkingColors, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
markingFColored.Add(marking, prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hair/facial hair - this may eventually be deprecated.
|
||||||
|
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||||
|
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, _prototypeManager)
|
||||||
|
? profile.Appearance.SkinColor : profile.Appearance.HairColor;
|
||||||
|
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, _prototypeManager)
|
||||||
|
? profile.Appearance.SkinColor : profile.Appearance.FacialHairColor;
|
||||||
|
|
||||||
|
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
|
||||||
|
_markingManager.CanBeApplied(profile.Species, hairPrototype, _prototypeManager))
|
||||||
|
{
|
||||||
|
AddMarking(uid, profile.Appearance.HairStyleId, hairColor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_markingManager.Markings.TryGetValue(profile.Appearance.FacialHairStyleId, out var facialHairPrototype) &&
|
||||||
|
_markingManager.CanBeApplied(profile.Species, facialHairPrototype, _prototypeManager))
|
||||||
|
{
|
||||||
|
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||||
|
|
||||||
|
// Finally adding marking with forced colors
|
||||||
|
foreach (var (marking, prototype) in markingFColored)
|
||||||
|
{
|
||||||
|
var markingColors = MarkingColoring.GetMarkingLayerColors(
|
||||||
|
prototype,
|
||||||
|
profile.Appearance.SkinColor,
|
||||||
|
profile.Appearance.EyeColor,
|
||||||
|
humanoid.MarkingSet
|
||||||
|
);
|
||||||
|
AddMarking(uid, marking.MarkingId, markingColors, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EnsureDefaultMarkings(uid, humanoid);
|
EnsureDefaultMarkings(uid, humanoid);
|
||||||
@@ -336,7 +377,6 @@ public sealed partial class HumanoidAppearanceSystem : SharedHumanoidAppearanceS
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
humanoid.MarkingSet.EnsureDefault(humanoid.SkinColor, humanoid.EyeColor, _markingManager);
|
||||||
humanoid.MarkingSet.EnsureDefault(humanoid.SkinColor, _markingManager);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ public sealed partial class HumanoidAppearanceSystem
|
|||||||
_uiSystem.TrySetUiState(
|
_uiSystem.TrySetUiState(
|
||||||
uid,
|
uid,
|
||||||
HumanoidMarkingModifierKey.Key,
|
HumanoidMarkingModifierKey.Key,
|
||||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species, component.SkinColor, component.CustomBaseLayers));
|
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||||
|
component.SkinColor,
|
||||||
|
component.CustomBaseLayers
|
||||||
|
));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -66,7 +69,10 @@ public sealed partial class HumanoidAppearanceSystem
|
|||||||
_uiSystem.TrySetUiState(
|
_uiSystem.TrySetUiState(
|
||||||
uid,
|
uid,
|
||||||
HumanoidMarkingModifierKey.Key,
|
HumanoidMarkingModifierKey.Key,
|
||||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species, component.SkinColor, component.CustomBaseLayers));
|
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||||
|
component.SkinColor,
|
||||||
|
component.CustomBaseLayers
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +93,10 @@ public sealed partial class HumanoidAppearanceSystem
|
|||||||
_uiSystem.TrySetUiState(
|
_uiSystem.TrySetUiState(
|
||||||
uid,
|
uid,
|
||||||
HumanoidMarkingModifierKey.Key,
|
HumanoidMarkingModifierKey.Key,
|
||||||
new HumanoidMarkingModifierState(component.MarkingSet, component.Species, component.SkinColor, component.CustomBaseLayers));
|
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
|
||||||
|
component.SkinColor,
|
||||||
|
component.CustomBaseLayers
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,18 @@ public sealed class HumanoidAppearanceComponent : Component
|
|||||||
|
|
||||||
[DataField("eyeColor")]
|
[DataField("eyeColor")]
|
||||||
public Color EyeColor = Color.Brown;
|
public Color EyeColor = Color.Brown;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hair color of this humanoid. Used to avoid looping through all markings
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
public Color? CachedHairColor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Facial Hair color of this humanoid. Used to avoid looping through all markings
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
public Color? CachedFacialHairColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ namespace Content.Shared.Humanoid
|
|||||||
{
|
{
|
||||||
markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
|
markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
|
||||||
markingSet.EnsureValid(markingManager);
|
markingSet.EnsureValid(markingManager);
|
||||||
markingSet.FilterSpecies(species, markingManager);
|
|
||||||
|
|
||||||
switch (speciesProto.SkinColoration)
|
switch (speciesProto.SkinColoration)
|
||||||
{
|
{
|
||||||
@@ -236,6 +235,7 @@ namespace Content.Shared.Humanoid
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
markingSet.EnsureSpecies(species, skinColor, markingManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HumanoidCharacterAppearance(
|
return new HumanoidCharacterAppearance(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Robust.Shared.Serialization;
|
using Content.Shared.Humanoid.Markings;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Humanoid
|
namespace Content.Shared.Humanoid
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors marking in color of first defined marking from specified category (in e.x. from Hair category)
|
||||||
|
/// </summary>
|
||||||
|
public sealed class CategoryColoring : LayerColoringType
|
||||||
|
{
|
||||||
|
[DataField("category", required: true)]
|
||||||
|
public MarkingCategories Category;
|
||||||
|
|
||||||
|
public override Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
Color? outColor = null;
|
||||||
|
if (markingSet.TryGetCategory(Category, out var markings) &&
|
||||||
|
markings.Count > 0)
|
||||||
|
{
|
||||||
|
outColor = markings[0].MarkingColors.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return outColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors layer in an eye color
|
||||||
|
/// </summary>
|
||||||
|
public sealed class EyeColoring : LayerColoringType
|
||||||
|
{
|
||||||
|
public override Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
return eyes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors layer in a specified color
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SimpleColoring : LayerColoringType
|
||||||
|
{
|
||||||
|
[DataField("color", required: true)]
|
||||||
|
public Color Color = Color.White;
|
||||||
|
|
||||||
|
public override Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
return Color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors layer in a skin color
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SkinColoring : LayerColoringType
|
||||||
|
{
|
||||||
|
public override Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
return skin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colors layer in skin color but much darker.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TattooColoring : LayerColoringType
|
||||||
|
{
|
||||||
|
public override Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
if (skin == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newColor = Color.ToHsv(skin.Value);
|
||||||
|
newColor.Z = .40f;
|
||||||
|
|
||||||
|
return Color.FromHsv(newColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.Humanoid.Markings
|
namespace Content.Shared.Humanoid.Markings
|
||||||
@@ -67,6 +69,14 @@ namespace Content.Shared.Humanoid.Markings
|
|||||||
public void SetColor(int colorIndex, Color color) =>
|
public void SetColor(int colorIndex, Color color) =>
|
||||||
_markingColors[colorIndex] = color;
|
_markingColors[colorIndex] = color;
|
||||||
|
|
||||||
|
public void SetColor(Color color)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _markingColors.Count; i++)
|
||||||
|
{
|
||||||
|
_markingColors[i] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int CompareTo(Marking? marking)
|
public int CompareTo(Marking? marking)
|
||||||
{
|
{
|
||||||
if (marking == null)
|
if (marking == null)
|
||||||
|
|||||||
147
Content.Shared/Humanoid/Markings/MarkingColoring.cs
Normal file
147
Content.Shared/Humanoid/Markings/MarkingColoring.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default colors for marking
|
||||||
|
/// </summary>
|
||||||
|
[DataDefinition]
|
||||||
|
public sealed class MarkingColors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Coloring properties that will be used on any unspecified layer
|
||||||
|
/// </summary>
|
||||||
|
[DataField("default", true)]
|
||||||
|
public LayerColoringDefinition Default = new LayerColoringDefinition();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Layers with their own coloring type and properties
|
||||||
|
/// </summary>
|
||||||
|
[DataField("layers", true)]
|
||||||
|
public Dictionary<string, LayerColoringDefinition>? Layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MarkingColoring
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns list of colors for marking layers
|
||||||
|
/// </summary>
|
||||||
|
public static List<Color> GetMarkingLayerColors
|
||||||
|
(
|
||||||
|
MarkingPrototype prototype,
|
||||||
|
Color? skinColor,
|
||||||
|
Color? eyeColor,
|
||||||
|
MarkingSet markingSet
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var colors = new List<Color>();
|
||||||
|
|
||||||
|
// Coloring from default properties
|
||||||
|
var defaultColor = prototype.Coloring.Default.GetColor(skinColor, eyeColor, markingSet);
|
||||||
|
|
||||||
|
if (prototype.Coloring.Layers == null)
|
||||||
|
{
|
||||||
|
// If layers is not specified, then every layer must be default
|
||||||
|
for (var i = 0; i < prototype.Sprites.Count; i++)
|
||||||
|
{
|
||||||
|
colors.Add(defaultColor);
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If some layers are specified.
|
||||||
|
for (var i = 0; i < prototype.Sprites.Count; i++)
|
||||||
|
{
|
||||||
|
// Getting layer name
|
||||||
|
string? name = prototype.Sprites[i] switch
|
||||||
|
{
|
||||||
|
SpriteSpecifier.Rsi rsi => rsi.RsiState,
|
||||||
|
SpriteSpecifier.Texture texture => texture.TexturePath.Filename,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
colors.Add(defaultColor);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All specified layers must be colored separately, all unspecified must depend on default coloring
|
||||||
|
if (prototype.Coloring.Layers.TryGetValue(name, out var layerColoring))
|
||||||
|
{
|
||||||
|
var marking_color = layerColoring.GetColor(skinColor, eyeColor, markingSet);
|
||||||
|
colors.Add(marking_color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors.Add(defaultColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class that defines coloring type and fallback for markings
|
||||||
|
/// </summary>
|
||||||
|
[DataDefinition]
|
||||||
|
public sealed class LayerColoringDefinition
|
||||||
|
{
|
||||||
|
[DataField("type")]
|
||||||
|
public LayerColoringType Type = new SkinColoring();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Coloring types that will be used if main coloring type will return nil
|
||||||
|
/// </summary>
|
||||||
|
[DataField("fallbackTypes")]
|
||||||
|
public List<LayerColoringType> FallbackTypes = new() {};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Color that will be used if coloring type and fallback type will return nil
|
||||||
|
/// </summary>
|
||||||
|
[DataField("fallbackColor")]
|
||||||
|
public Color FallbackColor = Color.White;
|
||||||
|
|
||||||
|
public Color GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
var color = Type.GetColor(skin, eyes, markingSet);
|
||||||
|
if (color == null)
|
||||||
|
{
|
||||||
|
foreach (var type in FallbackTypes)
|
||||||
|
{
|
||||||
|
color = type.GetColor(skin, eyes, markingSet);
|
||||||
|
if (color != null) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color ?? FallbackColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract class for coloring types
|
||||||
|
/// </summary>
|
||||||
|
[ImplicitDataDefinitionForInheritors]
|
||||||
|
public abstract class LayerColoringType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Makes output color negative
|
||||||
|
/// </summary>
|
||||||
|
[DataField("negative")]
|
||||||
|
public bool Negative { get; } = false;
|
||||||
|
public abstract Color? GetCleanColor(Color? skin, Color? eyes, MarkingSet markingSet);
|
||||||
|
public Color? GetColor(Color? skin, Color? eyes, MarkingSet markingSet)
|
||||||
|
{
|
||||||
|
var color = GetCleanColor(skin, eyes, markingSet);
|
||||||
|
// Negative color
|
||||||
|
if (color != null && Negative)
|
||||||
|
{
|
||||||
|
var rcolor = color.Value;
|
||||||
|
rcolor.R = 1f-rcolor.R;
|
||||||
|
rcolor.G = 1f-rcolor.G;
|
||||||
|
rcolor.B = 1f-rcolor.B;
|
||||||
|
return rcolor;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,5 +120,69 @@ namespace Content.Shared.Humanoid.Markings
|
|||||||
_index.Add(markingPrototype);
|
_index.Add(markingPrototype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanBeApplied(string species, Marking marking, IPrototypeManager? prototypeManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref prototypeManager);
|
||||||
|
|
||||||
|
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||||
|
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||||
|
|
||||||
|
if (!TryGetMarking(marking, out var prototype))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlyWhitelisted && prototype.SpeciesRestrictions == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prototype.SpeciesRestrictions != null
|
||||||
|
&& !prototype.SpeciesRestrictions.Contains(species))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanBeApplied(string species, MarkingPrototype prototype, IPrototypeManager? prototypeManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref prototypeManager);
|
||||||
|
|
||||||
|
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||||
|
var onlyWhitelisted = prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
|
||||||
|
|
||||||
|
if (onlyWhitelisted && prototype.SpeciesRestrictions == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prototype.SpeciesRestrictions != null &&
|
||||||
|
!prototype.SpeciesRestrictions.Contains(species))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MustMatchSkin(string species, HumanoidVisualLayers layer, IPrototypeManager? prototypeManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref prototypeManager);
|
||||||
|
|
||||||
|
var speciesProto = prototypeManager.Index<SpeciesPrototype>(species);
|
||||||
|
if (
|
||||||
|
!prototypeManager.TryIndex(speciesProto.SpriteSet, out HumanoidSpeciesBaseSpritesPrototype? baseSprites) ||
|
||||||
|
!baseSprites.Sprites.TryGetValue(layer, out var spriteName) ||
|
||||||
|
!prototypeManager.TryIndex(spriteName, out HumanoidSpeciesSpriteLayer? sprite) ||
|
||||||
|
sprite == null ||
|
||||||
|
!sprite.MarkingsMatchSkin
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ namespace Content.Shared.Humanoid.Markings
|
|||||||
[DataField("followSkinColor")]
|
[DataField("followSkinColor")]
|
||||||
public bool FollowSkinColor { get; } = false;
|
public bool FollowSkinColor { get; } = false;
|
||||||
|
|
||||||
|
[DataField("forcedColoring")]
|
||||||
|
public bool ForcedColoring { get; } = false;
|
||||||
|
|
||||||
|
[DataField("coloring")]
|
||||||
|
public MarkingColors Coloring { get; } = new();
|
||||||
|
|
||||||
[DataField("sprites", required: true)]
|
[DataField("sprites", required: true)]
|
||||||
public List<SpriteSpecifier> Sprites { get; private set; } = default!;
|
public List<SpriteSpecifier> Sprites { get; private set; } = default!;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Humanoid.Markings;
|
namespace Content.Shared.Humanoid.Markings;
|
||||||
|
|
||||||
@@ -104,6 +105,22 @@ public sealed class MarkingSet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a MarkingSet only with a points dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pointsPrototype">The ID of the points dictionary prototype.</param>
|
||||||
|
public MarkingSet(string pointsPrototype, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||||
|
{
|
||||||
|
IoCManager.Resolve(ref markingManager, ref prototypeManager);
|
||||||
|
|
||||||
|
if (!prototypeManager.TryIndex(pointsPrototype, out MarkingPointsPrototype? points))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Points = MarkingPoints.CloneMarkingPointDictionary(points.Points);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Construct a MarkingSet by deep cloning another set.
|
/// Construct a MarkingSet by deep cloning another set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -122,12 +139,13 @@ public sealed class MarkingSet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filters markings based on species restrictions in the marking's prototype from this marking set.
|
/// Filters and colors markings based on species and it's restrictions in the marking's prototype from this marking set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="species">The species to filter.</param>
|
/// <param name="species">The species to filter.</param>
|
||||||
|
/// <param name="skinColor">The skin color for recoloring (i.e. slimes). Use null if you want only filter markings</param>
|
||||||
/// <param name="markingManager">Marking manager.</param>
|
/// <param name="markingManager">Marking manager.</param>
|
||||||
/// <param name="prototypeManager">Prototype manager.</param>
|
/// <param name="prototypeManager">Prototype manager.</param>
|
||||||
public void FilterSpecies(string species, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
public void EnsureSpecies(string species, Color? skinColor, MarkingManager? markingManager = null, IPrototypeManager? prototypeManager = null)
|
||||||
{
|
{
|
||||||
IoCManager.Resolve(ref markingManager);
|
IoCManager.Resolve(ref markingManager);
|
||||||
IoCManager.Resolve(ref prototypeManager);
|
IoCManager.Resolve(ref prototypeManager);
|
||||||
@@ -163,6 +181,22 @@ public sealed class MarkingSet
|
|||||||
{
|
{
|
||||||
Remove(remove.category, remove.id);
|
Remove(remove.category, remove.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-color left markings them into skin color if needed (i.e. for slimes)
|
||||||
|
if (skinColor != null)
|
||||||
|
{
|
||||||
|
foreach (var (category, list) in Markings)
|
||||||
|
{
|
||||||
|
foreach (var marking in list)
|
||||||
|
{
|
||||||
|
if (markingManager.TryGetMarking(marking, out var prototype) &&
|
||||||
|
markingManager.MustMatchSkin(species, prototype.BodyPart, prototypeManager))
|
||||||
|
{
|
||||||
|
marking.SetColor(skinColor.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -200,9 +234,11 @@ public sealed class MarkingSet
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ensures that the default markings as defined by the marking point set in this marking set are applied.
|
/// Ensures that the default markings as defined by the marking point set in this marking set are applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skinColor">Color to apply.</param>
|
/// <param name="skinColor">Skin color for marking coloring.</param>
|
||||||
|
/// <param name="eyeColor">Eye color for marking coloring.</param>
|
||||||
|
/// <param name="hairColor">Hair color for marking coloring.</param>
|
||||||
/// <param name="markingManager">Marking manager.</param>
|
/// <param name="markingManager">Marking manager.</param>
|
||||||
public void EnsureDefault(Color? skinColor = null, MarkingManager? markingManager = null)
|
public void EnsureDefault(Color? skinColor = null, Color? eyeColor = null, MarkingManager? markingManager = null)
|
||||||
{
|
{
|
||||||
IoCManager.Resolve(ref markingManager);
|
IoCManager.Resolve(ref markingManager);
|
||||||
|
|
||||||
@@ -218,22 +254,13 @@ public sealed class MarkingSet
|
|||||||
{
|
{
|
||||||
if (markingManager.Markings.TryGetValue(points.DefaultMarkings[index], out var prototype))
|
if (markingManager.Markings.TryGetValue(points.DefaultMarkings[index], out var prototype))
|
||||||
{
|
{
|
||||||
Marking marking;
|
var colors = MarkingColoring.GetMarkingLayerColors(
|
||||||
if (skinColor == null)
|
prototype,
|
||||||
{
|
skinColor,
|
||||||
marking = new Marking(points.DefaultMarkings[index], prototype.Sprites.Count);
|
eyeColor,
|
||||||
}
|
this
|
||||||
else
|
);
|
||||||
{
|
var marking = new Marking(points.DefaultMarkings[index], colors);
|
||||||
var colors = new List<Color>();
|
|
||||||
|
|
||||||
for (var i = 0; i < prototype.Sprites.Count; i++)
|
|
||||||
{
|
|
||||||
colors.Add(skinColor.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
marking = new Marking(points.DefaultMarkings[index], colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddBack(category, marking);
|
AddBack(category, marking);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
humanoid.Species = species;
|
humanoid.Species = species;
|
||||||
humanoid.MarkingSet.FilterSpecies(species, _markingManager);
|
humanoid.MarkingSet.EnsureSpecies(species, humanoid.SkinColor, _markingManager);
|
||||||
var oldMarkings = humanoid.MarkingSet.GetForwardEnumerator().ToList();
|
var oldMarkings = humanoid.MarkingSet.GetForwardEnumerator().ToList();
|
||||||
humanoid.MarkingSet = new(oldMarkings, prototype.MarkingPoints, _markingManager, _prototypeManager);
|
humanoid.MarkingSet = new(oldMarkings, prototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,12 @@ public sealed class HumanoidMarkingModifierBaseLayersSetMessage : BoundUserInter
|
|||||||
public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
||||||
{
|
{
|
||||||
// TODO just use the component state, remove the BUI state altogether.
|
// TODO just use the component state, remove the BUI state altogether.
|
||||||
public HumanoidMarkingModifierState(MarkingSet markingSet, string species, Color skinColor, Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> customBaseLayers)
|
public HumanoidMarkingModifierState(
|
||||||
|
MarkingSet markingSet,
|
||||||
|
string species,
|
||||||
|
Color skinColor,
|
||||||
|
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> customBaseLayers
|
||||||
|
)
|
||||||
{
|
{
|
||||||
MarkingSet = markingSet;
|
MarkingSet = markingSet;
|
||||||
Species = species;
|
Species = species;
|
||||||
@@ -53,5 +58,8 @@ public sealed class HumanoidMarkingModifierState : BoundUserInterfaceState
|
|||||||
public MarkingSet MarkingSet { get; }
|
public MarkingSet MarkingSet { get; }
|
||||||
public string Species { get; }
|
public string Species { get; }
|
||||||
public Color SkinColor { get; }
|
public Color SkinColor { get; }
|
||||||
|
public Color EyeColor { get; }
|
||||||
|
public Color? HairColor { get; }
|
||||||
|
public Color? FacialHairColor { get; }
|
||||||
public Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> CustomBaseLayers { get; }
|
public Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> CustomBaseLayers { get; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:CategoryColoring
|
||||||
|
category: Hair
|
||||||
|
fallbackTypes:
|
||||||
|
- !type:SkinColoring
|
||||||
|
layers:
|
||||||
|
ears_cat_inner:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/cat_parts.rsi
|
- sprite: Mobs/Customization/cat_parts.rsi
|
||||||
state: ears_cat_outer
|
state: ears_cat_outer
|
||||||
@@ -14,6 +26,15 @@
|
|||||||
bodyPart: Tail
|
bodyPart: Tail
|
||||||
markingCategory: Tail
|
markingCategory: Tail
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:CategoryColoring
|
||||||
|
category: Hair
|
||||||
|
fallbackTypes:
|
||||||
|
- !type:CategoryColoring
|
||||||
|
category: FacialHair
|
||||||
|
- !type:SkinColoring
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/cat_parts.rsi
|
- sprite: Mobs/Customization/cat_parts.rsi
|
||||||
state: tail_cat
|
state: tail_cat
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: thorns_head
|
state: thorns_head
|
||||||
@@ -12,6 +17,11 @@
|
|||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: thorns_body
|
state: thorns_body
|
||||||
@@ -21,6 +31,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: flowers_head
|
state: flowers_head
|
||||||
@@ -30,6 +45,11 @@
|
|||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: flowers_body
|
state: flowers_body
|
||||||
@@ -39,6 +59,10 @@
|
|||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SkinColoring
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: leaf_cover
|
state: leaf_cover
|
||||||
@@ -48,6 +72,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: bloom
|
state: bloom
|
||||||
@@ -57,6 +86,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: bracket
|
state: bracket
|
||||||
@@ -66,6 +100,10 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SkinColoring
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: brush
|
state: brush
|
||||||
@@ -75,6 +113,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: cornflower
|
state: cornflower
|
||||||
@@ -84,6 +127,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: ficus
|
state: ficus
|
||||||
@@ -93,6 +141,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: garland
|
state: garland
|
||||||
@@ -102,6 +155,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: king
|
state: king
|
||||||
@@ -111,6 +169,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: laurel
|
state: laurel
|
||||||
@@ -120,6 +183,11 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: leafy
|
state: leafy
|
||||||
@@ -129,6 +197,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: lotus
|
state: lotus
|
||||||
@@ -138,6 +211,11 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: meadow
|
state: meadow
|
||||||
@@ -147,6 +225,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: oak
|
state: oak
|
||||||
@@ -156,6 +239,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: palm
|
state: palm
|
||||||
@@ -165,6 +253,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: root
|
state: root
|
||||||
@@ -174,6 +267,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: rose
|
state: rose
|
||||||
@@ -183,6 +281,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: rosey
|
state: rosey
|
||||||
@@ -192,6 +295,11 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: shrub
|
state: shrub
|
||||||
@@ -201,6 +309,11 @@
|
|||||||
bodyPart: HeadSide
|
bodyPart: HeadSide
|
||||||
markingCategory: HeadSide
|
markingCategory: HeadSide
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: spinner
|
state: spinner
|
||||||
@@ -210,6 +323,11 @@
|
|||||||
bodyPart: HeadSide
|
bodyPart: HeadSide
|
||||||
markingCategory: HeadSide
|
markingCategory: HeadSide
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: sprout
|
state: sprout
|
||||||
@@ -219,6 +337,11 @@
|
|||||||
bodyPart: HeadTop
|
bodyPart: HeadTop
|
||||||
markingCategory: HeadTop
|
markingCategory: HeadTop
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: vine
|
state: vine
|
||||||
@@ -228,6 +351,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: vinel
|
state: vinel
|
||||||
@@ -237,6 +365,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: vines
|
state: vines
|
||||||
@@ -246,6 +379,11 @@
|
|||||||
bodyPart: Head
|
bodyPart: Head
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Diona]
|
speciesRestriction: [Diona]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:SimpleColoring
|
||||||
|
color: "#FFFFFF"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/diona.rsi
|
- sprite: Mobs/Customization/diona.rsi
|
||||||
state: wildflower
|
state: wildflower
|
||||||
|
|||||||
@@ -157,7 +157,7 @@
|
|||||||
id: LizardSnoutRound
|
id: LizardSnoutRound
|
||||||
bodyPart: Snout
|
bodyPart: Snout
|
||||||
markingCategory: Snout
|
markingCategory: Snout
|
||||||
followSkinColor: true
|
forcedColoring: true
|
||||||
speciesRestriction: [Reptilian]
|
speciesRestriction: [Reptilian]
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/reptilian_parts.rsi
|
- sprite: Mobs/Customization/reptilian_parts.rsi
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
id: LizardSnoutSharp
|
id: LizardSnoutSharp
|
||||||
bodyPart: Snout
|
bodyPart: Snout
|
||||||
markingCategory: Snout
|
markingCategory: Snout
|
||||||
followSkinColor: true
|
forcedColoring: true
|
||||||
speciesRestriction: [Reptilian]
|
speciesRestriction: [Reptilian]
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/reptilian_parts.rsi
|
- sprite: Mobs/Customization/reptilian_parts.rsi
|
||||||
@@ -177,7 +177,6 @@
|
|||||||
id: LizardChestTiger
|
id: LizardChestTiger
|
||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
followSkinColor: false
|
|
||||||
speciesRestriction: [Reptilian]
|
speciesRestriction: [Reptilian]
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/reptilian_parts.rsi
|
- sprite: Mobs/Customization/reptilian_parts.rsi
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_hive_chest
|
state: tattoo_hive_chest
|
||||||
@@ -12,6 +17,11 @@
|
|||||||
bodyPart: Chest
|
bodyPart: Chest
|
||||||
markingCategory: Chest
|
markingCategory: Chest
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_nightling
|
state: tattoo_nightling
|
||||||
@@ -21,6 +31,11 @@
|
|||||||
bodyPart: LLeg
|
bodyPart: LLeg
|
||||||
markingCategory: Legs
|
markingCategory: Legs
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_silverburgh_l_leg
|
state: tattoo_silverburgh_l_leg
|
||||||
@@ -30,6 +45,11 @@
|
|||||||
bodyPart: RLeg
|
bodyPart: RLeg
|
||||||
markingCategory: Legs
|
markingCategory: Legs
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_silverburgh_r_leg
|
state: tattoo_silverburgh_r_leg
|
||||||
@@ -39,6 +59,11 @@
|
|||||||
bodyPart: LArm
|
bodyPart: LArm
|
||||||
markingCategory: Arms
|
markingCategory: Arms
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_campbell_l_arm
|
state: tattoo_campbell_l_arm
|
||||||
@@ -48,6 +73,11 @@
|
|||||||
bodyPart: RArm
|
bodyPart: RArm
|
||||||
markingCategory: Arms
|
markingCategory: Arms
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_campbell_r_arm
|
state: tattoo_campbell_r_arm
|
||||||
@@ -57,6 +87,11 @@
|
|||||||
bodyPart: LLeg
|
bodyPart: LLeg
|
||||||
markingCategory: Legs
|
markingCategory: Legs
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_campbell_l_leg
|
state: tattoo_campbell_l_leg
|
||||||
@@ -66,6 +101,11 @@
|
|||||||
bodyPart: RLeg
|
bodyPart: RLeg
|
||||||
markingCategory: Legs
|
markingCategory: Legs
|
||||||
speciesRestriction: [Human]
|
speciesRestriction: [Human]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:TattooColoring
|
||||||
|
fallbackColor: "#666666"
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_campbell_r_leg
|
state: tattoo_campbell_r_leg
|
||||||
@@ -75,6 +115,11 @@
|
|||||||
bodyPart: Eyes
|
bodyPart: Eyes
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Human, SlimePerson, Reptilian]
|
speciesRestriction: [Human, SlimePerson, Reptilian]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:EyeColoring
|
||||||
|
negative: true
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_eye_r
|
state: tattoo_eye_r
|
||||||
@@ -84,6 +129,11 @@
|
|||||||
bodyPart: Eyes
|
bodyPart: Eyes
|
||||||
markingCategory: Head
|
markingCategory: Head
|
||||||
speciesRestriction: [Human, SlimePerson, Reptilian]
|
speciesRestriction: [Human, SlimePerson, Reptilian]
|
||||||
|
coloring:
|
||||||
|
default:
|
||||||
|
type:
|
||||||
|
!type:EyeColoring
|
||||||
|
negative: true
|
||||||
sprites:
|
sprites:
|
||||||
- sprite: Mobs/Customization/tattoos.rsi
|
- sprite: Mobs/Customization/tattoos.rsi
|
||||||
state: tattoo_eye_l
|
state: tattoo_eye_l
|
||||||
|
|||||||
Reference in New Issue
Block a user