From 38c40b7536f6142253a26ba29bedb7a2b2039c12 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 17:34:35 +0100 Subject: Items/projectiles: ammo diagnostics, dispensers, launched RPG - Exempt chargers and ammo/supply crates from the fullness filter; reusable dispensers stay visible at max ammo/health. - Log the local ammo current/max table once and the first 24 ammo filter decisions, so the RPG/grenade/weapon cases can be diagnosed. - Classify the launched w_missile as an RPG projectile (class not item/ weapon) and exclude the w_missile_closed ammo pickup from projectile ESP. --- src/esp.cpp | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/esp.cpp b/src/esp.cpp index b4d3eee..a12cf9c 100644 --- a/src/esp.cpp +++ b/src/esp.cpp @@ -2796,11 +2796,32 @@ void esp_draw_items() { if (g_item_usable) local_vitals(vit_hp, vit_max, vit_armor); + static bool ammo_logged = false; + if (!ammo_logged) { + ammo_logged = true; + void *le = entitylist_get(local); + char buf[512] = {}; + int used = 0; + for (int t = 0; t < 12 && used < (int)sizeof(buf) - 24; t++) { + int w = snprintf(buf + used, sizeof(buf) - (size_t)used, "%d=%d/%d ", t, + local_ammo(le, t), ammo_max(t)); + if (w < 0) + break; + used += w; + } + logf("items: ammo current/max %s(usable=%d my_weapons=%d ammo=%d)", buf, + (int)g_item_usable, g_net.my_weapons, g_net.ammo); + } + for (int i = 0; i < g_nitems; i++) { const ItemTarget &t = g_item_targets[i]; if (!item_kind_enabled(t.kind)) continue; - if (g_item_usable) { + // Dispensers (chargers, ammo crates, supply crates) stay useful after a + // refill, so the fullness filter does not apply to them. + bool dispenser = strcasestr(t.label, "crate") || + strcasestr(t.label, "charger"); + if (g_item_usable && !dispenser) { if (t.kind == IK_HEALTH && vit_hp >= 0 && vit_max > 0 && vit_hp >= vit_max) continue; @@ -2809,6 +2830,12 @@ void esp_draw_items() { if (t.kind == IK_AMMO && t.ammo_type >= 0) { int maxa = ammo_max(t.ammo_type); int cura = local_ammo(entitylist_get(local), t.ammo_type); + static int flt_logs = 0; + if (flt_logs < 24) { + flt_logs++; + logf("items: ammo %s type=%d cur=%d max=%d", t.label, t.ammo_type, + cura, maxa); + } if (maxa > 0 && cura >= 0 && cura >= maxa) continue; } @@ -2946,16 +2973,17 @@ static void projs_collect(int local_idx) { bool owned = item_weapon_is_owned(ent); bool frag_cls = cls && strcasestr(cls, "grenade") && !strcasestr(cls, "weapon"); - bool missile_cls = cls && strcasestr(cls, "missile") && - !strcasestr(cls, "weapon"); + bool item_cls = cls && (strcasestr(cls, "item") || + strcasestr(cls, "weapon")); + bool missile_model = strcasestr(model, "w_missile") && + !strcasestr(model, "missile_closed"); int kind; if (strcasestr(model, "w_grenade") && (frag_cls || (!cls && owned))) { kind = PK_FRAG; - } else if ((strcasestr(model, "w_missile") || - strcasestr(model, "missile_launch") || - strcasestr(model, "missile_closed")) && - (missile_cls || (!cls && owned))) { + } else if ((missile_model || strcasestr(model, "missile_launch")) && + !item_cls) { + // Launched RPG rocket; ammo pickups/weapons use the same model family. kind = PK_RPG; } else if (strcasestr(model, "helicopter_bomb")) { kind = PK_BOMB; -- cgit v1.2.3