summaryrefslogtreecommitdiffstats
path: root/src/esp.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/esp.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/esp.cpp b/src/esp.cpp
index 34a702a..1cb8b70 100644
--- a/src/esp.cpp
+++ b/src/esp.cpp
@@ -316,6 +316,123 @@ static void draw_skeleton(const EspTarget &t) {
316 } 316 }
317} 317}
318 318
319// ---------------------------------------------------------------------------
320// aimbot v1: nearest hostile NPC head to the crosshair.
321// Bounded smoothing: never snap, never overshoot. Each tick moves at most
322// MAX_STEP degrees toward the target and stops inside DEADZONE.
323// ---------------------------------------------------------------------------
324
325static QAngle angle_to(const Vector &from, const Vector &to) {
326 float dx = to.x - from.x, dy = to.y - from.y, dz = to.z - from.z;
327 float horiz = sqrtf(dx * dx + dy * dy);
328 if (horiz < 0.001f)
329 horiz = 0.001f;
330 QAngle a{};
331 a.x = -atan2f(dz, horiz) * 180.0f / PI_F; // Source: positive pitch = down
332 a.y = atan2f(dy, dx) * 180.0f / PI_F;
333 a.z = 0.0f;
334 return a;
335}
336
337bool aimbot_apply(CUserCmd *cmd) {
338 if (!g_iface.entitylist || g_net.origin < 0 || g_net.maxs < 0)
339 return false;
340 int local = engine_get_local_player();
341 if (local <= 0)
342 return false;
343 void *local_ent = entitylist_get(local);
344 if (!local_ent)
345 return false;
346 if (g_net.health >= 0 &&
347 *(int *)((uintptr_t)local_ent + g_net.health) <= 0)
348 return false;
349
350 QAngle view{cmd->viewangles[0], cmd->viewangles[1], 0.0f};
351
352 using Fn = int (*)(void *);
353 int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist);
354 if (hi < 0 || hi > 4096)
355 hi = 4096;
356
357 constexpr float MAX_FOV = 60.0f; // only things near the crosshair
358 float best_fov = MAX_FOV;
359 int best_idx = -1;
360 Vector best_head{};
361
362 for (int idx = 1; idx <= hi; idx++) {
363 if (idx == local)
364 continue;
365 void *ent = entitylist_get(idx);
366 if (!ent)
367 continue;
368 void *net = entity_networkable(idx);
369 if (!net)
370 continue;
371 const char *cls = entity_class_name(net, nullptr);
372 if (!cls || !is_npc_class(cls))
373 continue;
374
375 uintptr_t e = (uintptr_t)ent;
376 int life = g_net.lifestate >= 0
377 ? (int)*(unsigned char *)(e + g_net.lifestate)
378 : -1;
379 if (life != LIFE_ALIVE)
380 continue;
381 const char *model = entity_model_name(ent);
382 if (model_is_friendly(model) || model_is_neutral(model))
383 continue;
384
385 float maxz = g_net.maxs >= 0 ? *(float *)(e + g_net.maxs + 8) : 72.0f;
386 if (!(maxz > 4.0f && maxz < 512.0f))
387 maxz = 72.0f;
388 Vector origin{*(float *)(e + g_net.origin),
389 *(float *)(e + g_net.origin + 4),
390 *(float *)(e + g_net.origin + 8)};
391 Vector approx{origin.x, origin.y, origin.z + maxz * 0.9f};
392 float fov = getfov(view, angle_to(g_cam_eye, approx));
393 if (fov >= best_fov)
394 continue;
395 best_fov = fov;
396 best_idx = idx;
397 best_head = approx;
398 }
399
400 if (best_idx < 0)
401 return false;
402
403 // Refine to the actual head hitbox/bone for the chosen target only.
404 void *best_ent = entitylist_get(best_idx);
405 if (best_ent && bones_update(best_idx, best_ent)) {
406 Vector head;
407 if (head_position(best_idx, head) &&
408 getfov(view, angle_to(g_cam_eye, head)) <= MAX_FOV)
409 best_head = head;
410 }
411
412 QAngle desired = angle_to(g_cam_eye, best_head);
413 float dp = desired.x - cmd->viewangles[0];
414 float dy = desired.y - cmd->viewangles[1];
415 while (dy > 180.0f) dy -= 360.0f;
416 while (dy < -180.0f) dy += 360.0f;
417
418 constexpr float DEADZONE = 0.05f;
419 constexpr float MAX_STEP = 5.0f;
420 float maxd = fmaxf(fabsf(dp), fabsf(dy));
421 if (maxd <= DEADZONE)
422 return false;
423
424 float scale = (maxd > MAX_STEP) ? (MAX_STEP / maxd) : 1.0f;
425 float np = cmd->viewangles[0] + dp * scale;
426 float ny = cmd->viewangles[1] + dy * scale;
427 if (np > 89.0f) np = 89.0f;
428 if (np < -89.0f) np = -89.0f;
429 while (ny > 180.0f) ny -= 360.0f;
430 while (ny < -180.0f) ny += 360.0f;
431 cmd->viewangles[0] = np;
432 cmd->viewangles[1] = ny;
433 return true;
434}
435
319void esp_draw() { 436void esp_draw() {
320 if (!g_surface || !g_iface.entitylist || !g_net.esp_ok()) return; 437 if (!g_surface || !g_iface.entitylist || !g_net.esp_ok()) return;
321 if (!g_scr_w) { 438 if (!g_scr_w) {