Skip to content

Kill feed: outline the names and put boxes behind lines or names (part of #562) - #1000

Merged
ccoventry merged 12 commits into
devfrom
feat/killfeed-outline-background-562
Oct 25, 2026
Merged

ccoventry merged 12 commits into
devfrom
feat/killfeed-outline-background-562

Conversation

@ccoventry

@ccoventry ccoventry commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Release note: New: the kill feed's names can have an outline (ds_hud_deathmsg outline 2) and a see-through box behind each line or each name (ds_hud_deathmsg background 150, background team 200), so they stay readable over busy walls; colours can be typed as r g b or as hex, like #0a286e.

Part of #562

The user looked at the screenshots and approved the looks (outline 2 and background 150), the options as built, and the Allies team-box default (a quarter of the team colour).

What

New ds_hud_deathmsg subcommands, all off by default:

  • outline <0..4> [colour] [alpha]: draws each name again at every offset within N px, before the coloured pass. At 1 px that's the 8 neighbours; wider is a filled disc (68 extra draws a name at 4 px). It works with the game's font and with font. With the game's font the outline is always opaque, because pfnDrawConsoleString takes no alpha.
  • background <alpha> [colour] [padding]: one translucent box per line, from the killer's name to the victim's. Default colour black, padding 4.
  • background team <alpha> [padding]: one box behind each name, in a quarter of that name's team colour. The icon gets no box.
  • background allies <colour> / background axis <colour>: that team's own box colour (... default goes back to the shade).
  • outline default / background default: off.
  • Colours: every colour argument is r g b (each 0..255) or one hex word: #0a286e, the short #0af (each digit doubled), or six digits without the # (0a286e).

All of it works with both kill-feed layouts, the game's (layout default) and #1023's layout even.

How

  • Everything runs inside font's redirected text calls and scale's redirected SPR_DrawHoles, which see each line in Draw's order.
  • The line box goes down at the line's first draw (the killer's name, or the icon when there's no killer). Each name box goes down just before its name.
  • The line height is the one Draw steps by: the icon rect the line-start stub reads, which is the even layout's 26-row box (times scale) when that layout is on. So the boxes follow the even layout's slots with no extra code.
  • Boxes are one GL quad each, from opengl32.dll's exports (as in hud_sprite_edges.rs), so there are no engine offsets and both builds are the same. Every GL state the quad touches is put back. pfnFillRGBA was no use: it adds its colour (GL_ONE), so a dark box comes out as nothing.
  • Settings are atomics, read on the engine thread. There are no locks in the draw path.
  • New modules: goldsrc-hooks/src/deathmsg/backdrop.rs (drawing, settings) and deathmsg/colour.rs (the one colour parser, with unit tests).
  • While either option is on, the right margin from Kill feed: names no longer cut off at the right edge with a bigger scale or your own font (part of #728) #998 also applies, and grows by the outline width or the padding.

Decisions

  • Team detection: by the colour the game passes for each name, from GetClientColor (client+0x2ad90, the same on both builds). Allies (team 1) is (0.3, 0.4, 0.3), Axis (team 2) is (1.0, 0.25, 0.25). The British are team 1 on a British map, so background allies covers them. Any other colour (spectator, HLTV) always gets its own quarter shade.
  • Line boxes: the line's own height, 2 px short, so neighbouring translucent boxes never overlap and darken. Padding applies sideways only, because Draw steps lines by exactly their height.
  • Name boxes: the text's height plus half the padding above and below, clipped to the line.
  • Team mode: the icon gets no box.
  • Hex forms: #rrggbb, #rgb and rrggbb are accepted. A bare rgb is not: 255 alone is a channel. Six characters are never a 0..255 number, so rrggbb without # is unambiguous. In background <alpha> [colour] [padding], one plain number is the padding and one hex word is the colour. Replies and the status line still print colours as r g b.
  • # in the console and in cfgs: the engine's tokenizer splits only at whitespace, quotes, : and { } ( ) ' ,, and cfg comments start with //, so #0a286e arrives whole. Tested in game both ways (below). Studio's cfg_scan and the Commands tab's suggestions only read the command name, so they don't look at arguments.
  • Settings: like scale/font, these are console subcommands set from a cfg (e.g. the WSOD25 movie cfg). There is no Studio-side setting.
  • Console names: no new console name. console_commands_data.js was regenerated (console_names.py --pre --post --hlae) and came out unchanged. Commands.txt's usage line for ds_hud_deathmsg lists the new subcommands and the hex form.

Merged with dev

dev brought #1023 (layout even|default), #1026 (replace) and #998's right margin into the same code. Kept all of them: the status line shows layout, outline/background and replace; "is the layout ours" counts the even layout and the boxes; the line box goes down before the even layout's atlas icon draw. Other open PRs touching the same files: #1044, #1040, #906, #885, #882 and #758 edit docs/dodstudio_commands.md and Commands.txt (other commands' lines). None touch the kill-feed code.

Test done

Test DLL: local\test-killfeed-outline\ (built from 4340a652). game_probe, Brain account, -addons, 2560x1440, demo ktps8w11sf-dyelife_gskill_m2_armory_h1 (dod_armory_b6), the WSOD25 kill-feed settings (scale 2.5, font Bahnschrift SemiBold 32 shadow), max 8, six faked kills plus the demo's own. For the even layout I copied #1023's atlas (sprites\dodstudio_killfeed.spr/.txt and its two HD frames) into each install's dod_addon and removed it afterwards.

  • POST and PRE, each with layout default and layout even: plain, outline 2, background 150, background team 200 + background allies #0a286e. All draw as intended. With layout even every line box sits on its 65 px slot with the 2 px gap, names centred in it; the victim's name and box stay clear of the right edge. Nothing overlaps.
  • Hex from the console (the remote pipe uses pfnClientCmd, the same buffer and tokenizer as a typed line): background allies #0a286e replied 10 40 110; background 150 #141428 6 replied colour 20 20 40, alpha 150, padding 6; #0a28 and #zzz were refused with the right message.
  • Hex from a cfg line (exec of a scratch cfg in dod_addon, deleted after): background allies #0a286e, background axis 5a0000 and outline 1 #fff gave allies 10 40 110, axis 90 0 0 and outline = 1 px 255 255 255, and drew that way.
  • No crashes on either install.
  • Seen, not from this PR: on PRE with layout default at scale 2.5 the weapon icons are the stock low-res sheets with bits of neighbouring icons, as Kill feed: an even layout where every weapon icon has the same height and nothing is cut off (#1022) #1023's review saw ([R&D] HD HUD sprites, and drawing the HUD bigger (kill feed first) #728's path). The boxes and outline don't touch the icons.
  • cargo test --workspace --locked: 2228 passed. cargo test -p goldsrc-hooks --target i686-pc-windows-msvc: 884 passed. Clippy 1.98.1 -D warnings is clean on the workspace and i686, cargo fmt --check passes, and npm run test:unit passed 904.

Screenshots: main checkout local\review-images\killfeed-outline\final\. Start with 00-contact-post.png and 00-contact-pre.png (top-right crops of every grab); the full grabs are in post-2560x1440\ and pre-2560x1440\.

🤖 Generated with Claude Code

New ds_hud_deathmsg subcommands, all off by default:
- outline <0..4> [r g b] [alpha]: each name drawn again at every offset
  within N px before the coloured pass (8 neighbours at 1 px, a disc
  beyond), through font's surface calls or the engine's own call.
- background <alpha> [r g b] [padding]: one translucent box per line.
- background team <alpha> [padding]: a box per name in a quarter of its
  team colour; background allies|axis <r g b> sets a team's own.
- outline default / background default turn them off.

The boxes are GL quads from opengl32.dll's exports (pfnFillRGBA adds its
colour, so it cannot darken). Settings are atomics read on the engine
thread; the right margin grows by the outline or the padding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ccoventry and others added 5 commits October 24, 2026 04:28
`background default` turned the boxes off but kept `background allies|axis`
colours, so a later `background team` came back with an old cfg's colours.
It now goes back to the shades too, as its usage line says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-562' into feat/killfeed-outline-background-562
@ccoventry

Copy link
Copy Markdown
Owner Author

Review pass (unattended): merged dev in, read the diff, one fix pushed (head 65e4909c).

Fixed

  • background default turned the boxes off but kept the background allies|axis colours, so a later background team came back with an old cfg's colours. It now resets those too. There's a test for it, and the usage line and docs say so.

Checked, no bug found

  • Draw paths: no unwrap, slicing or division on game values, and no locks per frame (atomics and a OnceLock only).
  • GL quad: it saves and restores the texture, blend and alpha-test enables, the blend func and the current colour.
  • Game-font outline: it sets the colour again before each pass and gives the game's own colour back exactly afterwards.
  • Line box right edge is screen - margin. The margin includes edge_extra() >= padding, so boxes stay inside Kill feed: names no longer cut off at the right edge with a bigger scale or your own font (part of #728) #998's right margin.
  • Boxes follow the y the game passes, so they move with the spectator bar.
  • Team colours: checked in client.dll on PRE and POST (GetClientColor at +0x2ad90). Team 1 is (0.3, 0.4, 0.3) and team 2 is (1.0, 0.25, 0.25). The truncating conversion gives 76/102/76 and 255/63/63, and the British are team 1. Team 0 also gets the Allies colour, which does no harm: unassigned players never show in the feed.
  • No settings.cfg persistence. font and scale don't have it either; all of these are set from a cfg.

Tests: cargo test -p goldsrc-hooks passes (779). clippy 1.98.1 -D warnings is clean for i686 and the host, and fmt is clean. The release DLL is built and copied to local\test-killfeed-outline\.

In game: POST only, 2560x1440, wsod25_grp1_h1_m00cat, with scale 2.5, font Bahnschrift SemiBold 32 shadow and outline 2.

  • background team 200 at about 105 s and background 150 at about 160 s: the boxes cover the names, the names stay clear of the right edge, and the viewmodel and crosshair show no tint.
  • background default and outline default clear both, and ds_debug_status reads outline = off, background = off.
  • No crash.
  • Not re-run on PRE: my change doesn't touch the draw code, and the PR's own run covered PRE.

Screenshots are in local\review-images\killfeed-outline\review1000\. It still needs the user's look for taste; I found nothing else blocking.

ccoventry and others added 2 commits October 25, 2026 16:21
…background-562

# Conflicts:
#	docs/dodstudio_commands.md
#	goldsrc-hooks/src/deathmsg.rs
#	goldsrc-hooks/src/deathmsg/scale.rs
#	goldsrc-hooks/ui/Commands.txt
…(part of #562)

One parser (deathmsg/colour.rs) for every colour argument of
ds_hud_deathmsg: outline, background and background allies|axis. Six hex
digits work without the #; three need it, since 255 alone is a channel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ccoventry

Copy link
Copy Markdown
Owner Author

Final pass (agent)

Screenshots: local\review-images\killfeed-outline\final\00-contact-post.png and 00-contact-pre.png.

🤖 Generated with Claude Code

@ccoventry
ccoventry merged commit 936dac0 into dev Oct 25, 2026
5 checks passed
@ccoventry
ccoventry deleted the feat/killfeed-outline-background-562 branch October 25, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant