From 210f3a12ee1d56750d593b4c404a0683f810aa3e Mon Sep 17 00:00:00 2001 From: salmonik Date: Sat, 12 Sep 2026 19:04:22 +0200 Subject: ISurface overlay working: PTEx draw path, -Werror, menu states, bind-driven features --- src/hl2h.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 5 deletions(-) (limited to 'src/hl2h.cpp') diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 0261ff2..a4a1a88 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp @@ -117,9 +117,20 @@ static void *entitylist_get(int idx) { static void do_move(int seq) { + static bool g_echo_sent = false; if (!g_input || !g_net.ok()) return; + if (!g_echo_sent) { + g_echo_sent = true; + if (g_conmsg) { + g_conmsg("[hl2hake] succesfully loaded\n"); + logf("console echo sent (first CreateMove)"); + } else { + logf("g_conmsg is NULL — in-game console output unavailable"); + } + } + int localIdx = engine_get_local_player(); if (localIdx <= 0 || localIdx > 64) return; @@ -137,17 +148,16 @@ static void do_move(int seq) { return; uintptr_t e = (uintptr_t)ent; - uint8_t movetype = *(uint8_t *)(e + g_net.movetype); int flags = *(int *)(e + g_net.flags); bool onground = (flags & FL_ONGROUND) != 0; bool inwater = (flags & FL_INWATER) != 0; - if (movetype == MOVETYPE_NOCLIP || movetype == MOVETYPE_LADDER) - return; + bool climb_on = feature_active(FEAT_CLIMB); // bind held (or middle mouse when unbound) + bool bhop_on = feature_active(FEAT_BHOP); static bool lastground = false; - if (middle_mouse_down()) { + if (climb_on) { if (cmd->command_number % 2) { cmd->buttons &= ~IN_JUMP; cmd->buttons |= IN_USE; @@ -156,7 +166,7 @@ static void do_move(int seq) { cmd->buttons |= IN_JUMP; } note_modified(cmd, flags, (float *)(e + g_net.velocity)); - } else if (cmd->buttons & IN_JUMP) { + } else if (bhop_on && (cmd->buttons & IN_JUMP)) { if (inwater && (cmd->buttons & IN_DUCK)) { lastground = onground; return; @@ -193,9 +203,63 @@ static void do_move(int seq) { using CreateMoveFn = bool (*)(void *, int, float, bool); static CreateMoveFn oCreateMove = nullptr; +using DrawPrintTextFn = void (*)(void *self, const wchar_t *text, int len, int drawType); +static DrawPrintTextFn oDrawPrintText = nullptr; +using PaintTraverseExFn = void (*)(void *, long, bool); +static PaintTraverseExFn oPaintTraverseEx = nullptr; +static bool g_in_draw = false; + +// Hooked ISurface slot 22. The game calls this from a valid paint context; +// our overlay draws are submitted through outer_draw() (menu.cpp), which +// wraps them in PushMakeCurrent/PopMakeCurrent with the embedded panel. +static void hkdDrawPrintText(void *self, const wchar_t *text, int len, int drawType) { + if (g_in_draw) { + oDrawPrintText(self, text, len, drawType); + return; + } + g_in_draw = true; + oDrawPrintText(self, text, len, drawType); + // fallback trigger: fires when the game draws text (menus). Primary draw + // path is the PaintTraverseEx hook (slot 114), which fires every frame. + outer_draw(); + g_in_draw = false; +} + +// PaintTraverseEx (slot 114, verified: IsVisible check + popups loop + "Too many +// popups" assert). Fires every frame for the root panel — unlike DrawPrintText +// (slot 22) which only fires when text is drawn, so it never fires in-world. +static void hkdPaintTraverseEx(void *self, long panel, bool paintPopups) { + using Fn = void (*)(void *, long, bool); + ((Fn)oPaintTraverseEx)(self, panel, paintPopups); + if (!g_in_draw) { + g_in_draw = true; + outer_draw(); + g_in_draw = false; + } +} + static bool hkdCreateMove(void *self, int seq, float frametime, bool active) { bool ret = oCreateMove(self, seq, frametime, active); do_move(seq); + + // Hook ISurface once: PaintTraverseEx (slot 114) fires every frame; keep + // DrawPrintText (slot 22) hooked as a fallback text-draw trigger. + static int isurface_hooked = 0; + if (!isurface_hooked && g_surface) { + void **svt = VTABLE(g_surface); + constexpr size_t VT_SIZE = 256; + void **newsvt = new void *[VT_SIZE]; + memcpy(newsvt, svt, VT_SIZE * sizeof(void *)); + oDrawPrintText = (DrawPrintTextFn)svt[22]; + newsvt[22] = (void *)&hkdDrawPrintText; + oPaintTraverseEx = (PaintTraverseExFn)svt[114]; + newsvt[114] = (void *)&hkdPaintTraverseEx; + VTABLE(g_surface) = newsvt; + isurface_hooked = 1; + logf("ISurface hooked: DrawPrintText slot 22 orig=%p, PaintTraverseEx slot 114 orig=%p", + (void *)oDrawPrintText, (void *)oPaintTraverseEx); + } + return ret; } -- cgit v1.2.3