using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; using LLib.GameUI; using Lumina.Excel.Sheets; namespace LLib.Gear; public static class DesynthActions { public const uint DesynthUnlockQuestId = 65688u; public unsafe static bool TryOpenDesynthWindow() { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr == null) { return false; } ptr->AgentInterface.Show(); return true; } public unsafe static bool IsDesynthAddonReady(IGameGui gameGui) { AtkUnitBase* addonPtr; return gameGui.TryGetReadyAddon("SalvageItemSelector", out addonPtr); } public unsafe static void SetCategory(AgentSalvage.SalvageItemCategory category) { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr != null) { ptr->SelectedCategory = category; } } public unsafe static AgentSalvage.SalvageItemCategory GetCategory() { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr == null) { return AgentSalvage.SalvageItemCategory.InventoryEquipment; } return ptr->SelectedCategory; } public unsafe static void RefreshItemList() { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr != null) { ptr->ItemListRefresh(isSalvageResultAddonOpen: true); } } public unsafe static int GetItemCount() { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr == null) { return 0; } return (int)ptr->ItemCount; } public unsafe static bool TrySelectItem(IGameGui gameGui, int itemIndex) { if (!gameGui.TryGetReadyAddon("SalvageItemSelector", out var addonPtr)) { return false; } AddonCallback.FireWithUpdate(addonPtr, 12, itemIndex); return true; } public unsafe static bool IsConfirmDialogReady(IGameGui gameGui) { AtkUnitBase* addonPtr; return gameGui.TryGetReadyAddon("SalvageDialog", out addonPtr); } public unsafe static bool TryConfirmDesynth(IGameGui gameGui, bool nqOnly = false) { if (!gameGui.TryGetReadyAddon("SalvageDialog", out var addonPtr)) { return false; } AddonCallback.FireWithUpdate(addonPtr, 15, nqOnly ? 1 : 0); AddonCallback.FireWithUpdate(addonPtr, default(int), default(int)); return true; } public unsafe static bool IsResultDialogReady(IGameGui gameGui) { AtkUnitBase* addonPtr; return gameGui.TryGetReadyAddon("SalvageResult", out addonPtr); } public unsafe static bool TryCloseResultDialog(IGameGui gameGui) { if (!gameGui.TryGetReadyAddon("SalvageResult", out var addonPtr)) { return false; } addonPtr->Close(fireCallback: true); return true; } public unsafe static bool TryCloseDesynthWindow(IGameGui gameGui) { if (!gameGui.TryGetReadyAddon("SalvageItemSelector", out var addonPtr)) { return false; } addonPtr->Close(fireCallback: true); return true; } public unsafe static AgentSalvage.SalvageListItem? GetItemAtIndex(int index) { AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr == null || ptr->ItemList == null || index < 0 || index >= ptr->ItemCount) { return null; } return ptr->ItemList[index]; } public unsafe static bool TryDesynthDirect(InventoryItem* item) { if (item == null || item->ItemId == 0) { return false; } AgentSalvage* ptr = AgentSalvage.Instance(); if (ptr == null) { return false; } ptr->SalvageItem(item, 0, 0); AtkValue* returnValue = stackalloc AtkValue[1]; AtkValue* ptr2 = stackalloc AtkValue[2]; ptr2->Type = AtkValueType.Int; ptr2->Int = 0; ptr2[1].Type = AtkValueType.Bool; ptr2[1].Byte = 1; ptr->AgentInterface.ReceiveEvent(returnValue, ptr2, 2u, 1uL); return true; } public static bool IsDesynthUnlocked() { return GearFeatures.IsDesynthUnlocked(); } public static bool IsItemDesynthable(IDataManager dataManager, uint itemId) { if (!dataManager.GetExcelSheet().TryGetRow(itemId, out var row)) { return false; } return row.Desynth > 0; } public unsafe static bool CanPlayerDesynthItem(IDataManager dataManager, uint itemId) { if (!dataManager.GetExcelSheet().TryGetRow(itemId, out var row)) { return false; } if (row.Desynth <= 0) { return false; } ClassJob? valueNullable = row.ClassJobRepair.ValueNullable; if (!valueNullable.HasValue) { return false; } PlayerState* ptr = PlayerState.Instance(); if (ptr == null) { return false; } return ptr->ClassJobLevels[valueNullable.Value.ExpArrayIndex] >= 30; } public unsafe static float GetDesynthLevel(uint classJobId) { PlayerState* ptr = PlayerState.Instance(); bool flag = ptr == null; if (!flag) { bool flag2 = ((classJobId < 8 || classJobId > 15) ? true : false); flag = flag2; } if (flag) { return 0f; } return ptr->GetDesynthesisLevel(classJobId); } }