Add BonusItem API.

This commit is contained in:
Ottermandias 2024-08-10 11:52:12 +02:00
parent 9e06125092
commit 5971592217
7 changed files with 100 additions and 8 deletions

@ -1 +1 @@
Subproject commit 4bad56d610132b419335b89896e1f387b9ba2039
Subproject commit b1b90e6ecfeee76a12cb27793753fa87af21083f

View file

@ -35,7 +35,8 @@ public sealed class IpcProviders : IDisposable, IApiService
(a, b, c, d, e, f) => (int)api.Items.SetItem(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f)),
new FuncProvider<string, byte, ulong, byte, uint, ulong, int>(pi, IpcSubscribers.Legacy.SetItemName.Label,
(a, b, c, d, e, f) => (int)api.Items.SetItemName(a, (ApiEquipSlot)b, c, [d], e, (ApplyFlag)f)),
IpcSubscribers.SetBonusItem.Provider(pi, api.Items),
IpcSubscribers.SetBonusItemName.Provider(pi, api.Items),
IpcSubscribers.GetState.Provider(pi, api.State),
IpcSubscribers.GetStateName.Provider(pi, api.State),
IpcSubscribers.GetStateBase64.Provider(pi, api.State),

View file

@ -57,6 +57,64 @@ public class ItemsApi(ApiHelpers helpers, ItemManager itemManager, StateManager
ApiHelpers.Lock(state, key, flags);
}
if (!anyFound)
return ApiHelpers.Return(GlamourerApiEc.ActorNotFound, args);
if (!anyHuman)
return ApiHelpers.Return(GlamourerApiEc.ActorNotHuman, args);
if (!anyUnlocked)
return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args);
return ApiHelpers.Return(GlamourerApiEc.Success, args);
}
public GlamourerApiEc SetBonusItem(int objectIndex, ApiBonusSlot slot, ulong bonusItemId, uint key, ApplyFlag flags)
{
var args = ApiHelpers.Args("Index", objectIndex, "Slot", slot, "ID", bonusItemId, "Key", key, "Flags", flags);
if (!ResolveBonusItem(slot, bonusItemId, out var item))
return ApiHelpers.Return(GlamourerApiEc.ItemInvalid, args);
if (helpers.FindState(objectIndex) is not { } state)
return ApiHelpers.Return(GlamourerApiEc.ActorNotFound, args);
if (!state.ModelData.IsHuman)
return ApiHelpers.Return(GlamourerApiEc.ActorNotHuman, args);
if (!state.CanUnlock(key))
return ApiHelpers.Return(GlamourerApiEc.InvalidKey, args);
var settings = new ApplySettings(Source: flags.HasFlag(ApplyFlag.Once) ? StateSource.IpcManual : StateSource.IpcFixed, Key: key);
stateManager.ChangeBonusItem(state, item.Slot, item, settings);
ApiHelpers.Lock(state, key, flags);
return GlamourerApiEc.Success;
}
public GlamourerApiEc SetBonusItemName(string playerName, ApiBonusSlot slot, ulong bonusItemId, uint key, ApplyFlag flags)
{
var args = ApiHelpers.Args("Name", playerName, "Slot", slot, "ID", bonusItemId, "Key", key, "Flags", flags);
if (!ResolveBonusItem(slot, bonusItemId, out var item))
return ApiHelpers.Return(GlamourerApiEc.ItemInvalid, args);
var settings = new ApplySettings(Source: flags.HasFlag(ApplyFlag.Once) ? StateSource.IpcManual : StateSource.IpcFixed, Key: key);
var anyHuman = false;
var anyFound = false;
var anyUnlocked = false;
foreach (var state in helpers.FindStates(playerName))
{
anyFound = true;
if (!state.ModelData.IsHuman)
continue;
anyHuman = true;
if (!state.CanUnlock(key))
continue;
anyUnlocked = true;
stateManager.ChangeBonusItem(state, item.Slot, item, settings);
ApiHelpers.Lock(state, key, flags);
}
if (!anyFound)
return ApiHelpers.Return(GlamourerApiEc.ActorNotFound, args);
@ -79,4 +137,15 @@ public class ItemsApi(ApiHelpers helpers, ItemManager itemManager, StateManager
item = itemManager.Resolve(slot, id);
return item.Valid;
}
private bool ResolveBonusItem(ApiBonusSlot apiSlot, ulong itemId, out BonusItem item)
{
var slot = apiSlot switch
{
ApiBonusSlot.Glasses => BonusItemFlag.Glasses,
_ => BonusItemFlag.Unknown,
};
return itemManager.IsBonusItemValid(slot, (BonusItemId)itemId, out item);
}
}

View file

@ -91,6 +91,7 @@ public class GlamourerChangelog
.RegisterEntry("Glamourer now has a Support Info button akin to Penumbra's.")
.RegisterEntry("Glamourer now respects write protection on designs better.")
.RegisterEntry("The advanced dye window popup should now get focused when it is opening even in detached state.")
.RegisterEntry("Added API and IPC for bonus items, i.e. the Glasses slot.")
.RegisterHighlight("You can now display your characters height in Corgis or Olympic Swimming Pools.")
.RegisterEntry("Fixed some issues with advanced customizations and dyes applied via IPC. (1.2.3.2)")
.RegisterEntry(

View file

@ -19,7 +19,8 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
private ApplyFlag _flags = ApplyFlagEx.DesignDefault;
private CustomItemId _customItemId;
private StainId _stainId;
private EquipSlot _slot = EquipSlot.Head;
private EquipSlot _slot = EquipSlot.Head;
private BonusItemFlag _bonusSlot = BonusItemFlag.Glasses;
private GlamourerApiEc _lastError;
public void Draw()
@ -47,6 +48,16 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
if (ImGui.Button("Set##Name"))
_lastError = new SetItemName(pluginInterface).Invoke(_gameObjectName, (ApiEquipSlot)_slot, _customItemId.Id, [_stainId.Id], _key,
_flags);
IpcTesterHelpers.DrawIntro(SetBonusItem.Label);
if (ImGui.Button("Set##BonusIdx"))
_lastError = new SetBonusItem(pluginInterface).Invoke(_gameObjectIndex, ToApi(_bonusSlot), _customItemId.Id, _key,
_flags);
IpcTesterHelpers.DrawIntro(SetBonusItemName.Label);
if (ImGui.Button("Set##BonusName"))
_lastError = new SetBonusItemName(pluginInterface).Invoke(_gameObjectName, ToApi(_bonusSlot), _customItemId.Id, _key,
_flags);
}
private void DrawItemInput()
@ -57,6 +68,7 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
if (ImGuiUtil.InputUlong("Custom Item ID", ref tmp))
_customItemId = tmp;
EquipSlotCombo.Draw("Equip Slot", string.Empty, ref _slot, width);
BonusSlotCombo.Draw("Bonus Slot", string.Empty, ref _bonusSlot, width);
var value = (int)_stainId.Id;
ImGui.SetNextItemWidth(width);
if (ImGui.InputInt("Stain ID", ref value, 1, 3))
@ -65,4 +77,11 @@ public class ItemsIpcTester(IDalamudPluginInterface pluginInterface) : IUiServic
_stainId = (StainId)value;
}
}
private static ApiBonusSlot ToApi(BonusItemFlag slot)
=> slot switch
{
BonusItemFlag.Glasses => ApiBonusSlot.Glasses,
_ => ApiBonusSlot.Unknown,
};
}

View file

@ -7,6 +7,7 @@ using Glamourer.Services;
using Glamourer.Unlocks;
using ImGuiNET;
using OtterGui.Raii;
using OtterGui.Text;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using ImGuiClip = OtterGui.ImGuiClip;
@ -200,11 +201,12 @@ public class UnlockOverview(
using var tt = ImRaii.Tooltip();
if (size.X >= iconSize.X && size.Y >= iconSize.Y)
ImGui.Image(icon, size);
ImGui.TextUnformatted(item.Name);
ImGui.TextUnformatted($"{item.Slot.ToName()}");
ImGui.TextUnformatted($"{item.ModelId.Id}-{item.Variant.Id}");
ImUtf8.Text(item.Name);
ImUtf8.Text($"{item.Slot.ToName()}");
ImUtf8.Text($"{item.Id.Id}");
ImUtf8.Text($"{item.ModelId.Id}-{item.Variant.Id}");
// TODO
ImGui.TextUnformatted("Always Unlocked"); // : $"Unlocked on {time:g}" : "Not Unlocked.");
ImUtf8.Text("Always Unlocked"); // : $"Unlocked on {time:g}" : "Not Unlocked.");
// TODO
//tooltip.CreateTooltip(item, string.Empty, false);
}

@ -1 +1 @@
Subproject commit bf020ebf5e4980f1814b336aabbaba5e2e00c362
Subproject commit 3a65ed1c86a2d5fd5794ff5c0559b02fc25d7224