From 048f6451c8422ae3e6cbb62d12695c9a208f6bd3 Mon Sep 17 00:00:00 2001 From: Knack117 Date: Sun, 1 Feb 2026 01:22:58 -0500 Subject: [PATCH] Release 1.0.5.0: World Object Tooltip (hover tooltip, detach option), version bump, pluginmaster Co-authored-by: Cursor --- HSUI.csproj | 6 +- HSUI.json | 2 +- Helpers/TooltipsHelper.cs | 145 ++++++++++++++++++++++++++++++++++++++ Interface/HudManager.cs | 3 + changelog.md | 3 + pluginmaster.json | 12 ++-- 6 files changed, 161 insertions(+), 10 deletions(-) diff --git a/HSUI.csproj b/HSUI.csproj index 6573e46..78c3f3f 100644 --- a/HSUI.csproj +++ b/HSUI.csproj @@ -9,9 +9,9 @@ HSUI - 1.0.4.0 - 1.0.4.0 - 1.0.4.0 + 1.0.5.0 + 1.0.5.0 + 1.0.5.0 diff --git a/HSUI.json b/HSUI.json index 23e4f3e..ef04207 100644 --- a/HSUI.json +++ b/HSUI.json @@ -2,7 +2,7 @@ "Author": "Knack117", "Name": "HSUI", "InternalName": "HSUI", - "AssemblyVersion": "1.0.4.0", + "AssemblyVersion": "1.0.5.0", "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/TooltipsHelper.cs b/Helpers/TooltipsHelper.cs index 5fd95ef..63199f7 100644 --- a/Helpers/TooltipsHelper.cs +++ b/Helpers/TooltipsHelper.cs @@ -1,3 +1,5 @@ +using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; using Dalamud.Interface.Utility; using HSUI.Config; @@ -6,6 +8,7 @@ using HSUI.Interface.GeneralElements; using Dalamud.Bindings.ImGui; using System; using System.Numerics; +using System.Text; namespace HSUI.Helpers { @@ -124,6 +127,109 @@ namespace HSUI.Helpers Plugin.Logger.Information($"[HSUI Tooltip DBG] ShowTooltip: title='{title}' textLen={text?.Length ?? 0} textPreview='{(text != null && text.Length > 80 ? text[..80] + "..." : text ?? "")}' pos=({_position.X:F0},{_position.Y:F0})"); } + private WorldObjectTooltipConfig? _worldTooltipConfig; + + /// + /// Shows a tooltip for the game object the mouse is hovering over in the 3D world. + /// Call this each frame before Draw(). + /// + public void ShowWorldObjectTooltip() + { + try + { + _worldTooltipConfig ??= ConfigurationManager.Instance.GetConfigObject(); + if (_worldTooltipConfig == null || !_worldTooltipConfig.Enabled) + return; + } + catch (Exception ex) + { + // Config not ready yet or not found - silently skip + if (_config.DebugTooltips) + Plugin.Logger.Warning($"[HSUI Tooltip] WorldObjectTooltipConfig not available: {ex.Message}"); + return; + } + + IGameObject? mouseOverTarget = Plugin.TargetManager.MouseOverTarget; + if (mouseOverTarget == null) + return; + + // Don't show tooltip for ourselves + if (mouseOverTarget.GameObjectId == Plugin.ObjectTable.LocalPlayer?.GameObjectId) + return; + + string name = mouseOverTarget.Name.ToString(); + if (string.IsNullOrEmpty(name)) + name = "Unknown"; + + var sb = new StringBuilder(); + + // Free Company tag for players + if (_worldTooltipConfig.ShowTitle && mouseOverTarget is IPlayerCharacter player) + { + string fcTag = player.CompanyTag.ToString(); + if (!string.IsNullOrEmpty(fcTag)) + sb.AppendLine($"«{fcTag}»"); + } + + // Level + if (_worldTooltipConfig.ShowLevel && mouseOverTarget is ICharacter charLevel) + { + byte level = charLevel.Level; + if (level > 0) + sb.AppendLine($"Level {level}"); + } + + // Job (for players) + if (_worldTooltipConfig.ShowJob && mouseOverTarget is IPlayerCharacter playerJob) + { + uint jobId = playerJob.ClassJob.RowId; + if (jobId > 0 && JobsHelper.JobNames.TryGetValue(jobId, out string? jobName)) + sb.AppendLine($"Job: {jobName}"); + } + + // HP + if (_worldTooltipConfig.ShowHP && mouseOverTarget is ICharacter charHp) + { + uint currentHp = charHp.CurrentHp; + uint maxHp = charHp.MaxHp; + if (maxHp > 0) + { + float pct = (float)currentHp / maxHp * 100f; + sb.AppendLine($"HP: {currentHp:N0} / {maxHp:N0} ({pct:F0}%)"); + } + } + + // Distance + if (_worldTooltipConfig.ShowDistance) + { + var localPlayer = Plugin.ObjectTable.LocalPlayer; + if (localPlayer != null) + { + float dist = Vector3.Distance(localPlayer.Position, mouseOverTarget.Position); + sb.AppendLine($"Distance: {dist:F1}y"); + } + } + + // Object ID (debug) + if (_worldTooltipConfig.ShowObjectId) + { + sb.AppendLine($"ID: {mouseOverTarget.GameObjectId}"); + } + + string body = sb.ToString().TrimEnd('\r', '\n'); + if (string.IsNullOrEmpty(body)) + body = "(No info)"; + + if (_worldTooltipConfig.DetachFromCursor) + { + ShowTooltip(body, _worldTooltipConfig.Position, name); + } + else + { + ShowTooltipOnCursor(body, name); + } + } + public void RemoveTooltip() { _dataIsValid = false; @@ -305,4 +411,43 @@ namespace HSUI.Helpers Thickness = thickness; } } + + [Section("Misc")] + [SubSection("World Tooltip", 0)] + public class WorldObjectTooltipConfig : PluginConfigObject + { + public new static WorldObjectTooltipConfig DefaultConfig() { return new WorldObjectTooltipConfig(); } + + [Checkbox("Detach from Cursor", spacing = true)] + [Order(1)] + public bool DetachFromCursor = false; + + [DragFloat2("Position (when detached)", min = -4000f, max = 4000f)] + [Order(2, collapseWith = nameof(DetachFromCursor))] + public Vector2 Position = new Vector2(100, 100); + + [Checkbox("Show Level", spacing = true)] + [Order(5)] + public bool ShowLevel = true; + + [Checkbox("Show HP")] + [Order(10)] + public bool ShowHP = true; + + [Checkbox("Show Job (Players)")] + [Order(15)] + public bool ShowJob = true; + + [Checkbox("Show FC Tag (Players)")] + [Order(20)] + public bool ShowTitle = false; + + [Checkbox("Show Distance")] + [Order(25)] + public bool ShowDistance = true; + + [Checkbox("Show Object ID")] + [Order(30)] + public bool ShowObjectId = false; + } } diff --git a/Interface/HudManager.cs b/Interface/HudManager.cs index de3c96a..2532e00 100644 --- a/Interface/HudManager.cs +++ b/Interface/HudManager.cs @@ -522,6 +522,9 @@ namespace HSUI.Interface DraggablesHelper.DrawElements(origin, _hudHelper, _hudElements.Values, _jobHud, _selectedElement); } + // world object tooltip (mouseover in 3D world) + TooltipsHelper.Instance.ShowWorldObjectTooltip(); + // tooltip TooltipsHelper.Instance.Draw(); diff --git a/changelog.md b/changelog.md index 9a3a440..ed418cc 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,6 @@ +# 1.0.5.0 +- **World Object Tooltip**: Hover over players, NPCs, or objects in the world to see a tooltip with name, level, HP, job (players), FC tag (optional), distance, and object ID. Enable in Misc → World Tooltip; optional detach-from-cursor with fixed position. + # 1.0.4.0 - **PvP nameplates**: Grand Company icons on enemy nameplates (Maelstrom, Twin Adder, Immortal Flames — icon IDs 62601, 62602, 62603). Configurable icon IDs in Nameplates → Enemies → Company Icon (PvP) if you need to override. - **PvP nameplates**: Role/Job icon on enemy player nameplates — enable in Nameplates → Enemies → Role/Job Icon (enemy players); supports job or role style like player nameplates. diff --git a/pluginmaster.json b/pluginmaster.json index 486aae2..5d89306 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": "PvP nameplates: Grand Company icons (Maelstrom/Adders/Flames 62601–62603), configurable GC icon IDs, Role/Job icon on enemy players. Main Actions tooltips. Alliance frame label fixes.", + "Changelog": "World Object Tooltip: hover over players/NPCs/objects for name, level, HP, job, FC tag, distance; optional detach-from-cursor. PvP nameplates: GC icons, Role/Job icon. Main Actions tooltips. Alliance frame fixes.", "InternalName": "HSUI", - "AssemblyVersion": "1.0.4.0", + "AssemblyVersion": "1.0.5.0", "RepoUrl": "https://github.com/Knack117/HSUI", "ApplicableVersion": "any", "Tags": ["UI", "HUD", "Unit Frames", "Nameplates", "Party Frames", "Hotbars"], @@ -14,11 +14,11 @@ "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.4.0/latest.zip", + "DownloadLinkInstall": "https://github.com/Knack117/HSUI/releases/download/v1.0.5.0/latest.zip", "IsHide": false, "IsTestingExclusive": false, - "DownloadLinkTesting": "https://github.com/Knack117/HSUI/releases/download/v1.0.4.0/latest.zip", - "DownloadLinkUpdate": "https://github.com/Knack117/HSUI/releases/download/v1.0.4.0/latest.zip", - "LastUpdate": "1769900470" + "DownloadLinkTesting": "https://github.com/Knack117/HSUI/releases/download/v1.0.5.0/latest.zip", + "DownloadLinkUpdate": "https://github.com/Knack117/HSUI/releases/download/v1.0.5.0/latest.zip", + "LastUpdate": "1738368000" } ]