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:
@@ -89,9 +89,48 @@ namespace HSUI.Helpers
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Track PvP state so we can restore PvE bars when leaving PvP (game sometimes leaves PvP data in StandardHotbars).</summary>
|
||||||
|
private static bool _pvpHotbarsActiveLastFrame;
|
||||||
|
private static bool _clientStatePvPLastFrame;
|
||||||
|
/// <summary>After leaving PvP, keep re-applying PvE load for this many frames in case the game overwrites.</summary>
|
||||||
|
private static int _restorePvEFramesLeft;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call once per frame (e.g. from Framework Update). When we detect leaving PvP, loads saved PvE hotbars into the live bars
|
||||||
|
/// and keeps re-applying for a short window so PvE actions are not overwritten by stale PvP state.
|
||||||
|
/// </summary>
|
||||||
|
public static unsafe void TryRestorePvEHotbarsAfterLeavePvP()
|
||||||
|
{
|
||||||
|
var module = RaptureHotbarModule.Instance();
|
||||||
|
if (module == null || !module->ModuleReady)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool pvpActive = module->PvPHotbarsActive;
|
||||||
|
bool clientPvP = Plugin.ClientState.IsPvP;
|
||||||
|
|
||||||
|
if (!pvpActive && !clientPvP)
|
||||||
|
{
|
||||||
|
bool justLeftPvP = _pvpHotbarsActiveLastFrame || _clientStatePvPLastFrame;
|
||||||
|
if (justLeftPvP)
|
||||||
|
_restorePvEFramesLeft = 120; // ~2s at 60fps
|
||||||
|
|
||||||
|
if (_restorePvEFramesLeft > 0)
|
||||||
|
{
|
||||||
|
uint classJobId = (uint)(module->ActiveHotbarClassJobId & 0x7F);
|
||||||
|
for (uint barId = 0; barId < 10; barId++)
|
||||||
|
module->LoadSavedHotbar(classJobId, barId);
|
||||||
|
_restorePvEFramesLeft--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_pvpHotbarsActiveLastFrame = pvpActive;
|
||||||
|
_clientStatePvPLastFrame = clientPvP;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads hotbar slot data from RaptureHotbarModule. Returns up to slotCount slots.
|
/// Reads hotbar slot data from RaptureHotbarModule. Returns up to slotCount slots.
|
||||||
/// hotbarIndex 1-10 maps to StandardHotbars 0-9.
|
/// hotbarIndex 1-10 maps to StandardHotbars 0-9.
|
||||||
|
/// Always reads from live Hotbars; when leaving PvP, TryRestorePvEHotbarsAfterLeavePvP loads saved PvE into live so we then show PvE.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe List<SlotInfo> GetSlotData(int hotbarIndex, int slotCount)
|
public unsafe List<SlotInfo> GetSlotData(int hotbarIndex, int slotCount)
|
||||||
{
|
{
|
||||||
@@ -100,11 +139,11 @@ namespace HSUI.Helpers
|
|||||||
if (module == null || !module->ModuleReady)
|
if (module == null || !module->ModuleReady)
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
var hotbars = module->StandardHotbars;
|
|
||||||
int barIdx = Math.Clamp(hotbarIndex, 1, 10) - 1;
|
int barIdx = Math.Clamp(hotbarIndex, 1, 10) - 1;
|
||||||
int count = Math.Clamp(slotCount, 1, 12);
|
int count = Math.Clamp(slotCount, 1, 12);
|
||||||
|
var hotbars = module->StandardHotbars;
|
||||||
ref var bar = ref hotbars[barIdx];
|
ref var bar = ref hotbars[barIdx];
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var slot = bar.GetHotbarSlot((uint)i);
|
var slot = bar.GetHotbarSlot((uint)i);
|
||||||
@@ -116,7 +155,6 @@ namespace HSUI.Helpers
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GearSet with id 0 is valid (first gearset); the game's IsEmpty (CommandId == 0) would wrongly treat it as empty.
|
|
||||||
bool isEmpty = slot->IsEmpty && slot->CommandType != RaptureHotbarModule.HotbarSlotType.GearSet;
|
bool isEmpty = slot->IsEmpty && slot->CommandType != RaptureHotbarModule.HotbarSlotType.GearSet;
|
||||||
if (isEmpty)
|
if (isEmpty)
|
||||||
{
|
{
|
||||||
@@ -124,7 +162,6 @@ namespace HSUI.Helpers
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use CommandType/CommandId for GearSet so we handle gearset 0 and slots not yet synced to Apparent*.
|
|
||||||
var slotType = slot->CommandType == RaptureHotbarModule.HotbarSlotType.GearSet
|
var slotType = slot->CommandType == RaptureHotbarModule.HotbarSlotType.GearSet
|
||||||
? RaptureHotbarModule.HotbarSlotType.GearSet
|
? RaptureHotbarModule.HotbarSlotType.GearSet
|
||||||
: slot->ApparentSlotType;
|
: slot->ApparentSlotType;
|
||||||
@@ -132,13 +169,11 @@ namespace HSUI.Helpers
|
|||||||
? slot->CommandId
|
? slot->CommandId
|
||||||
: slot->ApparentActionId;
|
: slot->ApparentActionId;
|
||||||
|
|
||||||
// For GearSet slots, refresh IconId from the gearset (e.g. job icon from first equipment slot).
|
|
||||||
if (slotType == RaptureHotbarModule.HotbarSlotType.GearSet)
|
if (slotType == RaptureHotbarModule.HotbarSlotType.GearSet)
|
||||||
slot->LoadIconId();
|
slot->LoadIconId();
|
||||||
|
|
||||||
bool usable = slot->IsSlotUsable(slotType, actionId);
|
bool usable = slot->IsSlotUsable(slotType, actionId);
|
||||||
uint iconId = slot->IconId;
|
uint iconId = slot->IconId;
|
||||||
// GearSet 0 or just-dropped: game may not have synced Apparent* so IconId can be 0; resolve for display.
|
|
||||||
if (slotType == RaptureHotbarModule.HotbarSlotType.GearSet && iconId == 0)
|
if (slotType == RaptureHotbarModule.HotbarSlotType.GearSet && iconId == 0)
|
||||||
{
|
{
|
||||||
int resolved = slot->GetIconIdForSlot(slotType, actionId);
|
int resolved = slot->GetIconIdForSlot(slotType, actionId);
|
||||||
@@ -148,8 +183,6 @@ namespace HSUI.Helpers
|
|||||||
|
|
||||||
(int pct, int secsLeft) = GetSlotCooldown(slot);
|
(int pct, int secsLeft) = GetSlotCooldown(slot);
|
||||||
(int currentCharges, int maxCharges) = GetSlotCharges(slotType, actionId);
|
(int currentCharges, int maxCharges) = GetSlotCharges(slotType, actionId);
|
||||||
// For charge-based actions, don't grey out the icon until all charges are spent.
|
|
||||||
// Use both the slot's recast-charge count and ActionManager so we catch all cases.
|
|
||||||
uint apparentCharges = slotType == RaptureHotbarModule.HotbarSlotType.Action ? slot->GetApparentIconRecastCharges() : 0;
|
uint apparentCharges = slotType == RaptureHotbarModule.HotbarSlotType.Action ? slot->GetApparentIconRecastCharges() : 0;
|
||||||
if (maxCharges > 1 && (apparentCharges > 0 || currentCharges > 0))
|
if (maxCharges > 1 && (apparentCharges > 0 || currentCharges > 0))
|
||||||
usable = true;
|
usable = true;
|
||||||
|
|||||||
@@ -52,50 +52,58 @@ namespace HSUI.Helpers
|
|||||||
|
|
||||||
private void OnFrameworkUpdate(IFramework framework)
|
private void OnFrameworkUpdate(IFramework framework)
|
||||||
{
|
{
|
||||||
if (!_config.ActionChatLinkEnabled) return;
|
try
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
_pendingActionId = 0;
|
if (!_config.ActionChatLinkEnabled) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capture action: 1) Addon list (ActionList or TraitList); 2) HoveredAction only when mouse is over ActionMenu (excludes hotbars)
|
bool shiftHeld = ImGui.IsKeyDown(ImGuiKey.LeftShift) || ImGui.IsKeyDown(ImGuiKey.RightShift);
|
||||||
if (shiftHeld)
|
bool leftClicked = ImGui.IsMouseClicked(ImGuiMouseButton.Left);
|
||||||
{
|
|
||||||
if (TryGetHoveredActionFromAddon(addon.Address, out uint fromAddon))
|
// ActionMenu must be visible
|
||||||
_pendingActionId = fromAddon;
|
var addon = Plugin.GameGui.GetAddonByName("ActionMenu", 1);
|
||||||
else if (IsMouseOverActionMenu(addon.Address) && !ActionBarsHitTestHelper.IsMouseOverAnyHSUIHotbar())
|
if (addon == null || addon.Address == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
var ha = Plugin.GameGui.HoveredAction;
|
_pendingActionId = 0;
|
||||||
if (ha != null && ha.ActionKind != HoverActionKind.None && ha.ActionID != 0)
|
return;
|
||||||
_pendingActionId = ha.ActionID;
|
}
|
||||||
|
|
||||||
|
// 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
|
else
|
||||||
_pendingActionId = 0;
|
_pendingActionId = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_pendingActionId = 0;
|
_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;
|
_pendingActionId = 0;
|
||||||
|
}
|
||||||
// On shift+click, use captured action or HoveredAction as fallback
|
catch (Exception ex)
|
||||||
if (!shiftHeld || !leftClicked) return;
|
{
|
||||||
|
_pendingActionId = 0;
|
||||||
if (_pendingActionId == 0) return;
|
Plugin.Logger.Warning($"[ActionChatLink] OnFrameworkUpdate: {ex.Message}");
|
||||||
uint idToUse = _pendingActionId;
|
}
|
||||||
|
|
||||||
string? actionName = GetActionName(idToUse);
|
|
||||||
if (string.IsNullOrWhiteSpace(actionName)) return;
|
|
||||||
|
|
||||||
string text = $"You should check out {actionName}";
|
|
||||||
InsertOrCopyToChat(text);
|
|
||||||
_pendingActionId = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Read action ID from AddonActionMenu. Tries ActionList and TraitList, HoveredItemIndex and HeldItemIndex.</summary>
|
/// <summary>Read action ID from AddonActionMenu. Tries ActionList and TraitList, HoveredItemIndex and HeldItemIndex.</summary>
|
||||||
@@ -104,19 +112,26 @@ namespace HSUI.Helpers
|
|||||||
actionId = 0;
|
actionId = 0;
|
||||||
if (addonAddress == IntPtr.Zero) return false;
|
if (addonAddress == IntPtr.Zero) return false;
|
||||||
|
|
||||||
var addon = (AddonActionMenu*)addonAddress;
|
try
|
||||||
byte* basePtr = (byte*)addonAddress;
|
|
||||||
|
|
||||||
foreach (var list in new[] { addon->ActionList, addon->TraitList })
|
|
||||||
{
|
{
|
||||||
if (list == null) continue;
|
var addon = (AddonActionMenu*)addonAddress;
|
||||||
foreach (int idx in new[] { list->HoveredItemIndex, list->HeldItemIndex })
|
byte* basePtr = (byte*)addonAddress;
|
||||||
|
|
||||||
|
foreach (var list in new[] { addon->ActionList, addon->TraitList })
|
||||||
{
|
{
|
||||||
if (idx < 0 || idx >= 80) continue;
|
if (list == null) continue;
|
||||||
actionId = *(uint*)(basePtr + 0x338 + idx * 0x38 + 0x14);
|
foreach (int idx in new[] { list->HoveredItemIndex, list->HeldItemIndex })
|
||||||
if (actionId != 0) return true;
|
{
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,13 +139,21 @@ namespace HSUI.Helpers
|
|||||||
private static unsafe bool IsMouseOverActionMenu(IntPtr addonAddress)
|
private static unsafe bool IsMouseOverActionMenu(IntPtr addonAddress)
|
||||||
{
|
{
|
||||||
if (addonAddress == IntPtr.Zero) return false;
|
if (addonAddress == IntPtr.Zero) return false;
|
||||||
var addon = (AtkUnitBase*)addonAddress;
|
try
|
||||||
var root = addon->RootNode;
|
{
|
||||||
if (root == null || !addon->IsVisible) return false;
|
var addon = (AtkUnitBase*)addonAddress;
|
||||||
|
var root = addon->RootNode;
|
||||||
|
if (root == null || !addon->IsVisible) return false;
|
||||||
|
|
||||||
var mp = ImGui.GetMousePos();
|
var mp = ImGui.GetMousePos();
|
||||||
float x = root->ScreenX, y = root->ScreenY, w = root->Width, h = root->Height;
|
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;
|
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)
|
private static string? GetActionName(uint actionId)
|
||||||
|
|||||||
+20
-10
@@ -470,18 +470,28 @@ namespace HSUI.Helpers
|
|||||||
|
|
||||||
public void OnFrameworkUpdate(IFramework framework)
|
public void OnFrameworkUpdate(IFramework framework)
|
||||||
{
|
{
|
||||||
// Keep WndProc hooked when: proxy mode (for mouseover) OR we need to block game drag
|
try
|
||||||
// release (so dropping on HSUI action bar doesn't execute the ability).
|
|
||||||
bool needHook = IsProxyEnabled || ShouldBlockGameDragRelease();
|
|
||||||
if (needHook && _wndProcPtr == IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
HookWndProc();
|
// When leaving PvP, force load PvE hotbars so HSUI bars don't keep showing PvP actions.
|
||||||
// Only log when we actually installed (HookWndProc can return early during init delay)
|
ActionBarsManager.TryRestorePvEHotbarsAfterLeavePvP();
|
||||||
if (_wndProcPtr != IntPtr.Zero && IsActionBarDragDropDebugEnabled())
|
|
||||||
Plugin.Logger.Information("[HSUI DragDrop DBG] WndProc hook INSTALLED (needHook=true for drag-block)");
|
// Keep WndProc hooked when: proxy mode (for mouseover) OR we need to block game drag
|
||||||
|
// release (so dropping on HSUI action bar doesn't execute the ability).
|
||||||
|
bool needHook = IsProxyEnabled || ShouldBlockGameDragRelease();
|
||||||
|
if (needHook && _wndProcPtr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
HookWndProc();
|
||||||
|
// Only log when we actually installed (HookWndProc can return early during init delay)
|
||||||
|
if (_wndProcPtr != IntPtr.Zero && IsActionBarDragDropDebugEnabled())
|
||||||
|
Plugin.Logger.Information("[HSUI DragDrop DBG] WndProc hook INSTALLED (needHook=true for drag-block)");
|
||||||
|
}
|
||||||
|
else if (!needHook && _wndProcPtr != IntPtr.Zero)
|
||||||
|
RestoreWndProc();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Plugin.Logger.Warning($"[HSUI InputsHelper] OnFrameworkUpdate: {ex.Message}");
|
||||||
}
|
}
|
||||||
else if (!needHook && _wndProcPtr != IntPtr.Zero)
|
|
||||||
RestoreWndProc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ShouldBlockGameDragRelease()
|
private static bool ShouldBlockGameDragRelease()
|
||||||
|
|||||||
+24
-25
@@ -43,35 +43,34 @@ namespace HSUI.Helpers
|
|||||||
|
|
||||||
private void FrameworkOnOnUpdateEvent(IFramework framework)
|
private void FrameworkOnOnUpdateEvent(IFramework framework)
|
||||||
{
|
{
|
||||||
var player = Plugin.ObjectTable.LocalPlayer;
|
try
|
||||||
if (player is null)
|
|
||||||
{
|
{
|
||||||
return;
|
var player = Plugin.ObjectTable.LocalPlayer;
|
||||||
}
|
if (player is null)
|
||||||
|
return;
|
||||||
|
|
||||||
var now = ImGui.GetTime();
|
var now = ImGui.GetTime();
|
||||||
if (now - LastUpdate < PollingRate)
|
if (now - LastUpdate < PollingRate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LastUpdate = now;
|
||||||
|
|
||||||
|
var mp = player.CurrentMp;
|
||||||
|
|
||||||
|
// account for lucid dreaming screwing up mp calculations
|
||||||
|
var lucidDreamingActive = Utils.StatusListForBattleChara(player).Any(e => e.StatusId == 1204);
|
||||||
|
|
||||||
|
if (!lucidDreamingActive && _lastMpValue < mp)
|
||||||
|
LastTickTime = now;
|
||||||
|
else if (LastTickTime + ServerTickRate <= now)
|
||||||
|
LastTickTime += ServerTickRate;
|
||||||
|
|
||||||
|
_lastMpValue = (int)mp;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return;
|
Plugin.Logger.Verbose($"[HSUI MpTickHelper] FrameworkOnOnUpdateEvent: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
LastUpdate = now;
|
|
||||||
|
|
||||||
var mp = player.CurrentMp;
|
|
||||||
|
|
||||||
// account for lucid dreaming screwing up mp calculations
|
|
||||||
var lucidDreamingActive = Utils.StatusListForBattleChara(player).Any(e => e.StatusId == 1204);
|
|
||||||
|
|
||||||
if (!lucidDreamingActive && _lastMpValue < mp)
|
|
||||||
{
|
|
||||||
LastTickTime = now;
|
|
||||||
}
|
|
||||||
else if (LastTickTime + ServerTickRate <= now)
|
|
||||||
{
|
|
||||||
LastTickTime += ServerTickRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastMpValue = (int)mp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ using System.Text;
|
|||||||
|
|
||||||
namespace HSUI.Helpers
|
namespace HSUI.Helpers
|
||||||
{
|
{
|
||||||
|
/// <summary>When showing an ID in the tooltip title, use Action for action IDs or Status for status effect IDs.</summary>
|
||||||
|
public enum TooltipIdKind
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Action = 1,
|
||||||
|
Status = 2,
|
||||||
|
}
|
||||||
|
|
||||||
public class TooltipsHelper : IDisposable
|
public class TooltipsHelper : IDisposable
|
||||||
{
|
{
|
||||||
#region Singleton
|
#region Singleton
|
||||||
@@ -65,12 +73,12 @@ namespace HSUI.Helpers
|
|||||||
|
|
||||||
private const float IconSize = 24f;
|
private const float IconSize = 24f;
|
||||||
|
|
||||||
public void ShowTooltipOnCursor(string text, string? title = null, uint id = 0, string name = "", uint? iconId = null)
|
public void ShowTooltipOnCursor(string text, string? title = null, uint id = 0, string name = "", uint? iconId = null, TooltipIdKind idKind = TooltipIdKind.None)
|
||||||
{
|
{
|
||||||
ShowTooltip(text, ImGui.GetMousePos(), title, id, name, iconId);
|
ShowTooltip(text, ImGui.GetMousePos(), title, id, name, iconId, idKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowTooltip(string text, Vector2 position, string? title = null, uint id = 0, string name = "", uint? iconId = null)
|
public void ShowTooltip(string text, Vector2 position, string? title = null, uint id = 0, string name = "", uint? iconId = null, TooltipIdKind idKind = TooltipIdKind.None)
|
||||||
{
|
{
|
||||||
if (text == null)
|
if (text == null)
|
||||||
{
|
{
|
||||||
@@ -99,7 +107,11 @@ namespace HSUI.Helpers
|
|||||||
_currentTooltipTitle += $" ({name})";
|
_currentTooltipTitle += $" ({name})";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.ShowStatusIDs)
|
bool showId = id != 0 && (
|
||||||
|
(idKind == TooltipIdKind.Action && _config.ShowActionIDs) ||
|
||||||
|
(idKind == TooltipIdKind.Status && _config.ShowStatusIDs) ||
|
||||||
|
(idKind == TooltipIdKind.None && _config.ShowStatusIDs));
|
||||||
|
if (showId)
|
||||||
{
|
{
|
||||||
_currentTooltipTitle += " (ID: " + id + ")";
|
_currentTooltipTitle += " (ID: " + id + ")";
|
||||||
}
|
}
|
||||||
@@ -407,6 +419,10 @@ namespace HSUI.Helpers
|
|||||||
[Order(7)]
|
[Order(7)]
|
||||||
public bool ShowStatusIDs = false;
|
public bool ShowStatusIDs = false;
|
||||||
|
|
||||||
|
[Checkbox("Show Action ID", help = "Show action ID in hotbar and action tooltips.")]
|
||||||
|
[Order(8)]
|
||||||
|
public bool ShowActionIDs = false;
|
||||||
|
|
||||||
[Checkbox("Show Source Name")]
|
[Checkbox("Show Source Name")]
|
||||||
[Order(10)]
|
[Order(10)]
|
||||||
public bool ShowSourceName = false;
|
public bool ShowSourceName = false;
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ namespace HSUI.Interface.GeneralElements
|
|||||||
if (!string.IsNullOrEmpty(title) || !string.IsNullOrEmpty(text))
|
if (!string.IsNullOrEmpty(title) || !string.IsNullOrEmpty(text))
|
||||||
{
|
{
|
||||||
string body = string.IsNullOrEmpty(text) ? title : text;
|
string body = string.IsNullOrEmpty(text) ? title : text;
|
||||||
TooltipsHelper.Instance.ShowTooltipOnCursor(body, title, slot.ActionId, "", slot.IconId > 0 ? slot.IconId : null);
|
TooltipsHelper.Instance.ShowTooltipOnCursor(body, title, slot.ActionId, "", slot.IconId > 0 ? slot.IconId : null, Helpers.TooltipIdKind.Action);
|
||||||
if (IsTooltipDebugEnabled())
|
if (IsTooltipDebugEnabled())
|
||||||
Plugin.Logger.Information($"[HSUI Tooltip DBG] ActionBar tooltip (main overlay): slot={i} title='{title}'");
|
Plugin.Logger.Information($"[HSUI Tooltip DBG] ActionBar tooltip (main overlay): slot={i} title='{title}'");
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,7 @@ namespace HSUI.Interface.GeneralElements
|
|||||||
if (!string.IsNullOrEmpty(title) || !string.IsNullOrEmpty(text))
|
if (!string.IsNullOrEmpty(title) || !string.IsNullOrEmpty(text))
|
||||||
{
|
{
|
||||||
string body = string.IsNullOrEmpty(text) ? title : text;
|
string body = string.IsNullOrEmpty(text) ? title : text;
|
||||||
TooltipsHelper.Instance.ShowTooltipOnCursor(body, title, slot.ActionId, "", slot.IconId > 0 ? slot.IconId : null);
|
TooltipsHelper.Instance.ShowTooltipOnCursor(body, title, slot.ActionId, "", slot.IconId > 0 ? slot.IconId : null, Helpers.TooltipIdKind.Action);
|
||||||
if (IsTooltipDebugEnabled())
|
if (IsTooltipDebugEnabled())
|
||||||
Plugin.Logger.Information($"[HSUI Tooltip DBG] ActionBar tooltip (overlay): slot={i} title='{title}'");
|
Plugin.Logger.Information($"[HSUI Tooltip DBG] ActionBar tooltip (overlay): slot={i} title='{title}'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,7 +289,8 @@ namespace HSUI.Interface.Party
|
|||||||
hoveringCooldown.Data.Name,
|
hoveringCooldown.Data.Name,
|
||||||
hoveringCooldown.Data.ActionId,
|
hoveringCooldown.Data.ActionId,
|
||||||
"",
|
"",
|
||||||
iconId
|
iconId,
|
||||||
|
HSUI.Helpers.TooltipIdKind.Action
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -310,7 +310,8 @@ namespace HSUI.Interface.PartyCooldowns
|
|||||||
cooldown.Data.Name,
|
cooldown.Data.Name,
|
||||||
cooldown.Data.ActionId,
|
cooldown.Data.ActionId,
|
||||||
"",
|
"",
|
||||||
iconId
|
iconId,
|
||||||
|
HSUI.Helpers.TooltipIdKind.Action
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -474,7 +474,8 @@ namespace HSUI.Interface.StatusEffects
|
|||||||
EncryptedStringsHelper.GetString(data.Data.Name.ToString()),
|
EncryptedStringsHelper.GetString(data.Data.Name.ToString()),
|
||||||
data.Status.StatusId,
|
data.Status.StatusId,
|
||||||
GetStatusActorName(data.Status),
|
GetStatusActorName(data.Status),
|
||||||
iconId
|
iconId,
|
||||||
|
HSUI.Helpers.TooltipIdKind.Status
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user