From 6b5425ebd35c28e20680f5f28c887b705827ba1c Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 27 Oct 2026 18:53:32 +0100 Subject: GUI: add on-screen toasts and atomic config writes - Toast queue drawn in the top-right by the overlay, independent of the GUI being open. Info/warn/error colors and 6/9/12 s lifetimes; timers start on the first painted frame so startup messages are not missed. - Queue a load toast after install_menu, plus warnings/errors for missing modules/interfaces/netvars, input hooks, fonts, ISurface, server datamap, and spread seed support. - Toast on config reload, reset, bind/unbind and config save failure. - Config saves now write `config.tmp`, flush, then rename it over the real file; failures leave the previous config intact. - config_load reports whether a file was found so Reload can distinguish a successful reload from a missing file. - Update CONTEXT and ISURFACE_STATUS for the single GUI, toasts and atomic config writes. --- src/hl2h.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src/hl2h.cpp') diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 1460577..c51d35e 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp @@ -467,7 +467,8 @@ static void hkdSrvRandomSeed(int seed) { } static void install_seed_hook() { - if (g_seed_hook_installed || !g_server.valid()) + static bool failed = false; + if (g_seed_hook_installed || failed || !g_server.valid()) return; g_srv_base = g_server.ranges[0].lo; uintptr_t slot = g_srv_base + 0xce1348; // R_386_JUMP_SLOT RandomSeed @@ -478,7 +479,9 @@ static void install_seed_hook() { if (!g_real_random_seed) g_real_random_seed = (void (*)(int))dlsym(RTLD_DEFAULT, "RandomSeed"); if (!g_real_random_seed) { + failed = true; logf("seed hook: real RandomSeed not found"); + toastf(TOAST_WARN, "Spread seed hook unavailable"); return; } mprotect((void *)(slot & ~(uintptr_t)0xFFF), 0x1000, @@ -808,6 +811,7 @@ static void *setup_thread(void *) { } if (!g_client.valid() || !g_engine.valid()) { logf("client.so/engine.so never appeared"); + toastf(TOAST_ERROR, "client.so/engine.so not found; hl2hake inactive"); return nullptr; } logf("client.so: %d mapped range(s), %s", (int)g_client.ranges.size(), @@ -822,6 +826,7 @@ static void *setup_thread(void *) { auto ef = (CreateInterfaceFn)dlsym(eh, "CreateInterface"); if (!cf || !ef) { logf("CreateInterface not found"); + toastf(TOAST_ERROR, "CreateInterface not found; hl2hake inactive"); return nullptr; } @@ -840,6 +845,7 @@ static void *setup_thread(void *) { logf("interfaces unresolved: VClient017=%p VClientEntityList003=%p " "VEngineClient014=%p", g_iface.client, g_iface.entitylist, g_iface.engine); + toastf(TOAST_ERROR, "Game interfaces unresolved; hl2hake inactive"); return nullptr; } logf("interfaces: VClient017=%p VClientEntityList003=%p " @@ -856,12 +862,27 @@ static void *setup_thread(void *) { g_iface.engineserver, g_iface.debugoverlay, g_iface.enginetrace); resolve_netvars(); - if (!find_input_global()) + if (!g_net.ok()) + toastf(TOAST_ERROR, "Netvars incomplete; features may be disabled"); + else if (g_net.absvelocity < 0) + toastf(TOAST_WARN, "Jumpbug assist disabled: velocity netvar missing"); + if (!g_iface.engineserver) + toastf(TOAST_WARN, "Server interfaces missing; jumpbug/spread limited"); + if (!g_iface.debugoverlay) + toastf(TOAST_WARN, "Debug overlay missing; ESP projection uses fallback"); + if (!g_iface.enginetrace) + toastf(TOAST_WARN, "Engine trace missing; vischeck fails open"); + + if (!find_input_global()) { + toastf(TOAST_ERROR, "Input hook failed; movement features disabled"); return nullptr; + } init_conmsg(); install_hook(); install_menu(); + if (g_surface) + toastf(TOAST_INFO, "hl2hake loaded - Insert opens the menu"); return nullptr; } -- cgit v1.2.3