mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 10:17:23 +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>
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ namespace Glamourer
|
|||
public class CharacterSave
|
||||
{
|
||||
public const byte CurrentVersion = 2;
|
||||
public const byte TotalSizeVersion1 = 1 + 1 + 2 + 56 + ActorCustomization.CustomizationBytes;
|
||||
public const byte TotalSizeVersion2 = 1 + 1 + 2 + 56 + ActorCustomization.CustomizationBytes + 4 + 1;
|
||||
public const byte TotalSizeVersion1 = 1 + 1 + 2 + 56 + CharacterCustomization.CustomizationBytes;
|
||||
public const byte TotalSizeVersion2 = 1 + 1 + 2 + 56 + CharacterCustomization.CustomizationBytes + 4 + 1;
|
||||
|
||||
public const byte TotalSize = TotalSizeVersion2;
|
||||
|
||||
|
|
@ -97,8 +97,8 @@ namespace Glamourer
|
|||
|
||||
public byte StateFlags
|
||||
{
|
||||
get => _bytes[64 + ActorCustomization.CustomizationBytes];
|
||||
set => _bytes[64 + ActorCustomization.CustomizationBytes] = value;
|
||||
get => _bytes[64 + CharacterCustomization.CustomizationBytes];
|
||||
set => _bytes[64 + CharacterCustomization.CustomizationBytes] = value;
|
||||
}
|
||||
|
||||
public bool HatState
|
||||
|
|
@ -119,9 +119,9 @@ namespace Glamourer
|
|||
set => StateFlags = (byte) (value ? StateFlags & ~0x02 : StateFlags | 0x02);
|
||||
}
|
||||
|
||||
public ActorEquipMask WriteEquipment
|
||||
public CharacterEquipMask WriteEquipment
|
||||
{
|
||||
get => (ActorEquipMask) (_bytes[2] | (_bytes[3] << 8));
|
||||
get => (CharacterEquipMask) (_bytes[2] | (_bytes[3] << 8));
|
||||
set
|
||||
{
|
||||
_bytes[2] = (byte) ((ushort) value & 0xFF);
|
||||
|
|
@ -133,7 +133,7 @@ namespace Glamourer
|
|||
{
|
||||
get
|
||||
{
|
||||
fixed (byte* ptr = &_bytes[60 + ActorCustomization.CustomizationBytes])
|
||||
fixed (byte* ptr = &_bytes[60 + CharacterCustomization.CustomizationBytes])
|
||||
{
|
||||
return *(float*) ptr;
|
||||
}
|
||||
|
|
@ -142,24 +142,24 @@ namespace Glamourer
|
|||
{
|
||||
fixed (byte* ptr = _bytes)
|
||||
{
|
||||
*(ptr + 60 + ActorCustomization.CustomizationBytes + 0) = *((byte*) &value + 0);
|
||||
*(ptr + 60 + ActorCustomization.CustomizationBytes + 1) = *((byte*) &value + 1);
|
||||
*(ptr + 60 + ActorCustomization.CustomizationBytes + 2) = *((byte*) &value + 2);
|
||||
*(ptr + 60 + ActorCustomization.CustomizationBytes + 3) = *((byte*) &value + 3);
|
||||
*(ptr + 60 + CharacterCustomization.CustomizationBytes + 0) = *((byte*) &value + 0);
|
||||
*(ptr + 60 + CharacterCustomization.CustomizationBytes + 1) = *((byte*) &value + 1);
|
||||
*(ptr + 60 + CharacterCustomization.CustomizationBytes + 2) = *((byte*) &value + 2);
|
||||
*(ptr + 60 + CharacterCustomization.CustomizationBytes + 3) = *((byte*) &value + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Load(ActorCustomization customization)
|
||||
public void Load(CharacterCustomization customization)
|
||||
{
|
||||
WriteCustomizations = true;
|
||||
customization.WriteBytes(_bytes, 4);
|
||||
}
|
||||
|
||||
public void Load(ActorEquipment equipment, ActorEquipMask mask = ActorEquipMask.All)
|
||||
public void Load(CharacterEquipment equipment, CharacterEquipMask mask = CharacterEquipMask.All)
|
||||
{
|
||||
WriteEquipment = mask;
|
||||
equipment.WriteBytes(_bytes, 4 + ActorCustomization.CustomizationBytes);
|
||||
equipment.WriteBytes(_bytes, 4 + CharacterCustomization.CustomizationBytes);
|
||||
}
|
||||
|
||||
public string ToBase64()
|
||||
|
|
@ -179,19 +179,19 @@ namespace Glamourer
|
|||
$"Can not parse Base64 string into CharacterSave:\n\tInvalid value {value} in byte {idx}, should be in [{min},{max}].");
|
||||
}
|
||||
|
||||
private static void CheckActorMask(byte val1, byte val2)
|
||||
private static void CheckCharacterMask(byte val1, byte val2)
|
||||
{
|
||||
var mask = (ActorEquipMask) (val1 | (val2 << 8));
|
||||
if (mask > ActorEquipMask.All)
|
||||
var mask = (CharacterEquipMask) (val1 | (val2 << 8));
|
||||
if (mask > CharacterEquipMask.All)
|
||||
throw new Exception($"Can not parse Base64 string into CharacterSave:\n\tInvalid value {mask} in byte 3 and 4.");
|
||||
}
|
||||
|
||||
public void LoadActor(Character a)
|
||||
public void LoadCharacter(Character a)
|
||||
{
|
||||
WriteCustomizations = true;
|
||||
Load(new ActorCustomization(a));
|
||||
Load(new CharacterCustomization(a));
|
||||
|
||||
Load(new ActorEquipment(a));
|
||||
Load(new CharacterEquipment(a));
|
||||
|
||||
SetHatState = true;
|
||||
SetVisorState = true;
|
||||
|
|
@ -206,7 +206,7 @@ namespace Glamourer
|
|||
{
|
||||
if (WriteCustomizations)
|
||||
Customizations.Write(a.Address);
|
||||
if (WriteEquipment != ActorEquipMask.None)
|
||||
if (WriteEquipment != CharacterEquipMask.None)
|
||||
Equipment.Write(a.Address, WriteEquipment, WriteEquipment);
|
||||
a.SetWetness(IsWet);
|
||||
a.Alpha() = Alpha;
|
||||
|
|
@ -243,7 +243,7 @@ namespace Glamourer
|
|||
default: throw new Exception($"Can not parse Base64 string into CharacterSave:\n\tInvalid Version {bytes[0]}.");
|
||||
}
|
||||
|
||||
CheckActorMask(bytes[2], bytes[3]);
|
||||
CheckCharacterMask(bytes[2], bytes[3]);
|
||||
bytes.CopyTo(_bytes, 0);
|
||||
}
|
||||
|
||||
|
|
@ -254,23 +254,23 @@ namespace Glamourer
|
|||
return ret;
|
||||
}
|
||||
|
||||
public unsafe ref ActorCustomization Customizations
|
||||
public unsafe ref CharacterCustomization Customizations
|
||||
{
|
||||
get
|
||||
{
|
||||
fixed (byte* ptr = _bytes)
|
||||
{
|
||||
return ref *(ActorCustomization*) (ptr + 4);
|
||||
return ref *(CharacterCustomization*) (ptr + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ActorEquipment Equipment
|
||||
public CharacterEquipment Equipment
|
||||
{
|
||||
get
|
||||
{
|
||||
var ret = new ActorEquipment();
|
||||
ret.FromBytes(_bytes, 4 + ActorCustomization.CustomizationBytes);
|
||||
var ret = new CharacterEquipment();
|
||||
ret.FromBytes(_bytes, 4 + CharacterCustomization.CustomizationBytes);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,9 +66,6 @@
|
|||
<Reference Include="Penumbra.GameData">
|
||||
<HintPath>..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.GameData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Penumbra.Api">
|
||||
<HintPath>..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.Api.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Penumbra.PlayerWatch">
|
||||
<HintPath>..\..\Penumbra\Penumbra\bin\$(Configuration)\$(TargetFramework)\Penumbra.PlayerWatch.dll</HintPath>
|
||||
</Reference>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,26 @@
|
|||
{
|
||||
{
|
||||
"Disabled": false,
|
||||
"Testing": false,
|
||||
"InstalledFromUrl": null,
|
||||
"Author": "Ottermandias",
|
||||
"Name": "Glamourer",
|
||||
"Description": "Adds functionality to change appearance of actors. Requires Penumbra to be installed and activated to work.",
|
||||
"Punchline": "Change and save appearance of players.",
|
||||
"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": null,
|
||||
"IsHide": false,
|
||||
"InternalName": "Glamourer",
|
||||
"AssemblyVersion": "0.0.3.0",
|
||||
"AssemblyVersion": "0.0.4.0",
|
||||
"TestingAssemblyVersion": null,
|
||||
"IsTestingExclusive": false,
|
||||
"RepoUrl": "https://github.com/Ottermandias/Glamourer",
|
||||
"ApplicableVersion": "any",
|
||||
"DalamudApiLevel": 4,
|
||||
"LoadPriority": -100
|
||||
"DownloadCount": 0,
|
||||
"LastUpdate": 0,
|
||||
"DownloadLinkInstall": null,
|
||||
"DownloadLinkUpdate": null,
|
||||
"DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/raw/main/Glamourer.zip",
|
||||
"LoadPriority": -100,
|
||||
"ImageUrls": null,
|
||||
"IconUrl": null
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ namespace Glamourer.Gui
|
|||
{
|
||||
public const float SelectorWidth = 200;
|
||||
public const float MinWindowWidth = 675;
|
||||
public const int GPoseActorId = 201;
|
||||
public const int GPoseObjectId = 201;
|
||||
private const string PluginName = "Glamourer";
|
||||
private readonly string _glamourerHeader;
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ namespace Glamourer.Gui
|
|||
if (!raii.Begin(() => ImGui.BeginTabBar("##tabBar"), ImGui.EndTabBar))
|
||||
return;
|
||||
|
||||
_inGPose = Dalamud.Objects[GPoseActorId] != null;
|
||||
_inGPose = Dalamud.Objects[GPoseObjectId] != null;
|
||||
_iconSize = Vector2.One * ImGui.GetTextLineHeightWithSpacing() * 2;
|
||||
_actualIconSize = _iconSize + 2 * ImGui.GetStyle().FramePadding;
|
||||
_comboSelectorSize = 4 * _actualIconSize.X + 3 * ImGui.GetStyle().ItemSpacing.X;
|
||||
|
|
@ -86,7 +86,7 @@ namespace Glamourer.Gui
|
|||
_raceSelectorWidth = _inputIntSize + _percentageSize - _actualIconSize.X;
|
||||
_itemComboWidth = 6 * _actualIconSize.X + 4 * ImGui.GetStyle().ItemSpacing.X - ColorButtonWidth + 1;
|
||||
|
||||
DrawActorTab();
|
||||
DrawPlayerTab();
|
||||
DrawSaves();
|
||||
DrawConfigTab();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Glamourer.Gui
|
|||
private const uint RedHeaderColor = 0xFF1818C0;
|
||||
private const uint GreenHeaderColor = 0xFF18C018;
|
||||
|
||||
private void DrawActorHeader()
|
||||
private void DrawPlayerHeader()
|
||||
{
|
||||
var color = _player == null ? RedHeaderColor : GreenHeaderColor;
|
||||
var buttonColor = ImGui.GetColorU32(ImGuiCol.FrameBg);
|
||||
|
|
@ -30,7 +30,7 @@ namespace Glamourer.Gui
|
|||
.PushColor(ImGuiCol.ButtonActive, buttonColor)
|
||||
.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.PushStyle(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.Button($"{_currentActorName}##actorHeader", -Vector2.UnitX * 0.0001f);
|
||||
ImGui.Button($"{_currentPlayerName}##playerHeader", -Vector2.UnitX * 0.0001f);
|
||||
}
|
||||
|
||||
private static void DrawCopyClipboardButton(CharacterSave save)
|
||||
|
|
@ -97,7 +97,7 @@ namespace Glamourer.Gui
|
|||
return;
|
||||
|
||||
var player = _inGPose
|
||||
? (Character?) Dalamud.Objects[GPoseActorId]
|
||||
? (Character?) Dalamud.Objects[GPoseObjectId]
|
||||
: Dalamud.ClientState.LocalPlayer;
|
||||
var fallback = _inGPose ? Dalamud.ClientState.LocalPlayer : null;
|
||||
if (player == null)
|
||||
|
|
@ -106,7 +106,7 @@ namespace Glamourer.Gui
|
|||
save.Apply(player);
|
||||
if (_inGPose)
|
||||
save.Apply(fallback!);
|
||||
Glamourer.Penumbra.UpdateActors(player, fallback);
|
||||
Glamourer.Penumbra.UpdateCharacters(player, fallback);
|
||||
}
|
||||
|
||||
private void DrawApplyToTargetButton(CharacterSave save)
|
||||
|
|
@ -118,11 +118,11 @@ namespace Glamourer.Gui
|
|||
if (player == null)
|
||||
return;
|
||||
|
||||
var fallBackActor = _playerNames[player.Name.ToString()];
|
||||
var fallBackCharacter = _playerNames[player.Name.ToString()];
|
||||
save.Apply(player);
|
||||
if (fallBackActor != null)
|
||||
save.Apply(fallBackActor);
|
||||
Glamourer.Penumbra.UpdateActors(player, fallBackActor);
|
||||
if (fallBackCharacter != null)
|
||||
save.Apply(fallBackCharacter);
|
||||
Glamourer.Penumbra.UpdateCharacters(player, fallBackCharacter);
|
||||
}
|
||||
|
||||
private void SaveNewDesign(CharacterSave save)
|
||||
|
|
@ -144,11 +144,11 @@ namespace Glamourer.Gui
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawActorPanel()
|
||||
private void DrawPlayerPanel()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
DrawActorHeader();
|
||||
if (!ImGui.BeginChild("##actorData", -Vector2.One, true))
|
||||
DrawPlayerHeader();
|
||||
if (!ImGui.BeginChild("##playerData", -Vector2.One, true))
|
||||
return;
|
||||
|
||||
DrawCopyClipboardButton(_currentSave);
|
||||
|
|
@ -180,7 +180,7 @@ namespace Glamourer.Gui
|
|||
changes |= DrawMiscellaneous(_currentSave, _player);
|
||||
|
||||
if (_player != null && changes)
|
||||
Glamourer.Penumbra.UpdateActors(_player);
|
||||
Glamourer.Penumbra.UpdateCharacters(_player);
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,49 +11,49 @@ namespace Glamourer.Gui
|
|||
internal partial class Interface
|
||||
{
|
||||
private Character? _player;
|
||||
private string _currentActorName = string.Empty;
|
||||
private string _actorFilter = string.Empty;
|
||||
private string _actorFilterLower = string.Empty;
|
||||
private string _currentPlayerName = string.Empty;
|
||||
private string _playerFilter = string.Empty;
|
||||
private string _playerFilterLower = string.Empty;
|
||||
private readonly Dictionary<string, Character?> _playerNames = new(400);
|
||||
|
||||
private void DrawActorFilter()
|
||||
private void DrawPlayerFilter()
|
||||
{
|
||||
using var raii = new ImGuiRaii()
|
||||
.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)
|
||||
.PushStyle(ImGuiStyleVar.FrameRounding, 0);
|
||||
ImGui.SetNextItemWidth(SelectorWidth * ImGui.GetIO().FontGlobalScale);
|
||||
if (ImGui.InputTextWithHint("##actorFilter", "Filter Players...", ref _actorFilter, 32))
|
||||
_actorFilterLower = _actorFilter.ToLowerInvariant();
|
||||
if (ImGui.InputTextWithHint("##playerFilter", "Filter Players...", ref _playerFilter, 32))
|
||||
_playerFilterLower = _playerFilter.ToLowerInvariant();
|
||||
}
|
||||
|
||||
private void DrawActorSelectable(Character actor, bool gPose)
|
||||
private void DrawPlayerSelectable(Character player, bool gPose)
|
||||
{
|
||||
var actorName = actor.Name.ToString();
|
||||
if (!actorName.Any())
|
||||
var playerName = player.Name.ToString();
|
||||
if (!playerName.Any())
|
||||
return;
|
||||
|
||||
if (_playerNames.ContainsKey(actorName))
|
||||
if (_playerNames.ContainsKey(playerName))
|
||||
{
|
||||
_playerNames[actorName] = actor;
|
||||
_playerNames[playerName] = player;
|
||||
return;
|
||||
}
|
||||
|
||||
_playerNames.Add(actorName, null);
|
||||
_playerNames.Add(playerName, null);
|
||||
|
||||
var label = gPose ? $"{actorName} (GPose)" : actorName;
|
||||
if (!_actorFilterLower.Any() || actorName.ToLowerInvariant().Contains(_actorFilterLower))
|
||||
if (ImGui.Selectable(label, _currentActorName == actorName))
|
||||
var label = gPose ? $"{playerName} (GPose)" : playerName;
|
||||
if (!_playerFilterLower.Any() || playerName.ToLowerInvariant().Contains(_playerFilterLower))
|
||||
if (ImGui.Selectable(label, _currentPlayerName == playerName))
|
||||
{
|
||||
_currentActorName = actorName;
|
||||
_currentSave.LoadActor(actor);
|
||||
_player = actor;
|
||||
_currentPlayerName = playerName;
|
||||
_currentSave.LoadCharacter(player);
|
||||
_player = player;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentActorName == actorName)
|
||||
if (_currentPlayerName == playerName)
|
||||
{
|
||||
_currentSave.LoadActor(actor);
|
||||
_player = actor;
|
||||
_currentSave.LoadCharacter(player);
|
||||
_player = player;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,40 +86,40 @@ namespace Glamourer.Gui
|
|||
|
||||
raii.PopFonts();
|
||||
if (ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip("Select the current target, if it is a player actor.");
|
||||
ImGui.SetTooltip("Select the current target, if it is a player object.");
|
||||
|
||||
if (select == null || select.ObjectKind != ObjectKind.Player)
|
||||
return;
|
||||
|
||||
_player = select;
|
||||
_currentActorName = _player.Name.ToString();
|
||||
_currentSave.LoadActor(_player);
|
||||
_currentPlayerName = _player.Name.ToString();
|
||||
_currentSave.LoadCharacter(_player);
|
||||
}
|
||||
|
||||
private void DrawActorSelector()
|
||||
private void DrawPlayerSelector()
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
DrawActorFilter();
|
||||
if (!ImGui.BeginChild("##actorSelector",
|
||||
DrawPlayerFilter();
|
||||
if (!ImGui.BeginChild("##playerSelector",
|
||||
new Vector2(SelectorWidth * ImGui.GetIO().FontGlobalScale, -ImGui.GetFrameHeight() - 1), true))
|
||||
return;
|
||||
|
||||
_playerNames.Clear();
|
||||
for (var i = GPoseActorId; i < GPoseActorId + 48; ++i)
|
||||
for (var i = GPoseObjectId; i < GPoseObjectId + 48; ++i)
|
||||
{
|
||||
var actor = Dalamud.Objects[i] as Character;
|
||||
if (actor == null)
|
||||
var player = Dalamud.Objects[i] as Character;
|
||||
if (player == null)
|
||||
break;
|
||||
|
||||
if (actor.ObjectKind == ObjectKind.Player)
|
||||
DrawActorSelectable(actor, true);
|
||||
if (player.ObjectKind == ObjectKind.Player)
|
||||
DrawPlayerSelectable(player, true);
|
||||
}
|
||||
|
||||
for (var i = 0; i < GPoseActorId; i += 2)
|
||||
for (var i = 0; i < GPoseObjectId; i += 2)
|
||||
{
|
||||
var actor = Dalamud.Objects[i] as Character;
|
||||
if (actor != null && actor.ObjectKind == ObjectKind.Player)
|
||||
DrawActorSelectable(actor, false);
|
||||
var player = Dalamud.Objects[i] as Character;
|
||||
if (player != null && player.ObjectKind == ObjectKind.Player)
|
||||
DrawPlayerSelectable(player, false);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -132,20 +132,20 @@ namespace Glamourer.Gui
|
|||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawActorTab()
|
||||
private void DrawPlayerTab()
|
||||
{
|
||||
using var raii = new ImGuiRaii();
|
||||
if (!raii.Begin(() => ImGui.BeginTabItem("Current Players"), ImGui.EndTabItem))
|
||||
return;
|
||||
|
||||
_player = null;
|
||||
DrawActorSelector();
|
||||
DrawPlayerSelector();
|
||||
|
||||
if (!_currentActorName.Any())
|
||||
if (!_currentPlayerName.Any())
|
||||
return;
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawActorPanel();
|
||||
DrawPlayerPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private static (int, Customization.Customization) GetCurrentCustomization(ref ActorCustomization customization, CustomizationId id,
|
||||
private static (int, Customization.Customization) GetCurrentCustomization(ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
var current = set.DataByValue(id, customization[id], out var custom);
|
||||
|
|
@ -78,7 +78,7 @@ namespace Glamourer.Gui
|
|||
return (current, custom!.Value);
|
||||
}
|
||||
|
||||
private bool DrawColorPicker(string label, string tooltip, ref ActorCustomization customization, CustomizationId id,
|
||||
private bool DrawColorPicker(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
var ret = false;
|
||||
|
|
@ -116,7 +116,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawListSelector(string label, string tooltip, ref ActorCustomization customization, CustomizationId id,
|
||||
private bool DrawListSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImGuiRaii.NewGroup();
|
||||
|
|
@ -158,7 +158,7 @@ namespace Glamourer.Gui
|
|||
private static readonly Vector4 NoColor = new(1f, 1f, 1f, 1f);
|
||||
private static readonly Vector4 RedColor = new(0.6f, 0.3f, 0.3f, 1f);
|
||||
|
||||
private bool DrawMultiSelector(ref ActorCustomization customization, CustomizationSet set)
|
||||
private bool DrawMultiSelector(ref CharacterCustomization customization, CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImGuiRaii.NewGroup();
|
||||
var ret = false;
|
||||
|
|
@ -242,7 +242,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawIconSelector(string label, string tooltip, ref ActorCustomization customization, CustomizationId id,
|
||||
private bool DrawIconSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImGuiRaii.NewGroup();
|
||||
|
|
@ -290,7 +290,7 @@ namespace Glamourer.Gui
|
|||
}
|
||||
|
||||
|
||||
private bool DrawPercentageSelector(string label, string tooltip, ref ActorCustomization customization, CustomizationId id,
|
||||
private bool DrawPercentageSelector(string label, string tooltip, ref CharacterCustomization customization, CustomizationId id,
|
||||
CustomizationSet set)
|
||||
{
|
||||
using var bigGroup = ImGuiRaii.NewGroup();
|
||||
|
|
@ -320,7 +320,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawRaceSelector(ref ActorCustomization customization)
|
||||
private bool DrawRaceSelector(ref CharacterCustomization customization)
|
||||
{
|
||||
using var group = ImGuiRaii.NewGroup();
|
||||
var ret = false;
|
||||
|
|
@ -345,7 +345,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawGenderSelector(ref ActorCustomization customization)
|
||||
private bool DrawGenderSelector(ref CharacterCustomization customization)
|
||||
{
|
||||
var ret = false;
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
|
|
@ -376,7 +376,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawPicker(CustomizationSet set, CustomizationId id, ref ActorCustomization customization)
|
||||
private bool DrawPicker(CustomizationSet set, CustomizationId id, ref CharacterCustomization customization)
|
||||
{
|
||||
if (!set.IsAvailable(id))
|
||||
return false;
|
||||
|
|
@ -396,7 +396,7 @@ namespace Glamourer.Gui
|
|||
|
||||
private static readonly CustomizationId[] AllCustomizations = (CustomizationId[]) Enum.GetValues(typeof(CustomizationId));
|
||||
|
||||
private bool DrawCustomization(ref ActorCustomization custom)
|
||||
private bool DrawCustomization(ref CharacterCustomization custom)
|
||||
{
|
||||
if (!ImGui.CollapsingHeader("Character Customization"))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -308,12 +308,12 @@ namespace Glamourer.Gui
|
|||
|
||||
var changesStates = save.SetHatState || save.SetVisorState || save.SetWeaponState || save.IsWet || save.Alpha != 1.0f;
|
||||
if (save.WriteCustomizations)
|
||||
if (save.WriteEquipment != ActorEquipMask.None)
|
||||
if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
return white;
|
||||
else
|
||||
return changesStates ? white : Glamourer.Config.CustomizationColor;
|
||||
|
||||
if (save.WriteEquipment != ActorEquipMask.None)
|
||||
if (save.WriteEquipment != CharacterEquipMask.None)
|
||||
return changesStates ? white : Glamourer.Config.EquipmentColor;
|
||||
|
||||
return changesStates ? Glamourer.Config.StateColor : grey;
|
||||
|
|
|
|||
|
|
@ -36,13 +36,13 @@ namespace Glamourer.Gui
|
|||
return false;
|
||||
}
|
||||
|
||||
private static bool DrawCheckbox(ActorEquipMask flag, ref ActorEquipMask mask)
|
||||
private static bool DrawCheckbox(CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var tmp = (uint) mask;
|
||||
var ret = false;
|
||||
if (ImGui.CheckboxFlags($"##flag_{(uint) flag}", ref tmp, (uint) flag) && tmp != (uint) mask)
|
||||
{
|
||||
mask = (ActorEquipMask) tmp;
|
||||
mask = (CharacterEquipMask) tmp;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquipSlot(EquipSlot slot, ActorArmor equip)
|
||||
private bool DrawEquipSlot(EquipSlot slot, CharacterArmor equip)
|
||||
{
|
||||
var (equipCombo, stainCombo) = _combos[slot];
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquipSlotWithCheck(EquipSlot slot, ActorArmor equip, ActorEquipMask flag, ref ActorEquipMask mask)
|
||||
private bool DrawEquipSlotWithCheck(EquipSlot slot, CharacterArmor equip, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = DrawCheckbox(flag, ref mask);
|
||||
ImGui.SameLine();
|
||||
|
|
@ -71,7 +71,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawWeapon(EquipSlot slot, ActorWeapon weapon)
|
||||
private bool DrawWeapon(EquipSlot slot, CharacterWeapon weapon)
|
||||
{
|
||||
var (equipCombo, stainCombo) = _combos[slot];
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawWeaponWithCheck(EquipSlot slot, ActorWeapon weapon, ActorEquipMask flag, ref ActorEquipMask mask)
|
||||
private bool DrawWeaponWithCheck(EquipSlot slot, CharacterWeapon weapon, CharacterEquipMask flag, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = DrawCheckbox(flag, ref mask);
|
||||
ImGui.SameLine();
|
||||
|
|
@ -91,7 +91,7 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquip(ActorEquipment equip)
|
||||
private bool DrawEquip(CharacterEquipment equip)
|
||||
{
|
||||
var ret = false;
|
||||
if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
|
|
@ -113,23 +113,23 @@ namespace Glamourer.Gui
|
|||
return ret;
|
||||
}
|
||||
|
||||
private bool DrawEquip(ActorEquipment equip, ref ActorEquipMask mask)
|
||||
private bool DrawEquip(CharacterEquipment equip, ref CharacterEquipMask mask)
|
||||
{
|
||||
var ret = false;
|
||||
if (ImGui.CollapsingHeader("Character Equipment"))
|
||||
{
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, ActorEquipMask.MainHand, ref mask);
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, ActorEquipMask.OffHand, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, ActorEquipMask.Head, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, ActorEquipMask.Body, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, ActorEquipMask.Hands, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, ActorEquipMask.Legs, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, ActorEquipMask.Feet, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, ActorEquipMask.Ears, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, ActorEquipMask.Neck, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, ActorEquipMask.Wrists, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, ActorEquipMask.RFinger, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, ActorEquipMask.LFinger, ref mask);
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.MainHand, equip.MainHand, CharacterEquipMask.MainHand, ref mask);
|
||||
ret |= DrawWeaponWithCheck(EquipSlot.OffHand, equip.OffHand, CharacterEquipMask.OffHand, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Head, equip.Head, CharacterEquipMask.Head, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Body, equip.Body, CharacterEquipMask.Body, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Hands, equip.Hands, CharacterEquipMask.Hands, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Legs, equip.Legs, CharacterEquipMask.Legs, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Feet, equip.Feet, CharacterEquipMask.Feet, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Ears, equip.Ears, CharacterEquipMask.Ears, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Neck, equip.Neck, CharacterEquipMask.Neck, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.Wrists, equip.Wrists, CharacterEquipMask.Wrists, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.RFinger, equip.RFinger, CharacterEquipMask.RFinger, ref mask);
|
||||
ret |= DrawEquipSlotWithCheck(EquipSlot.LFinger, equip.LFinger, CharacterEquipMask.LFinger, ref mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Glamourer.Gui
|
|||
}
|
||||
|
||||
// Go through a whole customization struct and fix up all settings that need fixing.
|
||||
private static void FixUpAttributes(ref ActorCustomization customization)
|
||||
private static void FixUpAttributes(ref CharacterCustomization customization)
|
||||
{
|
||||
var set = Glamourer.Customization.GetList(customization.Clan, customization.Gender);
|
||||
foreach (CustomizationId id in Enum.GetValues(typeof(CustomizationId)))
|
||||
|
|
@ -54,7 +54,7 @@ namespace Glamourer.Gui
|
|||
}
|
||||
|
||||
// Change a race and fix up all required customizations afterwards.
|
||||
private static bool ChangeRace(ref ActorCustomization customization, SubRace clan)
|
||||
private static bool ChangeRace(ref CharacterCustomization customization, SubRace clan)
|
||||
{
|
||||
if (clan == customization.Clan)
|
||||
return false;
|
||||
|
|
@ -76,7 +76,7 @@ namespace Glamourer.Gui
|
|||
}
|
||||
|
||||
// Change a gender and fix up all required customizations afterwards.
|
||||
private static bool ChangeGender(ref ActorCustomization customization, Gender gender)
|
||||
private static bool ChangeGender(ref CharacterCustomization customization, Gender gender)
|
||||
{
|
||||
if (gender == customization.Gender)
|
||||
return false;
|
||||
|
|
@ -156,7 +156,7 @@ namespace Glamourer.Gui
|
|||
break;
|
||||
case DesignNameUse.NewDesign:
|
||||
var empty = new CharacterSave();
|
||||
empty.Load(ActorCustomization.Default);
|
||||
empty.Load(CharacterCustomization.Default);
|
||||
empty.WriteCustomizations = false;
|
||||
SaveNewDesign(empty);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ namespace Glamourer
|
|||
public void OnGlamourer(string command, string arguments)
|
||||
=> _interface.ToggleVisibility();
|
||||
|
||||
private static GameObject? GetActor(string name)
|
||||
private static GameObject? GetPlayer(string name)
|
||||
{
|
||||
var lowerName = name.ToLowerInvariant();
|
||||
return lowerName switch
|
||||
{
|
||||
"" => null,
|
||||
"<me>" => Dalamud.Objects[Interface.GPoseActorId] ?? Dalamud.ClientState.LocalPlayer,
|
||||
"self" => Dalamud.Objects[Interface.GPoseActorId] ?? Dalamud.ClientState.LocalPlayer,
|
||||
"<me>" => Dalamud.Objects[Interface.GPoseObjectId] ?? Dalamud.ClientState.LocalPlayer,
|
||||
"self" => Dalamud.Objects[Interface.GPoseObjectId] ?? Dalamud.ClientState.LocalPlayer,
|
||||
"<t>" => Dalamud.Targets.Target,
|
||||
"target" => Dalamud.Targets.Target,
|
||||
"<f>" => Dalamud.Targets.FocusTarget,
|
||||
|
|
@ -74,14 +74,14 @@ namespace Glamourer
|
|||
};
|
||||
}
|
||||
|
||||
public void CopyToClipboard(Character actor)
|
||||
public void CopyToClipboard(Character player)
|
||||
{
|
||||
var save = new CharacterSave();
|
||||
save.LoadActor(actor);
|
||||
save.LoadCharacter(player);
|
||||
ImGui.SetClipboardText(save.ToBase64());
|
||||
}
|
||||
|
||||
public void ApplyCommand(Character actor, string target)
|
||||
public void ApplyCommand(Character player, string target)
|
||||
{
|
||||
CharacterSave? save = null;
|
||||
if (target.ToLowerInvariant() == "clipboard")
|
||||
|
|
@ -98,14 +98,14 @@ namespace Glamourer
|
|||
else
|
||||
save = d.Data;
|
||||
|
||||
save?.Apply(actor);
|
||||
Penumbra.UpdateActors(actor);
|
||||
save?.Apply(player);
|
||||
Penumbra.UpdateCharacters(player);
|
||||
}
|
||||
|
||||
public void SaveCommand(Character actor, string path)
|
||||
public void SaveCommand(Character player, string path)
|
||||
{
|
||||
var save = new CharacterSave();
|
||||
save.LoadActor(actor);
|
||||
save.LoadCharacter(player);
|
||||
try
|
||||
{
|
||||
var (folder, name) = Designs.FileSystem.CreateAllFolders(path);
|
||||
|
|
@ -147,17 +147,17 @@ namespace Glamourer
|
|||
return;
|
||||
}
|
||||
|
||||
var actor = GetActor(split[1]) as Character;
|
||||
if (actor == null)
|
||||
var player = GetPlayer(split[1]) as Character;
|
||||
if (player == null)
|
||||
{
|
||||
Dalamud.Chat.Print($"Could not find actor for {split[1]} or it was not a Character.");
|
||||
Dalamud.Chat.Print($"Could not find object for {split[1]} or it was not a Character.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (split[0].ToLowerInvariant())
|
||||
{
|
||||
case "copy":
|
||||
CopyToClipboard(actor);
|
||||
CopyToClipboard(player);
|
||||
return;
|
||||
case "apply":
|
||||
{
|
||||
|
|
@ -167,7 +167,7 @@ namespace Glamourer
|
|||
return;
|
||||
}
|
||||
|
||||
ApplyCommand(actor, split[2]);
|
||||
ApplyCommand(player, split[2]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ namespace Glamourer
|
|||
return;
|
||||
}
|
||||
|
||||
SaveCommand(actor, split[2]);
|
||||
SaveCommand(player, split[2]);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ using Dalamud.Logging;
|
|||
using Dalamud.Plugin;
|
||||
using Glamourer.Gui;
|
||||
using ImGuiNET;
|
||||
using Penumbra.Api;
|
||||
using Penumbra.PlayerWatch;
|
||||
using Penumbra.GameData.Enums;
|
||||
|
||||
namespace Glamourer
|
||||
{
|
||||
|
|
@ -73,18 +72,18 @@ namespace Glamourer
|
|||
if (button != MouseButton.Right || it is not Lumina.Excel.GeneratedSheets.Item item)
|
||||
return;
|
||||
|
||||
var gPose = Dalamud.Objects[Interface.GPoseActorId] as Character;
|
||||
var gPose = Dalamud.Objects[Interface.GPoseObjectId] as Character;
|
||||
var player = Dalamud.Objects[0] as Character;
|
||||
var writeItem = new Item(item, string.Empty);
|
||||
if (gPose != null)
|
||||
{
|
||||
writeItem.Write(gPose.Address);
|
||||
UpdateActors(gPose, player);
|
||||
UpdateCharacters(gPose, player);
|
||||
}
|
||||
else if (player != null)
|
||||
{
|
||||
writeItem.Write(player.Address);
|
||||
UpdateActors(player);
|
||||
UpdateCharacters(player);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +107,7 @@ namespace Glamourer
|
|||
}
|
||||
else
|
||||
{
|
||||
PluginLog.Debug($"Failure redrawing actor:\n{e}");
|
||||
PluginLog.Debug($"Failure redrawing object:\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,23 +117,23 @@ namespace Glamourer
|
|||
RedrawObject(actor, settings, false);
|
||||
}
|
||||
else
|
||||
PluginLog.Debug("Trying to redraw actor, but not attached to Penumbra.");
|
||||
PluginLog.Debug("Trying to redraw object, but not attached to Penumbra.");
|
||||
}
|
||||
|
||||
// Update actors without triggering PlayerWatcher Events,
|
||||
// Update objects without triggering PlayerWatcher Events,
|
||||
// then manually redraw using Penumbra.
|
||||
public void UpdateActors(Character actor, Character? gPoseOriginalActor = null)
|
||||
public void UpdateCharacters(Character character, Character? gPoseOriginalCharacter = null)
|
||||
{
|
||||
var newEquip = Glamourer.PlayerWatcher.UpdateActorWithoutEvent(actor);
|
||||
RedrawObject(actor, RedrawType.WithSettings, true);
|
||||
var newEquip = Glamourer.PlayerWatcher.UpdatePlayerWithoutEvent(character);
|
||||
RedrawObject(character, RedrawType.WithSettings, true);
|
||||
|
||||
// Special case for carrying over changes to the gPose actor to the regular player actor, too.
|
||||
if (gPoseOriginalActor == null)
|
||||
// Special case for carrying over changes to the gPose player to the regular player, too.
|
||||
if (gPoseOriginalCharacter == null)
|
||||
return;
|
||||
|
||||
newEquip.Write(gPoseOriginalActor.Address);
|
||||
Glamourer.PlayerWatcher.UpdateActorWithoutEvent(gPoseOriginalActor);
|
||||
RedrawObject(gPoseOriginalActor, RedrawType.AfterGPoseWithSettings, false);
|
||||
newEquip.Write(gPoseOriginalCharacter.Address);
|
||||
Glamourer.PlayerWatcher.UpdatePlayerWithoutEvent(gPoseOriginalCharacter);
|
||||
RedrawObject(gPoseOriginalCharacter, RedrawType.AfterGPoseWithSettings, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"Author": "Ottermandias",
|
||||
"Name": "Glamourer",
|
||||
"Description": "Adds functionality to change appearance of actors. Requires Penumbra to be installed and activated to work.",
|
||||
"Description": "Adds functionality to change appearance of players. Requires Penumbra to be installed and activated to work.",
|
||||
"InternalName": "Glamourer",
|
||||
"AssemblyVersion": "0.0.4.0",
|
||||
"TestingAssemblyVersion": "0.0.4.0",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue