Enhance hair color handling in AIImages by adding support for hair color genes in PawnAppearanceData. Update ColorDescriptionService to prioritize gene-based hair color descriptions, improving character appearance representation. Refactor related services to utilize new hair color logic.
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m40s
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m40s
This commit is contained in:
@@ -16,6 +16,7 @@ namespace AIImages.Models
|
|||||||
public string BodyType { get; set; }
|
public string BodyType { get; set; }
|
||||||
public Color SkinColor { get; set; }
|
public Color SkinColor { get; set; }
|
||||||
public List<string> SkinColorGeneDefNames { get; set; }
|
public List<string> SkinColorGeneDefNames { get; set; }
|
||||||
|
public List<string> HairColorGeneDefNames { get; set; }
|
||||||
public string HairStyle { get; set; }
|
public string HairStyle { get; set; }
|
||||||
public string HairDefName { get; set; }
|
public string HairDefName { get; set; }
|
||||||
public Color HairColor { get; set; }
|
public Color HairColor { get; set; }
|
||||||
@@ -27,6 +28,7 @@ namespace AIImages.Models
|
|||||||
Traits = new List<Trait>();
|
Traits = new List<Trait>();
|
||||||
Apparel = new List<ApparelData>();
|
Apparel = new List<ApparelData>();
|
||||||
SkinColorGeneDefNames = new List<string>();
|
SkinColorGeneDefNames = new List<string>();
|
||||||
|
HairColorGeneDefNames = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -253,24 +253,24 @@ namespace AIImages.Services
|
|||||||
case "Skin_Green":
|
case "Skin_Green":
|
||||||
return "green skin";
|
return "green skin";
|
||||||
default:
|
default:
|
||||||
// Пытаемся определить по названию
|
// Пытаемся определить по названию (defName всегда на английском)
|
||||||
if (geneDefName.Contains("Green") || geneDefName.Contains("зел"))
|
if (geneDefName.Contains("Green"))
|
||||||
return "green skin";
|
return "green skin";
|
||||||
if (geneDefName.Contains("Blue") || geneDefName.Contains("син"))
|
if (geneDefName.Contains("Blue"))
|
||||||
return "blue skin";
|
return "blue skin";
|
||||||
if (geneDefName.Contains("Red") || geneDefName.Contains("красн"))
|
if (geneDefName.Contains("Red"))
|
||||||
return "red skin";
|
return "red skin";
|
||||||
if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт"))
|
if (geneDefName.Contains("Yellow"))
|
||||||
return "yellow skin";
|
return "yellow skin";
|
||||||
if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет"))
|
if (geneDefName.Contains("Purple"))
|
||||||
return "purple skin";
|
return "purple skin";
|
||||||
if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж"))
|
if (geneDefName.Contains("Orange"))
|
||||||
return "orange skin";
|
return "orange skin";
|
||||||
if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн"))
|
if (geneDefName.Contains("Black"))
|
||||||
return "black skin";
|
return "black skin";
|
||||||
if (geneDefName.Contains("White") || geneDefName.Contains("бел"))
|
if (geneDefName.Contains("White"))
|
||||||
return "white skin";
|
return "white skin";
|
||||||
if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey") || geneDefName.Contains("сер"))
|
if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey"))
|
||||||
return "gray skin";
|
return "gray skin";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -283,8 +283,13 @@ namespace AIImages.Services
|
|||||||
|
|
||||||
StringBuilder hair = new StringBuilder();
|
StringBuilder hair = new StringBuilder();
|
||||||
|
|
||||||
// Цвет волос
|
// Цвет волос - сначала проверяем гены
|
||||||
string hairColor = ColorDescriptionService.GetHairColorDescription(data.HairColor);
|
string hairColor = GetHairColorFromData(data);
|
||||||
|
if (string.IsNullOrEmpty(hairColor))
|
||||||
|
{
|
||||||
|
// Если нет генов, используем цвет из RGB
|
||||||
|
hairColor = ColorDescriptionService.GetHairColorDescription(data.HairColor);
|
||||||
|
}
|
||||||
hair.Append(hairColor);
|
hair.Append(hairColor);
|
||||||
hair.Append(" hair, ");
|
hair.Append(" hair, ");
|
||||||
|
|
||||||
@@ -299,6 +304,94 @@ namespace AIImages.Services
|
|||||||
return hair.ToString();
|
return hair.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает описание цвета волос из генов в данных персонажа
|
||||||
|
/// </summary>
|
||||||
|
private string GetHairColorFromData(PawnAppearanceData data)
|
||||||
|
{
|
||||||
|
if (data?.HairColorGeneDefNames == null || !data.HairColorGeneDefNames.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Берем первый ген (они уже отсортированы по приоритету)
|
||||||
|
string geneDefName = data.HairColorGeneDefNames.FirstOrDefault();
|
||||||
|
if (string.IsNullOrEmpty(geneDefName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Определяем цвет волос по названию гена
|
||||||
|
return GetHairColorFromGeneDefName(geneDefName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает описание цвета волос из названия гена
|
||||||
|
/// </summary>
|
||||||
|
private string GetHairColorFromGeneDefName(string geneDefName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(geneDefName))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Специфичные описания для известных генов цвета волос
|
||||||
|
switch (geneDefName)
|
||||||
|
{
|
||||||
|
case "Hair_Blond":
|
||||||
|
case "Hair_Blonde":
|
||||||
|
return "blond";
|
||||||
|
case "Hair_Brown":
|
||||||
|
return "brown";
|
||||||
|
case "Hair_Black":
|
||||||
|
return "black";
|
||||||
|
case "Hair_White":
|
||||||
|
return "white";
|
||||||
|
case "Hair_Red":
|
||||||
|
return "red";
|
||||||
|
case "Hair_Ginger":
|
||||||
|
return "ginger";
|
||||||
|
case "Hair_Auburn":
|
||||||
|
return "auburn";
|
||||||
|
case "Hair_Copper":
|
||||||
|
case "Hair_CopperBrown":
|
||||||
|
return "copper-brown";
|
||||||
|
case "Hair_Light":
|
||||||
|
return "light";
|
||||||
|
case "Hair_Dark":
|
||||||
|
return "dark";
|
||||||
|
default:
|
||||||
|
// Пытаемся определить по названию (defName всегда на английском)
|
||||||
|
if (geneDefName.Contains("Blond"))
|
||||||
|
return "blond";
|
||||||
|
if (geneDefName.Contains("Brown"))
|
||||||
|
return "brown";
|
||||||
|
if (geneDefName.Contains("Black"))
|
||||||
|
return "black";
|
||||||
|
if (geneDefName.Contains("White"))
|
||||||
|
return "white";
|
||||||
|
if (geneDefName.Contains("Red"))
|
||||||
|
return "red";
|
||||||
|
if (geneDefName.Contains("Ginger"))
|
||||||
|
return "ginger";
|
||||||
|
if (geneDefName.Contains("Auburn"))
|
||||||
|
return "auburn";
|
||||||
|
if (geneDefName.Contains("Copper"))
|
||||||
|
return "copper-brown";
|
||||||
|
if (geneDefName.Contains("Orange"))
|
||||||
|
return "orange-red";
|
||||||
|
if (geneDefName.Contains("Light"))
|
||||||
|
return "light";
|
||||||
|
if (geneDefName.Contains("Dark"))
|
||||||
|
return "dark";
|
||||||
|
if (geneDefName.Contains("Blue"))
|
||||||
|
return "blue";
|
||||||
|
if (geneDefName.Contains("Green"))
|
||||||
|
return "green";
|
||||||
|
if (geneDefName.Contains("Purple"))
|
||||||
|
return "purple";
|
||||||
|
if (geneDefName.Contains("Pink"))
|
||||||
|
return "pink";
|
||||||
|
if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey"))
|
||||||
|
return "gray";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetMoodFromTraits(List<Trait> traits)
|
private string GetMoodFromTraits(List<Trait> traits)
|
||||||
{
|
{
|
||||||
if (traits == null || !traits.Any())
|
if (traits == null || !traits.Any())
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using RimWorld;
|
using RimWorld;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Verse;
|
using Verse;
|
||||||
@@ -12,6 +13,35 @@ namespace AIImages.Services
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получает текстовое описание цвета волос
|
/// Получает текстовое описание цвета волос
|
||||||
|
/// Сначала проверяет гены цвета волос, затем использует вычисленный RimWorld цвет волос
|
||||||
|
/// </summary>
|
||||||
|
public static string GetHairColorDescription(Pawn pawn)
|
||||||
|
{
|
||||||
|
if (pawn?.genes?.GenesListForReading != null)
|
||||||
|
{
|
||||||
|
// Ищем активные и неподавленные гены цвета волос
|
||||||
|
var hairColorGenes = pawn
|
||||||
|
.genes.GenesListForReading.Where(gene =>
|
||||||
|
gene.Active && !IsGeneSuppressed(pawn, gene) && IsHairColorGene(gene.def)
|
||||||
|
)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Если есть гены цвета волос, используем их описание
|
||||||
|
if (hairColorGenes.Any())
|
||||||
|
{
|
||||||
|
var hairColorGene = hairColorGenes[0];
|
||||||
|
string geneDescription = GetHairColorGeneDescription(hairColorGene.def);
|
||||||
|
if (!string.IsNullOrEmpty(geneDescription))
|
||||||
|
return geneDescription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Иначе используем вычисленный RimWorld цвет волос
|
||||||
|
return GetHairColorDescription(pawn?.story?.HairColor ?? Color.white);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает текстовое описание цвета волос по RGB цвету (fallback метод)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetHairColorDescription(Color color)
|
public static string GetHairColorDescription(Color color)
|
||||||
{
|
{
|
||||||
@@ -43,10 +73,10 @@ namespace AIImages.Services
|
|||||||
if (pawn?.genes?.GenesListForReading == null)
|
if (pawn?.genes?.GenesListForReading == null)
|
||||||
return GetSkinToneDescription(pawn.story.SkinColor);
|
return GetSkinToneDescription(pawn.story.SkinColor);
|
||||||
|
|
||||||
// Ищем активные гены цвета кожи (особенно специальные: зелёная, синяя, красная и т.д.)
|
// Ищем активные и неподавленные гены цвета кожи (особенно специальные: зелёная, синяя, красная и т.д.)
|
||||||
var skinColorGenes = pawn
|
var skinColorGenes = pawn
|
||||||
.genes.GenesListForReading.Where(gene =>
|
.genes.GenesListForReading.Where(gene =>
|
||||||
gene.Active && IsSpecialSkinColorGene(gene.def)
|
gene.Active && !IsGeneSuppressed(pawn, gene) && IsSpecialSkinColorGene(gene.def)
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@@ -66,6 +96,7 @@ namespace AIImages.Services
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.)
|
/// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.)
|
||||||
|
/// Исключает гены меланина (Melanin1-9), так как они определяют обычный цвет кожи
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static bool IsSpecialSkinColorGene(GeneDef geneDef)
|
private static bool IsSpecialSkinColorGene(GeneDef geneDef)
|
||||||
{
|
{
|
||||||
@@ -74,6 +105,10 @@ namespace AIImages.Services
|
|||||||
|
|
||||||
string geneDefName = geneDef.defName;
|
string geneDefName = geneDef.defName;
|
||||||
|
|
||||||
|
// Исключаем гены меланина - они не дают специальный цвет
|
||||||
|
if (geneDefName.StartsWith("Skin_Melanin"))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая
|
// Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая
|
||||||
return geneDefName.StartsWith("Skin_")
|
return geneDefName.StartsWith("Skin_")
|
||||||
&& (
|
&& (
|
||||||
@@ -127,33 +162,194 @@ namespace AIImages.Services
|
|||||||
case "Skin_Green":
|
case "Skin_Green":
|
||||||
return "green skin";
|
return "green skin";
|
||||||
default:
|
default:
|
||||||
// Пытаемся определить по названию
|
// Пытаемся определить по названию (defName всегда на английском)
|
||||||
if (geneDefName.Contains("Green") || geneDefName.Contains("зел"))
|
if (geneDefName.Contains("Green"))
|
||||||
return "green skin";
|
return "green skin";
|
||||||
if (geneDefName.Contains("Blue") || geneDefName.Contains("син"))
|
if (geneDefName.Contains("Blue"))
|
||||||
return "blue skin";
|
return "blue skin";
|
||||||
if (geneDefName.Contains("Red") || geneDefName.Contains("красн"))
|
if (geneDefName.Contains("Red"))
|
||||||
return "red skin";
|
return "red skin";
|
||||||
if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт"))
|
if (geneDefName.Contains("Yellow"))
|
||||||
return "yellow skin";
|
return "yellow skin";
|
||||||
if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет"))
|
if (geneDefName.Contains("Purple"))
|
||||||
return "purple skin";
|
return "purple skin";
|
||||||
if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж"))
|
if (geneDefName.Contains("Orange"))
|
||||||
return "orange skin";
|
return "orange skin";
|
||||||
if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн"))
|
if (geneDefName.Contains("Black"))
|
||||||
return "black skin";
|
return "black skin";
|
||||||
if (geneDefName.Contains("White") || geneDefName.Contains("бел"))
|
if (geneDefName.Contains("White"))
|
||||||
return "white skin";
|
return "white skin";
|
||||||
if (
|
if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey"))
|
||||||
geneDefName.Contains("Gray")
|
|
||||||
|| geneDefName.Contains("Grey")
|
|
||||||
|| geneDefName.Contains("сер")
|
|
||||||
)
|
|
||||||
return "gray skin";
|
return "gray skin";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// /// Проверяет, подавлен ли ген другим активным геном
|
||||||
|
/// </summary>
|
||||||
|
private static bool IsGeneSuppressed(Pawn pawn, Gene gene)
|
||||||
|
{
|
||||||
|
if (pawn?.genes == null || gene?.def == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// В RimWorld, если ген активен, он уже учтён в системе
|
||||||
|
// Но мы можем проверить, подавляет ли другой активный ген данный ген
|
||||||
|
// Используем GeneUtility для проверки подавления
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Проверяем все активные гены на предмет подавления данного гена
|
||||||
|
foreach (var otherGene in pawn.genes.GenesListForReading)
|
||||||
|
{
|
||||||
|
if (otherGene.Active && otherGene != gene && otherGene.def != null)
|
||||||
|
{
|
||||||
|
// Проверяем через GeneUtility, если доступен
|
||||||
|
// Или проверяем свойство suppresses через reflection, если оно есть
|
||||||
|
var suppressesField = otherGene.def.GetType().GetField("suppresses");
|
||||||
|
if (suppressesField != null)
|
||||||
|
{
|
||||||
|
var suppresses = suppressesField.GetValue(otherGene.def);
|
||||||
|
if (
|
||||||
|
suppresses
|
||||||
|
is System.Collections.Generic.List<GeneDef> suppressesList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (suppressesList.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
suppresses
|
||||||
|
is System.Collections.Generic.IEnumerable<GeneDef> suppressesEnum
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (suppressesEnum.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Если reflection не работает, возвращаем false
|
||||||
|
// В RimWorld свойство Active уже учитывает подавление
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверяет, является ли ген геном цвета волос
|
||||||
|
/// </summary>
|
||||||
|
private static bool IsHairColorGene(GeneDef geneDef)
|
||||||
|
{
|
||||||
|
if (geneDef == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string geneDefName = geneDef.defName;
|
||||||
|
|
||||||
|
// Проверяем стандартные паттерны для генов цвета волос
|
||||||
|
return geneDefName.StartsWith("Hair_")
|
||||||
|
|| geneDefName.Contains("HairColor")
|
||||||
|
|| geneDefName.Contains("HairColour")
|
||||||
|
|| geneDefName.Contains("HairTone")
|
||||||
|
|| (
|
||||||
|
geneDefName.Contains("Hair")
|
||||||
|
&& (
|
||||||
|
geneDefName.Contains("Color")
|
||||||
|
|| geneDefName.Contains("Colour")
|
||||||
|
|| geneDefName.Contains("Red")
|
||||||
|
|| geneDefName.Contains("Blue")
|
||||||
|
|| geneDefName.Contains("Green")
|
||||||
|
|| geneDefName.Contains("Blond")
|
||||||
|
|| geneDefName.Contains("Brown")
|
||||||
|
|| geneDefName.Contains("Black")
|
||||||
|
|| geneDefName.Contains("White")
|
||||||
|
|| geneDefName.Contains("Light")
|
||||||
|
|| geneDefName.Contains("Dark")
|
||||||
|
|| geneDefName.Contains("Ginger")
|
||||||
|
|| geneDefName.Contains("Auburn")
|
||||||
|
|| geneDefName.Contains("Copper")
|
||||||
|
|| geneDefName.Contains("Orange")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получает описание цвета волос из гена
|
||||||
|
/// </summary>
|
||||||
|
private static string GetHairColorGeneDescription(GeneDef geneDef)
|
||||||
|
{
|
||||||
|
if (geneDef == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string geneDefName = geneDef.defName;
|
||||||
|
|
||||||
|
// Специфичные описания для известных генов цвета волос
|
||||||
|
switch (geneDefName)
|
||||||
|
{
|
||||||
|
case "Hair_Blond":
|
||||||
|
case "Hair_Blonde":
|
||||||
|
return "blond hair";
|
||||||
|
case "Hair_Brown":
|
||||||
|
return "brown hair";
|
||||||
|
case "Hair_Black":
|
||||||
|
return "black hair";
|
||||||
|
case "Hair_White":
|
||||||
|
return "white hair";
|
||||||
|
case "Hair_Red":
|
||||||
|
return "red hair";
|
||||||
|
case "Hair_Ginger":
|
||||||
|
return "ginger hair";
|
||||||
|
case "Hair_Auburn":
|
||||||
|
return "auburn hair";
|
||||||
|
case "Hair_Copper":
|
||||||
|
case "Hair_CopperBrown":
|
||||||
|
return "copper-brown hair";
|
||||||
|
case "Hair_Light":
|
||||||
|
return "light hair";
|
||||||
|
case "Hair_Dark":
|
||||||
|
return "dark hair";
|
||||||
|
default:
|
||||||
|
// Пытаемся определить по названию (defName всегда на английском)
|
||||||
|
// Добавляем поддержку конкретных генов из RimWorld
|
||||||
|
if (geneDefName.Contains("Blond"))
|
||||||
|
return "blond hair";
|
||||||
|
if (geneDefName.Contains("Brown"))
|
||||||
|
return "brown hair";
|
||||||
|
if (geneDefName.Contains("Black"))
|
||||||
|
return "black hair";
|
||||||
|
if (geneDefName.Contains("White"))
|
||||||
|
return "white hair";
|
||||||
|
if (geneDefName.Contains("Red"))
|
||||||
|
return "red hair";
|
||||||
|
if (geneDefName.Contains("Ginger"))
|
||||||
|
return "ginger hair";
|
||||||
|
if (geneDefName.Contains("Auburn"))
|
||||||
|
return "auburn hair";
|
||||||
|
if (geneDefName.Contains("Copper"))
|
||||||
|
return "copper-brown hair";
|
||||||
|
if (geneDefName.Contains("Orange"))
|
||||||
|
return "orange-red hair";
|
||||||
|
if (geneDefName.Contains("Light"))
|
||||||
|
return "light hair";
|
||||||
|
if (geneDefName.Contains("Dark"))
|
||||||
|
return "dark hair";
|
||||||
|
if (geneDefName.Contains("Blue"))
|
||||||
|
return "blue hair";
|
||||||
|
if (geneDefName.Contains("Green"))
|
||||||
|
return "green hair";
|
||||||
|
if (geneDefName.Contains("Purple"))
|
||||||
|
return "purple hair";
|
||||||
|
if (geneDefName.Contains("Pink"))
|
||||||
|
return "pink hair";
|
||||||
|
if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey"))
|
||||||
|
return "gray hair";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получает текстовое описание цвета кожи по RGB цвету (fallback метод)
|
/// Получает текстовое описание цвета кожи по RGB цвету (fallback метод)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using AIImages.Models;
|
using AIImages.Models;
|
||||||
using RimWorld;
|
using RimWorld;
|
||||||
@@ -34,13 +35,24 @@ namespace AIImages.Services
|
|||||||
{
|
{
|
||||||
var skinColorGenes = pawn
|
var skinColorGenes = pawn
|
||||||
.genes.GenesListForReading
|
.genes.GenesListForReading
|
||||||
.Where(gene => gene.Active && IsSkinColorGene(gene.def))
|
.Where(gene => gene.Active && IsSkinColorGene(gene.def) && !IsGeneSuppressed(pawn, gene))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
foreach (var gene in skinColorGenes)
|
foreach (var gene in skinColorGenes)
|
||||||
{
|
{
|
||||||
data.SkinColorGeneDefNames.Add(gene.def.defName);
|
data.SkinColorGeneDefNames.Add(gene.def.defName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Извлекаем гены цвета волос
|
||||||
|
var hairColorGenes = pawn
|
||||||
|
.genes.GenesListForReading
|
||||||
|
.Where(gene => gene.Active && IsHairColorGene(gene.def) && !IsGeneSuppressed(pawn, gene))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var gene in hairColorGenes)
|
||||||
|
{
|
||||||
|
data.HairColorGeneDefNames.Add(gene.def.defName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Извлекаем черты характера
|
// Извлекаем черты характера
|
||||||
@@ -110,11 +122,10 @@ namespace AIImages.Services
|
|||||||
if (pawn.story.hairDef != null)
|
if (pawn.story.hairDef != null)
|
||||||
{
|
{
|
||||||
sb.AppendLine("AIImages.Appearance.Hairstyle".Translate(pawn.story.hairDef.label));
|
sb.AppendLine("AIImages.Appearance.Hairstyle".Translate(pawn.story.hairDef.label));
|
||||||
if (pawn.story.HairColor != null)
|
// Используем метод с проверкой генов
|
||||||
|
string hairColorDescription = ColorDescriptionService.GetHairColorDescription(pawn);
|
||||||
|
if (!string.IsNullOrEmpty(hairColorDescription))
|
||||||
{
|
{
|
||||||
string hairColorDescription = ColorDescriptionService.GetHairColorDescription(
|
|
||||||
pawn.story.HairColor
|
|
||||||
);
|
|
||||||
sb.AppendLine(
|
sb.AppendLine(
|
||||||
"AIImages.Appearance.HairColorDesc".Translate(hairColorDescription)
|
"AIImages.Appearance.HairColorDesc".Translate(hairColorDescription)
|
||||||
);
|
);
|
||||||
@@ -208,5 +219,100 @@ namespace AIImages.Services
|
|||||||
|| geneDefName.Contains("SkinColor")
|
|| geneDefName.Contains("SkinColor")
|
||||||
|| geneDefName.Contains("SkinTone");
|
|| geneDefName.Contains("SkinTone");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверяет, является ли ген геном цвета волос
|
||||||
|
/// </summary>
|
||||||
|
private bool IsHairColorGene(GeneDef geneDef)
|
||||||
|
{
|
||||||
|
if (geneDef == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string geneDefName = geneDef.defName;
|
||||||
|
return geneDefName.StartsWith("Hair_")
|
||||||
|
|| geneDefName.Contains("HairColor")
|
||||||
|
|| geneDefName.Contains("HairColour")
|
||||||
|
|| geneDefName.Contains("HairTone")
|
||||||
|
|| (geneDefName.Contains("Hair") && (
|
||||||
|
geneDefName.Contains("Color")
|
||||||
|
|| geneDefName.Contains("Colour")
|
||||||
|
|| geneDefName.Contains("Red")
|
||||||
|
|| geneDefName.Contains("Blue")
|
||||||
|
|| geneDefName.Contains("Green")
|
||||||
|
|| geneDefName.Contains("Blond")
|
||||||
|
|| geneDefName.Contains("Brown")
|
||||||
|
|| geneDefName.Contains("Black")
|
||||||
|
|| geneDefName.Contains("White")
|
||||||
|
|| geneDefName.Contains("Light")
|
||||||
|
|| geneDefName.Contains("Dark")
|
||||||
|
|| geneDefName.Contains("Ginger")
|
||||||
|
|| geneDefName.Contains("Auburn")
|
||||||
|
|| geneDefName.Contains("Copper")
|
||||||
|
|| geneDefName.Contains("Orange")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверяет, подавлен ли ген другим активным геном
|
||||||
|
/// </summary>
|
||||||
|
private bool IsGeneSuppressed(Pawn pawn, Gene gene)
|
||||||
|
{
|
||||||
|
if (pawn?.genes == null || gene?.def == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// В RimWorld, если ген активен, он уже учтён в системе
|
||||||
|
// Но мы можем проверить, подавляет ли другой активный ген данный ген
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Проверяем все активные гены на предмет подавления данного гена
|
||||||
|
foreach (var otherGene in pawn.genes.GenesListForReading)
|
||||||
|
{
|
||||||
|
if (otherGene.Active && otherGene != gene && otherGene.def != null)
|
||||||
|
{
|
||||||
|
// Проверяем через reflection, так как свойство suppresses может быть приватным
|
||||||
|
var suppressesField = otherGene.def.GetType().GetField("suppresses");
|
||||||
|
if (suppressesField != null)
|
||||||
|
{
|
||||||
|
var suppresses = suppressesField.GetValue(otherGene.def);
|
||||||
|
if (suppresses is System.Collections.Generic.List<GeneDef> suppressesList)
|
||||||
|
{
|
||||||
|
if (suppressesList.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (suppresses is System.Collections.Generic.IEnumerable<GeneDef> suppressesEnum)
|
||||||
|
{
|
||||||
|
if (suppressesEnum.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Также проверяем свойство, если оно публичное
|
||||||
|
var suppressesProperty = otherGene.def.GetType().GetProperty("suppresses");
|
||||||
|
if (suppressesProperty != null)
|
||||||
|
{
|
||||||
|
var suppresses = suppressesProperty.GetValue(otherGene.def);
|
||||||
|
if (suppresses is System.Collections.Generic.List<GeneDef> suppressesList)
|
||||||
|
{
|
||||||
|
if (suppressesList.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (suppresses is System.Collections.Generic.IEnumerable<GeneDef> suppressesEnum)
|
||||||
|
{
|
||||||
|
if (suppressesEnum.Contains(gene.def))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Если reflection не работает, возвращаем false
|
||||||
|
// В RimWorld свойство Active уже учитывает подавление
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -603,7 +603,7 @@ namespace AIImages
|
|||||||
("AIImages.Info.Hair".Translate(), appearanceData.HairStyle),
|
("AIImages.Info.Hair".Translate(), appearanceData.HairStyle),
|
||||||
(
|
(
|
||||||
"AIImages.Info.HairColor".Translate(),
|
"AIImages.Info.HairColor".Translate(),
|
||||||
ColorDescriptionService.GetHairColorDescription(appearanceData.HairColor)
|
ColorDescriptionService.GetHairColorDescription(pawn)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user