AI/Staff/Staff.Identity.cs
using System;

namespace HC3;

public partial class Staff : Component.ExecuteInEditor
{
	/// <summary>
	/// Is this staff member a male?
	/// </summary>
	[Property, Feature( "Identity" ), Group( "Identity" )]
	public bool IsMale { get; set; }

	[Property] public Texture FaceTexture { get => _faceTexture; set { _faceTexture = value; SetupSkin(); } }
	Texture _faceTexture;

	[Property, Feature( "Palette" )]
	public Color? Slot0 { get => _slot0; set { _slot0 = value; SetupSkin(); } }
	Color? _slot0 = new Color( 0.7f, 0.5f, 0.3f );

	[Property, Feature( "Palette" )]
	public Color? Slot1 { get => _slot1; set { _slot1 = value; SetupSkin(); } }
	Color? _slot1;

	[Property, Feature( "Palette" )]
	public Color? Slot2 { get => _slot2; set { _slot2 = value; SetupSkin(); } }
	Color? _slot2;

	[Property, Feature( "Palette" )]
	public Color? Slot3 { get => _slot3; set { _slot3 = value; SetupSkin(); } }
	Color? _slot3 = new Color( 0.3f, 0.5f, 0.7f );

	[Property, Feature( "Palette" )]
	public Color? Slot4 { get => _slot4; set { _slot4 = value; SetupSkin(); } }
	Color? _slot4;

	[Property, Feature( "Palette" )]
	public Color? Slot5 { get => _slot5; set { _slot5 = value; SetupSkin(); } }
	Color? _slot5;

	[Property, Feature( "Palette" ), Title( "Slot 6 -> Extra Slot 1" )]
	public Color? Slot6 { get => _slot6; set { _slot6 = value; SetupSkin(); } }
	Color? _slot6 = new Color( 0.7f, 0.5f, 0.3f );

	[Property, Feature( "Palette" ), Title( "Slot 7 -> Extra Slot 2" )]
	public Color? Slot7 { get => _slot7; set { _slot7 = value; SetupSkin(); } }
	Color? _slot7 = new Color( 0.3f, 0.5f, 0.7f );

	private Color GetRandomHair( Random random )
	{
		var colors = new Color[]
		{
			new( 0.05f, 0.05f, 0.05f ),    // Black
	        new( 0.2f, 0.15f, 0.1f ),      // Dark Brown
	        new( 0.4f, 0.3f, 0.2f ),       // Medium Brown
	        new( 0.6f, 0.5f, 0.35f ),      // Light Brown
	        new( 0.8f, 0.7f, 0.45f ),      // Dirty Blonde
	        new( 0.9f, 0.8f, 0.5f ),       // Blonde
	        new( 0.8f, 0.3f, 0.2f ),       // Ginger/Red
	        new( 0.5f, 0.5f, 0.5f ),       // Silver/Gray
	        new( 0.7f, 0.7f, 0.7f ),       // White/Platinum
	        new( 0.3f, 0.2f, 0.15f ),      // Auburn
	        new( 0.15f, 0.1f, 0.05f ),     // Very Dark Brown
	        new( 0.7f, 0.6f, 0.4f )        // Sandy Blonde
		};

		return random.FromArray( colors );
	}

	private Color GetRandomSkin( Random random )
	{
		var colors = new Color[]
		{
			new( 0.97f, 0.85f, 0.73f ),    // Very Light
	        new( 0.94f, 0.78f, 0.67f ),    // Light
	        new( 0.87f, 0.72f, 0.60f ),    // Light Medium
	        new( 0.80f, 0.65f, 0.52f ),    // Medium
	        new( 0.75f, 0.60f, 0.48f ),    // Medium Tan
	        new( 0.65f, 0.48f, 0.35f ),    // Tan
	        new( 0.55f, 0.38f, 0.27f ),    // Medium Dark
	        new( 0.45f, 0.30f, 0.22f ),    // Dark
	        new( 0.35f, 0.22f, 0.16f ),    // Deep Dark
	        new( 0.25f, 0.15f, 0.10f ),    // Very Deep Dark
	        new( 0.90f, 0.75f, 0.65f ),    // Peach
	        new( 0.85f, 0.68f, 0.55f ),    // Warm Medium
	        new( 0.70f, 0.55f, 0.42f ),    // Olive
	        new( 0.60f, 0.43f, 0.32f ),    // Golden Brown
	        new( 0.50f, 0.33f, 0.24f )     // Rich Brown
		};

		return random.FromArray( colors );
	}

	void SetupIdentity()
	{
		IsMale = Game.Random.Int( 0, 1 ) > 0;
		FullName = IdentitySystem.FetchName( IsMale );
	}

	void SetupSkin()
	{
		if ( !Body.SceneModel.IsValid() )
			return;

		var seed = GameObject.Id.ToString().FastHash();
		var random = new Random( seed );
		var skin = GetRandomSkin( random );

		// Can't batch these now
		Body.SceneModel.Batchable = false;
		Body.SceneModel.Attributes.Set( "Slot0", Slot0.HasValue ? Slot0.Value : new Color( 0.7f, 0.5f, 0.3f ) );
		Body.SceneModel.Attributes.Set( "Slot1", Slot1.HasValue ? Slot1.Value : skin );
		Body.SceneModel.Attributes.Set( "Slot2", Slot2.HasValue ? Slot2.Value : skin );
		Body.SceneModel.Attributes.Set( "Slot3", Slot3.HasValue ? Slot3.Value : new Color( 0.3f, 0.5f, 0.7f ) );
		Body.SceneModel.Attributes.Set( "Slot4", Slot4.HasValue ? Slot4.Value : Color.Parse( "#8E8B8E" ).Value );
		Body.SceneModel.Attributes.Set( "Slot5", Slot5.HasValue ? Slot5.Value : GetRandomHair( random ) );
		Body.SceneModel.Attributes.Set( "Slot6", Slot6.HasValue ? Slot6.Value : new Color( 0.7f, 0.5f, 0.3f ) );
		Body.SceneModel.Attributes.Set( "Slot7", Slot7.HasValue ? Slot7.Value : new Color( 0.3f, 0.5f, 0.7f ) );
		Body.SceneModel.Attributes.Set( "FaceTexture", FaceTexture );
	}
}