summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-04 12:52:03 +0100
committersalmonik <salmonik@tuta.io>2026-11-04 12:52:03 +0100
commit669d6c37306ca728e64836b61e9e466020129f48 (patch)
tree0061e6c9a289ff4912dbf44d2bc82b6d2244740a
parentProps: forward DrawModel's modelOrigin argument (diff)
downloadhl2h-669d6c37306ca728e64836b61e9e466020129f48.tar.gz
hl2h-669d6c37306ca728e64836b61e9e466020129f48.zip
ESP: render damage tags as small left-side labels
Draw ARM/VULN/IMM on the left edge of the box with a 10px font and a black 1px shadow, instead of full-size text above the name. The small font is a second HFont created next to the 16px body font. CONTEXT: document the DrawModel argument fix and the tag styling.
-rw-r--r--CONTEXT.md14
-rw-r--r--src/esp.cpp18
-rw-r--r--src/hl2h.h1
-rw-r--r--src/menu.cpp21
4 files changed, 47 insertions, 7 deletions
diff --git a/CONTEXT.md b/CONTEXT.md
index 7f8b131..5e36328 100644
--- a/CONTEXT.md
+++ b/CONTEXT.md
@@ -198,8 +198,10 @@ vocabulary / decisions.
198 - `VULNERABLE` — headcrab, antlion, manhack: punting them with the gravity 198 - `VULNERABLE` — headcrab, antlion, manhack: punting them with the gravity
199 gun / physics impact damage kills them. 199 gun / physics impact damage kills them.
200 - `NORMAL` — everything else. 200 - `NORMAL` — everything else.
201- ESP draws `ARMORED` (orange), `VULN` (cyan) or `IMMUNE` (grey) above the 201- ESP draws a small 10 px label on the left edge of the box with a black 1 px
202 name; toggle is `ESP → Damage tags` (`[esp] dmg=1`). 202 shadow: `ARM` (orange), `VULN` (cyan) or `IMM` (grey). Toggle is
203 `ESP → Damage tags` (`[esp] dmg=1`). The small font is a second `HFont`
204 created at glyph size 10 alongside the 16 px body font (`g_font_small`).
203- Aimbot/silent aim/triggerbot/melee skip `IMMUNE` targets always and 205- Aimbot/silent aim/triggerbot/melee skip `IMMUNE` targets always and
204 `ARMORED` targets unless the active weapon is the RPG 206 `ARMORED` targets unless the active weapon is the RPG
205 (`active_weapon_contains` for `rocket_launcher`/`rpg`). 207 (`active_weapon_contains` for `rocket_launcher`/`rpg`).
@@ -365,6 +367,14 @@ vocabulary / decisions.
365 `SetColorModulation(1,1,1)` *before* `DrawModel`. 367 `SetColorModulation(1,1,1)` *before* `DrawModel`.
366 Do not force `SetAlphaModulation` there: the earlier attempt produced 368 Do not force `SetAlphaModulation` there: the earlier attempt produced
367 error-material props and a material-system crash. 369 error-material props and a material-system crash.
370- `DrawModel` takes seven arguments after `this`: results, info, boneToWorld,
371 flexWeights, flexDelayedWeights, `const Vector &modelOrigin` (arrives as a
372 pointer) and `flags`. The hook must forward all of them; omitting
373 `modelOrigin` shifts `flags` into its slot and leaves the real `flags` as
374 caller stack garbage, which corrupted roughly every other prop draw
375 (checkerboard / error-material props). Verified against `studiorender.so`
376 0x83ad0: the callee reads `0x20(%ebp)` (modelOrigin) and `0x24(%ebp)`
377 (flags). `DrawModelStaticProp` takes info/modelToWorld/flags only.
368- `prop_tint_update()` also writes `m_clrRender` on prop entities (dynamic 378- `prop_tint_update()` also writes `m_clrRender` on prop entities (dynamic
369 props) as a secondary path; the netvar resolver rejects offset 0 (an 379 props) as a secondary path; the netvar resolver rejects offset 0 (an
370 embedded-table false positive) and only accepts 0x20..0x2000. 380 embedded-table false positive) and only accepts 0x20..0x2000.
diff --git a/src/esp.cpp b/src/esp.cpp
index aa9f645..51f46bc 100644
--- a/src/esp.cpp
+++ b/src/esp.cpp
@@ -1573,18 +1573,26 @@ void esp_draw() {
1573 const char *tag = nullptr; 1573 const char *tag = nullptr;
1574 int tr = 255, tg = 255, tb = 255; 1574 int tr = 255, tg = 255, tb = 255;
1575 if (t.damage == NPC_DMG_ARMORED) { 1575 if (t.damage == NPC_DMG_ARMORED) {
1576 tag = "ARMORED"; 1576 tag = "ARM";
1577 tr = 255; tg = 170; tb = 60; 1577 tr = 255; tg = 170; tb = 60;
1578 } else if (t.damage == NPC_DMG_VULNERABLE) { 1578 } else if (t.damage == NPC_DMG_VULNERABLE) {
1579 tag = "VULN"; 1579 tag = "VULN";
1580 tr = 90; tg = 220; tb = 255; 1580 tr = 90; tg = 220; tb = 255;
1581 } else if (t.damage == NPC_DMG_IMMUNE) { 1581 } else if (t.damage == NPC_DMG_IMMUNE) {
1582 tag = "IMMUNE"; 1582 tag = "IMM";
1583 tr = 180; tg = 180; tb = 180; 1583 tr = 180; tg = 180; tb = 180;
1584 } 1584 }
1585 if (tag) 1585 if (tag) {
1586 draw_text_col(left, top - (esp_option(ESP_OPT_SHOW_NAME) ? 28 : 14), 1586 // Small label on the left edge of the box, black 1px shadow for
1587 tag, tr, tg, tb); 1587 // readability against the world (the 10px ESP font).
1588 int tw = (int)strlen(tag) * 6;
1589 int tx = left - tw - 3;
1590 if (tx < 2)
1591 tx = 2;
1592 int ty = top + 2;
1593 draw_text_small_col(tx + 1, ty + 1, tag, 0, 0, 0);
1594 draw_text_small_col(tx, ty, tag, tr, tg, tb);
1595 }
1588 } 1596 }
1589 } 1597 }
1590 1598
diff --git a/src/hl2h.h b/src/hl2h.h
index 287563c..e35e737 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -297,6 +297,7 @@ void silentaim_reset_lock();
297void *entitylist_get(int idx); 297void *entitylist_get(int idx);
298int engine_get_local_player(); 298int engine_get_local_player();
299void draw_text_col(int x, int y, const char *s, int r, int g, int b); 299void draw_text_col(int x, int y, const char *s, int r, int g, int b);
300void draw_text_small_col(int x, int y, const char *s, int r, int g, int b);
300void esp_draw(); 301void esp_draw();
301void esp_draw_items(); 302void esp_draw_items();
302void prop_tint_update(); 303void prop_tint_update();
diff --git a/src/menu.cpp b/src/menu.cpp
index eb1075a..00aa189 100644
--- a/src/menu.cpp
+++ b/src/menu.cpp
@@ -683,6 +683,7 @@ using HFont = unsigned long;
683 683
684ISurface *g_surface = nullptr; 684ISurface *g_surface = nullptr;
685static HFont g_font = 0; 685static HFont g_font = 0;
686static HFont g_font_small = 0;
686 687
687// VGUI_Surface030 vtable slots (confirmed via binary disassembly of vguimatsurface.so): 688// VGUI_Surface030 vtable slots (confirmed via binary disassembly of vguimatsurface.so):
688// 8 = PushMakeCurrent(VPANEL, bool useInsets) — reads args at 0xc/0x10(%ebp) 689// 8 = PushMakeCurrent(VPANEL, bool useInsets) — reads args at 0xc/0x10(%ebp)
@@ -778,6 +779,16 @@ void draw_text_col(int x, int y, const char *text, int r, int g, int b) {
778 surf_draw_print_text(wtext, (int)wcslen(wtext)); 779 surf_draw_print_text(wtext, (int)wcslen(wtext));
779} 780}
780 781
782void draw_text_small_col(int x, int y, const char *text, int r, int g, int b) {
783 wchar_t wtext[256];
784 mbstowcs(wtext, text, 255);
785 wtext[255] = 0;
786 surf_draw_set_text_font(g_font_small ? g_font_small : g_font);
787 surf_draw_set_text_color(r, g, b, 255);
788 surf_draw_set_text_pos(x, y);
789 surf_draw_print_text(wtext, (int)wcslen(wtext));
790}
791
781// --------------------------------------------------------------------------- 792// ---------------------------------------------------------------------------
782// mat_fullbright 793// mat_fullbright
783// --------------------------------------------------------------------------- 794// ---------------------------------------------------------------------------
@@ -849,6 +860,7 @@ void outer_draw() {
849 } 860 }
850 if (font_reset && g_font) { 861 if (font_reset && g_font) {
851 g_font = 0; 862 g_font = 0;
863 g_font_small = 0;
852 logd("font: reset (local entity change)"); 864 logd("font: reset (local entity change)");
853 } 865 }
854 866
@@ -858,6 +870,7 @@ void outer_draw() {
858 "Liberation Sans", "DejaVu Sans", "Noto Sans", "Tahoma", 870 "Liberation Sans", "DejaVu Sans", "Noto Sans", "Tahoma",
859 "Verdana", "Arial", nullptr}; 871 "Verdana", "Arial", nullptr};
860 bool font_ok = false; 872 bool font_ok = false;
873 const char *chosen = nullptr;
861 for (int fi = 0; families[fi] && !font_ok; fi++) { 874 for (int fi = 0; families[fi] && !font_ok; fi++) {
862 g_font = surf_create_font(); 875 g_font = surf_create_font();
863 if (!g_font) 876 if (!g_font)
@@ -866,10 +879,18 @@ void outer_draw() {
866 0x20, 0xFF)) { 879 0x20, 0xFF)) {
867 logd("outer_draw: font family %s", families[fi]); 880 logd("outer_draw: font family %s", families[fi]);
868 font_ok = true; 881 font_ok = true;
882 chosen = families[fi];
869 } else { 883 } else {
870 g_font = 0; 884 g_font = 0;
871 } 885 }
872 } 886 }
887 if (font_ok && chosen && !g_font_small) {
888 g_font_small = surf_create_font();
889 if (g_font_small &&
890 !surf_set_font_glyph_set(g_font_small, chosen, 10, 400, 0, 0, 0x400,
891 0x20, 0xFF))
892 g_font_small = 0;
893 }
873 if (!font_ok) { 894 if (!font_ok) {
874 logf("outer_draw: no usable font"); 895 logf("outer_draw: no usable font");
875 toastf(TOAST_ERROR, "No usable overlay font"); 896 toastf(TOAST_ERROR, "No usable overlay font");