app+protocol: fire CHAT_MSG_HARDCORE, the realm's own chat type

`reference_ui`'s `UNPRODUCED` carried `CHAT_MSG_HARDCORE` as a chain
event nothing here fires: the window registered for it and benilla
routed no such message, so the realm's hardcore-death broadcasts simply
never arrived. Three of grom's addons listen for it too.

The missing piece was one number, and the realm's patched `WoW.exe` has
it in the PE section it names `.tdata`, beside the string `"HARDCORE"`
at `0xd06000`. Two detours do the whole job: `0x49f7aa`, in the chat
type-name lookup, jumps to `0xd06020`, which sets the name pointer to
that string and the type to `$0x5e`; and `0x49b193`, inside the
`CHAT_MSG_*` fire helper `0x49b0b0` whose format string this file
already cites, jumps to `0xd06040`, which tests the type against
`$0x5e` and swaps in the event-name index `0x21f`.

So wire type `0x5E` is `ChatEventKind::Hardcore`. Nothing in 1.12 claims
it — its last type is `CHAT_MSG_BATTLEGROUND_LEADER` at `0x5D` and its
`CHAT_MSG_BG_SYSTEM_*` block sits at `0x52`-`0x54` — so there is no
collision to arbitrate, and the test pins that adjacency along with the
decode, since a wrong id would look exactly like the silence it
replaces. The chain's `ChatFrame.xml` registers the event and its
`GlobalStrings.lua` has the `[Hardcore] %s: ` format, so the window
needed nothing from us but the fire; it takes the window's default
colour, as `FILTERED` does, the realm adding no `ChatTypeInfo` row.

Not covered: sending. The ruRU locale carries `SLASH_HARDCORE1 = "/h"`
and `CHAT_HARDCORE_SEND` where enUS has only the receive format, so the
send side needs its own look.

269 data-gated failures, identical to the baseline, all nine gates green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
2026-10-23 19:27:36 -06:00
co-authored by Claude Opus 5
parent 56bdd15cfe
commit cae59cdc11
5 changed files with 57 additions and 10 deletions
@@ -2250,12 +2250,6 @@ mod tests {
// Registered by a chain file we load and fired by nothing here; each says why.
const UNPRODUCED: &[(&str, &str)] = &[
(
"CHAT_MSG_HARDCORE",
"ChatFrame.xml — the realm's own hardcore-death broadcast channel. Its chat type \
has no producer here: benilla routes no such server message, so the window \
simply never receives one. Costs the death announcements, nothing functional",
),
(
"MODIFIER_STATE_CHANGED",
"AIO's Dep_LibWindow-1.1 — a 2.x event for live modifier-key tracking, used to \