From b287fc803c73d3ae076c49d726e17e13faa15050 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 11:39:18 +0100 Subject: Props: disable StudioRender hooks, fix m_clrRender offset Hooking IStudioRender's draw/setter slots made matched props render the error material and then crashed the material system ("debug/modelstats has bad reference count 0 when being bound"). Keep the hook code for reference but do not install it. Fix the m_clrRender netvar resolution: the walk picked an embedded table entry at offset 0, so the earlier entity writes stomped entity vtables. Only accept offsets inside C_BaseEntity (0x20..0x2000), then write the prop colour there for models/props entities. Restore white when disabled. --- src/esp.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'src/esp.cpp') diff --git a/src/esp.cpp b/src/esp.cpp index 1fd4904..64c1525 100644 --- a/src/esp.cpp +++ b/src/esp.cpp @@ -1405,12 +1405,58 @@ bool triggerbot_apply(CUserCmd *cmd) { return false; } -// Props are tinted through IStudioRender (studio.cpp), which covers both -// dynamic prop_physics entities and map-static props. There is no per-entity -// netvar write here: m_clrRender resolved to offset 0 in this build. +// Dynamic props are tinted through their client render colour. StudioRender +// feeds m_clrRender into the per-model colour modulation each draw, which is +// why tinting the prop material alone had no effect. (The IStudioRender hook +// experiment corrupted materials and crashed; see studio.cpp.) void prop_tint_update() { - if (feature_active(FEAT_WORLD_TINT) && g_tint_prop_on) - studio_props_init(); + static bool applied = false; + static bool logged_missing = false; + static bool logged_touched = false; + bool on = feature_active(FEAT_WORLD_TINT) && g_tint_prop_on; + if (!on && !applied) + return; + if (!g_iface.entitylist || g_net.clr_render < 0) { + if (on && !logged_missing) { + logged_missing = true; + logf("prop tint: m_clrRender unavailable"); + } + return; + } + static double last = 0.0; + double now = esp_now(); + if (on && now - last < 0.01) + return; + last = now; + + using Fn = int (*)(void *); + int hi = vfunc(g_iface.entitylist, 6)(g_iface.entitylist); + if (hi < 0 || hi > 4096) + hi = 4096; + uint32_t col = + on ? ((uint32_t)g_tint_prop_rgb[0] | ((uint32_t)g_tint_prop_rgb[1] << 8) | + ((uint32_t)g_tint_prop_rgb[2] << 16) | (255u << 24)) + : 0xFFFFFFFFu; + int touched = 0; + for (int idx = 1; idx <= hi; idx++) { + void *ent = entitylist_get(idx); + if (!ent) + continue; + const char *model = entity_model_name(ent); + if (!model) + continue; + bool prop = strncmp(model, "models/props", 12) == 0 || + strncmp(model, "props_", 6) == 0; + if (!prop) + continue; + *(uint32_t *)((uintptr_t)ent + (uintptr_t)g_net.clr_render) = col; + touched++; + } + applied = on; + if (on && touched > 0 && !logged_touched) { + logged_touched = true; + logf("prop tint: %d prop entities", touched); + } } void esp_draw() { -- cgit v1.2.3