Repository navigation
Conversation
…ooltip Ctrl+Shift+left-click on an identified item puts "[Name] #i<token>" in the chat input. The token is base64url of the item's save record (without "JM") plus its socket fillers' records. Receive: the PrintGameString entry is hooked; every "#i<token>" word is parsed by a bounded validator against the live data tables, canonicalized and re-encoded, and only those bytes reach the engine decoder (D2Common #11145) to build a transient item unit (never hashed, no room). Valid links are drawn as "[Item Name]" in the item's quality colour; invalid tokens stay plain text. Clicking a link opens the game's own item tooltip for the transient copy (D2Client 0x93450 + D2Win #10110); Esc, right-click or another click closes it. The tooltip matches PD2's inventory hover: PD2's hover leaves "Quantity: N" out for stacks of an equippable item type (ItemTypes Body set: javelins, throwing weapons), so the link tooltip drops that line too and re-stages the popup at the builder's anchor for the shorter text. Keys and other non-equippable stacks keep it. The register-convention D2Client helpers are naked __fastcall stubs, so the compiler treats eax/ecx/edx as clobbered across them. Link hit boxes leave a trailing colour code out of the measured span (D2Win's TextNWidth measures one that ends the span as glyphs). API for other chat UIs: BH/Modules/ItemLinks/ChatLinkApi.h (FormatMessage, Release, OnClick). Config: item_links.enabled (default true). 1.13c only; the feature stays off if any code site differs. A site another module has detoured (jmp rel32 + int3 padding, as PD2's D2GL renderer does to D2Win #10085/#10177) still matches when every byte after the padding does.
…own lines The observer sees every PrintGameString line after the link rewrite; while it is set the entry hook stays installed even with item links disabled.
New module BH/Modules/Chat (client-only; .chat off / chat.enabled=false = vanilla chat, nothing hooked):
- Tabs All / Party / Whispers / System / Global (placeholder), unread badges per tab.
- Lines classified from the S->C packet that printed them (0x26 chat types 1/2/4/6, 0x5A events,
party roster), everything else (BH item notifications, engine text) is System.
- 500-line bounded scrollback shared by all tabs: wheel, PgUp/PgDn, Home/End, Jump to latest.
- Optional [hh:mm] timestamps, mention highlight (character name + keywords) with optional sound.
- Input: Up/Down sent history (50, draft kept), Ctrl+R reply to last whisperer, Ctrl+Tab tab cycle,
.chat commands handled in the chat box itself.
- Hooks (1.13c, verified bytes, removed when disabled): PrintGameString/PrintPartyString entries,
packet-table slots 0x26/0x5A (chained), the two overlay draw calls, a window subclass.
- Pure parts in ChatModel.{h,cpp} (unit-tested natively by the harness).
- BH.json section chat; README section.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the in-game chat with a tabbed chat panel: All · Game · Whispers · System · Global. It adds 500 lines of scrollback, timestamps, highlighted mentions of your name, input history, and a reply hotkey. Item links from #96 work inside the panel, and
.chat offbrings back the stock chat at any time.demo-panel.mp4
Problem
D2's chat shows the last few lines for a few seconds and then they're gone. Trade offers, whispers and party messages scroll away, there's no way to scroll back, and whispers get lost between game messages and system spam.
Changes
New module
BH/Modules/Chat/:ChatModel(pure logic, unit-tested) +ChatOverhaul(engine glue)..chat on | off | ts | clear | status | tab <name>(tstoggles timestamps).ChatLinkApi.h(FormatMessage/Release/OnClick, plus the newSetLineObserver), so links render and click the same way in the panel..chat offremoves every hook.chat.enabled(default on),chat.timestamps,chat.history_lines,chat.fade_seconds/fade_rows,chat.always_open,chat.mention_highlight/mention_keywords/mention_sound,chat.reply_hotkey.How lines are sorted: chat packet
0x26type 1 from a player = Game, type 2/6 = Whispers, everything printed without a chat packet = System. Battle.net whispers are tagged from BH's existingSID_CHATEVENThandler.Testing
ChatModeltests (packet lines land in the right tabs, bounded ring buffer evicts oldest, mention matching, colour-code stripping, timestamps, word wrapping + edge cases, sent-message history, unread badges + scroll position).chat offback to stock.chat offNot tested: online play (all runs are single player with injected chat packets), so Battle.net whisper tagging and server-side behaviour need a quick check on a test realm.
.chat off: stock chat, links still work