mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge remote-tracking branch 'origin/master' into net9-rollup
This commit is contained in:
commit
a8f3098d74
12 changed files with 583 additions and 34 deletions
|
|
@ -25,8 +25,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lumina" Version="5.2.1" />
|
||||
<PackageReference Include="Lumina.Excel" Version="7.1.0" />
|
||||
<PackageReference Include="Lumina" Version="5.4.0" />
|
||||
<PackageReference Include="Lumina.Excel" Version="7.1.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.333">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@
|
|||
<PackageReference Include="goaaats.Reloaded.Hooks" Version="4.2.0-goat.4" />
|
||||
<PackageReference Include="goaaats.Reloaded.Assembler" Version="1.0.14-goat.2" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" />
|
||||
<PackageReference Include="Lumina" Version="5.2.1" />
|
||||
<PackageReference Include="Lumina.Excel" Version="7.1.0" />
|
||||
<PackageReference Include="Lumina" Version="5.4.0" />
|
||||
<PackageReference Include="Lumina.Excel" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0-preview.1.24081.5" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.46-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ internal class JobGauges : IServiceType, IJobGauges
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public unsafe IntPtr Address => (nint)(CSJobGaugeManager.Instance()->CurrentGauge);
|
||||
public unsafe IntPtr Address => (nint)(&CSJobGaugeManager.Instance()->EmptyGauge);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T Get<T>() where T : JobGaugeBase
|
||||
|
|
|
|||
|
|
@ -1436,4 +1436,46 @@ public enum SystemConfigOption
|
|||
/// </summary>
|
||||
[GameConfigOption("PadButton_R3", ConfigType.String)]
|
||||
PadButton_R3,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name ActiveInstanceGuid.
|
||||
/// This option is a String.
|
||||
/// </summary>
|
||||
[GameConfigOption("ActiveInstanceGuid", ConfigType.String)]
|
||||
ActiveInstanceGuid,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name ActiveProductGuid.
|
||||
/// This option is a String.
|
||||
/// </summary>
|
||||
[GameConfigOption("ActiveProductGuid", ConfigType.String)]
|
||||
ActiveProductGuid,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name MsqProgress.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("MsqProgress", ConfigType.UInt)]
|
||||
MsqProgress,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name PromptConfigUpdate.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("PromptConfigUpdate", ConfigType.UInt)]
|
||||
PromptConfigUpdate,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name TitleScreenType.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("TitleScreenType", ConfigType.UInt)]
|
||||
TitleScreenType,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name FirstConfigBackup.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("FirstConfigBackup", ConfigType.UInt)]
|
||||
FirstConfigBackup,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ public enum UiConfigOption
|
|||
/// System option with the internal name LockonDefaultZoom_179.
|
||||
/// This option is a Float.
|
||||
/// </summary>
|
||||
[Obsolete("This option won't work. Use LockonDefaultZoom.")]
|
||||
[GameConfigOption("LockonDefaultZoom_179", ConfigType.Float)]
|
||||
LockonDefaultZoom_179,
|
||||
|
||||
|
|
@ -3578,4 +3579,25 @@ public enum UiConfigOption
|
|||
/// </summary>
|
||||
[GameConfigOption("PadMode", ConfigType.UInt)]
|
||||
PadMode,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name EnableMoveTiltCharacter.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("EnableMoveTiltCharacter", ConfigType.UInt)]
|
||||
EnableMoveTiltCharacter,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name EnableMoveTiltMountGround.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("EnableMoveTiltMountGround", ConfigType.UInt)]
|
||||
EnableMoveTiltMountGround,
|
||||
|
||||
/// <summary>
|
||||
/// System option with the internal name EnableMoveTiltMountFly.
|
||||
/// This option is a UInt.
|
||||
/// </summary>
|
||||
[GameConfigOption("EnableMoveTiltMountFly", ConfigType.UInt)]
|
||||
EnableMoveTiltMountFly,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
{
|
||||
private static readonly ModuleLog Log = new("GameGui");
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly Framework framework = Service<Framework>.Get();
|
||||
|
||||
private readonly GameGuiAddressResolver address;
|
||||
|
||||
private readonly Hook<SetGlobalBgmDelegate> setGlobalBgmHook;
|
||||
private readonly Hook<AgentItemDetail.Delegates.Update> handleItemHoverHook;
|
||||
private readonly Hook<AgentItemDetail.Delegates.ReceiveEvent> handleItemOutHook;
|
||||
private readonly Hook<AgentActionDetail.Delegates.HandleActionHover> handleActionHoverHook;
|
||||
private readonly Hook<AgentActionDetail.Delegates.ReceiveEvent> handleActionOutHook;
|
||||
private readonly Hook<HandleImmDelegate> handleImmHook;
|
||||
|
|
@ -57,6 +56,9 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
|
||||
this.setGlobalBgmHook = Hook<SetGlobalBgmDelegate>.FromAddress(this.address.SetGlobalBgm, this.HandleSetGlobalBgmDetour);
|
||||
|
||||
this.handleItemHoverHook = Hook<AgentItemDetail.Delegates.Update>.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->Update, this.HandleItemHoverDetour);
|
||||
this.handleItemOutHook = Hook<AgentItemDetail.Delegates.ReceiveEvent>.FromAddress((nint)AgentItemDetail.StaticVirtualTablePointer->ReceiveEvent, this.HandleItemOutDetour);
|
||||
|
||||
this.handleActionHoverHook = Hook<AgentActionDetail.Delegates.HandleActionHover>.FromAddress(AgentActionDetail.Addresses.HandleActionHover.Value, this.HandleActionHoverDetour);
|
||||
this.handleActionOutHook = Hook<AgentActionDetail.Delegates.ReceiveEvent>.FromAddress((nint)AgentActionDetail.StaticVirtualTablePointer->ReceiveEvent, this.HandleActionOutDetour);
|
||||
|
||||
|
|
@ -67,13 +69,13 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
this.utf8StringFromSequenceHook = Hook<Utf8String.Delegates.Ctor_FromSequence>.FromAddress(Utf8String.Addresses.Ctor_FromSequence.Value, this.Utf8StringFromSequenceDetour);
|
||||
|
||||
this.setGlobalBgmHook.Enable();
|
||||
this.handleItemHoverHook.Enable();
|
||||
this.handleItemOutHook.Enable();
|
||||
this.handleImmHook.Enable();
|
||||
this.setUiVisibilityHook.Enable();
|
||||
this.handleActionHoverHook.Enable();
|
||||
this.handleActionOutHook.Enable();
|
||||
this.utf8StringFromSequenceHook.Enable();
|
||||
|
||||
this.framework.Update += this.FrameworkUpdate;
|
||||
}
|
||||
|
||||
// Hooked delegates
|
||||
|
|
@ -252,9 +254,9 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
/// </summary>
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
this.framework.Update -= this.FrameworkUpdate;
|
||||
|
||||
this.setGlobalBgmHook.Dispose();
|
||||
this.handleItemHoverHook.Dispose();
|
||||
this.handleItemOutHook.Dispose();
|
||||
this.handleImmHook.Dispose();
|
||||
this.setUiVisibilityHook.Dispose();
|
||||
this.handleActionHoverHook.Dispose();
|
||||
|
|
@ -300,6 +302,46 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void HandleItemHoverDetour(AgentItemDetail* thisPtr, uint frameCount)
|
||||
{
|
||||
this.handleItemHoverHook.Original(thisPtr, frameCount);
|
||||
|
||||
if (!thisPtr->IsAgentActive())
|
||||
return;
|
||||
|
||||
var itemId = (ulong)thisPtr->ItemId;
|
||||
if (this.HoveredItem == itemId)
|
||||
return;
|
||||
|
||||
this.HoveredItem = itemId;
|
||||
this.HoveredItemChanged?.InvokeSafely(this, itemId);
|
||||
|
||||
Log.Verbose($"HoveredItem changed: {itemId}");
|
||||
}
|
||||
|
||||
private AtkValue* HandleItemOutDetour(AgentItemDetail* thisPtr, AtkValue* returnValue, AtkValue* values, uint valueCount, ulong eventKind)
|
||||
{
|
||||
var ret = this.handleItemOutHook.Original(thisPtr, returnValue, values, valueCount, eventKind);
|
||||
|
||||
if (values != null && valueCount == 1 && values->Int == -1)
|
||||
{
|
||||
this.HoveredItem = 0;
|
||||
|
||||
try
|
||||
{
|
||||
this.HoveredItemChanged?.Invoke(this, 0);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Could not dispatch HoveredItemChanged event.");
|
||||
}
|
||||
|
||||
Log.Verbose("HoveredItem changed: 0");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void HandleActionHoverDetour(AgentActionDetail* hoverState, ActionKind actionKind, uint actionId, int a4, byte a5)
|
||||
{
|
||||
this.handleActionHoverHook.Original(hoverState, actionKind, actionId, a4, a5);
|
||||
|
|
@ -371,24 +413,6 @@ internal sealed unsafe class GameGui : IInternalDisposableService, IGameGui
|
|||
|
||||
return thisPtr; // this function shouldn't need to return but the original asm moves this into rax before returning so be safe?
|
||||
}
|
||||
|
||||
private unsafe void FrameworkUpdate(IFramework framework)
|
||||
{
|
||||
var agentItemDetail = AgentItemDetail.Instance();
|
||||
if (agentItemDetail != null)
|
||||
{
|
||||
var itemId = agentItemDetail->ItemId;
|
||||
|
||||
if (this.HoveredItem != itemId)
|
||||
{
|
||||
Log.Verbose($"HoveredItem changed: {itemId}");
|
||||
|
||||
this.HoveredItem = itemId;
|
||||
|
||||
this.HoveredItemChanged?.InvokeSafely(this, itemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ public unsafe struct GameInventoryItem : IEquatable<GameInventoryItem>
|
|||
/// <summary>
|
||||
/// Gets the color used for this item.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<ushort> Stains => new(Unsafe.AsPointer(ref this.InternalItem.Stains[0]), 2);
|
||||
public ReadOnlySpan<byte> Stains => new(Unsafe.AsPointer(ref this.InternalItem.Stains[0]), 2);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the glamour id for this item.
|
||||
|
|
|
|||
|
|
@ -766,4 +766,54 @@ public enum SeIconChar
|
|||
/// The Japanese Eorzea time icon unicode character.
|
||||
/// </summary>
|
||||
EorzeaTimeJa = 0xE0DB,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 0 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber0 = 0xE0E0,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 1 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber1 = 0xE0E1,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 2 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber2 = 0xE0E2,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 3 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber3 = 0xE0E3,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 4 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber4 = 0xE0E4,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 5 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber5 = 0xE0E5,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 6 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber6 = 0xE0E6,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 7 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber7 = 0xE0E7,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 8 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber8 = 0xE0E8,
|
||||
|
||||
/// <summary>
|
||||
/// The boxed, outlined number 9 icon unicode character.
|
||||
/// </summary>
|
||||
BoxedOutlinedNumber9 = 0xE0E9,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ internal class DataWindow : Window, IDisposable
|
|||
new HookWidget(),
|
||||
new IconBrowserWidget(),
|
||||
new ImGuiWidget(),
|
||||
new InventoryWidget(),
|
||||
new KeyStateWidget(),
|
||||
new MarketBoardWidget(),
|
||||
new NetworkMonitorWidget(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,405 @@
|
|||
using System.Buffers.Binary;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game.Inventory;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Interface.Textures;
|
||||
using Dalamud.Interface.Textures.Internal;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
using Lumina.Excel.Sheets;
|
||||
|
||||
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
|
||||
|
||||
#pragma warning disable SeStringRenderer
|
||||
|
||||
/// <summary>
|
||||
/// Widget for displaying inventory data.
|
||||
/// </summary>
|
||||
internal class InventoryWidget : IDataWindowWidget
|
||||
{
|
||||
private DataManager dataManager;
|
||||
private TextureManager textureManager;
|
||||
private InventoryType? selectedInventoryType = InventoryType.Inventory1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string[]? CommandShortcuts { get; init; } = ["inv", "inventory"];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string DisplayName { get; init; } = "Inventory";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Ready { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load()
|
||||
{
|
||||
this.Ready = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Draw()
|
||||
{
|
||||
this.dataManager ??= Service<DataManager>.Get();
|
||||
this.textureManager ??= Service<TextureManager>.Get();
|
||||
|
||||
this.DrawInventoryTypeList();
|
||||
|
||||
if (this.selectedInventoryType == null)
|
||||
return;
|
||||
|
||||
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
||||
|
||||
this.DrawInventoryType((InventoryType)this.selectedInventoryType);
|
||||
}
|
||||
|
||||
private static string StripSoftHypen(string input)
|
||||
{
|
||||
return input.Replace("\u00AD", string.Empty);
|
||||
}
|
||||
|
||||
private unsafe void DrawInventoryTypeList()
|
||||
{
|
||||
using var table = ImRaii.Table("InventoryTypeTable", 2, ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY | ImGuiTableFlags.NoSavedSettings, new Vector2(300, -1));
|
||||
if (!table) return;
|
||||
|
||||
ImGui.TableSetupColumn("Type");
|
||||
ImGui.TableSetupColumn("Size", ImGuiTableColumnFlags.WidthFixed, 40);
|
||||
ImGui.TableSetupScrollFreeze(2, 1);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
foreach (var inventoryType in Enum.GetValues<InventoryType>())
|
||||
{
|
||||
var items = GameInventoryItem.GetReadOnlySpanOfInventory((GameInventoryType)inventoryType);
|
||||
|
||||
using var itemDisabled = ImRaii.Disabled(items.IsEmpty);
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn(); // Type
|
||||
if (ImGui.Selectable(inventoryType.ToString(), this.selectedInventoryType == inventoryType, ImGuiSelectableFlags.SpanAllColumns))
|
||||
{
|
||||
this.selectedInventoryType = inventoryType;
|
||||
}
|
||||
|
||||
using (var contextMenu = ImRaii.ContextPopupItem($"##InventoryContext{inventoryType}"))
|
||||
{
|
||||
if (contextMenu)
|
||||
{
|
||||
if (ImGui.MenuItem("Copy Name"))
|
||||
{
|
||||
ImGui.SetClipboardText(inventoryType.ToString());
|
||||
}
|
||||
|
||||
if (ImGui.MenuItem("Copy Address"))
|
||||
{
|
||||
var container = InventoryManager.Instance()->GetInventoryContainer(inventoryType);
|
||||
ImGui.SetClipboardText($"0x{(nint)container:X}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn(); // Size
|
||||
ImGui.TextUnformatted(items.Length.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void DrawInventoryType(InventoryType inventoryType)
|
||||
{
|
||||
var items = GameInventoryItem.GetReadOnlySpanOfInventory((GameInventoryType)inventoryType);
|
||||
if (items.IsEmpty)
|
||||
{
|
||||
ImGui.TextUnformatted($"{inventoryType} is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
using var itemTable = ImRaii.Table("InventoryItemTable", 4, ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.ScrollY | ImGuiTableFlags.NoSavedSettings);
|
||||
if (!itemTable) return;
|
||||
ImGui.TableSetupColumn("Slot", ImGuiTableColumnFlags.WidthFixed, 40);
|
||||
ImGui.TableSetupColumn("ItemId", ImGuiTableColumnFlags.WidthFixed, 70);
|
||||
ImGui.TableSetupColumn("Quantity", ImGuiTableColumnFlags.WidthFixed, 70);
|
||||
ImGui.TableSetupColumn("Item");
|
||||
ImGui.TableSetupScrollFreeze(0, 1);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
for (var slotIndex = 0; slotIndex < items.Length; slotIndex++)
|
||||
{
|
||||
var item = items[slotIndex];
|
||||
|
||||
using var disableditem = ImRaii.Disabled(item.ItemId == 0);
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn(); // Slot
|
||||
ImGui.TextUnformatted(slotIndex.ToString());
|
||||
|
||||
ImGui.TableNextColumn(); // ItemId
|
||||
ImGuiHelpers.ClickToCopyText(item.ItemId.ToString());
|
||||
|
||||
ImGui.TableNextColumn(); // Quantity
|
||||
ImGuiHelpers.ClickToCopyText(item.Quantity.ToString());
|
||||
|
||||
ImGui.TableNextColumn(); // Item
|
||||
if (item.ItemId != 0 && item.Quantity != 0)
|
||||
{
|
||||
var itemName = this.GetItemName(item.ItemId);
|
||||
var iconId = this.GetItemIconId(item.ItemId);
|
||||
|
||||
if (item.IsHq)
|
||||
itemName += " " + SeIconChar.HighQuality.ToIconString();
|
||||
|
||||
if (this.textureManager.Shared.TryGetFromGameIcon(new GameIconLookup(iconId, item.IsHq), out var tex) && tex.TryGetWrap(out var texture, out _))
|
||||
{
|
||||
ImGui.Image(texture.ImGuiHandle, new Vector2(ImGui.GetTextLineHeight()));
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.TextUnformatted("Click to copy IconId");
|
||||
ImGui.TextUnformatted($"ID: {iconId} – Size: {texture.Width}x{texture.Height}");
|
||||
ImGui.Image(texture.ImGuiHandle, new(texture.Width, texture.Height));
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
ImGui.SetClipboardText(iconId.ToString());
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
using var itemNameColor = ImRaii.PushColor(ImGuiCol.Text, this.GetItemRarityColor(item.ItemId));
|
||||
using var node = ImRaii.TreeNode($"{itemName}###{inventoryType}_{slotIndex}", ImGuiTreeNodeFlags.SpanAvailWidth);
|
||||
itemNameColor.Dispose();
|
||||
|
||||
using (var contextMenu = ImRaii.ContextPopupItem($"{inventoryType}_{slotIndex}_ContextMenu"))
|
||||
{
|
||||
if (contextMenu)
|
||||
{
|
||||
if (ImGui.MenuItem("Copy Name"))
|
||||
{
|
||||
ImGui.SetClipboardText(itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!node) continue;
|
||||
|
||||
using var itemInfoTable = ImRaii.Table($"{inventoryType}_{slotIndex}_Table", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
|
||||
if (!itemInfoTable) continue;
|
||||
|
||||
ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 150);
|
||||
ImGui.TableSetupColumn("Value");
|
||||
// ImGui.TableHeadersRow();
|
||||
|
||||
static void AddKeyValueRow(string fieldName, string value)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted(fieldName);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiHelpers.ClickToCopyText(value);
|
||||
}
|
||||
|
||||
static void AddValueValueRow(string value1, string value2)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiHelpers.ClickToCopyText(value1);
|
||||
ImGui.TableNextColumn();
|
||||
ImGuiHelpers.ClickToCopyText(value2);
|
||||
}
|
||||
|
||||
AddKeyValueRow("ItemId", item.ItemId.ToString());
|
||||
AddKeyValueRow("Quantity", item.Quantity.ToString());
|
||||
AddKeyValueRow("GlamourId", item.GlamourId.ToString());
|
||||
|
||||
if (!this.IsEventItem(item.ItemId))
|
||||
{
|
||||
AddKeyValueRow(item.IsCollectable ? "Collectability" : "Spiritbond", item.Spiritbond.ToString());
|
||||
|
||||
if (item.CrafterContentId != 0)
|
||||
AddKeyValueRow("CrafterContentId", item.CrafterContentId.ToString());
|
||||
}
|
||||
|
||||
var flagsBuilder = new StringBuilder();
|
||||
|
||||
if (item.IsHq)
|
||||
{
|
||||
flagsBuilder.Append("IsHq");
|
||||
}
|
||||
|
||||
if (item.IsCompanyCrestApplied)
|
||||
{
|
||||
if (flagsBuilder.Length != 0)
|
||||
flagsBuilder.Append(", ");
|
||||
|
||||
flagsBuilder.Append("IsCompanyCrestApplied");
|
||||
}
|
||||
|
||||
if (item.IsRelic)
|
||||
{
|
||||
if (flagsBuilder.Length != 0)
|
||||
flagsBuilder.Append(", ");
|
||||
|
||||
flagsBuilder.Append("IsRelic");
|
||||
}
|
||||
|
||||
if (item.IsCollectable)
|
||||
{
|
||||
if (flagsBuilder.Length != 0)
|
||||
flagsBuilder.Append(", ");
|
||||
|
||||
flagsBuilder.Append("IsCollectable");
|
||||
}
|
||||
|
||||
if (flagsBuilder.Length == 0)
|
||||
flagsBuilder.Append("None");
|
||||
|
||||
AddKeyValueRow("Flags", flagsBuilder.ToString());
|
||||
|
||||
if (this.IsNormalItem(item.ItemId) && this.dataManager.Excel.GetSheet<Item>().TryGetRow(item.ItemId, out var itemRow))
|
||||
{
|
||||
if (itemRow.DyeCount > 0)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted("Stains");
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
using var stainTable = ImRaii.Table($"{inventoryType}_{slotIndex}_StainTable", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
|
||||
if (!stainTable) continue;
|
||||
|
||||
ImGui.TableSetupColumn("Stain Id", ImGuiTableColumnFlags.WidthFixed, 80);
|
||||
ImGui.TableSetupColumn("Name");
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
for (var i = 0; i < itemRow.DyeCount; i++)
|
||||
{
|
||||
AddValueValueRow(item.Stains[i].ToString(), this.GetStainName(item.Stains[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (itemRow.MateriaSlotCount > 0)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.TextUnformatted("Materia");
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
using var materiaTable = ImRaii.Table($"{inventoryType}_{slotIndex}_MateriaTable", 2, ImGuiTableFlags.BordersInner | ImGuiTableFlags.NoSavedSettings);
|
||||
if (!materiaTable) continue;
|
||||
|
||||
ImGui.TableSetupColumn("Materia Id", ImGuiTableColumnFlags.WidthFixed, 80);
|
||||
ImGui.TableSetupColumn("MateriaGrade Id");
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
for (var i = 0; i < Math.Min(itemRow.MateriaSlotCount, item.Materia.Length); i++)
|
||||
{
|
||||
AddValueValueRow(item.Materia[i].ToString(), item.MateriaGrade[i].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsEventItem(uint itemId) => itemId is > 2_000_000;
|
||||
|
||||
private bool IsHighQuality(uint itemId) => itemId is > 1_000_000 and < 2_000_000;
|
||||
|
||||
private bool IsCollectible(uint itemId) => itemId is > 500_000 and < 1_000_000;
|
||||
|
||||
private bool IsNormalItem(uint itemId) => itemId is < 500_000;
|
||||
|
||||
private uint GetBaseItemId(uint itemId)
|
||||
{
|
||||
if (this.IsEventItem(itemId)) return itemId; // uses EventItem sheet
|
||||
if (this.IsHighQuality(itemId)) return itemId - 1_000_000;
|
||||
if (this.IsCollectible(itemId)) return itemId - 500_000;
|
||||
return itemId;
|
||||
}
|
||||
|
||||
private string GetItemName(uint itemId)
|
||||
{
|
||||
// EventItem
|
||||
if (this.IsEventItem(itemId))
|
||||
{
|
||||
return this.dataManager.Excel.GetSheet<EventItem>().TryGetRow(itemId, out var eventItemRow)
|
||||
? StripSoftHypen(eventItemRow.Name.ExtractText())
|
||||
: $"EventItem#{itemId}";
|
||||
}
|
||||
|
||||
// HighQuality
|
||||
if (this.IsHighQuality(itemId))
|
||||
itemId -= 1_000_000;
|
||||
|
||||
// Collectible
|
||||
if (this.IsCollectible(itemId))
|
||||
itemId -= 500_000;
|
||||
|
||||
return this.dataManager.Excel.GetSheet<Item>().TryGetRow(itemId, out var itemRow)
|
||||
? StripSoftHypen(itemRow.Name.ExtractText())
|
||||
: $"Item#{itemId}";
|
||||
}
|
||||
|
||||
private string GetStainName(uint stainId)
|
||||
{
|
||||
return this.dataManager.Excel.GetSheet<Stain>().TryGetRow(stainId, out var stainRow)
|
||||
? StripSoftHypen(stainRow.Name.ExtractText())
|
||||
: $"Stain#{stainId}";
|
||||
}
|
||||
|
||||
private uint GetItemRarityColorType(Item item, bool isEdgeColor = false)
|
||||
{
|
||||
return (isEdgeColor ? 548u : 547u) + item.Rarity * 2u;
|
||||
}
|
||||
|
||||
private uint GetItemRarityColorType(uint itemId, bool isEdgeColor = false)
|
||||
{
|
||||
// EventItem
|
||||
if (this.IsEventItem(itemId))
|
||||
return this.GetItemRarityColorType(1, isEdgeColor);
|
||||
|
||||
if (!this.dataManager.Excel.GetSheet<Item>().TryGetRow(this.GetBaseItemId(itemId), out var item))
|
||||
return this.GetItemRarityColorType(1, isEdgeColor);
|
||||
|
||||
return this.GetItemRarityColorType(item, isEdgeColor);
|
||||
}
|
||||
|
||||
private uint GetItemRarityColor(uint itemId, bool isEdgeColor = false)
|
||||
{
|
||||
if (this.IsEventItem(itemId))
|
||||
return isEdgeColor ? 0xFF000000 : 0xFFFFFFFF;
|
||||
|
||||
if (!this.dataManager.Excel.GetSheet<Item>().TryGetRow(this.GetBaseItemId(itemId), out var item))
|
||||
return isEdgeColor ? 0xFF000000 : 0xFFFFFFFF;
|
||||
|
||||
var rowId = this.GetItemRarityColorType(item, isEdgeColor);
|
||||
return this.dataManager.Excel.GetSheet<UIColor>().TryGetRow(rowId, out var color)
|
||||
? BinaryPrimitives.ReverseEndianness(color.UIForeground) | 0xFF000000
|
||||
: 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
private uint GetItemIconId(uint itemId)
|
||||
{
|
||||
// EventItem
|
||||
if (this.IsEventItem(itemId))
|
||||
return this.dataManager.Excel.GetSheet<EventItem>().TryGetRow(itemId, out var eventItem) ? eventItem.Icon : 0u;
|
||||
|
||||
// HighQuality
|
||||
if (this.IsHighQuality(itemId))
|
||||
itemId -= 1_000_000;
|
||||
|
||||
// Collectible
|
||||
if (this.IsCollectible(itemId))
|
||||
itemId -= 500_000;
|
||||
|
||||
return this.dataManager.Excel.GetSheet<Item>().TryGetRow(itemId, out var item) ? item.Icon : 0u;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
using Dalamud.Game.Text;
|
||||
using ImGuiNET;
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -28,8 +30,11 @@ internal class SeFontTestWidget : IDataWindowWidget
|
|||
{
|
||||
var specialChars = string.Empty;
|
||||
|
||||
for (var i = 0xE020; i <= 0xE0DB; i++)
|
||||
specialChars += $"0x{i:X} - {(SeIconChar)i} - {(char)i}\n";
|
||||
var min = (char)Enum.GetValues<SeIconChar>().Min();
|
||||
var max = (char)Enum.GetValues<SeIconChar>().Max();
|
||||
|
||||
for (var i = min; i <= max; i++)
|
||||
specialChars += $"0x{(int)i:X} - {(SeIconChar)i} - {i}\n";
|
||||
|
||||
ImGui.TextUnformatted(specialChars);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit fca10adcab3911c1be79cb0753987a2a02b7e058
|
||||
Subproject commit 33a98af530e52d5b54714ec9f7704c07bf9fdd91
|
||||
Loading…
Add table
Add a link
Reference in a new issue