using System; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using LLib.GameUI; using Lumina.Excel; using Lumina.Excel.Sheets; namespace LLib.Gear; public static class RepairActions { public const uint RepairServiceDataId = 720915u; public unsafe static bool TryOpenRepairWindow() { ActionManager* ptr = ActionManager.Instance(); if (ptr == null) { return false; } return ptr->UseAction(ActionType.GeneralAction, 6u, 3758096384uL, 0u, ActionManager.UseActionMode.None, 0u, null); } public unsafe static bool IsRepairAddonReady(IGameGui gameGui) { AtkUnitBase* addonPtr; return gameGui.TryGetReadyAddon("Repair", out addonPtr); } public unsafe static bool TryRepairAll(IGameGui gameGui) { if (!gameGui.TryGetReadyAddon("Repair", out var addonPtr)) { return false; } return AddonCallback.ClickButton(addonPtr, ((AddonRepair*)addonPtr)->RepairAllButton); } public unsafe static bool TryConfirmDialog(IGameGui gameGui) { if (!gameGui.TryGetReadyAddon("Repair", out var _)) { return false; } if (!gameGui.TryGetReadyAddon("SelectYesno", out var addonPtr2)) { return false; } AddonCallback.ClickYes(addonPtr2); return true; } public unsafe static string DescribeRepairAddon(IGameGui gameGui) { if (!gameGui.TryGetAddonByName("Repair", out var addonPtr)) { return "addon: not open"; } AtkComponentButton* repairAllButton = ((AddonRepair*)addonPtr)->RepairAllButton; string value = ((repairAllButton == null) ? "null" : (repairAllButton->IsEnabled ? "enabled" : "disabled")); return $"addon: visible={addonPtr->IsVisible}, ready={LAddon.IsAddonReady(addonPtr)}, repair-all button: {value}"; } public unsafe static bool TryCloseRepairWindow(IGameGui gameGui) { if (!gameGui.TryGetAddonByName("Repair", out var addonPtr)) { return false; } addonPtr->Close(fireCallback: true); return true; } public unsafe static bool TrySelectRepairFromMenu(IGameGui gameGui, int repairIndex) { if (!gameGui.TryGetReadyAddon("SelectIconString", out var addonPtr)) { return false; } AddonCallback.FireWithUpdate(addonPtr, repairIndex); return true; } public static int? FindRepairIndex(IDataManager dataManager, uint npcBaseId) { if (!dataManager.GetExcelSheet().TryGetRow(npcBaseId, out var row)) { return null; } for (int i = 0; i < row.ENpcData.Count; i++) { if (row.ENpcData[i].RowId == 720915) { return i; } } return null; } public static bool CanSelfRepairItem(uint itemId, IDataManager dataManager, Func jobLevelLookup) { if (!dataManager.GetExcelSheet().TryGetRow(itemId, out var row)) { return false; } uint rowId = row.ClassJobRepair.RowId; if (rowId == 0) { return false; } byte num = jobLevelLookup(rowId); int num2 = Math.Max(row.LevelEquip - 10, 1); if (num < num2) { return false; } uint num3 = row.ItemRepair.ValueNullable?.Item.RowId ?? 0; if (num3 == 0) { return false; } return HasDarkMatterOrBetter(dataManager, num3); } public unsafe static bool CanSelfRepairAny(IDataManager dataManager, Func jobLevelLookup, int thresholdPercent = 100) { InventoryManager* ptr = InventoryManager.Instance(); if (ptr == null) { return false; } InventoryContainer* inventoryContainer = ptr->GetInventoryContainer(InventoryType.EquippedItems); if (inventoryContainer == null) { return false; } for (int i = 0; i < inventoryContainer->Size; i++) { InventoryItem* inventorySlot = inventoryContainer->GetInventorySlot(i); if (inventorySlot != null && inventorySlot->ItemId != 0 && inventorySlot->Condition * 100 / 30000 < thresholdPercent && CanSelfRepairItem(inventorySlot->ItemId, dataManager, jobLevelLookup)) { return true; } } return false; } private unsafe static bool HasDarkMatterOrBetter(IDataManager dataManager, uint requiredItemId) { InventoryManager* ptr = InventoryManager.Instance(); if (ptr == null) { return false; } ExcelSheet excelSheet = dataManager.GetExcelSheet(); bool flag = false; foreach (ItemRepairResource item in excelSheet) { if (item.Item.RowId == requiredItemId) { flag = true; } if (flag && ptr->GetInventoryItemCount(item.Item.RowId, isHq: false, checkEquipped: true, checkArmory: true, 0) > 0) { return true; } } return false; } }