diff --git a/HSUI.csproj b/HSUI.csproj index 561ec70..316ea34 100644 --- a/HSUI.csproj +++ b/HSUI.csproj @@ -9,9 +9,9 @@ HSUI - 1.0.2.4 - 1.0.2.4 - 1.0.2.4 + 1.0.2.5 + 1.0.2.5 + 1.0.2.5 diff --git a/HSUI.json b/HSUI.json index 5dfd083..630c733 100644 --- a/HSUI.json +++ b/HSUI.json @@ -2,7 +2,7 @@ "Author": "Knack117", "Name": "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.", "ApplicableVersion": "any", "RepoUrl": "https://github.com/Knack117/HSUI", diff --git a/Helpers/ActionBarsManager.cs b/Helpers/ActionBarsManager.cs index a4cb42f..d3804f0 100644 --- a/Helpers/ActionBarsManager.cs +++ b/Helpers/ActionBarsManager.cs @@ -3,10 +3,12 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI.Misc; using KamiToolKit.Controllers; +using static FFXIVClientStructs.FFXIV.Client.Game.ActionManager; namespace HSUI.Helpers { @@ -114,19 +116,72 @@ namespace HSUI.Helpers continue; } - int secsLeft = 0; - int pct = slot->GetSlotActionCooldownPercentage(&secsLeft, 0); bool usable = slot->IsSlotUsable(slot->ApparentSlotType, slot->ApparentActionId); uint iconId = slot->IconId; uint actionId = slot->ApparentActionId; var slotType = slot->ApparentSlotType; + (int pct, int secsLeft) = GetSlotCooldown(slot); list.Add(new SlotInfo(iconId, false, usable, pct, secsLeft, actionId, slotType, keybind)); } return list; } + /// + /// 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. + /// + 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); + } + /// /// Returns the default game keybind label for a hotbar slot (Hotbar 1: 1,2,...,0,-,=; Bar 2: Ctrl+1..12; etc.). /// hotbarIndex 1–10, slotIndex 0–11. Used to mirror the default hotbar keybind display. diff --git a/Interface/GeneralElements/ActionBarsHud.cs b/Interface/GeneralElements/ActionBarsHud.cs index 95afa57..e77a3fb 100644 --- a/Interface/GeneralElements/ActionBarsHud.cs +++ b/Interface/GeneralElements/ActionBarsHud.cs @@ -1378,8 +1378,8 @@ namespace HSUI.Interface.GeneralElements try { var parts = new List(); - float castSec = action.Cast100ms / 100f; - float recastSec = action.Recast100ms / 100f; + float castSec = action.Cast100ms / 10f; // Cast100ms/Recast100ms are in 100ms units + float recastSec = action.Recast100ms / 10f; if (castSec > 0) parts.Add($"Cast: {castSec:F1}s"); else diff --git a/changelog.md b/changelog.md index 8da6be1..5d8e5b4 100644 --- a/changelog.md +++ b/changelog.md @@ -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 - **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. diff --git a/pluginmaster.json b/pluginmaster.json index ed90456..3a355cc 100644 --- a/pluginmaster.json +++ b/pluginmaster.json @@ -4,9 +4,9 @@ "Name": "HSUI", "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.", - "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", - "AssemblyVersion": "1.0.2.4", + "AssemblyVersion": "1.0.2.5", "RepoUrl": "https://github.com/Knack117/HSUI", "ApplicableVersion": "any", "Tags": ["UI", "HUD", "Unit Frames", "Nameplates", "Party Frames", "Hotbars"], @@ -14,10 +14,10 @@ "DalamudApiLevel": 14, "IconUrl": "https://raw.githubusercontent.com/Knack117/HSUI/main/Media/Images/icon.png", "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, "IsTestingExclusive": false, - "DownloadLinkTesting": "https://github.com/Knack117/HSUI/releases/download/v1.0.2.4/latest.zip", - "DownloadLinkUpdate": "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.5/latest.zip" } ]