v1.0.2.5: More accurate hotbar cooldowns (ActionManager), fix tooltip cast/recast display

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-01-31 11:36:34 -05:00
parent 891eb59877
commit 95c4dfce38
6 changed files with 72 additions and 13 deletions
+3 -3
View File
@@ -9,9 +9,9 @@
<PropertyGroup> <PropertyGroup>
<AssemblyName>HSUI</AssemblyName> <AssemblyName>HSUI</AssemblyName>
<AssemblyVersion>1.0.2.4</AssemblyVersion> <AssemblyVersion>1.0.2.5</AssemblyVersion>
<FileVersion>1.0.2.4</FileVersion> <FileVersion>1.0.2.5</FileVersion>
<InformationalVersion>1.0.2.4</InformationalVersion> <InformationalVersion>1.0.2.5</InformationalVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
+1 -1
View File
@@ -2,7 +2,7 @@
"Author": "Knack117", "Author": "Knack117",
"Name": "HSUI", "Name": "HSUI",
"InternalName": "HSUI", "InternalName": "HSUI",
"AssemblyVersion": "1.0.2.4", "AssemblyVersion": "1.0.2.5",
"Description": "HSUI provides a highly configurable HUD replacement for FFXIV, recreated from DelvUI using KamiToolKit, FFXIVClientStructs, and Dalamud. Features unit frames, castbars, job gauges, nameplates, party frames, status effects, enemy list, configurable hotbars with drag-and-drop, and profiles.", "Description": "HSUI provides a highly configurable HUD replacement for FFXIV, recreated from DelvUI using KamiToolKit, FFXIVClientStructs, and Dalamud. Features unit frames, castbars, job gauges, nameplates, party frames, status effects, enemy list, configurable hotbars with drag-and-drop, and profiles.",
"ApplicableVersion": "any", "ApplicableVersion": "any",
"RepoUrl": "https://github.com/Knack117/HSUI", "RepoUrl": "https://github.com/Knack117/HSUI",
+57 -2
View File
@@ -3,10 +3,12 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Misc; using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using KamiToolKit.Controllers; using KamiToolKit.Controllers;
using static FFXIVClientStructs.FFXIV.Client.Game.ActionManager;
namespace HSUI.Helpers namespace HSUI.Helpers
{ {
@@ -114,19 +116,72 @@ namespace HSUI.Helpers
continue; continue;
} }
int secsLeft = 0;
int pct = slot->GetSlotActionCooldownPercentage(&secsLeft, 0);
bool usable = slot->IsSlotUsable(slot->ApparentSlotType, slot->ApparentActionId); bool usable = slot->IsSlotUsable(slot->ApparentSlotType, slot->ApparentActionId);
uint iconId = slot->IconId; uint iconId = slot->IconId;
uint actionId = slot->ApparentActionId; uint actionId = slot->ApparentActionId;
var slotType = slot->ApparentSlotType; var slotType = slot->ApparentSlotType;
(int pct, int secsLeft) = GetSlotCooldown(slot);
list.Add(new SlotInfo(iconId, false, usable, pct, secsLeft, actionId, slotType, keybind)); list.Add(new SlotInfo(iconId, false, usable, pct, secsLeft, actionId, slotType, keybind));
} }
return list; return list;
} }
/// <summary>
/// Gets cooldown for a hotbar slot. For Action/GeneralAction/PetAction, uses ActionManager recast API
/// (more accurate for adjusted IDs, recast groups). Falls back to slot's GetSlotActionCooldownPercentage for Items/Macros.
/// </summary>
private static unsafe (int CooldownPercent, int SecondsLeft) GetSlotCooldown(RaptureHotbarModule.HotbarSlot* slot)
{
if (slot == null) return (0, 0);
var slotType = slot->ApparentSlotType;
uint actionId = slot->ApparentActionId;
if (actionId == 0) return GetSlotCooldownFromSlot(slot);
var actionManager = ActionManager.Instance();
if (actionManager == null) return GetSlotCooldownFromSlot(slot);
ActionType? actionType = slotType switch
{
RaptureHotbarModule.HotbarSlotType.Action => ActionType.Action,
RaptureHotbarModule.HotbarSlotType.GeneralAction => ActionType.GeneralAction,
RaptureHotbarModule.HotbarSlotType.PetAction => ActionType.PetAction,
RaptureHotbarModule.HotbarSlotType.CraftAction => ActionType.CraftAction,
RaptureHotbarModule.HotbarSlotType.Item => ActionType.Item,
_ => null
};
if (actionType.HasValue)
{
// GetAdjustedActionId resolves Continuation, Egi Assaults, etc. Only applies to Action type
uint effectiveId = actionType.Value == ActionType.Action
? actionManager->GetAdjustedActionId(actionId)
: actionId;
float total = actionManager->GetRecastTime(actionType.Value, effectiveId);
float elapsed = actionManager->GetRecastTimeElapsed(actionType.Value, effectiveId);
if (total > 0.001f && elapsed < total)
{
float remaining = total - elapsed;
int pct = (int)Math.Clamp((remaining / total) * 100f, 0, 100);
int secsLeft = (int)Math.Ceiling(remaining);
return (pct, secsLeft);
}
}
return GetSlotCooldownFromSlot(slot);
}
private static unsafe (int CooldownPercent, int SecondsLeft) GetSlotCooldownFromSlot(RaptureHotbarModule.HotbarSlot* slot)
{
if (slot == null) return (0, 0);
int secsLeft = 0;
int pct = slot->GetSlotActionCooldownPercentage(&secsLeft, 0);
return (pct, secsLeft);
}
/// <summary> /// <summary>
/// Returns the default game keybind label for a hotbar slot (Hotbar 1: 1,2,...,0,-,=; Bar 2: Ctrl+1..12; etc.). /// Returns the default game keybind label for a hotbar slot (Hotbar 1: 1,2,...,0,-,=; Bar 2: Ctrl+1..12; etc.).
/// hotbarIndex 110, slotIndex 011. Used to mirror the default hotbar keybind display. /// hotbarIndex 110, slotIndex 011. Used to mirror the default hotbar keybind display.
+2 -2
View File
@@ -1378,8 +1378,8 @@ namespace HSUI.Interface.GeneralElements
try try
{ {
var parts = new List<string>(); var parts = new List<string>();
float castSec = action.Cast100ms / 100f; float castSec = action.Cast100ms / 10f; // Cast100ms/Recast100ms are in 100ms units
float recastSec = action.Recast100ms / 100f; float recastSec = action.Recast100ms / 10f;
if (castSec > 0) if (castSec > 0)
parts.Add($"Cast: {castSec:F1}s"); parts.Add($"Cast: {castSec:F1}s");
else else
+4
View File
@@ -1,3 +1,7 @@
# 1.0.2.5
- **Hotbars**: More accurate cooldown tracking using ActionManager recast API (fixes actions like Continuation, Egi Assaults).
- **Tooltips**: Fixed cast/recast display (60s was showing as 6.0s; correct Cast100ms/Recast100ms divisor).
# 1.0.2.4 # 1.0.2.4
- **HUD Layout**: Switched to proper HUD Layout config (AddonConfig) instead of memory reads. Uses authoritative ElementKind hashes from HUDManager for hiding default elements. Job gauges now use layout hashes. - **HUD Layout**: Switched to proper HUD Layout config (AddonConfig) instead of memory reads. Uses authoritative ElementKind hashes from HUDManager for hiding default elements. Job gauges now use layout hashes.
+5 -5
View File
@@ -4,9 +4,9 @@
"Name": "HSUI", "Name": "HSUI",
"Punchline": "A modern HUD replacement built for customization.", "Punchline": "A modern HUD replacement built for customization.",
"Description": "HSUI provides a highly configurable HUD replacement for FFXIV, recreated from DelvUI using KamiToolKit, FFXIVClientStructs, and Dalamud. Features unit frames, castbars, job gauges, nameplates, party frames, status effects, enemy list, configurable hotbars with drag-and-drop, and profiles.", "Description": "HSUI provides a highly configurable HUD replacement for FFXIV, recreated from DelvUI using KamiToolKit, FFXIVClientStructs, and Dalamud. Features unit frames, castbars, job gauges, nameplates, party frames, status effects, enemy list, configurable hotbars with drag-and-drop, and profiles.",
"Changelog": "HUD Layout: Use proper HUD config instead of memory reads. ElementKind hashes from HUDManager for hiding default elements.", "Changelog": "Hotbars: More accurate cooldown tracking. Tooltips: Fixed cast/recast display (60s was showing as 6.0s).",
"InternalName": "HSUI", "InternalName": "HSUI",
"AssemblyVersion": "1.0.2.4", "AssemblyVersion": "1.0.2.5",
"RepoUrl": "https://github.com/Knack117/HSUI", "RepoUrl": "https://github.com/Knack117/HSUI",
"ApplicableVersion": "any", "ApplicableVersion": "any",
"Tags": ["UI", "HUD", "Unit Frames", "Nameplates", "Party Frames", "Hotbars"], "Tags": ["UI", "HUD", "Unit Frames", "Nameplates", "Party Frames", "Hotbars"],
@@ -14,10 +14,10 @@
"DalamudApiLevel": 14, "DalamudApiLevel": 14,
"IconUrl": "https://raw.githubusercontent.com/Knack117/HSUI/main/Media/Images/icon.png", "IconUrl": "https://raw.githubusercontent.com/Knack117/HSUI/main/Media/Images/icon.png",
"ImageUrls": [], "ImageUrls": [],
"DownloadLinkInstall": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.4/latest.zip", "DownloadLinkInstall": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.5/latest.zip",
"IsHide": false, "IsHide": false,
"IsTestingExclusive": false, "IsTestingExclusive": false,
"DownloadLinkTesting": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.4/latest.zip", "DownloadLinkTesting": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.5/latest.zip",
"DownloadLinkUpdate": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.4/latest.zip" "DownloadLinkUpdate": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.5/latest.zip"
} }
] ]