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
@@ -40,6 +40,18 @@ pub const CHAT_MSG_FILTERED: u8 = 0x5B;
pub const CHAT_MSG_BATTLEGROUND: u8 = 0x5C;
pub const CHAT_MSG_BATTLEGROUND_LEADER: u8 = 0x5D;
/// Beyond 1.12, whose last type is `0x5D`: the realm's own hardcore-death broadcast channel,
/// `[Hardcore] %s: ` (`CHAT_HARDCORE_GET` in its `GlobalStrings.lua`).
///
/// The id is read off the realm's patched `WoW.exe`, which carries this in a PE section it names
/// `.tdata` alongside the string `"HARDCORE"` at `0xd06000`. Two detours do it: `0x49f7aa`, in the
/// type-name lookup, jumps to `0xd06020`, which sets the name pointer to that string and the type
/// to `$0x5e` before returning; and `0x49b193`, inside the `CHAT_MSG_*` fire helper `0x49b0b0`,
/// jumps to `0xd06040`, which tests the type against `$0x5e` and swaps in the event-name index
/// `0x21f`. Nothing in 1.12 claims `0x5E` — its `CHAT_MSG_BG_SYSTEM_*` sit at `0x52`-`0x54` — so
/// there is no collision to arbitrate.
pub const CHAT_MSG_HARDCORE: u8 = 0x5E;
/// The only chat types the 1.12 client runs its `$`-macro expander over; the rest reach the frame
/// verbatim. This is the wire gate (`0x49d5e4-0x49d606`); the re-expansion after a name query
/// (`0x49cf36`) omits `0x5A`.
+3 -3
View File
@@ -83,9 +83,9 @@ pub use chat::{
chat_tag, ChatMessage, CHAT_MSG_AFK, CHAT_MSG_BATTLEGROUND, CHAT_MSG_BATTLEGROUND_LEADER,
CHAT_MSG_BG_SYSTEM_ALLIANCE, CHAT_MSG_BG_SYSTEM_HORDE, CHAT_MSG_BG_SYSTEM_NEUTRAL,
CHAT_MSG_CHANNEL, CHAT_MSG_DND, CHAT_MSG_EMOTE, CHAT_MSG_FILTERED, CHAT_MSG_GUILD,
CHAT_MSG_IGNORED, CHAT_MSG_MONSTER_EMOTE, CHAT_MSG_MONSTER_SAY, CHAT_MSG_MONSTER_WHISPER,
CHAT_MSG_MONSTER_YELL, CHAT_MSG_OFFICER, CHAT_MSG_PARTY, CHAT_MSG_RAID,
CHAT_MSG_RAID_BOSS_EMOTE, CHAT_MSG_RAID_BOSS_WHISPER, CHAT_MSG_RAID_LEADER,
CHAT_MSG_HARDCORE, CHAT_MSG_IGNORED, CHAT_MSG_MONSTER_EMOTE, CHAT_MSG_MONSTER_SAY,
CHAT_MSG_MONSTER_WHISPER, CHAT_MSG_MONSTER_YELL, CHAT_MSG_OFFICER, CHAT_MSG_PARTY,
CHAT_MSG_RAID, CHAT_MSG_RAID_BOSS_EMOTE, CHAT_MSG_RAID_BOSS_WHISPER, CHAT_MSG_RAID_LEADER,
CHAT_MSG_RAID_WARNING, CHAT_MSG_SAY, CHAT_MSG_SYSTEM, CHAT_MSG_WHISPER,
CHAT_MSG_WHISPER_INFORM, CHAT_MSG_YELL, MACRO_EXPANDED_TYPES,
};