using AcDream.Content;
using AcDream.Core.Items;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Types;
namespace AcDream.App.UI.Layout;
///
/// Resolves the authored enum display names consumed by retail's appraisal
/// helpers. Material names follow
/// MaterialTypeEnumMapper::MaterialTypeToString @ 0x005CD500;
/// creature and heritage names follow
/// AppraisalSystem::InqCreatureDisplayName @ 0x005B59E0 and
/// InqHeritageGroupDisplayName @ 0x005B4710.
///
public sealed class RetailAppraisalNameResolver
{
private const uint MaterialClientEnum = 0x10000001u;
private const uint MaterialSubEnum = 1u;
public static RetailAppraisalNameResolver Empty { get; } = new(
new Dictionary(),
new CreatureDisplayNameResolver(new Dictionary()));
private readonly IReadOnlyDictionary _materials;
private readonly CreatureDisplayNameResolver _creatures;
public RetailAppraisalNameResolver(
IReadOnlyDictionary materials,
CreatureDisplayNameResolver creatures)
{
_materials = materials
?? throw new ArgumentNullException(nameof(materials));
_creatures = creatures
?? throw new ArgumentNullException(nameof(creatures));
}
public static RetailAppraisalNameResolver Load(
IDatReaderWriter dats,
CreatureDisplayNameResolver creatures)
{
ArgumentNullException.ThrowIfNull(dats);
ArgumentNullException.ThrowIfNull(creatures);
var materials = new Dictionary();
uint masterDid = (uint)dats.Portal.Db.Header.MasterMapId;
EnumIDMap? master = masterDid == 0u
? null
: dats.Get(masterDid);
if (master is not null
&& master.ClientEnumToID.TryGetValue(
MaterialClientEnum,
out uint materialRootMapDid)
&& dats.Get(materialRootMapDid) is { } materialRootMap
&& materialRootMap.ClientEnumToID.TryGetValue(
MaterialSubEnum,
out uint materialMapDid)
&& dats.Get(materialMapDid) is { } materialMap)
{
foreach ((uint id, PStringBase text)
in materialMap.ClientEnumToName)
{
materials.TryAdd(id, Normalize(text.Value));
}
}
return new RetailAppraisalNameResolver(materials, creatures);
}
public string ResolveCreature(int creatureType)
=> _creatures.Resolve(creatureType);
public string ResolveHeritage(int heritageGroup)
=> heritageGroup switch
{
2 => "Gharu'ndim",
5 => "Umbraen",
13 => "Olthoi",
_ => CharacterIdentityText.HeritageGroupDisplayName(heritageGroup)
?? string.Empty,
};
public string ResolveMaterial(int materialType)
=> materialType > 0
&& _materials.TryGetValue((uint)materialType, out string? name)
? name
: string.Empty;
///
/// Port of the material-decoration tail in
/// ACCWeenieObject::GetObjectName @ 0x0058E6E0. Retail first
/// chooses the singular/plural base name, removes an already-authored
/// occurrence of the resolved material, trims it, then prefixes the
/// material exactly once.
///
public string ResolveAppropriateName(ClientObject obj)
{
ArgumentNullException.ThrowIfNull(obj);
string baseName = obj.GetAppropriateName();
if (obj.MaterialType is not { } materialType)
return baseName;
string material = ResolveMaterial(unchecked((int)materialType));
if (string.IsNullOrEmpty(material))
return baseName;
string remainder = baseName
.Replace(material, string.Empty, StringComparison.Ordinal)
.Trim();
return string.IsNullOrEmpty(remainder)
? material
: $"{material} {remainder}";
}
private static string Normalize(string value)
=> value.Replace('_', ' ');
}