Files
HSCompare/PLUGIN_LAYOUT.md

119 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
1. **Hovered item** the item under the cursor
2. **Currently equipped item** the item in the same equipment slot
3. **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
1. **Hover**`IGameGui.HoveredItemChanged` fires with item ID (and HQ flag via offset 1_000_000).
2. **Resolve item**`IDataManager.GetExcelSheet<Item>().GetRow(itemId)``Item` + HQ flag → wrapped as `InvItem`.
3. **Is equipment?**`Item.EquipSlotCategory` non-null and not “none” (e.g. MainHand, Head, Body).
4. **Map to slot**`EquipSlotCategory` → FFXIVClientStructs `InventoryType` (e.g. ArmoryMainHand, ArmoryHead).
5. **Get equipped**`InventoryManager.Instance()->GetInventoryContainer(InventoryType.EquippedItems)`, scan by slot; get `Item` for same slot.
6. **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.
7. **Key check** → Each frame in Draw: `IKeyState[Configuration.ModifierKey]` (or fallback to Win32 `GetKeyState` for the configured VK). Only show comparison window when key is held.
---
## Implementation Details
### 1. Tooltip “replacement”
- The games 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()`, check `IKeyState[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 use `ImGuiWindowFlags.AlwaysAutoResize` and control width via `ImGui.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, add `Item.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).
- **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.ColoredText` green 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 items 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 | equipped) + stat change list; color-coded. |
This layout keeps the plugin modular, testable, and aligned with existing Dalamud and SimpleCompare patterns.