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

This commit is contained in:
Leonid Pershin
2025-11-01 09:15:29 +03:00
parent 60dcb279ae
commit 30010078b4
5 changed files with 431 additions and 34 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using AIImages.Models;
using RimWorld;
@@ -34,13 +35,24 @@ namespace AIImages.Services
{
var skinColorGenes = pawn
.genes.GenesListForReading
.Where(gene => gene.Active && IsSkinColorGene(gene.def))
.Where(gene => gene.Active && IsSkinColorGene(gene.def) && !IsGeneSuppressed(pawn, gene))
.ToList();
foreach (var gene in skinColorGenes)
{
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)
{
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(
"AIImages.Appearance.HairColorDesc".Translate(hairColorDescription)
);
@@ -208,5 +219,100 @@ namespace AIImages.Services
|| geneDefName.Contains("SkinColor")
|| 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;
}
}
}