mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
.
This commit is contained in:
parent
4cf082aa19
commit
1eb16b98a8
17 changed files with 735 additions and 497 deletions
|
|
@ -5,317 +5,304 @@ using Dalamud.Logging;
|
|||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Ipc;
|
||||
using System;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.State;
|
||||
using Penumbra.Api.Enums;
|
||||
|
||||
namespace Glamourer.Api;
|
||||
namespace Glamourer;
|
||||
|
||||
public class GlamourerIpc : IDisposable
|
||||
public partial class Glamourer
|
||||
{
|
||||
public const int CurrentApiVersion = 0;
|
||||
public const string LabelProviderApiVersion = "Glamourer.ApiVersion";
|
||||
public const string LabelProviderGetAllCustomization = "Glamourer.GetAllCustomization";
|
||||
public const string LabelProviderGetAllCustomizationFromCharacter = "Glamourer.GetAllCustomizationFromCharacter";
|
||||
public const string LabelProviderApplyAll = "Glamourer.ApplyAll";
|
||||
public const string LabelProviderApplyAllToCharacter = "Glamourer.ApplyAllToCharacter";
|
||||
public const string LabelProviderApplyOnlyEquipment = "Glamourer.ApplyOnlyEquipment";
|
||||
public const string LabelProviderApplyOnlyEquipmentToCharacter = "Glamourer.ApplyOnlyEquipmentToCharacter";
|
||||
public const string LabelProviderApplyOnlyCustomization = "Glamourer.ApplyOnlyCustomization";
|
||||
public const string LabelProviderApplyOnlyCustomizationToCharacter = "Glamourer.ApplyOnlyCustomizationToCharacter";
|
||||
public const string LabelProviderRevert = "Glamourer.Revert";
|
||||
public const string LabelProviderRevertCharacter = "Glamourer.RevertCharacter";
|
||||
|
||||
private readonly ClientState _clientState;
|
||||
private readonly ObjectTable _objectTable;
|
||||
private readonly DalamudPluginInterface _pluginInterface;
|
||||
|
||||
internal ICallGateProvider<string, string?>? ProviderGetAllCustomization;
|
||||
internal ICallGateProvider<Character?, string?>? ProviderGetAllCustomizationFromCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyAll;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyAllToCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyOnlyCustomization;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyOnlyCustomizationToCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyOnlyEquipment;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyOnlyEquipmentToCharacter;
|
||||
internal ICallGateProvider<string, object>? ProviderRevert;
|
||||
internal ICallGateProvider<Character?, object>? ProviderRevertCharacter;
|
||||
internal ICallGateProvider<int>? ProviderGetApiVersion;
|
||||
|
||||
public GlamourerIpc(ClientState clientState, ObjectTable objectTable, DalamudPluginInterface pluginInterface)
|
||||
public class GlamourerIpc : IDisposable
|
||||
{
|
||||
_clientState = clientState;
|
||||
_objectTable = objectTable;
|
||||
_pluginInterface = pluginInterface;
|
||||
public const int CurrentApiVersion = 0;
|
||||
public const string LabelProviderApiVersion = "Glamourer.ApiVersion";
|
||||
public const string LabelProviderGetAllCustomization = "Glamourer.GetAllCustomization";
|
||||
public const string LabelProviderGetAllCustomizationFromCharacter = "Glamourer.GetAllCustomizationFromCharacter";
|
||||
public const string LabelProviderApplyAll = "Glamourer.ApplyAll";
|
||||
public const string LabelProviderApplyAllToCharacter = "Glamourer.ApplyAllToCharacter";
|
||||
public const string LabelProviderApplyOnlyEquipment = "Glamourer.ApplyOnlyEquipment";
|
||||
public const string LabelProviderApplyOnlyEquipmentToCharacter = "Glamourer.ApplyOnlyEquipmentToCharacter";
|
||||
public const string LabelProviderApplyOnlyCustomization = "Glamourer.ApplyOnlyCustomization";
|
||||
public const string LabelProviderApplyOnlyCustomizationToCharacter = "Glamourer.ApplyOnlyCustomizationToCharacter";
|
||||
public const string LabelProviderRevert = "Glamourer.Revert";
|
||||
public const string LabelProviderRevertCharacter = "Glamourer.RevertCharacter";
|
||||
|
||||
InitializeProviders();
|
||||
}
|
||||
private readonly ObjectTable _objectTable;
|
||||
private readonly DalamudPluginInterface _pluginInterface;
|
||||
private readonly Glamourer _glamourer;
|
||||
|
||||
public void Dispose()
|
||||
=> DisposeProviders();
|
||||
internal ICallGateProvider<string, string?>? ProviderGetAllCustomization;
|
||||
internal ICallGateProvider<Character?, string?>? ProviderGetAllCustomizationFromCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyAll;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyAllToCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyOnlyCustomization;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyOnlyCustomizationToCharacter;
|
||||
internal ICallGateProvider<string, string, object>? ProviderApplyOnlyEquipment;
|
||||
internal ICallGateProvider<string, Character?, object>? ProviderApplyOnlyEquipmentToCharacter;
|
||||
internal ICallGateProvider<string, object>? ProviderRevert;
|
||||
internal ICallGateProvider<Character?, object>? ProviderRevertCharacter;
|
||||
internal ICallGateProvider<int>? ProviderGetApiVersion;
|
||||
|
||||
private void DisposeProviders()
|
||||
{
|
||||
ProviderGetAllCustomization?.UnregisterFunc();
|
||||
ProviderGetAllCustomizationFromCharacter?.UnregisterFunc();
|
||||
ProviderApplyAll?.UnregisterAction();
|
||||
ProviderApplyAllToCharacter?.UnregisterAction();
|
||||
ProviderApplyOnlyCustomization?.UnregisterAction();
|
||||
ProviderApplyOnlyCustomizationToCharacter?.UnregisterAction();
|
||||
ProviderApplyOnlyEquipment?.UnregisterAction();
|
||||
ProviderApplyOnlyEquipmentToCharacter?.UnregisterAction();
|
||||
ProviderRevert?.UnregisterAction();
|
||||
ProviderRevertCharacter?.UnregisterAction();
|
||||
ProviderGetApiVersion?.UnregisterFunc();
|
||||
}
|
||||
|
||||
private void InitializeProviders()
|
||||
{
|
||||
try
|
||||
public GlamourerIpc(Glamourer glamourer, ClientState clientState, ObjectTable objectTable,
|
||||
DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
ProviderGetApiVersion = _pluginInterface.GetIpcProvider<int>(LabelProviderApiVersion);
|
||||
ProviderGetApiVersion.RegisterFunc(GetApiVersion);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApiVersion}.");
|
||||
}
|
||||
|
||||
//try
|
||||
//{
|
||||
// ProviderGetAllCustomization = _pluginInterface.GetIpcProvider<string, string?>(LabelProviderGetAllCustomization);
|
||||
// ProviderGetAllCustomization.RegisterFunc(GetAllCustomization);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderGetAllCustomizationFromCharacter = _pluginInterface.GetIpcProvider<Character?, string?>(LabelProviderGetAllCustomizationFromCharacter);
|
||||
// ProviderGetAllCustomizationFromCharacter.RegisterFunc(GetAllCustomization);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderGetAllCustomizationFromCharacter}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyAll =
|
||||
// _pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyAll);
|
||||
// ProviderApplyAll.RegisterAction(ApplyAll);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyAll}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyAllToCharacter =
|
||||
// _pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyAllToCharacter);
|
||||
// ProviderApplyAllToCharacter.RegisterAction(ApplyAll);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyAll}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyOnlyCustomization =
|
||||
// _pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyOnlyCustomization);
|
||||
// ProviderApplyOnlyCustomization.RegisterAction(ApplyOnlyCustomization);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyCustomization}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyOnlyCustomizationToCharacter =
|
||||
// _pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyOnlyCustomizationToCharacter);
|
||||
// ProviderApplyOnlyCustomizationToCharacter.RegisterAction(ApplyOnlyCustomization);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyCustomization}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyOnlyEquipment =
|
||||
// _pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyOnlyEquipment);
|
||||
// ProviderApplyOnlyEquipment.RegisterAction(ApplyOnlyEquipment);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderApplyOnlyEquipmentToCharacter =
|
||||
// _pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyOnlyEquipmentToCharacter);
|
||||
// ProviderApplyOnlyEquipmentToCharacter.RegisterAction(ApplyOnlyEquipment);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderRevert =
|
||||
// _pluginInterface.GetIpcProvider<string, object>(LabelProviderRevert);
|
||||
// ProviderRevert.RegisterAction(Revert);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderRevert}.");
|
||||
//}
|
||||
//
|
||||
//try
|
||||
//{
|
||||
// ProviderRevertCharacter =
|
||||
// _pluginInterface.GetIpcProvider<Character?, object>(LabelProviderRevertCharacter);
|
||||
// ProviderRevertCharacter.RegisterAction(Revert);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderRevert}.");
|
||||
//}
|
||||
}
|
||||
_glamourer = glamourer;
|
||||
_objectTable = objectTable;
|
||||
_pluginInterface = pluginInterface;
|
||||
|
||||
private static int GetApiVersion()
|
||||
=> CurrentApiVersion;
|
||||
//
|
||||
//private void ApplyAll(string customization, string characterName)
|
||||
//{
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// foreach (var gameObject in _objectTable)
|
||||
// {
|
||||
// if (gameObject.Name.ToString() != characterName)
|
||||
// continue;
|
||||
//
|
||||
// var player = (Character)gameObject;
|
||||
// Glamourer.RevertableDesigns.Revert(player);
|
||||
// save.Apply(player);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, null);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private void ApplyAll(string customization, Character? character)
|
||||
//{
|
||||
// if (character == null)
|
||||
// return;
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// Glamourer.RevertableDesigns.Revert(character);
|
||||
// save.Apply(character);
|
||||
// Glamourer.Penumbra.UpdateCharacters(character, null);
|
||||
//}
|
||||
//
|
||||
//private void ApplyOnlyCustomization(string customization, string characterName)
|
||||
//{
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// foreach (var gameObject in _objectTable)
|
||||
// {
|
||||
// if (gameObject.Name.ToString() != characterName)
|
||||
// continue;
|
||||
//
|
||||
// var player = (Character)gameObject;
|
||||
// Glamourer.RevertableDesigns.Revert(player);
|
||||
// save.ApplyOnlyCustomizations(player);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, null);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private void ApplyOnlyCustomization(string customization, Character? character)
|
||||
//{
|
||||
// if (character == null)
|
||||
// return;
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// Glamourer.RevertableDesigns.Revert(character);
|
||||
// save.ApplyOnlyCustomizations(character);
|
||||
// Glamourer.Penumbra.UpdateCharacters(character, null);
|
||||
//}
|
||||
//
|
||||
//private void ApplyOnlyEquipment(string customization, string characterName)
|
||||
//{
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// foreach (var gameObject in _objectTable)
|
||||
// {
|
||||
// if (gameObject.Name.ToString() != characterName)
|
||||
// continue;
|
||||
//
|
||||
// var player = (Character)gameObject;
|
||||
// Glamourer.RevertableDesigns.Revert(player);
|
||||
// save.ApplyOnlyEquipment(player);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, null);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//private void ApplyOnlyEquipment(string customization, Character? character)
|
||||
//{
|
||||
// if (character == null)
|
||||
// return;
|
||||
// var save = CharacterSave.FromString(customization);
|
||||
// Glamourer.RevertableDesigns.Revert(character);
|
||||
// save.ApplyOnlyEquipment(character);
|
||||
// Glamourer.Penumbra.UpdateCharacters(character, null);
|
||||
//}
|
||||
//
|
||||
//private void Revert(string characterName)
|
||||
//{
|
||||
// foreach (var gameObject in _objectTable)
|
||||
// {
|
||||
// if (gameObject.Name.ToString() != characterName)
|
||||
// continue;
|
||||
//
|
||||
// var player = (Character)gameObject;
|
||||
// Glamourer.RevertableDesigns.Revert(player);
|
||||
// Glamourer.Penumbra.UpdateCharacters(player, null);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Glamourer.RevertableDesigns.RevertByNameWithoutApplication(characterName);
|
||||
//}
|
||||
//
|
||||
//private void Revert(Character? character)
|
||||
//{
|
||||
// if (character == null)
|
||||
// return;
|
||||
// Glamourer.RevertableDesigns.Revert(character);
|
||||
// Glamourer.Penumbra.UpdateCharacters(character, null);
|
||||
//}
|
||||
//
|
||||
//private string? GetAllCustomization(Character? character)
|
||||
//{
|
||||
// if (character == null)
|
||||
// return null;
|
||||
//
|
||||
// CharacterSave save = new CharacterSave();
|
||||
// save.LoadCharacter(character);
|
||||
// return save.ToBase64();
|
||||
//}
|
||||
//
|
||||
//private string? GetAllCustomization(string characterName)
|
||||
//{
|
||||
// CharacterSave save = null!;
|
||||
// foreach (var gameObject in _objectTable)
|
||||
// {
|
||||
// if (gameObject.Name.ToString() != characterName)
|
||||
// continue;
|
||||
//
|
||||
// var player = (Character)gameObject;
|
||||
// save = new CharacterSave();
|
||||
// save.LoadCharacter(player);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// return save?.ToBase64() ?? null;
|
||||
//}
|
||||
InitializeProviders();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
=> DisposeProviders();
|
||||
|
||||
private void DisposeProviders()
|
||||
{
|
||||
ProviderGetAllCustomization?.UnregisterFunc();
|
||||
ProviderGetAllCustomizationFromCharacter?.UnregisterFunc();
|
||||
ProviderApplyAll?.UnregisterAction();
|
||||
ProviderApplyAllToCharacter?.UnregisterAction();
|
||||
ProviderApplyOnlyCustomization?.UnregisterAction();
|
||||
ProviderApplyOnlyCustomizationToCharacter?.UnregisterAction();
|
||||
ProviderApplyOnlyEquipment?.UnregisterAction();
|
||||
ProviderApplyOnlyEquipmentToCharacter?.UnregisterAction();
|
||||
ProviderRevert?.UnregisterAction();
|
||||
ProviderRevertCharacter?.UnregisterAction();
|
||||
ProviderGetApiVersion?.UnregisterFunc();
|
||||
}
|
||||
|
||||
private void InitializeProviders()
|
||||
{
|
||||
try
|
||||
{
|
||||
ProviderGetApiVersion = _pluginInterface.GetIpcProvider<int>(LabelProviderApiVersion);
|
||||
ProviderGetApiVersion.RegisterFunc(GetApiVersion);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApiVersion}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderGetAllCustomization = _pluginInterface.GetIpcProvider<string, string?>(LabelProviderGetAllCustomization);
|
||||
ProviderGetAllCustomization.RegisterFunc(GetAllCustomization);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderGetAllCustomizationFromCharacter =
|
||||
_pluginInterface.GetIpcProvider<Character?, string?>(LabelProviderGetAllCustomizationFromCharacter);
|
||||
ProviderGetAllCustomizationFromCharacter.RegisterFunc(GetAllCustomization);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderGetAllCustomizationFromCharacter}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyAll =
|
||||
_pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyAll);
|
||||
ProviderApplyAll.RegisterAction(ApplyAll);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyAll}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyAllToCharacter =
|
||||
_pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyAllToCharacter);
|
||||
ProviderApplyAllToCharacter.RegisterAction(ApplyAll);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyAll}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyOnlyCustomization =
|
||||
_pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyOnlyCustomization);
|
||||
ProviderApplyOnlyCustomization.RegisterAction(ApplyOnlyCustomization);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyCustomization}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyOnlyCustomizationToCharacter =
|
||||
_pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyOnlyCustomizationToCharacter);
|
||||
ProviderApplyOnlyCustomizationToCharacter.RegisterAction(ApplyOnlyCustomization);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyCustomization}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyOnlyEquipment =
|
||||
_pluginInterface.GetIpcProvider<string, string, object>(LabelProviderApplyOnlyEquipment);
|
||||
ProviderApplyOnlyEquipment.RegisterAction(ApplyOnlyEquipment);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderApplyOnlyEquipmentToCharacter =
|
||||
_pluginInterface.GetIpcProvider<string, Character?, object>(LabelProviderApplyOnlyEquipmentToCharacter);
|
||||
ProviderApplyOnlyEquipmentToCharacter.RegisterAction(ApplyOnlyEquipment);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderApplyOnlyEquipment}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderRevert =
|
||||
_pluginInterface.GetIpcProvider<string, object>(LabelProviderRevert);
|
||||
ProviderRevert.RegisterAction(Revert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderRevert}.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ProviderRevertCharacter =
|
||||
_pluginInterface.GetIpcProvider<Character?, object>(LabelProviderRevertCharacter);
|
||||
ProviderRevertCharacter.RegisterAction(Revert);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Error registering IPC provider for {LabelProviderRevert}.");
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetApiVersion()
|
||||
=> CurrentApiVersion;
|
||||
|
||||
private void ApplyAll(string customization, string characterName)
|
||||
{
|
||||
foreach (var gameObject in _objectTable)
|
||||
{
|
||||
if (gameObject.Name.ToString() == characterName)
|
||||
{
|
||||
ApplyAll(customization, gameObject as Character);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyAll(string customization, Character? character)
|
||||
{
|
||||
if (character == null)
|
||||
return;
|
||||
|
||||
var design = Design.CreateTemporaryFromBase64(customization, true, true);
|
||||
var active = _glamourer._stateManager.GetOrCreateSave(character.Address);
|
||||
_glamourer._stateManager.ApplyDesign(active, design, false);
|
||||
}
|
||||
|
||||
private void ApplyOnlyCustomization(string customization, string characterName)
|
||||
{
|
||||
foreach (var gameObject in _objectTable)
|
||||
{
|
||||
if (gameObject.Name.ToString() == characterName)
|
||||
{
|
||||
ApplyOnlyCustomization(customization, gameObject as Character);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyOnlyCustomization(string customization, Character? character)
|
||||
{
|
||||
if (character == null)
|
||||
return;
|
||||
var design = Design.CreateTemporaryFromBase64(customization, true, false);
|
||||
var active = _glamourer._stateManager.GetOrCreateSave(character.Address);
|
||||
_glamourer._stateManager.ApplyDesign(active, design, false);
|
||||
}
|
||||
|
||||
private void ApplyOnlyEquipment(string customization, string characterName)
|
||||
{
|
||||
foreach (var gameObject in _objectTable)
|
||||
{
|
||||
if (gameObject.Name.ToString() == characterName)
|
||||
{
|
||||
ApplyOnlyEquipment(customization, gameObject as Character);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyOnlyEquipment(string customization, Character? character)
|
||||
{
|
||||
if (character == null)
|
||||
return;
|
||||
var design = Design.CreateTemporaryFromBase64(customization, false, true);
|
||||
var active = _glamourer._stateManager.GetOrCreateSave(character.Address);
|
||||
_glamourer._stateManager.ApplyDesign(active, design, false);
|
||||
}
|
||||
|
||||
private void Revert(string characterName)
|
||||
{
|
||||
foreach (var gameObject in _objectTable)
|
||||
{
|
||||
if (gameObject.Name.ToString() != characterName)
|
||||
continue;
|
||||
|
||||
Revert(gameObject as Character);
|
||||
}
|
||||
}
|
||||
|
||||
private void Revert(Character? character)
|
||||
{
|
||||
if (character == null)
|
||||
return;
|
||||
|
||||
var ident = Actors.FromObject(character, true, false, false);
|
||||
_glamourer._stateManager.DeleteSave(ident);
|
||||
_glamourer._penumbra.RedrawObject(character.Address, RedrawType.Redraw);
|
||||
}
|
||||
|
||||
private string? GetAllCustomization(Character? character)
|
||||
{
|
||||
if (character == null)
|
||||
return null;
|
||||
|
||||
var ident = Actors.FromObject(character, true, false, false);
|
||||
if (!_glamourer._stateManager.TryGetValue(ident, out var design))
|
||||
design = new ActiveDesign(ident, character.Address);
|
||||
|
||||
return design.CreateOldBase64();
|
||||
}
|
||||
|
||||
private string? GetAllCustomization(string characterName)
|
||||
{
|
||||
foreach (var gameObject in _objectTable)
|
||||
{
|
||||
if (gameObject.Name.ToString() == characterName)
|
||||
return GetAllCustomization(gameObject as Character);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,50 +21,50 @@ public partial class Design : DesignBase
|
|||
public string[] Tags { get; private set; } = Array.Empty<string>();
|
||||
public int Index { get; private set; }
|
||||
|
||||
private EquipFlag _applyEquip;
|
||||
private CustomizeFlag _applyCustomize;
|
||||
public QuadBool Wetness { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Visor { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Hat { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Weapon { get; private set; } = QuadBool.NullFalse;
|
||||
public bool WriteProtected { get; private set; }
|
||||
public EquipFlag ApplyEquip { get; private set; }
|
||||
public CustomizeFlag ApplyCustomize { get; private set; }
|
||||
public QuadBool Wetness { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Visor { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Hat { get; private set; } = QuadBool.NullFalse;
|
||||
public QuadBool Weapon { get; private set; } = QuadBool.NullFalse;
|
||||
public bool WriteProtected { get; private set; }
|
||||
|
||||
public bool DoApplyEquip(EquipSlot slot)
|
||||
=> _applyEquip.HasFlag(slot.ToFlag());
|
||||
=> ApplyEquip.HasFlag(slot.ToFlag());
|
||||
|
||||
public bool DoApplyStain(EquipSlot slot)
|
||||
=> _applyEquip.HasFlag(slot.ToStainFlag());
|
||||
=> ApplyEquip.HasFlag(slot.ToStainFlag());
|
||||
|
||||
public bool DoApplyCustomize(CustomizeIndex idx)
|
||||
=> _applyCustomize.HasFlag(idx.ToFlag());
|
||||
=> ApplyCustomize.HasFlag(idx.ToFlag());
|
||||
|
||||
private bool SetApplyEquip(EquipSlot slot, bool value)
|
||||
{
|
||||
var newValue = value ? _applyEquip | slot.ToFlag() : _applyEquip & ~slot.ToFlag();
|
||||
if (newValue == _applyEquip)
|
||||
var newValue = value ? ApplyEquip | slot.ToFlag() : ApplyEquip & ~slot.ToFlag();
|
||||
if (newValue == ApplyEquip)
|
||||
return false;
|
||||
|
||||
_applyEquip = newValue;
|
||||
ApplyEquip = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetApplyStain(EquipSlot slot, bool value)
|
||||
{
|
||||
var newValue = value ? _applyEquip | slot.ToStainFlag() : _applyEquip & ~slot.ToStainFlag();
|
||||
if (newValue == _applyEquip)
|
||||
var newValue = value ? ApplyEquip | slot.ToStainFlag() : ApplyEquip & ~slot.ToStainFlag();
|
||||
if (newValue == ApplyEquip)
|
||||
return false;
|
||||
|
||||
_applyEquip = newValue;
|
||||
ApplyEquip = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetApplyCustomize(CustomizeIndex idx, bool value)
|
||||
{
|
||||
var newValue = value ? _applyCustomize | idx.ToFlag() : _applyCustomize & ~idx.ToFlag();
|
||||
if (newValue == _applyCustomize)
|
||||
var newValue = value ? ApplyCustomize | idx.ToFlag() : ApplyCustomize & ~idx.ToFlag();
|
||||
if (newValue == ApplyCustomize)
|
||||
return false;
|
||||
|
||||
_applyCustomize = newValue;
|
||||
ApplyCustomize = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,8 @@ public partial class Design : DesignBase
|
|||
{
|
||||
[nameof(MainHand)] =
|
||||
Serialize(MainHand, CharacterData.MainHand.Stain, DoApplyEquip(EquipSlot.MainHand), DoApplyStain(EquipSlot.MainHand)),
|
||||
[nameof(OffHand)] = Serialize(OffHand, CharacterData.OffHand.Stain, DoApplyEquip(EquipSlot.OffHand), DoApplyStain(EquipSlot.OffHand)),
|
||||
[nameof(OffHand)] = Serialize(OffHand, CharacterData.OffHand.Stain, DoApplyEquip(EquipSlot.OffHand),
|
||||
DoApplyStain(EquipSlot.OffHand)),
|
||||
};
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
|
|
@ -258,82 +259,41 @@ public partial class Design : DesignBase
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void MigrateBase64(string base64)
|
||||
{
|
||||
static void CheckSize(int length, int requiredLength)
|
||||
{
|
||||
if (length != requiredLength)
|
||||
throw new Exception(
|
||||
$"Can not parse Base64 string into CharacterSave:\n\tInvalid size {length} instead of {requiredLength}.");
|
||||
}
|
||||
|
||||
var bytes = Convert.FromBase64String(base64);
|
||||
|
||||
byte applicationFlags;
|
||||
ushort equipFlags;
|
||||
|
||||
switch (bytes[0])
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CheckSize(bytes.Length, 86);
|
||||
applicationFlags = bytes[1];
|
||||
equipFlags = BitConverter.ToUInt16(bytes, 2);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
CheckSize(bytes.Length, 91);
|
||||
applicationFlags = bytes[1];
|
||||
equipFlags = BitConverter.ToUInt16(bytes, 2);
|
||||
Hat = Hat.SetValue((bytes[90] & 0x01) == 0);
|
||||
Visor = Visor.SetValue((bytes[90] & 0x10) != 0);
|
||||
Weapon = Weapon.SetValue((bytes[90] & 0x02) == 0);
|
||||
break;
|
||||
}
|
||||
default: throw new Exception($"Can not parse Base64 string into design for migration:\n\tInvalid Version {bytes[0]}.");
|
||||
}
|
||||
|
||||
_applyCustomize = (applicationFlags & 0x01) != 0 ? CustomizeFlagExtensions.All : 0;
|
||||
Wetness = (applicationFlags & 0x02) != 0 ? QuadBool.True : QuadBool.NullFalse;
|
||||
Hat = Hat.SetEnabled((applicationFlags & 0x04) != 0);
|
||||
Weapon = Weapon.SetEnabled((applicationFlags & 0x08) != 0);
|
||||
Visor = Visor.SetEnabled((applicationFlags & 0x10) != 0);
|
||||
WriteProtected = (applicationFlags & 0x20) != 0;
|
||||
|
||||
CharacterData.ModelId = 0;
|
||||
|
||||
SetApplyEquip(EquipSlot.MainHand, (equipFlags & 0x0001) != 0);
|
||||
SetApplyEquip(EquipSlot.OffHand, (equipFlags & 0x0002) != 0);
|
||||
SetApplyStain(EquipSlot.MainHand, (equipFlags & 0x0001) != 0);
|
||||
SetApplyStain(EquipSlot.OffHand, (equipFlags & 0x0002) != 0);
|
||||
var flag = 0x0002u;
|
||||
var data = MigrateBase64(base64, out var applyEquip, out var applyCustomize, out var writeProtected, out var wet, out var hat,
|
||||
out var visor, out var weapon);
|
||||
UpdateMainhand(data.MainHand);
|
||||
UpdateMainhand(data.OffHand);
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
flag <<= 1;
|
||||
var apply = (equipFlags & flag) != 0;
|
||||
SetApplyEquip(slot, apply);
|
||||
SetApplyStain(slot, apply);
|
||||
}
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = bytes)
|
||||
{
|
||||
CharacterData.CustomizeData.Read(ptr + 4);
|
||||
var cur = (CharacterWeapon*)(ptr + 30);
|
||||
|
||||
UpdateMainhand(cur[0]);
|
||||
SetStain(EquipSlot.MainHand, cur[0].Stain);
|
||||
UpdateOffhand(cur[1]);
|
||||
SetStain(EquipSlot.OffHand, cur[1].Stain);
|
||||
var eq = (CharacterArmor*)(cur + 2);
|
||||
foreach (var (slot, idx) in EquipSlotExtensions.EqdpSlots.WithIndex())
|
||||
{
|
||||
UpdateArmor(slot, eq[idx], true);
|
||||
SetStain(slot, eq[idx].Stain);
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateArmor(slot, data.Equipment[slot], true);
|
||||
CharacterData.CustomizeData = data.CustomizeData;
|
||||
ApplyEquip = applyEquip;
|
||||
ApplyCustomize = applyCustomize;
|
||||
WriteProtected = writeProtected;
|
||||
Wetness = wet;
|
||||
Hat = hat;
|
||||
Visor = visor;
|
||||
Weapon = weapon;
|
||||
}
|
||||
|
||||
public static Design CreateTemporaryFromBase64(string base64, bool customize, bool equip)
|
||||
{
|
||||
var ret = new Design();
|
||||
ret.MigrateBase64(base64);
|
||||
if (!customize)
|
||||
ret.ApplyCustomize = 0;
|
||||
if (!equip)
|
||||
ret.ApplyEquip = 0;
|
||||
ret.Wetness = ret.Wetness.SetEnabled(customize);
|
||||
ret.Visor = ret.Visor.SetEnabled(equip);
|
||||
ret.Hat = ret.Hat.SetEnabled(equip);
|
||||
ret.Weapon = ret.Weapon.SetEnabled(equip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Outdated.
|
||||
public string CreateOldBase64()
|
||||
=> CreateOldBase64(in CharacterData, ApplyEquip, ApplyCustomize, Wetness == QuadBool.True, Hat.ForcedValue, Hat.Enabled,
|
||||
Visor.ForcedValue, Visor.Enabled, Weapon.ForcedValue, Weapon.Enabled, WriteProtected, 1f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Util;
|
||||
using OtterGui.Classes;
|
||||
using OtterGui;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
|
||||
|
|
@ -74,11 +76,12 @@ public class DesignBase
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
public Weapon WeaponMain
|
||||
=> new(MainhandName, MainHand, CharacterData.MainHand, MainhandType);
|
||||
|
||||
public Weapon WeaponOff
|
||||
=> Designs.Weapon.Offhand(OffhandName, OffHand, CharacterData.OffHand, MainhandType);
|
||||
=> Weapon.Offhand(OffhandName, OffHand, CharacterData.OffHand, MainhandType);
|
||||
|
||||
public CustomizeValue GetCustomize(CustomizeIndex idx)
|
||||
=> Customize()[idx];
|
||||
|
|
@ -108,7 +111,6 @@ public class DesignBase
|
|||
protected bool UpdateArmor(EquipSlot slot, CharacterArmor armor, bool force)
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
switch (slot)
|
||||
{
|
||||
case EquipSlot.Head when CharacterData.Head.Value == armor.Value: return false;
|
||||
|
|
@ -122,7 +124,6 @@ public class DesignBase
|
|||
case EquipSlot.RFinger when CharacterData.RFinger.Value == armor.Value: return false;
|
||||
case EquipSlot.LFinger when CharacterData.LFinger.Value == armor.Value: return false;
|
||||
}
|
||||
}
|
||||
|
||||
var (valid, id, name) = Glamourer.Items.Identify(slot, armor.Set, armor.Variant);
|
||||
if (!valid)
|
||||
|
|
@ -329,4 +330,123 @@ public class DesignBase
|
|||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected const int Base64Size = 89;
|
||||
|
||||
public static CharacterData MigrateBase64(string base64, out EquipFlag equipFlags, out CustomizeFlag customizeFlags,
|
||||
out bool writeProtected, out QuadBool wet, out QuadBool hat, out QuadBool visor, out QuadBool weapon)
|
||||
{
|
||||
static void CheckSize(int length, int requiredLength)
|
||||
{
|
||||
if (length != requiredLength)
|
||||
throw new Exception(
|
||||
$"Can not parse Base64 string into CharacterSave:\n\tInvalid size {length} instead of {requiredLength}.");
|
||||
}
|
||||
|
||||
byte applicationFlags;
|
||||
ushort equipFlagsS;
|
||||
var bytes = Convert.FromBase64String(base64);
|
||||
hat = QuadBool.Null;
|
||||
visor = QuadBool.Null;
|
||||
weapon = QuadBool.Null;
|
||||
switch (bytes[0])
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
CheckSize(bytes.Length, 86);
|
||||
applicationFlags = bytes[1];
|
||||
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
CheckSize(bytes.Length, Base64Size);
|
||||
applicationFlags = bytes[1];
|
||||
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||
hat = hat.SetValue((bytes[90] & 0x01) == 0);
|
||||
visor = visor.SetValue((bytes[90] & 0x10) != 0);
|
||||
weapon = weapon.SetValue((bytes[90] & 0x02) == 0);
|
||||
break;
|
||||
}
|
||||
default: throw new Exception($"Can not parse Base64 string into design for migration:\n\tInvalid Version {bytes[0]}.");
|
||||
}
|
||||
|
||||
customizeFlags = (applicationFlags & 0x01) != 0 ? CustomizeFlagExtensions.All : 0;
|
||||
wet = (applicationFlags & 0x02) != 0 ? QuadBool.True : QuadBool.NullFalse;
|
||||
hat = hat.SetEnabled((applicationFlags & 0x04) != 0);
|
||||
weapon = weapon.SetEnabled((applicationFlags & 0x08) != 0);
|
||||
visor = visor.SetEnabled((applicationFlags & 0x10) != 0);
|
||||
writeProtected = (applicationFlags & 0x20) != 0;
|
||||
|
||||
equipFlags = 0;
|
||||
equipFlags |= (equipFlagsS & 0x0001) != 0 ? EquipFlag.Mainhand | EquipFlag.MainhandStain : 0;
|
||||
equipFlags |= (equipFlagsS & 0x0002) != 0 ? EquipFlag.Offhand | EquipFlag.OffhandStain : 0;
|
||||
var flag = 0x0002u;
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
flag <<= 1;
|
||||
equipFlags |= (equipFlagsS & flag) != 0 ? slot.ToFlag() | slot.ToStainFlag() : 0;
|
||||
}
|
||||
|
||||
var data = new CharacterData();
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = bytes)
|
||||
{
|
||||
data.CustomizeData.Read(ptr + 4);
|
||||
var cur = (CharacterWeapon*)(ptr + 30);
|
||||
data.MainHand = cur[0];
|
||||
data.OffHand = cur[1];
|
||||
var eq = (CharacterArmor*)(cur + 2);
|
||||
foreach (var (slot, idx) in EquipSlotExtensions.EqdpSlots.WithIndex())
|
||||
data.Equipment[slot] = eq[idx];
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static unsafe string CreateOldBase64(in CharacterData save, EquipFlag equipFlags, CustomizeFlag customizeFlags, bool wet, bool hat,
|
||||
bool setHat, bool visor, bool setVisor, bool weapon, bool setWeapon, bool writeProtected, float alpha)
|
||||
{
|
||||
var data = stackalloc byte[Base64Size];
|
||||
data[0] = 2;
|
||||
data[1] = (byte)((customizeFlags == CustomizeFlagExtensions.All ? 0x01 : 0)
|
||||
| (wet ? 0x02 : 0)
|
||||
| (setHat ? 0x04 : 0)
|
||||
| (setWeapon ? 0x08 : 0)
|
||||
| (setVisor ? 0x10 : 0)
|
||||
| (writeProtected ? 0x20 : 0));
|
||||
data[2] = (byte)((equipFlags.HasFlag(EquipFlag.Mainhand) ? 0x01 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Offhand) ? 0x02 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Head) ? 0x04 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Body) ? 0x08 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Hands) ? 0x10 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Legs) ? 0x20 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Feet) ? 0x40 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Ears) ? 0x80 : 0));
|
||||
data[3] = (byte)((equipFlags.HasFlag(EquipFlag.Neck) ? 0x01 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.Wrist) ? 0x02 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.RFinger) ? 0x04 : 0)
|
||||
| (equipFlags.HasFlag(EquipFlag.LFinger) ? 0x08 : 0));
|
||||
save.CustomizeData.Write(data + 4);
|
||||
((CharacterWeapon*)(data + 30))[0] = save.MainHand;
|
||||
((CharacterWeapon*)(data + 30))[1] = save.OffHand;
|
||||
((CharacterArmor*)(data + 44))[0] = save.Head;
|
||||
((CharacterArmor*)(data + 44))[1] = save.Body;
|
||||
((CharacterArmor*)(data + 44))[2] = save.Hands;
|
||||
((CharacterArmor*)(data + 44))[3] = save.Legs;
|
||||
((CharacterArmor*)(data + 44))[4] = save.Feet;
|
||||
((CharacterArmor*)(data + 44))[5] = save.Ears;
|
||||
((CharacterArmor*)(data + 44))[6] = save.Neck;
|
||||
((CharacterArmor*)(data + 44))[7] = save.Wrists;
|
||||
((CharacterArmor*)(data + 44))[8] = save.RFinger;
|
||||
((CharacterArmor*)(data + 44))[9] = save.LFinger;
|
||||
*(float*)(data + 84) = 1f;
|
||||
data[88] = (byte)((hat ? 0x01 : 0)
|
||||
| (visor ? 0x10 : 0)
|
||||
| (weapon ? 0x02 : 0));
|
||||
|
||||
return Convert.ToBase64String(new Span<byte>(data, Base64Size));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ public enum EquipFlag : uint
|
|||
|
||||
public static class EquipFlagExtensions
|
||||
{
|
||||
public const EquipFlag All = (EquipFlag)(((uint)EquipFlag.OffhandStain << 1) - 1);
|
||||
|
||||
public static EquipFlag ToFlag(this EquipSlot slot)
|
||||
=> slot switch
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class DrawObjectManager : IDisposable
|
|||
private void FixEquipment(DrawObject drawObject, EquipSlot slot, ref CharacterArmor item)
|
||||
{
|
||||
var customize = drawObject.Customize;
|
||||
var (changed, newArmor) = _items.RestrictedGear.ResolveRestricted(item, slot, customize.Race, customize.Gender);
|
||||
var (changed, newArmor) = _items.ResolveRestrictedGear(item, slot, customize.Race, customize.Gender);
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ public class DrawObjectManager : IDisposable
|
|||
if (gameObject.ModelId != modelId)
|
||||
return;
|
||||
|
||||
var identifier = _actors.FromObject((GameObject*)gameObjectPtr, out _, true, true);
|
||||
var identifier = _actors.FromObject((GameObject*)gameObjectPtr, out _, true, true, false);
|
||||
if (!identifier.IsValid || !_manager.TryGetValue(identifier, out var design))
|
||||
return;
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ public class DrawObjectManager : IDisposable
|
|||
foreach (var slot in EquipSlotExtensions.EquipmentSlots)
|
||||
{
|
||||
(_, equip[slot]) =
|
||||
Glamourer.Items.RestrictedGear.ResolveRestricted(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
Glamourer.Items.ResolveRestrictedGear(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using System.Reflection;
|
|||
using Dalamud.Game.Command;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using Dalamud.Plugin;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using Glamourer.Api;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
|
|
@ -19,7 +18,7 @@ using FixedDesigns = Glamourer.State.FixedDesigns;
|
|||
|
||||
namespace Glamourer;
|
||||
|
||||
public class Glamourer : IDalamudPlugin
|
||||
public partial class Glamourer : IDalamudPlugin
|
||||
{
|
||||
private const string HelpString = "[Copy|Apply|Save],[Name or PlaceHolder],<Name for Save>";
|
||||
private const string MainCommandString = "/glamourer";
|
||||
|
|
@ -56,15 +55,14 @@ public class Glamourer : IDalamudPlugin
|
|||
//public readonly DesignManager Designs;
|
||||
|
||||
//public static RevertableDesigns RevertableDesigns = new();
|
||||
//public readonly GlamourerIpc GlamourerIpc;
|
||||
public readonly GlamourerIpc Ipc;
|
||||
|
||||
public Glamourer(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dalamud.Initialize(pluginInterface);
|
||||
Log = new Logger();
|
||||
|
||||
Log = new Logger();
|
||||
_framework = new FrameworkManager(Dalamud.Framework, Log);
|
||||
_interop = new Interop.Interop();
|
||||
_penumbra = new PenumbraAttach();
|
||||
|
|
@ -100,8 +98,8 @@ public class Glamourer : IDalamudPlugin
|
|||
|
||||
_interface = new Interface(Dalamud.PluginInterface, Items, _stateManager, _designManager, _fileSystem, _objectManager);
|
||||
_windowSystem.AddWindow(_interface);
|
||||
Dalamud.PluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
||||
//FixedDesignManager.Flag((Human*)((Actor)Dalamud.ClientState.LocalPlayer?.Address).Pointer->GameObject.DrawObject, 0, &x);
|
||||
Dalamud.PluginInterface.UiBuilder.Draw += _windowSystem.Draw;
|
||||
Ipc = new GlamourerIpc(this, Dalamud.ClientState, Dalamud.Objects, Dalamud.PluginInterface);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -113,6 +111,7 @@ public class Glamourer : IDalamudPlugin
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
Ipc?.Dispose();
|
||||
_drawObjectManager?.Dispose();
|
||||
RedrawManager?.Dispose();
|
||||
if (_windowSystem != null)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Utility;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.State;
|
||||
using Glamourer.Util;
|
||||
using ImGuiNET;
|
||||
using OtterGui;
|
||||
|
|
@ -51,7 +51,7 @@ public class EquipmentDrawer
|
|||
if (slot.IsAccessory())
|
||||
return gear.Name;
|
||||
|
||||
var (changed, _) = _items.RestrictedGear.ResolveRestricted(gear.Model, slot, race, gender);
|
||||
var (changed, _) = _items.ResolveRestrictedGear(gear.Model, slot, race, gender);
|
||||
if (changed)
|
||||
return gear.Name + " (Restricted)";
|
||||
|
||||
|
|
@ -136,26 +136,51 @@ public class EquipmentDrawer
|
|||
}
|
||||
|
||||
public bool DrawApply(Design design, EquipSlot slot, out bool enabled)
|
||||
{
|
||||
enabled = design.DoApplyEquip(slot);
|
||||
var tmp = enabled;
|
||||
if (!ImGuiUtil.Checkbox($"##apply{slot}", string.Empty, enabled, v => tmp = v))
|
||||
return false;
|
||||
|
||||
var change = enabled != tmp;
|
||||
enabled = tmp;
|
||||
return change;
|
||||
}
|
||||
=> DrawCheckbox($"##apply{slot}", design.DoApplyEquip(slot), out enabled);
|
||||
|
||||
public bool DrawApplyStain(Design design, EquipSlot slot, out bool enabled)
|
||||
{
|
||||
enabled = design.DoApplyStain(slot);
|
||||
var tmp = enabled;
|
||||
if (!ImGuiUtil.Checkbox($"##applyStain{slot}", string.Empty, enabled, v => tmp = v))
|
||||
return false;
|
||||
=> DrawCheckbox($"##applyStain{slot}", design.DoApplyStain(slot), out enabled);
|
||||
|
||||
var change = enabled != tmp;
|
||||
enabled = tmp;
|
||||
return change;
|
||||
private static bool DrawCheckbox(string label, bool value, out bool on)
|
||||
{
|
||||
var ret = ImGuiUtil.Checkbox(label, string.Empty, value, v => value = v);
|
||||
on = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool DrawVisor(Design design, out bool on)
|
||||
=> DrawCheckbox("##visorToggled", design.Visor.ForcedValue, out on);
|
||||
|
||||
public bool DrawVisor(ActiveDesign design, out bool on)
|
||||
=> DrawCheckbox("##visorToggled", design.IsVisorToggled, out on);
|
||||
|
||||
public bool DrawHat(Design design, out bool on)
|
||||
=> DrawCheckbox("##hatVisible", design.Hat.ForcedValue, out on);
|
||||
|
||||
public bool DrawHat(ActiveDesign design, out bool on)
|
||||
=> DrawCheckbox("##hatVisible", design.IsHatVisible, out on);
|
||||
|
||||
public bool DrawWeapon(Design design, out bool on)
|
||||
=> DrawCheckbox("##weaponVisible", design.Weapon.ForcedValue, out on);
|
||||
|
||||
public bool DrawWeapon(ActiveDesign design, out bool on)
|
||||
=> DrawCheckbox("##weaponVisible", design.IsWeaponVisible, out on);
|
||||
|
||||
public bool DrawWetness(Design design, out bool on)
|
||||
=> DrawCheckbox("##wetness", design.Wetness.ForcedValue, out on);
|
||||
|
||||
public bool DrawWetness(ActiveDesign design, out bool on)
|
||||
=> DrawCheckbox("##wetnessVisible", design.IsWet, out on);
|
||||
|
||||
public bool DrawApplyVisor(Design design, out bool on)
|
||||
=> DrawCheckbox("##applyVisor", design.Visor.Enabled, out on);
|
||||
|
||||
public bool DrawApplyWetness(Design design, out bool on)
|
||||
=> DrawCheckbox("##applyWetness", design.Wetness.Enabled, out on);
|
||||
|
||||
public bool DrawApplyHatState(Design design, out bool on)
|
||||
=> DrawCheckbox("##applyHatState", design.Hat.Enabled, out on);
|
||||
|
||||
public bool DrawApplyWeaponState(Design design, out bool on)
|
||||
=> DrawCheckbox("##applyWeaponState", design.Weapon.Enabled, out on);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ internal partial class Interface
|
|||
return;
|
||||
|
||||
if (_currentData.Valid)
|
||||
_currentSave.Update(_currentData.Objects[0]);
|
||||
_currentSave.Initialize(_currentData.Objects[0]);
|
||||
|
||||
RevertButton();
|
||||
if (_main._customizationDrawer.Draw(_currentSave.Customize(), _identifier.Type == IdentifierType.Special))
|
||||
|
|
@ -93,6 +93,11 @@ internal partial class Interface
|
|||
ImGui.SameLine();
|
||||
_main._equipmentDrawer.DrawOffhand(currentOff, main.Type, out var off);
|
||||
}
|
||||
|
||||
if (_main._equipmentDrawer.DrawVisor(_currentSave, out var value))
|
||||
{
|
||||
_activeDesigns.ChangeVisor(_currentSave, value, false);
|
||||
}
|
||||
}
|
||||
|
||||
private const uint RedHeaderColor = 0xFF1818C0;
|
||||
|
|
|
|||
|
|
@ -43,19 +43,12 @@ internal partial class Interface
|
|||
private static void DrawRestorePenumbraButton()
|
||||
{
|
||||
const string buttonLabel = "Re-Register Penumbra";
|
||||
if (!Glamourer.Config.AttachToPenumbra)
|
||||
{
|
||||
using var style = ImRaii.PushStyle(ImGuiStyleVar.Alpha, 0.5f);
|
||||
ImGui.Button(buttonLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
//if (ImGui.Button(buttonLabel))
|
||||
// Glamourer.Penumbra.Reattach(true);
|
||||
|
||||
ImGuiUtil.HoverTooltip(
|
||||
"If Penumbra did not register the functions for some reason, pressing this button might help restore functionality.");
|
||||
//ImGuiUtil.HoverTooltip(
|
||||
// "If Penumbra did not register the functions for some reason, pressing this button might help restore functionality.");
|
||||
}
|
||||
|
||||
private static void DrawSettingsTab()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public unsafe partial struct Actor : IEquatable<Actor>, IDesignable
|
|||
=> actor.Pointer == null ? IntPtr.Zero : (IntPtr)actor.Pointer;
|
||||
|
||||
public ActorIdentifier GetIdentifier()
|
||||
=> Glamourer.Actors.FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Pointer, out _, true, true);
|
||||
=> Glamourer.Actors.FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Pointer, out _, true, true, false);
|
||||
|
||||
public bool Identifier(out ActorIdentifier ident)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,17 +10,5 @@ public unsafe partial class RedrawManager
|
|||
{
|
||||
|
||||
|
||||
public static void SetVisor(Human* data, bool on)
|
||||
{
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
var flags = &data->CharacterBase.UnkFlags_01;
|
||||
var state = (*flags & Offsets.DrawObjectVisorStateFlag) != 0;
|
||||
if (state == on)
|
||||
return;
|
||||
|
||||
var newFlag = (byte)(on ? *flags | Offsets.DrawObjectVisorStateFlag : *flags & ~Offsets.DrawObjectVisorStateFlag);
|
||||
*flags = (byte) (newFlag | Offsets.DrawObjectVisorToggleFlag);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,82 @@ public partial class Interop : IDisposable
|
|||
{
|
||||
SignatureHelper.Initialise(this);
|
||||
_changeJobHook.Enable();
|
||||
_flagSlotForUpdateHook.Enable();
|
||||
_setupVisorHook.Enable();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_changeJobHook.Dispose();
|
||||
_flagSlotForUpdateHook.Dispose();
|
||||
_setupVisorHook.Dispose();
|
||||
}
|
||||
|
||||
public static unsafe bool GetVisorState(nint humanPtr)
|
||||
{
|
||||
if (humanPtr == IntPtr.Zero)
|
||||
return false;
|
||||
|
||||
var data = (Human*)humanPtr;
|
||||
var flags = &data->CharacterBase.UnkFlags_01;
|
||||
return (*flags & Offsets.DrawObjectVisorStateFlag) != 0;
|
||||
}
|
||||
|
||||
public static unsafe void SetVisorState(nint humanPtr, bool on)
|
||||
{
|
||||
if (humanPtr == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
var data = (Human*)humanPtr;
|
||||
var flags = &data->CharacterBase.UnkFlags_01;
|
||||
var state = (*flags & Offsets.DrawObjectVisorStateFlag) != 0;
|
||||
if (state == on)
|
||||
return;
|
||||
|
||||
var newFlag = (byte)(on ? *flags | Offsets.DrawObjectVisorStateFlag : *flags & ~Offsets.DrawObjectVisorStateFlag);
|
||||
*flags = (byte)(newFlag | Offsets.DrawObjectVisorToggleFlag);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Interop
|
||||
{
|
||||
private delegate void UpdateVisorDelegateInternal(nint humanPtr, ushort modelId, bool on);
|
||||
public delegate void UpdateVisorDelegate(DrawObject human, SetId modelId, ref bool on);
|
||||
|
||||
[Signature(Penumbra.GameData.Sigs.SetupVisor, DetourName = nameof(SetupVisorDetour))]
|
||||
private readonly Hook<UpdateVisorDelegateInternal> _setupVisorHook = null!;
|
||||
|
||||
public event UpdateVisorDelegate? VisorUpdate;
|
||||
|
||||
private void SetupVisorDetour(nint humanPtr, ushort modelId, bool on)
|
||||
{
|
||||
InvokeVisorEvent(humanPtr, modelId, ref on);
|
||||
_setupVisorHook.Original(humanPtr, modelId, on);
|
||||
}
|
||||
|
||||
private void InvokeVisorEvent(DrawObject drawObject, SetId modelId, ref bool on)
|
||||
{
|
||||
if (VisorUpdate == null)
|
||||
{
|
||||
Glamourer.Log.Verbose($"Visor setup on 0x{drawObject.Address:X} with {modelId.Value}, setting to {on}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var initialValue = on;
|
||||
foreach (var del in VisorUpdate.GetInvocationList().OfType<UpdateVisorDelegate>())
|
||||
{
|
||||
try
|
||||
{
|
||||
del(drawObject, modelId, ref on);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Glamourer.Log.Error($"Could not invoke {nameof(VisorUpdate)} Subscriber:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
Glamourer.Log.Verbose(
|
||||
$"Visor setup on 0x{drawObject.Address:X} with {modelId.Value}, setting to {on}, initial call was {initialValue}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,8 +135,13 @@ public unsafe partial class Interop
|
|||
private void InvokeFlagSlotEvent(DrawObject drawObject, EquipSlot slot, ref CharacterArmor armor)
|
||||
{
|
||||
if (EquipUpdate == null)
|
||||
{
|
||||
Glamourer.Log.Verbose(
|
||||
$"{slot} updated on 0x{drawObject.Address:X} to {armor.Set.Value}-{armor.Variant} with stain {armor.Stain.Value}.");
|
||||
return;
|
||||
}
|
||||
|
||||
var iv = armor;
|
||||
foreach (var del in EquipUpdate.GetInvocationList().OfType<FlagSlotForUpdateDelegate>())
|
||||
{
|
||||
try
|
||||
|
|
@ -77,6 +153,9 @@ public unsafe partial class Interop
|
|||
Glamourer.Log.Error($"Could not invoke {nameof(EquipUpdate)} Subscriber:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
Glamourer.Log.Verbose(
|
||||
$"{slot} updated on 0x{drawObject.Address:X} to {armor.Set.Value}-{armor.Variant} with stain {armor.Stain.Value}, initial armor was {iv.Set.Value}-{iv.Variant} with stain {iv.Stain.Value}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,8 +201,8 @@ public unsafe partial class RedrawManager : IDisposable
|
|||
public RedrawManager(FixedDesigns fixedDesigns, ActiveDesign.Manager stateManager)
|
||||
{
|
||||
SignatureHelper.Initialise(this);
|
||||
_fixedDesigns = fixedDesigns;
|
||||
_stateManager = stateManager;
|
||||
_fixedDesigns = fixedDesigns;
|
||||
_stateManager = stateManager;
|
||||
_flagSlotForUpdateHook.Enable();
|
||||
_loadWeaponHook.Enable();
|
||||
}
|
||||
|
|
@ -161,7 +240,7 @@ public unsafe partial class RedrawManager : IDisposable
|
|||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
{
|
||||
(_, equip[slot]) =
|
||||
Glamourer.Items.RestrictedGear.ResolveRestricted(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
Glamourer.Items.ResolveRestrictedGear(saveEquip[slot], slot, customize.Race, customize.Gender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ using Glamourer.Interop;
|
|||
using Penumbra.GameData.Actors;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using Glamourer.Api;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
|
|
@ -65,20 +67,58 @@ public sealed partial class ActiveDesign
|
|||
|
||||
public unsafe ActiveDesign GetOrCreateSave(Actor actor)
|
||||
{
|
||||
var id = _actors.FromObject((GameObject*)actor.Pointer, out _, false, false);
|
||||
var id = _actors.FromObject((GameObject*)actor.Pointer, out _, false, false, false);
|
||||
if (_characterSaves.TryGetValue(id, out var save))
|
||||
{
|
||||
save.Update(actor);
|
||||
save.Initialize(actor);
|
||||
return save;
|
||||
}
|
||||
|
||||
id = id.CreatePermanent();
|
||||
save = new ActiveDesign(id, actor);
|
||||
save.Update(actor);
|
||||
save.Initialize(actor);
|
||||
_characterSaves.Add(id, save);
|
||||
return save;
|
||||
}
|
||||
|
||||
public void SetWetness(ActiveDesign design, bool wet, bool fromFixed)
|
||||
=> design.IsWet = wet;
|
||||
|
||||
public void SetHatVisible(ActiveDesign design, bool visible, bool fromFixed)
|
||||
=> design.IsHatVisible = visible;
|
||||
|
||||
public void SetVisor(ActiveDesign design, bool toggled, bool fromFixed)
|
||||
=> design.IsVisorToggled = toggled;
|
||||
|
||||
public void SetWeaponVisible(ActiveDesign design, bool visible, bool fromFixed)
|
||||
=> design.IsWeaponVisible = visible;
|
||||
|
||||
public unsafe void ApplyDesign(ActiveDesign to, Design from, bool fromFixed)
|
||||
{
|
||||
if (to.ModelId != from.ModelId)
|
||||
return;
|
||||
|
||||
if (from.DoApplyEquip(EquipSlot.MainHand))
|
||||
ChangeMainHand(to, from.MainHand, fromFixed);
|
||||
|
||||
if (from.DoApplyEquip(EquipSlot.OffHand))
|
||||
ChangeOffHand(to, from.OffHand, fromFixed);
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots.Where(from.DoApplyEquip))
|
||||
ChangeEquipment(to, slot, from.Armor(slot), fromFixed);
|
||||
|
||||
ChangeCustomize(to, from.ApplyCustomize, *from.Customize().Data, fromFixed);
|
||||
|
||||
if (from.Wetness.Enabled)
|
||||
SetWetness(to, from.Wetness.ForcedValue, fromFixed);
|
||||
if (from.Hat.Enabled)
|
||||
SetHatVisible(to, from.Hat.ForcedValue, fromFixed);
|
||||
if (from.Visor.Enabled)
|
||||
SetVisor(to, from.Visor.ForcedValue, fromFixed);
|
||||
if (from.Weapon.Enabled)
|
||||
SetWeaponVisible(to, from.Weapon.ForcedValue, fromFixed);
|
||||
}
|
||||
|
||||
public void RevertDesign(ActiveDesign design)
|
||||
{
|
||||
RevertCustomize(design, design.ChangedCustomize);
|
||||
|
|
@ -89,6 +129,12 @@ public sealed partial class ActiveDesign
|
|||
RevertOffHand(design);
|
||||
}
|
||||
|
||||
public void ChangeMainHand(ActiveDesign design, uint itemId, bool fromFixed)
|
||||
=> design.SetMainhand(itemId);
|
||||
|
||||
public void ChangeOffHand(ActiveDesign design, uint itemId, bool fromFixed)
|
||||
=> design.SetOffhand(itemId);
|
||||
|
||||
public void RevertMainHand(ActiveDesign design)
|
||||
{ }
|
||||
|
||||
|
|
@ -207,5 +253,20 @@ public sealed partial class ActiveDesign
|
|||
foreach (var obj in data.Objects)
|
||||
_interop.UpdateStain(obj.DrawObject, slot, stain);
|
||||
}
|
||||
|
||||
public void ChangeVisor(ActiveDesign design, bool on, bool fromFixed)
|
||||
{
|
||||
var current = design.IsVisorToggled;
|
||||
if (current == on)
|
||||
return;
|
||||
|
||||
design.IsVisorToggled = on;
|
||||
_objects.Update();
|
||||
if (!_objects.TryGetValue(design.Identifier, out var data))
|
||||
return;
|
||||
|
||||
foreach (var obj in data.Objects)
|
||||
Interop.Interop.SetVisorState(obj.DrawObject, on);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Glamourer.Customization;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Designs;
|
||||
using Glamourer.Interop;
|
||||
using Penumbra.Api.Enums;
|
||||
|
|
@ -27,13 +29,12 @@ public sealed partial class ActiveDesign : DesignBase
|
|||
private ActiveDesign(ActorIdentifier identifier)
|
||||
=> Identifier = identifier;
|
||||
|
||||
private ActiveDesign(ActorIdentifier identifier, Actor actor)
|
||||
public ActiveDesign(ActorIdentifier identifier, Actor actor)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Update(actor);
|
||||
Initialize(actor);
|
||||
}
|
||||
|
||||
|
||||
//public void ApplyToActor(Actor actor)
|
||||
//{
|
||||
// if (!actor)
|
||||
|
|
@ -64,7 +65,7 @@ public sealed partial class ActiveDesign : DesignBase
|
|||
// RedrawManager.SetVisor(actor.DrawObject.Pointer, actor.VisorEnabled);
|
||||
//}
|
||||
//
|
||||
public void Update(Actor actor)
|
||||
public void Initialize(Actor actor)
|
||||
{
|
||||
if (!actor)
|
||||
return;
|
||||
|
|
@ -101,5 +102,14 @@ public sealed partial class ActiveDesign : DesignBase
|
|||
UpdateOffhand(actor.OffHand);
|
||||
SetStain(EquipSlot.OffHand, actor.OffHand.Stain);
|
||||
}
|
||||
|
||||
var visor = Interop.Interop.GetVisorState(actor.DrawObject);
|
||||
if (IsVisorToggled != visor)
|
||||
IsVisorToggled = visor;
|
||||
}
|
||||
|
||||
public string CreateOldBase64()
|
||||
=> CreateOldBase64(in CharacterData, EquipFlagExtensions.All, CustomizeFlagExtensions.All, IsWet, IsHatVisible, true,
|
||||
IsVisorToggled,
|
||||
true, IsWeaponVisible, true, false, 1f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
using System.Collections.Generic;
|
||||
using Dalamud.Configuration;
|
||||
|
||||
namespace Glamourer.State
|
||||
namespace Glamourer.State;
|
||||
|
||||
public class GlamourerConfig : IPluginConfiguration
|
||||
{
|
||||
public class GlamourerConfig : IPluginConfiguration
|
||||
public class FixedDesign
|
||||
{
|
||||
public class FixedDesign
|
||||
{
|
||||
public string Name = string.Empty;
|
||||
public string Path = string.Empty;
|
||||
public uint JobGroups;
|
||||
public bool Enabled;
|
||||
}
|
||||
public string Name = string.Empty;
|
||||
public string Path = string.Empty;
|
||||
public uint JobGroups;
|
||||
public bool Enabled;
|
||||
}
|
||||
|
||||
public int Version { get; set; } = 1;
|
||||
public int Version { get; set; } = 1;
|
||||
|
||||
public const uint DefaultCustomizationColor = 0xFFC000C0;
|
||||
public const uint DefaultStateColor = 0xFF00C0C0;
|
||||
public const uint DefaultEquipmentColor = 0xFF00C000;
|
||||
public const uint DefaultCustomizationColor = 0xFFC000C0;
|
||||
public const uint DefaultStateColor = 0xFF00C0C0;
|
||||
public const uint DefaultEquipmentColor = 0xFF00C000;
|
||||
|
||||
public bool FoldersFirst { get; set; } = false;
|
||||
public bool ColorDesigns { get; set; } = true;
|
||||
public bool ShowLocks { get; set; } = true;
|
||||
public bool AttachToPenumbra { get; set; } = true;
|
||||
public bool ApplyFixedDesigns { get; set; } = true;
|
||||
public bool UseRestrictedGearProtection { get; set; } = true;
|
||||
|
||||
public uint CustomizationColor { get; set; } = DefaultCustomizationColor;
|
||||
public uint StateColor { get; set; } = DefaultStateColor;
|
||||
public uint EquipmentColor { get; set; } = DefaultEquipmentColor;
|
||||
public bool FoldersFirst { get; set; } = false;
|
||||
public bool ColorDesigns { get; set; } = true;
|
||||
public bool ShowLocks { get; set; } = true;
|
||||
public bool ApplyFixedDesigns { get; set; } = true;
|
||||
|
||||
public List<FixedDesign> FixedDesigns { get; set; } = new();
|
||||
public uint CustomizationColor { get; set; } = DefaultCustomizationColor;
|
||||
public uint StateColor { get; set; } = DefaultStateColor;
|
||||
public uint EquipmentColor { get; set; } = DefaultEquipmentColor;
|
||||
|
||||
public void Save()
|
||||
=> Dalamud.PluginInterface.SavePluginConfig(this);
|
||||
public List<FixedDesign> FixedDesigns { get; set; } = new();
|
||||
|
||||
public static GlamourerConfig Load()
|
||||
{
|
||||
if (Dalamud.PluginInterface.GetPluginConfig() is GlamourerConfig config)
|
||||
return config;
|
||||
public void Save()
|
||||
=> Dalamud.PluginInterface.SavePluginConfig(this);
|
||||
|
||||
config = new GlamourerConfig();
|
||||
config.Save();
|
||||
public static GlamourerConfig Load()
|
||||
{
|
||||
if (Dalamud.PluginInterface.GetPluginConfig() is GlamourerConfig config)
|
||||
return config;
|
||||
}
|
||||
|
||||
config = new GlamourerConfig();
|
||||
config.Save();
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,6 @@ public static class CustomizeExtensions
|
|||
return;
|
||||
|
||||
foreach (var slot in EquipSlotExtensions.EqdpSlots)
|
||||
(_, equip[slot]) = Glamourer.Items.RestrictedGear.ResolveRestricted(equip[slot], slot, race, gender);
|
||||
(_, equip[slot]) = Glamourer.Items.ResolveRestrictedGear(equip[slot], slot, race, gender);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Penumbra.GameData;
|
|||
using Penumbra.GameData.Data;
|
||||
using Penumbra.GameData.Enums;
|
||||
using Penumbra.GameData.Structs;
|
||||
using Race = Penumbra.GameData.Enums.Race;
|
||||
|
||||
namespace Glamourer.Util;
|
||||
|
||||
|
|
@ -43,6 +44,14 @@ public class ItemManager : IDisposable
|
|||
RestrictedGear.Dispose();
|
||||
}
|
||||
|
||||
public (bool, CharacterArmor) ResolveRestrictedGear(CharacterArmor armor, EquipSlot slot, Race race, Gender gender)
|
||||
{
|
||||
if (Glamourer.Config.UseRestrictedGearProtection)
|
||||
return RestrictedGear.ResolveRestricted(armor, slot, race, gender);
|
||||
|
||||
return (false, armor);
|
||||
}
|
||||
|
||||
public readonly Item DefaultSword;
|
||||
|
||||
public static uint NothingId(EquipSlot slot)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue