From f97829ab7f5e6ed49f4a25a4add63ca4b54dce08 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 25 May 2023 01:54:09 +0200 Subject: [PATCH] Update for 6.4, 0.1.2.0 --- .../CharacterEquipExtensions.cs | 322 +++++++++--------- .../Customization/CharacterCustomization.cs | 26 +- Glamourer/Glamourer.csproj | 4 +- Glamourer/Glamourer.json | 2 +- Glamourer/Offsets.cs | 14 +- Penumbra.PlayerWatch/CharacterEquipment.cs | 11 +- .../Penumbra.PlayerWatch.csproj | 4 + repo.json | 4 +- 8 files changed, 187 insertions(+), 200 deletions(-) diff --git a/Glamourer.GameData/CharacterEquipExtensions.cs b/Glamourer.GameData/CharacterEquipExtensions.cs index 32caa48..e53fa1d 100644 --- a/Glamourer.GameData/CharacterEquipExtensions.cs +++ b/Glamourer.GameData/CharacterEquipExtensions.cs @@ -1,181 +1,183 @@ using System; using System.ComponentModel; +using System.Runtime.InteropServices; +using FFXIVClientStructs.FFXIV.Client.Game.Character; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.PlayerWatch; -namespace Glamourer +namespace Glamourer; + +public static class WriteExtensions { - public static class WriteExtensions + private static unsafe void Write(IntPtr characterPtr, EquipSlot slot, SetId? id, WeaponType? type, ushort? variant, StainId? stain) { - private static unsafe void Write(IntPtr characterPtr, EquipSlot slot, SetId? id, WeaponType? type, ushort? variant, StainId? stain) + void WriteWeapon(int offset) { - void WriteWeapon(int offset) - { - var address = (byte*) characterPtr + offset; - if (id.HasValue) - *(ushort*) address = (ushort) id.Value; + var address = (byte*)characterPtr + offset; + if (id.HasValue) + *(ushort*)address = (ushort)id.Value; - if (type.HasValue) - *(ushort*) (address + 2) = (ushort) type.Value; + if (type.HasValue) + *(ushort*)(address + 2) = (ushort)type.Value; - if (variant.HasValue) - *(ushort*) (address + 4) = variant.Value; + if (variant.HasValue) + *(ushort*)(address + 4) = variant.Value; - if (*(ushort*) address == 0) - *(address + 6) = 0; - else if (stain.HasValue) - *(address + 6) = (byte) stain.Value; - } - - void WriteEquip(int offset) - { - var address = (byte*) characterPtr + offset; - if (id.HasValue) - *(ushort*) address = (ushort) id.Value; - - if (variant < byte.MaxValue) - *(address + 2) = (byte) variant.Value; - - if (stain.HasValue) - *(address + 3) = (byte) stain.Value; - } - - switch (slot) - { - case EquipSlot.MainHand: - WriteWeapon(CharacterEquipment.MainWeaponOffset); - break; - case EquipSlot.OffHand: - WriteWeapon(CharacterEquipment.OffWeaponOffset); - break; - case EquipSlot.Head: - WriteEquip(CharacterEquipment.EquipmentOffset); - break; - case EquipSlot.Body: - WriteEquip(CharacterEquipment.EquipmentOffset + 4); - break; - case EquipSlot.Hands: - WriteEquip(CharacterEquipment.EquipmentOffset + 8); - break; - case EquipSlot.Legs: - WriteEquip(CharacterEquipment.EquipmentOffset + 12); - break; - case EquipSlot.Feet: - WriteEquip(CharacterEquipment.EquipmentOffset + 16); - break; - case EquipSlot.Ears: - WriteEquip(CharacterEquipment.EquipmentOffset + 20); - break; - case EquipSlot.Neck: - WriteEquip(CharacterEquipment.EquipmentOffset + 24); - break; - case EquipSlot.Wrists: - WriteEquip(CharacterEquipment.EquipmentOffset + 28); - break; - case EquipSlot.RFinger: - WriteEquip(CharacterEquipment.EquipmentOffset + 32); - break; - case EquipSlot.LFinger: - WriteEquip(CharacterEquipment.EquipmentOffset + 36); - break; - default: throw new InvalidEnumArgumentException(); - } + if (*(ushort*)address == 0) + *(address + 6) = 0; + else if (stain.HasValue) + *(address + 6) = (byte)stain.Value; } - public static void Write(this Stain stain, IntPtr characterPtr, EquipSlot slot) - => Write(characterPtr, slot, null, null, null, stain.RowIndex); - - public static void Write(this Item item, IntPtr characterAddress) + void WriteEquip(int offset) { - var (id, type, variant) = item.MainModel; - Write(characterAddress, item.EquippableTo, id, type, variant, null); - if (item.EquippableTo == EquipSlot.MainHand && item.HasSubModel) - { - var (subId, subType, subVariant) = item.SubModel; - Write(characterAddress, EquipSlot.OffHand, subId, subType, subVariant, null); - } + var address = (byte*)characterPtr + offset; + if (id.HasValue) + *(ushort*)address = (ushort)id.Value; + + if (variant < byte.MaxValue) + *(address + 2) = (byte)variant.Value; + + if (stain.HasValue) + *(address + 3) = (byte)stain.Value; } - public static void Write(this CharacterArmor armor, IntPtr characterAddress, EquipSlot slot) - => Write(characterAddress, slot, armor.Set, null, armor.Variant, armor.Stain); - - public static void Write(this CharacterWeapon weapon, IntPtr characterAddress, EquipSlot slot) - => Write(characterAddress, slot, weapon.Set, weapon.Type, weapon.Variant, weapon.Stain); - - public static unsafe void Write(this CharacterEquipment equip, IntPtr characterAddress) + var drawDataOffset = (int) Marshal.OffsetOf(nameof(Character.DrawData)); + switch (slot) { - if (equip.IsSet == 0) - return; - - Write(characterAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, equip.MainHand.Stain); - Write(characterAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, equip.OffHand.Stain); - - fixed (CharacterArmor* equipment = &equip.Head) - { - Buffer.MemoryCopy(equipment, (byte*) characterAddress + CharacterEquipment.EquipmentOffset, - CharacterEquipment.EquipmentSlots * sizeof(CharacterArmor), CharacterEquipment.EquipmentSlots * sizeof(CharacterArmor)); - } - } - - public static void Write(this CharacterEquipment equip, IntPtr characterAddress, CharacterEquipMask models, CharacterEquipMask stains) - { - if (models == CharacterEquipMask.All && stains == CharacterEquipMask.All) - { - equip.Write(characterAddress); - return; - } - - if (models.HasFlag(CharacterEquipMask.MainHand)) - Write(characterAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, null); - if (stains.HasFlag(CharacterEquipMask.MainHand)) - Write(characterAddress, EquipSlot.MainHand, null, null, null, equip.MainHand.Stain); - if (models.HasFlag(CharacterEquipMask.OffHand)) - Write(characterAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, null); - if (stains.HasFlag(CharacterEquipMask.OffHand)) - Write(characterAddress, EquipSlot.OffHand, null, null, null, equip.OffHand.Stain); - - if (models.HasFlag(CharacterEquipMask.Head)) - Write(characterAddress, EquipSlot.Head, equip.Head.Set, null, equip.Head.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Head)) - Write(characterAddress, EquipSlot.Head, null, null, null, equip.Head.Stain); - if (models.HasFlag(CharacterEquipMask.Body)) - Write(characterAddress, EquipSlot.Body, equip.Body.Set, null, equip.Body.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Body)) - Write(characterAddress, EquipSlot.Body, null, null, null, equip.Body.Stain); - if (models.HasFlag(CharacterEquipMask.Hands)) - Write(characterAddress, EquipSlot.Hands, equip.Hands.Set, null, equip.Hands.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Hands)) - Write(characterAddress, EquipSlot.Hands, null, null, null, equip.Hands.Stain); - if (models.HasFlag(CharacterEquipMask.Legs)) - Write(characterAddress, EquipSlot.Legs, equip.Legs.Set, null, equip.Legs.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Legs)) - Write(characterAddress, EquipSlot.Legs, null, null, null, equip.Legs.Stain); - if (models.HasFlag(CharacterEquipMask.Feet)) - Write(characterAddress, EquipSlot.Feet, equip.Feet.Set, null, equip.Feet.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Feet)) - Write(characterAddress, EquipSlot.Feet, null, null, null, equip.Feet.Stain); - - if (models.HasFlag(CharacterEquipMask.Ears)) - Write(characterAddress, EquipSlot.Ears, equip.Ears.Set, null, equip.Ears.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Ears)) - Write(characterAddress, EquipSlot.Ears, null, null, null, equip.Ears.Stain); - if (models.HasFlag(CharacterEquipMask.Neck)) - Write(characterAddress, EquipSlot.Neck, equip.Neck.Set, null, equip.Neck.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Neck)) - Write(characterAddress, EquipSlot.Neck, null, null, null, equip.Neck.Stain); - if (models.HasFlag(CharacterEquipMask.Wrists)) - Write(characterAddress, EquipSlot.Wrists, equip.Wrists.Set, null, equip.Wrists.Variant, null); - if (stains.HasFlag(CharacterEquipMask.Wrists)) - Write(characterAddress, EquipSlot.Wrists, null, null, null, equip.Wrists.Stain); - if (models.HasFlag(CharacterEquipMask.LFinger)) - Write(characterAddress, EquipSlot.LFinger, equip.LFinger.Set, null, equip.LFinger.Variant, null); - if (stains.HasFlag(CharacterEquipMask.LFinger)) - Write(characterAddress, EquipSlot.LFinger, null, null, null, equip.LFinger.Stain); - if (models.HasFlag(CharacterEquipMask.RFinger)) - Write(characterAddress, EquipSlot.RFinger, equip.RFinger.Set, null, equip.RFinger.Variant, null); - if (stains.HasFlag(CharacterEquipMask.RFinger)) - Write(characterAddress, EquipSlot.RFinger, null, null, null, equip.RFinger.Stain); + case EquipSlot.MainHand: + WriteWeapon(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.MainHandModel))); + break; + case EquipSlot.OffHand: + WriteWeapon(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.OffHandModel))); + break; + case EquipSlot.Head: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Head))); + break; + case EquipSlot.Body: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Top))); + break; + case EquipSlot.Hands: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Arms))); + break; + case EquipSlot.Legs: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Legs))); + break; + case EquipSlot.Feet: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Feet))); + break; + case EquipSlot.Ears: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Ear))); + break; + case EquipSlot.Neck: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Neck))); + break; + case EquipSlot.Wrists: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.Wrist))); + break; + case EquipSlot.RFinger: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.RFinger))); + break; + case EquipSlot.LFinger: + WriteEquip(drawDataOffset + (int)Marshal.OffsetOf(nameof(DrawDataContainer.LFinger))); + break; + default: throw new InvalidEnumArgumentException(); } } + + public static void Write(this Stain stain, IntPtr characterPtr, EquipSlot slot) + => Write(characterPtr, slot, null, null, null, stain.RowIndex); + + public static void Write(this Item item, IntPtr characterAddress) + { + var (id, type, variant) = item.MainModel; + Write(characterAddress, item.EquippableTo, id, type, variant, null); + if (item.EquippableTo == EquipSlot.MainHand && item.HasSubModel) + { + var (subId, subType, subVariant) = item.SubModel; + Write(characterAddress, EquipSlot.OffHand, subId, subType, subVariant, null); + } + } + + public static void Write(this CharacterArmor armor, IntPtr characterAddress, EquipSlot slot) + => Write(characterAddress, slot, armor.Set, null, armor.Variant, armor.Stain); + + public static void Write(this CharacterWeapon weapon, IntPtr characterAddress, EquipSlot slot) + => Write(characterAddress, slot, weapon.Set, weapon.Type, weapon.Variant, weapon.Stain); + + public static unsafe void Write(this CharacterEquipment equip, IntPtr characterAddress) + { + if (equip.IsSet == 0) + return; + + Write(characterAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, equip.MainHand.Stain); + Write(characterAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, equip.OffHand.Stain); + + fixed (CharacterArmor* equipment = &equip.Head) + { + Buffer.MemoryCopy(equipment, &((Character*)characterAddress)->DrawData.Head, + CharacterEquipment.EquipmentSlots * sizeof(CharacterArmor), CharacterEquipment.EquipmentSlots * sizeof(CharacterArmor)); + } + } + + public static void Write(this CharacterEquipment equip, IntPtr characterAddress, CharacterEquipMask models, CharacterEquipMask stains) + { + if (models == CharacterEquipMask.All && stains == CharacterEquipMask.All) + { + equip.Write(characterAddress); + return; + } + + if (models.HasFlag(CharacterEquipMask.MainHand)) + Write(characterAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, null); + if (stains.HasFlag(CharacterEquipMask.MainHand)) + Write(characterAddress, EquipSlot.MainHand, null, null, null, equip.MainHand.Stain); + if (models.HasFlag(CharacterEquipMask.OffHand)) + Write(characterAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, null); + if (stains.HasFlag(CharacterEquipMask.OffHand)) + Write(characterAddress, EquipSlot.OffHand, null, null, null, equip.OffHand.Stain); + + if (models.HasFlag(CharacterEquipMask.Head)) + Write(characterAddress, EquipSlot.Head, equip.Head.Set, null, equip.Head.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Head)) + Write(characterAddress, EquipSlot.Head, null, null, null, equip.Head.Stain); + if (models.HasFlag(CharacterEquipMask.Body)) + Write(characterAddress, EquipSlot.Body, equip.Body.Set, null, equip.Body.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Body)) + Write(characterAddress, EquipSlot.Body, null, null, null, equip.Body.Stain); + if (models.HasFlag(CharacterEquipMask.Hands)) + Write(characterAddress, EquipSlot.Hands, equip.Hands.Set, null, equip.Hands.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Hands)) + Write(characterAddress, EquipSlot.Hands, null, null, null, equip.Hands.Stain); + if (models.HasFlag(CharacterEquipMask.Legs)) + Write(characterAddress, EquipSlot.Legs, equip.Legs.Set, null, equip.Legs.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Legs)) + Write(characterAddress, EquipSlot.Legs, null, null, null, equip.Legs.Stain); + if (models.HasFlag(CharacterEquipMask.Feet)) + Write(characterAddress, EquipSlot.Feet, equip.Feet.Set, null, equip.Feet.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Feet)) + Write(characterAddress, EquipSlot.Feet, null, null, null, equip.Feet.Stain); + + if (models.HasFlag(CharacterEquipMask.Ears)) + Write(characterAddress, EquipSlot.Ears, equip.Ears.Set, null, equip.Ears.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Ears)) + Write(characterAddress, EquipSlot.Ears, null, null, null, equip.Ears.Stain); + if (models.HasFlag(CharacterEquipMask.Neck)) + Write(characterAddress, EquipSlot.Neck, equip.Neck.Set, null, equip.Neck.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Neck)) + Write(characterAddress, EquipSlot.Neck, null, null, null, equip.Neck.Stain); + if (models.HasFlag(CharacterEquipMask.Wrists)) + Write(characterAddress, EquipSlot.Wrists, equip.Wrists.Set, null, equip.Wrists.Variant, null); + if (stains.HasFlag(CharacterEquipMask.Wrists)) + Write(characterAddress, EquipSlot.Wrists, null, null, null, equip.Wrists.Stain); + if (models.HasFlag(CharacterEquipMask.LFinger)) + Write(characterAddress, EquipSlot.LFinger, equip.LFinger.Set, null, equip.LFinger.Variant, null); + if (stains.HasFlag(CharacterEquipMask.LFinger)) + Write(characterAddress, EquipSlot.LFinger, null, null, null, equip.LFinger.Stain); + if (models.HasFlag(CharacterEquipMask.RFinger)) + Write(characterAddress, EquipSlot.RFinger, equip.RFinger.Set, null, equip.RFinger.Variant, null); + if (stains.HasFlag(CharacterEquipMask.RFinger)) + Write(characterAddress, EquipSlot.RFinger, null, null, null, equip.RFinger.Stain); + } } diff --git a/Glamourer.GameData/Customization/CharacterCustomization.cs b/Glamourer.GameData/Customization/CharacterCustomization.cs index 79bee13..deda32b 100644 --- a/Glamourer.GameData/Customization/CharacterCustomization.cs +++ b/Glamourer.GameData/Customization/CharacterCustomization.cs @@ -1,29 +1,13 @@ using System; using System.Runtime.InteropServices; -using Dalamud.Game.ClientState.Objects.Types; using Penumbra.GameData.Enums; +using Character = Dalamud.Game.ClientState.Objects.Types.Character; namespace Glamourer.Customization { - public unsafe struct LazyCustomization - { - public CharacterCustomization* Address; - - public LazyCustomization(IntPtr characterPtr) - => Address = (CharacterCustomization*) (characterPtr + CharacterCustomization.CustomizationOffset); - - public ref CharacterCustomization Value - => ref *Address; - - public LazyCustomization(CharacterCustomization data) - => Address = &data; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CharacterCustomization { - public const int CustomizationOffset = 0x840; public const int CustomizationBytes = 26; public static CharacterCustomization Default = new() @@ -150,13 +134,13 @@ namespace Glamourer.Customization } } - public void Read(Character character) - => Read(character.Address + CustomizationOffset); + public unsafe void Read(Character character) + => Read((nint) ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)character.Address)->DrawData.CustomizeData.Data); public CharacterCustomization(Character character) : this() { - Read(character.Address + CustomizationOffset); + Read(character); } public byte this[CustomizationId id] @@ -282,7 +266,7 @@ namespace Glamourer.Customization { fixed (Race* ptr = &Race) { - Buffer.MemoryCopy(ptr, (byte*) characterAddress + CustomizationOffset, CustomizationBytes, CustomizationBytes); + Buffer.MemoryCopy(ptr, ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)characterAddress)->DrawData.CustomizeData.Data, CustomizationBytes, CustomizationBytes); } } diff --git a/Glamourer/Glamourer.csproj b/Glamourer/Glamourer.csproj index 9b6b642..869ba3e 100644 --- a/Glamourer/Glamourer.csproj +++ b/Glamourer/Glamourer.csproj @@ -5,8 +5,8 @@ x64 Glamourer Glamourer - 0.1.1.5 - 0.1.1.5 + 0.1.2.0 + 0.1.2.0 SoftOtter Glamourer Copyright © 2020 diff --git a/Glamourer/Glamourer.json b/Glamourer/Glamourer.json index 8a628d1..5a2232e 100644 --- a/Glamourer/Glamourer.json +++ b/Glamourer/Glamourer.json @@ -5,7 +5,7 @@ "Description": "Adds functionality to change and store appearance of players, customization and equip. Requires Penumbra to be installed and activated to work. Can also add preview options to the Changed Items tab for Penumbra.", "Tags": [ "Appearance", "Glamour", "Race", "Outfit", "Armor", "Clothes", "Skins", "Customization", "Design", "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "0.1.1.5", + "AssemblyVersion": "0.1.2.0", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 8, diff --git a/Glamourer/Offsets.cs b/Glamourer/Offsets.cs index 93b89eb..a86530f 100644 --- a/Glamourer/Offsets.cs +++ b/Glamourer/Offsets.cs @@ -4,18 +4,18 @@ public static class Offsets { public static class Character { - public const int Wetness = 0x1B1F; - public const int HatVisible = 0x85E; - public const int VisorToggled = 0x85F; - public const int WeaponHidden1 = 0x85F; - public const int WeaponHidden2 = 0x73C; - public const int Alpha = 0x1A18; + public const int Wetness = 0x1B3A; + public const int HatVisible = 0x876; + public const int VisorToggled = 0x877; + public const int WeaponHidden1 = 0x877; + public const int WeaponHidden2 = 0x754; + public const int Alpha = 0x1A4C; public static class Flags { public const byte IsHatHidden = 0x01; public const byte IsVisorToggled = 0x08; - public const byte IsWet = 0x40; + public const byte IsWet = 0x20; public const byte IsWeaponHidden1 = 0x01; public const byte IsWeaponHidden2 = 0x02; } diff --git a/Penumbra.PlayerWatch/CharacterEquipment.cs b/Penumbra.PlayerWatch/CharacterEquipment.cs index 79c7950..653ca72 100644 --- a/Penumbra.PlayerWatch/CharacterEquipment.cs +++ b/Penumbra.PlayerWatch/CharacterEquipment.cs @@ -10,9 +10,6 @@ namespace Penumbra.PlayerWatch; [StructLayout(LayoutKind.Sequential, Pack = 1)] public class CharacterEquipment { - public const int MainWeaponOffset = 0x6E0; - public const int OffWeaponOffset = 0x748; - public const int EquipmentOffset = 0x818; public const int EquipmentSlots = 10; public const int WeaponSlots = 2; @@ -58,16 +55,16 @@ public class CharacterEquipment private unsafe CharacterEquipment(IntPtr actorAddress) { IsSet = 1; - var actorPtr = (byte*)actorAddress.ToPointer(); + var actorPtr = (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actorAddress.ToPointer(); fixed (CharacterWeapon* main = &MainHand, off = &OffHand) { - Buffer.MemoryCopy(actorPtr + MainWeaponOffset, main, sizeof(CharacterWeapon), sizeof(CharacterWeapon)); - Buffer.MemoryCopy(actorPtr + OffWeaponOffset, off, sizeof(CharacterWeapon), sizeof(CharacterWeapon)); + Buffer.MemoryCopy(&actorPtr->DrawData.MainHandModel, main, sizeof(CharacterWeapon), sizeof(CharacterWeapon)); + Buffer.MemoryCopy(&actorPtr->DrawData.OffHandModel, off, sizeof(CharacterWeapon), sizeof(CharacterWeapon)); } fixed (CharacterArmor* equipment = &Head) { - Buffer.MemoryCopy(actorPtr + EquipmentOffset, equipment, EquipmentSlots * sizeof(CharacterArmor), + Buffer.MemoryCopy(&actorPtr->DrawData.Head, equipment, EquipmentSlots * sizeof(CharacterArmor), EquipmentSlots * sizeof(CharacterArmor)); } } diff --git a/Penumbra.PlayerWatch/Penumbra.PlayerWatch.csproj b/Penumbra.PlayerWatch/Penumbra.PlayerWatch.csproj index c4c3489..8ddfe15 100644 --- a/Penumbra.PlayerWatch/Penumbra.PlayerWatch.csproj +++ b/Penumbra.PlayerWatch/Penumbra.PlayerWatch.csproj @@ -38,6 +38,10 @@ $(DalamudLibPath)Dalamud.dll False + + $(DalamudLibPath)FFXIVClientStructs.dll + False + diff --git a/repo.json b/repo.json index a37e3db..102e0e2 100644 --- a/repo.json +++ b/repo.json @@ -6,8 +6,8 @@ "Description": "Adds functionality to change and store appearance of players, customization and equip. Requires Penumbra to be installed and activated to work. Can also add preview options to the Changed Items tab for Penumbra.", "Tags": [ "Appearance", "Glamour", "Race", "Outfit", "Armor", "Clothes", "Skins", "Customization", "Design", "Character" ], "InternalName": "Glamourer", - "AssemblyVersion": "0.1.1.5", - "TestingAssemblyVersion": "0.1.1.5", + "AssemblyVersion": "0.1.2.0", + "TestingAssemblyVersion": "0.1.2.0", "RepoUrl": "https://github.com/Ottermandias/Glamourer", "ApplicableVersion": "any", "DalamudApiLevel": 8,