Glamourer/Glamourer/Designs/ModelData.cs
Ottermandias 10631341cb .
2023-05-12 16:20:52 +02:00

489 lines
22 KiB
C#

using System;
using Glamourer.Customization;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using Penumbra.String.Functions;
namespace Glamourer.Designs;
[Flags]
public enum ModelFlags : ushort
{
HatVisible = 0x01,
WeaponVisible = 0x02,
VisorToggled = 0x04,
}
public struct ModelData
{
public readonly unsafe ModelData Clone()
{
var data = new ModelData(MainHand);
fixed (void* ptr = &this)
{
MemoryUtility.MemCpyUnchecked(&data, ptr, sizeof(ModelData));
}
return data;
}
public Customize Customize = Customize.Default;
public ModelFlags Flags = ModelFlags.HatVisible | ModelFlags.WeaponVisible;
public CharacterWeapon MainHand;
public CharacterWeapon OffHand = CharacterWeapon.Empty;
public uint ModelId = 0;
public CharacterArmor Head = CharacterArmor.Empty;
public CharacterArmor Body = CharacterArmor.Empty;
public CharacterArmor Hands = CharacterArmor.Empty;
public CharacterArmor Legs = CharacterArmor.Empty;
public CharacterArmor Feet = CharacterArmor.Empty;
public CharacterArmor Ears = CharacterArmor.Empty;
public CharacterArmor Neck = CharacterArmor.Empty;
public CharacterArmor Wrists = CharacterArmor.Empty;
public CharacterArmor RFinger = CharacterArmor.Empty;
public CharacterArmor LFinger = CharacterArmor.Empty;
public ModelData(CharacterWeapon mainHand)
=> MainHand = mainHand;
public CharacterArmor Armor(EquipSlot slot)
=> slot switch
{
EquipSlot.MainHand => MainHand.ToArmor(),
EquipSlot.OffHand => OffHand.ToArmor(),
EquipSlot.Head => Head,
EquipSlot.Body => Body,
EquipSlot.Hands => Hands,
EquipSlot.Legs => Legs,
EquipSlot.Feet => Feet,
EquipSlot.Ears => Ears,
EquipSlot.Neck => Neck,
EquipSlot.Wrists => Wrists,
EquipSlot.RFinger => RFinger,
EquipSlot.LFinger => LFinger,
_ => CharacterArmor.Empty,
};
public CharacterWeapon Piece(EquipSlot slot)
=> slot switch
{
EquipSlot.MainHand => MainHand,
EquipSlot.OffHand => OffHand,
EquipSlot.Head => Head.ToWeapon(),
EquipSlot.Body => Body.ToWeapon(),
EquipSlot.Hands => Hands.ToWeapon(),
EquipSlot.Legs => Legs.ToWeapon(),
EquipSlot.Feet => Feet.ToWeapon(),
EquipSlot.Ears => Ears.ToWeapon(),
EquipSlot.Neck => Neck.ToWeapon(),
EquipSlot.Wrists => Wrists.ToWeapon(),
EquipSlot.RFinger => RFinger.ToWeapon(),
EquipSlot.LFinger => LFinger.ToWeapon(),
_ => CharacterWeapon.Empty,
};
public bool SetPiece(EquipSlot slot, SetId model, byte variant, out CharacterWeapon ret)
{
var changes = false;
switch (slot)
{
case EquipSlot.MainHand:
changes |= SetIfDifferent(ref MainHand.Set, model);
changes |= SetIfDifferent(ref MainHand.Variant, variant);
ret = MainHand;
return changes;
case EquipSlot.OffHand:
changes |= SetIfDifferent(ref OffHand.Set, model);
changes |= SetIfDifferent(ref OffHand.Variant, variant);
ret = OffHand;
return changes;
case EquipSlot.Head:
changes |= SetIfDifferent(ref Head.Set, model);
changes |= SetIfDifferent(ref Head.Variant, variant);
ret = Head.ToWeapon();
return changes;
case EquipSlot.Body:
changes |= SetIfDifferent(ref Body.Set, model);
changes |= SetIfDifferent(ref Body.Variant, variant);
ret = Body.ToWeapon();
return changes;
case EquipSlot.Hands:
changes |= SetIfDifferent(ref Hands.Set, model);
changes |= SetIfDifferent(ref Hands.Variant, variant);
ret = Hands.ToWeapon();
return changes;
case EquipSlot.Legs:
changes |= SetIfDifferent(ref Legs.Set, model);
changes |= SetIfDifferent(ref Legs.Variant, variant);
ret = Legs.ToWeapon();
return changes;
case EquipSlot.Feet:
changes |= SetIfDifferent(ref Feet.Set, model);
changes |= SetIfDifferent(ref Feet.Variant, variant);
ret = Feet.ToWeapon();
return changes;
case EquipSlot.Ears:
changes |= SetIfDifferent(ref Ears.Set, model);
changes |= SetIfDifferent(ref Ears.Variant, variant);
ret = Ears.ToWeapon();
return changes;
case EquipSlot.Neck:
changes |= SetIfDifferent(ref Neck.Set, model);
changes |= SetIfDifferent(ref Neck.Variant, variant);
ret = Neck.ToWeapon();
return changes;
case EquipSlot.Wrists:
changes |= SetIfDifferent(ref Wrists.Set, model);
changes |= SetIfDifferent(ref Wrists.Variant, variant);
ret = Wrists.ToWeapon();
return changes;
case EquipSlot.RFinger:
changes |= SetIfDifferent(ref RFinger.Set, model);
changes |= SetIfDifferent(ref RFinger.Variant, variant);
ret = RFinger.ToWeapon();
return changes;
case EquipSlot.LFinger:
changes |= SetIfDifferent(ref LFinger.Set, model);
changes |= SetIfDifferent(ref LFinger.Variant, variant);
ret = LFinger.ToWeapon();
return changes;
default:
ret = CharacterWeapon.Empty;
return changes;
}
}
public bool SetPiece(EquipSlot slot, SetId model, WeaponType type, byte variant, out CharacterWeapon ret)
{
var changes = false;
switch (slot)
{
case EquipSlot.MainHand:
changes |= SetIfDifferent(ref MainHand.Set, model);
changes |= SetIfDifferent(ref MainHand.Type, type);
changes |= SetIfDifferent(ref MainHand.Variant, variant);
ret = MainHand;
return changes;
case EquipSlot.OffHand:
changes |= SetIfDifferent(ref OffHand.Set, model);
changes |= SetIfDifferent(ref OffHand.Type, type);
changes |= SetIfDifferent(ref OffHand.Variant, variant);
ret = OffHand;
return changes;
case EquipSlot.Head:
changes |= SetIfDifferent(ref Head.Set, model);
changes |= SetIfDifferent(ref Head.Variant, variant);
ret = Head.ToWeapon();
return changes;
case EquipSlot.Body:
changes |= SetIfDifferent(ref Body.Set, model);
changes |= SetIfDifferent(ref Body.Variant, variant);
ret = Body.ToWeapon();
return changes;
case EquipSlot.Hands:
changes |= SetIfDifferent(ref Hands.Set, model);
changes |= SetIfDifferent(ref Hands.Variant, variant);
ret = Hands.ToWeapon();
return changes;
case EquipSlot.Legs:
changes |= SetIfDifferent(ref Legs.Set, model);
changes |= SetIfDifferent(ref Legs.Variant, variant);
ret = Legs.ToWeapon();
return changes;
case EquipSlot.Feet:
changes |= SetIfDifferent(ref Feet.Set, model);
changes |= SetIfDifferent(ref Feet.Variant, variant);
ret = Feet.ToWeapon();
return changes;
case EquipSlot.Ears:
changes |= SetIfDifferent(ref Ears.Set, model);
changes |= SetIfDifferent(ref Ears.Variant, variant);
ret = Ears.ToWeapon();
return changes;
case EquipSlot.Neck:
changes |= SetIfDifferent(ref Neck.Set, model);
changes |= SetIfDifferent(ref Neck.Variant, variant);
ret = Neck.ToWeapon();
return changes;
case EquipSlot.Wrists:
changes |= SetIfDifferent(ref Wrists.Set, model);
changes |= SetIfDifferent(ref Wrists.Variant, variant);
ret = Wrists.ToWeapon();
return changes;
case EquipSlot.RFinger:
changes |= SetIfDifferent(ref RFinger.Set, model);
changes |= SetIfDifferent(ref RFinger.Variant, variant);
ret = RFinger.ToWeapon();
return changes;
case EquipSlot.LFinger:
changes |= SetIfDifferent(ref LFinger.Set, model);
changes |= SetIfDifferent(ref LFinger.Variant, variant);
ret = LFinger.ToWeapon();
return changes;
default:
ret = CharacterWeapon.Empty;
return changes;
}
}
public bool SetPiece(EquipSlot slot, SetId model, byte variant, StainId stain, out CharacterWeapon ret)
{
var changes = false;
switch (slot)
{
case EquipSlot.MainHand:
changes |= SetIfDifferent(ref MainHand.Set, model);
changes |= SetIfDifferent(ref MainHand.Variant, variant);
changes |= SetIfDifferent(ref MainHand.Stain, stain);
ret = MainHand;
return changes;
case EquipSlot.OffHand:
changes |= SetIfDifferent(ref OffHand.Set, model);
changes |= SetIfDifferent(ref OffHand.Variant, variant);
changes |= SetIfDifferent(ref OffHand.Stain, stain);
ret = OffHand;
return changes;
case EquipSlot.Head:
changes |= SetIfDifferent(ref Head.Set, model);
changes |= SetIfDifferent(ref Head.Variant, variant);
changes |= SetIfDifferent(ref Head.Stain, stain);
ret = Head.ToWeapon();
return changes;
case EquipSlot.Body:
changes |= SetIfDifferent(ref Body.Set, model);
changes |= SetIfDifferent(ref Body.Variant, variant);
changes |= SetIfDifferent(ref Body.Stain, stain);
ret = Body.ToWeapon();
return changes;
case EquipSlot.Hands:
changes |= SetIfDifferent(ref Hands.Set, model);
changes |= SetIfDifferent(ref Hands.Variant, variant);
changes |= SetIfDifferent(ref Hands.Stain, stain);
ret = Hands.ToWeapon();
return changes;
case EquipSlot.Legs:
changes |= SetIfDifferent(ref Legs.Set, model);
changes |= SetIfDifferent(ref Legs.Variant, variant);
changes |= SetIfDifferent(ref Legs.Stain, stain);
ret = Legs.ToWeapon();
return changes;
case EquipSlot.Feet:
changes |= SetIfDifferent(ref Feet.Set, model);
changes |= SetIfDifferent(ref Feet.Variant, variant);
changes |= SetIfDifferent(ref Feet.Stain, stain);
ret = Feet.ToWeapon();
return changes;
case EquipSlot.Ears:
changes |= SetIfDifferent(ref Ears.Set, model);
changes |= SetIfDifferent(ref Ears.Variant, variant);
changes |= SetIfDifferent(ref Ears.Stain, stain);
ret = Ears.ToWeapon();
return changes;
case EquipSlot.Neck:
changes |= SetIfDifferent(ref Neck.Set, model);
changes |= SetIfDifferent(ref Neck.Variant, variant);
changes |= SetIfDifferent(ref Neck.Stain, stain);
ret = Neck.ToWeapon();
return changes;
case EquipSlot.Wrists:
changes |= SetIfDifferent(ref Wrists.Set, model);
changes |= SetIfDifferent(ref Wrists.Variant, variant);
changes |= SetIfDifferent(ref Wrists.Stain, stain);
ret = Wrists.ToWeapon();
return changes;
case EquipSlot.RFinger:
changes |= SetIfDifferent(ref RFinger.Set, model);
changes |= SetIfDifferent(ref RFinger.Variant, variant);
changes |= SetIfDifferent(ref RFinger.Stain, stain);
ret = RFinger.ToWeapon();
return changes;
case EquipSlot.LFinger:
changes |= SetIfDifferent(ref LFinger.Set, model);
changes |= SetIfDifferent(ref LFinger.Variant, variant);
changes |= SetIfDifferent(ref LFinger.Stain, stain);
ret = LFinger.ToWeapon();
return changes;
default:
ret = CharacterWeapon.Empty;
return changes;
}
}
public bool SetPiece(EquipSlot slot, CharacterWeapon weapon, out CharacterWeapon ret)
=> SetPiece(slot, weapon.Set, weapon.Type, (byte)weapon.Variant, weapon.Stain, out ret);
public bool SetPiece(EquipSlot slot, CharacterArmor armor, out CharacterWeapon ret)
=> SetPiece(slot, armor.Set, armor.Variant, armor.Stain, out ret);
public bool SetPiece(EquipSlot slot, SetId model, WeaponType type, byte variant, StainId stain, out CharacterWeapon ret)
{
var changes = false;
switch (slot)
{
case EquipSlot.MainHand:
changes |= SetIfDifferent(ref MainHand.Set, model);
changes |= SetIfDifferent(ref MainHand.Type, type);
changes |= SetIfDifferent(ref MainHand.Variant, variant);
changes |= SetIfDifferent(ref MainHand.Stain, stain);
ret = MainHand;
return changes;
case EquipSlot.OffHand:
changes |= SetIfDifferent(ref OffHand.Set, model);
changes |= SetIfDifferent(ref OffHand.Type, type);
changes |= SetIfDifferent(ref OffHand.Variant, variant);
changes |= SetIfDifferent(ref OffHand.Stain, stain);
ret = OffHand;
return changes;
case EquipSlot.Head:
changes |= SetIfDifferent(ref Head.Set, model);
changes |= SetIfDifferent(ref Head.Variant, variant);
changes |= SetIfDifferent(ref Head.Stain, stain);
ret = Head.ToWeapon();
return changes;
case EquipSlot.Body:
changes |= SetIfDifferent(ref Body.Set, model);
changes |= SetIfDifferent(ref Body.Variant, variant);
changes |= SetIfDifferent(ref Body.Stain, stain);
ret = Body.ToWeapon();
return changes;
case EquipSlot.Hands:
changes |= SetIfDifferent(ref Hands.Set, model);
changes |= SetIfDifferent(ref Hands.Variant, variant);
changes |= SetIfDifferent(ref Hands.Stain, stain);
ret = Hands.ToWeapon();
return changes;
case EquipSlot.Legs:
changes |= SetIfDifferent(ref Legs.Set, model);
changes |= SetIfDifferent(ref Legs.Variant, variant);
changes |= SetIfDifferent(ref Legs.Stain, stain);
ret = Legs.ToWeapon();
return changes;
case EquipSlot.Feet:
changes |= SetIfDifferent(ref Feet.Set, model);
changes |= SetIfDifferent(ref Feet.Variant, variant);
changes |= SetIfDifferent(ref Feet.Stain, stain);
ret = Feet.ToWeapon();
return changes;
case EquipSlot.Ears:
changes |= SetIfDifferent(ref Ears.Set, model);
changes |= SetIfDifferent(ref Ears.Variant, variant);
changes |= SetIfDifferent(ref Ears.Stain, stain);
ret = Ears.ToWeapon();
return changes;
case EquipSlot.Neck:
changes |= SetIfDifferent(ref Neck.Set, model);
changes |= SetIfDifferent(ref Neck.Variant, variant);
changes |= SetIfDifferent(ref Neck.Stain, stain);
ret = Neck.ToWeapon();
return changes;
case EquipSlot.Wrists:
changes |= SetIfDifferent(ref Wrists.Set, model);
changes |= SetIfDifferent(ref Wrists.Variant, variant);
changes |= SetIfDifferent(ref Wrists.Stain, stain);
ret = Wrists.ToWeapon();
return changes;
case EquipSlot.RFinger:
changes |= SetIfDifferent(ref RFinger.Set, model);
changes |= SetIfDifferent(ref RFinger.Variant, variant);
changes |= SetIfDifferent(ref RFinger.Stain, stain);
ret = RFinger.ToWeapon();
return changes;
case EquipSlot.LFinger:
changes |= SetIfDifferent(ref LFinger.Set, model);
changes |= SetIfDifferent(ref LFinger.Variant, variant);
changes |= SetIfDifferent(ref LFinger.Stain, stain);
ret = LFinger.ToWeapon();
return changes;
default:
ret = CharacterWeapon.Empty;
return changes;
}
}
public StainId Stain(EquipSlot slot)
=> slot switch
{
EquipSlot.MainHand => MainHand.Stain,
EquipSlot.OffHand => OffHand.Stain,
EquipSlot.Head => Head.Stain,
EquipSlot.Body => Body.Stain,
EquipSlot.Hands => Hands.Stain,
EquipSlot.Legs => Legs.Stain,
EquipSlot.Feet => Feet.Stain,
EquipSlot.Ears => Ears.Stain,
EquipSlot.Neck => Neck.Stain,
EquipSlot.Wrists => Wrists.Stain,
EquipSlot.RFinger => RFinger.Stain,
EquipSlot.LFinger => LFinger.Stain,
_ => 0,
};
public bool SetStain(EquipSlot slot, StainId stain, out CharacterWeapon ret)
{
var changes = false;
switch (slot)
{
case EquipSlot.MainHand:
changes = SetIfDifferent(ref MainHand.Stain, stain);
ret = MainHand;
return changes;
case EquipSlot.OffHand:
changes = SetIfDifferent(ref OffHand.Stain, stain);
ret = OffHand;
return changes;
case EquipSlot.Head:
changes = SetIfDifferent(ref Head.Stain, stain);
ret = Head.ToWeapon();
return changes;
case EquipSlot.Body:
changes = SetIfDifferent(ref Body.Stain, stain);
ret = Body.ToWeapon();
return changes;
case EquipSlot.Hands:
changes = SetIfDifferent(ref Hands.Stain, stain);
ret = Hands.ToWeapon();
return changes;
case EquipSlot.Legs:
changes = SetIfDifferent(ref Legs.Stain, stain);
ret = Legs.ToWeapon();
return changes;
case EquipSlot.Feet:
changes = SetIfDifferent(ref Feet.Stain, stain);
ret = Feet.ToWeapon();
return changes;
case EquipSlot.Ears:
changes = SetIfDifferent(ref Ears.Stain, stain);
ret = Ears.ToWeapon();
return changes;
case EquipSlot.Neck:
changes = SetIfDifferent(ref Neck.Stain, stain);
ret = Neck.ToWeapon();
return changes;
case EquipSlot.Wrists:
changes = SetIfDifferent(ref Wrists.Stain, stain);
ret = Wrists.ToWeapon();
return changes;
case EquipSlot.RFinger:
changes = SetIfDifferent(ref RFinger.Stain, stain);
ret = RFinger.ToWeapon();
return changes;
case EquipSlot.LFinger:
changes = SetIfDifferent(ref LFinger.Stain, stain);
ret = LFinger.ToWeapon();
return changes;
default:
ret = CharacterWeapon.Empty;
return false;
}
}
private static bool SetIfDifferent<T>(ref T old, T value) where T : IEquatable<T>
{
if (old.Equals(value))
return false;
old = value;
return true;
}
}