diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-04 13:19:50 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-04 13:19:50 +0100 |
| commit | 6a7e0b3bae04a5a4667267b6a45baddeb66fc570 (patch) | |
| tree | 557c31924d468345a15886ac6e75209d00c49524 /src/server.cpp | |
| parent | Studio: drop the prop draw diagnostic (diff) | |
| download | hl2h-6a7e0b3bae04a5a4667267b6a45baddeb66fc570.tar.gz hl2h-6a7e0b3bae04a5a4667267b6a45baddeb66fc570.zip | |
Fix No spread on the hl2_complete server build
The server RandomSeed GOT slot was hardcoded to 0xce1348, measured on the
older bin/server.so. The anniversary branch loads hl2_complete/bin/server.so,
whose R_386_JMP_SLOT for RandomSeed is 0xce5348, so the patch hit unrelated
writable data and no spread silently did nothing.
- Read the relocation from the loaded module's ELF (module_jump_slot) instead
of hardcoding, with the two known offsets as fallback.
- Override whenever the RandomSeed caller's `this` is the local server player
(CBaseEntity::FireBullets) instead of matching a hardcoded return-address
range that also moved between builds.
- m_takedamage is a char (FIELD_CHARACTER) in the 2013 SDK; resolve it as such
and read a byte, so the IMMUNE damage tag actually works.
Diffstat (limited to '')
| -rw-r--r-- | src/server.cpp | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/src/server.cpp b/src/server.cpp index e9fd921..f71b441 100644 --- a/src/server.cpp +++ b/src/server.cpp | |||
| @@ -142,7 +142,11 @@ bool resolve_server_netvars() { | |||
| 142 | g_srv_spawnflags = datamap_offset("m_spawnflags", FIELD_INTEGER, 0x4); | 142 | g_srv_spawnflags = datamap_offset("m_spawnflags", FIELD_INTEGER, 0x4); |
| 143 | g_srv_hacked = datamap_offset("m_bHackedByAlyx", FIELD_BOOLEAN); | 143 | g_srv_hacked = datamap_offset("m_bHackedByAlyx", FIELD_BOOLEAN); |
| 144 | g_srv_npcstate = datamap_offset("m_NPCState", FIELD_INTEGER); | 144 | g_srv_npcstate = datamap_offset("m_NPCState", FIELD_INTEGER); |
| 145 | g_srv_takedamage = datamap_offset("m_takedamage", FIELD_INTEGER); | 145 | // CBaseEntity::m_takedamage is a char in the 2013 SDK |
| 146 | // (CNetworkVarForDerived(char, m_takedamage)); older builds used int. | ||
| 147 | g_srv_takedamage = datamap_offset("m_takedamage", FIELD_CHARACTER); | ||
| 148 | if (g_srv_takedamage < 0) | ||
| 149 | g_srv_takedamage = datamap_offset("m_takedamage", FIELD_INTEGER); | ||
| 146 | g_srv_ready = g_srv_health > 0; | 150 | g_srv_ready = g_srv_health > 0; |
| 147 | if (g_srv_ready) { | 151 | if (g_srv_ready) { |
| 148 | logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d " | 152 | logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d " |
| @@ -272,7 +276,8 @@ int server_npc_state(int idx) { | |||
| 272 | } | 276 | } |
| 273 | 277 | ||
| 274 | // TAKEDAMAGE: 0 = DAMAGE_NO, 1 = DAMAGE_EVENTS_ONLY, 2 = DAMAGE_YES, | 278 | // TAKEDAMAGE: 0 = DAMAGE_NO, 1 = DAMAGE_EVENTS_ONLY, 2 = DAMAGE_YES, |
| 275 | // 3 = DAMAGE_AIM. 0/1 cannot be damaged at all. | 279 | // 3 = DAMAGE_AIM. 0/1 cannot be damaged at all. The field is a char, so read |
| 280 | // a byte even if the older int layout was resolved. | ||
| 276 | int server_npc_takedamage(int idx) { | 281 | int server_npc_takedamage(int idx) { |
| 277 | if (!g_srv_ready || g_srv_takedamage < 0) | 282 | if (!g_srv_ready || g_srv_takedamage < 0) |
| 278 | return -1; | 283 | return -1; |
| @@ -280,7 +285,7 @@ int server_npc_takedamage(int idx) { | |||
| 280 | server_entity_health(idx, nullptr, nullptr, &base); | 285 | server_entity_health(idx, nullptr, nullptr, &base); |
| 281 | if (!base) | 286 | if (!base) |
| 282 | return -1; | 287 | return -1; |
| 283 | return *(int *)((uintptr_t)base + g_srv_takedamage); | 288 | return (int)*(unsigned char *)((uintptr_t)base + g_srv_takedamage); |
| 284 | } | 289 | } |
| 285 | 290 | ||
| 286 | bool server_npc_has_follow_target(int idx) { | 291 | bool server_npc_has_follow_target(int idx) { |
