summaryrefslogtreecommitdiffstats
path: root/src/esp.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/esp.cpp92
1 files changed, 63 insertions, 29 deletions
diff --git a/src/esp.cpp b/src/esp.cpp
index e273bf6..447bee7 100644
--- a/src/esp.cpp
+++ b/src/esp.cpp
@@ -62,6 +62,12 @@ bool world_to_screen(const Vector &w, float &sx, float &sy) {
62 vfunc<Fn>(g_iface.debugoverlay, 9)(g_iface.debugoverlay, &w, &s); 62 vfunc<Fn>(g_iface.debugoverlay, 9)(g_iface.debugoverlay, &w, &s);
63 if (behind) 63 if (behind)
64 return false; 64 return false;
65 // A point on the view axis (e.g. directly below the feet) can produce
66 // NaN/inf or enormous coordinates; drawing those as ints corrupts the
67 // surface clip state and hides the rest of the overlay.
68 if (!std::isfinite(s.x) || !std::isfinite(s.y) || fabsf(s.x) > 1e7f ||
69 fabsf(s.y) > 1e7f)
70 return false;
65 sx = s.x; 71 sx = s.x;
66 sy = s.y; 72 sy = s.y;
67 return true; 73 return true;
@@ -82,7 +88,8 @@ bool world_to_screen(const Vector &w, float &sx, float &sy) {
82 float tanfov = tanf(75.0f * 0.5f * PI_F / 180.0f); 88 float tanfov = tanf(75.0f * 0.5f * PI_F / 180.0f);
83 sx = (float)g_scr_w * 0.5f + (x / z) * ((float)g_scr_w * 0.5f / tanfov); 89 sx = (float)g_scr_w * 0.5f + (x / z) * ((float)g_scr_w * 0.5f / tanfov);
84 sy = (float)g_scr_h * 0.5f - (y / z) * ((float)g_scr_w * 0.5f / tanfov); 90 sy = (float)g_scr_h * 0.5f - (y / z) * ((float)g_scr_w * 0.5f / tanfov);
85 return true; 91 return std::isfinite(sx) && std::isfinite(sy) && fabsf(sx) < 1e7f &&
92 fabsf(sy) < 1e7f;
86} 93}
87 94
88// --------------------------------------------------------------------------- 95// ---------------------------------------------------------------------------
@@ -2346,8 +2353,30 @@ static void items_collect(int local_idx) {
2346 int active_idx = local_active_weapon_idx(local_idx); 2353 int active_idx = local_active_weapon_idx(local_idx);
2347 2354
2348 // Which weapon types the local player already carries. A fallen weapon of 2355 // Which weapon types the local player already carries. A fallen weapon of
2349 // the same type is then just an ammo pickup. 2356 // the same type is then just an ammo pickup. Owner handles are unreliable on
2350 bool owned_weapon[WT_COUNT] = {}; 2357 // this client (owner/weapon_owner netvars resolve to -1), so remember every
2358 // type the player has held since the current local entity appeared.
2359 static uint32_t owned_mask = 0;
2360 static void *last_local = nullptr;
2361 void *local_ent = entitylist_get(local_idx);
2362 if (local_ent != last_local) {
2363 last_local = local_ent;
2364 owned_mask = 0;
2365 }
2366 int owned_idx = active_idx;
2367 if (owned_idx <= 0 && g_iface.engineserver) {
2368 resolve_server_netvars();
2369 owned_idx = server_active_weapon(local_idx);
2370 }
2371 if (owned_idx > 0) {
2372 void *aw = entitylist_get(owned_idx);
2373 void *anet = entity_networkable(owned_idx);
2374 const char *acls = anet ? entity_class_name(anet, nullptr) : nullptr;
2375 const char *amodel = aw ? entity_model_name(aw) : nullptr;
2376 int at = weapon_type_id(amodel, acls);
2377 if (at > 0)
2378 owned_mask |= 1u << at;
2379 }
2351 for (int idx = 1; idx <= hi; idx++) { 2380 for (int idx = 1; idx <= hi; idx++) {
2352 if (idx == local_idx) 2381 if (idx == local_idx)
2353 continue; 2382 continue;
@@ -2359,8 +2388,11 @@ static void items_collect(int local_idx) {
2359 const char *model = entity_model_name(ent); 2388 const char *model = entity_model_name(ent);
2360 int wt = weapon_type_id(model, cls); 2389 int wt = weapon_type_id(model, cls);
2361 if (wt > 0) 2390 if (wt > 0)
2362 owned_weapon[wt] = true; 2391 owned_mask |= 1u << wt;
2363 } 2392 }
2393 bool owned_weapon[WT_COUNT] = {};
2394 for (int t = 1; t < WT_COUNT; t++)
2395 owned_weapon[t] = (owned_mask & (1u << t)) != 0;
2364 static bool cats_logged = false; 2396 static bool cats_logged = false;
2365 if (!cats_logged) { 2397 if (!cats_logged) {
2366 cats_logged = true; 2398 cats_logged = true;
@@ -2706,12 +2738,6 @@ void esp_draw_projectiles() {
2706 projs_collect(engine_get_local_player()); 2738 projs_collect(engine_get_local_player());
2707 for (int i = 0; i < g_nprojs; i++) { 2739 for (int i = 0; i < g_nprojs; i++) {
2708 const ProjTarget &p = g_projs[i]; 2740 const ProjTarget &p = g_projs[i];
2709 float sx, sy;
2710 if (!world_to_screen(p.origin, sx, sy))
2711 continue;
2712 if (sx < -40 || sx > (float)g_scr_w + 40 || sy < -40 ||
2713 sy > (float)g_scr_h + 40)
2714 continue;
2715 int r = 255, g = 170, b = 60; 2741 int r = 255, g = 170, b = 60;
2716 if (p.kind == PK_RPG) { 2742 if (p.kind == PK_RPG) {
2717 r = 255; g = 120; b = 40; 2743 r = 255; g = 120; b = 40;
@@ -2722,25 +2748,33 @@ void esp_draw_projectiles() {
2722 } else if (p.fuse >= 0.0f && p.fuse < 0.8f) { 2748 } else if (p.fuse >= 0.0f && p.fuse < 0.8f) {
2723 r = 255; g = 60; b = 60; 2749 r = 255; g = 60; b = 60;
2724 } 2750 }
2725 int x = (int)sx, y = (int)sy; 2751 float sx, sy;
2726 surf_color(r, g, b, 255); 2752 bool center_ok = world_to_screen(p.origin, sx, sy) &&
2727 surf_rect(0, x - 4, y - 4, x + 4, y + 4); 2753 sx >= -40.0f && sx <= (float)g_scr_w + 40.0f &&
2728 surf_rect(1, x - 1, y - 1, x + 2, y + 2); 2754 sy >= -40.0f && sy <= (float)g_scr_h + 40.0f;
2729 char text[64]; 2755 if (center_ok) {
2730 if (g_proj_fuse && p.fuse >= 0.0f) 2756 int x = (int)sx, y = (int)sy;
2731 snprintf(text, sizeof(text), "%s %.1fs", proj_name(p.kind), p.fuse); 2757 surf_color(r, g, b, 255);
2732 else 2758 surf_rect(0, x - 4, y - 4, x + 4, y + 4);
2733 snprintf(text, sizeof(text), "%s", proj_name(p.kind)); 2759 surf_rect(1, x - 1, y - 1, x + 2, y + 2);
2734 int tx = x + 9; 2760 char text[64];
2735 if (tx > g_scr_w - 80) 2761 if (g_proj_fuse && p.fuse >= 0.0f)
2736 tx = x - 9 - (int)strlen(text) * 6; 2762 snprintf(text, sizeof(text), "%s %.1fs", proj_name(p.kind), p.fuse);
2737 if (tx < 4) 2763 else
2738 tx = 4; 2764 snprintf(text, sizeof(text), "%s", proj_name(p.kind));
2739 int ty = y - 14; 2765 int tx = x + 9;
2740 if (ty < 4) 2766 if (tx > g_scr_w - 80)
2741 ty = 4; 2767 tx = x - 9 - (int)strlen(text) * 6;
2742 draw_text_small_col(tx + 1, ty + 1, text, 0, 0, 0); 2768 if (tx < 4)
2743 draw_text_small_col(tx, ty, text, r, g, b); 2769 tx = 4;
2770 int ty = y - 14;
2771 if (ty < 4)
2772 ty = 4;
2773 draw_text_small_col(tx + 1, ty + 1, text, 0, 0, 0);
2774 draw_text_small_col(tx, ty, text, r, g, b);
2775 }
2776 // The ring is useful even when the grenade itself is behind the camera or
2777 // off-screen, so it is not gated on center_ok.
2744 if (g_proj_radius && p.radius > 1.0f) { 2778 if (g_proj_radius && p.radius > 1.0f) {
2745 const int SEG = 24; 2779 const int SEG = 24;
2746 float lx = 0.0f, ly = 0.0f; 2780 float lx = 0.0f, ly = 0.0f;