mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2026-01-03 06:13:45 +01:00
Further updates, change Actor to other words in most places, change to Penumbra IPC-API.
This commit is contained in:
parent
d4a00dca0c
commit
ebcd1ea795
18 changed files with 358 additions and 347 deletions
|
|
@ -1,168 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer
|
||||
{
|
||||
public static class WriteExtensions
|
||||
{
|
||||
private static unsafe void Write(IntPtr actorPtr, EquipSlot slot, SetId? id, WeaponType? type, ushort? variant, StainId? stain)
|
||||
{
|
||||
void WriteWeapon(int offset)
|
||||
{
|
||||
var address = (byte*) actorPtr + offset;
|
||||
if (id.HasValue)
|
||||
*(ushort*) address = (ushort) id.Value;
|
||||
|
||||
if (type.HasValue)
|
||||
*(ushort*) (address + 2) = (ushort) type.Value;
|
||||
|
||||
if (variant.HasValue)
|
||||
*(ushort*) (address + 4) = variant.Value;
|
||||
|
||||
if (stain.HasValue)
|
||||
*(address + 6) = (byte) stain.Value;
|
||||
}
|
||||
|
||||
void WriteEquip(int offset)
|
||||
{
|
||||
var address = (byte*) actorPtr + 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(ActorEquipment.MainWeaponOffset);
|
||||
break;
|
||||
case EquipSlot.OffHand:
|
||||
WriteWeapon(ActorEquipment.OffWeaponOffset);
|
||||
break;
|
||||
case EquipSlot.Head:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset);
|
||||
break;
|
||||
case EquipSlot.Body:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 4);
|
||||
break;
|
||||
case EquipSlot.Hands:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 8);
|
||||
break;
|
||||
case EquipSlot.Legs:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 12);
|
||||
break;
|
||||
case EquipSlot.Feet:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 16);
|
||||
break;
|
||||
case EquipSlot.Ears:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 20);
|
||||
break;
|
||||
case EquipSlot.Neck:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 24);
|
||||
break;
|
||||
case EquipSlot.Wrists:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 28);
|
||||
break;
|
||||
case EquipSlot.RFinger:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 32);
|
||||
break;
|
||||
case EquipSlot.LFinger:
|
||||
WriteEquip(ActorEquipment.EquipmentOffset + 36);
|
||||
break;
|
||||
default: throw new InvalidEnumArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(this Stain stain, IntPtr actorPtr, EquipSlot slot)
|
||||
=> Write(actorPtr, slot, null, null, null, stain.RowIndex);
|
||||
|
||||
public static void Write(this Item item, IntPtr actorAddress)
|
||||
{
|
||||
var (id, type, variant) = item.MainModel;
|
||||
Write(actorAddress, item.EquippableTo, id, type, variant, null);
|
||||
if (item.EquippableTo == EquipSlot.MainHand && item.HasSubModel)
|
||||
{
|
||||
var (subId, subType, subVariant) = item.SubModel;
|
||||
Write(actorAddress, EquipSlot.OffHand, subId, subType, subVariant, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(this ActorArmor armor, IntPtr actorAddress, EquipSlot slot)
|
||||
=> Write(actorAddress, slot, armor.Set, null, armor.Variant, armor.Stain);
|
||||
|
||||
public static void Write(this ActorWeapon weapon, IntPtr actorAddress, EquipSlot slot)
|
||||
=> Write(actorAddress, slot, weapon.Set, weapon.Type, weapon.Variant, weapon.Stain);
|
||||
|
||||
public static unsafe void Write(this ActorEquipment equip, IntPtr actorAddress)
|
||||
{
|
||||
if (equip.IsSet == 0)
|
||||
return;
|
||||
|
||||
Write(actorAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, equip.MainHand.Stain);
|
||||
Write(actorAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, equip.OffHand.Stain);
|
||||
|
||||
fixed (ActorArmor* equipment = &equip.Head)
|
||||
{
|
||||
Buffer.MemoryCopy(equipment, (byte*) actorAddress + ActorEquipment.EquipmentOffset,
|
||||
ActorEquipment.EquipmentSlots * sizeof(ActorArmor), ActorEquipment.EquipmentSlots * sizeof(ActorArmor));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(this ActorEquipment equip, IntPtr actorAddress, ActorEquipMask models, ActorEquipMask stains)
|
||||
{
|
||||
if (models == ActorEquipMask.All && stains == ActorEquipMask.All)
|
||||
{
|
||||
equip.Write(actorAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
if (models.HasFlag(ActorEquipMask.MainHand))
|
||||
Write(actorAddress, EquipSlot.MainHand, equip.MainHand.Set, equip.MainHand.Type, equip.MainHand.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.MainHand))
|
||||
Write(actorAddress, EquipSlot.MainHand, null, null, null, equip.MainHand.Stain);
|
||||
if (models.HasFlag(ActorEquipMask.OffHand))
|
||||
Write(actorAddress, EquipSlot.OffHand, equip.OffHand.Set, equip.OffHand.Type, equip.OffHand.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.OffHand))
|
||||
Write(actorAddress, EquipSlot.OffHand, null, null, null, equip.OffHand.Stain);
|
||||
|
||||
if (models.HasFlag(ActorEquipMask.Head))
|
||||
Write(actorAddress, EquipSlot.Head, equip.Head.Set, null, equip.Head.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.Head))
|
||||
Write(actorAddress, EquipSlot.Head, null, null, null, equip.Head.Stain);
|
||||
if (models.HasFlag(ActorEquipMask.Body))
|
||||
Write(actorAddress, EquipSlot.Body, equip.Body.Set, null, equip.Body.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.Body))
|
||||
Write(actorAddress, EquipSlot.Body, null, null, null, equip.Body.Stain);
|
||||
if (models.HasFlag(ActorEquipMask.Hands))
|
||||
Write(actorAddress, EquipSlot.Hands, equip.Hands.Set, null, equip.Hands.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.Hands))
|
||||
Write(actorAddress, EquipSlot.Hands, null, null, null, equip.Hands.Stain);
|
||||
if (models.HasFlag(ActorEquipMask.Legs))
|
||||
Write(actorAddress, EquipSlot.Legs, equip.Legs.Set, null, equip.Legs.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.Legs))
|
||||
Write(actorAddress, EquipSlot.Legs, null, null, null, equip.Legs.Stain);
|
||||
if (models.HasFlag(ActorEquipMask.Feet))
|
||||
Write(actorAddress, EquipSlot.Feet, equip.Feet.Set, null, equip.Feet.Variant, null);
|
||||
if (stains.HasFlag(ActorEquipMask.Feet))
|
||||
Write(actorAddress, EquipSlot.Feet, null, null, null, equip.Feet.Stain);
|
||||
|
||||
if (models.HasFlag(ActorEquipMask.Ears))
|
||||
Write(actorAddress, EquipSlot.Ears, equip.Ears.Set, null, equip.Ears.Variant, null);
|
||||
if (models.HasFlag(ActorEquipMask.Neck))
|
||||
Write(actorAddress, EquipSlot.Neck, equip.Neck.Set, null, equip.Neck.Variant, null);
|
||||
if (models.HasFlag(ActorEquipMask.Wrists))
|
||||
Write(actorAddress, EquipSlot.Wrists, equip.Wrists.Set, null, equip.Wrists.Variant, null);
|
||||
if (models.HasFlag(ActorEquipMask.LFinger))
|
||||
Write(actorAddress, EquipSlot.LFinger, equip.LFinger.Set, null, equip.LFinger.Variant, null);
|
||||
if (models.HasFlag(ActorEquipMask.RFinger))
|
||||
Write(actorAddress, EquipSlot.RFinger, equip.RFinger.Set, null, equip.RFinger.Variant, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
168
Glamourer.GameData/CharacterEquipExtensions.cs
Normal file
168
Glamourer.GameData/CharacterEquipExtensions.cs
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
namespace Glamourer
|
||||
{
|
||||
public static class WriteExtensions
|
||||
{
|
||||
private static unsafe void Write(IntPtr characterPtr, EquipSlot slot, SetId? id, WeaponType? type, ushort? variant, StainId? stain)
|
||||
{
|
||||
void WriteWeapon(int offset)
|
||||
{
|
||||
var address = (byte*) characterPtr + offset;
|
||||
if (id.HasValue)
|
||||
*(ushort*) address = (ushort) id.Value;
|
||||
|
||||
if (type.HasValue)
|
||||
*(ushort*) (address + 2) = (ushort) type.Value;
|
||||
|
||||
if (variant.HasValue)
|
||||
*(ushort*) (address + 4) = variant.Value;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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, (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 (models.HasFlag(CharacterEquipMask.Neck))
|
||||
Write(characterAddress, EquipSlot.Neck, equip.Neck.Set, null, equip.Neck.Variant, null);
|
||||
if (models.HasFlag(CharacterEquipMask.Wrists))
|
||||
Write(characterAddress, EquipSlot.Wrists, equip.Wrists.Set, null, equip.Wrists.Variant, null);
|
||||
if (models.HasFlag(CharacterEquipMask.LFinger))
|
||||
Write(characterAddress, EquipSlot.LFinger, equip.LFinger.Set, null, equip.LFinger.Variant, null);
|
||||
if (models.HasFlag(CharacterEquipMask.RFinger))
|
||||
Write(characterAddress, EquipSlot.RFinger, equip.RFinger.Set, null, equip.RFinger.Variant, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ using System;
|
|||
namespace Glamourer
|
||||
{
|
||||
[Flags]
|
||||
public enum ActorEquipMask : ushort
|
||||
public enum CharacterEquipMask : ushort
|
||||
{
|
||||
None = 0,
|
||||
MainHand = 0b000000000001,
|
||||
|
|
@ -7,26 +7,26 @@ namespace Glamourer.Customization
|
|||
{
|
||||
public unsafe struct LazyCustomization
|
||||
{
|
||||
public ActorCustomization* Address;
|
||||
public CharacterCustomization* Address;
|
||||
|
||||
public LazyCustomization(IntPtr actorPtr)
|
||||
=> Address = (ActorCustomization*) (actorPtr + ActorCustomization.CustomizationOffset);
|
||||
public LazyCustomization(IntPtr characterPtr)
|
||||
=> Address = (CharacterCustomization*) (characterPtr + CharacterCustomization.CustomizationOffset);
|
||||
|
||||
public ref ActorCustomization Value
|
||||
public ref CharacterCustomization Value
|
||||
=> ref *Address;
|
||||
|
||||
public LazyCustomization(ActorCustomization data)
|
||||
public LazyCustomization(CharacterCustomization data)
|
||||
=> Address = &data;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct ActorCustomization
|
||||
public struct CharacterCustomization
|
||||
{
|
||||
public const int CustomizationOffset = 0x1898;
|
||||
public const int CustomizationBytes = 26;
|
||||
|
||||
public static ActorCustomization Default = new()
|
||||
public static CharacterCustomization Default = new()
|
||||
{
|
||||
Race = Race.Hyur,
|
||||
Gender = Gender.Male,
|
||||
|
|
@ -150,13 +150,13 @@ namespace Glamourer.Customization
|
|||
}
|
||||
}
|
||||
|
||||
public void Read(Character actor)
|
||||
=> Read(actor.Address + CustomizationOffset);
|
||||
public void Read(Character character)
|
||||
=> Read(character.Address + CustomizationOffset);
|
||||
|
||||
public ActorCustomization(Character actor)
|
||||
public CharacterCustomization(Character character)
|
||||
: this()
|
||||
{
|
||||
Read(actor.Address + CustomizationOffset);
|
||||
Read(character.Address + CustomizationOffset);
|
||||
}
|
||||
|
||||
public byte this[CustomizationId id]
|
||||
|
|
@ -278,11 +278,11 @@ namespace Glamourer.Customization
|
|||
}
|
||||
}
|
||||
|
||||
public unsafe void Write(IntPtr actorAddress)
|
||||
public unsafe void Write(IntPtr characterAddress)
|
||||
{
|
||||
fixed (Race* ptr = &Race)
|
||||
{
|
||||
Buffer.MemoryCopy(ptr, (byte*) actorAddress + CustomizationOffset, CustomizationBytes, CustomizationBytes);
|
||||
Buffer.MemoryCopy(ptr, (byte*) characterAddress + CustomizationOffset, CustomizationBytes, CustomizationBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Penumbra.GameData">
|
||||
<HintPath>..\..\Penumbra\Penumbra\bin\$(Configuration)\net472\Penumbra.GameData.dll</HintPath>
|
||||
<HintPath>..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.GameData.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue