187 lines
6.4 KiB
C#
187 lines
6.4 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using AIImages.Models;
|
||
using RimWorld;
|
||
using Verse;
|
||
|
||
namespace AIImages.Services
|
||
{
|
||
/// <summary>
|
||
/// Сервис для извлечения и описания данных о внешности персонажа
|
||
/// </summary>
|
||
public class PawnDescriptionService : IPawnDescriptionService
|
||
{
|
||
public PawnAppearanceData ExtractAppearanceData(Pawn pawn)
|
||
{
|
||
if (pawn?.story == null)
|
||
return null;
|
||
|
||
var data = new PawnAppearanceData
|
||
{
|
||
Name = pawn.Name?.ToStringShort ?? "Unknown",
|
||
Gender = pawn.gender,
|
||
Age = pawn.ageTracker.AgeBiologicalYears,
|
||
BodyType = pawn.story.bodyType?.defName,
|
||
SkinColor = pawn.story.SkinColor,
|
||
HairStyle = pawn.story.hairDef?.label,
|
||
HairDefName = pawn.story.hairDef?.defName,
|
||
HairColor = pawn.story.HairColor,
|
||
};
|
||
|
||
// Извлекаем черты характера
|
||
if (pawn.story.traits?.allTraits != null)
|
||
{
|
||
data.Traits.AddRange(pawn.story.traits.allTraits);
|
||
}
|
||
|
||
// Извлекаем одежду
|
||
if (pawn.apparel?.WornApparel != null)
|
||
{
|
||
foreach (var apparel in pawn.apparel.WornApparel)
|
||
{
|
||
var apparelData = new ApparelData
|
||
{
|
||
Label = apparel.def.label,
|
||
DefName = apparel.def.defName,
|
||
Material = apparel.Stuff?.label,
|
||
MaterialDefName = apparel.Stuff?.defName,
|
||
Color = apparel.DrawColor,
|
||
LayerType = apparel.def.apparel?.LastLayer.ToString(),
|
||
Durability = apparel.HitPoints,
|
||
MaxDurability = apparel.MaxHitPoints,
|
||
};
|
||
|
||
if (apparel.TryGetQuality(out QualityCategory quality))
|
||
{
|
||
apparelData.Quality = quality;
|
||
}
|
||
|
||
data.Apparel.Add(apparelData);
|
||
}
|
||
}
|
||
|
||
return data;
|
||
}
|
||
|
||
public string GetAppearanceDescription(Pawn pawn)
|
||
{
|
||
if (pawn?.story == null)
|
||
return "AIImages.Appearance.NoInfo".Translate();
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
|
||
// Пол
|
||
sb.AppendLine("AIImages.Appearance.Gender".Translate(pawn.gender.GetLabel()));
|
||
|
||
// Возраст
|
||
sb.AppendLine("AIImages.Appearance.Age".Translate(pawn.ageTracker.AgeBiologicalYears));
|
||
|
||
// Тип тела
|
||
if (pawn.story.bodyType != null)
|
||
{
|
||
sb.AppendLine(
|
||
"AIImages.Appearance.BodyType".Translate(pawn.story.bodyType.defName)
|
||
);
|
||
}
|
||
|
||
// Цвет кожи (с умным описанием)
|
||
if (pawn.story.SkinColor != null)
|
||
{
|
||
string skinDescription = ColorDescriptionService.GetSkinToneDescription(
|
||
pawn.story.SkinColor
|
||
);
|
||
sb.AppendLine("AIImages.Appearance.SkinTone".Translate(skinDescription));
|
||
}
|
||
|
||
// Волосы
|
||
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.story.HairColor
|
||
);
|
||
sb.AppendLine(
|
||
"AIImages.Appearance.HairColorDesc".Translate(hairColorDescription)
|
||
);
|
||
}
|
||
}
|
||
|
||
// Черты характера
|
||
if (pawn.story.traits?.allTraits != null && pawn.story.traits.allTraits.Any())
|
||
{
|
||
sb.AppendLine("\n" + "AIImages.Appearance.Traits".Translate());
|
||
foreach (var trait in pawn.story.traits.allTraits)
|
||
{
|
||
sb.AppendLine($" • {trait.LabelCap}");
|
||
}
|
||
}
|
||
|
||
return sb.ToString();
|
||
}
|
||
|
||
public string GetApparelDescription(Pawn pawn)
|
||
{
|
||
if (pawn?.apparel == null)
|
||
return "AIImages.Apparel.NoInfo".Translate();
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
List<Apparel> wornApparel = pawn.apparel.WornApparel;
|
||
|
||
if (wornApparel == null || !wornApparel.Any())
|
||
{
|
||
sb.AppendLine("AIImages.Apparel.NoClothes".Translate());
|
||
}
|
||
else
|
||
{
|
||
sb.AppendLine("AIImages.Apparel.ListHeader".Translate(wornApparel.Count) + "\n");
|
||
foreach (Apparel apparel in wornApparel)
|
||
{
|
||
FormatApparelItem(sb, apparel);
|
||
}
|
||
}
|
||
|
||
return sb.ToString();
|
||
}
|
||
|
||
private void FormatApparelItem(StringBuilder sb, Apparel apparel)
|
||
{
|
||
sb.AppendLine($"• {apparel.LabelCap}");
|
||
|
||
if (apparel.TryGetQuality(out QualityCategory quality))
|
||
{
|
||
sb.AppendLine("AIImages.Apparel.Quality".Translate(quality.GetLabel()));
|
||
}
|
||
|
||
if (apparel.Stuff != null)
|
||
{
|
||
sb.AppendLine("AIImages.Apparel.Material".Translate(apparel.Stuff.LabelCap));
|
||
}
|
||
|
||
if (apparel.HitPoints < apparel.MaxHitPoints)
|
||
{
|
||
int percentage = (int)((float)apparel.HitPoints / apparel.MaxHitPoints * 100);
|
||
sb.AppendLine(
|
||
"AIImages.Apparel.Durability".Translate(
|
||
apparel.HitPoints,
|
||
apparel.MaxHitPoints,
|
||
percentage
|
||
)
|
||
);
|
||
}
|
||
|
||
if (apparel.DrawColor != UnityEngine.Color.white)
|
||
{
|
||
string colorDesc = ColorDescriptionService.GetApparelColorDescription(
|
||
apparel.DrawColor
|
||
);
|
||
sb.AppendLine("AIImages.Apparel.ColorDesc".Translate(colorDesc));
|
||
}
|
||
|
||
sb.AppendLine();
|
||
}
|
||
}
|
||
}
|