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