summaryrefslogtreecommitdiffstats
path: root/src/netvars.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/netvars.cpp')
-rw-r--r--src/netvars.cpp67
1 files changed, 51 insertions, 16 deletions
diff --git a/src/netvars.cpp b/src/netvars.cpp
index 5c8c296..f702c41 100644
--- a/src/netvars.cpp
+++ b/src/netvars.cpp
@@ -27,7 +27,24 @@ static bool module_string(uintptr_t p, char *out, size_t outn) {
27 27
28static int g_dumped_tables = 0; 28static int g_dumped_tables = 0;
29 29
30static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) { 30// per-client-class health offset (m_iHealth lives at different offsets per
31// class chain: CBasePlayer via DT_BasePlayer=128, NPCs via DT_BaseCombatCharacter)
32static struct {
33 char name[32];
34 int off;
35} g_class_health[256];
36static int g_class_health_n = 0;
37
38int class_health_off(const char *name) {
39 for (int i = 0; i < g_class_health_n; i++)
40 if (strcmp(name, g_class_health[i].name) == 0)
41 return g_class_health[i].off;
42 return -1;
43}
44
45static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth,
46 int *out_health)
47{
31 if (depth > 8) 48 if (depth > 8)
32 return; 49 return;
33 uintptr_t props = *(uintptr_t *)(table + 0x00); 50 uintptr_t props = *(uintptr_t *)(table + 0x00);
@@ -67,13 +84,19 @@ static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) {
67 if (dump) 84 if (dump)
68 logf(" [%s] %s type=%d off=%d(0x%x) table=%s array=%s", tname, pname2, 85 logf(" [%s] %s type=%d off=%d(0x%x) table=%s array=%s", tname, pname2,
69 ptype, poff, poff, ptable ? "yes" : "no", parray ? "yes" : "no"); 86 ptype, poff, poff, ptable ? "yes" : "no", parray ? "yes" : "no");
70
71 if (ptable) { 87 if (ptable) {
72 collect_netvars(ptable, base_off + (uint32_t)poff, depth + 1); 88 collect_netvars(ptable, base_off + (uint32_t)poff, depth + 1,
89 out_health);
73 continue; 90 continue;
74 } 91 }
75 92
76 if (strcmp(pname2, "m_fFlags") == 0 && g_net.flags < 0) { 93 if (out_health && *out_health < 0 && strcmp(pname2, "m_iHealth") == 0)
94 *out_health = (int)(base_off + (uint32_t)poff);
95 if (strcmp(pname2, "m_lifeState") == 0 && g_net.lifestate < 0) {
96 g_net.lifestate = (int)(base_off + (uint32_t)poff);
97 } else if (strcmp(pname2, "m_nModelIndex") == 0 && g_net.modelindex < 0) {
98 g_net.modelindex = (int)(base_off + (uint32_t)poff);
99 } else if (strcmp(pname2, "m_fFlags") == 0 && g_net.flags < 0) {
77 g_net.flags = (int)(base_off + (uint32_t)poff); 100 g_net.flags = (int)(base_off + (uint32_t)poff);
78 } else if (strcmp(pname2, "m_vecVelocity") == 0 && g_net.velocity < 0) { 101 } else if (strcmp(pname2, "m_vecVelocity") == 0 && g_net.velocity < 0) {
79 if (parray && g_client.contains(parray)) { 102 if (parray && g_client.contains(parray)) {
@@ -95,7 +118,8 @@ static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) {
95 } else { 118 } else {
96 g_net.origin = (int)(base_off + (uint32_t)poff); 119 g_net.origin = (int)(base_off + (uint32_t)poff);
97 } 120 }
98 } else if (strcmp(pname2, "m_vecViewOffset") == 0 && g_net.viewoffset < 0) { 121 } else if (strncmp(pname2, "m_vecViewOffset", 15) == 0 &&
122 g_net.viewoffset < 0) {
99 if (parray && g_client.contains(parray)) { 123 if (parray && g_client.contains(parray)) {
100 int32_t eoff = *(int32_t *)(parray + 0x2C); 124 int32_t eoff = *(int32_t *)(parray + 0x2C);
101 g_net.viewoffset = (int)(base_off + (uint32_t)(eoff ? eoff : poff)); 125 g_net.viewoffset = (int)(base_off + (uint32_t)(eoff ? eoff : poff));
@@ -117,9 +141,7 @@ static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) {
117 g_net.maxs = (int)(base_off + (uint32_t)poff); 141 g_net.maxs = (int)(base_off + (uint32_t)poff);
118 } 142 }
119 } 143 }
120 if (g_net.esp_ok()) 144 }
121 return;
122}
123} 145}
124 146
125// prediction datamap scan for m_MoveType (FIELD_CHARACTER, fieldOffset in range) 147// prediction datamap scan for m_MoveType (FIELD_CHARACTER, fieldOffset in range)
@@ -195,21 +217,34 @@ void resolve_netvars() {
195 for (uintptr_t cc = head; cc && g_client.contains(cc) && classes < 1024; 217 for (uintptr_t cc = head; cc && g_client.contains(cc) && classes < 1024;
196 cc = *(uintptr_t *)(cc + 0x10)) { 218 cc = *(uintptr_t *)(cc + 0x10)) {
197 classes++; 219 classes++;
198 collect_netvars(*(uintptr_t *)(cc + 0x0C), 0, 0); 220 char cname[32];
199 if (g_net.esp_ok() || (g_net.flags >= 0 && g_net.velocity >= 0 && 221 int hoff = -1;
200 g_net.health < 0)) 222 // per-class health offset — NPCs send m_iHealth via their own table chain,
201 break; 223 // not DT_BasePlayer's; g_net.health keeps the player's for aimbot use
224 if (module_string(*(uintptr_t *)(cc + 0x08), cname, sizeof(cname))) {
225 collect_netvars(*(uintptr_t *)(cc + 0x0C), 0, 0, &hoff);
226 if (hoff >= 0 && g_class_health_n < 256) {
227 char *dst = g_class_health[g_class_health_n].name;
228 const char *src = cname;
229 size_t n = sizeof(g_class_health[g_class_health_n].name) - 1;
230 for (size_t i = 0; i < n && src[i]; i++) dst[i] = src[i];
231 dst[n] = 0;
232 g_class_health[g_class_health_n].off = hoff;
233 g_class_health_n++;
234 }
235 }
202 } 236 }
203 logf("client classes walked: %d", classes); 237 logf("client classes walked: %d, health-offset classes: %d", classes,
238 g_class_health_n);
204 239
205 if (g_net.movetype < 0 && !resolve_movetype()) { 240 if (g_net.movetype < 0 && !resolve_movetype()) {
206 // movetype unresolved — bhop still works, just no noclip/ladder guard 241 // movetype unresolved — bhop still works, just no noclip/ladder guard
207 logf("movetype guard disabled"); 242 logf("movetype guard disabled");
208 } 243 }
209
210 logf("netvars: flags=%d velocity=%d movetype=%d health=%d maxhealth=%d " 244 logf("netvars: flags=%d velocity=%d movetype=%d health=%d maxhealth=%d "
211 "teamnum=%d origin=%d viewoffset=%d mins=%d maxs=%d", 245 "teamnum=%d origin=%d viewoffset=%d mins=%d maxs=%d lifeste=%d "
246 "modelindex=%d",
212 g_net.flags, g_net.velocity, g_net.movetype, g_net.health, 247 g_net.flags, g_net.velocity, g_net.movetype, g_net.health,
213 g_net.maxhealth, g_net.teamnum, g_net.origin, g_net.viewoffset, 248 g_net.maxhealth, g_net.teamnum, g_net.origin, g_net.viewoffset,
214 g_net.mins, g_net.maxs); 249 g_net.mins, g_net.maxs, g_net.lifestate, g_net.modelindex);
215} 250}