summaryrefslogtreecommitdiffstats
path: root/src/gui.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-03 22:03:01 +0100
committersalmonik <salmonik@tuta.io>2026-11-03 22:03:01 +0100
commit2e9373d530bca779b4070a79972f246ef41e4038 (patch)
treecc263d92cdcf7c9befd29f36da3cf04ed0b3a7f4 /src/gui.cpp
parentHandles: use the 11-bit networked EHANDLE entity index (diff)
downloadhl2h-2e9373d530bca779b4070a79972f246ef41e4038.tar.gz
hl2h-2e9373d530bca779b4070a79972f246ef41e4038.zip
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.
Diffstat (limited to 'src/gui.cpp')
-rw-r--r--src/gui.cpp106
1 files changed, 82 insertions, 24 deletions
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;
39static int g_body_h = 15; 39static int g_body_h = 15;
40static int g_title_h = 20; 40static int g_title_h = 20;
41static float g_font_scale = 0.0f; 41static float g_font_scale = 0.0f;
42static void *g_font_local = (void *)-1;
43static bool g_font_fail_logged = false;
42static int g_scr_w = 0, g_scr_h = 0; 44static int g_scr_w = 0, g_scr_h = 0;
43 45
44static void s_color(int r, int g, int b, int a) { 46static void s_color(int r, int g, int b, int a) {
@@ -485,41 +487,97 @@ bool gui_toasts_active() {
485 return active; 487 return active;
486} 488}
487 489
488static void ensure_fonts() { 490static bool font_valid(unsigned long f) {
489 if (g_font_body && fabsf(g_font_scale - g_scale) < 0.001f) 491 if (!f || !g_surface)
490 return; 492 return false;
491 g_font_scale = g_scale; 493 int w = 0, h = 0;
492 g_body_h = (int)(15.0f * g_scale + 0.5f); 494 s_text_size(f, L"M", w, h);
493 g_title_h = (int)(20.0f * g_scale + 0.5f); 495 return w > 0 && h > 0;
494 if (g_body_h < 11) g_body_h = 11; 496}
495 if (g_title_h < 15) g_title_h = 15; 497
498static void gui_reset_fonts() {
499 g_font_body = 0;
500 g_font_title = 0;
501 g_font_scale = 0.0f;
502}
503
504static unsigned long create_gui_font(int tall) {
496 static const char *families[] = {"Liberation Sans", "DejaVu Sans", 505 static const char *families[] = {"Liberation Sans", "DejaVu Sans",
497 "Noto Sans", "Tahoma", "Verdana", "Arial", 506 "Noto Sans", "Tahoma", "Verdana", "Arial",
498 nullptr}; 507 nullptr};
508 for (int i = 0; families[i]; i++) {
509 unsigned long f = s_create_font();
510 if (!f)
511 break;
512 if (s_set_font(f, families[i], tall, 400, 0x400, 0x20, 0xFF) &&
513 font_valid(f))
514 return f;
515 }
516 return 0;
517}
518
519static void ensure_fonts() {
520 void *le = nullptr;
521 if (g_iface.engine && g_iface.entitylist) {
522 int local = engine_get_local_player();
523 if (local > 0)
524 le = entitylist_get(local);
525 }
526 if (le != g_font_local) {
527 g_font_local = le;
528 gui_reset_fonts();
529 }
530
531 bool scale_changed = fabsf(g_font_scale - g_scale) >= 0.001f;
532 if (g_font_body && g_font_title && !scale_changed &&
533 font_valid(g_font_body) && font_valid(g_font_title))
534 return;
535 // Level transitions can silently invalidate VGUI font handles. Recreate
536 // them instead of drawing invisible text.
537 if ((g_font_body && !font_valid(g_font_body)) ||
538 (g_font_title && !font_valid(g_font_title)))
539 gui_reset_fonts();
540 if (scale_changed)
541 gui_reset_fonts();
542
543 g_font_scale = g_scale;
544 int req_body = (int)(15.0f * g_scale + 0.5f);
545 int req_title = (int)(20.0f * g_scale + 0.5f);
546 if (req_body < 11) req_body = 11;
547 if (req_title < 15) req_title = 15;
548 g_body_h = req_body;
549 g_title_h = req_title;
550
551 if (!g_font_body)
552 g_font_body = create_gui_font(g_body_h);
553 if (!g_font_title)
554 g_font_title = create_gui_font(g_title_h);
555
556 // Small scaled sizes can fail in the font manager; 16 px is the proven ESP
557 // size, so use it as a readable fallback.
499 if (!g_font_body) { 558 if (!g_font_body) {
500 for (int i = 0; families[i] && !g_font_body; i++) { 559 g_body_h = 16;
501 unsigned long f = s_create_font(); 560 g_font_body = create_gui_font(g_body_h);
502 if (!f)
503 break;
504 if (s_set_font(f, families[i], g_body_h, 400, 0x400, 0x20, 0xFF))
505 g_font_body = f;
506 }
507 } 561 }
508 if (!g_font_title) { 562 if (!g_font_title) {
509 for (int i = 0; families[i] && !g_font_title; i++) { 563 g_title_h = 16;
510 unsigned long f = s_create_font(); 564 g_font_title = create_gui_font(g_title_h);
511 if (!f)
512 break;
513 if (s_set_font(f, families[i], g_title_h, 400, 0x400, 0x20, 0xFF))
514 g_font_title = f;
515 }
516 } 565 }
517 if (!g_font_title) 566 if (!g_font_title)
518 g_font_title = g_font_body; 567 g_font_title = g_font_body;
568
519 if (!g_font_body) { 569 if (!g_font_body) {
520 logf("gui: no usable body font"); 570 if (!g_font_fail_logged) {
521 toastf(TOAST_ERROR, "No usable GUI font"); 571 g_font_fail_logged = true;
572 logf("gui: no usable body font");
573 toastf(TOAST_ERROR, "No usable GUI font");
574 }
575 return;
522 } 576 }
577 g_font_fail_logged = false;
578 if (g_body_h != req_body || g_title_h != req_title)
579 logd("gui: font fallback body=%d title=%d (requested %d/%d)", g_body_h,
580 g_title_h, req_body, req_title);
523} 581}
524 582
525static int text_w(const char *s, int tall) { 583static int text_w(const char *s, int tall) {