using Content.Shared.Humanoid.Markings; using Content.Shared.Humanoid.Prototypes; using Robust.Shared.Enums; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Utility; using static Content.Shared.Humanoid.HumanoidAppearanceState; namespace Content.Shared.Humanoid; [NetworkedComponent, RegisterComponent] public sealed class HumanoidAppearanceComponent : Component { [DataField("markingSet")] public MarkingSet MarkingSet = new(); [DataField("baseLayers")] public Dictionary BaseLayers = new(); [DataField("permanentlyHidden")] public HashSet PermanentlyHidden = new(); // Couldn't these be somewhere else? [DataField("gender")] [ViewVariables] public Gender Gender = default!; [DataField("age")] [ViewVariables] public int Age = 18; /// /// Any custom base layers this humanoid might have. See: /// limb transplants (potentially), robotic arms, etc. /// Stored on the server, this is merged in the client into /// all layer settings. /// [DataField("customBaseLayers")] public Dictionary CustomBaseLayers = new(); /// /// Current species. Dictates things like base body sprites, /// base humanoid to spawn, etc. /// [DataField("species", customTypeSerializer: typeof(PrototypeIdSerializer), required: true)] public string Species { get; set; } = default!; /// /// The initial profile and base layers to apply to this humanoid. /// [DataField("initial", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? Initial { get; } /// /// Skin color of this humanoid. /// [DataField("skinColor")] public Color SkinColor { get; set; } = Color.FromHex("#C0967F"); /// /// Visual layers currently hidden. This will affect the base sprite /// on this humanoid layer, and any markings that sit above it. /// [DataField("hiddenLayers")] public HashSet HiddenLayers = new(); [DataField("sex")] public Sex Sex = Sex.Male; [DataField("eyeColor")] public Color EyeColor = Color.Brown; /// /// Hair color of this humanoid. Used to avoid looping through all markings /// [ViewVariables(VVAccess.ReadOnly)] public Color? CachedHairColor; /// /// Facial Hair color of this humanoid. Used to avoid looping through all markings /// [ViewVariables(VVAccess.ReadOnly)] public Color? CachedFacialHairColor; } [Serializable, NetSerializable] public sealed class HumanoidAppearanceState : ComponentState { public readonly MarkingSet Markings; public readonly HashSet PermanentlyHidden; public readonly HashSet HiddenLayers; public readonly Dictionary CustomBaseLayers; public readonly Sex Sex; public readonly Gender Gender; public readonly int Age = 18; public readonly string Species; public readonly Color SkinColor; public readonly Color EyeColor; public HumanoidAppearanceState( MarkingSet currentMarkings, HashSet permanentlyHidden, HashSet hiddenLayers, Dictionary customBaseLayers, Sex sex, Gender gender, int age, string species, Color skinColor, Color eyeColor) { Markings = currentMarkings; PermanentlyHidden = permanentlyHidden; HiddenLayers = hiddenLayers; CustomBaseLayers = customBaseLayers; Sex = sex; Gender = gender; Age = age; Species = species; SkinColor = skinColor; EyeColor = eyeColor; } [DataDefinition] [Serializable, NetSerializable] public readonly struct CustomBaseLayerInfo { public CustomBaseLayerInfo(string? id, Color? color = null) { DebugTools.Assert(id == null || IoCManager.Resolve().HasIndex(id)); ID = id; Color = color; } /// /// ID of this custom base layer. Must be a . /// [DataField("id", customTypeSerializer: typeof(PrototypeIdSerializer))] public string? ID { init; get; } /// /// Color of this custom base layer. Null implies skin colour if the corresponding is set to match skin. /// [DataField("color")] public Color? Color { init; get; } } }