mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Start restructuring CharacterUtility
This commit is contained in:
parent
56286e0123
commit
7bad131542
4 changed files with 250 additions and 252 deletions
|
|
@ -4,151 +4,146 @@ using System.Linq;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Utility.Signatures;
|
using Dalamud.Utility.Signatures;
|
||||||
using Penumbra.GameData;
|
using Penumbra.GameData;
|
||||||
|
using Penumbra.Interop.Structs;
|
||||||
|
|
||||||
namespace Penumbra.Interop;
|
namespace Penumbra.Interop;
|
||||||
|
|
||||||
public unsafe partial class CharacterUtility : IDisposable
|
public unsafe partial class CharacterUtility : IDisposable
|
||||||
{
|
{
|
||||||
public record struct InternalIndex( int Value );
|
public record struct InternalIndex(int Value);
|
||||||
|
|
||||||
// A static pointer to the CharacterUtility address.
|
/// <summary> A static pointer to the CharacterUtility address. </summary>
|
||||||
[Signature( Sigs.CharacterUtility, ScanType = ScanType.StaticAddress )]
|
[Signature(Sigs.CharacterUtility, ScanType = ScanType.StaticAddress)]
|
||||||
private readonly Structs.CharacterUtility** _characterUtilityAddress = null;
|
private readonly CharacterUtilityData** _characterUtilityAddress = null;
|
||||||
|
|
||||||
// Only required for migration anymore.
|
/// <summary> Only required for migration anymore. </summary>
|
||||||
public delegate void LoadResources( Structs.CharacterUtility* address );
|
public delegate void LoadResources(CharacterUtilityData* address);
|
||||||
|
|
||||||
[Signature( Sigs.LoadCharacterResources )]
|
[Signature(Sigs.LoadCharacterResources)]
|
||||||
public readonly LoadResources LoadCharacterResourcesFunc = null!;
|
public readonly LoadResources LoadCharacterResourcesFunc = null!;
|
||||||
|
|
||||||
public void LoadCharacterResources()
|
public void LoadCharacterResources()
|
||||||
=> LoadCharacterResourcesFunc.Invoke( Address );
|
=> LoadCharacterResourcesFunc.Invoke(Address);
|
||||||
|
|
||||||
public Structs.CharacterUtility* Address
|
public CharacterUtilityData* Address
|
||||||
=> *_characterUtilityAddress;
|
=> *_characterUtilityAddress;
|
||||||
|
|
||||||
public bool Ready { get; private set; }
|
public bool Ready { get; private set; }
|
||||||
public event Action LoadingFinished;
|
public event Action LoadingFinished;
|
||||||
private IntPtr _defaultTransparentResource;
|
public IntPtr DefaultTransparentResource { get; private set; }
|
||||||
private IntPtr _defaultDecalResource;
|
public IntPtr DefaultDecalResource { get; private set; }
|
||||||
|
|
||||||
// The relevant indices depend on which meta manipulations we allow for.
|
/// <summary>
|
||||||
// The defines are set in the project configuration.
|
/// The relevant indices depend on which meta manipulations we allow for.
|
||||||
public static readonly Structs.CharacterUtility.Index[]
|
/// The defines are set in the project configuration.
|
||||||
RelevantIndices = Enum.GetValues< Structs.CharacterUtility.Index >();
|
/// </summary>
|
||||||
|
public static readonly MetaIndex[]
|
||||||
|
RelevantIndices = Enum.GetValues<MetaIndex>();
|
||||||
|
|
||||||
public static readonly InternalIndex[] ReverseIndices
|
public static readonly InternalIndex[] ReverseIndices
|
||||||
= Enumerable.Range( 0, Structs.CharacterUtility.TotalNumResources )
|
= Enumerable.Range(0, CharacterUtilityData.TotalNumResources)
|
||||||
.Select( i => new InternalIndex( Array.IndexOf( RelevantIndices, ( Structs.CharacterUtility.Index )i ) ) )
|
.Select(i => new InternalIndex(Array.IndexOf(RelevantIndices, (MetaIndex)i)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
private readonly List[] _lists = Enumerable.Range( 0, RelevantIndices.Length )
|
private readonly List[] _lists = Enumerable.Range(0, RelevantIndices.Length)
|
||||||
.Select( idx => new List( new InternalIndex( idx ) ) )
|
.Select(idx => new List(new InternalIndex(idx)))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
public IReadOnlyList< List > Lists
|
public IReadOnlyList<List> Lists
|
||||||
=> _lists;
|
=> _lists;
|
||||||
|
|
||||||
public (IntPtr Address, int Size) DefaultResource( InternalIndex idx )
|
public (IntPtr Address, int Size) DefaultResource(InternalIndex idx)
|
||||||
=> _lists[ idx.Value ].DefaultResource;
|
=> _lists[idx.Value].DefaultResource;
|
||||||
|
|
||||||
private readonly Framework _framework;
|
private readonly Framework _framework;
|
||||||
|
|
||||||
public CharacterUtility(Framework framework)
|
public CharacterUtility(Framework framework)
|
||||||
{
|
{
|
||||||
SignatureHelper.Initialise( this );
|
SignatureHelper.Initialise(this);
|
||||||
_framework = framework;
|
_framework = framework;
|
||||||
LoadingFinished += () => Penumbra.Log.Debug( "Loading of CharacterUtility finished." );
|
LoadingFinished += () => Penumbra.Log.Debug("Loading of CharacterUtility finished.");
|
||||||
LoadDefaultResources( null! );
|
LoadDefaultResources(null!);
|
||||||
if( !Ready )
|
if (!Ready)
|
||||||
{
|
|
||||||
_framework.Update += LoadDefaultResources;
|
_framework.Update += LoadDefaultResources;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We store the default data of the resources so we can always restore them.
|
/// <summary> We store the default data of the resources so we can always restore them. </summary>
|
||||||
private void LoadDefaultResources( object _ )
|
private void LoadDefaultResources(object _)
|
||||||
{
|
{
|
||||||
if( Address == null )
|
if (Address == null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var anyMissing = false;
|
var anyMissing = false;
|
||||||
for( var i = 0; i < RelevantIndices.Length; ++i )
|
for (var i = 0; i < RelevantIndices.Length; ++i)
|
||||||
{
|
{
|
||||||
var list = _lists[ i ];
|
var list = _lists[i];
|
||||||
if( !list.Ready )
|
if (list.Ready)
|
||||||
{
|
continue;
|
||||||
var resource = Address->Resource( RelevantIndices[ i ] );
|
|
||||||
var (data, length) = resource->GetData();
|
var resource = Address->Resource(RelevantIndices[i]);
|
||||||
list.SetDefaultResource( data, length );
|
var (data, length) = resource->GetData();
|
||||||
anyMissing |= !_lists[ i ].Ready;
|
list.SetDefaultResource(data, length);
|
||||||
}
|
anyMissing |= !_lists[i].Ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _defaultTransparentResource == IntPtr.Zero )
|
if (DefaultTransparentResource == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
_defaultTransparentResource = ( IntPtr )Address->TransparentTexResource;
|
DefaultTransparentResource = (IntPtr)Address->TransparentTexResource;
|
||||||
anyMissing |= _defaultTransparentResource == IntPtr.Zero;
|
anyMissing |= DefaultTransparentResource == IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _defaultDecalResource == IntPtr.Zero )
|
if (DefaultDecalResource == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
_defaultDecalResource = ( IntPtr )Address->DecalTexResource;
|
DefaultDecalResource = (IntPtr)Address->DecalTexResource;
|
||||||
anyMissing |= _defaultDecalResource == IntPtr.Zero;
|
anyMissing |= DefaultDecalResource == IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !anyMissing )
|
if (anyMissing)
|
||||||
{
|
return;
|
||||||
Ready = true;
|
|
||||||
_framework.Update -= LoadDefaultResources;
|
Ready = true;
|
||||||
LoadingFinished.Invoke();
|
_framework.Update -= LoadDefaultResources;
|
||||||
}
|
LoadingFinished.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetResource( Structs.CharacterUtility.Index resourceIdx, IntPtr data, int length )
|
public void SetResource(MetaIndex resourceIdx, IntPtr data, int length)
|
||||||
{
|
{
|
||||||
var idx = ReverseIndices[ ( int )resourceIdx ];
|
var idx = ReverseIndices[(int)resourceIdx];
|
||||||
var list = _lists[ idx.Value ];
|
var list = _lists[idx.Value];
|
||||||
list.SetResource( data, length );
|
list.SetResource(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetResource( Structs.CharacterUtility.Index resourceIdx )
|
public void ResetResource(MetaIndex resourceIdx)
|
||||||
{
|
{
|
||||||
var idx = ReverseIndices[ ( int )resourceIdx ];
|
var idx = ReverseIndices[(int)resourceIdx];
|
||||||
var list = _lists[ idx.Value ];
|
var list = _lists[idx.Value];
|
||||||
list.ResetResource();
|
list.ResetResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List.MetaReverter TemporarilySetResource( Structs.CharacterUtility.Index resourceIdx, IntPtr data, int length )
|
public List.MetaReverter TemporarilySetResource(MetaIndex resourceIdx, IntPtr data, int length)
|
||||||
{
|
{
|
||||||
var idx = ReverseIndices[ ( int )resourceIdx ];
|
var idx = ReverseIndices[(int)resourceIdx];
|
||||||
var list = _lists[ idx.Value ];
|
var list = _lists[idx.Value];
|
||||||
return list.TemporarilySetResource( data, length );
|
return list.TemporarilySetResource(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List.MetaReverter TemporarilyResetResource( Structs.CharacterUtility.Index resourceIdx )
|
public List.MetaReverter TemporarilyResetResource(MetaIndex resourceIdx)
|
||||||
{
|
{
|
||||||
var idx = ReverseIndices[ ( int )resourceIdx ];
|
var idx = ReverseIndices[(int)resourceIdx];
|
||||||
var list = _lists[ idx.Value ];
|
var list = _lists[idx.Value];
|
||||||
return list.TemporarilyResetResource();
|
return list.TemporarilyResetResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all relevant resources to the default resource.
|
/// <summary> Return all relevant resources to the default resource. </summary>
|
||||||
public void ResetAll()
|
public void ResetAll()
|
||||||
{
|
{
|
||||||
foreach( var list in _lists )
|
foreach (var list in _lists)
|
||||||
{
|
|
||||||
list.Dispose();
|
list.Dispose();
|
||||||
}
|
|
||||||
|
|
||||||
Address->TransparentTexResource = ( Structs.TextureResourceHandle* )_defaultTransparentResource;
|
Address->TransparentTexResource = (TextureResourceHandle*)DefaultTransparentResource;
|
||||||
Address->DecalTexResource = ( Structs.TextureResourceHandle* )_defaultDecalResource;
|
Address->DecalTexResource = (TextureResourceHandle*)DefaultDecalResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
=> ResetAll();
|
||||||
ResetAll();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Penumbra.GameData.Enums;
|
|
||||||
|
|
||||||
namespace Penumbra.Interop.Structs;
|
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Explicit )]
|
|
||||||
public unsafe struct CharacterUtility
|
|
||||||
{
|
|
||||||
public enum Index : int
|
|
||||||
{
|
|
||||||
Eqp = 0,
|
|
||||||
Gmp = 2,
|
|
||||||
|
|
||||||
Eqdp0101 = 3,
|
|
||||||
Eqdp0201,
|
|
||||||
Eqdp0301,
|
|
||||||
Eqdp0401,
|
|
||||||
Eqdp0501,
|
|
||||||
Eqdp0601,
|
|
||||||
Eqdp0701,
|
|
||||||
Eqdp0801,
|
|
||||||
Eqdp0901,
|
|
||||||
Eqdp1001,
|
|
||||||
Eqdp1101,
|
|
||||||
Eqdp1201,
|
|
||||||
Eqdp1301,
|
|
||||||
Eqdp1401,
|
|
||||||
Eqdp1501,
|
|
||||||
|
|
||||||
//Eqdp1601, // TODO: female Hrothgar
|
|
||||||
Eqdp1701 = Eqdp1501 + 2,
|
|
||||||
Eqdp1801,
|
|
||||||
Eqdp0104,
|
|
||||||
Eqdp0204,
|
|
||||||
Eqdp0504,
|
|
||||||
Eqdp0604,
|
|
||||||
Eqdp0704,
|
|
||||||
Eqdp0804,
|
|
||||||
Eqdp1304,
|
|
||||||
Eqdp1404,
|
|
||||||
Eqdp9104,
|
|
||||||
Eqdp9204,
|
|
||||||
|
|
||||||
Eqdp0101Acc,
|
|
||||||
Eqdp0201Acc,
|
|
||||||
Eqdp0301Acc,
|
|
||||||
Eqdp0401Acc,
|
|
||||||
Eqdp0501Acc,
|
|
||||||
Eqdp0601Acc,
|
|
||||||
Eqdp0701Acc,
|
|
||||||
Eqdp0801Acc,
|
|
||||||
Eqdp0901Acc,
|
|
||||||
Eqdp1001Acc,
|
|
||||||
Eqdp1101Acc,
|
|
||||||
Eqdp1201Acc,
|
|
||||||
Eqdp1301Acc,
|
|
||||||
Eqdp1401Acc,
|
|
||||||
Eqdp1501Acc,
|
|
||||||
|
|
||||||
//Eqdp1601Acc, // TODO: female Hrothgar
|
|
||||||
Eqdp1701Acc = Eqdp1501Acc + 2,
|
|
||||||
Eqdp1801Acc,
|
|
||||||
Eqdp0104Acc,
|
|
||||||
Eqdp0204Acc,
|
|
||||||
Eqdp0504Acc,
|
|
||||||
Eqdp0604Acc,
|
|
||||||
Eqdp0704Acc,
|
|
||||||
Eqdp0804Acc,
|
|
||||||
Eqdp1304Acc,
|
|
||||||
Eqdp1404Acc,
|
|
||||||
Eqdp9104Acc,
|
|
||||||
Eqdp9204Acc,
|
|
||||||
|
|
||||||
HumanCmp = 64,
|
|
||||||
FaceEst,
|
|
||||||
HairEst,
|
|
||||||
HeadEst,
|
|
||||||
BodyEst,
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int IndexTransparentTex = 72;
|
|
||||||
public const int IndexDecalTex = 73;
|
|
||||||
|
|
||||||
public static readonly Index[] EqdpIndices = Enum.GetNames< Index >()
|
|
||||||
.Zip( Enum.GetValues< Index >() )
|
|
||||||
.Where( n => n.First.StartsWith( "Eqdp" ) )
|
|
||||||
.Select( n => n.Second ).ToArray();
|
|
||||||
|
|
||||||
public const int TotalNumResources = 87;
|
|
||||||
|
|
||||||
public static Index EqdpIdx( GenderRace raceCode, bool accessory )
|
|
||||||
=> +( int )raceCode switch
|
|
||||||
{
|
|
||||||
0101 => accessory ? Index.Eqdp0101Acc : Index.Eqdp0101,
|
|
||||||
0201 => accessory ? Index.Eqdp0201Acc : Index.Eqdp0201,
|
|
||||||
0301 => accessory ? Index.Eqdp0301Acc : Index.Eqdp0301,
|
|
||||||
0401 => accessory ? Index.Eqdp0401Acc : Index.Eqdp0401,
|
|
||||||
0501 => accessory ? Index.Eqdp0501Acc : Index.Eqdp0501,
|
|
||||||
0601 => accessory ? Index.Eqdp0601Acc : Index.Eqdp0601,
|
|
||||||
0701 => accessory ? Index.Eqdp0701Acc : Index.Eqdp0701,
|
|
||||||
0801 => accessory ? Index.Eqdp0801Acc : Index.Eqdp0801,
|
|
||||||
0901 => accessory ? Index.Eqdp0901Acc : Index.Eqdp0901,
|
|
||||||
1001 => accessory ? Index.Eqdp1001Acc : Index.Eqdp1001,
|
|
||||||
1101 => accessory ? Index.Eqdp1101Acc : Index.Eqdp1101,
|
|
||||||
1201 => accessory ? Index.Eqdp1201Acc : Index.Eqdp1201,
|
|
||||||
1301 => accessory ? Index.Eqdp1301Acc : Index.Eqdp1301,
|
|
||||||
1401 => accessory ? Index.Eqdp1401Acc : Index.Eqdp1401,
|
|
||||||
1501 => accessory ? Index.Eqdp1501Acc : Index.Eqdp1501,
|
|
||||||
//1601 => accessory ? RelevantIndex.Eqdp1601Acc : RelevantIndex.Eqdp1601, Female Hrothgar
|
|
||||||
1701 => accessory ? Index.Eqdp1701Acc : Index.Eqdp1701,
|
|
||||||
1801 => accessory ? Index.Eqdp1801Acc : Index.Eqdp1801,
|
|
||||||
0104 => accessory ? Index.Eqdp0104Acc : Index.Eqdp0104,
|
|
||||||
0204 => accessory ? Index.Eqdp0204Acc : Index.Eqdp0204,
|
|
||||||
0504 => accessory ? Index.Eqdp0504Acc : Index.Eqdp0504,
|
|
||||||
0604 => accessory ? Index.Eqdp0604Acc : Index.Eqdp0604,
|
|
||||||
0704 => accessory ? Index.Eqdp0704Acc : Index.Eqdp0704,
|
|
||||||
0804 => accessory ? Index.Eqdp0804Acc : Index.Eqdp0804,
|
|
||||||
1304 => accessory ? Index.Eqdp1304Acc : Index.Eqdp1304,
|
|
||||||
1404 => accessory ? Index.Eqdp1404Acc : Index.Eqdp1404,
|
|
||||||
9104 => accessory ? Index.Eqdp9104Acc : Index.Eqdp9104,
|
|
||||||
9204 => accessory ? Index.Eqdp9204Acc : Index.Eqdp9204,
|
|
||||||
_ => ( Index )( -1 ),
|
|
||||||
};
|
|
||||||
|
|
||||||
[FieldOffset( 0 )]
|
|
||||||
public void* VTable;
|
|
||||||
|
|
||||||
[FieldOffset( 8 )]
|
|
||||||
public fixed ulong Resources[TotalNumResources];
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.Eqp * 8 )]
|
|
||||||
public ResourceHandle* EqpResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.Gmp * 8 )]
|
|
||||||
public ResourceHandle* GmpResource;
|
|
||||||
|
|
||||||
public ResourceHandle* Resource( int idx )
|
|
||||||
=> ( ResourceHandle* )Resources[ idx ];
|
|
||||||
|
|
||||||
public ResourceHandle* Resource( Index idx )
|
|
||||||
=> Resource( ( int )idx );
|
|
||||||
|
|
||||||
public ResourceHandle* EqdpResource( GenderRace raceCode, bool accessory )
|
|
||||||
=> Resource( ( int )EqdpIdx( raceCode, accessory ) );
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.HumanCmp * 8 )]
|
|
||||||
public ResourceHandle* HumanCmpResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.FaceEst * 8 )]
|
|
||||||
public ResourceHandle* FaceEstResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.HairEst * 8 )]
|
|
||||||
public ResourceHandle* HairEstResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.BodyEst * 8 )]
|
|
||||||
public ResourceHandle* BodyEstResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + ( int )Index.HeadEst * 8 )]
|
|
||||||
public ResourceHandle* HeadEstResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + IndexTransparentTex * 8 )]
|
|
||||||
public TextureResourceHandle* TransparentTexResource;
|
|
||||||
|
|
||||||
[FieldOffset( 8 + IndexDecalTex * 8 )]
|
|
||||||
public TextureResourceHandle* DecalTexResource;
|
|
||||||
|
|
||||||
// not included resources have no known use case.
|
|
||||||
}
|
|
||||||
99
Penumbra/Interop/Structs/CharacterUtilityData.cs
Normal file
99
Penumbra/Interop/Structs/CharacterUtilityData.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
|
namespace Penumbra.Interop.Structs;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Explicit )]
|
||||||
|
public unsafe struct CharacterUtilityData
|
||||||
|
{
|
||||||
|
public const int IndexTransparentTex = 72;
|
||||||
|
public const int IndexDecalTex = 73;
|
||||||
|
|
||||||
|
public static readonly MetaIndex[] EqdpIndices = Enum.GetNames< MetaIndex >()
|
||||||
|
.Zip( Enum.GetValues< MetaIndex >() )
|
||||||
|
.Where( n => n.First.StartsWith( "Eqdp" ) )
|
||||||
|
.Select( n => n.Second ).ToArray();
|
||||||
|
|
||||||
|
public const int TotalNumResources = 87;
|
||||||
|
|
||||||
|
/// <summary> Obtain the index for the eqdp file corresponding to the given race code and accessory. </summary>
|
||||||
|
public static MetaIndex EqdpIdx( GenderRace raceCode, bool accessory )
|
||||||
|
=> +( int )raceCode switch
|
||||||
|
{
|
||||||
|
0101 => accessory ? MetaIndex.Eqdp0101Acc : MetaIndex.Eqdp0101,
|
||||||
|
0201 => accessory ? MetaIndex.Eqdp0201Acc : MetaIndex.Eqdp0201,
|
||||||
|
0301 => accessory ? MetaIndex.Eqdp0301Acc : MetaIndex.Eqdp0301,
|
||||||
|
0401 => accessory ? MetaIndex.Eqdp0401Acc : MetaIndex.Eqdp0401,
|
||||||
|
0501 => accessory ? MetaIndex.Eqdp0501Acc : MetaIndex.Eqdp0501,
|
||||||
|
0601 => accessory ? MetaIndex.Eqdp0601Acc : MetaIndex.Eqdp0601,
|
||||||
|
0701 => accessory ? MetaIndex.Eqdp0701Acc : MetaIndex.Eqdp0701,
|
||||||
|
0801 => accessory ? MetaIndex.Eqdp0801Acc : MetaIndex.Eqdp0801,
|
||||||
|
0901 => accessory ? MetaIndex.Eqdp0901Acc : MetaIndex.Eqdp0901,
|
||||||
|
1001 => accessory ? MetaIndex.Eqdp1001Acc : MetaIndex.Eqdp1001,
|
||||||
|
1101 => accessory ? MetaIndex.Eqdp1101Acc : MetaIndex.Eqdp1101,
|
||||||
|
1201 => accessory ? MetaIndex.Eqdp1201Acc : MetaIndex.Eqdp1201,
|
||||||
|
1301 => accessory ? MetaIndex.Eqdp1301Acc : MetaIndex.Eqdp1301,
|
||||||
|
1401 => accessory ? MetaIndex.Eqdp1401Acc : MetaIndex.Eqdp1401,
|
||||||
|
1501 => accessory ? MetaIndex.Eqdp1501Acc : MetaIndex.Eqdp1501,
|
||||||
|
//1601 => accessory ? MetaIndex.Eqdp1601Acc : MetaIndex.Eqdp1601, Female Hrothgar
|
||||||
|
1701 => accessory ? MetaIndex.Eqdp1701Acc : MetaIndex.Eqdp1701,
|
||||||
|
1801 => accessory ? MetaIndex.Eqdp1801Acc : MetaIndex.Eqdp1801,
|
||||||
|
0104 => accessory ? MetaIndex.Eqdp0104Acc : MetaIndex.Eqdp0104,
|
||||||
|
0204 => accessory ? MetaIndex.Eqdp0204Acc : MetaIndex.Eqdp0204,
|
||||||
|
0504 => accessory ? MetaIndex.Eqdp0504Acc : MetaIndex.Eqdp0504,
|
||||||
|
0604 => accessory ? MetaIndex.Eqdp0604Acc : MetaIndex.Eqdp0604,
|
||||||
|
0704 => accessory ? MetaIndex.Eqdp0704Acc : MetaIndex.Eqdp0704,
|
||||||
|
0804 => accessory ? MetaIndex.Eqdp0804Acc : MetaIndex.Eqdp0804,
|
||||||
|
1304 => accessory ? MetaIndex.Eqdp1304Acc : MetaIndex.Eqdp1304,
|
||||||
|
1404 => accessory ? MetaIndex.Eqdp1404Acc : MetaIndex.Eqdp1404,
|
||||||
|
9104 => accessory ? MetaIndex.Eqdp9104Acc : MetaIndex.Eqdp9104,
|
||||||
|
9204 => accessory ? MetaIndex.Eqdp9204Acc : MetaIndex.Eqdp9204,
|
||||||
|
_ => ( MetaIndex )( -1 ),
|
||||||
|
};
|
||||||
|
|
||||||
|
[FieldOffset( 0 )]
|
||||||
|
public void* VTable;
|
||||||
|
|
||||||
|
[FieldOffset( 8 )]
|
||||||
|
public fixed ulong Resources[TotalNumResources];
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.Eqp * 8 )]
|
||||||
|
public ResourceHandle* EqpResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.Gmp * 8 )]
|
||||||
|
public ResourceHandle* GmpResource;
|
||||||
|
|
||||||
|
public ResourceHandle* Resource( int idx )
|
||||||
|
=> ( ResourceHandle* )Resources[ idx ];
|
||||||
|
|
||||||
|
public ResourceHandle* Resource( MetaIndex idx )
|
||||||
|
=> Resource( ( int )idx );
|
||||||
|
|
||||||
|
public ResourceHandle* EqdpResource( GenderRace raceCode, bool accessory )
|
||||||
|
=> Resource( ( int )EqdpIdx( raceCode, accessory ) );
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.HumanCmp * 8 )]
|
||||||
|
public ResourceHandle* HumanCmpResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.FaceEst * 8 )]
|
||||||
|
public ResourceHandle* FaceEstResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.HairEst * 8 )]
|
||||||
|
public ResourceHandle* HairEstResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.BodyEst * 8 )]
|
||||||
|
public ResourceHandle* BodyEstResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + ( int )MetaIndex.HeadEst * 8 )]
|
||||||
|
public ResourceHandle* HeadEstResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + IndexTransparentTex * 8 )]
|
||||||
|
public TextureResourceHandle* TransparentTexResource;
|
||||||
|
|
||||||
|
[FieldOffset( 8 + IndexDecalTex * 8 )]
|
||||||
|
public TextureResourceHandle* DecalTexResource;
|
||||||
|
|
||||||
|
// not included resources have no known use case.
|
||||||
|
}
|
||||||
74
Penumbra/Interop/Structs/MetaIndex.cs
Normal file
74
Penumbra/Interop/Structs/MetaIndex.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
namespace Penumbra.Interop.Structs;
|
||||||
|
|
||||||
|
/// <summary> Indices for the different meta files contained in CharacterUtility. </summary>
|
||||||
|
public enum MetaIndex : int
|
||||||
|
{
|
||||||
|
Eqp = 0,
|
||||||
|
Gmp = 2,
|
||||||
|
|
||||||
|
Eqdp0101 = 3,
|
||||||
|
Eqdp0201,
|
||||||
|
Eqdp0301,
|
||||||
|
Eqdp0401,
|
||||||
|
Eqdp0501,
|
||||||
|
Eqdp0601,
|
||||||
|
Eqdp0701,
|
||||||
|
Eqdp0801,
|
||||||
|
Eqdp0901,
|
||||||
|
Eqdp1001,
|
||||||
|
Eqdp1101,
|
||||||
|
Eqdp1201,
|
||||||
|
Eqdp1301,
|
||||||
|
Eqdp1401,
|
||||||
|
Eqdp1501,
|
||||||
|
|
||||||
|
//Eqdp1601, // TODO: female Hrothgar
|
||||||
|
Eqdp1701 = Eqdp1501 + 2,
|
||||||
|
Eqdp1801,
|
||||||
|
Eqdp0104,
|
||||||
|
Eqdp0204,
|
||||||
|
Eqdp0504,
|
||||||
|
Eqdp0604,
|
||||||
|
Eqdp0704,
|
||||||
|
Eqdp0804,
|
||||||
|
Eqdp1304,
|
||||||
|
Eqdp1404,
|
||||||
|
Eqdp9104,
|
||||||
|
Eqdp9204,
|
||||||
|
|
||||||
|
Eqdp0101Acc,
|
||||||
|
Eqdp0201Acc,
|
||||||
|
Eqdp0301Acc,
|
||||||
|
Eqdp0401Acc,
|
||||||
|
Eqdp0501Acc,
|
||||||
|
Eqdp0601Acc,
|
||||||
|
Eqdp0701Acc,
|
||||||
|
Eqdp0801Acc,
|
||||||
|
Eqdp0901Acc,
|
||||||
|
Eqdp1001Acc,
|
||||||
|
Eqdp1101Acc,
|
||||||
|
Eqdp1201Acc,
|
||||||
|
Eqdp1301Acc,
|
||||||
|
Eqdp1401Acc,
|
||||||
|
Eqdp1501Acc,
|
||||||
|
|
||||||
|
//Eqdp1601Acc, // TODO: female Hrothgar
|
||||||
|
Eqdp1701Acc = Eqdp1501Acc + 2,
|
||||||
|
Eqdp1801Acc,
|
||||||
|
Eqdp0104Acc,
|
||||||
|
Eqdp0204Acc,
|
||||||
|
Eqdp0504Acc,
|
||||||
|
Eqdp0604Acc,
|
||||||
|
Eqdp0704Acc,
|
||||||
|
Eqdp0804Acc,
|
||||||
|
Eqdp1304Acc,
|
||||||
|
Eqdp1404Acc,
|
||||||
|
Eqdp9104Acc,
|
||||||
|
Eqdp9204Acc,
|
||||||
|
|
||||||
|
HumanCmp = 64,
|
||||||
|
FaceEst,
|
||||||
|
HairEst,
|
||||||
|
HeadEst,
|
||||||
|
BodyEst,
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue