diff --git a/src/features/thirdperson.c b/src/features/thirdperson.c index 1aaff6b..8f647ce 100644 --- a/src/features/thirdperson.c +++ b/src/features/thirdperson.c @@ -39,13 +39,29 @@ void thirdperson_toggle(void) { } bool thirdperson_key_event(int keynum, int down) { - if (down && (keynum == 'C' || keynum == 'c' || keynum == 99)) { - thirdperson_toggle(); - return true; + i_engine->Con_Printf("Thirdperson key event: keynum=%d, down=%d, configured=%d\n", + keynum, down, g_settings.thirdperson_key); + + if (!down) { + return false; } - if (down && keynum == g_settings.thirdperson_key && - g_settings.thirdperson_key != 'C' && g_settings.thirdperson_key != 'c') { + bool should_toggle = false; + + if (keynum == 'C' || keynum == 'c' || keynum == 67 || keynum == 99) { + i_engine->Con_Printf("C key detected (keynum=%d)\n", keynum); + if (g_settings.thirdperson_key == 'C' || g_settings.thirdperson_key == 'c' || + g_settings.thirdperson_key == 67 || g_settings.thirdperson_key == 99) { + should_toggle = true; + } + } + + else if (keynum == g_settings.thirdperson_key) { + i_engine->Con_Printf("Configured key detected (keynum=%d)\n", keynum); + should_toggle = true; + } + + if (should_toggle) { thirdperson_toggle(); return true; } diff --git a/src/hooks.c b/src/hooks.c index 552d48b..94d2a26 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -13,24 +13,20 @@ #include "include/game_detection.h" #include "features/thirdperson.h" -// For ImGui context access #define IMGUI_IMPLEMENTATION #include "include/imgui/imgui.h" #include "include/imgui/backends/imgui_impl_opengl2.h" -// Include for mouse button constants #include "include/sdk/public/keydefs.h" #include <dlfcn.h> #include <GL/gl.h> #include <string.h> -#include <unistd.h> // usleep() +#include <unistd.h> -// For DetourFunction and DetourRemove extern void* DetourFunction(void* orig, void* hook); extern bool DetourRemove(void* orig, void* hook); -// Define BYTE as unsigned char for GL hooks typedef unsigned char BYTE; /* Forward declarations of hook functions */ @@ -91,23 +87,19 @@ bool hooks_init(void) { HOOK(i_client, CalcRefdef); HOOK(i_client, HUD_PostRunCmd); - /* Third-person hooks - use direct replacement approach */ ho_CL_IsThirdPerson = i_client->CL_IsThirdPerson; i_client->CL_IsThirdPerson = h_CL_IsThirdPerson; i_engine->Con_Printf("CL_IsThirdPerson hook installed at %p -> %p\n", ho_CL_IsThirdPerson, h_CL_IsThirdPerson); - /* Camera offset hook - critical for third-person view */ ho_CL_CameraOffset = i_client->CL_CameraOffset; i_client->CL_CameraOffset = h_CL_CameraOffset; i_engine->Con_Printf("CL_CameraOffset hook installed at %p -> %p\n", ho_CL_CameraOffset, h_CL_CameraOffset); - /* Manual hook for HUD_Key_Event - avoiding type cast issues */ ho_HUD_Key_Event = (key_event_func_t)i_client->HUD_Key_Event; i_client->HUD_Key_Event = (key_event_func_t)h_HUD_Key_Event; - /* Manual OpenGL hooks - get functions from the game engine's GL context */ real_glColor4f = (void (*)(GLfloat, GLfloat, GLfloat, GLfloat))glColor4f; if (real_glColor4f) { void* result = DetourFunction((void*)real_glColor4f, (void*)h_glColor4f); @@ -116,10 +108,6 @@ bool hooks_init(void) { } } - /* We don't hook swap buffers directly anymore - we use HUD_Redraw instead - which is more reliable in GoldSrc engine */ - - /* Detour hooks */ void* clmove_ptr = dlsym(hw, "CL_Move"); if (!clmove_ptr) { i_engine->Con_Printf("Failed to find CL_Move\n"); @@ -194,36 +182,29 @@ void h_CL_CreateMove(float frametime, usercmd_t* cmd, int active) { return; } - /* Declared in globals.c */ localplayer = i_engine->GetLocalPlayer(); - // First call original function to let the game set up movement commands ORIGINAL(CL_CreateMove, frametime, cmd, active); vec3_t old_angles = cmd->viewangles; - // Store original movement commands float origForward = cmd->forwardmove; float origSide = cmd->sidemove; float origUp = cmd->upmove; int origButtons = cmd->buttons; - // If menu is open and movement is not allowed, zero out movement commands if (g_menu_open && !g_settings.menu_allow_movement) { cmd->forwardmove = 0.0f; cmd->sidemove = 0.0f; cmd->upmove = 0.0f; cmd->buttons = 0; - // If menu is open and movement is not allowed, only force angles if (s_lock_initialized) { vec_copy(cmd->viewangles, s_locked_view_angles); } } else { - // Menu is closed OR movement is allowed, process all features - // Restore original movement values if menu is open with movement allowed if (g_menu_open && g_settings.menu_allow_movement) { cmd->forwardmove = origForward; cmd->sidemove = origSide; @@ -231,7 +212,6 @@ void h_CL_CreateMove(float frametime, usercmd_t* cmd, int active) { cmd->buttons = origButtons; } - // Always process features if movement is allowed or menu is closed bhop(cmd); aimbot(cmd); bullet_tracers(cmd); @@ -239,7 +219,6 @@ void h_CL_CreateMove(float frametime, usercmd_t* cmd, int active) { check_namechanger_mode_and_execute(cmd); fov_adjust(cmd); - // If menu is open with movement allowed, still need to lock view angles if (g_menu_open && s_lock_initialized) { vec_copy(cmd->viewangles, s_locked_view_angles); } @@ -263,44 +242,33 @@ rgb_t rainbow_color(float time) { } int h_HUD_Redraw(float time, int intermission) { - // Force set view angles every frame when menu is open force_view_angles(); - // Call original function to let the game draw int ret = ORIGINAL(HUD_Redraw, time, intermission); - // Draw watermark if enabled if (g_settings.watermark) { rgb_t color = g_settings.watermark_rainbow ? rainbow_color(time) : (rgb_t){ 0, 255, 255 }; engine_draw_text(5, 5, "https://git.deadzone.lol/Wizzard/goldsrc-cheat", color); } - // Draw ESP esp(); - // Draw custom crosshair custom_crosshair(); - // Handle cursor for ImGui when menu is open if (g_menu_open && g_imgui_context) { - // Get screen dimensions SCREENINFO scr_inf; scr_inf.iSize = sizeof(SCREENINFO); i_engine->pfnGetScreenInfo(&scr_inf); - // Get mouse position from engine int mouse_x, mouse_y; i_engine->GetMousePosition(&mouse_x, &mouse_y); - // Update ImGui mouse position ImGui::SetCurrentContext(g_imgui_context); ImGuiIO& io = ImGui::GetIO(); - // Update mouse buttons - using our tracked state from key events io.MouseDown[0] = g_mouse_down[0]; io.MouseDown[1] = g_mouse_down[1]; - // Update mouse position (clamped to screen) if (mouse_x >= 0 && mouse_x < scr_inf.iWidth && mouse_y >= 0 && mouse_y < scr_inf.iHeight) { io.MousePos.x = (float)mouse_x; @@ -308,7 +276,6 @@ int h_HUD_Redraw(float time, int intermission) { } } - // Render ImGui menu (if open) menu_render(); return ret; @@ -446,45 +413,48 @@ void h_CL_Move(void) /*----------------------------------------------------------------------------*/ int h_HUD_Key_Event(int down, int keynum, const char* pszCurrentBinding) { - // Debug output but only for specific keys to avoid spam - if (keynum == 'C' || keynum == g_settings.thirdperson_key || keynum == K_INS) { + // Debug output for important keys + if (keynum == 'C' || keynum == 'c' || keynum == 67 || keynum == 99 || + keynum == g_settings.thirdperson_key || keynum == K_INS) { i_engine->Con_Printf("Key event: down=%d, keynum=%d, binding=%s\n", down, keynum, pszCurrentBinding ? pszCurrentBinding : "none"); } - // Check if thirdperson feature wants to handle this key - if (thirdperson_key_event(down, keynum)) { + // Check if menu is in key binding mode - this must come first + extern bool g_waiting_for_key_bind; + if (g_waiting_for_key_bind && down) { + menu_key_event(keynum, down); + return 0; + } + + // Then try thirdperson key handling + if (thirdperson_key_event(keynum, down)) { + i_engine->Con_Printf("Thirdperson key event handled successfully\n"); return 0; // The key was handled by thirdperson } - // Toggle menu with Insert key or specific binding if (down && (keynum == K_INS || (pszCurrentBinding && strcmp(pszCurrentBinding, "dz_menu") == 0))) { i_engine->Con_Printf("Menu toggle key detected!\n"); menu_key_event(keynum, down); - return 0; // Block this key from reaching the game + return 0; } - // ImGui gets priority on all input when menu is open if (g_menu_open) { - // For mouse buttons, update our own tracking to help ImGui if (keynum == K_MOUSE1 || keynum == K_MOUSE2) { if (keynum == K_MOUSE1) g_mouse_down[0] = down ? true : false; else if (keynum == K_MOUSE2) g_mouse_down[1] = down ? true : false; - return 0; // Block mouse buttons from game + return 0; } - // Let ESC pass through to the game to close console/etc. if (keynum == K_ESCAPE && down) { if (ho_HUD_Key_Event) return ho_HUD_Key_Event(down, keynum, pszCurrentBinding); } - // Allow WASD movement keys if the setting is enabled if (g_settings.menu_allow_movement) { - // Check for movement key bindings instead of specific keys if (pszCurrentBinding && ( strstr(pszCurrentBinding, "+forward") || strstr(pszCurrentBinding, "+back") || @@ -499,11 +469,10 @@ int h_HUD_Key_Event(int down, int keynum, const char* pszCurrentBinding) { return ho_HUD_Key_Event(down, keynum, pszCurrentBinding); } - // Also allow WASD keys directly if (keynum == 'W' || keynum == 'A' || keynum == 'S' || keynum == 'D' || - keynum == ' ' || // Space for jump - keynum == K_CTRL || // Crouch - keynum == K_SHIFT) { // Walk + keynum == ' ' || + keynum == K_CTRL || + keynum == K_SHIFT) { i_engine->Con_Printf("Passing direct movement key to game: %d\n", keynum); if (ho_HUD_Key_Event) @@ -511,11 +480,9 @@ int h_HUD_Key_Event(int down, int keynum, const char* pszCurrentBinding) { } } - // Block all other keys from reaching the game return 0; } - // When menu is closed, let all keys pass to the game if (ho_HUD_Key_Event) { return ho_HUD_Key_Event(down, keynum, pszCurrentBinding); } @@ -525,28 +492,21 @@ int h_HUD_Key_Event(int down, int keynum, const char* pszCurrentBinding) { /*----------------------------------------------------------------------------*/ -// Force set view angles through the engine when menu is open static void force_view_angles(void) { - // Only do anything when menu is open/closed state changes static bool s_was_menu_open = false; - // Get the current time for smoother transitions float current_time = i_engine->GetClientTime(); static float s_menu_close_time = 0.0f; static bool s_is_restoring = false; - // Handle menu state changes if (g_menu_open != s_was_menu_open) { - // Menu state changed if (g_menu_open) { - // Menu just opened - store current view angles i_engine->GetViewAngles(s_locked_view_angles); s_lock_initialized = true; i_engine->Con_Printf("Stored view angles: %.1f %.1f %.1f\n", s_locked_view_angles[0], s_locked_view_angles[1], s_locked_view_angles[2]); s_is_restoring = false; } else { - // Menu just closed - set up restoration timing s_menu_close_time = current_time; s_is_restoring = true; @@ -561,19 +521,14 @@ static void force_view_angles(void) { s_was_menu_open = g_menu_open; } - // When menu is open, continuously force the locked view angles if (g_menu_open && s_lock_initialized) { - // Force the engine angles to match our locked angles i_engine->SetViewAngles(s_locked_view_angles); } - // Continue restoring angles for a short time after menu close to prevent flicker if (!g_menu_open && s_is_restoring) { if (current_time - s_menu_close_time < 0.2f) { - // Still in restoration period, keep forcing angles i_engine->SetViewAngles(s_locked_view_angles); } else { - // Done restoring s_is_restoring = false; } } diff --git a/src/include/menu.h b/src/include/menu.h index 9727624..d113b78 100644 --- a/src/include/menu.h +++ b/src/include/menu.h @@ -17,6 +17,8 @@ void menu_key_event(int keynum, int down); extern bool g_menu_open; extern bool g_imgui_initialized; extern ImGuiContext* g_imgui_context; +extern bool g_waiting_for_key_bind; +extern const char* g_current_key_binding_action; #ifdef __cplusplus } diff --git a/src/main.c b/src/main.c index d6ec12e..4509e4a 100644 --- a/src/main.c +++ b/src/main.c @@ -18,7 +18,6 @@ static bool loaded = false; -/* Create a debug log file */ void debug_log(const char* message) { FILE* logfile = fopen("/tmp/cheat-unload-debug.log", "a"); if (logfile) { @@ -30,54 +29,39 @@ void debug_log(const char* message) { } } -/* Enhanced unloading with debug logging */ void safe_unload_with_debug(void) { debug_log("Starting safe unload with debug logging"); - /* Log important function addresses for debugging */ char buf[256]; snprintf(buf, sizeof(buf), "Function addresses - self_unload: %p, unload: %p, hooks_restore: %p", (void*)self_unload, (void*)unload, (void*)hooks_restore); debug_log(buf); - /* Reset all settings to safe values */ debug_log("Resetting all settings to default values"); i_engine->pfnClientCmd("echo \"Step 0: Resetting all settings...\""); settings_reset(); - /* Unhook everything first in an orderly manner */ i_engine->pfnClientCmd("echo \"Step 1: Unhooking functions...\""); debug_log("Unhooking all functions"); - /* First OpenGL hooks since they're most likely to crash if not restored */ debug_log("Restoring OpenGL hooks"); - // Don't manually unhook GL functions, it's already handled in hooks_restore - /* Then restore other hooks */ debug_log("Restoring VMT hooks"); hooks_restore(); - /* Restore globals */ debug_log("Restoring globals"); globals_restore(); - /* Remove our command */ debug_log("Removing custom commands"); i_engine->pfnClientCmd("echo \"Step 2: Removing custom commands...\""); - /* Wait a bit to ensure all hooks are properly removed */ debug_log("Waiting for hooks to settle"); i_engine->pfnClientCmd("echo \"Step 3: Waiting for hooks to settle...\""); - usleep(250000); /* 250ms */ + usleep(250000); - /* Now try to unload the library */ debug_log("Beginning library unload sequence"); i_engine->pfnClientCmd("echo \"Step 4: Unloading library...\""); - - /* - * RTLD_LAZY: If the symbol is never referenced, then it is never resolved. - * RTLD_NOLOAD: Don't load the shared object. - */ + void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD); snprintf(buf, sizeof(buf), "dlopen result: %p", self); @@ -108,51 +92,42 @@ void safe_unload_with_debug(void) { i_engine->pfnClientCmd("echo \"Unload procedure completed\""); } -/* Handler for dz_uninject command */ void UNINJECT_CommandHandler(void) { i_engine->pfnClientCmd("echo \"Uninjecting goldsource-cheat with debug logging...\""); - /* Use the safe unload with debug instead of scheduling uninjection */ safe_unload_with_debug(); } -/* Handler for dz_menu command */ void MENU_CommandHandler(void) { extern bool g_menu_open; g_menu_open = !g_menu_open; i_engine->Con_Printf("Menu toggled to %s\n", g_menu_open ? "open" : "closed"); } -__attribute__((constructor)) /* Entry point when injected */ +__attribute__((constructor)) void load(void) { printf("goldsource-cheat injected!\n"); - /* Initialize globals/interfaces */ if (!globals_init()) { fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n"); self_unload(); return; } - /* Initialize settings with defaults */ settings_init(); - /* Hook functions */ if (!hooks_init()) { fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n"); self_unload(); return; } - /* Register custom commands */ i_engine->pfnAddCommand("dz_uninject", UNINJECT_CommandHandler); i_engine->pfnAddCommand("dz_menu", MENU_CommandHandler); - // Bind INSERT key to dz_menu command (for menu toggle) i_engine->pfnClientCmd("bind INS dz_menu"); i_engine->Con_Printf("Bound INSERT key to menu toggle\n"); - /* Play sound to indicate successful injection */ if (IsCS16()) { i_engine->pfnClientCmd("play weapons/knife_deploy1.wav"); i_engine->pfnClientCmd("speak \"Cheat successfully loaded\""); @@ -179,7 +154,6 @@ void load(void) { i_engine->pfnClientCmd("echo \"Deadzone rulez!\""); i_engine->pfnClientCmd("echo \"https://git.deadzone.lol/Wizzard/goldsrc-cheat\""); - /* Get game version after injecting */ GameType game = get_current_game(); switch(game) { case GAME_HALFLIFE: @@ -208,31 +182,24 @@ void load(void) { loaded = true; } -__attribute__((destructor)) /* Entry point when unloaded */ +__attribute__((destructor)) void unload(void) { if (loaded) { - /* Reset all settings to default values */ settings_reset(); globals_restore(); hooks_restore(); - // Don't manually unhook GL functions, it's already handled in hooks_restore } printf("goldsource-cheat unloaded.\n\n"); } void self_unload(void) { - /* - * RTLD_LAZY: If the symbol is never referenced, then it is never resolved. - * RTLD_NOLOAD: Don't load the shared object. - */ void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD); - - /* Close the call we just made to dlopen() */ - dlclose(self); - - /* Close the call our injector made */ - dlclose(self); + + if (self) { + dlclose(self); + dlclose(self); + } } diff --git a/src/menu.c b/src/menu.c index ba3de35..9593533 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1,37 +1,29 @@ #include <stdlib.h> #include <stdio.h> -// This file needs to be compiled as C++ #define IMGUI_IMPLEMENTATION #include "include/menu.h" #include "include/sdk.h" #include "include/globals.h" #include "include/settings.h" -#include "include/hooks.h" // For hook function declarations +#include "include/hooks.h" #include <GL/gl.h> -// Include for mouse button constants #include "include/sdk/public/keydefs.h" -// Access to hitbox enum from aim.c extern const char* hitbox_names[]; extern int current_hitbox; -// Menu state bool g_menu_open = false; -// ImGui context and state ImGuiContext* g_imgui_context = NULL; bool g_imgui_initialized = false; -// Key binding state -static bool g_waiting_for_key_bind = false; -static const char* g_current_key_binding_action = NULL; +bool g_waiting_for_key_bind = false; +const char* g_current_key_binding_action = NULL; -// Fallback menu if ImGui fails static void render_fallback_menu(void); -// Verify OpenGL state is valid static bool check_gl_state(void) { GLenum error = glGetError(); if (error != GL_NO_ERROR) { @@ -52,24 +44,19 @@ static bool check_gl_state(void) { } extern "C" bool menu_init(void) { - // Print debug message printf("Initializing ImGui menu...\n"); i_engine->Con_Printf("Initializing ImGui menu...\n"); - // Check for existing context and cleanup if (g_imgui_context) { printf("ImGui context already exists, shutting down first\n"); menu_shutdown(); } - // Check OpenGL state if (!check_gl_state()) { printf("OpenGL not ready for ImGui initialization\n"); i_engine->Con_Printf("Warning: OpenGL state not clean, continuing anyway\n"); - // Not fatal, just a warning } - // Create ImGui context g_imgui_context = ImGui::CreateContext(); if (!g_imgui_context) { printf("Failed to create ImGui context\n"); @@ -80,20 +67,16 @@ extern "C" bool menu_init(void) { printf("ImGui context created successfully\n"); i_engine->Con_Printf("ImGui context created successfully\n"); - // Configure ImGui ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; - // Enable mouse input - io.MouseDrawCursor = false; // Don't draw cursor until menu is open + io.MouseDrawCursor = false; - // Get initial screen dimensions SCREENINFO scr_inf; scr_inf.iSize = sizeof(SCREENINFO); i_engine->pfnGetScreenInfo(&scr_inf); - // Verify and set default dimensions if (scr_inf.iWidth <= 0 || scr_inf.iHeight <= 0) { scr_inf.iWidth = 800; scr_inf.iHeight = 600; @@ -104,10 +87,8 @@ extern "C" bool menu_init(void) { scr_inf.iWidth, scr_inf.iHeight); } - // Set initial display size - critical for NewFrame to succeed io.DisplaySize = ImVec2((float)scr_inf.iWidth, (float)scr_inf.iHeight); - // Initialize OpenGL implementation for ImGui bool init_result = ImGui_ImplOpenGL2_Init(); if (!init_result) { printf("Failed to initialize ImGui OpenGL2 backend\n"); @@ -120,7 +101,6 @@ extern "C" bool menu_init(void) { printf("ImGui OpenGL2 backend initialized successfully\n"); i_engine->Con_Printf("ImGui OpenGL2 backend initialized successfully\n"); - // Set ImGui style ImGui::StyleColorsDark(); ImGuiStyle& style = ImGui::GetStyle(); style.WindowRounding = 5.0f; @@ -133,11 +113,9 @@ extern "C" bool menu_init(void) { style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.3f, 0.3f, 0.3f, 1.0f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.4f, 0.4f, 0.4f, 1.0f); - // Menu starts closed g_menu_open = false; g_imgui_initialized = true; - // Ensure game has mouse control at start i_client->IN_ActivateMouse(); i_engine->Con_Printf("ImGui menu initialized successfully\n"); @@ -158,70 +136,54 @@ extern "C" void menu_shutdown(void) { i_engine->Con_Printf("ImGui shutdown complete\n"); } - // Always reset menu state on shutdown g_menu_open = false; - // Make sure the game mouse is active when we shut down i_client->IN_ActivateMouse(); - // Restore mouse bindings i_engine->pfnClientCmd("bind mouse1 +attack; bind mouse2 +attack2"); } extern "C" void menu_render(void) { - // Skip rendering if menu is not open if (!g_menu_open) return; if (g_imgui_initialized && g_imgui_context) { - // Set the current context ImGui::SetCurrentContext(g_imgui_context); - // Get screen dimensions SCREENINFO scr_inf; scr_inf.iSize = sizeof(SCREENINFO); i_engine->pfnGetScreenInfo(&scr_inf); - // Validate screen dimensions if (scr_inf.iWidth <= 0 || scr_inf.iHeight <= 0) { i_engine->Con_Printf("Warning: Invalid screen dimensions, using defaults\n"); scr_inf.iWidth = 800; scr_inf.iHeight = 600; } - // Set display size for ImGui ImGuiIO& io = ImGui::GetIO(); io.DisplaySize = ImVec2((float)scr_inf.iWidth, (float)scr_inf.iHeight); - // Start new ImGui frame ImGui_ImplOpenGL2_NewFrame(); ImGui::NewFrame(); - // Set window position and size ImGui::SetNextWindowPos(ImVec2(scr_inf.iWidth * 0.5f, scr_inf.iHeight * 0.5f), ImGuiCond_Once, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_Once); - // Begin main window if (ImGui::Begin("GoldSource Cheat", &g_menu_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize)) { - // Create tabs if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None)) { - // Aimbot tab if (ImGui::BeginTabItem("Aimbot")) { if (ImGui::Checkbox("Enable Aimbot", &g_settings.aimbot_enabled)) { - // No need to set cvar value } if (g_settings.aimbot_enabled) { if (ImGui::SliderFloat("FOV", &g_settings.aimbot_fov, 0.1f, 180.0f, "%.1f")) { - // No need to set cvar value } if (ImGui::SliderFloat("Smoothing", &g_settings.aimbot_smooth, 1.0f, 100.0f, "%.1f")) { - // No need to set cvar value } const char* hitbox_items[] = { "Head", "Chest", "Stomach", "Pelvis", "Nearest" }; @@ -240,7 +202,6 @@ extern "C" void menu_render(void) { ImGui::EndTabItem(); } - // Visuals tab if (ImGui::BeginTabItem("Visuals")) { const char* esp_modes[] = {"Off", "2D Box", "Name", "All"}; int esp_mode = (int)g_settings.esp_mode; @@ -251,7 +212,6 @@ extern "C" void menu_render(void) { ImGui::Checkbox("ESP Friendly", &g_settings.esp_friendly); if (ImGui::SliderFloat("FOV Changer", &g_settings.fov, 70.0f, 140.0f, "%.1f")) { - // No need to set cvar value } ImGui::Checkbox("Chams", &g_settings.chams); @@ -263,7 +223,6 @@ extern "C" void menu_render(void) { ImGui::EndTabItem(); } - // Movement tab if (ImGui::BeginTabItem("Movement")) { ImGui::Checkbox("Bunny Hop", &g_settings.bhop); @@ -282,7 +241,6 @@ extern "C" void menu_render(void) { ImGui::EndTabItem(); } - // Misc tab with extra options if (ImGui::BeginTabItem("Misc")) { ImGui::Checkbox("Name Changer", &g_settings.namechanger); @@ -298,7 +256,6 @@ extern "C" void menu_render(void) { ImGui::Separator(); - // Menu options ImGui::Text("Menu Settings:"); ImGui::Checkbox("Allow Movement (WASD) With Menu Open", &g_settings.menu_allow_movement); @@ -312,15 +269,12 @@ extern "C" void menu_render(void) { ImGui::EndTabItem(); } - // View settings tab if (ImGui::BeginTabItem("View")) { ImGui::Text("Camera Settings:"); - // Third-person settings bool thirdperson_changed = ImGui::Checkbox("Third-Person View", &g_settings.thirdperson); if (g_settings.thirdperson) { - // Distance preset buttons with direct setting of values ImGui::BeginGroup(); if (ImGui::Button("100")) { g_settings.thirdperson_dist = 100.0f; @@ -335,20 +289,15 @@ extern "C" void menu_render(void) { } ImGui::EndGroup(); - // Distance slider - DIRECTLY changes the value without console commands ImGui::SliderFloat("Camera Distance", &g_settings.thirdperson_dist, 30.0f, 800.0f, "%.1f"); - // Remove multiplier message since we don't multiply anymore ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Camera distance updates in real-time"); - // Key binding for third-person toggle ImGui::Separator(); ImGui::Text("Keybind for Third-Person Toggle:"); - // Display current key binding const char* key_name = "None"; if (g_settings.thirdperson_key > 0) { - // Get better key names switch(g_settings.thirdperson_key) { case 'F': key_name = "F"; break; case 'V': key_name = "V"; break; @@ -369,13 +318,11 @@ extern "C" void menu_render(void) { case K_MOUSE2: key_name = "Mouse2"; break; case K_MOUSE3: key_name = "Mouse3"; break; default: { - // For printable characters if (g_settings.thirdperson_key >= 32 && g_settings.thirdperson_key <= 126) { static char chr[2] = {0}; chr[0] = (char)g_settings.thirdperson_key; key_name = chr; } else { - // For other keys, show keycode static char code[32] = {0}; snprintf(code, sizeof(code), "Key %d", g_settings.thirdperson_key); key_name = code; @@ -386,35 +333,18 @@ extern "C" void menu_render(void) { ImGui::Text("Current Key: %s", key_name); - // TEMP: Disabled key binding until fixed - // Disable any active key bindings if (g_waiting_for_key_bind) { - g_waiting_for_key_bind = false; - g_current_key_binding_action = NULL; + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.1f, 1.0f)); + ImGui::Button("Press any key...", ImVec2(150, 25)); + ImGui::PopStyleColor(); + } else { + if (ImGui::Button("Bind new key", ImVec2(150, 25))) { + g_waiting_for_key_bind = true; + g_current_key_binding_action = "thirdperson"; + i_engine->Con_Printf("Press any key to bind for third-person toggle\n"); + } } - // Show preset buttons instead - if (ImGui::Button("Bind to C", ImVec2(100, 25))) { - g_settings.thirdperson_key = 'C'; - i_engine->Con_Printf("Third-person toggle bound to C key\n"); - } - - ImGui::SameLine(); - - if (ImGui::Button("Bind to V", ImVec2(100, 25))) { - g_settings.thirdperson_key = 'V'; - i_engine->Con_Printf("Third-person toggle bound to V key\n"); - } - - ImGui::SameLine(); - - if (ImGui::Button("Bind to F", ImVec2(100, 25))) { - g_settings.thirdperson_key = 'F'; - i_engine->Con_Printf("Third-person toggle bound to F key\n"); - } - - ImGui::SameLine(); - if (ImGui::Button("Clear", ImVec2(80, 25))) { g_settings.thirdperson_key = 0; i_engine->Con_Printf("Third-person key binding cleared\n"); @@ -432,7 +362,6 @@ extern "C" void menu_render(void) { ImGui::End(); } - // Render ImGui ImGui::Render(); ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); } else { @@ -440,36 +369,28 @@ extern "C" void menu_render(void) { } } -// This is our fallback menu that we know works static void render_fallback_menu(void) { - // Get screen dimensions SCREENINFO scr_inf; scr_inf.iSize = sizeof(SCREENINFO); i_engine->pfnGetScreenInfo(&scr_inf); - // Draw simple menu background int x1 = scr_inf.iWidth / 4; int y1 = scr_inf.iHeight / 4; int x2 = scr_inf.iWidth * 3 / 4; int y2 = scr_inf.iHeight * 3 / 4; - // More visible background (darker black with higher alpha) i_engine->pfnFillRGBA(x1, y1, x2-x1, y2-y1, 0, 0, 0, 230); - // Draw bright border for visibility - i_engine->pfnFillRGBA(x1, y1, x2-x1, 2, 255, 0, 0, 255); // Top - i_engine->pfnFillRGBA(x1, y2-2, x2-x1, 2, 255, 0, 0, 255); // Bottom - i_engine->pfnFillRGBA(x1, y1, 2, y2-y1, 255, 0, 0, 255); // Left - i_engine->pfnFillRGBA(x2-2, y1, 2, y2-y1, 255, 0, 0, 255); // Right + i_engine->pfnFillRGBA(x1, y1, x2-x1, 2, 255, 0, 0, 255); + i_engine->pfnFillRGBA(x1, y2-2, x2-x1, 2, 255, 0, 0, 255); + i_engine->pfnFillRGBA(x1, y1, 2, y2-y1, 255, 0, 0, 255); + i_engine->pfnFillRGBA(x2-2, y1, 2, y2-y1, 255, 0, 0, 255); - // Title i_engine->pfnDrawSetTextColor(1.0f, 1.0f, 0.0f); i_engine->pfnDrawConsoleString(x1+10, y1+10, "===== GoldSource Cheat Menu (Fallback) ====="); - // Reset color for menu items i_engine->pfnDrawSetTextColor(0.0f, 1.0f, 1.0f); - // Draw menu items int y = y1 + 40; i_engine->pfnDrawConsoleString(x1+20, y, "-- Aimbot Settings --"); y += 20; @@ -506,40 +427,39 @@ static void render_fallback_menu(void) { i_engine->pfnDrawConsoleString(x1+30, y, buffer); y += 30; - // Instructions i_engine->pfnDrawSetTextColor(1.0f, 1.0f, 0.0f); i_engine->pfnDrawConsoleString(x1+20, y, "Press INSERT to close menu"); y += 20; i_engine->pfnDrawConsoleString(x1+20, y, "Use console to change settings"); - // Draw help in bottom corner i_engine->pfnDrawSetTextColor(0.7f, 0.7f, 0.7f); i_engine->pfnDrawConsoleString(5, scr_inf.iHeight - 20, "Type 'dz_menu' in console to toggle menu"); } -// Update the key event handler to support key binding extern "C" void menu_key_event(int keynum, int down) { - // Add debug output - i_engine->Con_Printf("menu_key_event called: keynum=%d, down=%d\n", keynum, down); + i_engine->Con_Printf("menu_key_event called: keynum=%d, down=%d, waiting_for_key=%d\n", + keynum, down, g_waiting_for_key_bind); - // If we're waiting for a key bind and a key is pressed down if (g_waiting_for_key_bind && down && keynum != K_ESCAPE) { - // Don't bind mouse wheel or menu toggle key + i_engine->Con_Printf("Processing key bind: keynum=%d, action=%s\n", + keynum, g_current_key_binding_action ? g_current_key_binding_action : "none"); + + // Skip wheel events and menu toggle key if (keynum != K_MWHEELDOWN && keynum != K_MWHEELUP && keynum != K_INS) { - // Bind the key based on current action if (g_current_key_binding_action && strcmp(g_current_key_binding_action, "thirdperson") == 0) { g_settings.thirdperson_key = keynum; i_engine->Con_Printf("Third-person key bound to keycode: %d\n", keynum); } - // Exit binding mode g_waiting_for_key_bind = false; g_current_key_binding_action = NULL; + i_engine->Con_Printf("Key binding completed!\n"); return; + } else { + i_engine->Con_Printf("Ignored wheel/INS key: %d\n", keynum); } } - // Cancel key binding if escape is pressed if (g_waiting_for_key_bind && down && keynum == K_ESCAPE) { g_waiting_for_key_bind = false; g_current_key_binding_action = NULL; @@ -548,31 +468,24 @@ extern "C" void menu_key_event(int keynum, int down) { } if (keynum == K_INS && down) { - // Toggle menu state g_menu_open = !g_menu_open; i_engine->Con_Printf("Menu %s\n", g_menu_open ? "opened" : "closed"); - // Update ImGui IO if initialized if (g_imgui_initialized && g_imgui_context) { ImGui::SetCurrentContext(g_imgui_context); ImGuiIO& io = ImGui::GetIO(); io.MouseDrawCursor = g_menu_open; } - // Activate or deactivate mouse based on menu state if (g_menu_open) { - // When opening menu, deactivate mouse in game and use our own cursor i_client->IN_DeactivateMouse(); i_client->IN_ClearStates(); - // Fixes potential issues with key state i_engine->pfnClientCmd("unbind mouse1; unbind mouse2"); i_engine->Con_Printf("Mouse deactivated for game, using ImGui cursor\n"); } else { - // When closing menu, reactivate mouse in game i_client->IN_ActivateMouse(); - // Restore default bindings i_engine->pfnClientCmd("bind mouse1 +attack; bind mouse2 +attack2"); i_engine->Con_Printf("Mouse reactivated for game\n"); }