diff --git a/Gearsetter.IpcTest/GearsetterIpcTestPlugin.cs b/Gearsetter.IpcTest/GearsetterIpcTestPlugin.cs index 29effab..0ddb7a8 100644 --- a/Gearsetter.IpcTest/GearsetterIpcTestPlugin.cs +++ b/Gearsetter.IpcTest/GearsetterIpcTestPlugin.cs @@ -27,7 +27,7 @@ public class GearsetterIpcTestPlugin : IDalamudPlugin { int currentGearsetIndex = RaptureGearsetModule.Instance()->CurrentGearsetIndex; var recommendations = _pluginInterface - .GetIpcSubscriber>( + .GetIpcSubscriber>( "Gearsetter.GetRecommendationsForGearset").InvokeFunc((byte)currentGearsetIndex); if (recommendations.Count == 0) _chatGui.Print($"No recommendations for gearset #{currentGearsetIndex}."); @@ -35,7 +35,7 @@ public class GearsetterIpcTestPlugin : IDalamudPlugin { foreach (var recommendation in recommendations) _chatGui.Print( - $"Recommendation: Equip item {recommendation.ItemId} from {recommendation.SourceInventory} (slot {recommendation.SourceInventorySlot})"); + $"Recommendation: Equip item {recommendation.ItemId} from {recommendation.SourceInventory} (slot {recommendation.SourceInventorySlot}) as {recommendation.TargetSlot}"); } } diff --git a/Gearsetter/External/GearsetterIpc.cs b/Gearsetter/External/GearsetterIpc.cs index 949d18d..cfac541 100644 --- a/Gearsetter/External/GearsetterIpc.cs +++ b/Gearsetter/External/GearsetterIpc.cs @@ -17,7 +17,8 @@ internal sealed class GearsetterIpc : IDisposable private readonly IPluginLog _pluginLog; private readonly ICallGateProvider> + List<(uint ItemId, InventoryType? SourceInventory, int? SourceInventorySlot, + RaptureGearsetModule.GearsetItemIndex TargetSlot)>> _getRecommendationsForGearset; public GearsetterIpc(GearsetterPlugin plugin, IDalamudPluginInterface pluginInterface, IPluginLog pluginLog) @@ -25,11 +26,15 @@ internal sealed class GearsetterIpc : IDisposable _plugin = plugin; _pluginLog = pluginLog; _getRecommendationsForGearset = - pluginInterface.GetIpcProvider>(IpcGetRecommendationsForGearset); + pluginInterface + .GetIpcProvider>( + IpcGetRecommendationsForGearset); _getRecommendationsForGearset.RegisterFunc(GetRecommendationsForGearset); } - private unsafe List<(uint ItemId, InventoryType? SourceInventory, int? SourceInventorySlot)> + private unsafe List<(uint ItemId, InventoryType? SourceInventory, int? SourceInventorySlot, + RaptureGearsetModule.GearsetItemIndex TargetSlot)> GetRecommendationsForGearset(byte gearsetId) { if (gearsetId > 100) @@ -48,7 +53,7 @@ internal sealed class GearsetterIpc : IDisposable _pluginLog.Verbose($"Checking for gearset upgrades for gearset {gearset->Id}."); return _plugin.GetRecommendedUpgrades(gearset) - .Select(x => (x.ItemId, x.SourceInventory, x.SourceInventorySlot)) + .Select(x => (x.ItemId, x.SourceInventory, x.SourceInventorySlot, x.TargetSlot)) .ToList(); } diff --git a/Gearsetter/Gearsetter.csproj b/Gearsetter/Gearsetter.csproj index 6721e5b..92cb819 100644 --- a/Gearsetter/Gearsetter.csproj +++ b/Gearsetter/Gearsetter.csproj @@ -1,6 +1,6 @@ - 1.2 + 1.3 dist diff --git a/Gearsetter/GearsetterPlugin.cs b/Gearsetter/GearsetterPlugin.cs index cbdca93..3ec9218 100644 --- a/Gearsetter/GearsetterPlugin.cs +++ b/Gearsetter/GearsetterPlugin.cs @@ -189,7 +189,8 @@ public sealed class GearsetterPlugin : IDalamudPlugin private List GetRecommendedUpgrades(GearsetData gearset, Dictionary<(uint ItemId, bool Hql), List> inventoryItems, byte? level) { - List Handle(string label, EquipmentItem?[] gearsetItems, + List Handle(string label, + (EquipmentItem?, RaptureGearsetModule.GearsetItemIndex)[] gearsetItems, EEquipSlotCategory category) { return HandleGearsetItem(label, gearset, gearsetItems, inventoryItems, category, level); @@ -197,20 +198,25 @@ public sealed class GearsetterPlugin : IDalamudPlugin List> upgrades = new() { - Handle("Main Hand", [gearset.MainHand], EEquipSlotCategory.None), + Handle("Main Hand", [(gearset.MainHand, RaptureGearsetModule.GearsetItemIndex.MainHand)], + EEquipSlotCategory.None), HandleOffHand(gearset, inventoryItems, level), - Handle("Head", [gearset.Head], EEquipSlotCategory.Head), - Handle("Body", [gearset.Body], EEquipSlotCategory.Body), - Handle("Hands", [gearset.Hands], EEquipSlotCategory.Hands), - Handle("Legs", [gearset.Legs], EEquipSlotCategory.Legs), - Handle("Feet", [gearset.Feet], EEquipSlotCategory.Feet), + Handle("Head", [(gearset.Head, RaptureGearsetModule.GearsetItemIndex.Head)], EEquipSlotCategory.Head), + Handle("Body", [(gearset.Body, RaptureGearsetModule.GearsetItemIndex.Body)], EEquipSlotCategory.Body), + Handle("Hands", [(gearset.Hands, RaptureGearsetModule.GearsetItemIndex.Hands)], EEquipSlotCategory.Hands), + Handle("Legs", [(gearset.Legs, RaptureGearsetModule.GearsetItemIndex.Legs)], EEquipSlotCategory.Legs), + Handle("Feet", [(gearset.Feet, RaptureGearsetModule.GearsetItemIndex.Feet)], EEquipSlotCategory.Feet), - Handle("Ears", [gearset.Ears], EEquipSlotCategory.Ears), - Handle("Neck", [gearset.Neck], EEquipSlotCategory.Neck), - Handle("Wrists", [gearset.Wrists], EEquipSlotCategory.Wrists), + Handle("Ears", [(gearset.Ears, RaptureGearsetModule.GearsetItemIndex.Ears)], EEquipSlotCategory.Ears), + Handle("Neck", [(gearset.Neck, RaptureGearsetModule.GearsetItemIndex.Neck)], EEquipSlotCategory.Neck), + Handle("Wrists", [(gearset.Wrists, RaptureGearsetModule.GearsetItemIndex.Wrists)], + EEquipSlotCategory.Wrists), Handle("Rings", - [gearset.RingLeft, gearset.RingRight], + [ + (gearset.RingLeft, RaptureGearsetModule.GearsetItemIndex.RingLeft), + (gearset.RingRight, RaptureGearsetModule.GearsetItemIndex.RingRight) + ], EEquipSlotCategory.Rings), }; @@ -251,17 +257,18 @@ public sealed class GearsetterPlugin : IDalamudPlugin => gearset->NameString.Split((char)0)[0]; private List HandleGearsetItem(string label, GearsetData gearset, - EquipmentItem?[] gearsetItems, + (EquipmentItem? Item, RaptureGearsetModule.GearsetItemIndex Slot)[] gearsetItems, Dictionary<(uint ItemId, bool Hq), List> inventoryItems, EEquipSlotCategory equipSlotCategory, byte? level) { EClassJob classJob = gearset.ClassJob; + List availableGearsetSlots = gearsetItems.Select(x => x.Slot).ToList(); var itemLists = _gameDataHolder.GetItemLists(classJob); - if (equipSlotCategory == EEquipSlotCategory.None && gearsetItems.Any(x => x != null)) + if (equipSlotCategory == EEquipSlotCategory.None && gearsetItems.Any(x => x.Item != null)) { - var firstEquippedItem = gearsetItems.First(x => x != null); - equipSlotCategory = firstEquippedItem!.EquipSlotCategory; + var firstEquippedItem = gearsetItems.First(x => x.Item != null); + equipSlotCategory = firstEquippedItem.Item!.EquipSlotCategory; } if (equipSlotCategory == EEquipSlotCategory.None) @@ -270,15 +277,16 @@ public sealed class GearsetterPlugin : IDalamudPlugin return []; } - BaseItem?[] currentItems = gearsetItems + (BaseItem? Item, RaptureGearsetModule.GearsetItemIndex Slot)[] currentItems = gearsetItems .Select(x => { - if (x == null) - return null; + if (x.Item == null) + return (null, x.Slot); - return itemLists - .SelectMany(y => y.Items.Where(z => x.ItemId == z.ItemId && x.Hq == z.Hq)) + var baseItem = itemLists + .SelectMany(y => y.Items.Where(z => x.Item.ItemId == z.ItemId && x.Item.Hq == z.Hq)) .FirstOrDefault(); + return (baseItem, x.Slot); }) .ToArray(); @@ -299,19 +307,28 @@ public sealed class GearsetterPlugin : IDalamudPlugin .Take(gearsetItems.Length) .ToList(); //_pluginLog.Debug( - // $"{equipSlotCategory}: {string.Join(" ", currentItems.Select(x => $"{x?.ItemId}|{x?.Hq}"))}"); + // $"{equipSlotCategory}: {string.Join(" ", currentItems.Select(x => $"{x.Item}, {x.Slot}"))}"); foreach (var currentItem in currentItems) { var foundIndex = bestItems.FindIndex(x => - currentItem != null && currentItem.ItemId == x.ItemId && currentItem.Hq == x.Hq); + currentItem.Item != null && currentItem.Item.ItemId == x.ItemId && currentItem.Item.Hq == x.Hq); if (foundIndex >= 0) + { bestItems.RemoveAt(foundIndex); + availableGearsetSlots.Remove(currentItem.Slot); + } } return bestItems - .Select(x => ToItemRecommendation(x, - new SeString(new TextPayload($"{label}: ")) - .Append(SeString.CreateItemLink(x.ItemId, x.Hq)))) + .Select(x => + { + var slot = availableGearsetSlots[0]; + availableGearsetSlots.RemoveAt(0); + + return ToItemRecommendation(x, slot, + new SeString(new TextPayload($"{label}: ")) + .Append(SeString.CreateItemLink(x.ItemId, x.Hq))); + }) .ToList(); } finally @@ -332,7 +349,8 @@ public sealed class GearsetterPlugin : IDalamudPlugin if (equipSlotCategory != EEquipSlotCategory.OneHandedMainHand) return []; - return HandleGearsetItem("Off Hand", gearset, [gearset.OffHand], + return HandleGearsetItem("Off Hand", gearset, + [(gearset.OffHand, RaptureGearsetModule.GearsetItemIndex.OffHand)], inventoryItems, EEquipSlotCategory.Shield, level); } @@ -341,7 +359,8 @@ public sealed class GearsetterPlugin : IDalamudPlugin => RaptureGearsetModule.Instance()->EquipGearset((byte)commandId); - private unsafe RecommendedItemChange ToItemRecommendation(BaseItem baseItem, SeString text) + private unsafe RecommendedItemChange ToItemRecommendation(BaseItem baseItem, + RaptureGearsetModule.GearsetItemIndex targetSlot, SeString text) { InventoryManager* inventoryManager = InventoryManager.Instance(); foreach (var inventoryType in _gameDataHolder.DefaultInventoryTypes) @@ -357,12 +376,12 @@ public sealed class GearsetterPlugin : IDalamudPlugin MateriaStats actualMateriaStats = FetchMateriaStats(item); if (expectedMateriaStats == actualMateriaStats) - return new RecommendedItemChange(item->ItemId, inventoryType, i, text); + return new RecommendedItemChange(item->ItemId, inventoryType, i, targetSlot, text); } } } - return new RecommendedItemChange(baseItem.ItemId, null, null, text); + return new RecommendedItemChange(baseItem.ItemId, null, null, targetSlot, text); } internal unsafe Dictionary<(uint ItemId, bool Hq), List> GetAllInventoryItems() diff --git a/Gearsetter/Model/RecommendedItemChange.cs b/Gearsetter/Model/RecommendedItemChange.cs index 543141a..61fbac6 100644 --- a/Gearsetter/Model/RecommendedItemChange.cs +++ b/Gearsetter/Model/RecommendedItemChange.cs @@ -1,5 +1,6 @@ using Dalamud.Game.Text.SeStringHandling; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI.Misc; namespace Gearsetter.Model; @@ -7,4 +8,5 @@ internal sealed record RecommendedItemChange( uint ItemId, InventoryType? SourceInventory, int? SourceInventorySlot, + RaptureGearsetModule.GearsetItemIndex TargetSlot, SeString Text);