From a224cc451233a487a3d931954b125f6e1736e710 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 23:46:58 +0100 Subject: Grenade trajectory: actual grenade state, full-length path, rounder rings - Prefer the local player's thrown frag over the pre-throw estimate: resolve CBaseGrenade::m_hThrower from the server datamap (client owner handles as fallback), then seed the prediction from the live origin/velocity. The real frag is a spinning VPhysics box with a random Y angular impulse, so bounce points remain approximate; the doc now says so. - Keep 512 path points sampled every other 20 ms step (up to 24 s) instead of 127 points / ~2.5 s, so the line reaches the landing instead of stopping in mid-air. - Radius rings use 36 segments; a segment whose near-plane-clipped endpoint the engine overlay refuses falls back to the local projection, and that projection now uses the configured camera FOV instead of a hardcoded 75 degrees (the wide-FOV ring no longer kinks/drops pieces). --- src/server.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/server.cpp') diff --git a/src/server.cpp b/src/server.cpp index f69ab30..cffc24f 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_thrower = -1; static int g_srv_juice_suit = -1; static int g_srv_juice_health = -1; static int g_srv_ammo = -1; @@ -181,6 +182,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_thrower = datamap_offset("m_hThrower", FIELD_EHANDLE); int juice_offs[8]; int njuice = datamap_offsets("m_iJuice", FIELD_INTEGER, 0x40, 0x4000, juice_offs, 8); @@ -510,8 +512,24 @@ 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. +// CBaseGrenade::m_hThrower, used to recognise the local player's own frag even +// when the client owner handles are unresolved. +int server_grenade_thrower(int idx) { + if (!g_srv_ready || g_srv_thrower < 0) + return -1; + void *base = nullptr; + server_entity_health(idx, nullptr, nullptr, &base); + if (!base) + return -1; + uint32_t h = *(uint32_t *)((uintptr_t)base + g_srv_thrower); + if (h == 0 || h == 0xFFFFFFFFu) + return -1; + return (int)(h & 0x7FF); +} + +// Health chargers (CWallHealth, CBaseToggle) and suit chargers +// (CNewRecharge, CBaseAnimating) have m_iJuice at different offsets; pick by +// the server class name. int server_item_juice(int idx) { if (!g_srv_ready) return -1; -- cgit v1.2.3