From 074e315c8550712dce0c7b530a90eee6aca29e63 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 23:26:53 +0100 Subject: Add grenade trajectory, RPG armour priority, empty chargers, mega gravity gun - Projectiles gets a "Grenade trajectory" toggle. While a frag grenade is held, simulate the weapon_frag throw (1200 u/s forward + 120 z, player velocity, gravity 600) and trace each step with a new trace_solid_segment(); reflect on impact, stop on a slow upward-normal hit, and draw the path, landing cross and a 300-unit blast ring. Verified on :99 (arcs, bounces off the tunnel wall, lands). - With the RPG equipped, armoured NPCs (striders, gunships, dropships, hunter-choppers) sort before normal enemies during target acquisition. Added helicopter/chopper to the ARMORED model list. - Empty health/suit chargers are hidden: read m_iJuice from the server datamap (0 = depleted, -1 = unreadable/fail open). - The citadel supercharged gravity gun (d3_citadel_03, d3_citadel_04, d3_breen_01 via IVEngineClient::GetLevelName) is treated as a normal weapon, so the melee aimbot no longer restricts it to VULNERABLE NPCs. --- src/server.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/server.cpp') diff --git a/src/server.cpp b/src/server.cpp index bae355e..6479b25 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -58,6 +58,7 @@ static int g_srv_mapname = -1; static int g_srv_armor = -1; static int g_srv_detonate = -1; static int g_srv_grenade_radius = -1; +static int g_srv_juice = -1; static int g_srv_ammo = -1; static int g_srv_myweapons = -1; static bool g_srv_ready = false; @@ -162,6 +163,7 @@ bool resolve_server_netvars() { // CBaseGrenade fuse / blast radius (m_flDetonateTime is not networked). g_srv_detonate = datamap_offset("m_flDetonateTime", FIELD_TIME); g_srv_grenade_radius = datamap_offset("m_DmgRadius", FIELD_FLOAT); + g_srv_juice = datamap_offset("m_iJuice", FIELD_INTEGER); // CBaseCombatCharacter arrays: ammo counts and the weapon handle list. g_srv_ammo = datamap_offset("m_iAmmo", FIELD_INTEGER, 0x40, 0x4000); g_srv_myweapons = datamap_offset("m_hMyWeapons", FIELD_EHANDLE); @@ -171,13 +173,13 @@ bool resolve_server_netvars() { "modelindex=%d absvel=%d vel=%d activeweapon=%d relationship=%d " "followtarget=%d spawnflags=%d hacked=%d npcstate=%d " "takedamage=%d mapname=%d armor=%d detonate=%d dmgradius=%d " - "ammo=%d myweapons=%d", + "ammo=%d myweapons=%d juice=%d", g_server.path.c_str(), g_srv_health, g_srv_maxhealth, g_srv_lifestate, g_srv_modelindex, g_srv_absvelocity, g_srv_velocity, g_srv_activeweapon, g_srv_relationship, g_srv_followtarget, g_srv_spawnflags, g_srv_hacked, g_srv_npcstate, g_srv_takedamage, g_srv_mapname, g_srv_armor, g_srv_detonate, g_srv_grenade_radius, - g_srv_ammo, g_srv_myweapons); + g_srv_ammo, g_srv_myweapons, g_srv_juice); fail_logged = false; } else if (!fail_logged) { fail_logged = true; @@ -475,6 +477,18 @@ float server_grenade_radius(int idx) { return *(float *)((uintptr_t)base + g_srv_grenade_radius); } +// CWallHealth / CNewRecharge share the same m_iJuice layout (the fields before +// it match), so one datamap offset works for both health and suit chargers. +int server_item_juice(int idx) { + if (!g_srv_ready || g_srv_juice < 0) + return -1; + void *base = nullptr; + server_entity_health(idx, nullptr, nullptr, &base); + if (!base) + return -1; + return *(int *)((uintptr_t)base + g_srv_juice); +} + // Server-side CBaseCombatCharacter::m_iAmmo array (reserve ammo). The datamap // offset points at the CNetworkArray length header; the elements start 4 bytes // later (confirmed by the shifted current/max table). -- cgit v1.2.3