- Status
- Offline
- Joined
- Mar 3, 2026
- Messages
- 447
- Reaction score
- 7
If you are looking to mess with how kills appear in the feed or just want to add some custom flavor to your TF2 internal, here is a clean way to hook the death notices. This snippet allows you to hijack the killfeed event, swap out icons (like the bumper kart), and even modify the info text strings.
Technical Breakdown
The logic relies on hooking CTFHudDeathNotice_OnGameEvent inside client.dll. We are using manual pointer arithmetic based on IDA disassembly to reach the DeathNoticeItem structure.
The Signature
Implementation Snippet
Visual Showcase
Has anyone tried expanding this to show custom kill reasons or dynamic icons based on projectile types?
Technical Breakdown
The logic relies on hooking CTFHudDeathNotice_OnGameEvent inside client.dll. We are using manual pointer arithmetic based on IDA disassembly to reach the DeathNoticeItem structure.
- Signature scanning for the HUD kill feed event handler.
- Calculating the message pointer via the thisptr offset (79 * 8 = 632).
- Modifying the team index to bypass team-specific restrictions (useful for Merasmus or neutral events).
- Overwriting the icon string and info text directly in memory.
The Signature
Code:
48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B F2
Implementation Snippet
Code:
MAKE_HOOK(CTFHudDeathNotice_OnGameEvent, signature::hud_kill_feed_event, void, __fastcall, void* rcx, IGameEvent* event, int death_notice_msg) {
if (!i::engine_client->is_connected() || !tf2::local)
return CALL_ORIGINAL(rcx, event, death_notice_msg);
int attacker_id = i::engine_client->get_player_for_user_id(event->GetInt("attacker"));
auto thispointer = reinterpret_cast<std::uintptr_t>(rcx);
auto list = *reinterpret_cast<std::uintptr_t*>(thispointer + 632);
auto message = list + 432 * death_notice_msg;
if (attacker_id == tf2::local->entidx()) {
*reinterpret_cast<std::uint32_t*>(message + 64) = 0; // m_iTeam -> TEAM_UNASSIGNED
wchar_t* wzInfoText = reinterpret_cast<wchar_t*>(message + 168);
char* szIcon = reinterpret_cast<char*>(message + 136);
wcscpy(wzInfoText, L"[PASTER]");
strcpy(szIcon, "d_bumper_kart");
event->SetInt("customkill", 60);
}
CALL_ORIGINAL(rcx, event, death_notice_msg);
}
Visual Showcase
The author mentioned being unsure if wcscpy is 100% memory safe here. If you are worried about buffer overflows, check the size of the destination buffer in the DeathNoticeItem struct before copying long strings. The customkill value 60 specifically triggers the bumper kart icon logic in the source engine's hud death notice handler.
Has anyone tried expanding this to show custom kill reasons or dynamic icons based on projectile types?