using Robust.Shared.Random;
using Robust.Shared.Serialization;
-namespace Content.Shared.Humanoid
+namespace Content.Shared.Humanoid;
+
+[DataDefinition]
+[Serializable, NetSerializable]
+public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance
{
- [DataDefinition]
- [Serializable, NetSerializable]
- public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance
+ public HumanoidCharacterAppearance(string hairStyleId,
+ Color hairColor,
+ string facialHairStyleId,
+ Color facialHairColor,
+ Color eyeColor,
+ Color skinColor,
+ List<Marking> markings)
{
- public HumanoidCharacterAppearance(string hairStyleId,
- Color hairColor,
- string facialHairStyleId,
- Color facialHairColor,
- Color eyeColor,
- Color skinColor,
- List<Marking> markings)
- {
- HairStyleId = hairStyleId;
- HairColor = ClampColor(hairColor);
- FacialHairStyleId = facialHairStyleId;
- FacialHairColor = ClampColor(facialHairColor);
- EyeColor = ClampColor(eyeColor);
- SkinColor = ClampColor(skinColor);
- Markings = markings;
- }
+ HairStyleId = hairStyleId;
+ HairColor = ClampColor(hairColor);
+ FacialHairStyleId = facialHairStyleId;
+ FacialHairColor = ClampColor(facialHairColor);
+ EyeColor = ClampColor(eyeColor);
+ SkinColor = ClampColor(skinColor);
+ Markings = markings;
+ }
- [DataField("hair")]
- public string HairStyleId { get; private set; }
+ [DataField("hair")]
+ public string HairStyleId { get; private set; }
- [DataField("hairColor")]
- public Color HairColor { get; private set; }
+ [DataField("hairColor")]
+ public Color HairColor { get; private set; }
- [DataField("facialHair")]
- public string FacialHairStyleId { get; private set; }
+ [DataField("facialHair")]
+ public string FacialHairStyleId { get; private set; }
- [DataField("facialHairColor")]
- public Color FacialHairColor { get; private set; }
+ [DataField("facialHairColor")]
+ public Color FacialHairColor { get; private set; }
- [DataField("eyeColor")]
- public Color EyeColor { get; private set; }
+ [DataField("eyeColor")]
+ public Color EyeColor { get; private set; }
- [DataField("skinColor")]
- public Color SkinColor { get; private set; }
+ [DataField("skinColor")]
+ public Color SkinColor { get; private set; }
- [DataField("markings")]
- public List<Marking> Markings { get; private set; }
+ [DataField("markings")]
+ public List<Marking> Markings { get; private set; }
- public HumanoidCharacterAppearance WithHairStyleName(string newName)
- {
- return new(newName, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings);
- }
+ public HumanoidCharacterAppearance WithHairStyleName(string newName)
+ {
+ return new(newName, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings);
+ }
- public HumanoidCharacterAppearance WithHairColor(Color newColor)
- {
- return new(HairStyleId, newColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings);
- }
+ public HumanoidCharacterAppearance WithHairColor(Color newColor)
+ {
+ return new(HairStyleId, newColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings);
+ }
- public HumanoidCharacterAppearance WithFacialHairStyleName(string newName)
- {
- return new(HairStyleId, HairColor, newName, FacialHairColor, EyeColor, SkinColor, Markings);
- }
+ public HumanoidCharacterAppearance WithFacialHairStyleName(string newName)
+ {
+ return new(HairStyleId, HairColor, newName, FacialHairColor, EyeColor, SkinColor, Markings);
+ }
- public HumanoidCharacterAppearance WithFacialHairColor(Color newColor)
- {
- return new(HairStyleId, HairColor, FacialHairStyleId, newColor, EyeColor, SkinColor, Markings);
- }
+ public HumanoidCharacterAppearance WithFacialHairColor(Color newColor)
+ {
+ return new(HairStyleId, HairColor, FacialHairStyleId, newColor, EyeColor, SkinColor, Markings);
+ }
- public HumanoidCharacterAppearance WithEyeColor(Color newColor)
- {
- return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, newColor, SkinColor, Markings);
- }
+ public HumanoidCharacterAppearance WithEyeColor(Color newColor)
+ {
+ return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, newColor, SkinColor, Markings);
+ }
- public HumanoidCharacterAppearance WithSkinColor(Color newColor)
- {
- return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, newColor, Markings);
- }
+ public HumanoidCharacterAppearance WithSkinColor(Color newColor)
+ {
+ return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, newColor, Markings);
+ }
+
+ public HumanoidCharacterAppearance WithMarkings(List<Marking> newMarkings)
+ {
+ return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, newMarkings);
+ }
- public HumanoidCharacterAppearance WithMarkings(List<Marking> newMarkings)
+ public HumanoidCharacterAppearance() : this(
+ HairStyles.DefaultHairStyle,
+ Color.Black,
+ HairStyles.DefaultFacialHairStyle,
+ Color.Black,
+ Color.Black,
+ Humanoid.SkinColor.ValidHumanSkinTone,
+ new ()
+ )
+ {
+ }
+
+ public static HumanoidCharacterAppearance DefaultWithSpecies(string species)
+ {
+ var speciesPrototype = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species);
+ var skinColor = speciesPrototype.SkinColoration switch
{
- return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, newMarkings);
- }
+ HumanoidSkinColor.HumanToned => Humanoid.SkinColor.HumanSkinTone(speciesPrototype.DefaultHumanSkinTone),
+ HumanoidSkinColor.Hues => speciesPrototype.DefaultSkinTone,
+ HumanoidSkinColor.TintedHues => Humanoid.SkinColor.TintedHues(speciesPrototype.DefaultSkinTone),
+ _ => Humanoid.SkinColor.ValidHumanSkinTone
+ };
- public HumanoidCharacterAppearance() : this(
+ return new(
HairStyles.DefaultHairStyle,
Color.Black,
HairStyles.DefaultFacialHairStyle,
Color.Black,
Color.Black,
- Humanoid.SkinColor.ValidHumanSkinTone,
+ skinColor,
new ()
- )
- {
- }
-
- public static HumanoidCharacterAppearance DefaultWithSpecies(string species)
- {
- var speciesPrototype = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species);
- var skinColor = speciesPrototype.SkinColoration switch
- {
- HumanoidSkinColor.HumanToned => Humanoid.SkinColor.HumanSkinTone(speciesPrototype.DefaultHumanSkinTone),
- HumanoidSkinColor.Hues => speciesPrototype.DefaultSkinTone,
- HumanoidSkinColor.TintedHues => Humanoid.SkinColor.TintedHues(speciesPrototype.DefaultSkinTone),
- _ => Humanoid.SkinColor.ValidHumanSkinTone
- };
-
- return new(
- HairStyles.DefaultHairStyle,
- Color.Black,
- HairStyles.DefaultFacialHairStyle,
- Color.Black,
- Color.Black,
- skinColor,
- new ()
- );
- }
-
- private static IReadOnlyList<Color> RealisticEyeColors = new List<Color>
- {
- Color.Brown,
- Color.Gray,
- Color.Azure,
- Color.SteelBlue,
- Color.Black
- };
+ );
+ }
- public static HumanoidCharacterAppearance Random(string species, Sex sex)
- {
- var random = IoCManager.Resolve<IRobustRandom>();
- var markingManager = IoCManager.Resolve<MarkingManager>();
- var hairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.Hair, species).Keys.ToList();
- var facialHairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.FacialHair, species).Keys.ToList();
+ private static IReadOnlyList<Color> RealisticEyeColors = new List<Color>
+ {
+ Color.Brown,
+ Color.Gray,
+ Color.Azure,
+ Color.SteelBlue,
+ Color.Black
+ };
+
+ public static HumanoidCharacterAppearance Random(string species, Sex sex)
+ {
+ var random = IoCManager.Resolve<IRobustRandom>();
+ var markingManager = IoCManager.Resolve<MarkingManager>();
+ var hairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.Hair, species).Keys.ToList();
+ var facialHairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.FacialHair, species).Keys.ToList();
- var newHairStyle = hairStyles.Count > 0
- ? random.Pick(hairStyles)
- : HairStyles.DefaultHairStyle;
+ var newHairStyle = hairStyles.Count > 0
+ ? random.Pick(hairStyles)
+ : HairStyles.DefaultHairStyle;
- var newFacialHairStyle = facialHairStyles.Count == 0 || sex == Sex.Female
- ? HairStyles.DefaultFacialHairStyle
- : random.Pick(facialHairStyles);
+ var newFacialHairStyle = facialHairStyles.Count == 0 || sex == Sex.Female
+ ? HairStyles.DefaultFacialHairStyle
+ : random.Pick(facialHairStyles);
- var newHairColor = random.Pick(HairStyles.RealisticHairColors);
- newHairColor = newHairColor
- .WithRed(RandomizeColor(newHairColor.R))
- .WithGreen(RandomizeColor(newHairColor.G))
- .WithBlue(RandomizeColor(newHairColor.B));
+ var newHairColor = random.Pick(HairStyles.RealisticHairColors);
+ newHairColor = newHairColor
+ .WithRed(RandomizeColor(newHairColor.R))
+ .WithGreen(RandomizeColor(newHairColor.G))
+ .WithBlue(RandomizeColor(newHairColor.B));
- // TODO: Add random markings
+ // TODO: Add random markings
- var newEyeColor = random.Pick(RealisticEyeColors);
+ var newEyeColor = random.Pick(RealisticEyeColors);
- var skinType = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species).SkinColoration;
+ var skinType = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species).SkinColoration;
- var newSkinColor = Humanoid.SkinColor.ValidHumanSkinTone;
- switch (skinType)
- {
- case HumanoidSkinColor.HumanToned:
- var tone = random.Next(0, 100);
- newSkinColor = Humanoid.SkinColor.HumanSkinTone(tone);
- break;
- case HumanoidSkinColor.Hues:
- case HumanoidSkinColor.TintedHues:
- var rbyte = random.NextByte();
- var gbyte = random.NextByte();
- var bbyte = random.NextByte();
- newSkinColor = new Color(rbyte, gbyte, bbyte);
- break;
- }
-
- if (skinType == HumanoidSkinColor.TintedHues)
- {
+ var newSkinColor = new Color(random.NextFloat(1), random.NextFloat(1), random.NextFloat(1), 1);
+ switch (skinType)
+ {
+ case HumanoidSkinColor.HumanToned:
+ var tone = Math.Round(Humanoid.SkinColor.HumanSkinToneFromColor(newSkinColor));
+ newSkinColor = Humanoid.SkinColor.HumanSkinTone((int)tone);
+ break;
+ case HumanoidSkinColor.Hues:
+ break;
+ case HumanoidSkinColor.TintedHues:
newSkinColor = Humanoid.SkinColor.ValidTintedHuesSkinTone(newSkinColor);
- }
-
- return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor, newEyeColor, newSkinColor, new ());
-
- float RandomizeColor(float channel)
- {
- return MathHelper.Clamp01(channel + random.Next(-25, 25) / 100f);
- }
+ break;
}
- public static Color ClampColor(Color color)
+ return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor, newEyeColor, newSkinColor, new ());
+
+ float RandomizeColor(float channel)
{
- return new(color.RByte, color.GByte, color.BByte);
+ return MathHelper.Clamp01(channel + random.Next(-25, 25) / 100f);
}
+ }
- public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, Sex sex)
- {
- var hairStyleId = appearance.HairStyleId;
- var facialHairStyleId = appearance.FacialHairStyleId;
+ public static Color ClampColor(Color color)
+ {
+ return new(color.RByte, color.GByte, color.BByte);
+ }
- var hairColor = ClampColor(appearance.HairColor);
- var facialHairColor = ClampColor(appearance.FacialHairColor);
- var eyeColor = ClampColor(appearance.EyeColor);
+ public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, Sex sex)
+ {
+ var hairStyleId = appearance.HairStyleId;
+ var facialHairStyleId = appearance.FacialHairStyleId;
- var proto = IoCManager.Resolve<IPrototypeManager>();
- var markingManager = IoCManager.Resolve<MarkingManager>();
+ var hairColor = ClampColor(appearance.HairColor);
+ var facialHairColor = ClampColor(appearance.FacialHairColor);
+ var eyeColor = ClampColor(appearance.EyeColor);
- if (!markingManager.MarkingsByCategory(MarkingCategories.Hair).ContainsKey(hairStyleId))
- {
- hairStyleId = HairStyles.DefaultHairStyle;
- }
+ var proto = IoCManager.Resolve<IPrototypeManager>();
+ var markingManager = IoCManager.Resolve<MarkingManager>();
- if (!markingManager.MarkingsByCategory(MarkingCategories.FacialHair).ContainsKey(facialHairStyleId))
- {
- facialHairStyleId = HairStyles.DefaultFacialHairStyle;
- }
+ if (!markingManager.MarkingsByCategory(MarkingCategories.Hair).ContainsKey(hairStyleId))
+ {
+ hairStyleId = HairStyles.DefaultHairStyle;
+ }
- var markingSet = new MarkingSet();
- var skinColor = appearance.SkinColor;
- if (proto.TryIndex(species, out SpeciesPrototype? speciesProto))
- {
- markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
- markingSet.EnsureValid(markingManager);
+ if (!markingManager.MarkingsByCategory(MarkingCategories.FacialHair).ContainsKey(facialHairStyleId))
+ {
+ facialHairStyleId = HairStyles.DefaultFacialHairStyle;
+ }
- if (!Humanoid.SkinColor.VerifySkinColor(speciesProto.SkinColoration, skinColor))
- {
- skinColor = Humanoid.SkinColor.ValidSkinTone(speciesProto.SkinColoration, skinColor);
- }
+ var markingSet = new MarkingSet();
+ var skinColor = appearance.SkinColor;
+ if (proto.TryIndex(species, out SpeciesPrototype? speciesProto))
+ {
+ markingSet = new MarkingSet(appearance.Markings, speciesProto.MarkingPoints, markingManager, proto);
+ markingSet.EnsureValid(markingManager);
- markingSet.EnsureSpecies(species, skinColor, markingManager);
- markingSet.EnsureSexes(sex, markingManager);
+ if (!Humanoid.SkinColor.VerifySkinColor(speciesProto.SkinColoration, skinColor))
+ {
+ skinColor = Humanoid.SkinColor.ValidSkinTone(speciesProto.SkinColoration, skinColor);
}
- return new HumanoidCharacterAppearance(
- hairStyleId,
- hairColor,
- facialHairStyleId,
- facialHairColor,
- eyeColor,
- skinColor,
- markingSet.GetForwardEnumerator().ToList());
+ markingSet.EnsureSpecies(species, skinColor, markingManager);
+ markingSet.EnsureSexes(sex, markingManager);
}
- public bool MemberwiseEquals(ICharacterAppearance maybeOther)
- {
- if (maybeOther is not HumanoidCharacterAppearance other) return false;
- if (HairStyleId != other.HairStyleId) return false;
- if (!HairColor.Equals(other.HairColor)) return false;
- if (FacialHairStyleId != other.FacialHairStyleId) return false;
- if (!FacialHairColor.Equals(other.FacialHairColor)) return false;
- if (!EyeColor.Equals(other.EyeColor)) return false;
- if (!SkinColor.Equals(other.SkinColor)) return false;
- if (!Markings.SequenceEqual(other.Markings)) return false;
- return true;
- }
+ return new HumanoidCharacterAppearance(
+ hairStyleId,
+ hairColor,
+ facialHairStyleId,
+ facialHairColor,
+ eyeColor,
+ skinColor,
+ markingSet.GetForwardEnumerator().ToList());
+ }
+
+ public bool MemberwiseEquals(ICharacterAppearance maybeOther)
+ {
+ if (maybeOther is not HumanoidCharacterAppearance other) return false;
+ if (HairStyleId != other.HairStyleId) return false;
+ if (!HairColor.Equals(other.HairColor)) return false;
+ if (FacialHairStyleId != other.FacialHairStyleId) return false;
+ if (!FacialHairColor.Equals(other.FacialHairColor)) return false;
+ if (!EyeColor.Equals(other.EyeColor)) return false;
+ if (!SkinColor.Equals(other.SkinColor)) return false;
+ if (!Markings.SequenceEqual(other.Markings)) return false;
+ return true;
}
}