diff options
| author | salmonik <salmonik@tuta.io> | 2026-09-12 19:22:29 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-09-12 19:22:29 +0200 |
| commit | cc5e5ede87ae3b8c58221ce41b1a0b74fd173d1e (patch) | |
| tree | e8b063ec8fc825fc8cee15df76df1d3b3d7becec | |
| parent | ISurface overlay working: PTEx draw path, -Werror, menu states, bind-driven f... (diff) | |
| download | hl2h-cc5e5ede87ae3b8c58221ce41b1a0b74fd173d1e.tar.gz hl2h-cc5e5ede87ae3b8c58221ce41b1a0b74fd173d1e.zip | |
Remove Climb feature; keep bind system for aimbot prep (mouse buttons bindable)
Diffstat (limited to '')
| -rw-r--r-- | src/hl2h.cpp | 13 | ||||
| -rw-r--r-- | src/hl2h.h | 5 | ||||
| -rw-r--r-- | src/menu.cpp | 133 |
3 files changed, 49 insertions, 102 deletions
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index a4a1a88..c6c0aeb 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -152,21 +152,11 @@ static void do_move(int seq) { | |||
| 152 | bool onground = (flags & FL_ONGROUND) != 0; | 152 | bool onground = (flags & FL_ONGROUND) != 0; |
| 153 | bool inwater = (flags & FL_INWATER) != 0; | 153 | bool inwater = (flags & FL_INWATER) != 0; |
| 154 | 154 | ||
| 155 | bool climb_on = feature_active(FEAT_CLIMB); // bind held (or middle mouse when unbound) | ||
| 156 | bool bhop_on = feature_active(FEAT_BHOP); | 155 | bool bhop_on = feature_active(FEAT_BHOP); |
| 157 | 156 | ||
| 158 | static bool lastground = false; | 157 | static bool lastground = false; |
| 159 | 158 | ||
| 160 | if (climb_on) { | 159 | if (bhop_on && (cmd->buttons & IN_JUMP)) { |
| 161 | if (cmd->command_number % 2) { | ||
| 162 | cmd->buttons &= ~IN_JUMP; | ||
| 163 | cmd->buttons |= IN_USE; | ||
| 164 | } else { | ||
| 165 | cmd->buttons &= ~IN_USE; | ||
| 166 | cmd->buttons |= IN_JUMP; | ||
| 167 | } | ||
| 168 | note_modified(cmd, flags, (float *)(e + g_net.velocity)); | ||
| 169 | } else if (bhop_on && (cmd->buttons & IN_JUMP)) { | ||
| 170 | if (inwater && (cmd->buttons & IN_DUCK)) { | 160 | if (inwater && (cmd->buttons & IN_DUCK)) { |
| 171 | lastground = onground; | 161 | lastground = onground; |
| 172 | return; | 162 | return; |
| @@ -282,7 +272,6 @@ static void install_hook() { | |||
| 282 | extern void find_modules(); | 272 | extern void find_modules(); |
| 283 | extern void resolve_netvars(); | 273 | extern void resolve_netvars(); |
| 284 | extern bool find_input_global(); | 274 | extern bool find_input_global(); |
| 285 | extern void init_x11(); | ||
| 286 | extern void init_conmsg(); | 275 | extern void init_conmsg(); |
| 287 | extern void install_menu(); | 276 | extern void install_menu(); |
| 288 | 277 | ||
| @@ -125,7 +125,7 @@ float getfov(const QAngle &my_view, const QAngle &aim_ang); | |||
| 125 | // --------------------------------------------------------------------------- | 125 | // --------------------------------------------------------------------------- |
| 126 | 126 | ||
| 127 | // feature ids shared by menu (feature_active) and hl2h.cpp (do_move) | 127 | // feature ids shared by menu (feature_active) and hl2h.cpp (do_move) |
| 128 | enum FeatureId { FEAT_CLIMB = 0, FEAT_BHOP = 1, FEAT_ABH = 2 }; | 128 | enum FeatureId { FEAT_BHOP = 0, FEAT_ABH = 1 }; |
| 129 | void note_modified(const CUserCmd *cmd, int flags, const float *vel); | 129 | void note_modified(const CUserCmd *cmd, int flags, const float *vel); |
| 130 | CUserCmd *get_usercmd(int seq); | 130 | CUserCmd *get_usercmd(int seq); |
| 131 | void fix_verified_crc(int seq, uint32_t crc); | 131 | void fix_verified_crc(int seq, uint32_t crc); |
| @@ -133,10 +133,7 @@ uint32_t usercmd_checksum(const CUserCmd *c); | |||
| 133 | bool find_input_global(); | 133 | bool find_input_global(); |
| 134 | void resolve_netvars(); | 134 | void resolve_netvars(); |
| 135 | void find_modules(); | 135 | void find_modules(); |
| 136 | void install_menu(); | ||
| 137 | void init_conmsg(); | 136 | void init_conmsg(); |
| 138 | void init_x11(); | ||
| 139 | bool middle_mouse_down(); | ||
| 140 | bool feature_active(int feature); | 137 | bool feature_active(int feature); |
| 141 | void outer_draw(); | 138 | void outer_draw(); |
| 142 | // raw ISurface slot calls used by the PaintTraverseEx hook (hl2h.cpp) | 139 | // raw ISurface slot calls used by the PaintTraverseEx hook (hl2h.cpp) |
diff --git a/src/menu.cpp b/src/menu.cpp index c62db47..6dccf1c 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -26,55 +26,6 @@ void init_conmsg() { | |||
| 26 | if (h) | 26 | if (h) |
| 27 | g_conmsg = (decltype(g_conmsg))dlsym(h, "_Z6ConMsgPKcz"); | 27 | g_conmsg = (decltype(g_conmsg))dlsym(h, "_Z6ConMsgPKcz"); |
| 28 | } | 28 | } |
| 29 | |||
| 30 | // --------------------------------------------------------------------------- | ||
| 31 | // X11 middle mouse (for climb feature) | ||
| 32 | // --------------------------------------------------------------------------- | ||
| 33 | |||
| 34 | static struct { | ||
| 35 | void *handle = nullptr; | ||
| 36 | void *dpy = nullptr; | ||
| 37 | int (*query)(void *, unsigned long, unsigned long *, unsigned long *, int *, | ||
| 38 | int *, int *, int *, unsigned int *) = nullptr; | ||
| 39 | int (*default_screen)(void *) = nullptr; | ||
| 40 | unsigned long (*root_window)(void *, int) = nullptr; | ||
| 41 | bool ok = false; | ||
| 42 | } g_x11; | ||
| 43 | |||
| 44 | static constexpr unsigned int BUTTON2_MASK = 1u << 9; // X11 Button2Mask | ||
| 45 | |||
| 46 | void init_x11() { | ||
| 47 | g_x11.handle = dlopen("libX11.so.6", RTLD_LAZY | RTLD_GLOBAL); | ||
| 48 | if (!g_x11.handle) | ||
| 49 | return; | ||
| 50 | g_x11.query = (decltype(g_x11.query))dlsym(g_x11.handle, "XQueryPointer"); | ||
| 51 | g_x11.default_screen = | ||
| 52 | (decltype(g_x11.default_screen))dlsym(g_x11.handle, "XDefaultScreen"); | ||
| 53 | g_x11.root_window = | ||
| 54 | (decltype(g_x11.root_window))dlsym(g_x11.handle, "XRootWindow"); | ||
| 55 | auto open_display = | ||
| 56 | (void *(*)(const char *))dlsym(g_x11.handle, "XOpenDisplay"); | ||
| 57 | if (!g_x11.query || !g_x11.default_screen || !g_x11.root_window || | ||
| 58 | !open_display) | ||
| 59 | return; | ||
| 60 | g_x11.dpy = open_display(nullptr); | ||
| 61 | if (g_x11.dpy) | ||
| 62 | g_x11.ok = true; | ||
| 63 | } | ||
| 64 | |||
| 65 | bool middle_mouse_down() { | ||
| 66 | if (!g_x11.ok) | ||
| 67 | return false; | ||
| 68 | unsigned long root = | ||
| 69 | g_x11.root_window(g_x11.dpy, g_x11.default_screen(g_x11.dpy)); | ||
| 70 | unsigned long rret, cret; | ||
| 71 | int rx, ry, wx, wy; | ||
| 72 | unsigned int mask = 0; | ||
| 73 | if (!g_x11.query(g_x11.dpy, root, &rret, &cret, &rx, &ry, &wx, &wy, &mask)) | ||
| 74 | return false; | ||
| 75 | return (mask & BUTTON2_MASK) != 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | // --------------------------------------------------------------------------- | 29 | // --------------------------------------------------------------------------- |
| 79 | // menu tree structure | 30 | // menu tree structure |
| 80 | // --------------------------------------------------------------------------- | 31 | // --------------------------------------------------------------------------- |
| @@ -100,15 +51,11 @@ struct FeatureState { | |||
| 100 | int bind; // SDL scancode, 0 = none | 51 | int bind; // SDL scancode, 0 = none |
| 101 | }; | 52 | }; |
| 102 | 53 | ||
| 103 | static FeatureState g_climb{true, 0}; | ||
| 104 | static FeatureState g_bhop{true, 0}; | 54 | static FeatureState g_bhop{true, 0}; |
| 105 | static FeatureState g_abh{true, 0}; | 55 | static FeatureState g_abh{true, 0}; |
| 106 | 56 | ||
| 107 | // tree | 57 | // tree |
| 108 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; | 58 | static MenuNode g_root{NODE_ROOT, "HL2hake", true, 0, {}, nullptr, nullptr, nullptr}; |
| 109 | static MenuNode g_climb_feat{NODE_FEATURE, "Climb", true, 2, {}, nullptr, nullptr, nullptr}; | ||
| 110 | static MenuNode g_climb_active{NODE_TOGGLE, "Active", false, 0, {}, &g_climb.active, nullptr, nullptr}; | ||
| 111 | static MenuNode g_climb_bind{NODE_BIND, "Bind", false, 0, {}, nullptr, &g_climb.bind, "None"}; | ||
| 112 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; | 59 | static MenuNode g_bhop_feat{NODE_FEATURE, "Bunnyhop", true, 1, {}, nullptr, nullptr, nullptr}; |
| 113 | static MenuNode g_bhop_active{NODE_TOGGLE, "Active", false, 0, {}, &g_bhop.active, nullptr, nullptr}; | 60 | static MenuNode g_bhop_active{NODE_TOGGLE, "Active", false, 0, {}, &g_bhop.active, nullptr, nullptr}; |
| 114 | static MenuNode g_abh_feat{NODE_FEATURE, "ABH", true, 1, {}, nullptr, nullptr, nullptr}; | 61 | static MenuNode g_abh_feat{NODE_FEATURE, "ABH", true, 1, {}, nullptr, nullptr, nullptr}; |
| @@ -123,14 +70,11 @@ bool g_menu_open = false; | |||
| 123 | static bool g_bind_mode = false; // true = waiting for key press | 70 | static bool g_bind_mode = false; // true = waiting for key press |
| 124 | 71 | ||
| 125 | static void build_tree() { | 72 | static void build_tree() { |
| 126 | g_climb_feat.children[0] = &g_climb_active; | ||
| 127 | g_climb_feat.children[1] = &g_climb_bind; | ||
| 128 | g_bhop_feat.children[0] = &g_bhop_active; | 73 | g_bhop_feat.children[0] = &g_bhop_active; |
| 129 | g_abh_feat.children[0] = &g_abh_active; | 74 | g_abh_feat.children[0] = &g_abh_active; |
| 130 | g_root.children[0] = &g_climb_feat; | 75 | g_root.children[0] = &g_bhop_feat; |
| 131 | g_root.children[1] = &g_bhop_feat; | 76 | g_root.children[1] = &g_abh_feat; |
| 132 | g_root.children[2] = &g_abh_feat; | 77 | g_root.child_count = 2; |
| 133 | g_root.child_count = 3; | ||
| 134 | } | 78 | } |
| 135 | 79 | ||
| 136 | static int g_depth[16]; // depth of each visible row (for indentation) | 80 | static int g_depth[16]; // depth of each visible row (for indentation) |
| @@ -190,7 +134,6 @@ static void config_save() { | |||
| 190 | FILE *f = fopen(config_path().c_str(), "w"); | 134 | FILE *f = fopen(config_path().c_str(), "w"); |
| 191 | if (!f) | 135 | if (!f) |
| 192 | return; | 136 | return; |
| 193 | fprintf(f, "[climb]\nactive=%d\nbind=%d\n", g_climb.active, g_climb.bind); | ||
| 194 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\n", g_bhop.active, g_bhop.bind); | 137 | fprintf(f, "[bhop]\nactive=%d\nbind=%d\n", g_bhop.active, g_bhop.bind); |
| 195 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); | 138 | fprintf(f, "[abh]\nactive=%d\nbind=%d\n", g_abh.active, g_abh.bind); |
| 196 | fclose(f); | 139 | fclose(f); |
| @@ -205,9 +148,7 @@ static void config_load() { | |||
| 205 | while (fgets(line, sizeof(line), f)) { | 148 | while (fgets(line, sizeof(line), f)) { |
| 206 | line[strcspn(line, "\r\n")] = 0; | 149 | line[strcspn(line, "\r\n")] = 0; |
| 207 | if (line[0] == '[') { | 150 | if (line[0] == '[') { |
| 208 | if (strstr(line, "[climb]")) | 151 | if (strstr(line, "[bhop]")) |
| 209 | cur = &g_climb; | ||
| 210 | else if (strstr(line, "[bhop]")) | ||
| 211 | cur = &g_bhop; | 152 | cur = &g_bhop; |
| 212 | else if (strstr(line, "[abh]")) | 153 | else if (strstr(line, "[abh]")) |
| 213 | cur = &g_abh; | 154 | cur = &g_abh; |
| @@ -265,18 +206,42 @@ static const char *scancode_name(int sc) { | |||
| 265 | case 87: return "F1"; case 88: return "F2"; case 89: return "F3"; | 206 | case 87: return "F1"; case 88: return "F2"; case 89: return "F3"; |
| 266 | case 90: return "F4"; case 91: return "F5"; case 92: return "F6"; | 207 | case 90: return "F4"; case 91: return "F5"; case 92: return "F6"; |
| 267 | case 93: return "F7"; case 94: return "F8"; | 208 | case 93: return "F7"; case 94: return "F8"; |
| 209 | case 600: return "MouseL"; case 601: return "MouseR"; | ||
| 210 | case 602: return "MouseM"; case 603: return "Mouse4"; | ||
| 211 | case 604: return "Mouse5"; | ||
| 268 | default: return scancode_name(0); // "None" for unmapped | 212 | default: return scancode_name(0); // "None" for unmapped |
| 269 | } | 213 | } |
| 270 | } | 214 | } |
| 271 | 215 | ||
| 272 | // get a snapshot of key states: returns array of currently-held scancodes | 216 | // get a snapshot of key states: returns array of currently-held scancodes |
| 273 | static bool g_prev_key_state[512] = {}; | 217 | static bool g_prev_key_state[608] = {}; |
| 274 | static bool g_key_down[512] = {}; // true for ONE frame on press | 218 | static bool g_key_down[608] = {}; // true for ONE frame on press |
| 275 | 219 | ||
| 276 | // read SDL_GetKeyboardState — the game's own SDL is in-process | 220 | // read SDL_GetKeyboardState — the game's own SDL is in-process |
| 277 | using SDL_GetKeyboardState_fn = const uint8_t *(*)(int *); | 221 | using SDL_GetKeyboardState_fn = const uint8_t *(*)(int *); |
| 278 | static SDL_GetKeyboardState_fn SDL_GetKeyboardState_real = nullptr; | 222 | static SDL_GetKeyboardState_fn SDL_GetKeyboardState_real = nullptr; |
| 279 | 223 | ||
| 224 | // mouse buttons map to pseudo-scancodes 600..604 | ||
| 225 | static constexpr int MOUSE_BASE = 600; // 600=L 601=R 602=M 603=X1 604=X2 | ||
| 226 | using SDL_GetMouseState_fn = unsigned (*)(int *, int *); | ||
| 227 | static SDL_GetMouseState_fn SDL_GetMouseState_real = nullptr; | ||
| 228 | |||
| 229 | static void poll_mouse() { | ||
| 230 | if (!SDL_GetMouseState_real) | ||
| 231 | SDL_GetMouseState_real = | ||
| 232 | (SDL_GetMouseState_fn)dlsym(RTLD_DEFAULT, "SDL_GetMouseState"); | ||
| 233 | if (!SDL_GetMouseState_real) | ||
| 234 | return; | ||
| 235 | int mx, my; | ||
| 236 | unsigned mask = SDL_GetMouseState_real(&mx, &my); | ||
| 237 | for (int b = 0; b < 5; b++) { | ||
| 238 | bool down = (mask & (1u << b)) != 0; // SDL buttons 1..5 = bits 0..4 | ||
| 239 | int sc = MOUSE_BASE + b; | ||
| 240 | g_key_down[sc] = down && !g_prev_key_state[sc]; | ||
| 241 | g_prev_key_state[sc] = down; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 280 | static void poll_keyboard() { | 245 | static void poll_keyboard() { |
| 281 | if (!SDL_GetKeyboardState_real) | 246 | if (!SDL_GetKeyboardState_real) |
| 282 | SDL_GetKeyboardState_real = | 247 | SDL_GetKeyboardState_real = |
| @@ -285,36 +250,32 @@ static void poll_keyboard() { | |||
| 285 | return; | 250 | return; |
| 286 | int numkeys = 0; | 251 | int numkeys = 0; |
| 287 | const uint8_t *state = SDL_GetKeyboardState_real(&numkeys); | 252 | const uint8_t *state = SDL_GetKeyboardState_real(&numkeys); |
| 288 | if (!state) | 253 | if (state) |
| 289 | return; | 254 | for (int i = 0; i < numkeys && i < MOUSE_BASE; i++) { |
| 290 | for (int i = 0; i < numkeys && i < 512; i++) { | 255 | g_key_down[i] = state[i] && !g_prev_key_state[i]; |
| 291 | g_key_down[i] = state[i] && !g_prev_key_state[i]; | 256 | g_prev_key_state[i] = state[i]; |
| 292 | g_prev_key_state[i] = state[i]; | 257 | } |
| 293 | } | 258 | poll_mouse(); |
| 294 | } | 259 | } |
| 295 | 260 | ||
| 296 | static bool key_pressed(int sc) { | 261 | static bool key_pressed(int sc) { |
| 297 | return sc >= 0 && sc < 512 && g_key_down[sc]; | 262 | return sc >= 0 && sc < MOUSE_BASE + 5 && g_key_down[sc]; |
| 298 | } | 263 | } |
| 299 | 264 | ||
| 300 | [[maybe_unused]] static bool key_held(int sc) { | 265 | [[maybe_unused]] static bool key_held(int sc) { |
| 301 | return sc >= 0 && sc < 512 && g_prev_key_state[sc]; | 266 | return sc >= 0 && sc < MOUSE_BASE + 5 && g_prev_key_state[sc]; |
| 302 | } | 267 | } |
| 303 | 268 | ||
| 304 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND | 269 | // feature gate queried from hl2h.cpp do_move(): feature must be Active AND |
| 305 | // the activation condition met. Climb activates on its bind key held (falls | 270 | // its bind key held (always-on when unbound). |
| 306 | // back to the historic middle-mouse behavior when unbound); other features | ||
| 307 | // activate on their bind key held, or are always-on when unbound. | ||
| 308 | bool feature_active(int feature) { | 271 | bool feature_active(int feature) { |
| 309 | static FeatureState *feats[3] = {&g_climb, &g_bhop, &g_abh}; | 272 | static FeatureState *feats[2] = {&g_bhop, &g_abh}; |
| 310 | if (feature < 0 || feature > 2) | 273 | if (feature < 0 || feature > 1) |
| 311 | return false; | 274 | return false; |
| 312 | FeatureState *f = feats[feature]; | 275 | FeatureState *f = feats[feature]; |
| 313 | if (!f->active) | 276 | if (!f->active) |
| 314 | return false; | 277 | return false; |
| 315 | if (f->bind == 0) | 278 | return f->bind == 0 || key_held(f->bind); |
| 316 | return feature == FEAT_CLIMB ? middle_mouse_down() : true; | ||
| 317 | return key_held(f->bind); | ||
| 318 | } | 279 | } |
| 319 | 280 | ||
| 320 | static void menu_handle_input() { | 281 | static void menu_handle_input() { |
| @@ -333,7 +294,7 @@ static void menu_handle_input() { | |||
| 333 | // menu is open | 294 | // menu is open |
| 334 | if (g_bind_mode) { | 295 | if (g_bind_mode) { |
| 335 | // wait for any key press (except Insert, Up, Down, Escape, Enter) | 296 | // wait for any key press (except Insert, Up, Down, Escape, Enter) |
| 336 | for (int i = 0; i < 512; i++) { | 297 | for (int i = 0; i < MOUSE_BASE + 5; i++) { |
| 337 | if (!g_key_down[i]) | 298 | if (!g_key_down[i]) |
| 338 | continue; | 299 | continue; |
| 339 | if (i == SCAN_INSERT || i == SCAN_UP || i == SCAN_DOWN || | 300 | if (i == SCAN_INSERT || i == SCAN_UP || i == SCAN_DOWN || |
| @@ -359,7 +320,7 @@ static void menu_handle_input() { | |||
| 359 | MenuNode *n = g_visible[g_selected]; | 320 | MenuNode *n = g_visible[g_selected]; |
| 360 | if (n->bind_ptr) { | 321 | if (n->bind_ptr) { |
| 361 | // clear same bind from other features | 322 | // clear same bind from other features |
| 362 | FeatureState *features[] = {&g_climb, &g_bhop, &g_abh}; | 323 | FeatureState *features[] = {&g_bhop, &g_abh}; |
| 363 | for (auto *f : features) | 324 | for (auto *f : features) |
| 364 | if (&f->bind != n->bind_ptr && f->bind == i) | 325 | if (&f->bind != n->bind_ptr && f->bind == i) |
| 365 | f->bind = 0; | 326 | f->bind = 0; |
| @@ -549,10 +510,10 @@ void outer_draw() { | |||
| 549 | draw_text(200, 10 + i * 20, "[press key]"); | 510 | draw_text(200, 10 + i * 20, "[press key]"); |
| 550 | else { | 511 | else { |
| 551 | /* stable name for current bind */ | 512 | /* stable name for current bind */ |
| 552 | static char bn[3][32]; | 513 | static char bn[2][32]; |
| 553 | static FeatureState *feats[] = {&g_climb, &g_bhop, &g_abh}; | 514 | static FeatureState *feats[] = {&g_bhop, &g_abh}; |
| 554 | int fi = 0; | 515 | int fi = 0; |
| 555 | for (int k = 0; k < 3; k++) | 516 | for (int k = 0; k < 2; k++) |
| 556 | if (n->bind_ptr == &feats[k]->bind) | 517 | if (n->bind_ptr == &feats[k]->bind) |
| 557 | fi = k; | 518 | fi = k; |
| 558 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); | 519 | snprintf(bn[fi], 32, "[%s]", scancode_name(*n->bind_ptr)); |
