Added Appearence editor for ZA and annotated hair styles and eye cuts. (#4642)

This commit is contained in:
Pasquale Nardiello
2025-12-01 04:51:12 +01:00
committed by GitHub
parent 7658ba8994
commit dc1818d589
6 changed files with 70 additions and 15 deletions

View File

@@ -23,6 +23,7 @@ public sealed class SaveBlockAccessor9ZA(SAV9ZA sav) : SCBlockAccessor
public Epoch1900DateTimeValue EnrollmentDate { get; } = new(Block(sav, KEnrollmentDate)); // not actually used
public Coordinates9a Coordinates { get; } = new(sav, Block(sav, KCoordinates));
public InfiniteRoyale9a InfiniteRoyale { get; } = new(sav, Block(sav, KInfiniteRoyale));
public PlayerAppearance9a PlayerAppearance { get; } = new(sav, Block(sav, KCurrentAppearance));
public PlayerFashion9a PlayerFashion { get; } = new(sav, Block(sav, KCurrentClothing));
public ConfigSave9a Config { get; } = new(sav, Block(sav, KConfig));

View File

@@ -72,6 +72,7 @@ public override void CopyChangesFrom(SaveFile sav)
public Epoch1900DateTimeValue StartTime => Blocks.EnrollmentDate;
public Coordinates9a Coordinates => Blocks.Coordinates;
public InfiniteRoyale9a InfiniteRoyale => Blocks.InfiniteRoyale;
public PlayerAppearance9a PlayerAppearance => Blocks.PlayerAppearance;
public PlayerFashion9a PlayerFashion => Blocks.PlayerFashion;
public ConfigSave9a Config => Blocks.Config;
#endregion

View File

@@ -1,4 +1,3 @@
using System.ComponentModel;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
@@ -6,7 +5,6 @@ namespace PKHeX.Core;
/// <summary>
/// Stores the selected facial appearances of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class PlayerAppearance9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public ulong SkinColor { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }

View File

@@ -6,18 +6,17 @@ namespace PKHeX.Core;
/// <summary>
/// Stores the selected clothing choices of the player.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public sealed class PlayerFashion9(SAV9SV sav, SCBlock block) : SaveBlock<SAV9SV>(sav, block.Raw)
{
public ulong Base { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
public ulong Accessory { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }
public ulong Bag { get => ReadUInt64LittleEndian(Data[0x10..]); set => WriteUInt64LittleEndian(Data[0x10..], value); }
public ulong Eyewear { get => ReadUInt64LittleEndian(Data[0x18..]); set => WriteUInt64LittleEndian(Data[0x18..], value); }
public ulong Footwear { get => ReadUInt64LittleEndian(Data[0x20..]); set => WriteUInt64LittleEndian(Data[0x20..], value); }
public ulong Gloves { get => ReadUInt64LittleEndian(Data[0x28..]); set => WriteUInt64LittleEndian(Data[0x28..], value); }
public ulong Headwear { get => ReadUInt64LittleEndian(Data[0x30..]); set => WriteUInt64LittleEndian(Data[0x30..], value); }
public ulong Hairstyle { get => ReadUInt64LittleEndian(Data[0x38..]); set => WriteUInt64LittleEndian(Data[0x38..], value); }
public ulong Legwear { get => ReadUInt64LittleEndian(Data[0x40..]); set => WriteUInt64LittleEndian(Data[0x40..], value); }
public ulong Clothing { get => ReadUInt64LittleEndian(Data[0x48..]); set => WriteUInt64LittleEndian(Data[0x48..], value); }
public ulong Face { get => ReadUInt64LittleEndian(Data[0x50..]); set => WriteUInt64LittleEndian(Data[0x50..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Base { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Accessory { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Bag { get => ReadUInt64LittleEndian(Data[0x10..]); set => WriteUInt64LittleEndian(Data[0x10..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Eyewear { get => ReadUInt64LittleEndian(Data[0x18..]); set => WriteUInt64LittleEndian(Data[0x18..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Footwear { get => ReadUInt64LittleEndian(Data[0x20..]); set => WriteUInt64LittleEndian(Data[0x20..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Gloves { get => ReadUInt64LittleEndian(Data[0x28..]); set => WriteUInt64LittleEndian(Data[0x28..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Headwear { get => ReadUInt64LittleEndian(Data[0x30..]); set => WriteUInt64LittleEndian(Data[0x30..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Hairstyle { get => ReadUInt64LittleEndian(Data[0x38..]); set => WriteUInt64LittleEndian(Data[0x38..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Legwear { get => ReadUInt64LittleEndian(Data[0x40..]); set => WriteUInt64LittleEndian(Data[0x40..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Clothing { get => ReadUInt64LittleEndian(Data[0x48..]); set => WriteUInt64LittleEndian(Data[0x48..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Face { get => ReadUInt64LittleEndian(Data[0x50..]); set => WriteUInt64LittleEndian(Data[0x50..], value); }
}

View File

@@ -0,0 +1,28 @@
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core;
/// <summary>
/// Stores the selected traits of appearance of the player, minus hairstyle and eye cut.
/// </summary>
public sealed class PlayerAppearance9a(SAV9ZA sav, SCBlock block) : SaveBlock<SAV9ZA>(sav, block.Raw)
{
public uint SkinColor { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
public uint LipColor { get => ReadUInt32LittleEndian(Data[0x04..]); set => WriteUInt32LittleEndian(Data[0x04..], value); }
public uint DarkCircles { get => ReadUInt32LittleEndian(Data[0x08..]); set => WriteUInt32LittleEndian(Data[0x08..], value); }
public uint EyeColor { get => ReadUInt32LittleEndian(Data[0x0C..]); set => WriteUInt32LittleEndian(Data[0x0C..], value); }
public uint EyebrowColor { get => ReadUInt32LittleEndian(Data[0x10..]); set => WriteUInt32LittleEndian(Data[0x10..], value); }
public uint EyebrowShape { get => ReadUInt32LittleEndian(Data[0x14..]); set => WriteUInt32LittleEndian(Data[0x14..], value); }
public uint EyelashColor { get => ReadUInt32LittleEndian(Data[0x18..]); set => WriteUInt32LittleEndian(Data[0x18..], value); }
public uint EyelashShape { get => ReadUInt32LittleEndian(Data[0x1C..]); set => WriteUInt32LittleEndian(Data[0x1C..], value); }
public uint BeautySpotFirst { get => ReadUInt32LittleEndian(Data[0x20..]); set => WriteUInt32LittleEndian(Data[0x20..], value); }
public uint BeautySpotSecond { get => ReadUInt32LittleEndian(Data[0x24..]); set => WriteUInt32LittleEndian(Data[0x24..], value); }
public uint Freckles { get => ReadUInt32LittleEndian(Data[0x28..]); set => WriteUInt32LittleEndian(Data[0x28..], value); }
public uint HairColor { get => ReadUInt32LittleEndian(Data[0x2C..]); set => WriteUInt32LittleEndian(Data[0x2C..], value); }
public uint ColorBlocking { get => ReadUInt32LittleEndian(Data[0x30..]); set => WriteUInt32LittleEndian(Data[0x30..], value); }
public uint BalayageFadeFirst { get => ReadUInt32LittleEndian(Data[0x34..]); set => WriteUInt32LittleEndian(Data[0x34..], value); }
public uint BalayageFadeSecond { get => ReadUInt32LittleEndian(Data[0x38..]); set => WriteUInt32LittleEndian(Data[0x38..], value); }
public uint FaceShape { get => ReadUInt32LittleEndian(Data[0x3C..]); set => WriteUInt32LittleEndian(Data[0x3C..], value); }
public uint Bangs { get => ReadUInt32LittleEndian(Data[0x40..]); set => WriteUInt32LittleEndian(Data[0x44..], value); }
public uint HairColorMode { get => ReadUInt32LittleEndian(Data[0x44..]); set => WriteUInt32LittleEndian(Data[0x44..], value); }
}

View File

@@ -8,6 +8,34 @@ namespace PKHeX.Core;
/// </summary>
public sealed class PlayerFashion9a(SAV9ZA sav, SCBlock block) : SaveBlock<SAV9ZA>(sav, block.Raw)
{
/*
private static ReadOnlySpan<ulong> HairStyles =>
[
0x602243E9930CA16A, //hi-top fade
0x687687B775074243, //undercut pixie
0x24B41B3ED9600552, //flyaway short cut
0xDB129181F4248AE2, //slicked back
0x80DF9648F4352C39, //simple short hair
0x1E3D50B87ACACDA4, //half-up chignon
0xFDC0716E8FA64F1E, //simple bob
0x1457BCB559D4A5A4, //low chignon
0x51A05031BE8DABCC, //asymmetrical bob
0x85D18D31D168FE64, //ponytail
0x4CC69633553865E4, //braids
0xE75A2816E2B0B2B5, //long and wavy
0x6C59B2A77D1231F7, //side ponytail
0x21767F6261C9F4DD, //pigtails
];
private static ReadOnlySpan<ulong> EyeCuts =>
[
0xF99D26ADCE42E2BE, //droopy
0x22EF6E329FB657D1, //half-open
0xC8CA8B6B8EE7CC38, //rounded
0x93071833CC739399, //angled
];
*/
[TypeConverter(typeof(TypeConverterU64))] public ulong Base { get => ReadUInt64LittleEndian(Data); set => WriteUInt64LittleEndian(Data, value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Accessory { get => ReadUInt64LittleEndian(Data[0x08..]); set => WriteUInt64LittleEndian(Data[0x08..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Bag { get => ReadUInt64LittleEndian(Data[0x10..]); set => WriteUInt64LittleEndian(Data[0x10..], value); }
@@ -18,7 +46,7 @@ public sealed class PlayerFashion9a(SAV9ZA sav, SCBlock block) : SaveBlock<SAV9Z
[TypeConverter(typeof(TypeConverterU64))] public ulong Hairstyle { get => ReadUInt64LittleEndian(Data[0x38..]); set => WriteUInt64LittleEndian(Data[0x38..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Legwear { get => ReadUInt64LittleEndian(Data[0x40..]); set => WriteUInt64LittleEndian(Data[0x40..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Clothing { get => ReadUInt64LittleEndian(Data[0x48..]); set => WriteUInt64LittleEndian(Data[0x48..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Face { get => ReadUInt64LittleEndian(Data[0x50..]); set => WriteUInt64LittleEndian(Data[0x50..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong Eyes { get => ReadUInt64LittleEndian(Data[0x50..]); set => WriteUInt64LittleEndian(Data[0x50..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong LowerBody { get => ReadUInt64LittleEndian(Data[0x58..]); set => WriteUInt64LittleEndian(Data[0x58..], value); }
[TypeConverter(typeof(TypeConverterU64))] public ulong UpperBody { get => ReadUInt64LittleEndian(Data[0x60..]); set => WriteUInt64LittleEndian(Data[0x60..], value); }
}