diff --git a/Penumbra.GameData b/Penumbra.GameData index 19923f8d..62f6acfb 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 19923f8d5649f11edcfae710c26d6273cf2e9d62 +Subproject commit 62f6acfb0f9e31b2907c02a270d723bfff18b390 diff --git a/Penumbra/Interop/Hooks/HookSettings.cs b/Penumbra/Interop/Hooks/HookSettings.cs index ed4eb669..9dd8d74f 100644 --- a/Penumbra/Interop/Hooks/HookSettings.cs +++ b/Penumbra/Interop/Hooks/HookSettings.cs @@ -4,11 +4,11 @@ public static class HookSettings { public const bool AllHooks = true; - public const bool ObjectHooks = false && AllHooks; + public const bool ObjectHooks = true && AllHooks; public const bool ReplacementHooks = true && AllHooks; - public const bool ResourceHooks = false && AllHooks; - public const bool MetaEntryHooks = false && AllHooks; - public const bool MetaParentHooks = false && AllHooks; + public const bool ResourceHooks = true && AllHooks; + public const bool MetaEntryHooks = true && AllHooks; + public const bool MetaParentHooks = true && AllHooks; public const bool VfxIdentificationHooks = false && AllHooks; - public const bool PostProcessingHooks = false && AllHooks; + public const bool PostProcessingHooks = true && AllHooks; } diff --git a/Penumbra/Interop/Hooks/Meta/GetEqpIndirect2.cs b/Penumbra/Interop/Hooks/Meta/GetEqpIndirect2.cs index 3767c4a2..e90674a8 100644 --- a/Penumbra/Interop/Hooks/Meta/GetEqpIndirect2.cs +++ b/Penumbra/Interop/Hooks/Meta/GetEqpIndirect2.cs @@ -1,6 +1,5 @@ using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using OtterGui.Services; -using Penumbra.Collections; using Penumbra.GameData; using Penumbra.Interop.PathResolving; diff --git a/Penumbra/Interop/Hooks/Meta/GmpHook.cs b/Penumbra/Interop/Hooks/Meta/GmpHook.cs index 329a8beb..12b221d9 100644 --- a/Penumbra/Interop/Hooks/Meta/GmpHook.cs +++ b/Penumbra/Interop/Hooks/Meta/GmpHook.cs @@ -1,3 +1,5 @@ +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; +using Lumina.Data.Parsing.Uld; using OtterGui.Services; using Penumbra.GameData; using Penumbra.Interop.PathResolving; @@ -8,12 +10,10 @@ namespace Penumbra.Interop.Hooks.Meta; public unsafe class GmpHook : FastHook, IDisposable { - public delegate nint Delegate(nint gmpResource, uint dividedHeadId); + public delegate ulong Delegate(CharacterUtility* characterUtility, ulong* outputEntry, ushort setId); private readonly MetaState _metaState; - private static readonly Finalizer StablePointer = new(); - public GmpHook(HookManager hooks, MetaState metaState) { _metaState = metaState; @@ -21,50 +21,21 @@ public unsafe class GmpHook : FastHook, IDisposable _metaState.Config.ModsEnabled += Toggle; } - /// - /// This function returns a pointer to the correct block in the GMP file, if it exists - cf. . - /// To work around this, we just have a single stable ulong accessible and offset the pointer to this by the required distance, - /// which is defined by the modulo of the original ID and the block size, if we return our own custom gmp entry. - /// - private nint Detour(nint gmpResource, uint dividedHeadId) + private ulong Detour(CharacterUtility* characterUtility, ulong* outputEntry, ushort setId) { - nint ret; + ulong ret; if (_metaState.GmpCollection.TryPeek(out var collection) && collection.Collection is { Valid: true, ModCollection.MetaCache: { } cache } && cache.Gmp.TryGetValue(new GmpIdentifier(collection.Id), out var entry)) - { - if (entry.Entry.Enabled) - { - *StablePointer.Pointer = entry.Entry.Value; - // This function already gets the original ID divided by the block size, so we can compute the modulo with a single multiplication and addition. - // We then go backwards from our pointer because this gets added by the calling functions. - ret = (nint)(StablePointer.Pointer - (collection.Id.Id - dividedHeadId * ExpandedEqpGmpBase.BlockSize)); - } - else - { - ret = nint.Zero; - } - } + ret = (*outputEntry) = entry.Entry.Enabled ? entry.Entry.Value : 0ul; else - { - ret = Task.Result.Original(gmpResource, dividedHeadId); - } + ret = Task.Result.Original(characterUtility, outputEntry, setId); - Penumbra.Log.Excessive($"[GetGmpFlags] Invoked on 0x{gmpResource:X} with {dividedHeadId}, returned {ret:X10}."); + Penumbra.Log.Excessive( + $"[GetGmpFlags] Invoked on 0x{(ulong)characterUtility:X} for {setId} with 0x{(ulong)outputEntry:X} (={*outputEntry:X}), returned {ret:X10}."); return ret; } - /// Allocate and clean up our single stable ulong pointer. - private class Finalizer - { - public readonly ulong* Pointer = (ulong*)Marshal.AllocHGlobal(8); - - ~Finalizer() - { - Marshal.FreeHGlobal((nint)Pointer); - } - } - public void Dispose() => _metaState.Config.ModsEnabled -= Toggle; } diff --git a/Penumbra/Interop/Hooks/Meta/ModelLoadComplete.cs b/Penumbra/Interop/Hooks/Meta/ModelLoadComplete.cs index 79e7f6a6..c1803745 100644 --- a/Penumbra/Interop/Hooks/Meta/ModelLoadComplete.cs +++ b/Penumbra/Interop/Hooks/Meta/ModelLoadComplete.cs @@ -13,7 +13,7 @@ public sealed unsafe class ModelLoadComplete : FastHook("Model Load Complete", vtables.HumanVTable[58], Detour, HookSettings.MetaParentHooks); + Task = hooks.CreateHook("Model Load Complete", vtables.HumanVTable[59], Detour, HookSettings.MetaParentHooks); } public delegate void Delegate(DrawObject* drawObject); diff --git a/Penumbra/Interop/Hooks/Meta/RspBustHook.cs b/Penumbra/Interop/Hooks/Meta/RspBustHook.cs index eb8a8a37..e08dc393 100644 --- a/Penumbra/Interop/Hooks/Meta/RspBustHook.cs +++ b/Penumbra/Interop/Hooks/Meta/RspBustHook.cs @@ -10,8 +10,7 @@ namespace Penumbra.Interop.Hooks.Meta; public unsafe class RspBustHook : FastHook, IDisposable { - public delegate float* Delegate(nint cmpResource, float* storage, Race race, byte gender, byte isSecondSubRace, byte bodyType, - byte bustSize); + public delegate float* Delegate(nint cmpResource, float* storage, SubRace race, byte gender, byte bodyType, byte bustSize); private readonly MetaState _metaState; private readonly MetaFileManager _metaFileManager; @@ -24,7 +23,7 @@ public unsafe class RspBustHook : FastHook, IDisposable _metaState.Config.ModsEnabled += Toggle; } - private float* Detour(nint cmpResource, float* storage, Race race, byte gender, byte isSecondSubRace, byte bodyType, byte bustSize) + private float* Detour(nint cmpResource, float* storage, SubRace clan, byte gender, byte bodyType, byte bustSize) { if (gender == 0) { @@ -38,7 +37,6 @@ public unsafe class RspBustHook : FastHook, IDisposable if (bodyType < 2 && _metaState.RspCollection.TryPeek(out var collection) && collection is { Valid: true, ModCollection.MetaCache: { } cache }) { var bustScale = bustSize / 100f; - var clan = (SubRace)(((int)race - 1) * 2 + 1 + isSecondSubRace); var ptr = CmpFile.GetDefaults(_metaFileManager, clan, RspAttribute.BustMinX); storage[0] = GetValue(0, RspAttribute.BustMinX, RspAttribute.BustMaxX); storage[1] = GetValue(1, RspAttribute.BustMinY, RspAttribute.BustMaxY); @@ -58,11 +56,11 @@ public unsafe class RspBustHook : FastHook, IDisposable } else { - ret = Task.Result.Original(cmpResource, storage, race, gender, isSecondSubRace, bodyType, bustSize); + ret = Task.Result.Original(cmpResource, storage, clan, gender, bodyType, bustSize); } Penumbra.Log.Excessive( - $"[GetRspBust] Invoked on 0x{cmpResource:X} with {race}, {(Gender)(gender + 1)}, {isSecondSubRace == 1}, {bodyType}, {bustSize}, returned {storage[0]}, {storage[1]}, {storage[2]}."); + $"[GetRspBust] Invoked on 0x{cmpResource:X} with {clan}, {(Gender)(gender + 1)}, {bodyType}, {bustSize}, returned {storage[0]}, {storage[1]}, {storage[2]}."); return ret; } diff --git a/Penumbra/Interop/Hooks/Meta/RspHeightHook.cs b/Penumbra/Interop/Hooks/Meta/RspHeightHook.cs index f8f9e51e..20e3c939 100644 --- a/Penumbra/Interop/Hooks/Meta/RspHeightHook.cs +++ b/Penumbra/Interop/Hooks/Meta/RspHeightHook.cs @@ -10,7 +10,7 @@ namespace Penumbra.Interop.Hooks.Meta; public class RspHeightHook : FastHook, IDisposable { - public delegate float Delegate(nint cmpResource, Race clan, byte gender, byte isSecondSubRace, byte bodyType, byte height); + public delegate float Delegate(nint cmpResource, SubRace clan, byte gender, byte bodyType, byte height); private readonly MetaState _metaState; private readonly MetaFileManager _metaFileManager; @@ -23,7 +23,7 @@ public class RspHeightHook : FastHook, IDisposable _metaState.Config.ModsEnabled += Toggle; } - private unsafe float Detour(nint cmpResource, Race race, byte gender, byte isSecondSubRace, byte bodyType, byte height) + private unsafe float Detour(nint cmpResource, SubRace clan, byte gender, byte bodyType, byte height) { float scale; if (bodyType < 2 @@ -36,7 +36,6 @@ public class RspHeightHook : FastHook, IDisposable if (height > 100) height = 0; - var clan = (SubRace)(((int)race - 1) * 2 + 1 + isSecondSubRace); var (minIdent, maxIdent) = gender == 0 ? (new RspIdentifier(clan, RspAttribute.MaleMinSize), new RspIdentifier(clan, RspAttribute.MaleMaxSize)) : (new RspIdentifier(clan, RspAttribute.FemaleMinSize), new RspIdentifier(clan, RspAttribute.FemaleMaxSize)); @@ -68,11 +67,11 @@ public class RspHeightHook : FastHook, IDisposable } else { - scale = Task.Result.Original(cmpResource, race, gender, isSecondSubRace, bodyType, height); + scale = Task.Result.Original(cmpResource, clan, gender, bodyType, height); } Penumbra.Log.Excessive( - $"[GetRspHeight] Invoked on 0x{cmpResource:X} with {race}, {(Gender)(gender + 1)}, {isSecondSubRace == 1}, {bodyType}, {height}, returned {scale}."); + $"[GetRspHeight] Invoked on 0x{cmpResource:X} with {clan}, {(Gender)(gender + 1)}, {bodyType}, {height}, returned {scale}."); return scale; } diff --git a/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs b/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs index 663209ae..d81043c8 100644 --- a/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs +++ b/Penumbra/Interop/Hooks/Objects/CopyCharacter.cs @@ -9,7 +9,7 @@ public sealed unsafe class CopyCharacter : EventWrapperPtr + /// CutsceneService = 0, } @@ -38,8 +38,7 @@ public sealed unsafe class CopyCharacter : EventWrapperPtrOwnerObject; Penumbra.Log.Verbose($"[{Name}] Triggered with target: 0x{(nint)target:X}, source : 0x{(nint)source:X} unk: {unk}."); Invoke(character, source); return _task.Result.Original(target, source, unk); diff --git a/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs b/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs index 56b3d853..f00a9984 100644 --- a/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs +++ b/Penumbra/Interop/Hooks/Objects/CreateCharacterBase.cs @@ -10,7 +10,7 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr + /// MetaState = 0, } @@ -64,10 +64,10 @@ public sealed unsafe class CreateCharacterBase : EventWrapperPtr + /// DrawObjectState = 0, - /// + /// MetaState = 0, } } diff --git a/Penumbra/Interop/Structs/CharacterUtilityData.cs b/Penumbra/Interop/Structs/CharacterUtilityData.cs index 22150cc1..d33da477 100644 --- a/Penumbra/Interop/Structs/CharacterUtilityData.cs +++ b/Penumbra/Interop/Structs/CharacterUtilityData.cs @@ -6,16 +6,16 @@ namespace Penumbra.Interop.Structs; public unsafe struct CharacterUtilityData { public const int IndexHumanPbd = 63; - public const int IndexTransparentTex = 72; - public const int IndexDecalTex = 73; - public const int IndexSkinShpk = 76; + public const int IndexTransparentTex = 79; + public const int IndexDecalTex = 80; + public const int IndexSkinShpk = 83; public static readonly MetaIndex[] EqdpIndices = Enum.GetNames() .Zip(Enum.GetValues()) .Where(n => n.First.StartsWith("Eqdp")) .Select(n => n.Second).ToArray(); - public const int TotalNumResources = 87; + public const int TotalNumResources = 89; /// Obtain the index for the eqdp file corresponding to the given race code and accessory. public static MetaIndex EqdpIdx(GenderRace raceCode, bool accessory) @@ -36,7 +36,7 @@ public unsafe struct CharacterUtilityData 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 + 1601 => accessory ? MetaIndex.Eqdp1601Acc : MetaIndex.Eqdp1601, 1701 => accessory ? MetaIndex.Eqdp1701Acc : MetaIndex.Eqdp1701, 1801 => accessory ? MetaIndex.Eqdp1801Acc : MetaIndex.Eqdp1801, 0104 => accessory ? MetaIndex.Eqdp0104Acc : MetaIndex.Eqdp0104, diff --git a/Penumbra/Interop/Structs/MetaIndex.cs b/Penumbra/Interop/Structs/MetaIndex.cs index 65302264..2ec5fce4 100644 --- a/Penumbra/Interop/Structs/MetaIndex.cs +++ b/Penumbra/Interop/Structs/MetaIndex.cs @@ -4,6 +4,7 @@ namespace Penumbra.Interop.Structs; public enum MetaIndex : int { Eqp = 0, + Evp = 1, Gmp = 2, Eqdp0101 = 3, @@ -21,9 +22,8 @@ public enum MetaIndex : int Eqdp1301, Eqdp1401, Eqdp1501, - - //Eqdp1601, // TODO: female Hrothgar - Eqdp1701 = Eqdp1501 + 2, + Eqdp1601, + Eqdp1701, Eqdp1801, Eqdp0104, Eqdp0204, @@ -51,9 +51,8 @@ public enum MetaIndex : int Eqdp1301Acc, Eqdp1401Acc, Eqdp1501Acc, - - //Eqdp1601Acc, // TODO: female Hrothgar - Eqdp1701Acc = Eqdp1501Acc + 2, + Eqdp1601Acc, + Eqdp1701Acc, Eqdp1801Acc, Eqdp0104Acc, Eqdp0204Acc, @@ -66,7 +65,7 @@ public enum MetaIndex : int Eqdp9104Acc, Eqdp9204Acc, - HumanCmp = 64, + HumanCmp = 71, FaceEst, HairEst, HeadEst,