diff --git a/Deliveroo/Configuration.cs b/Deliveroo/Configuration.cs index 4caf366..27dbb2a 100644 --- a/Deliveroo/Configuration.cs +++ b/Deliveroo/Configuration.cs @@ -31,6 +31,7 @@ internal sealed class Configuration : IPluginConfiguration public int Limit { get; set; } public bool Enabled { get; set; } = true; public PurchaseType Type { get; set; } = PurchaseType.KeepStocked; + public bool CheckRetainerInventory { get; set; } public string GetIcon() { diff --git a/Deliveroo/DeliverooPlugin.Exchange.cs b/Deliveroo/DeliverooPlugin.Exchange.cs index 7f804ea..ce70ddc 100644 --- a/Deliveroo/DeliverooPlugin.Exchange.cs +++ b/Deliveroo/DeliverooPlugin.Exchange.cs @@ -40,7 +40,7 @@ partial class DeliverooPlugin if (request.Type == Configuration.PurchaseType.KeepStocked) { - if (GetItemCount(request.ItemId) + toBuy < request.EffectiveLimit) + if (GetItemCount(request.ItemId, request.CheckRetainerInventory) + toBuy < request.EffectiveLimit) return request; } else @@ -148,7 +148,7 @@ partial class DeliverooPlugin _pluginLog.Information($"Selecting item {itemId}, {i}"); long toBuy = (GetCurrentSealCount() - EffectiveReservedSealCount) / item.SealCost; if (item.Type == Configuration.PurchaseType.KeepStocked) - toBuy = Math.Min(toBuy, item.EffectiveLimit - GetItemCount(item.ItemId)); + toBuy = Math.Min(toBuy, item.EffectiveLimit - GetItemCount(item.ItemId, item.CheckRetainerInventory)); else toBuy = Math.Min(toBuy, item.EffectiveLimit); diff --git a/Deliveroo/DeliverooPlugin.GameFunctions.cs b/Deliveroo/DeliverooPlugin.GameFunctions.cs index 966f645..75a4c31 100644 --- a/Deliveroo/DeliverooPlugin.GameFunctions.cs +++ b/Deliveroo/DeliverooPlugin.GameFunctions.cs @@ -97,10 +97,13 @@ partial class DeliverooPlugin public uint GetMaxSealCap() => _sealCaps[11]; - public unsafe int GetItemCount(uint itemId) + public unsafe int GetItemCount(uint itemId, bool checkRetainerInventory) { InventoryManager* inventoryManager = InventoryManager.Instance(); - return inventoryManager->GetInventoryItemCount(itemId, false, false, false); + int count = inventoryManager->GetInventoryItemCount(itemId, false, false, false); + if (checkRetainerInventory) + count += (int)_externalPluginHandler.GetRetainerItemCount(itemId); + return count; } private decimal GetSealMultiplier() diff --git a/Deliveroo/External/AllaganToolsIpc.cs b/Deliveroo/External/AllaganToolsIpc.cs new file mode 100644 index 0000000..8b33177 --- /dev/null +++ b/Deliveroo/External/AllaganToolsIpc.cs @@ -0,0 +1,48 @@ +using System.Linq; +using Dalamud.Plugin; +using Dalamud.Plugin.Ipc; +using Dalamud.Plugin.Ipc.Exceptions; +using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Game; + +namespace ARControl.External; + +public class AllaganToolsIpc +{ + private readonly IPluginLog _pluginLog; + + private static readonly uint[] RetainerInventoryTypes = new[] + { + InventoryType.RetainerPage1, + InventoryType.RetainerPage2, + InventoryType.RetainerPage3, + InventoryType.RetainerPage4, + InventoryType.RetainerPage5, + InventoryType.RetainerPage6, + InventoryType.RetainerPage7, + } + .Select(x => (uint)x).ToArray(); + + private readonly ICallGateSubscriber _itemCountOwned; + + public AllaganToolsIpc(DalamudPluginInterface pluginInterface, IPluginLog pluginLog) + { + _pluginLog = pluginLog; + _itemCountOwned = pluginInterface.GetIpcSubscriber("AllaganTools.ItemCountOwned"); + } + + public uint GetRetainerItemCount(uint itemId) + { + try + { + uint itemCount = _itemCountOwned.InvokeFunc(itemId, true, RetainerInventoryTypes); + _pluginLog.Verbose($"Found {itemCount} items in retainer inventories for itemId {itemId}"); + return itemCount; + } + catch (IpcError) + { + _pluginLog.Warning("Could not query allagantools for retainer inventory counts"); + return 0; + } + } +} diff --git a/Deliveroo/External/ExternalPluginHandler.cs b/Deliveroo/External/ExternalPluginHandler.cs index 9eb101e..6130d82 100644 --- a/Deliveroo/External/ExternalPluginHandler.cs +++ b/Deliveroo/External/ExternalPluginHandler.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using ARControl.External; using Dalamud.Plugin; using Dalamud.Plugin.Services; @@ -11,6 +12,7 @@ internal sealed class ExternalPluginHandler : IDisposable private readonly IPluginLog _pluginLog; private readonly DeliverooIpc _deliverooIpc; private readonly PandoraIpc _pandoraIpc; + private readonly AllaganToolsIpc _allaganToolsIpc; private bool? _pandoraState; @@ -20,6 +22,7 @@ internal sealed class ExternalPluginHandler : IDisposable _pluginLog = pluginLog; _deliverooIpc = new DeliverooIpc(pluginInterface); _pandoraIpc = new PandoraIpc(pluginInterface, pluginLog); + _allaganToolsIpc = new AllaganToolsIpc(pluginInterface, pluginLog); } public bool Saved { get; private set; } @@ -89,4 +92,6 @@ internal sealed class ExternalPluginHandler : IDisposable { _deliverooIpc.Dispose(); } + + public uint GetRetainerItemCount(uint itemId) => _allaganToolsIpc.GetRetainerItemCount(itemId); } diff --git a/Deliveroo/PurchaseItemRequest.cs b/Deliveroo/PurchaseItemRequest.cs index f372518..4caaf80 100644 --- a/Deliveroo/PurchaseItemRequest.cs +++ b/Deliveroo/PurchaseItemRequest.cs @@ -13,6 +13,7 @@ internal sealed class PurchaseItemRequest public required RewardSubCategory SubCategory { get; init; } public required uint StackSize { get; init; } public required Configuration.PurchaseType Type { get; init; } + public required bool CheckRetainerInventory { get; init; } public Action? OnPurchase { get; set; } public long TemporaryPurchaseQuantity { get; set; } diff --git a/Deliveroo/Windows/TurnInWindow.cs b/Deliveroo/Windows/TurnInWindow.cs index 9b2d669..8b2c781 100644 --- a/Deliveroo/Windows/TurnInWindow.cs +++ b/Deliveroo/Windows/TurnInWindow.cs @@ -138,6 +138,7 @@ internal sealed class TurnInWindow : LImGui.LWindow SubCategory = x.Reward.SubCategory, StackSize = x.Reward.StackSize, Type = x.Item.Type, + CheckRetainerInventory = x.Item.CheckRetainerInventory, }; if (x.Item.Type == Configuration.PurchaseType.PurchaseOneTime) { @@ -241,18 +242,22 @@ internal sealed class TurnInWindow : LImGui.LWindow var itemsWrapper = ItemsWrapper; ImGui.Text($"Items to buy ({itemsWrapper.Name}):"); - List<(GcRewardItem Item, string Name)> comboValues = new() + List<(GcRewardItem Item, string NameWithoutRetainers, string NameWithRetainers)> comboValues = new() { - (GcRewardItem.None, GcRewardItem.None.Name), + (GcRewardItem.None, GcRewardItem.None.Name, GcRewardItem.None.Name), }; foreach (uint itemId in _configuration.ItemsAvailableForPurchase) { var gcReward = _gcRewardsCache.GetReward(itemId); - int itemCount = _plugin.GetItemCount(itemId); - string itemName = gcReward.Name; - if (itemCount > 0) - itemName += $" ({itemCount:N0})"; - comboValues.Add((gcReward, itemName)); + int itemCountWithoutRetainers = _plugin.GetItemCount(itemId, false); + int itemCountWithRetainers = _plugin.GetItemCount(itemId, true); + string itemNameWithoutRetainers = gcReward.Name; + string itemNameWithRetainers = gcReward.Name; + if (itemCountWithoutRetainers > 0) + itemNameWithoutRetainers += $" ({itemCountWithoutRetainers:N0})"; + if (itemCountWithRetainers > 0) + itemNameWithRetainers += $" ({itemCountWithRetainers:N0})"; + comboValues.Add((gcReward, itemNameWithoutRetainers, itemNameWithRetainers)); } if (itemsWrapper.GetItemsToPurchase().Count == 0) @@ -291,14 +296,27 @@ internal sealed class TurnInWindow : LImGui.LWindow itemsWrapper.Save(); } - ImGui.SetNextItemWidth(150 * ImGuiHelpers.GlobalScale); + ImGui.SetNextItemWidth(375 * ImGuiHelpers.GlobalScale); int type = (int)item.Type; if (ImGui.Combo($"##Type{i}", ref type, StockingTypeLabels, StockingTypeLabels.Length)) { item.Type = (Configuration.PurchaseType)type; + if (item.Type != Configuration.PurchaseType.KeepStocked) + item.CheckRetainerInventory = false; itemsWrapper.Save(); } + if (item.Type == Configuration.PurchaseType.KeepStocked && item.ItemId != ItemIds.Venture) + { + bool checkRetainerInventory = item.CheckRetainerInventory; + if (ImGui.Checkbox("Check Retainer Inventory for items (requires AllaganTools)", + ref checkRetainerInventory)) + { + item.CheckRetainerInventory = checkRetainerInventory; + itemsWrapper.Save(); + } + } + ImGui.EndPopup(); } @@ -324,7 +342,9 @@ internal sealed class TurnInWindow : LImGui.LWindow indentX = ImGui.GetCursorPosX() - indentX; - if (ImGui.Combo("", ref comboValueIndex, comboValues.Select(x => x.Name).ToArray(), comboValues.Count)) + if (ImGui.Combo("", ref comboValueIndex, + comboValues.Select(x => item.CheckRetainerInventory ? x.NameWithRetainers : x.NameWithoutRetainers) + .ToArray(), comboValues.Count)) { comboItem = comboValues[comboValueIndex]; item.ItemId = comboItem.Item.ItemId;