using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Penumbra.GameData.Structs;
namespace Glamourer.GameData;
/// A struct containing everything to replicate the appearance of a human NPC.
public unsafe struct NpcData
{
/// The name of the NPC.
public string Name;
/// The customizations of the NPC.
public CustomizeArray Customize;
/// The equipment appearance of the NPC, 10 * CharacterArmor.
private fixed byte _equip[40];
/// The mainhand weapon appearance of the NPC.
public CharacterWeapon Mainhand;
/// The offhand weapon appearance of the NPC.
public CharacterWeapon Offhand;
/// The data ID of the NPC, either event NPC or battle NPC name.
public NpcId Id;
/// The Model ID of the NPC.
public uint ModelId;
/// Whether the NPCs visor is toggled.
public bool VisorToggled;
/// Whether the NPC is an event NPC or a battle NPC.
public ObjectKind Kind;
/// Obtain the equipment as CharacterArmors.
public ReadOnlySpan Equip
{
get
{
fixed (byte* ptr = _equip)
{
return new ReadOnlySpan((CharacterArmor*)ptr, 10);
}
}
}
/// Write all the gear appearance to a single string.
public string WriteGear()
{
var sb = new StringBuilder(128);
var span = Equip;
for (var i = 0; i < 10; ++i)
{
sb.Append(span[i].Set.Id.ToString("D4"))
.Append('-')
.Append(span[i].Variant.Id.ToString("D3"))
.Append('-')
.Append(span[i].Stain.Id.ToString("D3"))
.Append(", ");
}
sb.Append(Mainhand.Skeleton.Id.ToString("D4"))
.Append('-')
.Append(Mainhand.Weapon.Id.ToString("D4"))
.Append('-')
.Append(Mainhand.Variant.Id.ToString("D3"))
.Append('-')
.Append(Mainhand.Stain.Id.ToString("D4"))
.Append(", ")
.Append(Offhand.Skeleton.Id.ToString("D4"))
.Append('-')
.Append(Offhand.Weapon.Id.ToString("D4"))
.Append('-')
.Append(Offhand.Variant.Id.ToString("D3"))
.Append('-')
.Append(Offhand.Stain.Id.ToString("D3"));
return sb.ToString();
}
/// Set an equipment piece to a given value.
internal void Set(int idx, uint value)
{
fixed (byte* ptr = _equip)
{
((uint*)ptr)[idx] = value;
}
}
/// Check if the appearance data, excluding ID and Name, of two NpcData is equal.
public bool DataEquals(in NpcData other)
{
if (ModelId != other.ModelId)
return false;
if (VisorToggled != other.VisorToggled)
return false;
if (!Customize.Equals(other.Customize))
return false;
if (!Mainhand.Equals(other.Mainhand))
return false;
if (!Offhand.Equals(other.Offhand))
return false;
fixed (byte* ptr1 = _equip, ptr2 = other._equip)
{
return new ReadOnlySpan(ptr1, 40).SequenceEqual(new ReadOnlySpan(ptr2, 40));
}
}
}