# Sneak + Hide for multiclass rogues (staged 2026-10-03, TEST only, not published)

Report: Laythe (BRD/MNK/ROG, char 1000038, primary Bard): hides fine, sneaks fine, but the hide drops on the
first step even after "You have hidden yourself from view" / "quiet as a cat".

Cause (client, not server): the RoF2 client drops hide on movement by itself. Code at 0x45E997 keeps the hide on a
move only when the PROFILE class (primary) is Rogue (9) and the spawn is sneaking; otherwise it clears the hide,
sends OP_SpawnAppearance Invisibility 0 (the server obeys it) and prints eqstr 12682 "You have moved and are no
longer hidden!!". The server side was already right (Handle_OP_ClientUpdate only breaks hide when not sneaking;
the hide/sneak messages use HasClass(Rogue)). No server change.

Fix: client_dll 5fb3228 (build 540a0c6): the GetProfile call at 0x45EA03 is retargeted (call site HideMoveRogue);
when Rogue is one of the character's classes but not the primary, the class test sees 9. Everyone else is stock.

Files: dinput8.dll (md5 5aa21452a9e371c6a39faaa834d50cdc). verify_sites.py: 31 hooks + 40 bytes-only checks +
2 call sites, 0 problems against patch_files/eqgame.exe, clients/everquest_rof2_tanks and clients/thj_latest.
Built on top of the live DLL (d48de17, md5 52b5fa13 = current patch_files/dinput8.dll); nothing else changes.

## Test on the desktop (TEST world)
1. scp -r openclawvm:heroes_journey_workspace/patcher/staged_sneakhide /tmp/ && bash /tmp/staged_sneakhide/install_desktop.sh
2. Launch "EverQuest RoF2 Tanks (Direct)" (NOT the Patcher launcher: it puts the live DLL back). Log in to the test world.
3. hjclient.log, near the top: "...+mapmobs+sneakhide) loaded", "call HideMoveRogue @0045ea03 ok",
   "2/2 call sites retargeted". After zone-in: "MultiClassSync ... classes=8/7/9 mask=...".
   ("SKIP call HideMoveRogue" instead = the fix is off; send the log.)
4. A character whose PRIMARY is not Rogue but has Rogue as 2nd/3rd class (e.g. a Bard: #multiclass pick2 rogue;
   if needed #setskill 29 100 and #setskill 42 100 = Hide / Sneak). Near an aggressive (KOS) NPC:
   - Sneak (cat message), then Hide (success message), then walk: you stay hidden, no
     "You have moved and are no longer hidden!!", an aggro NPC in range ignores you.
   - Sneak off (press Sneak again), Hide, walk: hide drops with that message (stock).
   - Hide without sneaking, walk: hide drops (stock).
5. Controls: a pure Rogue behaves as before; a non-rogue (e.g. a Monk/Warrior, or a Halfling with racial hide)
   sneaking + hidden still drops hide on movement (stock).
Undo: bash /tmp/staged_sneakhide/install_desktop.sh --revert (or run the Patcher launcher once).

## Publish (after Trevor confirms on test) - NOT run
1. cd ~/heroes_journey_workspace/patcher && D=~/.local/share/eq-backups/$(date +%F) && mkdir -p "$D" &&
   cp -p patch_files/dinput8.dll "$D/dinput8.dll.pre-sneakhide"
2. md5sum patch_files/dinput8.dll   (expect 52b5fa13...; if it changed, another DLL feature was published meanwhile:
   rebuild from client_dll HEAD instead of copying this one)
3. cp staged_sneakhide/dinput8.dll patch_files/dinput8.dll && md5sum patch_files/dinput8.dll   (expect 5aa21452...)
4. news.txt, right under the welcome line:
   Oct 3: Rogues of every class combo can now sneak while hidden - Sneak, then Hide, and you stay hidden while you move.
5. python3 generate_manifest.py, then check the dinput8.dll entry in patch_manifest.json against
   sha256sum patch_files/dinput8.dll. No server restart and no C++ deploy needed.
Players get it at their next Patcher launch; until then a non-Rogue-primary rogue still loses hide on movement.
