From c91c7248fcb3911a8a2b6442d8657167364a911c Mon Sep 17 00:00:00 2001 From: salmonik Date: Tue, 27 Oct 2026 21:11:32 +0100 Subject: Stucklaunch: fix prop detection and add diagnostics - Client physics props are CPhysicsProp/CPhysBox, not the server class prop_physics; the old case-sensitive class check never matched. Detect MOVETYPE_VPHYSICS first (the reliable signal), then case-insensitive class/model patterns. - Log the first few prop checks with index, movetype, class and model so a failed ground lookup is diagnosable. - Log once when Stucklaunch is active (with run state, bind and ground offset), when it engages, and when the ground is not a prop. - Toast a warning when binding a feature that is not Active yet. --- src/esp.cpp | 46 +++++++++++++++++++++++++++++++++++++++------- src/gui.cpp | 7 ++++++- src/hl2h.cpp | 29 +++++++++++++++++++++++++++-- src/hl2h.h | 2 +- 4 files changed, 73 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/esp.cpp b/src/esp.cpp index bda6232..ca7bae0 100644 --- a/src/esp.cpp +++ b/src/esp.cpp @@ -2,6 +2,7 @@ #include "hl2h.h" #include #include +#include #include #include #include @@ -1131,18 +1132,49 @@ static void spread_compute() { g_spread_ready = true; } +static bool icontains(const char *hay, const char *needle) { + if (!hay || !needle || !*needle) + return false; + size_t n = strlen(needle); + for (const char *p = hay; *p; p++) + if (strncasecmp(p, needle, n) == 0) + return true; + return false; +} + bool entity_is_physics_prop(int idx) { if (idx <= 0 || idx > 4096) return false; + void *ent = entitylist_get(idx); + if (!ent) + return false; + int mt = -1; + // The reliable signal: physics objects use MOVETYPE_VPHYSICS. The client + // class is CPhysicsProp / CPhysBox, not the server's prop_physics name. + if (g_net.movetype >= 0) { + mt = *(int *)((uintptr_t)ent + g_net.movetype); + if (mt == MOVETYPE_VPHYSICS) + return true; + } void *net = entity_networkable(idx); const char *cls = net ? entity_class_name(net, nullptr) : nullptr; - void *ent = entitylist_get(idx); - const char *model = ent ? entity_model_name(ent) : nullptr; - if (cls && (strstr(cls, "prop_physics") || strstr(cls, "physbox"))) - return true; - if (model && (strstr(model, "props_junk") || strstr(model, "props_physics"))) - return true; - return false; + const char *model = entity_model_name(ent); + bool is_prop = icontains(cls, "physicsprop") || icontains(cls, "physbox") || + icontains(cls, "prop_physics") || + icontains(model, "props_junk") || + icontains(model, "props_physics") || + icontains(model, "props_c17") || + icontains(model, "props_interiors") || + icontains(model, "props_lab"); + if (!is_prop) { + static int miss_logs = 0; + if (miss_logs < 6) { + miss_logs++; + logf("stucklaunch prop? idx=%d movetype=%d cls=%s model=%s", idx, mt, + cls ? cls : "?", model ? model : "?"); + } + } + return is_prop; } bool active_weapon_is_gravity_gun(void *local_ent) { diff --git a/src/gui.cpp b/src/gui.cpp index 9af8003..156e496 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -879,6 +879,8 @@ static void handle_capture(const unsigned char *keys) { config_save(); toastf(TOAST_INFO, "%s bound to %s", card.title, scancode_name(card.feat->bind)); + if (!card.feat->active) + toastf(TOAST_WARN, "%s is not Active yet", card.title); return; } for (int k = 0; k < 512; k++) { @@ -890,9 +892,12 @@ static void handle_capture(const unsigned char *keys) { card.feat->bind = k; g_capture_card = -1; config_save(); - if (card.feat) + if (card.feat) { toastf(TOAST_INFO, "%s bound to %s", card.title, scancode_name(card.feat->bind)); + if (!card.feat->active) + toastf(TOAST_WARN, "%s is not Active yet", card.title); + } return; } } diff --git a/src/hl2h.cpp b/src/hl2h.cpp index 84de815..defdd27 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp @@ -172,8 +172,14 @@ static void apply_autostrafe(CUserCmd *cmd, const float *vel) { // True while the player stands on (or just left) a physics prop. m_hGroundEntity // is latched briefly because it clears during each hop. static bool stucklaunch_prop_ok(void *ent, int tick) { - if (g_net.groundentity < 0) + if (g_net.groundentity < 0) { + static bool logged = false; + if (!logged) { + logged = true; + logf("stucklaunch: m_hGroundEntity unavailable; prop detection off"); + } return true; // no netvar: the bind is the only safeguard + } static int last_prop_tick = -100000; uint32_t h = *(uint32_t *)((uintptr_t)ent + g_net.groundentity); int gi = (h == 0xFFFFFFFFu) ? 0 : (int)(h & 0xFFFF); @@ -182,9 +188,15 @@ static bool stucklaunch_prop_ok(void *ent, int tick) { static int prop_logs = 0; if (prop_logs < 4) { prop_logs++; - logf("stucklaunch: prop idx=%d", gi); + logf("stucklaunch: prop idx=%d engaged", gi); } last_prop_tick = tick; + } else { + static int miss_logs = 0; + if (miss_logs < 4) { + miss_logs++; + logf("stucklaunch: ground h=%#x idx=%d is not a physics prop", h, gi); + } } return tick - last_prop_tick < 32; // ~0.5 s at 66 tick } @@ -194,6 +206,11 @@ static bool stucklaunch_prop_ok(void *ent, int tick) { // gun's +attack) to keep regrabbing the prop, and air-strafes the hops. static void stucklaunch_apply(CUserCmd *cmd, void *local_ent, bool onground, const float *vel) { + static bool engaged_logged = false; + if (!engaged_logged) { + engaged_logged = true; + logf("stucklaunch: applying jump/spam (onground=%d)", (int)onground); + } cmd->buttons |= IN_JUMP; int period = stucklaunch_spam_ticks(); if (period < 1) @@ -629,6 +646,14 @@ static void do_move(int seq, float frametime) { } bool stuck_on = feature_active(FEAT_STUCKLAUNCH); + if (g_stucklaunch.active) { + static bool state_logged = false; + if (!state_logged) { + state_logged = true; + logf("stucklaunch: active=1 run=%d bind=%d groundoff=%d", + (int)stuck_on, g_stucklaunch.bind, g_net.groundentity); + } + } bool stuck_engaged = stuck_on && stucklaunch_prop_ok(ent, cmd->tick_count); if (stuck_engaged) { stucklaunch_apply(cmd, ent, onground, vel); diff --git a/src/hl2h.h b/src/hl2h.h index 2607ece..d6729cb 100644 --- a/src/hl2h.h +++ b/src/hl2h.h @@ -141,7 +141,7 @@ struct CUserCmd { enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 }; enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; -enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; +enum { MOVETYPE_WALK = 2, MOVETYPE_VPHYSICS = 6, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; // --------------------------------------------------------------------------- // vector math -- cgit v1.2.3