diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/esp.cpp | 111 | ||||
| -rw-r--r-- | src/server.cpp | 9 |
2 files changed, 113 insertions, 7 deletions
diff --git a/src/esp.cpp b/src/esp.cpp index c956d1b..e273bf6 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -2049,6 +2049,21 @@ static bool item_weapon_is_owned(void *ent) { | |||
| 2049 | return false; | 2049 | return false; |
| 2050 | } | 2050 | } |
| 2051 | 2051 | ||
| 2052 | // Entity index of the weapon's owner, or -1. Used to distinguish the local | ||
| 2053 | // player's inventory from NPC weapons. | ||
| 2054 | static int item_weapon_owner_idx(void *ent) { | ||
| 2055 | if (!ent) | ||
| 2056 | return -1; | ||
| 2057 | uint32_t h = 0; | ||
| 2058 | if (g_net.owner >= 0) | ||
| 2059 | h = *(uint32_t *)((uintptr_t)ent + g_net.owner); | ||
| 2060 | if (!item_handle_valid(h) && g_net.weapon_owner >= 0) | ||
| 2061 | h = *(uint32_t *)((uintptr_t)ent + g_net.weapon_owner); | ||
| 2062 | if (!item_handle_valid(h)) | ||
| 2063 | return -1; | ||
| 2064 | return (int)(h & 0x7FF); | ||
| 2065 | } | ||
| 2066 | |||
| 2052 | static int local_active_weapon_idx(int local_idx) { | 2067 | static int local_active_weapon_idx(int local_idx) { |
| 2053 | if (local_idx <= 0 || g_net.activeweapon < 0) | 2068 | if (local_idx <= 0 || g_net.activeweapon < 0) |
| 2054 | return -1; | 2069 | return -1; |
| @@ -2104,6 +2119,44 @@ static int classify_weapon(const char *model, const char *cls, char *label, | |||
| 2104 | return 1; | 2119 | return 1; |
| 2105 | } | 2120 | } |
| 2106 | 2121 | ||
| 2122 | // Weapon identity for the "owned weapon -> fallen weapon is ammo" rule. | ||
| 2123 | enum { | ||
| 2124 | WT_NONE = 0, | ||
| 2125 | WT_PISTOL, | ||
| 2126 | WT_357, | ||
| 2127 | WT_SMG, | ||
| 2128 | WT_AR2, | ||
| 2129 | WT_SHOTGUN, | ||
| 2130 | WT_CROSSBOW, | ||
| 2131 | WT_RPG, | ||
| 2132 | WT_GRENADE, | ||
| 2133 | WT_SNIPER, | ||
| 2134 | WT_COUNT | ||
| 2135 | }; | ||
| 2136 | |||
| 2137 | static int weapon_type_id(const char *model, const char *cls) { | ||
| 2138 | if (item_icontains(model, "pistol") || item_icontains(cls, "pistol")) | ||
| 2139 | return WT_PISTOL; | ||
| 2140 | if (item_icontains(model, "357") || item_icontains(cls, "357")) | ||
| 2141 | return WT_357; | ||
| 2142 | if (item_icontains(model, "smg") || item_icontains(cls, "smg")) | ||
| 2143 | return WT_SMG; | ||
| 2144 | if (item_icontains(model, "ar2") || item_icontains(model, "irifle") || | ||
| 2145 | item_icontains(cls, "ar2") || item_icontains(cls, "irifle")) | ||
| 2146 | return WT_AR2; | ||
| 2147 | if (item_icontains(model, "shotgun") || item_icontains(cls, "shotgun")) | ||
| 2148 | return WT_SHOTGUN; | ||
| 2149 | if (item_icontains(model, "crossbow") || item_icontains(cls, "crossbow")) | ||
| 2150 | return WT_CROSSBOW; | ||
| 2151 | if (item_icontains(model, "rocket") || item_icontains(cls, "rpg")) | ||
| 2152 | return WT_RPG; | ||
| 2153 | if (item_icontains(model, "grenade") || item_icontains(cls, "frag")) | ||
| 2154 | return WT_GRENADE; | ||
| 2155 | if (item_icontains(model, "sniper") || item_icontains(cls, "sniper")) | ||
| 2156 | return WT_SNIPER; | ||
| 2157 | return WT_NONE; | ||
| 2158 | } | ||
| 2159 | |||
| 2107 | static int classify_item(const char *model, const char *cls, char *label, | 2160 | static int classify_item(const char *model, const char *cls, char *label, |
| 2108 | size_t outn) { | 2161 | size_t outn) { |
| 2109 | if (!model && !cls) | 2162 | if (!model && !cls) |
| @@ -2291,6 +2344,23 @@ static void items_collect(int local_idx) { | |||
| 2291 | if (hi < 0 || hi > 4096) | 2344 | if (hi < 0 || hi > 4096) |
| 2292 | hi = 4096; | 2345 | hi = 4096; |
| 2293 | int active_idx = local_active_weapon_idx(local_idx); | 2346 | int active_idx = local_active_weapon_idx(local_idx); |
| 2347 | |||
| 2348 | // Which weapon types the local player already carries. A fallen weapon of | ||
| 2349 | // the same type is then just an ammo pickup. | ||
| 2350 | bool owned_weapon[WT_COUNT] = {}; | ||
| 2351 | for (int idx = 1; idx <= hi; idx++) { | ||
| 2352 | if (idx == local_idx) | ||
| 2353 | continue; | ||
| 2354 | void *ent = entitylist_get(idx); | ||
| 2355 | if (!ent || item_weapon_owner_idx(ent) != local_idx) | ||
| 2356 | continue; | ||
| 2357 | void *net = entity_networkable(idx); | ||
| 2358 | const char *cls = net ? entity_class_name(net, nullptr) : nullptr; | ||
| 2359 | const char *model = entity_model_name(ent); | ||
| 2360 | int wt = weapon_type_id(model, cls); | ||
| 2361 | if (wt > 0) | ||
| 2362 | owned_weapon[wt] = true; | ||
| 2363 | } | ||
| 2294 | static bool cats_logged = false; | 2364 | static bool cats_logged = false; |
| 2295 | if (!cats_logged) { | 2365 | if (!cats_logged) { |
| 2296 | cats_logged = true; | 2366 | cats_logged = true; |
| @@ -2347,6 +2417,13 @@ static void items_collect(int local_idx) { | |||
| 2347 | if (kind == IK_WEAPON) { | 2417 | if (kind == IK_WEAPON) { |
| 2348 | if (idx == active_idx || item_weapon_is_owned(ent)) | 2418 | if (idx == active_idx || item_weapon_is_owned(ent)) |
| 2349 | continue; | 2419 | continue; |
| 2420 | int wt = weapon_type_id(model, cls); | ||
| 2421 | if (wt > 0 && owned_weapon[wt]) { | ||
| 2422 | char base_label[160]; | ||
| 2423 | snprintf(base_label, sizeof(base_label), "%s", label); | ||
| 2424 | snprintf(label, sizeof(label), "%.100s ammo", base_label); | ||
| 2425 | kind = IK_AMMO; | ||
| 2426 | } | ||
| 2350 | } | 2427 | } |
| 2351 | // Distance applies to every tag; 0 means unlimited. | 2428 | // Distance applies to every tag; 0 means unlimited. |
| 2352 | if (g_item_max_dist > 0 && dist > (float)g_item_max_dist) | 2429 | if (g_item_max_dist > 0 && dist > (float)g_item_max_dist) |
| @@ -2511,6 +2588,23 @@ static const char *proj_name(int kind) { | |||
| 2511 | } | 2588 | } |
| 2512 | } | 2589 | } |
| 2513 | 2590 | ||
| 2591 | // Fallback fuse clock when the server detonate time cannot be read. The stock | ||
| 2592 | // frag fuse is 3 s from the first sighting. | ||
| 2593 | static double proj_first_seen(int idx, double now) { | ||
| 2594 | static int idxs[32]; | ||
| 2595 | static double first[32]; | ||
| 2596 | static int n = 0; | ||
| 2597 | for (int i = 0; i < n; i++) | ||
| 2598 | if (idxs[i] == idx) | ||
| 2599 | return first[i]; | ||
| 2600 | if (n < 32) { | ||
| 2601 | idxs[n] = idx; | ||
| 2602 | first[n] = now; | ||
| 2603 | n++; | ||
| 2604 | } | ||
| 2605 | return now; | ||
| 2606 | } | ||
| 2607 | |||
| 2514 | static void projs_collect(int local_idx) { | 2608 | static void projs_collect(int local_idx) { |
| 2515 | static double last_scan = 0.0; | 2609 | static double last_scan = 0.0; |
| 2516 | double now = esp_now(); | 2610 | double now = esp_now(); |
| @@ -2578,19 +2672,24 @@ static void projs_collect(int local_idx) { | |||
| 2578 | p.radius = kind == PK_RPG ? 200.0f : kind == PK_BALL ? 150.0f : 300.0f; | 2672 | p.radius = kind == PK_RPG ? 200.0f : kind == PK_BALL ? 150.0f : 300.0f; |
| 2579 | // m_flDetonateTime is server-only (not in the send table). | 2673 | // m_flDetonateTime is server-only (not in the send table). |
| 2580 | p.fuse = -1.0f; | 2674 | p.fuse = -1.0f; |
| 2675 | float det = -1.0f; | ||
| 2581 | if (kind != PK_RPG) { | 2676 | if (kind != PK_RPG) { |
| 2582 | float det = server_grenade_detonate(idx); | 2677 | det = server_grenade_detonate(idx); |
| 2583 | if (det > 0.0f && curtime > 0.0f) | 2678 | if (det > 0.0f && curtime > 0.0f) |
| 2584 | p.fuse = det - curtime; | 2679 | p.fuse = det - curtime; |
| 2585 | if (!(p.fuse > -2.0f && p.fuse < 30.0f)) | 2680 | if (!(p.fuse > -2.0f && p.fuse < 30.0f)) { |
| 2586 | p.fuse = -1.0f; | 2681 | p.fuse = 3.0f - (float)(now - proj_first_seen(idx, now)); |
| 2682 | if (!(p.fuse > -2.0f && p.fuse < 30.0f)) | ||
| 2683 | p.fuse = -1.0f; | ||
| 2684 | } | ||
| 2587 | } | 2685 | } |
| 2588 | static int logs = 0; | 2686 | static int logs = 0; |
| 2589 | if (logs < 8) { | 2687 | if (logs < 8) { |
| 2590 | logs++; | 2688 | logs++; |
| 2591 | logf("projectile: idx=%d cls=%s model=%s kind=%s fuse=%.2f " | 2689 | logf("projectile: idx=%d cls=%s model=%s kind=%s det=%.2f cur=%.2f " |
| 2592 | "radius=%.0f", | 2690 | "fuse=%.2f radius=%.0f", |
| 2593 | idx, cls ? cls : "?", model, proj_name(kind), p.fuse, p.radius); | 2691 | idx, cls ? cls : "?", model, proj_name(kind), det, curtime, p.fuse, |
| 2692 | p.radius); | ||
| 2594 | } | 2693 | } |
| 2595 | } | 2694 | } |
| 2596 | } | 2695 | } |
diff --git a/src/server.cpp b/src/server.cpp index 40aa850..1313f00 100644 --- a/src/server.cpp +++ b/src/server.cpp | |||
| @@ -455,7 +455,14 @@ float server_grenade_detonate(int idx) { | |||
| 455 | server_entity_health(idx, nullptr, nullptr, &base); | 455 | server_entity_health(idx, nullptr, nullptr, &base); |
| 456 | if (!base) | 456 | if (!base) |
| 457 | return -1.0f; | 457 | return -1.0f; |
| 458 | return *(float *)((uintptr_t)base + g_srv_detonate); | 458 | float v = *(float *)((uintptr_t)base + g_srv_detonate); |
| 459 | static int logs = 0; | ||
| 460 | if (logs < 8) { | ||
| 461 | logs++; | ||
| 462 | logf("grenade fuse: idx=%d base=%p off=%d value=%.2f", idx, base, | ||
| 463 | g_srv_detonate, v); | ||
| 464 | } | ||
| 465 | return v; | ||
| 459 | } | 466 | } |
| 460 | 467 | ||
| 461 | float server_grenade_radius(int idx) { | 468 | float server_grenade_radius(int idx) { |
