# Loadouts / spec builder (staged 2026-10-03, TEST only, not published)

Trevor: "setting up alternate specs is too convoluted ... an interface like on character creation". Built to the
EQ Legends references (Loadouts tab + Adjust Loadout window, no race panel).

Files:
- dinput8.dll: md5 b9f85a6d, client_dll 99e5c07 (build of 260c8f3; feature commits 654ef6b, d740f6a, 260c8f3), on top of the published build d48c19c
  (= patch_files/dinput8.dll 6f76b340). Nothing else unpublished is in it.
- HJ_LoadoutWnd.xml (new, md5 d334126d): the Adjust Loadout window (client_dll genxml_loadout.py).
- EQUI_Inventory.xml (md5 ed949935): patch_files copy (08ddb1e3) with the Classes tab reworked, the Pet tab stats
  list and the tab order Inventory, Pet, Classes, Hoard, Alt Currency, Stats, Evolving, Shroud
  (client_dll patch_inventory_loadouts.py, reproducible from patch_files).
- EQUI.xml (md5 900da6f3): patch_files copy (0bc54b93) + `<Include>HJ_LoadoutWnd.xml</Include>`.
verify_sites.py vs patch_files/eqgame.exe: 38 hook sites (+HandleKeyDown), 40 byte patches + signatures,
2 call sites, 0 problems.
Server side: test quests b63a68771 + b941b5f4d + 55baa19b7 + 15fb321e8 (on top of per-class levels 49e0db9fc / 891858f0a), live on TEST.

What it does:
- Classes tab (inventory window): Character Loadouts list (# | Primary Class | Additional Classes | Lvl | Name;
  your current classes green, a "Now (not saved)" row when they are not in a slot), Add / Edit / Swap (500pp),
  "Swapping available: Yes/No" (tooltip: Bazaar / PoK / Guild Lobby, not while attacking), Class Levels grid (16
  classes, current ones green; a class never played shows the level it would start at). The 2nd/3rd class chooser
  for new characters is unchanged below it. Save Here and 2nd/3rd Primary are gone from the tab (Add/Edit cover
  them; the chat commands still work).
- Add (next empty slot, starts from your current classes) / Edit (selected slot) open Adjust Loadout: Primary grid
  left, Additional grid right (character-creation class icons: grey = not picked, colour + gold frame = picked; a
  class picked on one side is refused on the other), progress lines, a table of the picks with role and level,
  "This loadout would be level N", Name, Keep this gear on, Clear Slot (two clicks) / Cancel / Save.
  Save = `#spec set <slot> <c1> <c2> <c3> [name]` (free; the server checks again); the window closes and the slot
  is selected, so Swap is the next click.
- Swap = the existing `#spec swap` (500pp, safe zone, not attacking, confirm link when your level would drop, pets
  dismissed, re-zone when the primary changes) plus the gear step: equipped gear none of the new classes can use goes
  to the Hoard (else a free bag slot, else a parcel, else it stays equipped), "Moved to Hoard: ..." in chat. Keep
  this gear on = nothing moves. Spell gems the new classes cannot cast are cleared.
- N (plain N; RoF2 leaves it unbound) opens/closes the inventory on the Classes tab. Not while typing, and a key
  binding you gave N yourself wins. /classes does the same.
- Without the DLL: Add/Edit print the chat version (`#spec set ...`).

Round 2 (after Trevor's first test): Class Levels rows all visible; whole rows coloured, muted selection fill;
"Now" fits; auto names shown as "Spec N"; the 2nd/3rd class chooser only while a class slot is open (PMODE);
picker icons lit when selectable, grey when not; Add preselects your classes; Keep this gear on is a tick box;
Pet tab: per-pet stats with the gear bonus (#pet stats, refreshed every 4 s while the Pet tab is open).

## Test on the desktop
    scp -r openclawvm:heroes_journey_workspace/patcher/staged_specbuilder /tmp/ && bash /tmp/staged_specbuilder/install_desktop.sh
Launch with "EverQuest RoF2 Tanks (Direct)", log in to the TEST world. hjclient.log line 1 ends "+specbuilder) loaded",
and it lists `hook HandleKeyDown @005594e0 ok`. Steps: see the agent report (in-game test list).
Undo: `bash /tmp/staged_specbuilder/install_desktop.sh --revert` (or run the Patcher launcher once).

## Publish (after Trevor confirms on test). Order: server first, then the patcher
1. Prod quests: per-class levels first (`flock ~/eqserver-test/.deploy.lock ~/eqserver-test/deploy-classlevels/deploy.sh`,
   its PREFLIGHT_ONLY=1 run was clean on prod 811c53b84), then in ~/eqserver/quests:
   `git cherry-pick b63a68771 b941b5f4d 55baa19b7 15fb321e8` (preflight on a copy of prod 811c53b84 + 49e0db9fc + 891858f0a: clean,
   luac ok), then prod console `api reload 22`. No restart, no SQL, no C++ (prod zone has every binding used).
2. Patcher: back up patch_files/dinput8.dll and uifiles/default/{EQUI_Inventory,EQUI}.xml to
   ~/.local/share/eq-backups/<date>/specbuilder; copy this folder's dinput8.dll to patch_files/ and the three XML files
   to patch_files/uifiles/default/; add a news.txt line; `python3 generate_manifest.py`; check the manifest lists the
   four files. If patch_files changed since 2026-10-03 (EQUI_Inventory 08ddb1e3, EQUI.xml 0bc54b93), regenerate:
   `python3 client_dll/patch_inventory_loadouts.py patch_files/.../EQUI_Inventory.xml out.xml` and re-add the include.
   Old DLL + new XML: the tab shows the new layout with old-style rows, Add/Edit give the chat help. New DLL + old
   XML: N opens the old Class Switch window, nothing breaks.
