# Melee-primary mana fix + 28 buff slots (staged 2026-09-30, Trevor test only)

dinput8.dll md5 3692f773d00bd2592a23ea22bd5ef142, built from client_dll/hjclient.c (previous source:
client_dll/hjclient.c.bak-mana; previous DLL 13dad719 = click-to-mem + tier colours + slot tints:
client_dll/dinput8.dll.bak-mana). Contains everything 13dad719 had plus the two changes below.
verify_sites.py against patch_files/eqgame.exe (md5 e5ea76b0): 26 hooks + 6 byte patches + 1 call site, 0 problems.

## 1. Mana on the player window for WAR/ROG/MNK/BER-primary multiclass characters
Report: "mana doesn't display on the player window if you..." (melee first class, caster 2nd/3rd class).

Root cause (DLL, not the server). The mana gauge (EQType 2, GetGaugeValueFromEQ 0x7624DC) and the mana labels
(GetLabelFromEQ 0x7651F6 ...) read max mana through CharacterZoneClient vtable+0x24 = 0x581E60 and current mana
through 0x4442E0. Both are hooked and return the server's STATS numbers (OP_HJUIData "STATS|..."), but only while
g_stats_ok is set. The DLL cleared g_stats_ok on EVERY OP_MultiClassSync. At zone-in the server sends:
  client_packet.cpp:794 SendMultiClassSync -> :795 SendHJStats -> :802 EVENT_ENTER_ZONE
  -> tri_class_engine.lua:363 ApplySpellsAndSkills -> client:SendMultiClassSync()   (a 3rd sync, after STATS)
so the pools were thrown away right after they arrived and the stock numbers were used until the next
HP/mana/endurance change. Stock max mana for a Warrior/Rogue/Monk/Berserker primary is 0, so the gauge was empty
and the label 0 (and a character at full vitals got no new STATS packet). A caster or hybrid primary has a
stock pool, so it looked fine (though with the primary's numbers).
Fix: the pools now reset only when the character id in the sync changes (another character logged in).

Also: CPlayerWnd's 500 ms update (0x718DE6) shows/hides PlayerMana/ManaLabel/ManPercLabel with 0x59FB90
("is spellcaster", hooked) on [pinstLocalPC+0x2DD0]. The hook only helped when that spawn == pinstLocalPlayer
(0xDD2630); it now also accepts pinstLocalPC+0x2DD0 itself, so the gauge cannot stay hidden if the two differ.

Server: Client::CalcMaxMana (client_mods.cpp:537) is multiclass-aware (any INT/WIS caster class gives mana),
so STATS carry the right max mana. Not wrong. Small gap (not fixed, needs C++ or Lua): Client class change
(client.cpp:13755) sends a sync after CalcBonuses but no STATS, so after a class change the numbers stay the
old ones until the next HP/mana/end change. Fix: call SendHJStats() at the end of Client::SendMultiClassSync().

## 2. Base buff slots 28 (server change: 15 -> 28, + Mystical Attunement, cap 42)
Hook 0x438EE0 (CharacterZoneClient, thiscall(czc, bool, bool, bool)): the client's "last usable long-buff slot"
= 14 + |SPA 327 totals| + level bonus (+1 above 71, +1 above 74), max 41. For the local player (czc =
pinstLocalPC+0x2DC8, a PC, all flags false) the DLL adds BASE_BUFF_SLOTS - 15 = 13, max 41 (= 42 slots).
It is used by the client's free-slot finder (0x43A6D0) and the buff placement/stacking routine (0x43DED1).
Applies to every character (not only multiclass): the server raised the base for everyone.
Note: the Buff window itself always has 42 buttons (CBuffWindow ctor 0x642FAC) and draws whatever the server
puts in slots 0-41, so slots 16-28 were probably already drawn and clickable; this hook makes the client's own
slot count agree with the server's.

## Log
hjclient.log first line: "hjclient milestone2 (advloot+clickmem+tiercolor+slottint+mana+buffs28)",
"hook LastBuffSlot @00438ee0 ok", "26/26 hooks installed". Each sync line now ends "stats_ok=N": at zone-in the
3rd sync line should read stats_ok=1 (before this fix it was always 0 there).

## Test (Trevor)
1. Restart the game (the DLL loads at start). Log in a Warrior/Cleric (Tobin) or Berserker/Shaman character.
2. Player window: blue mana bar filled and the mana number/percent showing, right after zone-in, even at full
   HP/mana/endurance. Zone once and check again. Inventory window mana line too.
3. Cast a spell: the bar drops and regenerates.
4. Buffs (after the server change is live): get more than 15 buffs; the 16th-28th show in the Buff window and
   right-click removes them.

## Promote (after Trevor's OK)
cp staged_mana/dinput8.dll patch_files/dinput8.dll, regenerate the manifest (generate_manifest.py), players
restart the game. Not done here.
