c87c3ba8f8
Co-authored-by: Cursor <cursoragent@cursor.com>
7.1 KiB
7.1 KiB
HSCompare Plugin – Layout and Implementation Plan
Overview
HSCompare is a Dalamud plugin for FFXIV that replaces or augments equipment tooltips with a comparison view. When the user hovers over an equipment item (armor/weapon) and holds a configurable modifier key (default: Shift), the plugin shows:
- Hovered item – the item under the cursor
- Currently equipped item – the item in the same equipment slot
- Total stat difference – below the tooltip, showing the net stat change if the hovered item were equipped (WoW-style: green for gains, red for losses)
If the hovered item is already equipped, or the item is not equipment, the default game tooltip behavior is unchanged (no replacement).
Architecture
Components
| Component | Purpose |
|---|---|
| Plugin.cs | Entry point. Subscribes to IGameGui.HoveredItemChanged, registers /hscompare command, injects services, and draws UI each frame. |
| Configuration.cs | Persisted settings: modifier key (VirtualKey), tooltip font size, comparison window size (width/scale). |
| PluginUI.cs | ImGui logic: draws comparison window when conditions are met, applies font/size from config; config window is in the same class. |
| ItemBonusType.cs | Enum of FFXIV base param IDs with display names (Strength, Vitality, etc.). |
Data Flow
- Hover →
IGameGui.HoveredItemChangedfires with item ID (and HQ flag via offset 1_000_000). - Resolve item →
IDataManager.GetExcelSheet<Item>().GetRow(itemId)→Item+ HQ flag → wrapped asInvItem. - Is equipment? →
Item.EquipSlotCategorynon-null and not “none” (e.g. MainHand, Head, Body). - Map to slot →
EquipSlotCategory→ FFXIVClientStructsInventoryType(e.g. ArmoryMainHand, ArmoryHead). - Get equipped →
InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems), scan by slot; getItemfor same slot. - Compare → Only show comparison if hovered item is not the same as equipped (different RowId or slot). Build stat maps for both items (base params + defense/damage/block), then diff.
- Key check → Each frame in Draw:
IKeyState[Configuration.ModifierKey](or fallback to Win32GetKeyStatefor the configured VK). Only show comparison window when key is held.
Implementation Details
1. Tooltip “replacement”
- The game’s own tooltip is not suppressed (no public Dalamud API to hide it). The plugin draws an additional ImGui window when comparison is active.
- Layout: One window or two side-by-side:
- Left: Hovered item (name, ilvl, main stats, substats).
- Right: “Currently Equipped” (same fields).
- Below (or bottom section of same window): “If you replace this item, the following stat changes will occur:” then list of stat deltas (e.g. “+12 Strength”, “-5 Critical Hit”) in green/red.
- Position: near cursor or below default tooltip (e.g. cursor + offset so the comparison appears below the game tooltip).
2. Modifier key (configurable)
- Config: Store
VirtualKey(e.g.VirtualKey.SHIFT). Default: Shift. - Runtime: In
PluginUI.Draw(), checkIKeyState[config.ModifierKey]. If not pressed, do not draw comparison. - Config UI: Dropdown or key selector for modifier (list common: Shift, Ctrl, Alt).
3. Font and window size (configurable)
- Font:
ImGui.GetIO().Fonts– push a scaled font (e.g.ImGui.GetFont()->FontSize * config.TooltipFontScale) before drawing the comparison window; pop after. - Window size:
ImGui.SetWindowSize()or useImGuiWindowFlags.AlwaysAutoResizeand control width viaImGui.PushItemWidth()/ text wrap width, or store a “max width” in config and use it for wrapping. Alternatively, a simple “scale” factor that scales both font and padding.
4. Stat difference (total change when equipping hovered item)
- Meaning: “Total stat change” = (hovered item stats) − (equipped item stats). Positive = gain if you equip hovered, negative = loss.
- Sources for stats:
- Substats:
Item.UnkData59(BaseParam, BaseParamValue). If HQ, addItem.UnkData73(BaseParamValueSpecial) for the same BaseParamSpecial. - Main stats: Defense (Phys/Mag), Damage (Phys/Mag), Block, BlockRate from
Item(mapped into the same “bonus” map by type, as in SimpleCompare).
- Substats:
- Display: One line per stat that has a non-zero delta: “+12 Strength”, “-5 Critical Hit”, “-0.7 Damage Per Second” (if we compute DPS or just “Physical Damage”). Use
ImGui.ColoredTextgreen for positive, red for negative. - Materia: Optional: show materia slot count difference (e.g. “+1 Materia slot”).
5. Equipment slot mapping
- Use
Item.EquipSlotCategory.Value(Lumina): MainHand, OffHand, Head, Body, Hands, Waist, Legs, Feet, Ears, Neck, Wrists, FingerL, FingerR, SoulCrystal. - Map to
FFXIVClientStructs.FFXIV.Client.Game.InventoryType: ArmoryMainHand, ArmoryOffHand, ArmoryHead, ArmoryBody, ArmoryHands, ArmoryWaist, ArmoryLegs, ArmoryFeets, ArmoryEar, ArmoryNeck, ArmoryWrist, ArmoryRings (both fingers), ArmorySoulCrystal. - Rings: Two slots; we compare against “the slot this item would go in” – e.g. first ring slot that matches. Simple approach: compare hovered to both equipped rings and show the one that matches slot or the first.
6. Edge cases
- Soul crystal / non-equipment: Ignore (no comparison).
- Same item equipped: If hovered item RowId equals equipped item RowId, optionally hide comparison or show “No change”.
- Empty slot: If nothing equipped in that slot, show only hovered item and “Currently equipped: (empty)” with stat list = hovered item’s stats as gains.
File Structure
HSCompare/
├── HSCompare.sln
├── HSCompare/
│ ├── HSCompare.csproj
│ ├── HSCompare.json # Manifest template for DalamudPackager
│ ├── Plugin.cs
│ ├── Configuration.cs
│ ├── PluginUI.cs
│ ├── ItemBonusType.cs
└── PLUGIN_LAYOUT.md # This file
Dependencies
- Dalamud (via
$(DalamudLibPath)): Dalamud.dll, ImGui.NET.dll, ImGuiScene.dll, Lumina.dll, Lumina.Excel.dll, Newtonsoft.Json.dll. - FFXIVClientStructs: For
InventoryManager,InventoryType,InventoryItem(equipped item IDs and HQ flag).
Summary
| Requirement | Implementation |
|---|---|
| Replace/augment equipment tooltips | Draw ImGui comparison window when modifier held and hovered item is equipment. |
| Compare to equipped when not equipped | Resolve slot from EquipSlotCategory, read equipped from InventoryManager, show both. |
| Configurable key | Configuration.ModifierKey (VirtualKey), checked via IKeyState. |
| Configurable font and window size | Config: font scale and/or window width; apply in PluginUI before drawing. |
| Total stat difference below tooltip | Section “If you replace this item…” with (hovered − equipped) deltas, green/red. |
| WoW-like comparison | Two blocks (hovered |
This layout keeps the plugin modular, testable, and aligned with existing Dalamud and SimpleCompare patterns.