From 2e9373d530bca779b4070a79972f246ef41e4038 Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 3 Nov 2026 22:03:01 +0100 Subject: GUI: recover invalid fonts; vischeck: props and bulletproof glass - Validate the GUI font handles with GetTextSize and recreate them when the local player entity or UI scale changes. Small scaled sizes fall back to the proven 16 px size, and the failure log/toast is emitted once instead of every frame. This fixes sessions where the menu rendered with no text after a level transition. - Rework visibility: trace with MASK_SHOT/TRACE_EVERYTHING while ignoring the local player and target, so static props, crates and other NPCs block. Non-solid glass and breakable-glass materials are skipped; solid non-break glass (bulletproof) blocks. Fix CONTENTS_WINDOW 0x2 (was 0x4) in the masks. - Pass self/target to is_visible from aimbot/silent/melee callers. --- src/gui.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 24 deletions(-) (limited to 'src/gui.cpp') diff --git a/src/gui.cpp b/src/gui.cpp index b512ef3..417860f 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -39,6 +39,8 @@ static unsigned long g_font_title = 0; static int g_body_h = 15; static int g_title_h = 20; static float g_font_scale = 0.0f; +static void *g_font_local = (void *)-1; +static bool g_font_fail_logged = false; static int g_scr_w = 0, g_scr_h = 0; static void s_color(int r, int g, int b, int a) { @@ -485,41 +487,97 @@ bool gui_toasts_active() { return active; } -static void ensure_fonts() { - if (g_font_body && fabsf(g_font_scale - g_scale) < 0.001f) - return; - g_font_scale = g_scale; - g_body_h = (int)(15.0f * g_scale + 0.5f); - g_title_h = (int)(20.0f * g_scale + 0.5f); - if (g_body_h < 11) g_body_h = 11; - if (g_title_h < 15) g_title_h = 15; +static bool font_valid(unsigned long f) { + if (!f || !g_surface) + return false; + int w = 0, h = 0; + s_text_size(f, L"M", w, h); + return w > 0 && h > 0; +} + +static void gui_reset_fonts() { + g_font_body = 0; + g_font_title = 0; + g_font_scale = 0.0f; +} + +static unsigned long create_gui_font(int tall) { static const char *families[] = {"Liberation Sans", "DejaVu Sans", "Noto Sans", "Tahoma", "Verdana", "Arial", nullptr}; + for (int i = 0; families[i]; i++) { + unsigned long f = s_create_font(); + if (!f) + break; + if (s_set_font(f, families[i], tall, 400, 0x400, 0x20, 0xFF) && + font_valid(f)) + return f; + } + return 0; +} + +static void ensure_fonts() { + void *le = nullptr; + if (g_iface.engine && g_iface.entitylist) { + int local = engine_get_local_player(); + if (local > 0) + le = entitylist_get(local); + } + if (le != g_font_local) { + g_font_local = le; + gui_reset_fonts(); + } + + bool scale_changed = fabsf(g_font_scale - g_scale) >= 0.001f; + if (g_font_body && g_font_title && !scale_changed && + font_valid(g_font_body) && font_valid(g_font_title)) + return; + // Level transitions can silently invalidate VGUI font handles. Recreate + // them instead of drawing invisible text. + if ((g_font_body && !font_valid(g_font_body)) || + (g_font_title && !font_valid(g_font_title))) + gui_reset_fonts(); + if (scale_changed) + gui_reset_fonts(); + + g_font_scale = g_scale; + int req_body = (int)(15.0f * g_scale + 0.5f); + int req_title = (int)(20.0f * g_scale + 0.5f); + if (req_body < 11) req_body = 11; + if (req_title < 15) req_title = 15; + g_body_h = req_body; + g_title_h = req_title; + + if (!g_font_body) + g_font_body = create_gui_font(g_body_h); + if (!g_font_title) + g_font_title = create_gui_font(g_title_h); + + // Small scaled sizes can fail in the font manager; 16 px is the proven ESP + // size, so use it as a readable fallback. if (!g_font_body) { - for (int i = 0; families[i] && !g_font_body; i++) { - unsigned long f = s_create_font(); - if (!f) - break; - if (s_set_font(f, families[i], g_body_h, 400, 0x400, 0x20, 0xFF)) - g_font_body = f; - } + g_body_h = 16; + g_font_body = create_gui_font(g_body_h); } if (!g_font_title) { - for (int i = 0; families[i] && !g_font_title; i++) { - unsigned long f = s_create_font(); - if (!f) - break; - if (s_set_font(f, families[i], g_title_h, 400, 0x400, 0x20, 0xFF)) - g_font_title = f; - } + g_title_h = 16; + g_font_title = create_gui_font(g_title_h); } if (!g_font_title) g_font_title = g_font_body; + if (!g_font_body) { - logf("gui: no usable body font"); - toastf(TOAST_ERROR, "No usable GUI font"); + if (!g_font_fail_logged) { + g_font_fail_logged = true; + logf("gui: no usable body font"); + toastf(TOAST_ERROR, "No usable GUI font"); + } + return; } + g_font_fail_logged = false; + if (g_body_h != req_body || g_title_h != req_title) + logd("gui: font fallback body=%d title=%d (requested %d/%d)", g_body_h, + g_title_h, req_body, req_title); } static int text_w(const char *s, int tall) { -- cgit v1.2.3