Update thirdperson.c, hooks.c, and 3 more files...
This commit is contained in:
parent
0c63d7c969
commit
07b05f02c4
src
@ -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;
|
||||
}
|
||||
|
83
src/hooks.c
83
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
43
src/main.c
43
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() */
|
||||
if (self) {
|
||||
dlclose(self);
|
||||
|
||||
/* Close the call our injector made */
|
||||
dlclose(self);
|
||||
}
|
||||
}
|
||||
|
137
src/menu.c
137
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");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user