using System.Linq; using RimWorld; using UnityEngine; using Verse; namespace AIImages.Services { /// /// Сервис для умного определения цветов (вместо RGB значений) /// public static class ColorDescriptionService { /// /// Получает текстовое описание цвета волос /// public static string GetHairColorDescription(Color color) { float h, s, v; Color.RGBToHSV(color, out h, out s, out v); // Проверяем на оттенки серого if (s < 0.15f) { return GetGrayscaleDescription(v); } // Определяем оттенок string hueDescription = GetHueDescription(h); string brightnessModifier = GetBrightnessModifier(v, s); return $"{brightnessModifier}{hueDescription}".Trim(); } /// /// Получает текстовое описание цвета кожи /// Сначала проверяет специальные гены цвета кожи (зелёная, синяя и т.д.), /// затем использует вычисленный RimWorld цвет кожи /// public static string GetSkinToneDescription(Pawn pawn) { if (pawn?.genes?.GenesListForReading == null) return GetSkinToneDescription(pawn.story.SkinColor); // Ищем активные гены цвета кожи (особенно специальные: зелёная, синяя, красная и т.д.) var skinColorGenes = pawn .genes.GenesListForReading.Where(gene => gene.Active && IsSpecialSkinColorGene(gene.def) ) .ToList(); // Если есть специальные гены цвета кожи, используем их описание if (skinColorGenes.Any()) { var specialGene = skinColorGenes[0]; string geneDescription = GetSpecialGeneSkinTone(specialGene.def.defName); if (!string.IsNullOrEmpty(geneDescription)) return geneDescription; } // Иначе RimWorld уже определил цвет текстуры пешки на основе генов (включая уровень мелатонина) // Используем этот вычисленный цвет return GetSkinToneDescription(pawn.story.SkinColor); } /// /// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.) /// private static bool IsSpecialSkinColorGene(GeneDef geneDef) { if (geneDef == null) return false; string geneDefName = geneDef.defName; // Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая return geneDefName.StartsWith("Skin_") && ( geneDefName.Contains("Green") || geneDefName.Contains("Blue") || geneDefName.Contains("Red") || geneDefName.Contains("Yellow") || geneDefName.Contains("Purple") || geneDefName.Contains("Orange") || geneDefName.Contains("Black") || geneDefName.Contains("White") || geneDefName.Contains("Gray") || geneDefName.Contains("Grey") || geneDefName.Contains("Ink") || geneDefName.Contains("Slate") || geneDefName.Contains("Sheer") || geneDefName.Contains("Pale") || geneDefName.Contains("Deep") ); } /// /// Получает описание для специальных генов цвета кожи /// private static string GetSpecialGeneSkinTone(string geneDefName) { switch (geneDefName) { case "Skin_InkBlack": return "ink black skin"; case "Skin_SlateGray": return "slate gray skin"; case "Skin_LightGray": return "light gray skin"; case "Skin_SheerWhite": return "sheer white skin"; case "Skin_Blue": return "blue skin"; case "Skin_Purple": return "purple skin"; case "Skin_PaleRed": return "pale red skin"; case "Skin_DeepRed": return "deep red skin"; case "Skin_PaleYellow": return "pale yellow skin"; case "Skin_DeepYellow": return "deep yellow skin"; case "Skin_Orange": return "orange skin"; case "Skin_Green": return "green skin"; default: // Пытаемся определить по названию if (geneDefName.Contains("Green") || geneDefName.Contains("зел")) return "green skin"; if (geneDefName.Contains("Blue") || geneDefName.Contains("син")) return "blue skin"; if (geneDefName.Contains("Red") || geneDefName.Contains("красн")) return "red skin"; if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт")) return "yellow skin"; if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет")) return "purple skin"; if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж")) return "orange skin"; if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн")) return "black skin"; if (geneDefName.Contains("White") || geneDefName.Contains("бел")) return "white skin"; if ( geneDefName.Contains("Gray") || geneDefName.Contains("Grey") || geneDefName.Contains("сер") ) return "gray skin"; return null; } } /// /// Получает текстовое описание цвета кожи по RGB цвету (fallback метод) /// public static string GetSkinToneDescription(Color color) { // Вычисляем яркость float brightness = (color.r + color.g + color.b) / 3f; // Определяем оттенок кожи if (brightness >= 0.85f) return "very fair skin"; else if (brightness >= 0.75f) return "fair skin"; else if (brightness >= 0.65f) return "light skin"; else if (brightness >= 0.55f) return "medium skin"; else if (brightness >= 0.45f) return "olive skin"; else if (brightness >= 0.35f) return "tan skin"; else if (brightness >= 0.25f) return "brown skin"; else if (brightness >= 0.15f) return "dark brown skin"; else return "very dark skin"; } /// /// Получает описание цвета одежды /// public static string GetApparelColorDescription(Color color) { float h, s, v; Color.RGBToHSV(color, out h, out s, out v); // Проверяем на оттенки серого if (s < 0.1f) { return GetGrayscaleDescription(v); } // Определяем оттенок string hueDescription = GetHueDescription(h); // Модификаторы насыщенности и яркости string saturationModifier = ""; if (s < 0.3f) saturationModifier = "pale "; else if (s > 0.8f) saturationModifier = "vivid "; string brightnessModifier = ""; if (v < 0.3f) brightnessModifier = "dark "; else if (v > 0.8f) brightnessModifier = "bright "; return $"{brightnessModifier}{saturationModifier}{hueDescription}".Trim(); } private static string GetGrayscaleDescription(float value) { if (value >= 0.95f) return "white"; else if (value >= 0.8f) return "light gray"; else if (value >= 0.6f) return "gray"; else if (value >= 0.4f) return "dark gray"; else if (value >= 0.2f) return "charcoal"; else return "black"; } private static string GetHueDescription(float hue) { // Hue from 0 to 1 if (hue < 0.05f || hue >= 0.95f) return "red"; if (hue < 0.083f) return "orange-red"; if (hue < 0.15f) return "orange"; if (hue < 0.19f) return "golden"; if (hue < 0.22f) return "yellow"; if (hue < 0.35f) return "yellow-green"; if (hue < 0.45f) return "green"; if (hue < 0.52f) return "cyan"; if (hue < 0.58f) return "light blue"; if (hue < 0.65f) return "blue"; if (hue < 0.72f) return "deep blue"; if (hue < 0.78f) return "purple"; if (hue < 0.85f) return "violet"; if (hue < 0.92f) return "magenta"; return "pink"; } private static string GetBrightnessModifier(float value, float saturation) { // Для волос используем специальные термины if (value < 0.2f) return "jet black "; else if (value < 0.3f) return "black "; else if (value < 0.45f) return "dark "; else if (value > 0.85f && saturation < 0.3f) return "platinum "; else if (value > 0.75f) return "light "; else return ""; } } }