summaryrefslogtreecommitdiffstats
path: root/src/server.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-27 13:48:27 +0100
committersalmonik <salmonik@tuta.io>2026-10-27 13:48:27 +0100
commit471f022f449a18766fedb1ff0a4204a933b95b9c (patch)
tree499fcd29f1c9f7933aade3f8ffad88b3ef10f377 /src/server.cpp
parentscript: change the map for tests (diff)
downloadhl2h-471f022f449a18766fedb1ff0a4204a933b95b9c.tar.gz
hl2h-471f022f449a18766fedb1ff0a4204a933b95b9c.zip
Jumpbug: optional velocity-timed assist
The unduck window is only 2 units, while a 625-ups fall moves ~9.3 units per 66.7 Hz movement command, so pure jumpbug is ~20% reliable at that speed. - Add Jumpbug -> Assist timing (default off). When the natural next command would skip [36,38], pin the post-command ducked distance to 37 by writing the vertical velocity for that command. Pure jumpbug remains available with the option off. - Resolve the client local m_vecAbsVelocity (0x11C) via the client datamap and the server m_vecAbsVelocity (0x228) via the server datamap. - Write both the authoritative server velocity (what SetupMove reads through GetAbsVelocity) and the local prediction fields, so the next CreateMove sees the assisted origin on both sides. - Do not write the server m_vecVelocity directly: the datamap scan finds two same-named entries (0x1C and 0x29C); SetAbsVelocity syncs it after movement.
Diffstat (limited to 'src/server.cpp')
-rw-r--r--src/server.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/server.cpp b/src/server.cpp
index 6feb55b..3766906 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -31,6 +31,8 @@ int g_srv_health = -1;
31int g_srv_maxhealth = -1; 31int g_srv_maxhealth = -1;
32int g_srv_lifestate = -1; 32int g_srv_lifestate = -1;
33int g_srv_modelindex = -1; 33int g_srv_modelindex = -1;
34int g_srv_absvelocity = -1;
35int g_srv_velocity = -1;
34static bool g_srv_ready = false; 36static bool g_srv_ready = false;
35static bool g_srv_checked = false; 37static bool g_srv_checked = false;
36 38
@@ -105,12 +107,14 @@ bool resolve_server_netvars() {
105 g_srv_maxhealth = datamap_offset("m_iMaxHealth", FIELD_INTEGER); 107 g_srv_maxhealth = datamap_offset("m_iMaxHealth", FIELD_INTEGER);
106 g_srv_lifestate = datamap_offset("m_lifeState", FIELD_CHARACTER); 108 g_srv_lifestate = datamap_offset("m_lifeState", FIELD_CHARACTER);
107 g_srv_modelindex = datamap_offset("m_nModelIndex", 7); // FIELD_SHORT 109 g_srv_modelindex = datamap_offset("m_nModelIndex", 7); // FIELD_SHORT
110 g_srv_absvelocity = datamap_offset("m_vecAbsVelocity", 3); // FIELD_VECTOR
111 g_srv_velocity = datamap_offset("m_vecVelocity", 3); // FIELD_VECTOR
108 g_srv_ready = g_srv_health > 0; 112 g_srv_ready = g_srv_health > 0;
109 if (g_srv_ready) { 113 if (g_srv_ready) {
110 logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d " 114 logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d "
111 "modelindex=%d", 115 "modelindex=%d absvel=%d vel=%d",
112 g_server.path.c_str(), g_srv_health, g_srv_maxhealth, g_srv_lifestate, 116 g_server.path.c_str(), g_srv_health, g_srv_maxhealth, g_srv_lifestate,
113 g_srv_modelindex); 117 g_srv_modelindex, g_srv_absvelocity, g_srv_velocity);
114 fail_logged = false; 118 fail_logged = false;
115 } else if (!fail_logged) { 119 } else if (!fail_logged) {
116 fail_logged = true; 120 fail_logged = true;
@@ -175,3 +179,18 @@ int server_model_index(void *base) {
175 return -1; 179 return -1;
176 return (int)*(short *)((uintptr_t)base + g_srv_modelindex); 180 return (int)*(short *)((uintptr_t)base + g_srv_modelindex);
177} 181}
182
183// Set the authoritative vertical velocity of a server entity. m_vecAbsVelocity
184// is what CGameMovement::SetupMove reads through GetAbsVelocity(); writing the
185// networked m_vecVelocity directly is deliberately avoided because the server
186// datamap scan can find a same-named field on another class first. The movement
187// code syncs m_vecVelocity through SetAbsVelocity after the command.
188bool server_set_velocity_z(int idx, float vz) {
189 if (!g_srv_ready || !g_iface.engineserver || g_srv_absvelocity <= 0)
190 return false;
191 void *base = nullptr;
192 if (server_entity_health(idx, nullptr, nullptr, &base) < 0 || !base)
193 return false;
194 *(float *)((uintptr_t)base + g_srv_absvelocity + 8) = vz;
195 return true;
196}