diff options
Diffstat (limited to '')
| -rw-r--r-- | CONTEXT.md | 17 | ||||
| -rw-r--r-- | src/esp.cpp | 31 |
2 files changed, 37 insertions, 11 deletions
| @@ -692,11 +692,18 @@ vocabulary / decisions. | |||
| 692 | `CBaseCombatCharacter::m_hMyWeapons[48]` array (client `m_hMyWeapons` and the | 692 | `CBaseCombatCharacter::m_hMyWeapons[48]` array (client `m_hMyWeapons` and the |
| 693 | remembered active weapon are fallbacks). NPC-held weapons are ignored. | 693 | remembered active weapon are fallbacks). NPC-held weapons are ignored. |
| 694 | Weapons the player does not own stay under the Weapons category. | 694 | Weapons the player does not own stay under the Weapons category. |
| 695 | - Ammo pickups also honour "Only if usable": the reserve count from | 695 | - Ammo pickups also honour "Only if usable": the reserve count from the |
| 696 | `m_iAmmo[type]` (client array when resolved, otherwise the server | 696 | authoritative server `CBaseCombatCharacter::m_iAmmo` array is compared with |
| 697 | `CBaseCombatCharacter::m_iAmmo` array) is compared with the `sk_max_*` cvar | 697 | the `sk_max_*` cvar (stock caps as fallback, e.g. RPG rockets = 3); the |
| 698 | (stock caps as fallback, e.g. RPG rockets = 3). Full ammo hides the pickup; | 698 | client array is only a fallback. Full ammo hides the pickup; if either value |
| 699 | if either value cannot be read the item stays visible. | 699 | cannot be read the item stays visible. Preferring the server array fixed |
| 700 | "full" counts flickering as other ammo was spent — the client `m_iAmmo` | ||
| 701 | netvar offset can be off by an element. | ||
| 702 | - Frag grenade pickups were falling through to a generic "Ammo" label with | ||
| 703 | `ammo_type = -1`, so the usable filter never applied and they always showed. | ||
| 704 | `models/weapons/w_grenade`, `w_frag`, `items/grenade` and `frag_grenade` are | ||
| 705 | now labelled "Frag grenade" and mapped to `m_iAmmo[11]` (`sk_max_grenade`, | ||
| 706 | stock 5). AR2/SMG1 grenade variants map to `m_iAmmo[8]` (stock 3). | ||
| 700 | - The datamap offset for `m_iAmmo`/`m_hMyWeapons` points at the | 707 | - The datamap offset for `m_iAmmo`/`m_hMyWeapons` points at the |
| 701 | `CNetworkArray` length header; the actual elements start **4 bytes later**. | 708 | `CNetworkArray` length header; the actual elements start **4 bytes later**. |
| 702 | Reading at the raw offset shifted every count by one type (e.g. RPG read the | 709 | Reading at the raw offset shifted every count by one type (e.g. RPG read the |
diff --git a/src/esp.cpp b/src/esp.cpp index 3785107..7ddc86b 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -2419,10 +2419,15 @@ static int item_ammo_type(const char *model) { | |||
| 2419 | item_icontains(model, "w_rocket_launcher")) | 2419 | item_icontains(model, "w_rocket_launcher")) |
| 2420 | return 7; | 2420 | return 7; |
| 2421 | if (item_icontains(model, "ar2_grenade") || | 2421 | if (item_icontains(model, "ar2_grenade") || |
| 2422 | item_icontains(model, "ammocrate_smg2")) | 2422 | item_icontains(model, "ammocrate_smg2") || |
| 2423 | item_icontains(model, "smg1_grenade") || | ||
| 2424 | item_icontains(model, "smg_grenade")) | ||
| 2423 | return 8; | 2425 | return 8; |
| 2424 | if (item_icontains(model, "ammocrate_grenade") || | 2426 | if (item_icontains(model, "ammocrate_grenade") || |
| 2425 | item_icontains(model, "w_grenade") || item_icontains(model, "w_frag")) | 2427 | item_icontains(model, "w_grenade") || |
| 2428 | item_icontains(model, "w_frag") || | ||
| 2429 | item_icontains(model, "frag_grenade") || | ||
| 2430 | item_icontains(model, "items/grenade")) | ||
| 2426 | return 11; | 2431 | return 11; |
| 2427 | if (item_icontains(model, "w_smg1") || item_icontains(model, "w_smg2")) | 2432 | if (item_icontains(model, "w_smg1") || item_icontains(model, "w_smg2")) |
| 2428 | return 3; | 2433 | return 3; |
| @@ -2479,12 +2484,19 @@ static int ammo_max(int type) { | |||
| 2479 | static int local_ammo(void *local_ent, int type) { | 2484 | static int local_ammo(void *local_ent, int type) { |
| 2480 | if (type < 0 || type >= 32) | 2485 | if (type < 0 || type >= 32) |
| 2481 | return -1; | 2486 | return -1; |
| 2487 | // Prefer the authoritative server array; the client m_iAmmo netvar offset | ||
| 2488 | // can be off by an element, which made "full" counts flicker as other ammo | ||
| 2489 | // was spent. server_player_ammo already skips the CNetworkArray header. | ||
| 2490 | int local = engine_get_local_player(); | ||
| 2491 | if (local > 0 && g_iface.engineserver) { | ||
| 2492 | resolve_server_netvars(); | ||
| 2493 | int s = server_player_ammo(local, type); | ||
| 2494 | if (s >= 0) | ||
| 2495 | return s; | ||
| 2496 | } | ||
| 2482 | if (local_ent && g_net.ammo >= 0) | 2497 | if (local_ent && g_net.ammo >= 0) |
| 2483 | return *(int *)((uintptr_t)local_ent + g_net.ammo + type * 4); | 2498 | return *(int *)((uintptr_t)local_ent + g_net.ammo + type * 4); |
| 2484 | // Client array offset may not resolve; the listen-server player has the | 2499 | return -1; |
| 2485 | // same array in its datamap. | ||
| 2486 | int local = engine_get_local_player(); | ||
| 2487 | return local > 0 ? server_player_ammo(local, type) : -1; | ||
| 2488 | } | 2500 | } |
| 2489 | 2501 | ||
| 2490 | static int classify_item(const char *model, const char *cls, char *label, | 2502 | static int classify_item(const char *model, const char *cls, char *label, |
| @@ -2610,6 +2622,13 @@ static int classify_item(const char *model, const char *cls, char *label, | |||
| 2610 | snprintf(label, outn, "AR2 grenade"); | 2622 | snprintf(label, outn, "AR2 grenade"); |
| 2611 | return IK_AMMO; | 2623 | return IK_AMMO; |
| 2612 | } | 2624 | } |
| 2625 | if (item_icontains(model, "w_grenade") || | ||
| 2626 | item_icontains(model, "w_frag") || | ||
| 2627 | item_icontains(model, "frag_grenade") || | ||
| 2628 | item_icontains(model, "items/grenade")) { | ||
| 2629 | snprintf(label, outn, "Frag grenade"); | ||
| 2630 | return IK_AMMO; | ||
| 2631 | } | ||
| 2613 | if (item_icontains(model, "models/items/")) { | 2632 | if (item_icontains(model, "models/items/")) { |
| 2614 | snprintf(label, outn, "Ammo"); | 2633 | snprintf(label, outn, "Ammo"); |
| 2615 | return IK_AMMO; | 2634 | return IK_AMMO; |
