Glamourer/Glamourer.GameData/ActorEquipExtensions.cs
2021-07-30 17:23:15 +02:00

168 lines
8 KiB
C#

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);
}
}
}