From 7a768afa005861a6f5d42ade76d285d43252c622 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Mon, 20 Jan 2025 08:46:38 +0100 Subject: [PATCH] Add DrawDataContainer.LoadGearsetData (#1277) * Add DrawDataContainer.LoadGearsetData Co-authored-by: Cordelia * Add RaptureGearsetModule.EquipGearsetInternal Co-authored-by: Cordelia * Fix namespace --------- Co-authored-by: Cordelia --- .../Client/Game/Character/DrawDataContainer.cs | 12 ++++++++++++ .../Game/Network/PacketPlayerGearsetData.cs | 17 +++++++++++++++++ .../Client/UI/Misc/RaptureGearsetModule.cs | 3 +++ ida/data.yml | 2 ++ 4 files changed, 34 insertions(+) create mode 100644 FFXIVClientStructs/FFXIV/Client/Game/Network/PacketPlayerGearsetData.cs diff --git a/FFXIVClientStructs/FFXIV/Client/Game/Character/DrawDataContainer.cs b/FFXIVClientStructs/FFXIV/Client/Game/Character/DrawDataContainer.cs index 8ecc09b5c..2b5696eb0 100644 --- a/FFXIVClientStructs/FFXIV/Client/Game/Character/DrawDataContainer.cs +++ b/FFXIVClientStructs/FFXIV/Client/Game/Character/DrawDataContainer.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using FFXIVClientStructs.FFXIV.Client.Game.Network; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.UI.Agent; @@ -70,6 +71,9 @@ public ref EquipmentModelId Equipment(EquipmentSlot slot) { [MemberFunction("E8 ?? ?? ?? ?? EB 50 44 8B 03")] public partial void SetGlasses(int index, ushort id); + [MemberFunction("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 44 0F B6 B9")] + public partial void LoadGearsetData(PacketPlayerGearsetData* gearsetData); + public enum EquipmentSlot : uint { Head = 0, Body = 1, @@ -200,3 +204,11 @@ public struct EquipmentModelId { [FieldOffset(0), CExportIgnore] public ulong Value; } + +[StructLayout(LayoutKind.Explicit, Size = 4)] +public struct LegacyEquipmentModelId { + [FieldOffset(0)] public ushort Id; + [FieldOffset(2)] public byte Variant; + [FieldOffset(3)] public byte Stain; + // Second Stain id is stored separately +} diff --git a/FFXIVClientStructs/FFXIV/Client/Game/Network/PacketPlayerGearsetData.cs b/FFXIVClientStructs/FFXIV/Client/Game/Network/PacketPlayerGearsetData.cs new file mode 100644 index 000000000..fff98bed3 --- /dev/null +++ b/FFXIVClientStructs/FFXIV/Client/Game/Network/PacketPlayerGearsetData.cs @@ -0,0 +1,17 @@ +using FFXIVClientStructs.FFXIV.Client.Game.Character; + +namespace FFXIVClientStructs.FFXIV.Client.Game.Network; + +[GenerateInterop] +[StructLayout(LayoutKind.Explicit, Size = 0x46)] +public partial struct PacketPlayerGearsetData { + // Stores the weapon data. Includes both dyes in the data. + [FieldOffset(0x00)] public WeaponModelId MainhandWeaponData; + [FieldOffset(0x08)] public WeaponModelId OffhandWeaponData; + [FieldOffset(0x10)] public byte CrestBitField; // A Bitfield:: ShieldCrest == 1, HeadCrest == 2, Chest Crest == 4 + [FieldOffset(0x11)] public byte JobId; // Job ID associated with the gearset change. + [FieldOffset(0x12)] private byte Unk12; // Flicks from 0 to 128 (anywhere inbetween), have yet to associate what it is linked to. Remains the same when flicking between gearsets of the same job. + [FieldOffset(0x13)] private byte Unk13; // I have never seen this be anything other than 0. + [FieldOffset(0x14), FixedSizeArray] internal FixedSizeArray10 _equipmentModelIds; + [FieldOffset(0x3C), FixedSizeArray] internal FixedSizeArray10 _equipmentSecondaryDyes; +} diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Misc/RaptureGearsetModule.cs b/FFXIVClientStructs/FFXIV/Client/UI/Misc/RaptureGearsetModule.cs index 4b6f8253e..ee5f225c0 100644 --- a/FFXIVClientStructs/FFXIV/Client/UI/Misc/RaptureGearsetModule.cs +++ b/FFXIVClientStructs/FFXIV/Client/UI/Misc/RaptureGearsetModule.cs @@ -64,6 +64,9 @@ public unsafe partial struct RaptureGearsetModule { [MemberFunction("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 41 0F B6 F0 48 8D 0D")] public partial int EquipGearset(int gearsetId, byte glamourPlateId = 0); + [MemberFunction("40 55 53 56 57 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 4C 63 FA")] + public partial int EquipGearsetInternal(int gearsetId, byte glamourPlateId = 0); + /// /// Save the player's current inventory to a new gearset at the next possible ID. /// diff --git a/ida/data.yml b/ida/data.yml index 33432fa6c..ef1a85b38 100644 --- a/ida/data.yml +++ b/ida/data.yml @@ -353,6 +353,7 @@ functions: 0x140A03370: ProcessPacketPlayerStateFlags 0x140A03390: ProcessPacketPlayerClassInfo 0x140A034C0: ProcessPacketPlayerBlueMageActions + 0x140A034E0: ProcessPacketPlayerGearsetData 0x140A03520: ProcessPacketUpdateRecastTimes 0x140A03570: ProcessPacketActorSetPos 0x140A03590: ProcessPacketActorMove @@ -8394,6 +8395,7 @@ classes: base: Client::Game::Character::ContainerInterface funcs: # 0x1413171F0: ctor # inlined at 0x1408CF5D2 + 0x140842F50: LoadGearsetData 0x140843E20: LoadWeapon 0x140844AE0: HideWeapons 0x1408454C0: LoadEquipment