From 9b3e13ffebc0a8770e37044210f8c6ca0f2dc799 Mon Sep 17 00:00:00 2001
From: Jackson <9527380+Jaksuhn@users.noreply.github.com>
Date: Fri, 26 Jun 2026 16:43:54 +0100
Subject: [PATCH 1/6] Update AgentMiragePrismPrismSetConvert.cs
---
.../Agent/AgentMiragePrismPrismSetConvert.cs | 24 ++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
index 13105c599..eb77d1f6d 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
@@ -27,9 +27,17 @@ public partial struct AgentData {
[FieldOffset(0x0C)] public ushort CrystallizeAddonId; // MiragePrismPrismBoxCrystallize, the opener
[FieldOffset(0x0E)] public ushort PrismBoxAddonId; // MiragePrismPrismBoxAddonId
+ [FieldOffset(0x10)] public SetConvertState State;
+ [FieldOffset(0x14)] public uint SelectedSetIndex;
[FieldOffset(0x18)] public int ContextMenuItemIndex;
-
- [FieldOffset(0x2C)] public bool EnableSorting;
+ [FieldOffset(0x1C)] public uint YesNoAddonId;
+ [FieldOffset(0x24)] public uint GlamourPrismCount;
+ /// Index for
+ [FieldOffset(0x28)] public uint PrismBoxIndex;
+ [FieldOffset(0x2C), Obsolete("Renamed to EnableStoring")] public bool EnableSorting;
+ [FieldOffset(0x2C)] public bool EnableStoring; // false = preview mode
+ [FieldOffset(0x2D)] public bool StoreInExistingOutfit; // false = will be a new outfit, set on Open
+ [FieldOffset(0x38)] public uint ItemSetCount;
[FieldOffset(0x40), FixedSizeArray] internal FixedSizeArray5 _itemSets;
[FieldOffset(0x2C0)] public uint NumItemsInSet;
@@ -43,6 +51,7 @@ public partial struct AgentData {
public struct ItemSet {
[FieldOffset(0x00)] public uint ItemId;
[FieldOffset(0x04)] public uint IconId;
+ [FieldOffset(0x08)] public uint SlotUnlockMask;
[FieldOffset(0x10)] public Utf8String Name;
}
@@ -51,7 +60,7 @@ public struct ItemSet {
public struct ItemSetItem {
[FieldOffset(0x00)] public uint ItemId;
[FieldOffset(0x04)] public uint IconId;
- [FieldOffset(0x08)] private uint SlotIndex; // probably? seems to match MainHand, OffHand, Head, Body etc.
+ [FieldOffset(0x08)] public uint MirageStoreSetItemColumn; // column index of MirageStoreSetItem
[FieldOffset(0x0C)] public InventoryType InventoryType;
@@ -76,3 +85,12 @@ public partial struct HandInItem {
}
}
}
+
+public enum SetConvertState : uint {
+ None = 0, // idle/closed
+ Loading = 1, // loads the icons/names
+ Unk2 = 2,
+ Unk3 = 3,
+ RefreshHandInSlots = 4,
+ Ready = 5,
+}
From ca30910d3165f62fd810df7950ef15b291e17046 Mon Sep 17 00:00:00 2001
From: Jackson <9527380+Jaksuhn@users.noreply.github.com>
Date: Fri, 26 Jun 2026 19:59:53 +0100
Subject: [PATCH 2/6] pretty sure these are right
---
.../Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs | 8 ++++----
ida/data.yml | 4 ++++
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
index eb77d1f6d..cc4e40e22 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
@@ -27,7 +27,7 @@ public partial struct AgentData {
[FieldOffset(0x0C)] public ushort CrystallizeAddonId; // MiragePrismPrismBoxCrystallize, the opener
[FieldOffset(0x0E)] public ushort PrismBoxAddonId; // MiragePrismPrismBoxAddonId
- [FieldOffset(0x10)] public SetConvertState State;
+ [FieldOffset(0x10)] public AddonState State;
[FieldOffset(0x14)] public uint SelectedSetIndex;
[FieldOffset(0x18)] public int ContextMenuItemIndex;
[FieldOffset(0x1C)] public uint YesNoAddonId;
@@ -42,8 +42,8 @@ public partial struct AgentData {
[FieldOffset(0x40), FixedSizeArray] internal FixedSizeArray5 _itemSets;
[FieldOffset(0x2C0)] public uint NumItemsInSet;
[FieldOffset(0x2C4), FixedSizeArray] internal FixedSizeArray9 _items;
- [FieldOffset(0x408)] private uint Unk408;
- [FieldOffset(0x40C)] private uint Unk40C;
+ [FieldOffset(0x408)] public uint HandInItemCount;
+ [FieldOffset(0x40C)] public uint HandInItemValidCount; // ones that are able to be turned in (i.e. 100% condition)
[FieldOffset(0x410), FixedSizeArray] internal FixedSizeArray190 _handIns;
[FieldOffset(0x18D8)] public Utf8String HandInItemName; // for tooltip?
@@ -86,7 +86,7 @@ public partial struct HandInItem {
}
}
-public enum SetConvertState : uint {
+public enum AddonState : uint {
None = 0, // idle/closed
Loading = 1, // loads the icons/names
Unk2 = 2,
diff --git a/ida/data.yml b/ida/data.yml
index 82964d8ef..9b5baab47 100644
--- a/ida/data.yml
+++ b/ida/data.yml
@@ -1840,6 +1840,8 @@ classes:
0x140893120: Clear
0x1408931E0: RequestPrismBox
0x140893380: IsSetSlotUnlocked
+ 0x1408935F0: StoreOutfitAsNewEntry
+ 0x140893840: StoreOutfitIntoExistingEntry
0x140893B20: RestorePrismBoxItem
0x140893D00: RestorePrismBoxSetItem
0x1408945F0: RequestGlamourPlates
@@ -14173,6 +14175,8 @@ classes:
funcs:
0x140DB0840: Open # todo: check this (7.4)
0x140DB0B10: OpenPreview
+ 0x140DB1EB0: PopulateHandInItems
+ 0x140DB2980: ValidateItems
Client::UI::Agent::AgentMiragePrismPrismSetConvert::AgentData:
funcs:
#fail 0x140C36B10: ctor # inlined (7.3)
From 5e5fdfec3d356c59e81840a6e61eea9f413e7754 Mon Sep 17 00:00:00 2001
From: Jackson <9527380+Jaksuhn@users.noreply.github.com>
Date: Sat, 27 Jun 2026 00:40:40 +0100
Subject: [PATCH 3/6] yeah they were right
---
.../FFXIV/Client/Game/MirageManager.cs | 18 ++++++++++++++++++
.../Agent/AgentMiragePrismPrismSetConvert.cs | 8 ++++++++
2 files changed, 26 insertions(+)
diff --git a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
index afe5f50e3..efd3f0f81 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
@@ -48,6 +48,24 @@ public unsafe partial struct MirageManager {
[MemberFunction("E8 ?? ?? ?? ?? 84 C0 75 ?? 0B F3")]
public partial bool IsSetSlotUnlocked(uint itemIndex, int slot);
+ ///
+ /// Deposits gear into dresser as a new outfit set.
+ ///
+ /// Which outfit set this is (MirageStoreSetItem row id).
+ /// Containers where each piece is. Must be in order of MirageStoreSetItem. Leftover slots use
+ /// Slots where each piece is. Leftovers must be 0.
+ [MemberFunction("E8 ?? ?? ?? ?? 84 C0 74 08 48 8B 47 28")]
+ public partial bool StoreOutfitAsNewPrismBoxEntry(uint setItemId, InventoryType* containers, ushort* slots);
+
+ ///
+ /// Deposits gear into dresser into an existing outfit set.
+ ///
+ /// Which dresser slot the outfit occupies ( index).
+ /// Same as
+ /// Same as
+ [MemberFunction("E8 ?? ?? ?? ?? EB 1A E8 ?? ?? ?? ?? 8B 57 40")]
+ public partial bool StoreOutfitIntoExistingPrismBoxEntry(uint prismBoxIndex, InventoryType* containers, ushort* slots);
+
[GenerateInterop]
[StructLayout(LayoutKind.Explicit, Size = 0x48)]
public partial struct GlamourPlate {
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
index cc4e40e22..a78441ea3 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismSetConvert.cs
@@ -18,6 +18,14 @@ public unsafe partial struct AgentMiragePrismPrismSetConvert {
// OpenPreview in data.yml
public void Open(uint itemId) => Open(itemId, InventoryType.Invalid, 0, 0, 0, false);
+ /// Scans inventory for matching pieces and populates .
+ [MemberFunction("E8 ?? ?? ?? ?? 83 BB ?? ?? ?? ?? ?? 74 AA")]
+ public partial void PopulateHandInItems(InventoryType container, int slot, int a3);
+
+ /// Validates and refreshes the SetConvert addon.
+ [MemberFunction("E9 ?? ?? ?? ?? 48 83 C4 28 41 5E 5D E9 ?? ?? ?? ?? 48 83 C4 28")]
+ public partial void ValidateItems();
+
[GenerateInterop]
[StructLayout(LayoutKind.Explicit, Size = 0x1940)]
public partial struct AgentData {
From a43e8c2701044004a669f8898d366e4a4ee54cd3 Mon Sep 17 00:00:00 2001
From: Jackson <9527380+Jaksuhn@users.noreply.github.com>
Date: Sat, 27 Jun 2026 00:45:53 +0100
Subject: [PATCH 4/6] Update MirageManager.cs
---
FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
index efd3f0f81..33e8b3b9a 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
@@ -1,3 +1,5 @@
+using FFXIVClientStructs.FFXIV.Client.UI.Agent;
+
namespace FFXIVClientStructs.FFXIV.Client.Game;
// Client::Game::MirageManager
@@ -51,7 +53,7 @@ public unsafe partial struct MirageManager {
///
/// Deposits gear into dresser as a new outfit set.
///
- /// Which outfit set this is (MirageStoreSetItem row id).
+ /// MirageStoreSetItem row id
/// Containers where each piece is. Must be in order of MirageStoreSetItem. Leftover slots use
/// Slots where each piece is. Leftovers must be 0.
[MemberFunction("E8 ?? ?? ?? ?? 84 C0 74 08 48 8B 47 28")]
@@ -60,7 +62,7 @@ public unsafe partial struct MirageManager {
///
/// Deposits gear into dresser into an existing outfit set.
///
- /// Which dresser slot the outfit occupies ( index).
+ /// index (see also )
/// Same as
/// Same as
[MemberFunction("E8 ?? ?? ?? ?? EB 1A E8 ?? ?? ?? ?? 8B 57 40")]
From 263d1905512a11637d9837f48975484abe0fd094 Mon Sep 17 00:00:00 2001
From: Jackson <9527380+Jaksuhn@users.noreply.github.com>
Date: Sat, 27 Jun 2026 11:56:34 +0100
Subject: [PATCH 5/6] crystallize nodes
---
.../UI/AddonMiragePrismPrismBoxCrystallize.cs | 24 +++++++++++++++++++
.../UI/Agent/AgentMiragePrismPrismBox.cs | 7 ++++++
.../Component/GUI/AtkComponentTreeList.cs | 3 +++
ida/data.yml | 9 +++++++
4 files changed, 43 insertions(+)
create mode 100644 FFXIVClientStructs/FFXIV/Client/UI/AddonMiragePrismPrismBoxCrystallize.cs
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/AddonMiragePrismPrismBoxCrystallize.cs b/FFXIVClientStructs/FFXIV/Client/UI/AddonMiragePrismPrismBoxCrystallize.cs
new file mode 100644
index 000000000..8995505d8
--- /dev/null
+++ b/FFXIVClientStructs/FFXIV/Client/UI/AddonMiragePrismPrismBoxCrystallize.cs
@@ -0,0 +1,24 @@
+using FFXIVClientStructs.FFXIV.Component.GUI;
+
+namespace FFXIVClientStructs.FFXIV.Client.UI;
+
+// Client::UI::AddonMiragePrismPrismBoxCrystallize
+// Component::GUI::AtkUnitBase
+// Component::GUI::AtkEventListener
+[Addon("MiragePrismPrismBoxCrystallize")]
+[GenerateInterop]
+[Inherits]
+[StructLayout(LayoutKind.Explicit, Size = 0x2E0)]
+public unsafe partial struct AddonMiragePrismPrismBoxCrystallize {
+ [FieldOffset(0x238)] public AtkComponentTreeList* ItemTreeList;
+ [FieldOffset(0x240)] private void* Unk240; // icon renderer?
+ [FieldOffset(0x248)] private void* Unk248; // text renderer?
+ [FieldOffset(0x250)] private void* Unk250; // I think it's some callback to the tree list populator
+ [FieldOffset(0x268)] public AtkComponentCheckBox* GearsetFilterCheckbox;
+ [FieldOffset(0x270), FixedSizeArray] internal FixedSizeArray6 _categoryLabels;
+ [FieldOffset(0x2A0)] private byte Unk2A0;
+ [FieldOffset(0x2A8)] public AtkComponentDropDownList* CategoryDropDown;
+ [FieldOffset(0x2B0)] public AtkComponentButton* CategoryPrevButton;
+ [FieldOffset(0x2B8)] public AtkComponentButton* CategoryNextButton;
+ [FieldOffset(0x2D8)] public bool IsTooltipVisible;
+}
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismBox.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismBox.cs
index 37147d6e3..4a45bbba7 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismBox.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentMiragePrismPrismBox.cs
@@ -24,6 +24,9 @@ public unsafe partial struct AgentMiragePrismPrismBox {
[MemberFunction("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 0F B6 43 3A")]
public partial void UpdateItems(bool resetTabIndex, bool a2);
+
+ [MemberFunction("E8 ?? ?? ?? ?? 84 C0 0F 84 ?? ?? ?? ?? 48 8B 46 28 C6 80 ?? ?? ?? ?? ??")]
+ public partial bool PopulateCrystallizeAndFireRefresh();
}
[GenerateInterop]
@@ -48,15 +51,19 @@ public unsafe partial struct MiragePrismPrismBoxData {
[FieldOffset(0x11AE70)] public uint ItemCount;
[FieldOffset(0x11AE74)] public uint FilterSettingsAddonId;
[FieldOffset(0x11AE78)] public bool IsPopulatingList;
+ [FieldOffset(0x11AE79)] public bool IsPopulatingComplete;
[FieldOffset(0x11AE7B)] private byte Unk11AE7B;
[FieldOffset(0x11AE7C)] public bool IsAddonReady;
[FieldOffset(0x11AE7D)] private byte Unk11AE7D;
[FieldOffset(0x11AE7E)] private byte Unk11AE7E;
[FieldOffset(0x11AE7F)] public bool IsPositionSaved;
+ [FieldOffset(0x11AE80)] private int Unk11AE80; // something with the category
[FieldOffset(0x11AE84)] public int CrystallizeCategory;
[FieldOffset(0x11AE88)] public ushort CrystallizeItemIndex;
[FieldOffset(0x11AE8A)] public ushort CrystallizeItemCount;
+ [FieldOffset(0x11AE8C)] public ushort CrystallizeTreeRowCount;
+ [FieldOffset(0x11AE8E)] private ushort Unk11AE8E; // cursor related?
[FieldOffset(0x11AE90), FixedSizeArray] internal FixedSizeArray140 _crystallizeItems;
[FieldOffset(0x11BDE0)] public PrismBoxCrystallizeItem CrystallizeSelectedItem;
diff --git a/FFXIVClientStructs/FFXIV/Component/GUI/AtkComponentTreeList.cs b/FFXIVClientStructs/FFXIV/Component/GUI/AtkComponentTreeList.cs
index 4edaefbbb..85c2625d6 100644
--- a/FFXIVClientStructs/FFXIV/Component/GUI/AtkComponentTreeList.cs
+++ b/FFXIVClientStructs/FFXIV/Component/GUI/AtkComponentTreeList.cs
@@ -28,6 +28,9 @@ public unsafe partial struct AtkComponentTreeList : ICreatable
Date: Sun, 28 Jun 2026 13:32:58 +0100
Subject: [PATCH 6/6] change name
---
FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs | 8 ++++----
ida/data.yml | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
index 33e8b3b9a..d71db4165 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/MirageManager.cs
@@ -57,16 +57,16 @@ public unsafe partial struct MirageManager {
/// Containers where each piece is. Must be in order of MirageStoreSetItem. Leftover slots use
/// Slots where each piece is. Leftovers must be 0.
[MemberFunction("E8 ?? ?? ?? ?? 84 C0 74 08 48 8B 47 28")]
- public partial bool StoreOutfitAsNewPrismBoxEntry(uint setItemId, InventoryType* containers, ushort* slots);
+ public partial bool StoreNewOutfit(uint setItemId, InventoryType* containers, ushort* slots);
///
/// Deposits gear into dresser into an existing outfit set.
///
/// index (see also )
- /// Same as
- /// Same as
+ /// Same as
+ /// Same as
[MemberFunction("E8 ?? ?? ?? ?? EB 1A E8 ?? ?? ?? ?? 8B 57 40")]
- public partial bool StoreOutfitIntoExistingPrismBoxEntry(uint prismBoxIndex, InventoryType* containers, ushort* slots);
+ public partial bool StoreExistingOutfit(uint prismBoxIndex, InventoryType* containers, ushort* slots);
[GenerateInterop]
[StructLayout(LayoutKind.Explicit, Size = 0x48)]
diff --git a/ida/data.yml b/ida/data.yml
index fbdc3e787..5e55efdbd 100644
--- a/ida/data.yml
+++ b/ida/data.yml
@@ -1840,8 +1840,8 @@ classes:
0x140893120: Clear
0x1408931E0: RequestPrismBox
0x140893380: IsSetSlotUnlocked
- 0x1408935F0: StoreOutfitAsNewEntry
- 0x140893840: StoreOutfitIntoExistingEntry
+ 0x1408935F0: StoreNewOutfit
+ 0x140893840: StoreExistingOutfit
0x140893B20: RestorePrismBoxItem
0x140893D00: RestorePrismBoxSetItem
0x1408945F0: RequestGlamourPlates