Gigantic update with menu

This commit is contained in:
Wizzard 2025-04-04 16:51:40 -04:00
parent e53e7c5d37
commit 0c63d7c969
44 changed files with 54332 additions and 393 deletions

@ -1,11 +1,15 @@
# Need to use g++ because the sdk headers use classes
CC=g++
INCLUDES=-Isrc/include/sdk/common -Isrc/include/sdk/public -Isrc/include/sdk/pm_shared -Isrc/include/sdk/engine
CFLAGS=-Wall -Wextra -Wno-write-strings -m32 -fPIC $(INCLUDES)
LDFLAGS=-lm
INCLUDES=-Isrc/include/sdk/common -Isrc/include/sdk/public -Isrc/include/sdk/pm_shared -Isrc/include/sdk/engine -Isrc/include
CFLAGS=-Wall -Wextra -Wno-write-strings -m32 -fPIC -fpermissive $(INCLUDES)
LDFLAGS=-lm -lGL
OBJS=obj/main.c.o obj/globals.c.o obj/cvars.c.o obj/hooks.c.o obj/detour.c.o obj/util.c.o obj/features/movement.c.o obj/features/anti_aim.c.o obj/features/fov.c.o obj/features/namechanger.c.o obj/features/esp.c.o obj/features/chams.c.o obj/features/aim.c.o obj/features/misc.c.o obj/game_detection.c.o
IMGUI_DIR=src/include/imgui
IMGUI_INCLUDES=-I$(IMGUI_DIR)
IMGUI_SRCS=$(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
IMGUI_OBJS=$(patsubst %.cpp,%.o,$(IMGUI_SRCS))
OBJS=obj/main.c.o obj/globals.c.o obj/settings.c.o obj/hooks.c.o obj/detour.c.o obj/util.c.o obj/features/movement.c.o obj/features/anti_aim.c.o obj/features/fov.c.o obj/features/namechanger.c.o obj/features/esp.c.o obj/features/chams.c.o obj/features/aim.c.o obj/features/misc.c.o obj/features/thirdperson.c.o obj/game_detection.c.o obj/menu.c.o $(IMGUI_OBJS)
BIN=libhlcheat.so
.PHONY: clean all inject
@ -28,6 +32,12 @@ inject: $(BIN)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) -shared -o $@ $(OBJS) $(LDFLAGS)
$(OBJS): obj/%.c.o : src/%.c
@mkdir -p obj/features/
obj/%.c.o: src/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c -o $@ $< $(LDFLAGS)
$(IMGUI_DIR)/backends/%.o: $(IMGUI_DIR)/backends/%.cpp
$(CC) $(CFLAGS) $(IMGUI_INCLUDES) -c -o $@ $< $(LDFLAGS)
%.o: %.cpp
$(CC) $(CFLAGS) -c -o $@ $< $(LDFLAGS)

217
inject-debug.sh Executable file

@ -0,0 +1,217 @@
#!/bin/bash
pid=$(pidof "hl_linux")
libpath=$(realpath "libhlcheat.so")
if [ "$pid" == "" ]; then
echo "inject-debug.sh: process not running."
exit 1
fi
show_help() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --help Show this help message"
echo " --unload Debug the unload process interactively"
echo " --inject Debug the injection process interactively"
echo ""
echo "Common GDB commands to use during debugging:"
echo " bt Show backtrace"
echo " info locals Show local variables"
echo " n Step over (next line)"
echo " s Step into function"
echo " c Continue execution"
echo " p expression Print value of expression"
echo " finish Run until current function returns"
echo ""
echo "Without options, the script will inject the cheat normally."
exit 0
}
UNLOAD_MODE=0
INJECT_MODE=0
for arg in "$@"; do
case $arg in
--help)
show_help
;;
--unload)
UNLOAD_MODE=1
;;
--inject)
INJECT_MODE=1
;;
esac
done
cat > /tmp/gdbinit-goldsrc << EOF
set confirm off
set pagination off
set print pretty on
define hook-stop
echo \nBREAKPOINT HIT\n
bt
echo \nLOCAL VARIABLES:\n
info locals
echo \nSTACK FRAME:\n
info frame
echo \nCommands: n (next), s (step), c (continue), bt (backtrace), finish (run until function returns)\n
end
EOF
if [ $UNLOAD_MODE -eq 1 ]; then
echo "Starting interactive unload debugging session..."
cat >> /tmp/gdbinit-goldsrc << EOF
# Set up functions to help with dlopen/dlclose
set \$dlopen = (void* (*)(char*, int))dlopen
set \$dlclose = (int (*)(void*))dlclose
set \$dlerror = (char* (*)(void))dlerror
# Set breakpoints on critical functions
break self_unload
break unload
break safe_unload_with_debug
break UNINJECT_CommandHandler
break hooks_restore
break globals_restore
break GL_UNHOOK
# Command to manually invoke the unload from GDB
define uninject
set \$self = \$dlopen("$libpath", 6)
p \$self
call \$dlclose(\$self)
call \$dlclose(\$self)
call \$dlerror()
end
define call_uninject_cmd
call UNINJECT_CommandHandler()
end
echo \nType 'call_uninject_cmd' to execute the uninject command\n
echo Type 'uninject' to manually trigger the unload process\n
EOF
sudo gdb -x /tmp/gdbinit-goldsrc -p $pid
echo "Interactive unload debugging session ended."
exit 0
fi
if [ $INJECT_MODE -eq 1 ]; then
echo "Starting interactive injection debugging session..."
cat >> /tmp/gdbinit-goldsrc << EOF
# Set up functions to help with dlopen/dlclose
set \$dlopen = (void* (*)(char*, int))dlopen
set \$dlclose = (int (*)(void*))dlclose
set \$dlerror = (char* (*)(void))dlerror
# Set breakpoints on critical functions
break load
break globals_init
break cvars_init
break hooks_init
# Command to manually inject the library
define inject
call \$dlopen("$libpath", 2)
call \$dlerror()
end
echo \nType 'inject' to load the library\n
EOF
sudo gdb -x /tmp/gdbinit-goldsrc -p $pid
echo "Interactive injection debugging session ended."
exit 0
fi
echo "Injecting cheat..."
if grep -q "$libpath" "/proc/$pid/maps"; then
echo -e "goldsource-cheat already loaded. Reloading...\n"
cat > /tmp/gdbinit-goldsrc << EOF
set confirm off
set pagination off
set print pretty on
set \$dlopen = (void* (*)(char*, int))dlopen
set \$dlclose = (int (*)(void*))dlclose
set \$dlerror = (char* (*)(void))dlerror
# Reload library
define reload_lib
set \$self = \$dlopen("$libpath", 6)
call \$dlclose(\$self)
call \$dlclose(\$self)
call \$dlopen("$libpath", 2)
call \$dlerror()
echo "\nReload complete. Library has been reloaded.\n"
echo "You can now debug interactively.\n"
echo "Type 'continue' or 'c' to let the game run normally.\n"
echo "Type 'call_uninject_cmd' to trigger the uninject command.\n"
end
# Command to manually trigger uninject
define call_uninject_cmd
call UNINJECT_CommandHandler()
end
# Execute reload automatically
reload_lib
# Break on uninject command
break UNINJECT_CommandHandler
break safe_unload_with_debug
break self_unload
echo "\nType 'help' for GDB commands or 'continue' to let the game run.\n"
EOF
sudo gdb -x /tmp/gdbinit-goldsrc -p $pid
else
cat > /tmp/gdbinit-goldsrc << EOF
set confirm off
set pagination off
set print pretty on
set \$dlopen = (void* (*)(char*, int))dlopen
set \$dlclose = (int (*)(void*))dlclose
set \$dlerror = (char* (*)(void))dlerror
# Initial library load
define load_lib
call \$dlopen("$libpath", 2)
call \$dlerror()
echo "\nInjection complete. Library has been loaded.\n"
echo "You can now debug interactively.\n"
echo "Type 'continue' or 'c' to let the game run normally.\n"
echo "Type 'call_uninject_cmd' to trigger the uninject command.\n"
end
# Command to manually trigger uninject
define call_uninject_cmd
call UNINJECT_CommandHandler()
end
# Execute load automatically
load_lib
# Break on uninject command
break UNINJECT_CommandHandler
break safe_unload_with_debug
break self_unload
echo "\nType 'help' for GDB commands or 'continue' to let the game run.\n"
EOF
sudo gdb -x /tmp/gdbinit-goldsrc -p $pid
fi
echo -e "\nDebug session ended."

@ -1,53 +0,0 @@
#include "include/cvars.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/game_detection.h"
DECL_CVAR(movement_bhop);
DECL_CVAR(movement_autostrafe);
DECL_CVAR(aim_aimbot);
DECL_CVAR(aim_autoshoot);
DECL_CVAR(visuals_esp);
DECL_CVAR(visuals_chams);
DECL_CVAR(visuals_crosshair);
DECL_CVAR(visuals_tracers);
DECL_CVAR(movement_clmove);
DECL_CVAR(watermark);
DECL_CVAR(watermark_rainbow);
DECL_CVAR(aim_aimbot_silent);
DECL_CVAR(visuals_friendly);
DECL_CVAR(movement_antiaim);
DECL_CVAR(movement_antiaim_view);
DECL_CVAR(movement_fakeduck);
DECL_CVAR(misc_namechanger);
DECL_CVAR(misc_namechanger_speed);
DECL_CVAR(visuals_fov);
bool cvars_init(void) {
REGISTER_CVAR(movement_bhop, 1);
REGISTER_CVAR(movement_autostrafe, 1);
REGISTER_CVAR(aim_aimbot, 0);
REGISTER_CVAR(aim_autoshoot, 0); /* Only works with aimbot enabled */
REGISTER_CVAR(visuals_esp, 3);
REGISTER_CVAR(visuals_chams, 1);
REGISTER_CVAR(visuals_crosshair, 0);
REGISTER_CVAR(movement_clmove, 0);
REGISTER_CVAR(watermark, 1);
REGISTER_CVAR(watermark_rainbow, 1);
REGISTER_CVAR(aim_aimbot_silent, 1);
REGISTER_CVAR(visuals_friendly, 0);
REGISTER_CVAR(movement_antiaim, 0);
REGISTER_CVAR(movement_antiaim_view, 0);
REGISTER_CVAR(movement_fakeduck, 0);
REGISTER_CVAR(misc_namechanger, 0);
REGISTER_CVAR(misc_namechanger_speed, 10);
REGISTER_CVAR(visuals_fov, 90);
if (IsCS16()) {
REGISTER_CVAR(visuals_tracers, 0);
} else {
REGISTER_CVAR(visuals_tracers, 1);
}
return true;
}

@ -11,6 +11,7 @@
#include <string.h>
#include <unistd.h> /* getpagesize */
#include <sys/mman.h> /* mprotect */
#include <stdio.h> /* printf */
#include "include/detour.h"
@ -19,6 +20,11 @@
#define PAGE_ALIGN(x) ((x + PAGE_SIZE - 1) & PAGE_MASK)
#define PAGE_ALIGN_DOWN(x) (PAGE_ALIGN(x) - PAGE_SIZE)
/* Store detour data for functions we've hooked */
#define MAX_HOOKS 32
static detour_data_t g_hooks[MAX_HOOKS];
static int g_hook_count = 0;
static bool protect_addr(void* ptr, int new_flags) {
void* p = (void*)PAGE_ALIGN_DOWN((detour_ptr_t)ptr);
int pgsz = getpagesize();
@ -49,6 +55,9 @@ static uint8_t def_jmp_bytes[] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00,
#endif
void detour_init(detour_data_t* data, void* orig, void* hook) {
if (!orig || !hook)
return;
data->detoured = false;
data->orig = orig;
data->hook = hook;
@ -108,3 +117,95 @@ bool detour_del(detour_data_t* d) {
return false;
}
/* Get existing hook data for an original function pointer */
static detour_data_t* find_hook_data(void* orig) {
for (int i = 0; i < g_hook_count; i++) {
if (g_hooks[i].orig == orig) {
return &g_hooks[i];
}
}
return NULL;
}
/* Wrapper functions for backward compatibility with code using
* DetourFunction and DetourRemove naming convention */
/*
* Wrapper for detour_add that saves and returns the original
* function pointer as required by the DetourFunction interface
*/
void* DetourFunction(void* orig, void* hook) {
if (!orig || !hook) {
printf("DetourFunction error: NULL pointer provided\n");
return NULL;
}
/* Check if we already have a hook for this function */
detour_data_t* existing = find_hook_data(orig);
if (existing) {
/* If the function was already hooked but with a different hook,
restore the original first */
if (existing->hook != hook) {
printf("DetourFunction: Function at %p already hooked, updating\n", orig);
detour_del(existing);
existing->hook = hook;
/* Recreate the jump instruction with new hook */
memcpy(existing->jmp_bytes, &def_jmp_bytes, sizeof(def_jmp_bytes));
memcpy(&existing->jmp_bytes[JMP_BYTES_PTR], &hook, sizeof(detour_ptr_t));
if (!detour_add(existing)) {
printf("DetourFunction error: Failed to update hook for %p\n", orig);
return NULL;
}
}
return existing->orig;
}
/* No existing hook, create a new one if we have space */
if (g_hook_count >= MAX_HOOKS) {
printf("DetourFunction error: Max hooks (%d) reached\n", MAX_HOOKS);
return NULL;
}
detour_data_t* data = &g_hooks[g_hook_count++];
memset(data, 0, sizeof(detour_data_t)); // Clear memory before use
detour_init(data, orig, hook);
if (detour_add(data))
return data->orig;
/* If detour failed, decrement the counter */
printf("DetourFunction error: Failed to add hook for %p\n", orig);
g_hook_count--;
return NULL;
}
/*
* Wrapper for detour_del that takes the original and hook
* function pointers directly
*/
bool DetourRemove(void* orig, void* hook) {
if (!orig) {
printf("DetourRemove error: NULL original function pointer\n");
return false;
}
/* Find the hook in our array */
detour_data_t* data = find_hook_data(orig);
if (!data) {
printf("DetourRemove error: Hook for function %p not found\n", orig);
return false; /* Not found */
}
/* If hook is specified, make sure it matches */
if (hook && data->hook != hook) {
printf("DetourRemove error: Hook function mismatch for %p\n", orig);
return false;
}
/* Remove the hook */
bool result = detour_del(data);
if (!result) {
printf("DetourRemove error: Failed to remove hook for %p\n", orig);
}
return result;
}

@ -1,142 +1,356 @@
#include <math.h>
#include <cfloat>
#include <string.h>
#include "features.h"
#include "../include/sdk.h"
#include "../include/cvars.h"
#include "../include/util.h"
#include "../include/game_detection.h"
#include "../include/entityutil.h"
#include "../include/mathutil.h"
#include "../include/menu.h"
#include "../include/settings.h"
#include "features.h"
/* Game units to add to the entity origin to get the head */
#define HL1_HEAD_OFFSET 25.f
#define CS16_HEAD_OFFSET 22.f
#define CS16_HORIZONTAL_OFFSET 8.0f
#define DOD_HEAD_OFFSET 22.f
#define DOD_HORIZONTAL_OFFSET 8.0f
#define HITBOX_HEAD 0
#define HITBOX_CHEST 1
#define HITBOX_STOMACH 2
#define HITBOX_PELVIS 3
#define HITBOX_LEFTARM 4
#define HITBOX_RIGHTARM 5
#define HITBOX_LEFTLEG 6
#define HITBOX_RIGHTLEG 7
#define HITBOX_NEAREST 4
#define MAX_HITBOXES 7
/* Scale factor for aim punch */
#define AIM_PUNCH_MULT 2
#define AIM_PUNCH_MULT 2.0f
static float vec_length(vec3_t v) {
return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
#define SMOOTHING_FACTOR 3.0f
#define PITCH 0
#define YAW 1
#define ROLL 2
static bool is_visible(vec3_t start, vec3_t end) {
pmtrace_t* tr = i_engine->PM_TraceLine(start, end, PM_TRACELINE_PHYSENTSONLY, 2, -1);
if (tr->ent <= 0) return false;
const int ent_idx = i_pmove->physents[tr->ent].info;
return get_player(ent_idx) != NULL;
}
#define PRIORITY_NONE 0
#define PRIORITY_LOW 1
#define PRIORITY_MEDIUM 2
#define PRIORITY_HIGH 3
static vec3_t get_closest_delta(vec3_t viewangles) {
// Compensate for aim punch
viewangles.x += g_punchAngles.x * AIM_PUNCH_MULT;
viewangles.y += g_punchAngles.y * AIM_PUNCH_MULT;
viewangles.z += g_punchAngles.z * AIM_PUNCH_MULT;
extern const char* hitbox_options[];
extern int current_hitbox;
vec3_t view_height;
i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height);
vec3_t local_eyes = vec_add(localplayer->origin, view_height);
const char* hitbox_names[] = {
"Head",
"Chest",
"Stomach",
"Pelvis",
"Nearest Point"
};
float min_distance = FLT_MAX; // For tracking the closest player
float best_fov = dz_aim_aimbot->value;
vec3_t best_delta = { 0, 0, 0 };
int current_hitbox = HITBOX_HEAD;
for (int i = 1; i <= i_engine->GetMaxClients(); i++) {
cl_entity_t* ent = get_player(i);
typedef struct {
vec3_t mins;
vec3_t maxs;
vec3_t origin;
float radius;
} hitbox_t;
if (!is_alive(ent) || is_friend(ent)) {
continue; // Skip if not alive or is a friend
}
bool get_hitbox(cl_entity_t* ent, int hitbox_index, hitbox_t* out_hitbox) {
if (!ent || !ent->model || !out_hitbox)
return false;
vec3_t head_pos = ent->origin;
if (ent->curstate.usehull != 1) { // Not crouched
if (IsCS16()) {
head_pos.z += CS16_HEAD_OFFSET;
head_pos.x += CS16_HORIZONTAL_OFFSET;
} else if (IsDayOfDefeat()) {
head_pos.z += DOD_HEAD_OFFSET;
head_pos.x += DOD_HORIZONTAL_OFFSET;
} else {
head_pos.z += HL1_HEAD_OFFSET;
}
}
float distance = vec_length(vec_sub(ent->origin, local_eyes));
if (distance > min_distance) {
continue; // Skip players that are further than the current closest target
}
const vec3_t enemy_angle = vec_to_ang(vec_sub(head_pos, local_eyes));
const vec3_t delta = vec_sub(enemy_angle, viewangles);
vec_norm(delta);
float fov = hypotf(delta.x, delta.y);
if (fov > 360.0f) {
fov = remainderf(fov, 360.0f);
}
if (fov > 180.0f) {
fov = 360.0f - fov;
}
// Only check visibility for potential targets
if (fov < best_fov && is_visible(local_eyes, head_pos)) {
best_fov = fov;
vec_copy(best_delta, delta);
min_distance = distance; // Update the closest target's distance
}
studiohdr_t* studio_model = (studiohdr_t*)i_enginestudio->Mod_Extradata(ent->model);
if (!studio_model)
return false;
mstudiobbox_t* studio_box = NULL;
if (studio_model->hitboxindex) {
studio_box = (mstudiobbox_t*)((byte*)studio_model + studio_model->hitboxindex);
if (hitbox_index >= studio_model->numhitboxes || hitbox_index < 0)
return false;
studio_box += hitbox_index;
} else {
return false;
}
return best_delta;
vec_copy(out_hitbox->mins, studio_box->bbmin);
vec_copy(out_hitbox->maxs, studio_box->bbmax);
vec3_t center;
center.x = (out_hitbox->mins.x + out_hitbox->maxs.x) * 0.5f;
center.y = (out_hitbox->mins.y + out_hitbox->maxs.y) * 0.5f;
center.z = (out_hitbox->mins.z + out_hitbox->maxs.z) * 0.5f;
vec3_t angles;
vec_copy(angles, ent->angles);
int bone = studio_box->bone;
if (bone >= 0 && bone < studio_model->numbones) {
mstudiobone_t* pbone = (mstudiobone_t*)((byte*)studio_model + studio_model->boneindex);
pbone += bone;
angles[0] = pbone->value[0];
angles[1] = pbone->value[1];
angles[2] = pbone->value[2];
}
vec3_t forward, right, up;
i_engine->pfnAngleVectors(angles, forward, right, up);
vec3_t offset;
offset.x = center.x * forward.x + center.y * right.x + center.z * up.x;
offset.y = center.x * forward.y + center.y * right.y + center.z * up.y;
offset.z = center.x * forward.z + center.y * right.z + center.z * up.z;
out_hitbox->origin = vec_add(ent->origin, offset);
if (hitbox_index == HITBOX_HEAD) {
out_hitbox->origin.z += 8.0f;
}
vec3_t size;
size.x = fabs(out_hitbox->maxs.x - out_hitbox->mins.x) * 0.5f;
size.y = fabs(out_hitbox->maxs.y - out_hitbox->mins.y) * 0.5f;
size.z = fabs(out_hitbox->maxs.z - out_hitbox->mins.z) * 0.5f;
out_hitbox->radius = sqrtf(size.x * size.x + size.y * size.y + size.z * size.z);
return true;
}
void aimbot(usercmd_t* cmd) {
static bool shouldShootNextFrame = false; // If you're not using this variable, you can remove it.
static bool hasAdjustedView = false;
bool is_hitbox_visible(vec3_t eye_pos, hitbox_t* hitbox) {
if (!hitbox)
return false;
pmtrace_t* trace = i_engine->PM_TraceLine(eye_pos, hitbox->origin, PM_TRACELINE_PHYSENTSONLY, 2, -1);
if (g_settings.aimbot_rage_mode && trace->fraction > 0.5f) {
return true;
}
if (trace->fraction < 1.0f && trace->ent <= 0)
return false;
if (trace->ent > 0) {
const int ent_idx = i_pmove->physents[trace->ent].info;
if (get_player(ent_idx))
return true;
}
return false;
}
if (!CVAR_ON(aim_aimbot) || !can_shoot())
return;
typedef struct {
cl_entity_t* entity;
float fov;
vec3_t aim_point;
bool is_visible;
int priority;
float distance;
} target_t;
vec3_t engine_viewangles;
i_engine->GetViewAngles(engine_viewangles);
vec3_t best_delta = get_closest_delta(engine_viewangles);
int get_target_priority(cl_entity_t* ent) {
if (!ent)
return PRIORITY_NONE;
if (g_settings.aimbot_rage_mode) {
return PRIORITY_HIGH;
}
return PRIORITY_MEDIUM;
}
if (!vec_is_zero(best_delta)) {
/*
if (!lastShotHit) {
// If the last shot missed, adjust the angle slightly
// This is a simple approach and might need further tweaking
best_delta.y += 0.5f; // Adjust yaw slightly
}
*/
engine_viewangles.x += best_delta.x;
engine_viewangles.y += best_delta.y;
engine_viewangles.z += best_delta.z;
if (CVAR_ON(aim_aimbot_silent)) {
vec_copy(cmd->viewangles, engine_viewangles);
if (cmd->buttons & IN_ATTACK) {
cmd->buttons |= IN_ATTACK;
}
} else {
if (cmd->buttons & IN_ATTACK) {
if (hasAdjustedView) {
hasAdjustedView = false; // Reset flag
} else {
i_engine->SetViewAngles(engine_viewangles);
hasAdjustedView = true;
cmd->buttons &= ~IN_ATTACK; // Defer the shot to the next frame
static bool get_best_hitbox(cl_entity_t* ent, vec3_t eye_pos, hitbox_t* out_hitbox) {
if (!ent || !out_hitbox)
return false;
if (current_hitbox == HITBOX_NEAREST) {
float best_distance = 9999.0f;
bool found_hitbox = false;
for (int i = 0; i < MAX_HITBOXES; i++) {
hitbox_t temp_hitbox;
if (get_hitbox(ent, i, &temp_hitbox)) {
if (is_hitbox_visible(eye_pos, &temp_hitbox)) {
vec3_t to_hitbox = vec_sub(temp_hitbox.origin, eye_pos);
float distance = vec_len2d(to_hitbox);
if (distance < best_distance) {
best_distance = distance;
*out_hitbox = temp_hitbox;
found_hitbox = true;
}
}
}
}
} else if (CVAR_ON(aim_autoshoot) && (cmd->buttons & IN_ATTACK)) {
cmd->buttons &= ~IN_ATTACK;
return found_hitbox;
}
else {
if (get_hitbox(ent, current_hitbox, out_hitbox)) {
return is_hitbox_visible(eye_pos, out_hitbox);
}
}
return false;
}
static target_t get_best_target(vec3_t viewangles, vec3_t eye_pos) {
target_t best_target = {NULL, 0.0f, {0, 0, 0}, false, PRIORITY_NONE, 9999.0f};
float best_score = 0.0f;
float max_fov = g_settings.aimbot_fov;
if (g_settings.aimbot_rage_mode && max_fov < 90.0f) {
max_fov = 90.0f;
}
for (int i = 1; i <= i_engine->GetMaxClients(); i++) {
cl_entity_t* ent = get_player(i);
if (!ent || !is_alive(ent))
continue;
if (!g_settings.aimbot_friendly_fire && is_friend(ent))
continue;
hitbox_t target_hitbox;
bool hitbox_found = false;
hitbox_found = get_best_hitbox(ent, eye_pos, &target_hitbox);
if (!hitbox_found)
continue;
vec3_t to_target = vec_sub(target_hitbox.origin, eye_pos);
vec3_t aim_angles = vec_to_ang(to_target);
vec3_t angle_delta = vec_sub(aim_angles, viewangles);
vec_norm(&angle_delta);
ang_clamp(&angle_delta);
float fov_distance = sqrtf(angle_delta.x * angle_delta.x + angle_delta.y * angle_delta.y);
if (fov_distance > max_fov)
continue;
float distance = sqrtf(to_target.x * to_target.x + to_target.y * to_target.y + to_target.z * to_target.z);
float fov_score = 1.0f - (fov_distance / max_fov);
float priority_score = 0.0f;
if (g_settings.aimbot_rage_mode) {
int priority = get_target_priority(ent);
priority_score = priority / (float)PRIORITY_HIGH;
}
float final_score = fov_score;
if (g_settings.aimbot_rage_mode) {
final_score = (fov_score * 0.5f) + (priority_score * 0.5f);
}
if (final_score > best_score) {
best_score = final_score;
best_target.entity = ent;
best_target.fov = fov_distance;
vec_copy(best_target.aim_point, target_hitbox.origin);
best_target.is_visible = true;
best_target.priority = get_target_priority(ent);
best_target.distance = distance;
}
}
return best_target;
}
void aimbot(usercmd_t* cmd) {
if (!g_settings.aimbot_enabled)
return;
bool should_run_aimbot = true;
bool should_autoshoot = g_settings.aimbot_autoshoot;
switch (0) {
case 0:
should_run_aimbot = true;
break;
case 1:
should_run_aimbot = (cmd->buttons & IN_ATTACK) != 0;
break;
case 2:
should_run_aimbot = (cmd->buttons & IN_ATTACK2) != 0;
break;
default:
should_run_aimbot = true;
}
if (!should_run_aimbot && !g_settings.aimbot_rage_mode)
return;
if (g_settings.aimbot_rage_mode)
should_run_aimbot = true;
bool can_fire = can_shoot();
vec3_t view_height;
i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height);
vec3_t eye_pos = vec_add(localplayer->origin, view_height);
vec3_t engine_viewangles;
i_engine->GetViewAngles(engine_viewangles);
vec3_t adjusted_viewangles = engine_viewangles;
if (g_settings.aimbot_norecoil) {
adjusted_viewangles.x += g_punchAngles.x * AIM_PUNCH_MULT;
adjusted_viewangles.y += g_punchAngles.y * AIM_PUNCH_MULT;
adjusted_viewangles.z += g_punchAngles.z * AIM_PUNCH_MULT;
}
target_t best_target = get_best_target(adjusted_viewangles, eye_pos);
if (best_target.entity && best_target.is_visible) {
vec3_t to_target = vec_sub(best_target.aim_point, eye_pos);
vec3_t aim_angles = vec_to_ang(to_target);
vec3_t delta = vec_sub(aim_angles, engine_viewangles);
vec_norm(&delta);
ang_clamp(&delta);
if (g_settings.aimbot_silent) {
cmd->viewangles.x = engine_viewangles.x + delta.x;
cmd->viewangles.y = engine_viewangles.y + delta.y;
cmd->viewangles.z = engine_viewangles.z + delta.z;
} else {
float smoothing = SMOOTHING_FACTOR;
smoothing = g_settings.aimbot_smooth > 0 ? g_settings.aimbot_smooth : SMOOTHING_FACTOR;
if (g_settings.aimbot_rage_mode) {
smoothing = 1.2f;
}
engine_viewangles.x += delta.x / smoothing;
engine_viewangles.y += delta.y / smoothing;
engine_viewangles.z += delta.z / smoothing;
ang_clamp(&engine_viewangles);
i_engine->SetViewAngles(engine_viewangles);
cmd->viewangles.x = engine_viewangles.x;
cmd->viewangles.y = engine_viewangles.y;
cmd->viewangles.z = engine_viewangles.z;
}
if (should_autoshoot && can_fire) {
if (g_settings.aimbot_rage_mode) {
cmd->buttons |= IN_ATTACK;
} else {
float aim_error = sqrtf(delta.x * delta.x + delta.y * delta.y);
if (aim_error < 5.0f) {
cmd->buttons |= IN_ATTACK;
}
}
}
} else if (should_autoshoot) {
cmd->buttons &= ~IN_ATTACK;
}
}

@ -6,7 +6,7 @@
#include "features.h"
#include "../include/sdk.h"
#include "../include/cvars.h"
#include "../include/settings.h"
#include "../include/util.h"
float random_float(float min, float max) {
@ -16,7 +16,7 @@ float random_float(float min, float max) {
bool isSpacebarPressed() {
Display* display = XOpenDisplay(NULL);
if (!display) {
return false; // Could not open the display, assume not pressed
return false;
}
char keys_return[32];
@ -38,7 +38,7 @@ void anti_aim(usercmd_t* cmd) {
return;
}
if (!CVAR_ON(movement_antiaim)) {
if (!g_settings.antiaim) {
return;
}
@ -68,8 +68,7 @@ void anti_aim(usercmd_t* cmd) {
bool isBunnyHopping = cmd->buttons & IN_JUMP;
bool isStationary = (cmd->forwardmove == 0.0f && cmd->sidemove == 0.0f);
// This shit busted right now
if (CVAR_ON(movement_fakeduck) && (isStationary || isBunnyHopping || isSpacebarPressed())) {
if (g_settings.fakeduck && (isStationary || isBunnyHopping || isSpacebarPressed())) {
static int duckCounter = 0;
if (duckCounter < 2) {
cmd->buttons |= IN_DUCK;
@ -84,7 +83,7 @@ void anti_aim(usercmd_t* cmd) {
if (view_angles.y > 180.0f) view_angles.y -= 360.0f;
if (view_angles.y < -180.0f) view_angles.y += 360.0f;
if (CVAR_ON(movement_antiaim_view)) {
if (g_settings.antiaim_view) {
i_engine->SetViewAngles(view_angles);
i_engine->pfnClientCmd("echo \"Set view angles directly using movement_antiaim_view.\"");
} else {

@ -1,7 +1,6 @@
#include "features.h"
#include "../include/globals.h"
#include "../include/cvars.h"
#include "../include/settings.h"
#include "../include/util.h"
#include <GL/gl.h>
@ -15,7 +14,7 @@ enum chams_settings {
visible_flags visible_mode;
bool chams(void* this_ptr) {
const int setting = dz_visuals_chams->value == 5.0f ? 7 : dz_visuals_chams->value;
const int setting = g_settings.chams ? PLAYER_CHAMS : DISABLED;
if (setting == DISABLED)
return false;
@ -39,8 +38,7 @@ bool chams(void* this_ptr) {
const bool friendly = is_friend(ent);
// Check if the player is friendly and if visuals_friendly is 0
if (friendly && dz_visuals_friendly->value == 0)
if (friendly && !g_settings.esp_friendly)
return false; // Do not render chams for friendlies
/* If we got here it means we are rendering a valid player */

@ -1,18 +1,11 @@
#include <stdint.h>
#include "features.h"
#include "../include/globals.h"
#include "../include/cvars.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/game_detection.h"
/* For dz_esp */
enum esp_values {
ESP_OFF = 0,
ESP_BOX = 1,
ESP_NAME = 2,
/* ESP_ALL should be 3 but we can just OR box and name */
};
// ESP enums moved to settings.h as esp_mode_t
bool gl_draw3dbox(vec3_t o, int bh, int bw, int lw) {
/*
@ -99,7 +92,7 @@ static bool gl_draw2dbox(vec3_t o, int bh) {
}
void esp(void) {
const int setting = (int)dz_visuals_esp->value;
const int setting = g_settings.esp_mode;
if (setting == ESP_OFF)
return;
@ -109,7 +102,7 @@ void esp(void) {
if (!valid_player(ent) || !is_alive(ent) || vec_is_zero(ent->origin))
continue;
if (is_friend(ent) && dz_visuals_friendly->value == 0)
if (is_friend(ent) && !g_settings.esp_friendly)
continue;
int bh = 70;

@ -1,4 +1,3 @@
#ifndef FEATURES_H_
#define FEATURES_H_
@ -11,8 +10,13 @@ enum visible_flags {
FRIEND_VISIBLE = 3,
FRIEND_NOT_VISIBLE = 4,
HANDS = 5,
SCOPE = 6,
};
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------*/
/* src/features/movement.c */
@ -42,4 +46,13 @@ void anti_aim(usercmd_t* cmd);
/* src/features/fov.c */
void fov_adjust(usercmd_t* cmd);
/* src/features/thirdperson.c */
void thirdperson_init(void);
void thirdperson_update(void);
bool thirdperson_key_event(int keynum, int down);
#ifdef __cplusplus
}
#endif
#endif /* FEATURES_H_ */

@ -2,9 +2,9 @@
#include "../include/globals.h"
#include "../include/sdk.h"
#include "../include/util.h"
#include "../include/settings.h"
#include "features.h"
extern cvar_t* dz_visuals_fov;
extern float* scr_fov_value;
void fov_adjust(usercmd_t* cmd) {
@ -13,7 +13,7 @@ void fov_adjust(usercmd_t* cmd) {
return;
}
if (dz_visuals_fov->value) {
*scr_fov_value = dz_visuals_fov->value;
if (g_settings.fov > 0) {
*scr_fov_value = g_settings.fov;
}
}

@ -1,13 +1,12 @@
#include "features.h"
#include "../include/sdk.h"
#include "../include/globals.h"
#include "../include/cvars.h"
#include "../include/util.h"
#include "../include/game_detection.h"
#include "../include/settings.h"
void custom_crosshair(void) {
if (!CVAR_ON(visuals_crosshair))
if (!g_settings.custom_crosshair)
return;
/* Get window size, and then the center. */
@ -15,7 +14,7 @@ void custom_crosshair(void) {
int my = game_info->m_height / 2;
/* The real length is sqrt(2 * (len^2)) */
const int len = dz_visuals_crosshair->value;
const int len = 5;
const int gap = 1;
const float w = 1;
const rgb_t col = { 255, 255, 255 };
@ -37,7 +36,7 @@ static double lastTracerTime = 0;
static bool attackReleased = true;
void bullet_tracers(usercmd_t* cmd) {
if (!CVAR_ON(visuals_tracers) || !is_alive(localplayer))
if (!g_settings.tracers || !is_alive(localplayer))
return;
if (IsCS16()) {

@ -1,11 +1,10 @@
#include <stdio.h>
#include <math.h>
#include "features.h"
#include "../include/sdk.h"
#include "../include/globals.h"
#include "../include/cvars.h"
#include "../include/settings.h"
#include "../include/util.h"
static void autostrafe_legit(usercmd_t* cmd) {
@ -65,7 +64,7 @@ static void autostrafe_rage(usercmd_t* cmd) {
}
void bhop(usercmd_t* cmd) {
if (!CVAR_ON(movement_bhop) || i_pmove->movetype != MOVETYPE_WALK)
if (!g_settings.bhop || i_pmove->movetype != MOVETYPE_WALK)
return;
static bool was_in_air = false;
@ -81,18 +80,8 @@ void bhop(usercmd_t* cmd) {
was_in_air = (i_pmove->flags & FL_ONGROUND) == 0;
/* Autostrafe if enabled. Check if we are in the air and holding space. */
if (is_jumping) {
switch ((int)dz_movement_autostrafe->value) {
case 1:
autostrafe_rage(cmd);
break;
case 2:
autostrafe_legit(cmd);
break;
case 0:
default:
break;
}
if (is_jumping && g_settings.autostrafe) {
autostrafe_rage(cmd);
}
}

@ -4,7 +4,7 @@
#include <vector>
#include "features.h"
#include "../include/globals.h"
#include "../include/cvars.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/game_detection.h"
@ -70,14 +70,20 @@ void change_name_all_players() {
}
void change_name_based_on_mode(usercmd_t* cmd) {
if (!CVAR_ON(misc_namechanger)) return;
if (!g_settings.namechanger) return;
if (++change_counter < dz_misc_namechanger_speed->value) {
if (++change_counter < g_settings.namechanger_speed) {
return;
}
change_counter = 0;
switch ((int)dz_misc_namechanger->value) {
int mode = 3;
if (g_settings.namechanger) {
mode = 3;
}
switch (mode) {
case 1:
change_name_teammates();
break;
@ -93,7 +99,7 @@ void change_name_based_on_mode(usercmd_t* cmd) {
}
void check_namechanger_mode_and_execute(usercmd_t* cmd) {
if (!CVAR_ON(misc_namechanger)) return;
if (!g_settings.namechanger) return;
change_name_based_on_mode(cmd);
}

24
src/features/no_recoil.c Normal file

@ -0,0 +1,24 @@
#include "../include/sdk.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/globals.h"
#include <stdio.h> // For printf
#include <time.h> // For time
static time_t last_log_time = 0;
void no_recoil(usercmd_t* cmd) {
if (!g_settings.aimbot_norecoil || !is_alive(localplayer)) {
return;
}
time_t current_time = time(NULL);
if (current_time - last_log_time >= 5) {
printf("Applying anti-recoil: Punch Angles (X: %f, Y: %f)\n", g_punchAngles[0], g_punchAngles[1]);
last_log_time = current_time;
}
float anti_recoil_value = 100.0f;
cmd->viewangles[0] -= (g_punchAngles[0] * anti_recoil_value);
cmd->viewangles[1] -= (g_punchAngles[1] * anti_recoil_value);
}

8
src/features/no_recoil.h Normal file

@ -0,0 +1,8 @@
#ifndef NO_RECOIL_H
#define NO_RECOIL_H
#include "../include/sdk.h"
void aim_no_recoil(usercmd_t* cmd);
#endif

122
src/features/thirdperson.c Normal file

@ -0,0 +1,122 @@
#include "../include/sdk.h"
#include "../include/settings.h"
#include "../include/globals.h"
#include "../include/util.h"
#include "thirdperson.h"
#include <stdio.h>
#define TP_MIN_DIST 30.0f
#define TP_MAX_DIST 800.0f
#define TP_DEFAULT_DIST 150.0f
#define YAW 1
#define PITCH 0
#define ROLL 2
static bool s_initialized = false;
static bool s_thirdperson_enabled = false;
static vec3_t s_camera_origin = {0, 0, 0};
#ifdef __cplusplus
extern "C" {
#endif
void thirdperson_init(void) {
s_initialized = true;
s_thirdperson_enabled = false;
i_engine->Con_Printf("Third-person system initialized\n");
}
void thirdperson_toggle(void) {
g_settings.thirdperson = !g_settings.thirdperson;
s_thirdperson_enabled = g_settings.thirdperson;
if (s_thirdperson_enabled) {
i_engine->Con_Printf("Third-person view enabled (distance: %.1f)\n", g_settings.thirdperson_dist);
} else {
i_engine->Con_Printf("Third-person view disabled\n");
}
}
bool thirdperson_key_event(int keynum, int down) {
if (down && (keynum == 'C' || keynum == 'c' || keynum == 99)) {
thirdperson_toggle();
return true;
}
if (down && keynum == g_settings.thirdperson_key &&
g_settings.thirdperson_key != 'C' && g_settings.thirdperson_key != 'c') {
thirdperson_toggle();
return true;
}
return false;
}
void thirdperson_modify_view(ref_params_t* pparams) {
if (!g_settings.thirdperson) {
return;
}
float distance = g_settings.thirdperson_dist;
vec3_t forward, right, up;
i_engine->pfnAngleVectors(pparams->viewangles, forward, right, up);
vec3_t camera_offset;
for (int i = 0; i < 3; i++) {
camera_offset[i] = -forward[i] * distance;
}
vec3_t newOrigin;
for (int i = 0; i < 3; i++) {
newOrigin[i] = pparams->vieworg[i] + camera_offset[i];
}
vec_copy(s_camera_origin, newOrigin);
pmtrace_t trace;
i_engine->pEventAPI->EV_SetTraceHull(2);
i_engine->pEventAPI->EV_PlayerTrace(pparams->vieworg, newOrigin, PM_NORMAL, -1, &trace);
if (trace.fraction < 1.0) {
vec3_t dir;
for (int i = 0; i < 3; i++) {
dir[i] = newOrigin[i] - pparams->vieworg[i];
}
float len = sqrtf(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
if (len > 0) {
for (int i = 0; i < 3; i++) {
dir[i] /= len;
}
}
vec3_t collisionPoint;
for (int i = 0; i < 3; i++) {
collisionPoint[i] = pparams->vieworg[i] + (trace.fraction * distance - 5.0f) * forward[i];
}
vec_copy(newOrigin, collisionPoint);
}
vec_copy(pparams->vieworg, newOrigin);
static int debug_count = 0;
if (++debug_count % 300 == 0) {
i_engine->Con_Printf("Camera position: [%.1f, %.1f, %.1f], distance=%.1f\n",
newOrigin[0], newOrigin[1], newOrigin[2], distance);
}
}
void thirdperson_update(void) {
s_thirdperson_enabled = g_settings.thirdperson;
}
int thirdperson_is_active(void) {
return g_settings.thirdperson ? 1 : 0;
}
#ifdef __cplusplus
}
#endif

@ -0,0 +1,28 @@
#ifndef THIRDPERSON_H_
#define THIRDPERSON_H_
#include "../include/sdk.h"
#ifdef __cplusplus
extern "C" {
#endif
void thirdperson_init(void);
int thirdperson_is_active(void);
void thirdperson_get_offset(float* offset);
void thirdperson_update(void);
void thirdperson_toggle(void);
bool thirdperson_key_event(int keynum, int down);
void thirdperson_modify_view(ref_params_t* pparams);
#ifdef __cplusplus
}
#endif
#endif

@ -2,7 +2,7 @@
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/mman.h> /* PROT_* */
#include <sys/mman.h>
#include "include/globals.h"
#include "include/sdk.h"
@ -11,7 +11,6 @@
game_id this_game_id = HL;
vec3_t g_punchAngles = { 0, 0, 0 };
/* Weapon info */
float g_flNextAttack = 0.f, g_flNextPrimaryAttack = 0.f;
int g_iClip = 0;
@ -26,13 +25,10 @@ DECL_INTF(playermove_t, pmove);
DECL_INTF(engine_studio_api_t, enginestudio);
DECL_INTF(StudioModelRenderer_t, studiomodelrenderer);
/* Game struct with some useful info */
game_t* game_info;
/* Array of extra_player_info's for each player */
void* player_extra_info;
/* Updated in CL_CreateMove hook */
cl_entity_t* localplayer = NULL;
float* scr_fov_value = NULL;
@ -40,11 +36,6 @@ float* scr_fov_value = NULL;
/*----------------------------------------------------------------------------*/
bool globals_init(void) {
/*
* Get handler for hw.so
* RTLD_LAZY: If the symbol is never referenced, then it is never resolved.
* RTLD_NOLOAD: Don't load the shared object.
*/
hw = dlopen("hw.so", RTLD_LAZY | RTLD_NOLOAD);
if (!hw) {
printf("goldsource-cheat: globals_init: can't open hw.so\n");
@ -57,7 +48,6 @@ bool globals_init(void) {
return false;
}
/* Get symbol addresses using dlsym and the handler we just opened */
i_engine = (cl_enginefunc_t*)dlsym(hw, "cl_enginefuncs");
i_client = (cl_clientfunc_t*)dlsym(hw, "cl_funcs");
i_pmove = *(playermove_t**)dlsym(hw, "pmove");

@ -1,11 +1,43 @@
#include <stdio.h>
#include <math.h>
#include "include/settings.h"
#include "include/hooks.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/util.h"
#include "include/cvars.h"
#include "include/sdk.h"
#include "include/detour.h" /* 8dcc/detour-lib */
#include "include/main.h" /* For self_unload() */
#include "include/menu.h" /* ImGui menu */
#include "features/features.h" /* bhop(), esp(), etc. */
#include "include/entityutil.h"
#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()
// 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 */
void h_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void h_CL_Move(void);
int h_CL_IsThirdPerson(void);
void h_CL_CameraOffset(float* ofs);
/* Normal VMT hooks */
DECL_HOOK(CL_CreateMove);
@ -13,63 +45,209 @@ DECL_HOOK(HUD_Redraw);
DECL_HOOK(StudioRenderModel);
DECL_HOOK(CalcRefdef);
DECL_HOOK(HUD_PostRunCmd);
key_event_func_t ho_HUD_Key_Event = NULL; // Manually declare the hook
/* OpenGL hooks */
DECL_HOOK(glColor4f);
// Manual declarations for third-person hooks
int (*ho_CL_IsThirdPerson)(void) = NULL;
void (*ho_CL_CameraOffset)(float* ofs) = NULL;
/* OpenGL hooks - use function pointer as we get actual addresses from game */
void (*real_glColor4f)(GLfloat, GLfloat, GLfloat, GLfloat) = NULL;
/* Detour hooks */
static detour_data_t detour_data_clmove;
DECL_DETOUR_TYPE(void, clmove_type);
DECL_HOOK(CL_Move);
/* Flag to delay uninject until next frame */
static bool g_should_uninject = false;
/* Mouse position tracking independent from the game engine */
static int g_menu_mouse_x = 0;
static int g_menu_mouse_y = 0;
static bool g_mouse_down[5] = {false, false, false, false, false}; // Tracking mouse buttons
/* Store last known camera angles for locking */
static vec3_t s_locked_view_angles = {0, 0, 0};
static bool s_lock_initialized = false;
/* Forward declarations */
static void force_view_angles(void);
/*----------------------------------------------------------------------------*/
bool hooks_init(void) {
/* Initialize ImGui menu before hooking any rendering functions */
if (!menu_init()) {
i_engine->Con_Printf("Failed to initialize ImGui menu\n");
return false;
}
/* Initialize third-person camera system */
thirdperson_init();
/* VMT hooking */
HOOK(i_client, CL_CreateMove);
HOOK(i_client, HUD_Redraw);
HOOK(i_studiomodelrenderer, StudioRenderModel);
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;
/* OpenGL hooks */
GL_HOOK(glColor4f);
/* 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);
if (!result) {
i_engine->Con_Printf("Failed to hook glColor4f\n");
}
}
/* 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)
if (!clmove_ptr) {
i_engine->Con_Printf("Failed to find CL_Move\n");
return false;
}
/* Initialize detour_data_clmove struct for detour, and add the hook */
detour_init(&detour_data_clmove, clmove_ptr, (void*)h_CL_Move);
detour_add(&detour_data_clmove);
if (!detour_add(&detour_data_clmove)) {
i_engine->Con_Printf("Failed to hook CL_Move\n");
return false;
}
/* Initialize debug info */
if (g_settings.thirdperson) {
i_engine->Con_Printf("Third-person mode initialized with distance %.1f\n",
g_settings.thirdperson_dist);
}
i_engine->Con_Printf("All hooks initialized successfully\n");
return true;
}
void hooks_restore(void) {
detour_del(&detour_data_clmove);
/* First shut down ImGui to prevent any rendering after hooks are removed */
menu_shutdown();
/* Remove CL_Move detour */
if (detour_data_clmove.detoured) {
detour_del(&detour_data_clmove);
}
/* Remove OpenGL hooks */
if (real_glColor4f) {
DetourRemove((void*)real_glColor4f, (void*)h_glColor4f);
real_glColor4f = NULL;
}
/* Restore VMT hooks */
if (i_client) {
i_client->CL_CreateMove = ho_CL_CreateMove;
i_client->HUD_Redraw = ho_HUD_Redraw;
i_client->CalcRefdef = ho_CalcRefdef;
i_client->HUD_PostRunCmd = ho_HUD_PostRunCmd;
i_client->CL_IsThirdPerson = ho_CL_IsThirdPerson;
i_client->CL_CameraOffset = ho_CL_CameraOffset;
if (ho_HUD_Key_Event) {
i_client->HUD_Key_Event = ho_HUD_Key_Event;
ho_HUD_Key_Event = NULL;
}
}
if (i_studiomodelrenderer) {
i_studiomodelrenderer->StudioRenderModel = ho_StudioRenderModel;
}
i_engine->Con_Printf("All hooks restored\n");
}
void hooks_schedule_uninject(void) {
g_should_uninject = true;
}
/*----------------------------------------------------------------------------*/
void h_CL_CreateMove(float frametime, usercmd_t* cmd, int active) {
ORIGINAL(CL_CreateMove, frametime, cmd, active);
vec3_t old_angles = cmd->viewangles;
/* Check if we should uninject before doing anything else */
if (g_should_uninject) {
g_should_uninject = false;
self_unload();
return;
}
/* Declared in globals.c */
localplayer = i_engine->GetLocalPlayer();
bhop(cmd);
aimbot(cmd);
bullet_tracers(cmd);
anti_aim(cmd);
check_namechanger_mode_and_execute(cmd);
fov_adjust(cmd);
// 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;
cmd->upmove = origUp;
cmd->buttons = origButtons;
}
// Always process features if movement is allowed or menu is closed
bhop(cmd);
aimbot(cmd);
bullet_tracers(cmd);
anti_aim(cmd);
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);
}
}
// Always maintain view angle control and clamp angles
correct_movement(cmd, old_angles);
vec_clamp(cmd->viewangles);
ang_clamp(&cmd->viewangles);
}
/*----------------------------------------------------------------------------*/
@ -85,23 +263,53 @@ 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);
if (dz_watermark->value) {
/* Determine the color for the watermark */
rgb_t color;
if (dz_watermark_rainbow->value) {
color = rainbow_color(time);
} else {
color = (rgb_t){ 0, 255, 255 }; // default color
}
/* Watermark */
// 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;
io.MousePos.y = (float)mouse_y;
}
}
// Render ImGui menu (if open)
menu_render();
return ret;
}
@ -118,8 +326,14 @@ void h_StudioRenderModel(void* this_ptr) {
void h_CalcRefdef(ref_params_t* params) {
/* Store punch angles for CreateMove */
vec_copy(g_punchAngles, params->punchangle);
/* Call original CalcRefdef */
ORIGINAL(CalcRefdef, params);
/* Apply third-person camera with direct view modification */
if (g_settings.thirdperson) {
thirdperson_modify_view(params);
}
}
/*----------------------------------------------------------------------------*/
@ -181,16 +395,186 @@ void h_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
break;
}
ORIGINAL(glColor4f, r, g, b, a);
/* This part is executed regardless of the visible_mode.
* NOTE: Not calling original breaks chams. */
if (real_glColor4f)
real_glColor4f(r, g, b, a);
}
/*----------------------------------------------------------------------------*/
void h_CL_Move() {
if (dz_movement_clmove->value != 0) {
for (int i = 0; i < (int)dz_movement_clmove->value; i++)
CALL_ORIGINAL(detour_data_clmove, clmove_type);
/*
* Simple passthrough to thirdperson module
*/
int h_CL_IsThirdPerson(void) {
// We still need this to tell the engine we're in third person view
return thirdperson_is_active();
}
/*
* This isn't used anymore - our direct camera control in CalcRefdef handles everything
*/
void h_CL_CameraOffset(float* ofs) {
// Not used by our new implementation
ofs[0] = ofs[1] = ofs[2] = 0.0f;
}
// Function to handle CL_Move
void h_CL_Move(void)
{
// Get original function address safely
void (*original_func)(void) = NULL;
if (detour_data_clmove.detoured) {
detour_del(&detour_data_clmove);
original_func = (void (*)(void))detour_data_clmove.orig;
}
// Call original function if we have it
if (original_func) {
original_func();
}
// Update third-person camera every frame
thirdperson_update();
// Restore the detour
if (detour_data_clmove.orig) {
detour_add(&detour_data_clmove);
}
}
/*----------------------------------------------------------------------------*/
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) {
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)) {
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
}
CALL_ORIGINAL(detour_data_clmove, clmove_type);
// 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
}
// 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") ||
strstr(pszCurrentBinding, "+moveleft") ||
strstr(pszCurrentBinding, "+moveright") ||
strstr(pszCurrentBinding, "+jump") ||
strstr(pszCurrentBinding, "+duck") ||
strstr(pszCurrentBinding, "+speed"))) {
i_engine->Con_Printf("Passing movement key to game: %s\n", pszCurrentBinding);
if (ho_HUD_Key_Event)
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
i_engine->Con_Printf("Passing direct movement key to game: %d\n", keynum);
if (ho_HUD_Key_Event)
return ho_HUD_Key_Event(down, keynum, 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);
}
return 0;
}
/*----------------------------------------------------------------------------*/
// 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;
// Immediately restore angles
if (s_lock_initialized) {
i_engine->SetViewAngles(s_locked_view_angles);
i_engine->Con_Printf("Restored view angles: %.1f %.1f %.1f\n",
s_locked_view_angles[0], s_locked_view_angles[1], s_locked_view_angles[2]);
}
}
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;
}
}
}

@ -1,57 +0,0 @@
#ifndef CVARS_H_
#define CVARS_H_
#include "sdk.h"
#include "globals.h"
#define CVAR_PREFIX "dz_"
#define CVAR_HACK_ID 0x4000 /* (1<<14) One that is not in use by the game */
/*
* DECL_CVAR: Declares cvar variable in source file.
* DECL_CVAR_EXTERN: Same but for headers.
* REGISTER_CVAR: Create the cvar, return cvar_t*
* CVAR_ON: Returns true if the cvar is non-zero
*
* prefix | meaning
* -------+-------------------------------
* dz_* | cvar variable
*/
#define DECL_CVAR(name) cvar_t* dz_##name = NULL;
#define DECL_CVAR_EXTERN(name) extern cvar_t* dz_##name;
#define REGISTER_CVAR(name, value) \
dz_##name = \
i_engine->pfnRegisterVariable(CVAR_PREFIX #name, #value, CVAR_HACK_ID);
#define CVAR_ON(name) (dz_##name->value != 0.0f)
/*----------------------------------------------------------------------------*/
DECL_CVAR_EXTERN(movement_bhop);
DECL_CVAR_EXTERN(movement_autostrafe);
DECL_CVAR_EXTERN(aim_aimbot);
DECL_CVAR_EXTERN(aim_autoshoot);
DECL_CVAR_EXTERN(visuals_esp);
DECL_CVAR_EXTERN(visuals_chams);
DECL_CVAR_EXTERN(visuals_crosshair);
DECL_CVAR_EXTERN(visuals_tracers);
DECL_CVAR_EXTERN(movement_clmove);
DECL_CVAR_EXTERN(watermark);
DECL_CVAR_EXTERN(watermark_rainbow);
DECL_CVAR_EXTERN(aim_aimbot_silent);
DECL_CVAR_EXTERN(visuals_friendly);
DECL_CVAR_EXTERN(movement_antiaim);
DECL_CVAR_EXTERN(movement_antiaim_view);
DECL_CVAR_EXTERN(movement_fakeduck);
DECL_CVAR_EXTERN(misc_namechanger)
DECL_CVAR_EXTERN(misc_namechanger_speed)
/*----------------------------------------------------------------------------*/
bool cvars_init(void);
#endif /* CVARS_H_ */

14
src/include/entityutil.h Normal file

@ -0,0 +1,14 @@
#ifndef ENTITY_H_
#define ENTITY_H_ 1
#include "sdk.h"
cl_entity_t* get_player(int ent_idx);
bool is_alive(cl_entity_t* ent);
bool valid_player(cl_entity_t* ent);
bool is_friend(cl_entity_t* ent);
bool can_shoot(void);
char* get_name(int ent_idx);
#endif /* ENTITY_H_ */

@ -1,4 +1,3 @@
#ifndef HOOKS_H_
#define HOOKS_H_
@ -8,6 +7,12 @@
#include <dlfcn.h> /* dlsym */
#include <GL/gl.h> /* GLFloat */
#include <stdint.h>
typedef void (*hook_func_t)(void);
typedef int (*key_event_func_t)(int down, int keynum, const char* pszCurrentBinding);
/*
* Table of prefixes:
* prefix | meaning
@ -51,18 +56,15 @@
* GL_HOOK: Hooks a OpenGL function. Example:
*
* GL_HOOK(glColor4f);
* void** hp_glColor4f = (void**)dlsym(hw, "qglColor4f"); // Ptr
* ho_glColor4f = (glColor4f_t)(*hp_glColor4f); // Original from ptr
* *hp_glColor4f = (void*)h_glColor4f; // Set ptr to our func
* Note: ho_glColor4f and h_glColor4f sould be declared with DECL_HOOK_EXTERN
*
* Will store the original function in o_glColor4f and set the function to
* h_glColor4f (which must be defined)
*
* GL_UNHOOK: Restores a OpenGL hook created by GL_HOOK. Example:
*
* GL_UNHOOK(glColor4f);
* void** hp_glColor4f = (void**)dlsym(hw, "qglColor4f"); // Ptr
* *hp_glColor4f = (void*)ho_glColor4f; // Set to original
*
* Will restore the original function from o_glColor4f to the original pointer.
*/
#define DECL_HOOK_EXTERN(type, name, ...) \
typedef type (*name##_t)(__VA_ARGS__); \
@ -77,19 +79,27 @@
#define ORIGINAL(name, ...) ho_##name(__VA_ARGS__);
#define GL_HOOK(name) \
void** hp_##name = (void**)dlsym(hw, "q" #name); \
ho_##name = (name##_t)(*hp_##name); \
*hp_##name = (void*)h_##name;
#define GL_HOOK(ret_type, name, ...) \
typedef ret_type (*name##_t)(__VA_ARGS__); \
name##_t h_##name; \
name##_t o_##name;
#define GL_UNHOOK(name) \
void** hp_##name = (void**)dlsym(hw, "q" #name); \
*hp_##name = (void*)ho_##name;
#define GL_UNHOOK(name) \
o_##name = h_##name;
/*----------------------------------------------------------------------------*/
/* For GL hooking */
typedef void (*glColor4f_t)(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
typedef void* (*wglSwapBuffers_t)(void*);
bool hooks_init(void);
void hooks_restore(void);
/* OpenGL hooks */
extern void h_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
extern void* o_glColor4f;
extern wglSwapBuffers_t o_wglSwapBuffers;
/* HUD_Key_Event hook */
extern int h_HUD_Key_Event(int down, int keynum, const char* pszCurrentBinding);
extern key_event_func_t ho_HUD_Key_Event;
/* VMT hooks */
DECL_HOOK_EXTERN(void, CL_CreateMove, float, usercmd_t*, int);
@ -100,10 +110,16 @@ DECL_HOOK_EXTERN(void, HUD_PostRunCmd, struct local_state_s*,
struct local_state_s*, struct usercmd_s*, int, double,
unsigned int);
/* OpenGL hooks */
DECL_HOOK_EXTERN(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat);
/* Detour hooks */
DECL_HOOK_EXTERN(void, CL_Move);
/* Detour for CL_Move */
#define ORIGINAL_DETOUR(type) ((type)detour_get_original(&detour_data_clmove))()
/*----------------------------------------------------------------------------*/
bool hooks_init(void);
void hooks_restore(void);
void hooks_schedule_uninject(void);
#endif /* HOOKS_H_ */

@ -0,0 +1,321 @@
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
// **Prefer using the code in imgui_impl_opengl3.cpp**
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
// confuse your GPU driver.
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-06-28: OpenGL: ImGui_ImplOpenGL2_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL2_DestroyFontsTexture(). (#7748)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
// 2017-09-01: OpenGL: Save and restore current polygon mode.
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_opengl2.h"
#include <stdint.h> // intptr_t
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
#endif
// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
#if defined(_WIN32) && !defined(APIENTRY)
#define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
#endif
#if defined(_WIN32) && !defined(WINGDIAPI)
#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
#endif
#if defined(__APPLE__)
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
// [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG
#include <stdio.h>
#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check
#else
#define GL_CALL(_CALL) _CALL // Call without error check
#endif
// OpenGL data
struct ImGui_ImplOpenGL2_Data
{
GLuint FontTexture;
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
// Functions
bool ImGui_ImplOpenGL2_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl2";
return true;
}
void ImGui_ImplOpenGL2_Shutdown()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL2_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
IM_DELETE(bd);
}
void ImGui_ImplOpenGL2_NewFrame()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL2_Init()?");
if (!bd->FontTexture)
ImGui_ImplOpenGL2_CreateDeviceObjects();
if (!bd->FontTexture)
ImGui_ImplOpenGL2_CreateFontsTexture();
}
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
// (DO NOT MODIFY THIS FILE! Add the code in your calling function)
// GLint last_program;
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
// glUseProgram(0);
// ImGui_ImplOpenGL2_RenderDrawData(...);
// glUseProgram(last_program)
// There are potentially many more states you could need to clear/setup that we can't access from default headers.
// e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
// OpenGL2 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
// Backup GL state
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
// Setup desired GL state
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, col)));
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
}
}
}
// Restore modified GL state
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
glShadeModel(last_shade_model);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
}
bool ImGui_ImplOpenGL2_CreateFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
GLint last_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
glGenTextures(1, &bd->FontTexture);
glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
return true;
}
void ImGui_ImplOpenGL2_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
if (bd->FontTexture)
{
glDeleteTextures(1, &bd->FontTexture);
io.Fonts->SetTexID(0);
bd->FontTexture = 0;
}
}
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
{
return ImGui_ImplOpenGL2_CreateFontsTexture();
}
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
{
ImGui_ImplOpenGL2_DestroyFontsTexture();
}
//-----------------------------------------------------------------------------
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

@ -0,0 +1,41 @@
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
// **Prefer using the code in imgui_impl_opengl3.cpp**
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
// confuse your GPU driver.
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
#pragma once
#include "../imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
// Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
#endif // #ifndef IMGUI_DISABLE

@ -0,0 +1,141 @@
//-----------------------------------------------------------------------------
// DEAR IMGUI COMPILE-TIME OPTIONS
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
//-----------------------------------------------------------------------------
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
#pragma once
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
//---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
//#define IMGUI_USE_LEGACY_CRC32_ADLER
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
//#define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
// Only works in combination with IMGUI_ENABLE_FREETYPE.
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
//---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
/*
#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- ...Or use Dear ImGui's own very basic math operators.
//#define IMGUI_DEFINE_MATH_OPERATORS
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
//#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
/*
namespace ImGui
{
void MyFunction(const char* name, MyMatrix44* mtx);
}
*/

17080
src/include/imgui/imgui.cpp Normal file

File diff suppressed because it is too large Load Diff

3777
src/include/imgui/imgui.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,627 @@
// [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.01.
// Grep for [DEAR IMGUI] to find the changes.
//
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Before #including,
//
// #define STB_RECT_PACK_IMPLEMENTATION
//
// in the file that you want to have the implementation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
//
// Has only had a few tests run, may have issues.
//
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
// Please note: better rectangle packers are welcome! Please
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// github:IntellectualKitty
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
// 0.09 (2016-08-27) fix compiler warnings
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//
// LICENSE
//
// See end of file for license information.
//////////////////////////////////////////////////////////////////////////////
//
// INCLUDE SECTION
//
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
typedef int stbrp_coord;
#define STBRP__MAXVAL 0x7fffffff
// Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
// 'stbrp_rect' defined below, stored in the array 'rects', and there
// are 'num_rects' many of them.
//
// Rectangles which are successfully packed have the 'was_packed' flag
// set to a non-zero value and 'x' and 'y' store the minimum location
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
// if you imagine y increasing downwards). Rectangles which do not fit
// have the 'was_packed' flag set to 0.
//
// You should not try to access the 'rects' array from another thread
// while this function is running, as the function temporarily reorders
// the array while it executes.
//
// To pack into another rectangle, you need to call stbrp_init_target
// again. To continue packing into the same rectangle, you can call
// this function again. Calling this multiple times with multiple rect
// arrays will probably produce worse packing results than calling it
// a single time with the full rectangle array, but the option is
// available.
//
// The function returns 1 if all of the rectangles were successfully
// packed and 0 otherwise.
struct stbrp_rect
{
// reserved for your use:
int id;
// input:
stbrp_coord w, h;
// output:
stbrp_coord x, y;
int was_packed; // non-zero if valid packing
}; // 16 bytes, nominally
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
// Initialize a rectangle packer to:
// pack a rectangle that is 'width' by 'height' in dimensions
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
//
// You must call this function every time you start packing into a new target.
//
// There is no "shutdown" function. The 'nodes' memory must stay valid for
// the following stbrp_pack_rects() call (or calls), but can be freed after
// the call (or calls) finish.
//
// Note: to guarantee best results, either:
// 1. make sure 'num_nodes' >= 'width'
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
//
// If you don't do either of the above things, widths will be quantized to multiples
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
//
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
// may run out of temporary storage and be unable to pack some rectangles.
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
// Optionally call this function after init but before doing any packing to
// change the handling of the out-of-temp-memory scenario, described above.
// If you call init again, this will be reset to the default (false).
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
// Optionally select which packing heuristic the library should use. Different
// heuristics will produce better/worse results for different data sets.
// If you call init again, this will be reset to the default.
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
};
//////////////////////////////////////////////////////////////////////////////
//
// the details of the following structures don't matter to you, but they must
// be visible so you can handle the memory allocations for them
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
};
#ifdef __cplusplus
}
#endif
#endif
//////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION SECTION
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
{
STBRP__INIT_skyline = 1
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
// if it's ok to run out of memory, then don't bother aligning them;
// this gives better packing, but may fail due to OOM (even though
// the rectangles easily fit). @TODO a smarter approach would be to only
// quantize once we've hit OOM, then we could get rid of this parameter.
context->align = 1;
else {
// if it's not ok to run out of memory, then quantize the widths
// so that num_nodes is always enough nodes.
//
// I.e. num_nodes * align >= width
// align >= width / num_nodes
// align = ceil(width/num_nodes)
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
context->extra[1].y = (1<<30);
context->extra[1].next = NULL;
}
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP__NOTUSED(c);
STBRP_ASSERT(first->x <= x0);
#if 0
// skip in case we're past the node
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
// add waste area
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
// align to multiple of c->align
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
// bottom left
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
// best-fit
if (y + height <= c->height) {
// can only use it if it first vertically
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
// if doing best-fit (BF), we also have to try aligning right edge to each node position
//
// e.g, if fitting
//
// ____________________
// |____________________|
//
// into
//
// | |
// | ____________|
// |____________|
//
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
//
// This makes BF take about 2x the time
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
// find first node that's admissible
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
// find the left position that matches this
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
// find best position according to heuristic
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
// bail if:
// 1. it failed
// 2. the best node doesn't fit (we don't always check this)
// 3. we're out of memory
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
// on success, create new node
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
cur = *res.prev_link;
if (cur->x < res.x) {
// preserve the existing one, so start testing with the next one
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
// from here, traverse cur and free the nodes, until we get to one
// that shouldn't be freed
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
// move the current node to the free list
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
// stitch the list back in
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
int count=0;
cur = context->active_head;
while (cur) {
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
}
// sort according to heuristic
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0; // empty rect needs no space
} else {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
// unsort
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags and all_rects_packed status
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
if (!rects[i].was_packed)
all_rects_packed = 0;
}
// return the all_rects_packed status
return all_rects_packed;
}
#endif
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,9 +1,10 @@
#ifndef MAIN_H_
#define MAIN_H_
void load(void);
void unload(void);
void self_unload(void);
void UNINJECT_CommandHandler(void);
void safe_unload_with_debug(void);
#endif /* MAIN_H_ */

39
src/include/mathutil.h Normal file

@ -0,0 +1,39 @@
#ifndef MATHUTIL_H_
#define MATHUTIL_H_ 1
#include "sdk.h"
/* Vector 2 for 2d points */
typedef float vec2_t[2];
/*----------------------------------------------------------------------------*/
#define DEG2RAD(n) ((n)*M_PI / 180.0f)
#define RAD2DEG(n) ((n)*180.0f / M_PI)
#define CLAMP(val, min, max) \
(((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
/* Use indexes so it works for float[] as well as vec3_t */
#define vec_copy(dst, src) \
do { \
dst[0] = src[0]; \
dst[1] = src[1]; \
dst[2] = src[2]; \
} while (0)
/*----------------------------------------------------------------------------*/
vec3_t vec3(float x, float y, float z);
vec3_t vec_add(vec3_t a, vec3_t b);
vec3_t vec_sub(vec3_t a, vec3_t b);
bool vec_is_zero(vec3_t v);
float vec_len2d(vec3_t v);
void ang_clamp(vec3_t* v);
void vec_norm(vec3_t* v);
float angle_delta_rad(float a, float b);
vec3_t vec_to_ang(vec3_t v);
vec3_t matrix_3x4_origin(matrix_3x4 m);
bool world_to_screen(vec3_t vec, vec2_t screen);
#endif /* MATHUTIL_H_ */

23
src/include/menu.h Normal file

@ -0,0 +1,23 @@
#pragma once
#include <stdbool.h>
#include "imgui/imgui.h"
#include "imgui/backends/imgui_impl_opengl2.h"
#include "sdk.h"
#ifdef __cplusplus
extern "C" {
#endif
bool menu_init(void);
void menu_shutdown(void);
void menu_render(void);
void menu_key_event(int keynum, int down);
extern bool g_menu_open;
extern bool g_imgui_initialized;
extern ImGuiContext* g_imgui_context;
#ifdef __cplusplus
}
#endif

@ -35,6 +35,38 @@
/* engine_studio_api_t */
#include "sdk/common/r_studioint.h"
#define K_TAB 9
#define K_ENTER 13
#define K_ESCAPE 27
#define K_SPACE 32
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_PAUSE 255
typedef float matrix_3x4[3][4];
typedef matrix_3x4 bone_matrix[128];

82
src/include/settings.h Normal file

@ -0,0 +1,82 @@
#pragma once
#include <stdbool.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ESP_OFF = 0,
ESP_BOX = 1,
ESP_NAME = 2,
ESP_ALL = 3
} esp_mode_t;
typedef struct {
esp_mode_t esp_mode;
bool esp_friendly;
float fov;
bool chams;
bool tracers;
bool custom_crosshair;
bool watermark;
bool watermark_rainbow;
bool aimbot_enabled;
float aimbot_fov;
float aimbot_smooth;
bool aimbot_silent;
bool aimbot_autoshoot;
bool aimbot_norecoil;
bool aimbot_recoil_comp;
bool aimbot_friendly_fire;
bool aimbot_rage_mode;
bool aimbot_team_attack;
int aimbot_hitbox;
bool bhop;
bool autostrafe;
bool antiaim;
bool antiaim_view;
bool fakeduck;
bool clmove;
bool namechanger;
float namechanger_speed;
bool menu_allow_movement;
bool thirdperson;
int thirdperson_key;
float thirdperson_dist;
} cheat_settings_t;
extern cheat_settings_t g_settings;
void settings_init(void);
void settings_reset(void);
inline void init_default_settings(void) {
memset(&g_settings, 0, sizeof(g_settings));
g_settings.aimbot_fov = 5.0f;
g_settings.aimbot_smooth = 10.0f;
g_settings.aimbot_hitbox = 0;
g_settings.esp_mode = ESP_OFF;
g_settings.fov = 90.0f;
g_settings.namechanger_speed = 5.0f;
g_settings.thirdperson = false;
g_settings.thirdperson_dist = 300.0f;
g_settings.thirdperson_key = 'C';
g_settings.menu_allow_movement = true;
}
#ifdef __cplusplus
}
#endif

@ -14,6 +14,13 @@ typedef struct {
uint8_t r, g, b;
} rgb_t;
#define ERR(...) \
do { \
fprintf(stderr, "hl-cheat: %s: ", __func__); \
fprintf(stderr, __VA_ARGS__); \
fputc('\n', stderr); \
} while (0)
#define DEG2RAD(n) ((n)*M_PI / 180.0f)
#define RAD2DEG(n) ((n)*180.0f / M_PI)
#define CLAMP(val, min, max) \
@ -24,9 +31,11 @@ typedef struct {
/* Use indexes so it works for float[] as well as vec3_t */
#define vec_copy(dst, src) \
dst[0] = src[0]; \
dst[1] = src[1]; \
dst[2] = src[2];
do { \
dst[0] = src[0]; \
dst[1] = src[1]; \
dst[2] = src[2]; \
} while (0)
/*----------------------------------------------------------------------------*/
@ -36,13 +45,14 @@ bool valid_player(cl_entity_t* ent);
bool is_friend(cl_entity_t* ent);
bool can_shoot(void);
char* get_name(int ent_idx);
game_id get_cur_game(void);
vec3_t vec3(float x, float y, float z);
vec3_t vec_add(vec3_t a, vec3_t b);
vec3_t vec_sub(vec3_t a, vec3_t b);
bool vec_is_zero(vec3_t v);
float vec_len2d(vec3_t v);
void vec_clamp(vec3_t v);
void vec_norm(vec3_t v);
void ang_clamp(vec3_t* v);
void vec_norm(vec3_t* v);
float angle_delta_rad(float a, float b);
vec3_t vec_to_ang(vec3_t v);
vec3_t matrix_3x4_origin(matrix_3x4 m);
@ -53,4 +63,4 @@ void gl_drawbox(int x, int y, int w, int h, rgb_t c);
void gl_drawline(int x0, int y0, int x1, int y1, float w, rgb_t col);
bool protect_addr(void* ptr, int new_flags);
#endif /* UTIL_H_ */
#endif /* UTIL_H_ */

@ -1,18 +1,128 @@
#include <ctype.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "include/main.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/cvars.h"
#include "include/settings.h"
#include "include/hooks.h"
#include "include/util.h"
#include "include/game_detection.h"
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) {
time_t now = time(NULL);
char timestamp[64];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
fprintf(logfile, "[%s] %s\n", timestamp, message);
fclose(logfile);
}
}
/* 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 */
/* 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);
debug_log(buf);
if (self) {
/* Close the call we just made to dlopen() */
debug_log("Closing first dlopen reference");
int result = dlclose(self);
snprintf(buf, sizeof(buf), "First dlclose result: %d", result);
debug_log(buf);
/* Close the call our injector made */
debug_log("Closing second dlopen reference");
result = dlclose(self);
snprintf(buf, sizeof(buf), "Second dlclose result: %d", result);
debug_log(buf);
} else {
debug_log("ERROR: Failed to get handle to library");
const char* error = dlerror();
if (error) {
debug_log(error);
i_engine->pfnClientCmd("echo \"ERROR: Failed to get handle to library\"");
}
}
debug_log("Safe unload completed");
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 */
void load(void) {
printf("goldsource-cheat injected!\n");
@ -24,12 +134,8 @@ void load(void) {
return;
}
/* Create cvars for settings */
if (!cvars_init()) {
fprintf(stderr, "goldsource-cheat: load: error creating cvars, aborting\n");
self_unload();
return;
}
/* Initialize settings with defaults */
settings_init();
/* Hook functions */
if (!hooks_init()) {
@ -38,33 +144,42 @@ void load(void) {
return;
}
/* Get game version after injecting */
/* 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 'sound/radio/go.wav'");
i_engine->pfnClientCmd("play weapons/knife_deploy1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDayOfDefeat()) {
i_engine->pfnClientCmd("play 'sound/player/gersniper.wav'");
i_engine->pfnClientCmd("play weapons/kar_cock.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsTFC()) {
i_engine->pfnClientCmd("play 'sound/misc/party2.wav'");
i_engine->pfnClientCmd("play misc/party2.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDeathmatchClassic()) {
i_engine->pfnClientCmd("play 'sound/items/suit.wav'");
}
else if (IsSpaceLife()) {
i_engine->pfnClientCmd("play 'sound/finley/soccer_ball.wav'");
i_engine->pfnClientCmd("play items/r_item1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else
{
i_engine->pfnClientCmd("play 'valve/sound/vox/suit.wav'");
i_engine->pfnClientCmd("play weapons/cbar_hit1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
i_engine->pfnClientCmd("echo \"goldsource-cheat loaded successfully!\"");
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:
@ -90,20 +205,19 @@ void load(void) {
break;
}
return;
loaded = true;
}
__attribute__((destructor)) /* Entry point when unloaded */
void unload(void) {
if (loaded) {
/* TODO: Remove our cvars */
/* Reset all settings to default values */
settings_reset();
globals_restore();
hooks_restore();
GL_UNHOOK(glColor4f); /* Manually restore OpenGL hooks here */
// Don't manually unhook GL functions, it's already handled in hooks_restore
}
printf("goldsource-cheat unloaded.\n\n");

580
src/menu.c Normal file

@ -0,0 +1,580 @@
#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 <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;
// 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) {
const char* err_str = "Unknown";
switch (error) {
case GL_INVALID_ENUM: err_str = "GL_INVALID_ENUM"; break;
case GL_INVALID_VALUE: err_str = "GL_INVALID_VALUE"; break;
case GL_INVALID_OPERATION: err_str = "GL_INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: err_str = "GL_STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: err_str = "GL_STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: err_str = "GL_OUT_OF_MEMORY"; break;
}
printf("OpenGL error: %s (0x%x)\n", err_str, error);
i_engine->Con_Printf("OpenGL error: %s (0x%x)\n", err_str, error);
return false;
}
return true;
}
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");
i_engine->Con_Printf("Error: Failed to create ImGui context\n");
return false;
}
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
// 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;
i_engine->Con_Printf("Using default screen dimensions: %dx%d\n",
scr_inf.iWidth, scr_inf.iHeight);
} else {
i_engine->Con_Printf("Screen dimensions: %dx%d\n",
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");
i_engine->Con_Printf("Error: Failed to initialize ImGui OpenGL2 backend\n");
ImGui::DestroyContext(g_imgui_context);
g_imgui_context = NULL;
return false;
}
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;
style.FrameRounding = 3.0f;
style.ItemSpacing = ImVec2(8, 4);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.1f, 0.1f, 0.1f, 0.9f);
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.0f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.15f, 0.15f, 0.15f, 1.0f);
style.Colors[ImGuiCol_Button] = ImVec4(0.2f, 0.2f, 0.2f, 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);
// 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");
return true;
}
extern "C" void menu_shutdown(void) {
if (g_imgui_initialized) {
i_engine->Con_Printf("Shutting down ImGui...\n");
if (g_imgui_context) {
ImGui_ImplOpenGL2_Shutdown();
ImGui::DestroyContext(g_imgui_context);
g_imgui_context = NULL;
}
g_imgui_initialized = false;
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" };
if (ImGui::Combo("Hitbox", &g_settings.aimbot_hitbox, hitbox_items, 5)) {
current_hitbox = g_settings.aimbot_hitbox;
}
ImGui::Checkbox("Auto Shoot", &g_settings.aimbot_autoshoot);
ImGui::Checkbox("Silent Aim", &g_settings.aimbot_silent);
ImGui::Checkbox("No Recoil", &g_settings.aimbot_norecoil);
ImGui::Checkbox("Recoil Compensation", &g_settings.aimbot_recoil_comp);
ImGui::Checkbox("Shoot Teammates", &g_settings.aimbot_team_attack);
ImGui::Checkbox("Rage Mode", &g_settings.aimbot_rage_mode);
}
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;
if (ImGui::Combo("ESP", &esp_mode, esp_modes, 4)) {
g_settings.esp_mode = (esp_mode_t)esp_mode;
}
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);
ImGui::Checkbox("Custom Crosshair", &g_settings.custom_crosshair);
ImGui::Checkbox("Bullet Tracers", &g_settings.tracers);
ImGui::EndTabItem();
}
// Movement tab
if (ImGui::BeginTabItem("Movement")) {
ImGui::Checkbox("Bunny Hop", &g_settings.bhop);
ImGui::Checkbox("Auto Strafe", &g_settings.autostrafe);
ImGui::Checkbox("Anti-Aim", &g_settings.antiaim);
if (g_settings.antiaim) {
ImGui::Checkbox("Anti-Aim View", &g_settings.antiaim_view);
}
ImGui::Checkbox("Fake Duck", &g_settings.fakeduck);
ImGui::Checkbox("CL_Move", &g_settings.clmove);
ImGui::EndTabItem();
}
// Misc tab with extra options
if (ImGui::BeginTabItem("Misc")) {
ImGui::Checkbox("Name Changer", &g_settings.namechanger);
if (g_settings.namechanger) {
ImGui::SliderFloat("Name Change Speed", &g_settings.namechanger_speed, 1.0f, 50.0f, "%.1f");
}
ImGui::Checkbox("Watermark", &g_settings.watermark);
if (g_settings.watermark) {
ImGui::Checkbox("Rainbow Watermark", &g_settings.watermark_rainbow);
}
ImGui::Separator();
// Menu options
ImGui::Text("Menu Settings:");
ImGui::Checkbox("Allow Movement (WASD) With Menu Open", &g_settings.menu_allow_movement);
ImGui::Separator();
if (ImGui::Button("Uninject Cheat", ImVec2(150, 30))) {
i_engine->pfnClientCmd("dz_uninject");
g_menu_open = false;
}
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;
}
ImGui::SameLine();
if (ImGui::Button("270")) {
g_settings.thirdperson_dist = 270.0f;
}
ImGui::SameLine();
if (ImGui::Button("500")) {
g_settings.thirdperson_dist = 500.0f;
}
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;
case 'T': key_name = "T"; break;
case 'P': key_name = "P"; break;
case 'C': key_name = "C"; break;
case K_F1: key_name = "F1"; break;
case K_F2: key_name = "F2"; break;
case K_F3: key_name = "F3"; break;
case K_F4: key_name = "F4"; break;
case K_F5: key_name = "F5"; break;
case K_TAB: key_name = "Tab"; break;
case K_SPACE: key_name = "Space"; break;
case K_CTRL: key_name = "Ctrl"; break;
case K_SHIFT: key_name = "Shift"; break;
case K_ALT: key_name = "Alt"; break;
case K_MOUSE1: key_name = "Mouse1"; break;
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;
}
}
}
}
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;
}
// 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");
}
ImGui::Text("Note: Default binding is C key");
}
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
}
// Render ImGui
ImGui::Render();
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
} else {
render_fallback_menu();
}
}
// 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
// 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;
char buffer[128];
bool aimbot_enabled = g_settings.aimbot_enabled;
snprintf(buffer, sizeof(buffer), "- Aimbot: %s", aimbot_enabled ? "ON" : "OFF");
i_engine->pfnDrawConsoleString(x1+30, y, buffer);
y += 15;
if (aimbot_enabled) {
snprintf(buffer, sizeof(buffer), "- FOV: %.1f", g_settings.aimbot_fov);
i_engine->pfnDrawConsoleString(x1+30, y, buffer);
y += 15;
snprintf(buffer, sizeof(buffer), "- Smoothing: %.1f", g_settings.aimbot_smooth);
i_engine->pfnDrawConsoleString(x1+30, y, buffer);
y += 15;
}
y += 10;
i_engine->pfnDrawSetTextColor(0.0f, 1.0f, 1.0f);
i_engine->pfnDrawConsoleString(x1+20, y, "-- Visual Settings --");
y += 20;
int esp_mode = (int)g_settings.esp_mode;
snprintf(buffer, sizeof(buffer), "- ESP: %s", esp_mode > 0 ? "ON" : "OFF");
i_engine->pfnDrawConsoleString(x1+30, y, buffer);
y += 15;
bool chams_enabled = g_settings.chams;
snprintf(buffer, sizeof(buffer), "- Chams: %s", chams_enabled ? "ON" : "OFF");
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);
// 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
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;
return;
}
}
// 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;
i_engine->Con_Printf("Key binding canceled\n");
return;
}
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");
}
}
}

56
src/settings.c Normal file

@ -0,0 +1,56 @@
#include "include/settings.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/game_detection.h"
cheat_settings_t g_settings;
void settings_init(void) {
init_default_settings();
g_settings.thirdperson_key = 'C';
i_engine->Con_Printf("Settings initialized with defaults. Third-person key bound to C.\n");
}
void settings_reset(void) {
g_settings.esp_mode = ESP_OFF;
g_settings.esp_friendly = false;
g_settings.chams = false;
g_settings.tracers = false;
g_settings.custom_crosshair = false;
g_settings.watermark = false;
g_settings.watermark_rainbow = false;
g_settings.aimbot_enabled = false;
g_settings.aimbot_autoshoot = false;
g_settings.aimbot_silent = false;
g_settings.aimbot_norecoil = false;
g_settings.aimbot_recoil_comp = false;
g_settings.aimbot_friendly_fire = false;
g_settings.aimbot_rage_mode = false;
g_settings.aimbot_team_attack = false;
g_settings.bhop = false;
g_settings.autostrafe = false;
g_settings.antiaim = false;
g_settings.antiaim_view = false;
g_settings.fakeduck = false;
g_settings.clmove = false;
g_settings.namechanger = false;
g_settings.fov = 90.0f;
g_settings.thirdperson = false;
g_settings.thirdperson_key = 0;
g_settings.thirdperson_dist = 150.0f;
i_engine->pfnClientCmd("echo \"All cheat settings have been reset to default values\"");
}

@ -108,16 +108,16 @@ float vec_len2d(vec3_t v) {
return sqrtf(v.x * v.x + v.y * v.y);
}
void vec_clamp(vec3_t v) {
v.x = CLAMP(v.x, -89.0f, 89.0f);
v.y = CLAMP(remainderf(v.y, 360.0f), -180.0f, 180.0f); /* v.y % 360 */
v.z = CLAMP(v.z, -50.0f, 50.0f);
void ang_clamp(vec3_t* v) {
v->x = CLAMP(v->x, -89.0f, 89.0f);
v->y = CLAMP(remainderf(v->y, 360.0f), -180.0f, 180.0f);
v->z = CLAMP(v->z, -50.0f, 50.0f);
}
void vec_norm(vec3_t v) {
v.x = isfinite(v.x) ? remainder(v.x, 360) : 0;
v.y = isfinite(v.y) ? remainder(v.y, 360) : 0;
v.z = 0.0f;
void vec_norm(vec3_t* v) {
v->x = isfinite(v->x) ? remainderf(v->x, 360.f) : 0.f;
v->y = isfinite(v->y) ? remainderf(v->y, 360.f) : 0.f;
v->z = 0.0f;
}
float angle_delta_rad(float a, float b) {