PvP hotbar fix: load saved PvE on zone leave then use live bars; Show Action ID in tooltips
- On leaving PvP, LoadSavedHotbar for all 10 bars (via TryRestorePvEHotbarsAfterLeavePvP in Framework update) and re-apply for ~2s so live Hotbars show PvE - GetSlotData always reads from live StandardHotbars so combo updates (e.g. Pictomancer) and icons work normally - Misc: Show Action ID option in Misc -> Tooltips; hotbar/party cooldown tooltips pass TooltipIdKind for Action vs Status IDs Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -52,50 +52,58 @@ namespace HSUI.Helpers
|
||||
|
||||
private void OnFrameworkUpdate(IFramework framework)
|
||||
{
|
||||
if (!_config.ActionChatLinkEnabled) return;
|
||||
|
||||
bool shiftHeld = ImGui.IsKeyDown(ImGuiKey.LeftShift) || ImGui.IsKeyDown(ImGuiKey.RightShift);
|
||||
bool leftClicked = ImGui.IsMouseClicked(ImGuiMouseButton.Left);
|
||||
|
||||
// ActionMenu must be visible
|
||||
var addon = Plugin.GameGui.GetAddonByName("ActionMenu", 1);
|
||||
if (addon == null || addon.Address == IntPtr.Zero)
|
||||
try
|
||||
{
|
||||
_pendingActionId = 0;
|
||||
return;
|
||||
}
|
||||
if (!_config.ActionChatLinkEnabled) return;
|
||||
|
||||
// Capture action: 1) Addon list (ActionList or TraitList); 2) HoveredAction only when mouse is over ActionMenu (excludes hotbars)
|
||||
if (shiftHeld)
|
||||
{
|
||||
if (TryGetHoveredActionFromAddon(addon.Address, out uint fromAddon))
|
||||
_pendingActionId = fromAddon;
|
||||
else if (IsMouseOverActionMenu(addon.Address) && !ActionBarsHitTestHelper.IsMouseOverAnyHSUIHotbar())
|
||||
bool shiftHeld = ImGui.IsKeyDown(ImGuiKey.LeftShift) || ImGui.IsKeyDown(ImGuiKey.RightShift);
|
||||
bool leftClicked = ImGui.IsMouseClicked(ImGuiMouseButton.Left);
|
||||
|
||||
// ActionMenu must be visible
|
||||
var addon = Plugin.GameGui.GetAddonByName("ActionMenu", 1);
|
||||
if (addon == null || addon.Address == IntPtr.Zero)
|
||||
{
|
||||
var ha = Plugin.GameGui.HoveredAction;
|
||||
if (ha != null && ha.ActionKind != HoverActionKind.None && ha.ActionID != 0)
|
||||
_pendingActionId = ha.ActionID;
|
||||
_pendingActionId = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture action: 1) Addon list (ActionList or TraitList); 2) HoveredAction only when mouse is over ActionMenu (excludes hotbars)
|
||||
if (shiftHeld)
|
||||
{
|
||||
if (TryGetHoveredActionFromAddon(addon.Address, out uint fromAddon))
|
||||
_pendingActionId = fromAddon;
|
||||
else if (IsMouseOverActionMenu(addon.Address) && !ActionBarsHitTestHelper.IsMouseOverAnyHSUIHotbar())
|
||||
{
|
||||
var ha = Plugin.GameGui.HoveredAction;
|
||||
if (ha != null && ha.ActionKind != HoverActionKind.None && ha.ActionID != 0)
|
||||
_pendingActionId = ha.ActionID;
|
||||
else
|
||||
_pendingActionId = 0;
|
||||
}
|
||||
else
|
||||
_pendingActionId = 0;
|
||||
}
|
||||
else
|
||||
_pendingActionId = 0;
|
||||
}
|
||||
else
|
||||
|
||||
// On shift+click, use captured action or HoveredAction as fallback
|
||||
if (!shiftHeld || !leftClicked) return;
|
||||
|
||||
if (_pendingActionId == 0) return;
|
||||
uint idToUse = _pendingActionId;
|
||||
|
||||
string? actionName = GetActionName(idToUse);
|
||||
if (string.IsNullOrWhiteSpace(actionName)) return;
|
||||
|
||||
string text = $"You should check out {actionName}";
|
||||
InsertOrCopyToChat(text);
|
||||
_pendingActionId = 0;
|
||||
|
||||
// On shift+click, use captured action or HoveredAction as fallback
|
||||
if (!shiftHeld || !leftClicked) return;
|
||||
|
||||
if (_pendingActionId == 0) return;
|
||||
uint idToUse = _pendingActionId;
|
||||
|
||||
string? actionName = GetActionName(idToUse);
|
||||
if (string.IsNullOrWhiteSpace(actionName)) return;
|
||||
|
||||
string text = $"You should check out {actionName}";
|
||||
InsertOrCopyToChat(text);
|
||||
_pendingActionId = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_pendingActionId = 0;
|
||||
Plugin.Logger.Warning($"[ActionChatLink] OnFrameworkUpdate: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Read action ID from AddonActionMenu. Tries ActionList and TraitList, HoveredItemIndex and HeldItemIndex.</summary>
|
||||
@@ -104,19 +112,26 @@ namespace HSUI.Helpers
|
||||
actionId = 0;
|
||||
if (addonAddress == IntPtr.Zero) return false;
|
||||
|
||||
var addon = (AddonActionMenu*)addonAddress;
|
||||
byte* basePtr = (byte*)addonAddress;
|
||||
|
||||
foreach (var list in new[] { addon->ActionList, addon->TraitList })
|
||||
try
|
||||
{
|
||||
if (list == null) continue;
|
||||
foreach (int idx in new[] { list->HoveredItemIndex, list->HeldItemIndex })
|
||||
var addon = (AddonActionMenu*)addonAddress;
|
||||
byte* basePtr = (byte*)addonAddress;
|
||||
|
||||
foreach (var list in new[] { addon->ActionList, addon->TraitList })
|
||||
{
|
||||
if (idx < 0 || idx >= 80) continue;
|
||||
actionId = *(uint*)(basePtr + 0x338 + idx * 0x38 + 0x14);
|
||||
if (actionId != 0) return true;
|
||||
if (list == null) continue;
|
||||
foreach (int idx in new[] { list->HoveredItemIndex, list->HeldItemIndex })
|
||||
{
|
||||
if (idx < 0 || idx >= 80) continue;
|
||||
actionId = *(uint*)(basePtr + 0x338 + idx * 0x38 + 0x14);
|
||||
if (actionId != 0) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Plugin.Logger.Verbose($"[ActionChatLink] TryGetHoveredActionFromAddon: {ex.Message}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -124,13 +139,21 @@ namespace HSUI.Helpers
|
||||
private static unsafe bool IsMouseOverActionMenu(IntPtr addonAddress)
|
||||
{
|
||||
if (addonAddress == IntPtr.Zero) return false;
|
||||
var addon = (AtkUnitBase*)addonAddress;
|
||||
var root = addon->RootNode;
|
||||
if (root == null || !addon->IsVisible) return false;
|
||||
try
|
||||
{
|
||||
var addon = (AtkUnitBase*)addonAddress;
|
||||
var root = addon->RootNode;
|
||||
if (root == null || !addon->IsVisible) return false;
|
||||
|
||||
var mp = ImGui.GetMousePos();
|
||||
float x = root->ScreenX, y = root->ScreenY, w = root->Width, h = root->Height;
|
||||
return mp.X >= x && mp.X < x + w && mp.Y >= y && mp.Y < y + h;
|
||||
var mp = ImGui.GetMousePos();
|
||||
float x = root->ScreenX, y = root->ScreenY, w = root->Width, h = root->Height;
|
||||
return mp.X >= x && mp.X < x + w && mp.Y >= y && mp.Y < y + h;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Plugin.Logger.Verbose($"[ActionChatLink] IsMouseOverActionMenu: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? GetActionName(uint actionId)
|
||||
|
||||
Reference in New Issue
Block a user