diff options
Diffstat (limited to '')
| -rw-r--r-- | CONTEXT.md | 24 | ||||
| -rw-r--r-- | src/esp.cpp | 318 | ||||
| -rw-r--r-- | src/gui.cpp | 32 | ||||
| -rw-r--r-- | src/hl2h.cpp | 93 | ||||
| -rw-r--r-- | src/hl2h.h | 24 | ||||
| -rw-r--r-- | src/menu.cpp | 84 | ||||
| -rw-r--r-- | src/netvars.cpp | 5 |
7 files changed, 339 insertions, 241 deletions
| @@ -268,22 +268,20 @@ vocabulary / decisions. | |||
| 268 | - Aimbot vischeck (`MASK_VISIBLE`/world-only) differs from triggerbot | 268 | - Aimbot vischeck (`MASK_VISIBLE`/world-only) differs from triggerbot |
| 269 | (`MASK_SHOT`/all entities): glass and static props can behave differently. | 269 | (`MASK_SHOT`/all entities): glass and static props can behave differently. |
| 270 | 270 | ||
| 271 | ## Stucklaunch assist | 271 | ## Valuable items |
| 272 | 272 | ||
| 273 | - Optional Movement feature; Active is off by default. | 273 | - Visuals feature; Active is on by default and unbound (always-on). |
| 274 | - While engaged it holds jump, alternates +use (or +attack/+use as a | 274 | - Scans the client entity list every 100 ms for item models/classes and tags |
| 275 | pickup/drop cycle while the gravity gun is active) every N ticks (default | 275 | health, ammo, armor/suit, supply crates and generic items. |
| 276 | 2), and air-strafes the hops. | 276 | - Each tag is a colored marker with a name and optional distance, filtered by |
| 277 | - Engagement comes from `m_hGroundEntity`, latched for ~0.5 s so the prop | 277 | category toggles and a max-distance slider. Drawn through walls and |
| 278 | stays "active" during each hop. If that netvar is unavailable it runs | 278 | independently of the hostile NPC ESP. |
| 279 | whenever the feature is active, so bind it to a key. | 279 | - Detection is model-first (`models/items/...`, `models/healthvial.mdl`, |
| 280 | - It does not spawn or move props. The player still supplies the prop and the | 280 | `models/props_combine/*_charger*.mdl`, `models/w_longjump.mdl`) with class |
| 281 | small initial speed. Pallets and brush physboxes work best. | 281 | fallbacks. Weapon pickups are intentionally not tagged. |
| 282 | 282 | ||
| 283 | ## Roadmap / TODO | 283 | ## Roadmap / TODO |
| 284 | 284 | ||
| 285 | - **Stucklaunch tuning**: use-spam period, prop class coverage, and a possible | ||
| 286 | pause/unpause variant still need in-game testing. | ||
| 287 | - **Server-side spread/recoil control**: not planned; recoil and accuracy | 285 | - **Server-side spread/recoil control**: not planned; recoil and accuracy |
| 288 | penalties are intentionally left stock. | 286 | penalties are intentionally left stock. |
| 289 | - **Distance weapon spread thesis**: addressed by Spread control; stock HL2 | 287 | - **Distance weapon spread thesis**: addressed by Spread control; stock HL2 |
diff --git a/src/esp.cpp b/src/esp.cpp index ca7bae0..d10a2cf 100644 --- a/src/esp.cpp +++ b/src/esp.cpp | |||
| @@ -1132,71 +1132,6 @@ static void spread_compute() { | |||
| 1132 | g_spread_ready = true; | 1132 | g_spread_ready = true; |
| 1133 | } | 1133 | } |
| 1134 | 1134 | ||
| 1135 | static bool icontains(const char *hay, const char *needle) { | ||
| 1136 | if (!hay || !needle || !*needle) | ||
| 1137 | return false; | ||
| 1138 | size_t n = strlen(needle); | ||
| 1139 | for (const char *p = hay; *p; p++) | ||
| 1140 | if (strncasecmp(p, needle, n) == 0) | ||
| 1141 | return true; | ||
| 1142 | return false; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | bool entity_is_physics_prop(int idx) { | ||
| 1146 | if (idx <= 0 || idx > 4096) | ||
| 1147 | return false; | ||
| 1148 | void *ent = entitylist_get(idx); | ||
| 1149 | if (!ent) | ||
| 1150 | return false; | ||
| 1151 | int mt = -1; | ||
| 1152 | // The reliable signal: physics objects use MOVETYPE_VPHYSICS. The client | ||
| 1153 | // class is CPhysicsProp / CPhysBox, not the server's prop_physics name. | ||
| 1154 | if (g_net.movetype >= 0) { | ||
| 1155 | mt = *(int *)((uintptr_t)ent + g_net.movetype); | ||
| 1156 | if (mt == MOVETYPE_VPHYSICS) | ||
| 1157 | return true; | ||
| 1158 | } | ||
| 1159 | void *net = entity_networkable(idx); | ||
| 1160 | const char *cls = net ? entity_class_name(net, nullptr) : nullptr; | ||
| 1161 | const char *model = entity_model_name(ent); | ||
| 1162 | bool is_prop = icontains(cls, "physicsprop") || icontains(cls, "physbox") || | ||
| 1163 | icontains(cls, "prop_physics") || | ||
| 1164 | icontains(model, "props_junk") || | ||
| 1165 | icontains(model, "props_physics") || | ||
| 1166 | icontains(model, "props_c17") || | ||
| 1167 | icontains(model, "props_interiors") || | ||
| 1168 | icontains(model, "props_lab"); | ||
| 1169 | if (!is_prop) { | ||
| 1170 | static int miss_logs = 0; | ||
| 1171 | if (miss_logs < 6) { | ||
| 1172 | miss_logs++; | ||
| 1173 | logf("stucklaunch prop? idx=%d movetype=%d cls=%s model=%s", idx, mt, | ||
| 1174 | cls ? cls : "?", model ? model : "?"); | ||
| 1175 | } | ||
| 1176 | } | ||
| 1177 | return is_prop; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | bool active_weapon_is_gravity_gun(void *local_ent) { | ||
| 1181 | if (!local_ent || g_net.activeweapon < 0) | ||
| 1182 | return false; | ||
| 1183 | uint32_t h = *(uint32_t *)((uintptr_t)local_ent + g_net.activeweapon); | ||
| 1184 | if (h == 0xFFFFFFFFu) | ||
| 1185 | return false; | ||
| 1186 | int idx = (int)(h & 0xFFFF); | ||
| 1187 | if (idx <= 0 || idx > 4096) | ||
| 1188 | return false; | ||
| 1189 | void *wep = entitylist_get(idx); | ||
| 1190 | void *net = entity_networkable(idx); | ||
| 1191 | const char *cls = net ? entity_class_name(net, nullptr) : nullptr; | ||
| 1192 | const char *model = wep ? entity_model_name(wep) : nullptr; | ||
| 1193 | if (cls && strstr(cls, "physcannon")) | ||
| 1194 | return true; | ||
| 1195 | if (model && (strstr(model, "physcannon") || strstr(model, "w_physics"))) | ||
| 1196 | return true; | ||
| 1197 | return false; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | static bool active_weapon_is_shotgun(void *local_ent) { | 1135 | static bool active_weapon_is_shotgun(void *local_ent) { |
| 1201 | if (!local_ent || g_net.activeweapon < 0) | 1136 | if (!local_ent || g_net.activeweapon < 0) |
| 1202 | return false; | 1137 | return false; |
| @@ -1402,3 +1337,256 @@ void esp_draw() { | |||
| 1402 | 1337 | ||
| 1403 | draw_speed_graph(); | 1338 | draw_speed_graph(); |
| 1404 | } | 1339 | } |
| 1340 | |||
| 1341 | |||
| 1342 | // --------------------------------------------------------------------------- | ||
| 1343 | // Valuable item tags | ||
| 1344 | // --------------------------------------------------------------------------- | ||
| 1345 | |||
| 1346 | enum ItemKind { IK_HEALTH, IK_AMMO, IK_ARMOR, IK_CRATE, IK_OTHER }; | ||
| 1347 | |||
| 1348 | struct ItemTarget { | ||
| 1349 | int idx; | ||
| 1350 | int kind; | ||
| 1351 | Vector origin; | ||
| 1352 | char label[48]; | ||
| 1353 | }; | ||
| 1354 | |||
| 1355 | static ItemTarget g_item_targets[192]; | ||
| 1356 | static int g_nitems = 0; | ||
| 1357 | static bool g_items_logged = false; | ||
| 1358 | |||
| 1359 | static bool item_icontains(const char *hay, const char *needle) { | ||
| 1360 | if (!hay || !needle || !*needle) | ||
| 1361 | return false; | ||
| 1362 | size_t n = strlen(needle); | ||
| 1363 | for (const char *p = hay; *p; p++) | ||
| 1364 | if (strncasecmp(p, needle, n) == 0) | ||
| 1365 | return true; | ||
| 1366 | return false; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | static int classify_item(const char *model, const char *cls, char *label, | ||
| 1370 | size_t outn) { | ||
| 1371 | if (!model && !cls) | ||
| 1372 | return -1; | ||
| 1373 | |||
| 1374 | if (item_icontains(model, "healthkit")) { | ||
| 1375 | snprintf(label, outn, "Medkit"); | ||
| 1376 | return IK_HEALTH; | ||
| 1377 | } | ||
| 1378 | if (item_icontains(model, "healthvial")) { | ||
| 1379 | snprintf(label, outn, "Health vial"); | ||
| 1380 | return IK_HEALTH; | ||
| 1381 | } | ||
| 1382 | if (item_icontains(model, "health_charger")) { | ||
| 1383 | snprintf(label, outn, "Health charger"); | ||
| 1384 | return IK_HEALTH; | ||
| 1385 | } | ||
| 1386 | if (item_icontains(model, "battery")) { | ||
| 1387 | snprintf(label, outn, "Battery"); | ||
| 1388 | return IK_ARMOR; | ||
| 1389 | } | ||
| 1390 | if (item_icontains(model, "hevsuit")) { | ||
| 1391 | snprintf(label, outn, "HEV suit"); | ||
| 1392 | return IK_ARMOR; | ||
| 1393 | } | ||
| 1394 | if (item_icontains(model, "w_longjump")) { | ||
| 1395 | snprintf(label, outn, "Long jump"); | ||
| 1396 | return IK_ARMOR; | ||
| 1397 | } | ||
| 1398 | if (item_icontains(model, "suit_charger")) { | ||
| 1399 | snprintf(label, outn, "Suit charger"); | ||
| 1400 | return IK_ARMOR; | ||
| 1401 | } | ||
| 1402 | if (item_icontains(model, "item_item_crate") || | ||
| 1403 | item_icontains(model, "item_beacon_crate")) { | ||
| 1404 | snprintf(label, outn, "Supply crate"); | ||
| 1405 | return IK_CRATE; | ||
| 1406 | } | ||
| 1407 | if (item_icontains(model, "ammocrate")) { | ||
| 1408 | snprintf(label, outn, "Ammo crate"); | ||
| 1409 | return IK_AMMO; | ||
| 1410 | } | ||
| 1411 | if (item_icontains(model, "w_missile_closed")) { | ||
| 1412 | snprintf(label, outn, "RPG ammo"); | ||
| 1413 | return IK_AMMO; | ||
| 1414 | } | ||
| 1415 | if (item_icontains(model, "models/items/")) { | ||
| 1416 | if (item_icontains(model, "crossbowrounds")) | ||
| 1417 | snprintf(label, outn, "Crossbow bolts"); | ||
| 1418 | else if (item_icontains(model, "ar2_grenade")) | ||
| 1419 | snprintf(label, outn, "AR2 grenade"); | ||
| 1420 | else if (item_icontains(model, "357ammo")) | ||
| 1421 | snprintf(label, outn, "357 ammo"); | ||
| 1422 | else if (item_icontains(model, "boxbuckshot")) | ||
| 1423 | snprintf(label, outn, "Buckshot"); | ||
| 1424 | else if (item_icontains(model, "boxsniperrounds")) | ||
| 1425 | snprintf(label, outn, "Sniper ammo"); | ||
| 1426 | else | ||
| 1427 | snprintf(label, outn, "Ammo"); | ||
| 1428 | return IK_AMMO; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | if (item_icontains(cls, "healthkit") || item_icontains(cls, "healthvial") || | ||
| 1432 | item_icontains(cls, "wallhealth")) { | ||
| 1433 | snprintf(label, outn, "Health"); | ||
| 1434 | return IK_HEALTH; | ||
| 1435 | } | ||
| 1436 | if (item_icontains(cls, "battery") || item_icontains(cls, "itemsuit") || | ||
| 1437 | item_icontains(cls, "recharge")) { | ||
| 1438 | snprintf(label, outn, "Armor"); | ||
| 1439 | return IK_ARMOR; | ||
| 1440 | } | ||
| 1441 | if (item_icontains(cls, "itemcrate") || | ||
| 1442 | item_icontains(cls, "dynamicresupply")) { | ||
| 1443 | snprintf(label, outn, "Supply crate"); | ||
| 1444 | return IK_CRATE; | ||
| 1445 | } | ||
| 1446 | if (item_icontains(cls, "item_ammo") || item_icontains(cls, "itemammo")) { | ||
| 1447 | snprintf(label, outn, "Ammo"); | ||
| 1448 | return IK_AMMO; | ||
| 1449 | } | ||
| 1450 | if (item_icontains(cls, "item") || item_icontains(cls, "pickup")) { | ||
| 1451 | snprintf(label, outn, "Item"); | ||
| 1452 | return IK_OTHER; | ||
| 1453 | } | ||
| 1454 | return -1; | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | static bool item_kind_enabled(int kind) { | ||
| 1458 | switch (kind) { | ||
| 1459 | case IK_HEALTH: return g_item_health; | ||
| 1460 | case IK_AMMO: return g_item_ammo; | ||
| 1461 | case IK_ARMOR: return g_item_armor; | ||
| 1462 | case IK_CRATE: return g_item_crates; | ||
| 1463 | default: return true; | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | static void items_collect(int local_idx) { | ||
| 1468 | static double last_scan = 0.0; | ||
| 1469 | double now = esp_now(); | ||
| 1470 | if (now - last_scan < 0.10) | ||
| 1471 | return; | ||
| 1472 | last_scan = now; | ||
| 1473 | g_nitems = 0; | ||
| 1474 | if (!g_iface.entitylist || g_net.origin < 0 || g_net.modelindex < 0) | ||
| 1475 | return; | ||
| 1476 | |||
| 1477 | using Fn = int (*)(void *); | ||
| 1478 | int hi = vfunc<Fn>(g_iface.entitylist, 6)(g_iface.entitylist); | ||
| 1479 | if (hi < 0 || hi > 4096) | ||
| 1480 | hi = 4096; | ||
| 1481 | |||
| 1482 | static int dbg_lines = 0; | ||
| 1483 | for (int idx = 1; idx <= hi && g_nitems < 192; idx++) { | ||
| 1484 | if (idx == local_idx) | ||
| 1485 | continue; | ||
| 1486 | void *ent = entitylist_get(idx); | ||
| 1487 | if (!ent) | ||
| 1488 | continue; | ||
| 1489 | void *net = entity_networkable(idx); | ||
| 1490 | if (!net) | ||
| 1491 | continue; | ||
| 1492 | const char *cls = entity_class_name(net, nullptr); | ||
| 1493 | const char *model = entity_model_name(ent); | ||
| 1494 | char label[48]; | ||
| 1495 | int kind = classify_item(model, cls, label, sizeof(label)); | ||
| 1496 | if (kind < 0) | ||
| 1497 | continue; | ||
| 1498 | |||
| 1499 | Vector origin{*(float *)((uintptr_t)ent + g_net.origin), | ||
| 1500 | *(float *)((uintptr_t)ent + g_net.origin + 4), | ||
| 1501 | *(float *)((uintptr_t)ent + g_net.origin + 8)}; | ||
| 1502 | float dx = origin.x - g_cam_eye.x; | ||
| 1503 | float dy = origin.y - g_cam_eye.y; | ||
| 1504 | float dz = origin.z - g_cam_eye.z; | ||
| 1505 | float dist = sqrtf(dx * dx + dy * dy + dz * dz); | ||
| 1506 | if (g_item_max_dist > 0 && dist > (float)g_item_max_dist) | ||
| 1507 | continue; | ||
| 1508 | |||
| 1509 | ItemTarget &t = g_item_targets[g_nitems++]; | ||
| 1510 | t.idx = idx; | ||
| 1511 | t.kind = kind; | ||
| 1512 | t.origin = origin; | ||
| 1513 | snprintf(t.label, sizeof(t.label), "%s", label); | ||
| 1514 | if (dbg_lines < 8) { | ||
| 1515 | dbg_lines++; | ||
| 1516 | logf("item: idx=%d kind=%d cls=%s model=%s", idx, kind, | ||
| 1517 | cls ? cls : "?", model ? model : "?"); | ||
| 1518 | } | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | if (!g_items_logged) { | ||
| 1522 | g_items_logged = true; | ||
| 1523 | logf("items: tagging %d valuable entities", g_nitems); | ||
| 1524 | } | ||
| 1525 | } | ||
| 1526 | |||
| 1527 | void esp_draw_items() { | ||
| 1528 | if (!g_surface || !g_iface.entitylist || g_net.origin < 0) | ||
| 1529 | return; | ||
| 1530 | if (!g_item_health && !g_item_ammo && !g_item_armor && !g_item_crates) | ||
| 1531 | return; | ||
| 1532 | int local = engine_get_local_player(); | ||
| 1533 | if (local <= 0) | ||
| 1534 | return; | ||
| 1535 | if (!g_scr_w) { | ||
| 1536 | using Fn = void (*)(void *, int &, int &); | ||
| 1537 | vfunc<Fn>(g_surface, SURF_GetScreenSize)(g_surface, g_scr_w, g_scr_h); | ||
| 1538 | if (!g_scr_w) | ||
| 1539 | return; | ||
| 1540 | } | ||
| 1541 | items_collect(local); | ||
| 1542 | |||
| 1543 | for (int i = 0; i < g_nitems; i++) { | ||
| 1544 | const ItemTarget &t = g_item_targets[i]; | ||
| 1545 | if (!item_kind_enabled(t.kind)) | ||
| 1546 | continue; | ||
| 1547 | float sx, sy; | ||
| 1548 | if (!world_to_screen(t.origin, sx, sy)) | ||
| 1549 | continue; | ||
| 1550 | if (sx < -40 || sx > (float)g_scr_w + 40 || sy < -20 || | ||
| 1551 | sy > (float)g_scr_h + 20) | ||
| 1552 | continue; | ||
| 1553 | |||
| 1554 | int r = 230, g = 230, b = 230; | ||
| 1555 | switch (t.kind) { | ||
| 1556 | case IK_HEALTH: r = 90; g = 255; b = 130; break; | ||
| 1557 | case IK_AMMO: r = 255; g = 210; b = 80; break; | ||
| 1558 | case IK_ARMOR: r = 90; g = 180; b = 255; break; | ||
| 1559 | case IK_CRATE: r = 220; g = 150; b = 255; break; | ||
| 1560 | default: break; | ||
| 1561 | } | ||
| 1562 | int x = (int)sx, y = (int)sy; | ||
| 1563 | surf_color(r, g, b, 255); | ||
| 1564 | surf_rect(0, x - 4, y - 4, x + 4, y + 4); | ||
| 1565 | surf_line(x - 8, y, x - 5, y); | ||
| 1566 | surf_line(x + 5, y, x + 8, y); | ||
| 1567 | surf_line(x, y - 8, x, y - 5); | ||
| 1568 | surf_line(x, y + 5, x, y + 8); | ||
| 1569 | |||
| 1570 | float dx = t.origin.x - g_cam_eye.x; | ||
| 1571 | float dy = t.origin.y - g_cam_eye.y; | ||
| 1572 | float dz = t.origin.z - g_cam_eye.z; | ||
| 1573 | int dist = (int)sqrtf(dx * dx + dy * dy + dz * dz); | ||
| 1574 | char text[96]; | ||
| 1575 | if (g_item_distance) | ||
| 1576 | snprintf(text, sizeof(text), "%s %du", t.label, dist); | ||
| 1577 | else | ||
| 1578 | snprintf(text, sizeof(text), "%s", t.label); | ||
| 1579 | int tw = (int)strlen(text) * 9; | ||
| 1580 | int tx = x + 10; | ||
| 1581 | if (tx + tw > g_scr_w - 4) | ||
| 1582 | tx = x - 10 - tw; | ||
| 1583 | if (tx < 4) | ||
| 1584 | tx = 4; | ||
| 1585 | int ty = y - 7; | ||
| 1586 | if (ty < 0) | ||
| 1587 | ty = 0; | ||
| 1588 | if (ty + 16 > g_scr_h) | ||
| 1589 | ty = g_scr_h - 16; | ||
| 1590 | draw_text_col(tx, ty, text, r, g, b); | ||
| 1591 | } | ||
| 1592 | } | ||
diff --git a/src/gui.cpp b/src/gui.cpp index 156e496..eb9a964 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -299,21 +299,6 @@ static void build_cards() { | |||
| 299 | add_card(0, &g_abh, "ABH", "Accelerate on the jump tick by facing away " | 299 | add_card(0, &g_abh, "ABH", "Accelerate on the jump tick by facing away " |
| 300 | "from the velocity.", true); | 300 | "from the velocity.", true); |
| 301 | 301 | ||
| 302 | int sl = add_card(0, &g_stucklaunch, "Stucklaunch", | ||
| 303 | "Hop on a physics prop while spamming grab to build " | ||
| 304 | "speed in a small space.", | ||
| 305 | true); | ||
| 306 | add_toggle(sl, "Use spam", | ||
| 307 | "Rapidly press +use to keep regrabbing the prop.", | ||
| 308 | &g_stucklaunch_use_spam); | ||
| 309 | add_toggle(sl, "Gravity gun spam", | ||
| 310 | "Alternate +attack and +use while holding the gravity gun.", | ||
| 311 | &g_stucklaunch_gravspam); | ||
| 312 | add_toggle(sl, "Auto-strafe", "Air-strafe each hop.", | ||
| 313 | &g_stucklaunch_autostrafe); | ||
| 314 | add_slider(sl, "Spam rate", "Ticks between spam toggles; higher is slower.", | ||
| 315 | 1, 16, &g_stucklaunch_spam_ticks); | ||
| 316 | |||
| 317 | int jb = add_card(0, &g_jumpbug, "Jumpbug", | 302 | int jb = add_card(0, &g_jumpbug, "Jumpbug", |
| 318 | "Duck+jump when landing would hurt.", true); | 303 | "Duck+jump when landing would hurt.", true); |
| 319 | add_toggle(jb, "Assist timing", | 304 | add_toggle(jb, "Assist timing", |
| @@ -364,6 +349,23 @@ static void build_cards() { | |||
| 364 | for (int i = 0; i < ESP_OPT_COUNT; i++) | 349 | for (int i = 0; i < ESP_OPT_COUNT; i++) |
| 365 | add_toggle(esp, esp_names[i], esp_descs[i], &g_esp_opt[i]); | 350 | add_toggle(esp, esp_names[i], esp_descs[i], &g_esp_opt[i]); |
| 366 | 351 | ||
| 352 | int items = add_card(2, &g_item_esp, "Valuable items", | ||
| 353 | "Tag medkits, ammo, armor and supply crates.", true); | ||
| 354 | add_toggle(items, "Medkits / health", | ||
| 355 | "Tag health kits, health vials and health chargers.", | ||
| 356 | &g_item_health); | ||
| 357 | add_toggle(items, "Ammo", "Tag ammo boxes, crates and grenades.", | ||
| 358 | &g_item_ammo); | ||
| 359 | add_toggle(items, "Armor / suit", "Tag batteries, HEV suits and chargers.", | ||
| 360 | &g_item_armor); | ||
| 361 | add_toggle(items, "Supply crates", "Tag item and beacon crates.", | ||
| 362 | &g_item_crates); | ||
| 363 | add_toggle(items, "Show distance", "Append the distance in units.", | ||
| 364 | &g_item_distance); | ||
| 365 | add_slider(items, "Max distance", | ||
| 366 | "Items farther away than this are not tagged.", 250, 5000, | ||
| 367 | &g_item_max_dist); | ||
| 368 | |||
| 367 | int spread = add_card(3, &g_spread, "Spread control", | 369 | int spread = add_card(3, &g_spread, "Spread control", |
| 368 | "Choose a server shot seed that tightens the cone.", | 370 | "Choose a server shot seed that tightens the cone.", |
| 369 | true); | 371 | true); |
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index defdd27..c51d35e 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -169,75 +169,6 @@ static void apply_autostrafe(CUserCmd *cmd, const float *vel) { | |||
| 169 | cmd->sidemove = (dx * rx + dy * ry) * 450.0f; | 169 | cmd->sidemove = (dx * rx + dy * ry) * 450.0f; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | // True while the player stands on (or just left) a physics prop. m_hGroundEntity | ||
| 173 | // is latched briefly because it clears during each hop. | ||
| 174 | static bool stucklaunch_prop_ok(void *ent, int tick) { | ||
| 175 | if (g_net.groundentity < 0) { | ||
| 176 | static bool logged = false; | ||
| 177 | if (!logged) { | ||
| 178 | logged = true; | ||
| 179 | logf("stucklaunch: m_hGroundEntity unavailable; prop detection off"); | ||
| 180 | } | ||
| 181 | return true; // no netvar: the bind is the only safeguard | ||
| 182 | } | ||
| 183 | static int last_prop_tick = -100000; | ||
| 184 | uint32_t h = *(uint32_t *)((uintptr_t)ent + g_net.groundentity); | ||
| 185 | int gi = (h == 0xFFFFFFFFu) ? 0 : (int)(h & 0xFFFF); | ||
| 186 | bool on = gi > 0 && gi <= 4096 && entity_is_physics_prop(gi); | ||
| 187 | if (on) { | ||
| 188 | static int prop_logs = 0; | ||
| 189 | if (prop_logs < 4) { | ||
| 190 | prop_logs++; | ||
| 191 | logf("stucklaunch: prop idx=%d engaged", gi); | ||
| 192 | } | ||
| 193 | last_prop_tick = tick; | ||
| 194 | } else { | ||
| 195 | static int miss_logs = 0; | ||
| 196 | if (miss_logs < 4) { | ||
| 197 | miss_logs++; | ||
| 198 | logf("stucklaunch: ground h=%#x idx=%d is not a physics prop", h, gi); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | return tick - last_prop_tick < 32; // ~0.5 s at 66 tick | ||
| 202 | } | ||
| 203 | |||
| 204 | // Stucklaunch assist. The player supplies the physics prop and a little | ||
| 205 | // initial speed; this holds jump, alternates +use (and optionally the gravity | ||
| 206 | // gun's +attack) to keep regrabbing the prop, and air-strafes the hops. | ||
| 207 | static void stucklaunch_apply(CUserCmd *cmd, void *local_ent, bool onground, | ||
| 208 | const float *vel) { | ||
| 209 | static bool engaged_logged = false; | ||
| 210 | if (!engaged_logged) { | ||
| 211 | engaged_logged = true; | ||
| 212 | logf("stucklaunch: applying jump/spam (onground=%d)", (int)onground); | ||
| 213 | } | ||
| 214 | cmd->buttons |= IN_JUMP; | ||
| 215 | int period = stucklaunch_spam_ticks(); | ||
| 216 | if (period < 1) | ||
| 217 | period = 1; | ||
| 218 | int phase = (cmd->tick_count / period) & 1; | ||
| 219 | bool gravity = stucklaunch_gravspam_enabled() && | ||
| 220 | active_weapon_is_gravity_gun(local_ent); | ||
| 221 | if (gravity) { | ||
| 222 | // Pick up with +attack, drop with +use on the next half-cycle. Pressing | ||
| 223 | // both together would punt instead of regrabbing. | ||
| 224 | if (phase == 0) { | ||
| 225 | cmd->buttons |= IN_ATTACK; | ||
| 226 | cmd->buttons &= ~IN_USE; | ||
| 227 | } else { | ||
| 228 | cmd->buttons |= IN_USE; | ||
| 229 | cmd->buttons &= ~IN_ATTACK; | ||
| 230 | } | ||
| 231 | } else if (stucklaunch_use_spam_enabled()) { | ||
| 232 | if (phase == 0) | ||
| 233 | cmd->buttons |= IN_USE; | ||
| 234 | else | ||
| 235 | cmd->buttons &= ~IN_USE; | ||
| 236 | } | ||
| 237 | if (stucklaunch_autostrafe_enabled() && !onground) | ||
| 238 | apply_autostrafe(cmd, vel); | ||
| 239 | } | ||
| 240 | |||
| 241 | // --------------------------------------------------------------------------- | 172 | // --------------------------------------------------------------------------- |
| 242 | // jumpbug | 173 | // jumpbug |
| 243 | // --------------------------------------------------------------------------- | 174 | // --------------------------------------------------------------------------- |
| @@ -645,23 +576,8 @@ static void do_move(int seq, float frametime) { | |||
| 645 | return; | 576 | return; |
| 646 | } | 577 | } |
| 647 | 578 | ||
| 648 | bool stuck_on = feature_active(FEAT_STUCKLAUNCH); | 579 | bool bhop_on = feature_active(FEAT_BHOP); |
| 649 | if (g_stucklaunch.active) { | 580 | bool abh_on = feature_active(FEAT_ABH); |
| 650 | static bool state_logged = false; | ||
| 651 | if (!state_logged) { | ||
| 652 | state_logged = true; | ||
| 653 | logf("stucklaunch: active=1 run=%d bind=%d groundoff=%d", | ||
| 654 | (int)stuck_on, g_stucklaunch.bind, g_net.groundentity); | ||
| 655 | } | ||
| 656 | } | ||
| 657 | bool stuck_engaged = stuck_on && stucklaunch_prop_ok(ent, cmd->tick_count); | ||
| 658 | if (stuck_engaged) { | ||
| 659 | stucklaunch_apply(cmd, ent, onground, vel); | ||
| 660 | note_modified(cmd, flags, vel); | ||
| 661 | } | ||
| 662 | |||
| 663 | bool bhop_on = !stuck_engaged && feature_active(FEAT_BHOP); | ||
| 664 | bool abh_on = !stuck_engaged && feature_active(FEAT_ABH); | ||
| 665 | 581 | ||
| 666 | static bool lastground = false; | 582 | static bool lastground = false; |
| 667 | 583 | ||
| @@ -712,8 +628,7 @@ static void do_move(int seq, float frametime) { | |||
| 712 | } | 628 | } |
| 713 | } | 629 | } |
| 714 | 630 | ||
| 715 | if (!stuck_engaged && | 631 | if (jumpbug_apply(cmd, localIdx, ent, flags, vel, frametime)) |
| 716 | jumpbug_apply(cmd, localIdx, ent, flags, vel, frametime)) | ||
| 717 | note_modified(cmd, flags, vel); | 632 | note_modified(cmd, flags, vel); |
| 718 | 633 | ||
| 719 | bool melee = feature_active(FEAT_MELEE) && melee_weapon_active(ent); | 634 | bool melee = feature_active(FEAT_MELEE) && melee_weapon_active(ent); |
| @@ -951,8 +866,6 @@ static void *setup_thread(void *) { | |||
| 951 | toastf(TOAST_ERROR, "Netvars incomplete; features may be disabled"); | 866 | toastf(TOAST_ERROR, "Netvars incomplete; features may be disabled"); |
| 952 | else if (g_net.absvelocity < 0) | 867 | else if (g_net.absvelocity < 0) |
| 953 | toastf(TOAST_WARN, "Jumpbug assist disabled: velocity netvar missing"); | 868 | toastf(TOAST_WARN, "Jumpbug assist disabled: velocity netvar missing"); |
| 954 | if (g_net.groundentity < 0) | ||
| 955 | toastf(TOAST_WARN, "Stucklaunch prop detection unavailable; bind it"); | ||
| 956 | if (!g_iface.engineserver) | 869 | if (!g_iface.engineserver) |
| 957 | toastf(TOAST_WARN, "Server interfaces missing; jumpbug/spread limited"); | 870 | toastf(TOAST_WARN, "Server interfaces missing; jumpbug/spread limited"); |
| 958 | if (!g_iface.debugoverlay) | 871 | if (!g_iface.debugoverlay) |
| @@ -92,7 +92,6 @@ struct NetVars { | |||
| 92 | int modelindex = -1; | 92 | int modelindex = -1; |
| 93 | int absvelocity = -1; // client C_BaseEntity::m_vecAbsVelocity (prediction) | 93 | int absvelocity = -1; // client C_BaseEntity::m_vecAbsVelocity (prediction) |
| 94 | int activeweapon = -1; // client m_hActiveWeapon handle | 94 | int activeweapon = -1; // client m_hActiveWeapon handle |
| 95 | int groundentity = -1; // client m_hGroundEntity handle | ||
| 96 | // ponytail: mins/maxs may be absent from some HL2 netvar tables; esp.cpp falls back to h=72 | 95 | // ponytail: mins/maxs may be absent from some HL2 netvar tables; esp.cpp falls back to h=72 |
| 97 | bool ok() const { return flags >= 0 && velocity >= 0 && movetype >= 0; } | 96 | bool ok() const { return flags >= 0 && velocity >= 0 && movetype >= 0; } |
| 98 | // ponytail: m_iMaxHealth isn't a netvar in HL2 SP; esp.cpp falls back to 100. | 97 | // ponytail: m_iMaxHealth isn't a netvar in HL2 SP; esp.cpp falls back to 100. |
| @@ -141,7 +140,7 @@ struct CUserCmd { | |||
| 141 | 140 | ||
| 142 | enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 }; | 141 | enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 }; |
| 143 | enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; | 142 | enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; |
| 144 | enum { MOVETYPE_WALK = 2, MOVETYPE_VPHYSICS = 6, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; | 143 | enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; |
| 145 | 144 | ||
| 146 | // --------------------------------------------------------------------------- | 145 | // --------------------------------------------------------------------------- |
| 147 | // vector math | 146 | // vector math |
| @@ -173,7 +172,7 @@ enum FeatureId { | |||
| 173 | FEAT_JUMPBUG = 6, | 172 | FEAT_JUMPBUG = 6, |
| 174 | FEAT_MELEE = 7, | 173 | FEAT_MELEE = 7, |
| 175 | FEAT_SPREAD = 8, | 174 | FEAT_SPREAD = 8, |
| 176 | FEAT_STUCKLAUNCH = 9, | 175 | FEAT_ITEM_ESP = 9, |
| 177 | FEAT_COUNT = 10 | 176 | FEAT_COUNT = 10 |
| 178 | }; | 177 | }; |
| 179 | enum EspOption { | 178 | enum EspOption { |
| @@ -206,14 +205,16 @@ struct FeatureState { | |||
| 206 | }; | 205 | }; |
| 207 | 206 | ||
| 208 | extern FeatureState g_bhop, g_abh, g_jumpbug, g_melee, g_spread, g_esp, | 207 | extern FeatureState g_bhop, g_abh, g_jumpbug, g_melee, g_spread, g_esp, |
| 209 | g_aimbot, g_triggerbot, g_silentaim, g_stucklaunch; | 208 | g_aimbot, g_triggerbot, g_silentaim, g_item_esp; |
| 210 | extern bool g_bhop_autostrafe; | 209 | extern bool g_bhop_autostrafe; |
| 211 | extern bool g_jumpbug_assist; | 210 | extern bool g_jumpbug_assist; |
| 212 | extern bool g_spread_no_spread; | 211 | extern bool g_spread_no_spread; |
| 213 | extern bool g_stucklaunch_use_spam; | 212 | extern bool g_item_health; |
| 214 | extern bool g_stucklaunch_gravspam; | 213 | extern bool g_item_ammo; |
| 215 | extern bool g_stucklaunch_autostrafe; | 214 | extern bool g_item_armor; |
| 216 | extern int g_stucklaunch_spam_ticks; | 215 | extern bool g_item_crates; |
| 216 | extern bool g_item_distance; | ||
| 217 | extern int g_item_max_dist; | ||
| 217 | extern bool g_aim_bones[AIM_BONE_COUNT]; | 218 | extern bool g_aim_bones[AIM_BONE_COUNT]; |
| 218 | extern int g_aim_smooth; | 219 | extern int g_aim_smooth; |
| 219 | extern bool g_aim_vischeck; | 220 | extern bool g_aim_vischeck; |
| @@ -252,12 +253,6 @@ bool esp_option(int opt); | |||
| 252 | bool bhop_autostrafe_enabled(); | 253 | bool bhop_autostrafe_enabled(); |
| 253 | bool jumpbug_assist_enabled(); | 254 | bool jumpbug_assist_enabled(); |
| 254 | bool spread_no_spread_enabled(); | 255 | bool spread_no_spread_enabled(); |
| 255 | bool stucklaunch_use_spam_enabled(); | ||
| 256 | bool stucklaunch_gravspam_enabled(); | ||
| 257 | bool stucklaunch_autostrafe_enabled(); | ||
| 258 | int stucklaunch_spam_ticks(); | ||
| 259 | bool active_weapon_is_gravity_gun(void *local_ent); | ||
| 260 | bool entity_is_physics_prop(int idx); | ||
| 261 | unsigned aimbot_bone_mask(); | 256 | unsigned aimbot_bone_mask(); |
| 262 | int aimbot_smooth_step(); | 257 | int aimbot_smooth_step(); |
| 263 | bool aimbot_vischeck_enabled(); | 258 | bool aimbot_vischeck_enabled(); |
| @@ -270,6 +265,7 @@ void *entitylist_get(int idx); | |||
| 270 | int engine_get_local_player(); | 265 | int engine_get_local_player(); |
| 271 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); | 266 | void draw_text_col(int x, int y, const char *s, int r, int g, int b); |
| 272 | void esp_draw(); | 267 | void esp_draw(); |
| 268 | void esp_draw_items(); | ||
| 273 | bool world_to_screen(const Vector &w, float &sx, float &sy); | 269 | bool world_to_screen(const Vector &w, float &sx, float &sy); |
| 274 | void set_silent_restore(const QAngle &angles); | 270 | void set_silent_restore(const QAngle &angles); |
| 275 | bool is_visible(const Vector &eye, const Vector &point); | 271 | bool is_visible(const Vector &eye, const Vector &point); |
diff --git a/src/menu.cpp b/src/menu.cpp index cc3890a..af8d10d 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -44,11 +44,13 @@ FeatureState g_esp{true, 0}; | |||
| 44 | FeatureState g_aimbot{true, 604}; // default Mouse5, rebindable in the GUI | 44 | FeatureState g_aimbot{true, 604}; // default Mouse5, rebindable in the GUI |
| 45 | FeatureState g_triggerbot{true, 603}; // default Mouse4 | 45 | FeatureState g_triggerbot{true, 603}; // default Mouse4 |
| 46 | FeatureState g_silentaim{true, 602}; // default Mouse3 | 46 | FeatureState g_silentaim{true, 602}; // default Mouse3 |
| 47 | FeatureState g_stucklaunch{false, 0}; // opt-in movement assist | 47 | FeatureState g_item_esp{true, 0}; // valuable item tags, always-on by default |
| 48 | bool g_stucklaunch_use_spam = true; | 48 | bool g_item_health = true; |
| 49 | bool g_stucklaunch_gravspam = false; | 49 | bool g_item_ammo = true; |
| 50 | bool g_stucklaunch_autostrafe = true; | 50 | bool g_item_armor = true; |
| 51 | int g_stucklaunch_spam_ticks = 2; | 51 | bool g_item_crates = true; |
| 52 | bool g_item_distance = true; | ||
| 53 | int g_item_max_dist = 2500; | ||
| 52 | 54 | ||
| 53 | // Aimbot bone checklist. Head defaults on (v1 behaviour). | 55 | // Aimbot bone checklist. Head defaults on (v1 behaviour). |
| 54 | bool g_aim_bones[AIM_BONE_COUNT] = {true, false, false, | 56 | bool g_aim_bones[AIM_BONE_COUNT] = {true, false, false, |
| @@ -163,11 +165,6 @@ void config_save() { | |||
| 163 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active, | 165 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\nautostrafe=%d\n", g_bhop.active, |
| 164 | g_bhop.bind, g_bhop_autostrafe); | 166 | g_bhop.bind, g_bhop_autostrafe); |
| 165 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); | 167 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); |
| 166 | fprintf(f, "[stucklaunch]\nactive=%d\nbind=%d\nuse_spam=%d\n" | ||
| 167 | "gravspam=%d\nautostrafe=%d\nspam_ticks=%d\n", | ||
| 168 | g_stucklaunch.active, g_stucklaunch.bind, | ||
| 169 | (int)g_stucklaunch_use_spam, (int)g_stucklaunch_gravspam, | ||
| 170 | (int)g_stucklaunch_autostrafe, g_stucklaunch_spam_ticks); | ||
| 171 | fprintf(f, "[jumpbug]\nactive=%d\nbind=%d\nassist=%d\n", | 168 | fprintf(f, "[jumpbug]\nactive=%d\nbind=%d\nassist=%d\n", |
| 172 | g_jumpbug.active, g_jumpbug.bind, (int)g_jumpbug_assist); | 169 | g_jumpbug.active, g_jumpbug.bind, (int)g_jumpbug_assist); |
| 173 | fprintf(f, "[melee]\nactive=%d\nbind=%d\n", g_melee.active, g_melee.bind); | 170 | fprintf(f, "[melee]\nactive=%d\nbind=%d\n", g_melee.active, g_melee.bind); |
| @@ -186,6 +183,11 @@ void config_save() { | |||
| 186 | g_triggerbot.bind); | 183 | g_triggerbot.bind); |
| 187 | fprintf(f, "[silentaim]\nactive=%d\nbind=%d\nfov=%d\n", g_silentaim.active, | 184 | fprintf(f, "[silentaim]\nactive=%d\nbind=%d\nfov=%d\n", g_silentaim.active, |
| 188 | g_silentaim.bind, g_silent_fov); | 185 | g_silentaim.bind, g_silent_fov); |
| 186 | fprintf(f, "[items]\nactive=%d\nbind=%d\nhealth=%d\nammo=%d\n" | ||
| 187 | "armor=%d\ncrates=%d\ndistance=%d\nmax_dist=%d\n", | ||
| 188 | g_item_esp.active, g_item_esp.bind, (int)g_item_health, | ||
| 189 | (int)g_item_ammo, (int)g_item_armor, (int)g_item_crates, | ||
| 190 | (int)g_item_distance, g_item_max_dist); | ||
| 189 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" | 191 | fprintf(f, "[esp]\nactive=%d\nbind=%d\nneutral=%d\nhealthbar=%d\n" |
| 190 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\nspeedgraph=%d\n", | 192 | "healthnum=%d\nname=%d\nskeleton=%d\nbox=%d\nspeedgraph=%d\n", |
| 191 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], | 193 | g_esp.active, g_esp.bind, g_esp_opt[ESP_OPT_SHOW_NEUTRAL], |
| @@ -214,7 +216,7 @@ static bool config_load() { | |||
| 214 | char line[256]; | 216 | char line[256]; |
| 215 | FeatureState *cur = nullptr; | 217 | FeatureState *cur = nullptr; |
| 216 | bool in_esp = false, in_bhop = false, in_aim = false, in_silent = false, | 218 | bool in_esp = false, in_bhop = false, in_aim = false, in_silent = false, |
| 217 | in_jumpbug = false, in_spread = false, in_stucklaunch = false; | 219 | in_jumpbug = false, in_spread = false, in_items = false; |
| 218 | while (fgets(line, sizeof(line), f)) { | 220 | while (fgets(line, sizeof(line), f)) { |
| 219 | line[strcspn(line, "\r\n")] = 0; | 221 | line[strcspn(line, "\r\n")] = 0; |
| 220 | if (line[0] == '[') { | 222 | if (line[0] == '[') { |
| @@ -222,8 +224,6 @@ static bool config_load() { | |||
| 222 | cur = &g_bhop; | 224 | cur = &g_bhop; |
| 223 | else if (strstr(line, "[abh]")) | 225 | else if (strstr(line, "[abh]")) |
| 224 | cur = &g_abh; | 226 | cur = &g_abh; |
| 225 | else if (strstr(line, "[stucklaunch]")) | ||
| 226 | cur = &g_stucklaunch; | ||
| 227 | else if (strstr(line, "[jumpbug]")) | 227 | else if (strstr(line, "[jumpbug]")) |
| 228 | cur = &g_jumpbug; | 228 | cur = &g_jumpbug; |
| 229 | else if (strstr(line, "[melee]")) | 229 | else if (strstr(line, "[melee]")) |
| @@ -232,6 +232,8 @@ static bool config_load() { | |||
| 232 | cur = &g_spread; | 232 | cur = &g_spread; |
| 233 | else if (strstr(line, "[esp]")) | 233 | else if (strstr(line, "[esp]")) |
| 234 | cur = &g_esp; | 234 | cur = &g_esp; |
| 235 | else if (strstr(line, "[items]")) | ||
| 236 | cur = &g_item_esp; | ||
| 235 | else if (strstr(line, "[aimbot]")) | 237 | else if (strstr(line, "[aimbot]")) |
| 236 | cur = &g_aimbot; | 238 | cur = &g_aimbot; |
| 237 | else if (strstr(line, "[triggerbot]")) | 239 | else if (strstr(line, "[triggerbot]")) |
| @@ -246,7 +248,7 @@ static bool config_load() { | |||
| 246 | in_silent = (cur == &g_silentaim); | 248 | in_silent = (cur == &g_silentaim); |
| 247 | in_jumpbug = (cur == &g_jumpbug); | 249 | in_jumpbug = (cur == &g_jumpbug); |
| 248 | in_spread = (cur == &g_spread); | 250 | in_spread = (cur == &g_spread); |
| 249 | in_stucklaunch = (cur == &g_stucklaunch); | 251 | in_items = (cur == &g_item_esp); |
| 250 | } else if (cur) { | 252 | } else if (cur) { |
| 251 | char *eq = strchr(line, '='); | 253 | char *eq = strchr(line, '='); |
| 252 | if (!eq) | 254 | if (!eq) |
| @@ -262,18 +264,22 @@ static bool config_load() { | |||
| 262 | if (in_spread && strcmp(key, "no_spread") == 0) { | 264 | if (in_spread && strcmp(key, "no_spread") == 0) { |
| 263 | g_spread_no_spread = atoi(val) != 0; | 265 | g_spread_no_spread = atoi(val) != 0; |
| 264 | } | 266 | } |
| 265 | if (in_stucklaunch) { | 267 | if (in_items) { |
| 266 | if (strcmp(key, "use_spam") == 0) | 268 | if (strcmp(key, "health") == 0) |
| 267 | g_stucklaunch_use_spam = atoi(val) != 0; | 269 | g_item_health = atoi(val) != 0; |
| 268 | else if (strcmp(key, "gravspam") == 0) | 270 | else if (strcmp(key, "ammo") == 0) |
| 269 | g_stucklaunch_gravspam = atoi(val) != 0; | 271 | g_item_ammo = atoi(val) != 0; |
| 270 | else if (strcmp(key, "autostrafe") == 0) | 272 | else if (strcmp(key, "armor") == 0) |
| 271 | g_stucklaunch_autostrafe = atoi(val) != 0; | 273 | g_item_armor = atoi(val) != 0; |
| 272 | else if (strcmp(key, "spam_ticks") == 0) { | 274 | else if (strcmp(key, "crates") == 0) |
| 275 | g_item_crates = atoi(val) != 0; | ||
| 276 | else if (strcmp(key, "distance") == 0) | ||
| 277 | g_item_distance = atoi(val) != 0; | ||
| 278 | else if (strcmp(key, "max_dist") == 0) { | ||
| 273 | int v = atoi(val); | 279 | int v = atoi(val); |
| 274 | if (v < 1) v = 1; | 280 | if (v < 250) v = 250; |
| 275 | if (v > 16) v = 16; | 281 | if (v > 5000) v = 5000; |
| 276 | g_stucklaunch_spam_ticks = v; | 282 | g_item_max_dist = v; |
| 277 | } | 283 | } |
| 278 | } | 284 | } |
| 279 | if (in_aim) { | 285 | if (in_aim) { |
| @@ -354,11 +360,6 @@ void config_reset_defaults() { | |||
| 354 | g_bhop = {true, 0}; | 360 | g_bhop = {true, 0}; |
| 355 | g_bhop_autostrafe = true; | 361 | g_bhop_autostrafe = true; |
| 356 | g_abh = {true, 0}; | 362 | g_abh = {true, 0}; |
| 357 | g_stucklaunch = {false, 0}; | ||
| 358 | g_stucklaunch_use_spam = true; | ||
| 359 | g_stucklaunch_gravspam = false; | ||
| 360 | g_stucklaunch_autostrafe = true; | ||
| 361 | g_stucklaunch_spam_ticks = 2; | ||
| 362 | g_jumpbug = {true, 0}; | 363 | g_jumpbug = {true, 0}; |
| 363 | g_jumpbug_assist = false; | 364 | g_jumpbug_assist = false; |
| 364 | g_melee = {true, 0}; | 365 | g_melee = {true, 0}; |
| @@ -367,6 +368,13 @@ void config_reset_defaults() { | |||
| 367 | g_esp = {true, 0}; | 368 | g_esp = {true, 0}; |
| 368 | for (int i = 0; i < ESP_OPT_COUNT; i++) | 369 | for (int i = 0; i < ESP_OPT_COUNT; i++) |
| 369 | g_esp_opt[i] = true; | 370 | g_esp_opt[i] = true; |
| 371 | g_item_esp = {true, 0}; | ||
| 372 | g_item_health = true; | ||
| 373 | g_item_ammo = true; | ||
| 374 | g_item_armor = true; | ||
| 375 | g_item_crates = true; | ||
| 376 | g_item_distance = true; | ||
| 377 | g_item_max_dist = 2500; | ||
| 370 | g_aimbot = {true, 604}; | 378 | g_aimbot = {true, 604}; |
| 371 | g_triggerbot = {true, 603}; | 379 | g_triggerbot = {true, 603}; |
| 372 | g_silentaim = {true, 602}; | 380 | g_silentaim = {true, 602}; |
| @@ -476,7 +484,7 @@ static bool key_held(int sc) { | |||
| 476 | static FeatureState *feature_state(int feature) { | 484 | static FeatureState *feature_state(int feature) { |
| 477 | static FeatureState *feats[FEAT_COUNT] = { | 485 | static FeatureState *feats[FEAT_COUNT] = { |
| 478 | &g_bhop, &g_abh, &g_esp, &g_aimbot, &g_triggerbot, | 486 | &g_bhop, &g_abh, &g_esp, &g_aimbot, &g_triggerbot, |
| 479 | &g_silentaim, &g_jumpbug, &g_melee, &g_spread, &g_stucklaunch}; | 487 | &g_silentaim, &g_jumpbug, &g_melee, &g_spread, &g_item_esp}; |
| 480 | if (feature < 0 || feature >= FEAT_COUNT) | 488 | if (feature < 0 || feature >= FEAT_COUNT) |
| 481 | return nullptr; | 489 | return nullptr; |
| 482 | return feats[feature]; | 490 | return feats[feature]; |
| @@ -509,14 +517,6 @@ bool jumpbug_assist_enabled() { return g_jumpbug_assist; } | |||
| 509 | 517 | ||
| 510 | bool spread_no_spread_enabled() { return g_spread_no_spread; } | 518 | bool spread_no_spread_enabled() { return g_spread_no_spread; } |
| 511 | 519 | ||
| 512 | bool stucklaunch_use_spam_enabled() { return g_stucklaunch_use_spam; } | ||
| 513 | |||
| 514 | bool stucklaunch_gravspam_enabled() { return g_stucklaunch_gravspam; } | ||
| 515 | |||
| 516 | bool stucklaunch_autostrafe_enabled() { return g_stucklaunch_autostrafe; } | ||
| 517 | |||
| 518 | int stucklaunch_spam_ticks() { return g_stucklaunch_spam_ticks; } | ||
| 519 | |||
| 520 | unsigned aimbot_bone_mask() { | 520 | unsigned aimbot_bone_mask() { |
| 521 | unsigned m = 0; | 521 | unsigned m = 0; |
| 522 | if (g_aim_bones[AIM_BONE_HEAD]) | 522 | if (g_aim_bones[AIM_BONE_HEAD]) |
| @@ -658,8 +658,10 @@ void outer_draw() { | |||
| 658 | // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open | 658 | // HL2H_DRAW_TEST=1 draws a probe rect without needing the GUI open |
| 659 | static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr; | 659 | static bool draw_test = getenv("HL2H_DRAW_TEST") != nullptr; |
| 660 | bool esp_on = feature_active(FEAT_ESP); | 660 | bool esp_on = feature_active(FEAT_ESP); |
| 661 | bool items_on = feature_active(FEAT_ITEM_ESP); | ||
| 661 | bool toasts = gui_toasts_active(); | 662 | bool toasts = gui_toasts_active(); |
| 662 | if (!g_surface || (!gui_is_open() && !draw_test && !esp_on && !toasts)) | 663 | if (!g_surface || |
| 664 | (!gui_is_open() && !draw_test && !esp_on && !items_on && !toasts)) | ||
| 663 | return; | 665 | return; |
| 664 | 666 | ||
| 665 | // Level/menu -> game transitions can invalidate the VGUI font handle. | 667 | // Level/menu -> game transitions can invalidate the VGUI font handle. |
| @@ -709,6 +711,8 @@ void outer_draw() { | |||
| 709 | surf_push_make_current(panel, false); | 711 | surf_push_make_current(panel, false); |
| 710 | if (esp_on && overlay_font) | 712 | if (esp_on && overlay_font) |
| 711 | esp_draw(); | 713 | esp_draw(); |
| 714 | if (items_on && overlay_font) | ||
| 715 | esp_draw_items(); | ||
| 712 | if (draw_test && overlay_font) { | 716 | if (draw_test && overlay_font) { |
| 713 | surf_draw_set_color(255, 0, 0, 255); | 717 | surf_draw_set_color(255, 0, 0, 255); |
| 714 | surf_draw_filled_rect(20, 20, 180, 60); | 718 | surf_draw_filled_rect(20, 20, 180, 60); |
diff --git a/src/netvars.cpp b/src/netvars.cpp index e304317..3b2d3b8 100644 --- a/src/netvars.cpp +++ b/src/netvars.cpp | |||
| @@ -92,9 +92,6 @@ static void collect_netvars(uintptr_t table, uintptr_t base_off, int depth) { | |||
| 92 | } else if (strcmp(pname2, "m_hActiveWeapon") == 0 && | 92 | } else if (strcmp(pname2, "m_hActiveWeapon") == 0 && |
| 93 | g_net.activeweapon < 0) { | 93 | g_net.activeweapon < 0) { |
| 94 | g_net.activeweapon = (int)(base_off + (uint32_t)poff); | 94 | g_net.activeweapon = (int)(base_off + (uint32_t)poff); |
| 95 | } else if (strcmp(pname2, "m_hGroundEntity") == 0 && | ||
| 96 | g_net.groundentity < 0) { | ||
| 97 | g_net.groundentity = (int)(base_off + (uint32_t)poff); | ||
| 98 | } else if (strcmp(pname2, "m_iTeamNum") == 0 && g_net.teamnum < 0) { | 95 | } else if (strcmp(pname2, "m_iTeamNum") == 0 && g_net.teamnum < 0) { |
| 99 | g_net.teamnum = (int)(base_off + (uint32_t)poff); | 96 | g_net.teamnum = (int)(base_off + (uint32_t)poff); |
| 100 | } else if (strcmp(pname2, "m_vecOrigin") == 0 && g_net.origin < 0) { | 97 | } else if (strcmp(pname2, "m_vecOrigin") == 0 && g_net.origin < 0) { |
| @@ -275,7 +272,7 @@ void resolve_netvars() { | |||
| 275 | logf("m_vecAbsVelocity unresolved; jumpbug assist disabled"); | 272 | logf("m_vecAbsVelocity unresolved; jumpbug assist disabled"); |
| 276 | logf("netvars: flags=%d velocity=%d movetype=%d health=%d maxhealth=%d " | 273 | logf("netvars: flags=%d velocity=%d movetype=%d health=%d maxhealth=%d " |
| 277 | "teamnum=%d origin=%d viewoffset=%d mins=%d maxs=%d lifeste=%d " | 274 | "teamnum=%d origin=%d viewoffset=%d mins=%d maxs=%d lifeste=%d " |
| 278 | "modelindex=%d absvelocity=%d activeweapon=%d groundentity=%d", | 275 | "modelindex=%d absvelocity=%d activeweapon=%d", |
| 279 | g_net.flags, g_net.velocity, g_net.movetype, g_net.health, | 276 | g_net.flags, g_net.velocity, g_net.movetype, g_net.health, |
| 280 | g_net.maxhealth, g_net.teamnum, g_net.origin, g_net.viewoffset, | 277 | g_net.maxhealth, g_net.teamnum, g_net.origin, g_net.viewoffset, |
| 281 | g_net.mins, g_net.maxs, g_net.lifestate, g_net.modelindex, | 278 | g_net.mins, g_net.maxs, g_net.lifestate, g_net.modelindex, |
