mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Compare commits
10 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b6517aae8 | ||
|
|
aadcf771e7 | ||
|
|
bf4673a1d9 | ||
|
|
76b214c643 | ||
|
|
434a5a809e | ||
|
|
88fe25f69e | ||
|
|
bef1e39ac3 | ||
|
|
c604d5dbe5 | ||
|
|
a0d912a395 | ||
|
|
a56852f918 |
14 changed files with 121 additions and 29 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7e8505cd6f8dbc5bcf41b72e16785d62b4d218f3
|
Subproject commit 59a7ab5fa9941eb754757b62e4cb189e455e9514
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
using Glamourer.Api.Enums;
|
using Glamourer.Api.Enums;
|
||||||
using Glamourer.Designs;
|
using Glamourer.Designs;
|
||||||
using Glamourer.State;
|
using Glamourer.State;
|
||||||
using OtterGui;
|
|
||||||
using OtterGui.Extensions;
|
using OtterGui.Extensions;
|
||||||
using OtterGui.Log;
|
using OtterGui.Log;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.GameData.Actors;
|
using Penumbra.GameData.Actors;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.String;
|
using Penumbra.String;
|
||||||
|
|
||||||
namespace Glamourer.Api;
|
namespace Glamourer.Api;
|
||||||
|
|
@ -15,15 +15,24 @@ namespace Glamourer.Api;
|
||||||
public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
|
public class ApiHelpers(ActorObjectManager objects, StateManager stateManager, ActorManager actors) : IApiService
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal IEnumerable<ActorState> FindExistingStates(string actorName)
|
internal IEnumerable<ActorState> FindExistingStates(string actorName, ushort worldId = ushort.MaxValue)
|
||||||
{
|
{
|
||||||
if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString))
|
if (actorName.Length == 0 || !ByteString.FromString(actorName, out var byteString))
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
|
if (worldId == WorldId.AnyWorld.Id)
|
||||||
|
{
|
||||||
foreach (var state in stateManager.Values.Where(state
|
foreach (var state in stateManager.Values.Where(state
|
||||||
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
|
=> state.Identifier.Type is IdentifierType.Player && state.Identifier.PlayerName == byteString))
|
||||||
yield return state;
|
yield return state;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var identifier = actors.CreatePlayer(byteString, worldId);
|
||||||
|
if (stateManager.TryGetValue(identifier, out var state))
|
||||||
|
yield return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
|
internal GlamourerApiEc FindExistingState(int objectIndex, out ActorState? state)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ namespace Glamourer.Api;
|
||||||
public class GlamourerApi(DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
|
public class GlamourerApi(DesignsApi designs, StateApi state, ItemsApi items) : IGlamourerApi, IApiService
|
||||||
{
|
{
|
||||||
public const int CurrentApiVersionMajor = 1;
|
public const int CurrentApiVersionMajor = 1;
|
||||||
public const int CurrentApiVersionMinor = 6;
|
public const int CurrentApiVersionMinor = 7;
|
||||||
|
|
||||||
public (int Major, int Minor) ApiVersion
|
public (int Major, int Minor) ApiVersion
|
||||||
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);
|
=> (CurrentApiVersionMajor, CurrentApiVersionMinor);
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ public sealed class IpcProviders : IDisposable, IApiService
|
||||||
IpcSubscribers.RevertStateName.Provider(pi, api.State),
|
IpcSubscribers.RevertStateName.Provider(pi, api.State),
|
||||||
IpcSubscribers.UnlockState.Provider(pi, api.State),
|
IpcSubscribers.UnlockState.Provider(pi, api.State),
|
||||||
IpcSubscribers.UnlockStateName.Provider(pi, api.State),
|
IpcSubscribers.UnlockStateName.Provider(pi, api.State),
|
||||||
|
IpcSubscribers.DeletePlayerState.Provider(pi, api.State),
|
||||||
IpcSubscribers.UnlockAll.Provider(pi, api.State),
|
IpcSubscribers.UnlockAll.Provider(pi, api.State),
|
||||||
IpcSubscribers.RevertToAutomation.Provider(pi, api.State),
|
IpcSubscribers.RevertToAutomation.Provider(pi, api.State),
|
||||||
IpcSubscribers.RevertToAutomationName.Provider(pi, api.State),
|
IpcSubscribers.RevertToAutomationName.Provider(pi, api.State),
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using Glamourer.State;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.GameData.Interop;
|
using Penumbra.GameData.Interop;
|
||||||
|
using Penumbra.GameData.Structs;
|
||||||
using StateChanged = Glamourer.Events.StateChanged;
|
using StateChanged = Glamourer.Events.StateChanged;
|
||||||
|
|
||||||
namespace Glamourer.Api;
|
namespace Glamourer.Api;
|
||||||
|
|
@ -17,7 +18,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
private readonly ApiHelpers _helpers;
|
private readonly ApiHelpers _helpers;
|
||||||
private readonly StateManager _stateManager;
|
private readonly StateManager _stateManager;
|
||||||
private readonly DesignConverter _converter;
|
private readonly DesignConverter _converter;
|
||||||
private readonly Configuration _config;
|
|
||||||
private readonly AutoDesignApplier _autoDesigns;
|
private readonly AutoDesignApplier _autoDesigns;
|
||||||
private readonly ActorObjectManager _objects;
|
private readonly ActorObjectManager _objects;
|
||||||
private readonly StateChanged _stateChanged;
|
private readonly StateChanged _stateChanged;
|
||||||
|
|
@ -27,7 +27,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
public StateApi(ApiHelpers helpers,
|
public StateApi(ApiHelpers helpers,
|
||||||
StateManager stateManager,
|
StateManager stateManager,
|
||||||
DesignConverter converter,
|
DesignConverter converter,
|
||||||
Configuration config,
|
|
||||||
AutoDesignApplier autoDesigns,
|
AutoDesignApplier autoDesigns,
|
||||||
ActorObjectManager objects,
|
ActorObjectManager objects,
|
||||||
StateChanged stateChanged,
|
StateChanged stateChanged,
|
||||||
|
|
@ -37,7 +36,6 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
_helpers = helpers;
|
_helpers = helpers;
|
||||||
_stateManager = stateManager;
|
_stateManager = stateManager;
|
||||||
_converter = converter;
|
_converter = converter;
|
||||||
_config = config;
|
|
||||||
_autoDesigns = autoDesigns;
|
_autoDesigns = autoDesigns;
|
||||||
_objects = objects;
|
_objects = objects;
|
||||||
_stateChanged = stateChanged;
|
_stateChanged = stateChanged;
|
||||||
|
|
@ -202,6 +200,27 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable
|
||||||
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
return ApiHelpers.Return(GlamourerApiEc.Success, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GlamourerApiEc DeletePlayerState(string playerName, ushort worldId, uint key)
|
||||||
|
{
|
||||||
|
var args = ApiHelpers.Args("Name", playerName, "World", worldId, "Key", key);
|
||||||
|
var states = _helpers.FindExistingStates(playerName).ToList();
|
||||||
|
if (states.Count is 0)
|
||||||
|
return ApiHelpers.Return(GlamourerApiEc.NothingDone, args);
|
||||||
|
|
||||||
|
var anyLocked = false;
|
||||||
|
foreach (var state in states)
|
||||||
|
{
|
||||||
|
if (state.CanUnlock(key))
|
||||||
|
_stateManager.DeleteState(state.Identifier);
|
||||||
|
else
|
||||||
|
anyLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiHelpers.Return(anyLocked
|
||||||
|
? GlamourerApiEc.InvalidKey
|
||||||
|
: GlamourerApiEc.Success, args);
|
||||||
|
}
|
||||||
|
|
||||||
public int UnlockAll(uint key)
|
public int UnlockAll(uint key)
|
||||||
=> _stateManager.Values.Count(state => state.Unlock(key));
|
=> _stateManager.Values.Count(state => state.Unlock(key));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
||||||
|
|
||||||
public new JObject JsonSerialize()
|
public new JObject JsonSerialize()
|
||||||
{
|
{
|
||||||
var ret = new JObject()
|
var ret = new JObject
|
||||||
{
|
{
|
||||||
["FileVersion"] = FileVersion,
|
["FileVersion"] = FileVersion,
|
||||||
["Identifier"] = Identifier,
|
["Identifier"] = Identifier,
|
||||||
|
|
@ -131,12 +131,17 @@ public sealed class Design : DesignBase, ISavable, IDesignStandIn
|
||||||
var ret = new JArray();
|
var ret = new JArray();
|
||||||
foreach (var (mod, settings) in AssociatedMods)
|
foreach (var (mod, settings) in AssociatedMods)
|
||||||
{
|
{
|
||||||
var obj = new JObject()
|
var obj = new JObject
|
||||||
{
|
{
|
||||||
["Name"] = mod.Name,
|
["Name"] = mod.Name,
|
||||||
["Directory"] = mod.DirectoryName,
|
["Directory"] = mod.DirectoryName,
|
||||||
["Enabled"] = settings.Enabled,
|
|
||||||
};
|
};
|
||||||
|
if (settings.Remove)
|
||||||
|
obj["Remove"] = true;
|
||||||
|
else if (settings.ForceInherit)
|
||||||
|
obj["Inherit"] = true;
|
||||||
|
else
|
||||||
|
obj["Enabled"] = settings.Enabled;
|
||||||
if (settings.Enabled)
|
if (settings.Enabled)
|
||||||
{
|
{
|
||||||
obj["Priority"] = settings.Priority;
|
obj["Priority"] = settings.Priority;
|
||||||
|
|
|
||||||
|
|
@ -557,7 +557,7 @@ public sealed class DesignManager : DesignEditor
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Move(SaveService.FileNames.MigrationDesignFile,
|
File.Move(SaveService.FileNames.MigrationDesignFile,
|
||||||
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"));
|
Path.ChangeExtension(SaveService.FileNames.MigrationDesignFile, ".json.bak"), true);
|
||||||
Glamourer.Log.Information($"Moved migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file.");
|
Glamourer.Log.Information($"Moved migrated design file {SaveService.FileNames.MigrationDesignFile} to backup file.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,12 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
||||||
private readonly CustomizeService _customize;
|
private readonly CustomizeService _customize;
|
||||||
private readonly GPoseService _gpose;
|
private readonly GPoseService _gpose;
|
||||||
|
|
||||||
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2];
|
private readonly EquipItem[] _lastItems = new EquipItem[EquipFlagExtensions.NumEquipFlags / 2 + BonusExtensions.AllFlags.Count];
|
||||||
|
|
||||||
public IEnumerable<KeyValuePair<EquipSlot, EquipItem>> LastItems
|
public IEnumerable<KeyValuePair<object, EquipItem>> LastItems
|
||||||
=> EquipSlotExtensions.EqdpSlots.Append(EquipSlot.MainHand).Append(EquipSlot.OffHand).Zip(_lastItems)
|
=> EquipSlotExtensions.EqdpSlots.Cast<object>().Append(EquipSlot.MainHand).Append(EquipSlot.OffHand)
|
||||||
.Select(p => new KeyValuePair<EquipSlot, EquipItem>(p.First, p.Second));
|
.Concat(BonusExtensions.AllFlags.Cast<object>()).Zip(_lastItems)
|
||||||
|
.Select(p => new KeyValuePair<object, EquipItem>(p.First, p.Second));
|
||||||
|
|
||||||
public ChangedItemType LastType { get; private set; } = ChangedItemType.None;
|
public ChangedItemType LastType { get; private set; } = ChangedItemType.None;
|
||||||
public uint LastId { get; private set; }
|
public uint LastId { get; private set; }
|
||||||
|
|
@ -72,6 +73,21 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
||||||
if (!Player())
|
if (!Player())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var bonusSlot = item.Type.ToBonus();
|
||||||
|
if (bonusSlot is not BonusItemFlag.Unknown)
|
||||||
|
{
|
||||||
|
// + 2 due to weapons.
|
||||||
|
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
|
||||||
|
using (_ = !openTooltip ? null : ImRaii.Tooltip())
|
||||||
|
{
|
||||||
|
ImGui.TextUnformatted($"{prefix}Right-Click to apply to current actor.");
|
||||||
|
if (glasses.Valid)
|
||||||
|
ImGui.TextUnformatted($"{prefix}Control + Right-Click to re-apply {glasses.Name} to current actor.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var slot = item.Type.ToSlot();
|
var slot = item.Type.ToSlot();
|
||||||
var last = _lastItems[slot.ToIndex()];
|
var last = _lastItems[slot.ToIndex()];
|
||||||
switch (slot)
|
switch (slot)
|
||||||
|
|
@ -109,6 +125,27 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
||||||
|
|
||||||
public void ApplyItem(ActorState state, EquipItem item)
|
public void ApplyItem(ActorState state, EquipItem item)
|
||||||
{
|
{
|
||||||
|
var bonusSlot = item.Type.ToBonus();
|
||||||
|
if (bonusSlot is not BonusItemFlag.Unknown)
|
||||||
|
{
|
||||||
|
// + 2 due to weapons.
|
||||||
|
var glasses = _lastItems[bonusSlot.ToSlot() + 2];
|
||||||
|
if (ImGui.GetIO().KeyCtrl && glasses.Valid)
|
||||||
|
{
|
||||||
|
Glamourer.Log.Debug($"Re-Applying {glasses.Name} to {bonusSlot.ToName()}.");
|
||||||
|
SetLastItem(bonusSlot, default, state);
|
||||||
|
_stateManager.ChangeBonusItem(state, bonusSlot, glasses, ApplySettings.Manual);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Glamourer.Log.Debug($"Applying {item.Name} to {bonusSlot.ToName()}.");
|
||||||
|
SetLastItem(bonusSlot, item, state);
|
||||||
|
_stateManager.ChangeBonusItem(state, bonusSlot, item, ApplySettings.Manual);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var slot = item.Type.ToSlot();
|
var slot = item.Type.ToSlot();
|
||||||
var last = _lastItems[slot.ToIndex()];
|
var last = _lastItems[slot.ToIndex()];
|
||||||
switch (slot)
|
switch (slot)
|
||||||
|
|
@ -265,7 +302,22 @@ public sealed class PenumbraChangedItemTooltip : IDisposable
|
||||||
{
|
{
|
||||||
var oldItem = state.ModelData.Item(slot);
|
var oldItem = state.ModelData.Item(slot);
|
||||||
if (oldItem.Id != item.Id)
|
if (oldItem.Id != item.Id)
|
||||||
_lastItems[slot.ToIndex()] = oldItem;
|
last = oldItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetLastItem(BonusItemFlag slot, EquipItem item, ActorState state)
|
||||||
|
{
|
||||||
|
ref var last = ref _lastItems[slot.ToSlot() + 2];
|
||||||
|
if (!item.Valid)
|
||||||
|
{
|
||||||
|
last = default;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var oldItem = state.ModelData.BonusItem(slot);
|
||||||
|
if (oldItem.Id != item.Id)
|
||||||
|
last = oldItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,13 @@ public unsafe class PenumbraPanel(PenumbraService _penumbra, PenumbraChangedItem
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
foreach (var (slot, item) in _penumbraTooltip.LastItems)
|
foreach (var (slot, item) in _penumbraTooltip.LastItems)
|
||||||
{
|
{
|
||||||
ImGuiUtil.DrawTableColumn($"{slot.ToName()} Revert-Item");
|
switch (slot)
|
||||||
|
{
|
||||||
|
case EquipSlot e: ImGuiUtil.DrawTableColumn($"{e.ToName()} Revert-Item"); break;
|
||||||
|
case BonusItemFlag f: ImGuiUtil.DrawTableColumn($"{f.ToName()} Revert-Item"); break;
|
||||||
|
default: ImGuiUtil.DrawTableColumn("Unk Revert-Item"); break;
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiUtil.DrawTableColumn(item.Valid ? item.Name : "None");
|
ImGuiUtil.DrawTableColumn(item.Valid ? item.Name : "None");
|
||||||
ImGui.TableNextColumn();
|
ImGui.TableNextColumn();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ public class StateApplier(
|
||||||
var actors = ChangeMetaState(state, MetaIndex.Wetness, true);
|
var actors = ChangeMetaState(state, MetaIndex.Wetness, true);
|
||||||
if (redraw)
|
if (redraw)
|
||||||
{
|
{
|
||||||
if (withLock)
|
if (withLock && actors.Valid)
|
||||||
state.TempLock();
|
state.TempLock();
|
||||||
ForceRedraw(actors);
|
ForceRedraw(actors);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit f354444776591ae423e2d8374aae346308d81424
|
Subproject commit 1459e2b8f5e1687f659836709e23571235d4206c
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 648b6fc2ce600a95ab2b2ced27e1639af2b04502
|
Subproject commit c23ee05c1e9fa103eaa52e6aa7e855ef568ee669
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3baace73c828271dcb71a8156e3e7b91e1dd12ae
|
Subproject commit d889f9ef918514a46049725052d378b441915b00
|
||||||
10
repo.json
10
repo.json
|
|
@ -17,8 +17,8 @@
|
||||||
"Character"
|
"Character"
|
||||||
],
|
],
|
||||||
"InternalName": "Glamourer",
|
"InternalName": "Glamourer",
|
||||||
"AssemblyVersion": "1.5.1.2",
|
"AssemblyVersion": "1.5.1.5",
|
||||||
"TestingAssemblyVersion": "1.5.1.2",
|
"TestingAssemblyVersion": "1.5.1.5",
|
||||||
"RepoUrl": "https://github.com/Ottermandias/Glamourer",
|
"RepoUrl": "https://github.com/Ottermandias/Glamourer",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"DalamudApiLevel": 13,
|
"DalamudApiLevel": 13,
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
"IsTestingExclusive": "False",
|
"IsTestingExclusive": "False",
|
||||||
"DownloadCount": 1,
|
"DownloadCount": 1,
|
||||||
"LastUpdate": 1618608322,
|
"LastUpdate": 1618608322,
|
||||||
"DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.2/Glamourer.zip",
|
"DownloadLinkInstall": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip",
|
||||||
"DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.2/Glamourer.zip",
|
"DownloadLinkUpdate": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip",
|
||||||
"DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.2/Glamourer.zip",
|
"DownloadLinkTesting": "https://github.com/Ottermandias/Glamourer/releases/download/1.5.1.5/Glamourer.zip",
|
||||||
"IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/main/images/icon.png"
|
"IconUrl": "https://raw.githubusercontent.com/Ottermandias/Glamourer/main/images/icon.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue