mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +01:00
181 lines
8.4 KiB
C#
181 lines
8.4 KiB
C#
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;
|
|
|
|
public static class WriteExtensions
|
|
{
|
|
private static unsafe void Write(IntPtr characterPtr, EquipSlot slot, SetId? id, WeaponType? type, ushort? variant, StainId? stain)
|
|
{
|
|
void WriteWeapon(WeaponModelId* address)
|
|
{
|
|
if (id.HasValue)
|
|
address->Id = (ushort)id.Value;
|
|
|
|
if (type.HasValue)
|
|
address->Type = (ushort)type.Value;
|
|
|
|
if (variant.HasValue)
|
|
address->Variant = variant.Value;
|
|
|
|
if (*(ushort*)address == 0)
|
|
address->Stain = 0;
|
|
else if (stain.HasValue)
|
|
address->Stain = (byte)stain.Value;
|
|
}
|
|
|
|
void WriteEquip(EquipmentModelId* address)
|
|
{
|
|
if (id.HasValue)
|
|
address->Id = (ushort)id.Value;
|
|
|
|
if (variant < byte.MaxValue)
|
|
address->Variant = (byte)variant.Value;
|
|
|
|
if (stain.HasValue)
|
|
address->Stain = (byte)stain.Value;
|
|
}
|
|
|
|
var ptr = (Character*)characterPtr;
|
|
switch (slot)
|
|
{
|
|
case EquipSlot.MainHand:
|
|
WriteWeapon(&ptr->DrawData.MainHandModel);
|
|
break;
|
|
case EquipSlot.OffHand:
|
|
WriteWeapon(&ptr->DrawData.OffHandModel);
|
|
break;
|
|
case EquipSlot.Head:
|
|
WriteEquip(&ptr->DrawData.Head);
|
|
break;
|
|
case EquipSlot.Body:
|
|
WriteEquip(&ptr->DrawData.Top);
|
|
break;
|
|
case EquipSlot.Hands:
|
|
WriteEquip(&ptr->DrawData.Arms);
|
|
break;
|
|
case EquipSlot.Legs:
|
|
WriteEquip(&ptr->DrawData.Legs);
|
|
break;
|
|
case EquipSlot.Feet:
|
|
WriteEquip(&ptr->DrawData.Feet);
|
|
break;
|
|
case EquipSlot.Ears:
|
|
WriteEquip(&ptr->DrawData.Ear);
|
|
break;
|
|
case EquipSlot.Neck:
|
|
WriteEquip(&ptr->DrawData.Neck);
|
|
break;
|
|
case EquipSlot.Wrists:
|
|
WriteEquip(&ptr->DrawData.Wrist);
|
|
break;
|
|
case EquipSlot.RFinger:
|
|
WriteEquip(&ptr->DrawData.RFinger);
|
|
break;
|
|
case EquipSlot.LFinger:
|
|
WriteEquip(&ptr->DrawData.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);
|
|
}
|
|
}
|