Compare commits

...

75 Commits

Author SHA1 Message Date
1da95a4c35 Update weaponIds 2025-04-04 22:10:48 -04:00
40f014de59 Update aim.c, anti_aim.c, and no_recoil.c 2025-04-04 21:49:26 -04:00
0b9c748444 Update anti_aim.c, globals.c, and 7 more files... 2025-04-04 21:13:50 -04:00
dcdd090677 Update README.org 2025-04-04 20:08:19 -04:00
f885095c39 Update aim.c and no_recoil.c 2025-04-04 20:06:09 -04:00
51c3b979ea Update aim.c, settings.h, and 2 more files... 2025-04-04 18:55:08 -04:00
6a640a716c Update settings.h and settings.c 2025-04-04 18:50:09 -04:00
66b4abf888 Update menu.c 2025-04-04 18:48:52 -04:00
5bf0dfce70 Update Makefile, aim.c, and 4 more files... 2025-04-04 18:48:09 -04:00
cbea54c5ce Fire button 2025-04-04 18:24:27 -04:00
1d94704814 Update settings.c 2025-04-04 18:19:40 -04:00
2ca8c26f8f Less retarded 2025-04-04 18:15:03 -04:00
3fa74e6ab0 Update README.org 2025-04-04 17:35:27 -04:00
1ccab9d518 Default config 2025-04-04 17:27:31 -04:00
c5a0ec15e9 Update hooks.c, menu.h, and 3 more files... 2025-04-04 17:22:43 -04:00
07b05f02c4 Update thirdperson.c, hooks.c, and 3 more files... 2025-04-04 17:07:54 -04:00
0c63d7c969 Gigantic update with menu 2025-04-04 16:51:40 -04:00
e53e7c5d37 Add support for Space-Life 2024-01-23 01:45:59 -05:00
Wizzard
184e52dcbc Better temp CS1.6 tracer fix 2023-09-22 00:35:35 -04:00
Wizzard
3738e6cd7c Fix links 2023-09-21 15:08:13 -04:00
Wizzard
543c00e294 Added dz_visuals_fov 2023-09-21 15:00:14 -04:00
Wizzard
21d9cac264 Added invisible character & added 'dz_misc_namechanger_speed' 2023-09-21 12:33:22 -04:00
Wizzard
8a5b96505b Added basic namechanger 'dz_misc_namechanger' 2023-09-21 12:16:03 -04:00
Wizzard
72dc42006f Updated util.c 2023-09-21 02:31:39 -04:00
Wizzard
1c4bc57713 Formatting fixes 2023-09-21 02:30:31 -04:00
Wizzard
d9339d0d5a Small esp update 2023-09-21 02:30:15 -04:00
Wizzard
44e5dc34c0 DOD specific aiming 2023-09-21 00:12:50 -04:00
Wizzard
17b4e4e3a3 Fakeduck always when holding space 2023-09-20 23:58:54 -04:00
Wizzard
0b0664e4cf More advanced antiaim, also added fakeduck 2023-09-20 23:43:31 -04:00
Wizzard
d3b6c64003 More advanced antiaim, also added fakeduck 2023-09-20 23:42:41 -04:00
Wizzard
f93a21ce16 Stop anti-aim on attack and use 2023-09-20 23:19:16 -04:00
Wizzard
87208744e1 Anti aim fixed 2023-09-20 23:10:57 -04:00
Wizzard
f7fc075c4a Modified aim.c 2023-09-20 22:51:43 -04:00
Wizzard
f26da3e84f Added back aim_autoshoot 2023-09-20 22:47:45 -04:00
Wizzard
e440b15a9d Adjust aim for 1.6 2023-09-20 21:11:07 -04:00
Wizzard
1d99e0758a Fix non silent aim missing it's first shot 2023-09-20 20:37:29 -04:00
Wizzard
9a109b3882 Updated silent aim 2023-09-20 20:34:38 -04:00
Wizzard
36459f0d6a Updated aim.c 2023-09-20 20:22:25 -04:00
Wizzard
3bd0fe52da Added anti-aim 'dz_movement_antiaim' and 'dz_movement_antiaim_view' 2023-09-20 19:40:32 -04:00
Wizzard
88bdad24b1 Fixed aimbot for CS1.6 2023-09-20 17:49:26 -04:00
Wizzard
a898563249 Remove get_cur_game and references to it 2023-09-20 15:50:57 -04:00
Wizzard
2401ecf71e Updated README again, I might be retarded 2023-09-20 15:06:00 -04:00
4b54871340 Credits 2023-09-20 19:03:32 +00:00
Wizzard
a09d80fbfa Readme fix 2023-09-20 14:53:39 -04:00
Wizzard
7fc0a14ae6 Added dz_visuals_friendly to not render friendly players. Change all cvars to a new format. 2023-09-20 14:51:49 -04:00
Wizzard
7239d610a8 Renamed 'dz_silent_aim' to 'dz_aimbot_silent_aim' 2 2023-09-20 10:33:34 -04:00
Wizzard
3aaf7c8346 Renamed 'dz_silent_aim' to 'dz_aimbot_silent_aim' 2023-09-20 10:32:49 -04:00
Wizzard
a5234c16a3 Replaced original arthurs game detection code. Fixed aimbot shooting teamates and chams. 2023-09-20 10:28:08 -04:00
Wizzard
f38678d727 Added cvar 'dz_silent_aim' 2023-09-20 09:59:07 -04:00
Wizzard
e43cea56f8 Updated aim.c 2023-09-20 09:17:50 -04:00
Wizzard
c5e985bc42 Deathmatch classic support 2023-09-20 08:46:08 -04:00
Wizzard
c1ff555e17 Add sounds on injection 2023-09-19 18:54:15 -04:00
Wizzard
b7bac66484 Disable tracers by default on CS1.6 2023-09-19 18:19:04 -04:00
Wizzard
a688d94e9d Rainbow watermark + cvar dz_watermark_rainbow 2023-09-19 16:41:13 -04:00
Wizzard
deccfca8e3 Faster Bhop 2023-09-19 16:29:37 -04:00
Wizzard
b29f71e597 Dirty temp fix for tracers in CS1.6 2023-09-19 14:46:59 -04:00
Wizzard
c7ee48dfa6 Added game by game detection to help fix certain issues with specific games 2023-09-19 13:16:13 -04:00
Wizzard
a7b30ca7f8 Note about watermark 2023-09-19 11:54:58 -04:00
Wizzard
1f3e531610 Revert "Fix cvars not showing up"
This reverts commit 0e7f955c7d55a996e8d3f5b3056e4ed4204e9871.
2023-09-19 10:55:51 -04:00
Wizzard
0e7f955c7d Fix cvars not showing up 2023-09-19 10:54:04 -04:00
Wizzard
f0485a3f36 Change cvar from 'cv_' to 'dz_' 2023-09-19 10:45:57 -04:00
Wizzard
02888c1158 Fix links 2023-09-19 10:42:56 -04:00
Wizzard
b9851de177 Fix readme 2023-09-19 10:40:05 -04:00
Wizzard
56f8ae79d7 Added cv_watermark 2023-09-19 10:38:01 -04:00
8dcc
f9db9ff1b6 Change value of cl_forwardspeed 2023-08-05 00:50:28 +02:00
8dcc
29a40f63da Add missing unload to include 2023-08-01 19:53:43 +02:00
8dcc
b7c6e74dd4 README - Add supported games 2023-08-01 13:35:36 +02:00
8dcc
510243c46d Add can_shoot to aimbot 2023-07-31 20:57:25 +02:00
8dcc
fb6ed02dd4 Add clip check to can_shoot 2023-07-31 20:10:45 +02:00
8dcc
42a7961142 Store clip from HUD_PostRunCmd 2023-07-31 20:10:27 +02:00
8dcc
da6cf86910 README - Add autoshoot to features 2023-07-31 18:06:21 +02:00
8dcc
3414d131f4 Add autoshoot
If this cvar is enabled (1), and the aimbot is enabled (fov>0), it will
stop attacking if there is no visible target.
2023-07-31 18:03:26 +02:00
8dcc
83278b9983 Change head offset if crouched 2023-07-31 18:03:14 +02:00
8dcc
4bb21a4ca6 Fix fov calculations, fix aimbot head offset 2023-07-31 17:40:01 +02:00
8dcc
51c302f492 Add alive check to localplayer 2023-07-31 16:10:47 +02:00
50 changed files with 56050 additions and 399 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/esp.c.o obj/features/chams.c.o obj/features/aim.c.o obj/features/misc.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/features/no_recoil.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)

@ -1,14 +1,24 @@
#+title: Half-Life cheat
#+title: Half-Life cheat (Original author: [[https://github.com/8dcc/][8dcc]])
#+options: toc:nil
#+startup: showeverything
#+author: 8dcc
#+author: Wizzard
*Linux cheat for Half-Life 1 (and goldsrc).*
*Linux cheat for goldsrc games.*
#+TOC: headlines 2
* WARNING
TO USE THIS YOU MUST BE RUNNING THE LEGACY BETA
* Description
Simple linux cheat for Half-Life 1 (and most /goldsrc/ games) made in C.
Simple linux cheat for most goldsrc games, made in C.
Supported games:
- [[https://store.steampowered.com/app/70/HalfLife/][Half-Life 1]]
- [[https://store.steampowered.com/app/10/CounterStrike/][Counter-Strike 1.6]]
- [[https://store.steampowered.com/app/20/Team_Fortress_Classic/][Team Fortress Classic]]
- [[https://store.steampowered.com/app/30/Day_of_Defeat/][Day of Defeat]]
- [[https://store.steampowered.com/app/40/Deathmatch_Classic/][Deathmatch Classic]]
This project was heavily inspired by [[https://github.com/UnkwUsr/hlhax][UnkwUsr/hlhax]], and would not have been
possible without his help. Make sure to check out his repo too.
@ -17,16 +27,39 @@ Also make sure to check out [[https://github.com/deboogerxyz/ahc][deboogerxyz/ah
* Features
| Feature | Command | Values (0..n) |
|------------+---------------+------------------------|
| Bhop | =cv_bhop= | off/on |
| Autostrafe | =cv_autostrafe= | off/rage/legit |
| Aimbot | =cv_aimbot= | off/fov* |
| ESP | =cv_esp= | off/3d-box/name/all |
| Chams | =cv_chams= | off/players/hands/all* |
| Crosshair | =cv_crosshair= | off/length |
| Tracers | =cv_tracers= | off/on* |
| Feature | Description |
|-------------|-----------------------------------|
| Bhop | Automatically jump when landing |
| Autostrafe | Automatic strafing movement |
| Aimbot | Aim assistance with FOV control |
| Autoshoot | Automatically shoot at enemies |
| ESP | See enemies through walls |
| Chams | Colored player models |
| Crosshair | Custom crosshair |
| Tracers | Show bullet paths |
| Namechanger | Automatically change player name |
| ThirdPerson | Third-person camera view |
#+begin_quote
*Note:* All features can now be controlled via the ImGui menu (press INSERT to open).
#+end_quote
* GUI Menu
The cheat includes a full graphical user interface that can be opened by pressing the *INSERT* key. The menu includes several tabs:
- *Aimbot:* Configure aimbot settings including FOV, smoothing, and autoshoot
- *Visuals:* ESP, chams, crosshair and other visual enhancements
- *Misc:* Various utilities including name changer
- *Movement:* Bunny hop and auto-strafe settings
- *ThirdPerson:* Configure third-person camera view and key binding
- *Config:* Save and load configurations, set default settings
Key features of the menu:
- Press INSERT to toggle the menu on/off
- Settings are automatically saved to =~/.config/dz-goldsrccheat/=
- Default settings can be saved and will automatically load on startup
- Bind custom keys for features like third-person toggle
#+begin_quote
*Note:* Aimbot FOV goes from 0 (off) to 180 (all enemies)
@ -34,19 +67,19 @@ Also make sure to check out [[https://github.com/deboogerxyz/ahc][deboogerxyz/ah
#+begin_quote
*Note:* Chams color can be changed from the =h_glColor4f()= function inside
[[https://github.com/8dcc/hl-cheat/blob/main/src/hooks.c][src/hooks.c]]. Since this cheat is not hard to compile, I rather have less
[[https://git.deadzone.lol/Wizzard/goldsrc-cheat/src/branch/main/src/hooks.c][src/hooks.c]]. Since this cheat is not hard to compile, I rather have less
console variables than more customization at runtime.
#+end_quote
#+begin_quote
*Note:* Bullet tracer color, width and time can be changed at the bottom of the
=bullet_tracers()= function inside [[https://github.com/8dcc/hl-cheat/blob/main/src/features/misc.c][src/features/misc.c]]. See previous chams note.
=bullet_tracers()= function inside [[https://git.deadzone.lol/Wizzard/goldsrc-cheat/src/branch/main/src/features/misc.c][src/features/misc.c]]. See previous chams note.
#+end_quote
* Building
#+begin_src console
$ git clone --recurse-submodules https://github.com/8dcc/hl-cheat
$ cd hl-cheat
$ git clone --recurse-submodules https://git.deadzone.lol/Wizzard/goldsrc-cheat
$ cd goldsource-cheat
$ make
...
#+end_src
@ -55,7 +88,7 @@ Note that you will need to clone with =--recurse-submodules= for the sdk. If you
have already cloned it, you can just:
#+begin_src console
$ cd hl-cheat
$ cd goldsource-cheat
$ git submodule update --init --recursive
#+end_src
@ -68,5 +101,5 @@ $ ./injector.sh
...
hl-cheat loaded!
goldsource-cheat loaded!
#+end_src

BIN
default.cfg Normal file

Binary file not shown.

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."

@ -30,7 +30,7 @@ if [ "$1" == "unload" ]; then
fi
if grep -q "$libpath" "/proc/$pid/maps"; then
echo -e "hl-cheat already loaded. Reloading...\n";
echo -e "goldsource-cheat already loaded. Reloading...\n";
# 0x2 -> RTLD_NOW
# 0x6 -> RTLD_LAZY | RTLD_NOLOAD

@ -1,26 +0,0 @@
#include "include/cvars.h"
#include "include/sdk.h"
#include "include/globals.h"
DECL_CVAR(bhop);
DECL_CVAR(autostrafe);
DECL_CVAR(aimbot);
DECL_CVAR(esp);
DECL_CVAR(chams);
DECL_CVAR(crosshair);
DECL_CVAR(tracers);
DECL_CVAR(clmove);
bool cvars_init(void) {
REGISTER_CVAR(bhop, 1);
REGISTER_CVAR(autostrafe, 0);
REGISTER_CVAR(aimbot, 0);
REGISTER_CVAR(esp, 3);
REGISTER_CVAR(chams, 1);
REGISTER_CVAR(crosshair, 0);
REGISTER_CVAR(tracers, 0);
REGISTER_CVAR(clmove, 0);
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,101 +1,417 @@
#include <math.h>
#include <string.h>
#include "features.h"
#include "../include/sdk.h"
#include "../include/cvars.h"
#include "../include/util.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 HEAD_OFFSET 0.8f
#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 bool is_visible(vec3_t start, vec3_t end) {
/* Syntax: PM_TraceLine(start, end, flags, usehulll, ignore_pe); */
pmtrace_t* tr =
i_engine->PM_TraceLine(start, end, PM_TRACELINE_PHYSENTSONLY, 2, -1);
#define SMOOTHING_FACTOR 3.0f
/* We didn't hit a valid entity */
if (tr->ent <= 0)
#define PITCH 0
#define YAW 1
#define ROLL 2
#define PRIORITY_NONE 0
#define PRIORITY_LOW 1
#define PRIORITY_MEDIUM 2
#define PRIORITY_HIGH 3
// Weapon IDs
#define WEAPON_GLOCK 17
#define WEAPON_DEAGLE 26
#define WEAPON_AK47 28
#define WEAPON_M4A1 22
#define WEAPON_AWP 33
extern const char* hitbox_options[];
extern int current_hitbox;
const char* hitbox_names[] = {
"Head",
"Chest",
"Stomach",
"Pelvis",
"Nearest Point"
};
int current_hitbox = HITBOX_HEAD;
typedef struct {
vec3_t mins;
vec3_t maxs;
vec3_t origin;
float radius;
} hitbox_t;
bool get_hitbox(cl_entity_t* ent, int hitbox_id, hitbox_t* out_hitbox) {
if (!ent || !out_hitbox) {
return false;
}
/* Get entity index from physents, check if we can't get a valid player */
const int ent_idx = i_pmove->physents[tr->ent].info;
if (!get_player(ent_idx))
out_hitbox->radius = 5.0f;
bool is_ak47 = (g_currentWeaponID == WEAPON_AK47);
studiohdr_t* studio = NULL;
if (ent->model) {
studio = (studiohdr_t*)i_enginestudio->Mod_Extradata(ent->model);
}
switch (hitbox_id) {
case 0: {
vec3_t view_offset;
view_offset.x = 0.0f;
view_offset.y = 0.0f;
if (is_ak47) {
view_offset.z = 26.0f;
} else {
view_offset.z = 27.0f;
}
out_hitbox->origin = vec_add(ent->origin, view_offset);
out_hitbox->radius = 7.0f;
vec3_t head_offset;
head_offset.x = 0.0f;
head_offset.y = 0.0f;
head_offset.z = 0.0f;
if (is_ak47) {
head_offset.z = -1.0f;
}
out_hitbox->origin = vec_add(out_hitbox->origin, head_offset);
static int debug_counter = 0;
if (debug_counter++ % 500 == 0) {
i_engine->Con_Printf("Head hitbox: Origin(%.1f,%.1f,%.1f) Radius(%.1f) WeaponID: %d\n",
out_hitbox->origin.x, out_hitbox->origin.y, out_hitbox->origin.z,
out_hitbox->radius, g_currentWeaponID);
}
return true;
}
case 1: {
vec3_t chest_offset;
chest_offset.x = 0.0f;
chest_offset.y = 0.0f;
chest_offset.z = 18.0f;
out_hitbox->origin = vec_add(ent->origin, chest_offset);
out_hitbox->radius = 10.0f;
return true;
}
case 2: {
vec3_t stomach_offset;
stomach_offset.x = 0.0f;
stomach_offset.y = 0.0f;
stomach_offset.z = 12.0f;
out_hitbox->origin = vec_add(ent->origin, stomach_offset);
out_hitbox->radius = 9.0f;
return true;
}
case 3: {
vec3_t pelvis_offset;
pelvis_offset.x = 0.0f;
pelvis_offset.y = 0.0f;
pelvis_offset.z = 6.0f;
out_hitbox->origin = vec_add(ent->origin, pelvis_offset);
out_hitbox->radius = 8.0f;
return true;
}
default:
if (is_ak47) {
vec3_t fallback_offset;
fallback_offset.x = 0.0f;
fallback_offset.y = 0.0f;
fallback_offset.z = 20.0f;
out_hitbox->origin = vec_add(ent->origin, fallback_offset);
} else {
vec3_t fallback_offset;
fallback_offset.x = 0.0f;
fallback_offset.y = 0.0f;
fallback_offset.z = 25.0f;
out_hitbox->origin = vec_add(ent->origin, fallback_offset);
}
out_hitbox->radius = 8.0f;
return true;
}
}
bool is_hitbox_visible(vec3_t eye_pos, hitbox_t* hitbox) {
if (!hitbox)
return false;
/* We hit a valid player */
pmtrace_t* trace = i_engine->PM_TraceLine(eye_pos, hitbox->origin, PM_TRACELINE_PHYSENTSONLY, 2, -1);
static int trace_debug = 0;
if (trace_debug++ % 500 == 0) {
printf("Trace: fraction=%.3f, ent=%d\n", trace->fraction, trace->ent);
}
if (trace->fraction < 0.9f) {
if (trace->ent <= 0) {
return false;
}
const int ent_idx = i_pmove->physents[trace->ent].info;
cl_entity_t* hit_entity = get_player(ent_idx);
if (hit_entity) {
return true;
}
return false;
}
return true;
}
static vec3_t get_closest_delta(vec3_t viewangles) {
/* Compensate aim punch. We get g_punchAngles from CalcRefdef hook */
viewangles.x += g_punchAngles.x * AIM_PUNCH_MULT;
viewangles.y += g_punchAngles.y * AIM_PUNCH_MULT;
viewangles.z += g_punchAngles.z * AIM_PUNCH_MULT;
typedef struct {
cl_entity_t* entity;
float fov;
vec3_t aim_point;
bool is_visible;
int priority;
float distance;
} target_t;
vec3_t view_height;
i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height);
vec3_t local_eyes = vec_add(localplayer->origin, view_height);
/* These 2 vars are used to store the best target across iterations.
* NOTE: The default value of best_fov will be the aimbot fov */
float best_fov = cv_aimbot->value;
vec3_t best_delta = { 0, 0, 0 };
int get_target_priority(cl_entity_t* ent) {
if (!ent)
return PRIORITY_NONE;
return PRIORITY_MEDIUM;
}
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;
for (int i = 1; i <= i_engine->GetMaxClients(); i++) {
cl_entity_t* ent = get_player(i);
if (!is_alive(ent) || is_friend(ent))
if (!ent || !is_alive(ent))
continue;
/* TODO: Get bones origin instead of calculating from ent origin */
const vec3_t head_pos = vec_add(ent->origin, vec3(0, 0, HEAD_OFFSET));
if (!is_visible(local_eyes, head_pos)) /* We can't see player */
if (!g_settings.aimbot_team_attack && is_friend(ent))
continue;
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;
hitbox_t target_hitbox;
bool hitbox_found = false;
if (current_hitbox == HITBOX_NEAREST) {
const int hitbox_priority[] = {HITBOX_HEAD, HITBOX_CHEST, HITBOX_STOMACH, HITBOX_PELVIS};
for (int h = 0; h < 4; h++) {
if (get_hitbox(ent, hitbox_priority[h], &target_hitbox)) {
if (is_hitbox_visible(eye_pos, &target_hitbox)) {
hitbox_found = true;
break;
}
}
}
} else {
hitbox_found = get_hitbox(ent, current_hitbox, &target_hitbox);
if (hitbox_found) {
hitbox_found = is_hitbox_visible(eye_pos, &target_hitbox);
}
}
if (fov < best_fov) {
best_fov = fov;
vec_copy(best_delta, delta);
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);
int priority = get_target_priority(ent);
float priority_score = priority / (float)PRIORITY_HIGH;
float distance_score = 1.0f - fmin(1.0f, distance / 3000.0f);
float final_score = (fov_score * 0.6f) + (priority_score * 0.3f) + (distance_score * 0.1f);
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 = priority;
best_target.distance = distance;
}
}
return best_delta;
return best_target;
}
#define RECOIL_DETECTION_MULT 1.0f
#define RECOIL_DECAY_RATE 0.5f
static vec3_t s_last_viewangles = {0, 0, 0};
static vec3_t s_punch_angles = {0, 0, 0};
static int s_firing_frames = 0;
void aimbot(usercmd_t* cmd) {
if (!CVAR_ON(aimbot) || !(cmd->buttons & IN_ATTACK))
if (!g_settings.aimbot_enabled)
return;
/* Calculate delta with the engine viewangles, not with the cmd ones */
if (!is_alive(localplayer))
return;
if (g_settings.aimbot_require_key && !(cmd->buttons & IN_ATTACK))
return;
bool can_fire = g_flCurrentTime >= g_flNextPrimaryAttack;
vec3_t eye_pos;
vec_copy(eye_pos, localplayer->origin);
eye_pos.z += 28.0f;
vec3_t viewangles;
i_engine->GetViewAngles(viewangles);
static int shot_count = 0;
static float last_shot_time = 0.0f;
if (cmd->buttons & IN_ATTACK) {
if (g_flCurrentTime - last_shot_time > 0.08f) {
shot_count++;
last_shot_time = g_flCurrentTime;
if (shot_count % 5 == 0) {
i_engine->Con_Printf("Shot counter: %d shots in spray\n", shot_count);
}
}
} else {
if (g_flCurrentTime - last_shot_time > 0.25f) {
if (shot_count > 3) {
i_engine->Con_Printf("Reset shot counter from %d\n", shot_count);
}
shot_count = 0;
}
}
if (cmd->buttons & IN_ATTACK) {
if (g_currentWeaponID == WEAPON_AK47) {
viewangles.x -= g_punchAngles[0] * 1.2f;
viewangles.y -= g_punchAngles[1] * 0.8f;
if (shot_count >= 3) {
float extra_comp = CLAMP((shot_count - 2) * 0.3f, 0.0f, 3.0f);
viewangles.x -= extra_comp;
if (shot_count % 5 == 0) {
i_engine->Con_Printf("AK-47 Extra comp: %.1f degrees down\n", extra_comp);
}
}
} else {
viewangles.x -= g_punchAngles[0] * 0.6f;
viewangles.y -= g_punchAngles[1] * 0.4f;
}
}
target_t best_target = get_best_target(viewangles, eye_pos);
if (!best_target.entity) {
return;
}
vec3_t aim_direction = vec_sub(best_target.aim_point, eye_pos);
vec3_t aim_angles = vec_to_ang(aim_direction);
if (g_currentWeaponID == WEAPON_AK47) {
if (shot_count > 0) {
float ak_compensation = CLAMP(shot_count * 0.25f, 0.0f, 6.0f);
aim_angles.x -= ak_compensation;
if (shot_count % 5 == 0) {
i_engine->Con_Printf("AK-47 aim adjust: Shot %d, Aiming %.1f lower\n",
shot_count, ak_compensation);
}
}
}
vec3_t engine_viewangles;
i_engine->GetViewAngles(engine_viewangles);
/* TODO: Add setting for lowest health */
vec3_t best_delta = get_closest_delta(engine_viewangles);
if (!vec_is_zero(best_delta)) {
/* NOTE: We can divide the best delta here to add smoothing */
engine_viewangles.x += best_delta.x;
engine_viewangles.y += best_delta.y;
engine_viewangles.z += best_delta.z;
if (g_settings.aimbot_smoothing_enabled && !g_settings.aimbot_silent) {
vec3_t delta;
delta.x = aim_angles.x - engine_viewangles.x;
delta.y = aim_angles.y - engine_viewangles.y;
delta.z = 0.0f;
if (delta.y > 180.0f) delta.y -= 360.0f;
if (delta.y < -180.0f) delta.y += 360.0f;
float smooth_factor = g_settings.aimbot_smooth;
if (g_currentWeaponID == WEAPON_AK47 && shot_count > 1) {
smooth_factor *= 0.7f;
}
if (best_target.fov < g_settings.aimbot_fov * 0.5f) {
smooth_factor *= 0.6f;
}
if (smooth_factor < 1.0f) smooth_factor = 1.0f;
vec3_t smooth_angles;
smooth_angles.x = engine_viewangles.x + delta.x / smooth_factor;
smooth_angles.y = engine_viewangles.y + delta.y / smooth_factor;
smooth_angles.z = 0.0f;
ang_clamp(&smooth_angles);
engine_viewangles = smooth_angles;
i_engine->SetViewAngles(engine_viewangles);
}
else if (g_settings.aimbot_silent) {
vec_copy(cmd->viewangles, aim_angles);
}
else {
engine_viewangles = aim_angles;
i_engine->SetViewAngles(engine_viewangles);
}
vec_copy(cmd->viewangles, engine_viewangles);
/* NOTE: Uncomment to disable silent aim */
/* i_engine->SetViewAngles(engine_viewangles); */
}
if (g_settings.aimbot_autoshoot && best_target.is_visible && can_fire) {
cmd->buttons |= IN_ATTACK;
}
}

323
src/features/anti_aim.c Normal file

@ -0,0 +1,323 @@
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include "features.h"
#include "../include/sdk.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/globals.h"
#define AA_PITCH_NONE 0
#define AA_PITCH_DOWN 1
#define AA_PITCH_UP 2
#define AA_PITCH_ZERO 3
#define AA_PITCH_JITTER 4
#define AA_PITCH_CUSTOM 5
#define AA_YAW_NONE 0
#define AA_YAW_BACKWARD 1
#define AA_YAW_SPIN 2
#define AA_YAW_JITTER 3
#define AA_YAW_SIDEWAYS 4
#define AA_YAW_CUSTOM 5
static float spin_angle = 0.0f;
static float last_update_time = 0.0f;
static float jitter_next_update = 0.0f;
float random_float(float min, float max) {
return (max - min) * ((float)rand() / (float)RAND_MAX) + min;
}
bool isSpacebarPressed() {
Display* display = XOpenDisplay(NULL);
if (!display) {
return false;
}
char keys_return[32];
XQueryKeymap(display, keys_return);
KeyCode kc = XKeysymToKeycode(display, XK_space);
bool pressed = (keys_return[kc >> 3] & (1 << (kc & 7))) != 0;
XCloseDisplay(display);
return pressed;
}
bool is_key_pressed(int key_code) {
if (key_code <= 0) {
return false;
}
Display* display = XOpenDisplay(NULL);
if (!display) {
return false;
}
char keys_return[32];
XQueryKeymap(display, keys_return);
KeyCode kc;
if (key_code >= 'A' && key_code <= 'Z') {
kc = XKeysymToKeycode(display, XK_a + (key_code - 'A'));
} else if (key_code >= 'a' && key_code <= 'z') {
kc = XKeysymToKeycode(display, XK_a + (key_code - 'a'));
} else {
switch (key_code) {
case K_SPACE: kc = XKeysymToKeycode(display, XK_space); break;
case K_CTRL: kc = XKeysymToKeycode(display, XK_Control_L); break;
case K_SHIFT: kc = XKeysymToKeycode(display, XK_Shift_L); break;
case K_ALT: kc = XKeysymToKeycode(display, XK_Alt_L); break;
case K_TAB: kc = XKeysymToKeycode(display, XK_Tab); break;
default: kc = XKeysymToKeycode(display, key_code);
}
}
bool pressed = (keys_return[kc >> 3] & (1 << (kc & 7))) != 0;
XCloseDisplay(display);
return pressed;
}
void apply_pitch_anti_aim(vec3_t* view_angles, int pitch_mode, float custom_pitch) {
switch (pitch_mode) {
case AA_PITCH_DOWN:
view_angles->x = 89.0f;
break;
case AA_PITCH_UP:
view_angles->x = -89.0f;
break;
case AA_PITCH_ZERO:
view_angles->x = 0.0f;
break;
case AA_PITCH_JITTER: {
static bool flip_pitch = false;
if (flip_pitch) {
view_angles->x = 89.0f;
} else {
view_angles->x = -89.0f;
}
if (g_flCurrentTime > jitter_next_update) {
flip_pitch = !flip_pitch;
jitter_next_update = g_flCurrentTime + random_float(0.1f, 0.3f);
}
break;
}
case AA_PITCH_CUSTOM:
view_angles->x = CLAMP(custom_pitch, -89.0f, 89.0f);
break;
default:
break;
}
}
void apply_yaw_anti_aim(vec3_t* view_angles, int yaw_mode, float custom_yaw, float speed, float jitter_range) {
float time_now;
float time_delta;
static bool is_left = true;
switch (yaw_mode) {
case AA_YAW_BACKWARD:
view_angles->y += 180.0f;
break;
case AA_YAW_SPIN:
time_now = g_flCurrentTime;
time_delta = time_now - last_update_time;
spin_angle += time_delta * speed;
if (spin_angle > 360.0f) {
spin_angle -= 360.0f;
}
view_angles->y = spin_angle;
last_update_time = time_now;
break;
case AA_YAW_JITTER:
if (g_flCurrentTime > jitter_next_update) {
view_angles->y += random_float(-jitter_range, jitter_range);
jitter_next_update = g_flCurrentTime + random_float(0.1f, 0.3f);
}
break;
case AA_YAW_SIDEWAYS:
if (g_flCurrentTime > jitter_next_update) {
is_left = !is_left;
jitter_next_update = g_flCurrentTime + random_float(0.5f, 1.5f);
}
if (is_left) {
view_angles->y += 90.0f;
} else {
view_angles->y -= 90.0f;
}
break;
case AA_YAW_CUSTOM:
view_angles->y = custom_yaw;
break;
default:
break;
}
}
void apply_lby_breaker(vec3_t* view_angles, bool enable_breaker) {
if (!enable_breaker)
return;
static bool lby_update = false;
static float next_lby_update = 0.0f;
if (g_flCurrentTime > next_lby_update) {
lby_update = !lby_update;
next_lby_update = g_flCurrentTime + 1.1f;
if (lby_update) {
view_angles->y += 120.0f;
}
}
}
void apply_fake_duck(usercmd_t* cmd, bool enable_duck) {
if (!enable_duck)
return;
static int duck_state = 0;
static float next_duck_time = 0.0f;
if (g_flCurrentTime > next_duck_time) {
duck_state = (duck_state + 1) % 4;
next_duck_time = g_flCurrentTime + 0.05f;
}
if (duck_state < 2) {
cmd->buttons |= IN_DUCK;
} else {
cmd->buttons &= ~IN_DUCK;
}
}
void anti_aim(usercmd_t* cmd) {
if (!g_settings.antiaim_enabled) {
return;
}
if (!is_alive(localplayer)) {
return;
}
if ((cmd->buttons & IN_ATTACK) && !g_settings.antiaim_on_attack) {
return;
}
if (cmd->buttons & IN_USE) {
return;
}
vec3_t view_angles;
i_engine->GetViewAngles(view_angles);
if (g_settings.antiaim_pitch_enabled) {
if (g_settings.antiaim_pitch_mode == 0) {
view_angles.x = g_settings.antiaim_pitch;
view_angles.x = CLAMP(view_angles.x, -89.0f, 89.0f);
} else {
apply_pitch_anti_aim(&view_angles, g_settings.antiaim_pitch_mode, g_settings.antiaim_custom_pitch);
}
static float last_debug_time = 0.0f;
if (g_flCurrentTime > last_debug_time + 5.0f) {
i_engine->Con_Printf("Anti-Aim: Applied pitch angle %.1f (mode %d)\n",
view_angles.x, g_settings.antiaim_pitch_mode);
last_debug_time = g_flCurrentTime;
}
}
if (g_settings.antiaim_yaw_enabled) {
if (g_settings.antiaim_yaw_mode == 0) {
if (g_settings.antiaim_legit) {
float legit_yaw_max = 35.0f;
view_angles.y += CLAMP(g_settings.antiaim_yaw, -legit_yaw_max, legit_yaw_max);
} else {
view_angles.y += g_settings.antiaim_yaw;
}
} else {
apply_yaw_anti_aim(&view_angles, g_settings.antiaim_yaw_mode, g_settings.antiaim_custom_yaw,
g_settings.antiaim_spin_speed, g_settings.antiaim_jitter_range);
}
if (view_angles.y > 180.0f) view_angles.y -= 360.0f;
if (view_angles.y < -180.0f) view_angles.y += 360.0f;
}
apply_lby_breaker(&view_angles, g_settings.antiaim_lby_breaker);
if (g_settings.antiaim_desync) {
static bool switch_side = false;
static float next_switch = 0.0f;
if (g_flCurrentTime > next_switch) {
switch_side = !switch_side;
next_switch = g_flCurrentTime + random_float(0.4f, 0.8f);
}
if (!g_settings.antiaim_view) {
vec3_t real_angles;
i_engine->GetViewAngles(real_angles);
vec3_t server_angles;
vec_copy(server_angles, real_angles);
server_angles.y += (switch_side ? 58.0f : -58.0f);
if (server_angles.y > 180.0f) server_angles.y -= 360.0f;
if (server_angles.y < -180.0f) server_angles.y += 360.0f;
vec_copy(cmd->viewangles, server_angles);
i_engine->SetViewAngles(real_angles);
static float last_desync_log = 0.0f;
if (g_flCurrentTime > last_desync_log + 3.0f) {
i_engine->Con_Printf("Desync active: Server %.1f, Client %.1f (invisible to user)\n",
server_angles.y, real_angles.y);
last_desync_log = g_flCurrentTime;
}
return;
}
float desync_amount = switch_side ? 58.0f : -58.0f;
view_angles.y += desync_amount;
if (view_angles.y > 180.0f) view_angles.y -= 360.0f;
if (view_angles.y < -180.0f) view_angles.y += 360.0f;
}
bool should_fake_duck = false;
if (g_settings.antiaim_fakeduck_key > 0) {
should_fake_duck = g_settings.antiaim_fakeduck && is_key_pressed(g_settings.antiaim_fakeduck_key);
} else {
should_fake_duck = g_settings.antiaim_fakeduck;
}
if (should_fake_duck) {
apply_fake_duck(cmd, true);
}
if (g_settings.antiaim_view) {
i_engine->SetViewAngles(view_angles);
} else {
vec_copy(cmd->viewangles, view_angles);
}
static float last_log_time = 0.0f;
if (g_flCurrentTime > last_log_time + 5.0f) {
i_engine->Con_Printf("Anti-Aim active: Pitch=%.1f, Yaw=%.1f, Mode=%d/%d\n",
view_angles.x, view_angles.y,
g_settings.antiaim_pitch_mode, g_settings.antiaim_yaw_mode);
last_log_time = g_flCurrentTime;
}
}

@ -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 = cv_chams->value == 5.0f ? 7 : cv_chams->value;
const int setting = g_settings.chams ? PLAYER_CHAMS : DISABLED;
if (setting == DISABLED)
return false;
@ -39,6 +38,9 @@ bool chams(void* this_ptr) {
const bool friendly = is_friend(ent);
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 */
glDisable(GL_TEXTURE_2D);

@ -1,17 +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 cv_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) {
/*
@ -98,38 +92,36 @@ static bool gl_draw2dbox(vec3_t o, int bh) {
}
void esp(void) {
const int setting = (int)cv_esp->value;
const int setting = g_settings.esp_mode;
if (setting == ESP_OFF)
return;
/* Iterate all clients */
for (int i = 1; i <= i_engine->GetMaxClients(); i++) {
cl_entity_t* ent = get_player(i);
if (!valid_player(ent) || !is_alive(ent) || vec_is_zero(ent->origin))
continue;
const int bh = (ent->curstate.usehull == 1) ? 44 : 70;
/* const int bw = 25; */
if (is_friend(ent) && !g_settings.esp_friendly)
continue;
int bh = 70;
if (IsDayOfDefeat()) {
bh = 76;
} else if (ent->curstate.usehull == 1) {
bh = 44;
}
/* If ESP_BOX is enabled, draw it. If it returns false, continue */
if (setting & ESP_BOX && !gl_draw2dbox(ent->origin, bh))
continue;
/* Rest of the loop is for name esp, if var is not enabled, continue */
if (!(setting & ESP_NAME))
continue;
/* Draw name on top of the player. */
vec3_t top = vec3(ent->origin.x, ent->origin.y, ent->origin.z + bh);
vec2_t s_top;
if (!world_to_screen(top, s_top))
continue;
/* TODO: Instead of -5px, center the player name to the player origin.
* I don't know how to get the text size before rendering. */
engine_draw_text(s_top[0] - 5, s_top[1] - 2, get_name(ent->index),
(rgb_t){ 255, 255, 255 });
vec3_t name_pos = vec3(ent->origin.x, ent->origin.y, ent->origin.z + bh + 5);
vec2_t s_name_pos;
if (world_to_screen(name_pos, s_name_pos)) {
engine_draw_text(s_name_pos[0] - 5, s_name_pos[1] - 2, get_name(ent->index), (rgb_t){ 255, 255, 255 });
}
}
}

@ -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 */
@ -29,8 +33,29 @@ bool chams(void* this_ptr);
/* src/features/aim.c */
void aimbot(usercmd_t* cmd);
/* src/features/no_recoil.c */
void no_recoil(usercmd_t* cmd);
/* src/features/misc.c */
void custom_crosshair(void);
void bullet_tracers(usercmd_t* cmd);
#endif /* FEATURES_H_ */
/* src/features/namechanger.c */
void check_namechanger_mode_and_execute(usercmd_t* cmd);
/* src/features/anti_aim.c */
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_ */

19
src/features/fov.c Normal file

@ -0,0 +1,19 @@
#include <stdio.h>
#include "../include/globals.h"
#include "../include/sdk.h"
#include "../include/util.h"
#include "../include/settings.h"
#include "features.h"
extern float* scr_fov_value;
void fov_adjust(usercmd_t* cmd) {
if (!scr_fov_value) {
printf("FOV ERROR: Check globals.c missing scr_fov_value.\n");
return;
}
if (g_settings.fov > 0) {
*scr_fov_value = g_settings.fov;
}
}

@ -1,12 +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(crosshair))
if (!g_settings.custom_crosshair)
return;
/* Get window size, and then the center. */
@ -14,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 = cv_crosshair->value;
const int len = 5;
const int gap = 1;
const float w = 1;
const rgb_t col = { 255, 255, 255 };
@ -30,16 +30,40 @@ void custom_crosshair(void) {
gl_drawline(mx + gap, my + gap, mx + gap + len, my + gap + len, w, col);
}
weapon_data_t g_currentWeapon;
static double lastTracerTime = 0;
static bool attackReleased = true;
void bullet_tracers(usercmd_t* cmd) {
/* Only draw if we are holding attack and we can shoot */
if (!CVAR_ON(tracers) || !(cmd->buttons & IN_ATTACK) || !can_shoot())
if (!g_settings.tracers || !is_alive(localplayer))
return;
if (IsCS16()) {
if (cmd->buttons & IN_ATTACK) {
if (!attackReleased) {
return;
}
attackReleased = false;
} else {
attackReleased = true;
return;
}
if (!can_shoot()) {
return;
}
}
else {
if (!(cmd->buttons & IN_ATTACK) || !can_shoot()) {
return;
}
}
/* Get player eye pos, start of tracer */
vec3_t view_height;
i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height);
vec3_t local_eyes = vec_add(localplayer->origin, view_height);
/* Get forward vector from viewangles */
vec3_t fwd;
i_engine->pfnAngleVectors(cmd->viewangles, fwd, NULL, NULL);

@ -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) {
@ -24,6 +23,8 @@ static void autostrafe_legit(usercmd_t* cmd) {
* https://github.com/deboogerxyz/ahc/blob/0492646e28dd7234a8cd431d37b152dc18a21b04/ahc.c#L201
* https://github.com/NullHooks/NullHooks/blob/535351569ca599cadd21a286d88098b6dc057a46/src/core/features/movement/bhop.cpp#L73
*/
static const float DEG2RAD_CACHED = M_PI / 180.0f;
static void autostrafe_rage(usercmd_t* cmd) {
if (i_pmove->movetype != MOVETYPE_WALK)
return;
@ -31,7 +32,7 @@ static void autostrafe_rage(usercmd_t* cmd) {
/* TODO: Get at runtime */
const float sv_airaccelerate = 10.0f;
const float sv_maxspeed = 320.0f;
const float cl_forwardspeed = 400.0f;
const float cl_forwardspeed = 425.0f;
const float cl_sidespeed = 400.0f;
float speed = vec_len2d(i_pmove->velocity);
@ -48,24 +49,22 @@ static void autostrafe_rage(usercmd_t* cmd) {
float best_delta = acosf(term);
/* Use engine viewangles in case we do something nasty with cmd's angles */
vec3_t viewangles;
i_engine->GetViewAngles(viewangles);
/* Get our desired angles and delta */
float yaw = DEG2RAD(viewangles.y);
float vel_dir = atan2f(i_pmove->velocity.y, i_pmove->velocity.x) - yaw;
float yaw = viewangles.y * DEG2RAD_CACHED;
float vel_dir = atan2f(i_pmove->velocity.y, i_pmove->velocity.x) - yaw;
float target_ang = atan2f(-cmd->sidemove, cmd->forwardmove);
float delta = angle_delta_rad(vel_dir, target_ang);
float delta = angle_delta_rad(vel_dir, target_ang);
float movedir = delta < 0 ? vel_dir + best_delta : vel_dir - best_delta;
cmd->forwardmove = cosf(movedir) * cl_forwardspeed;
cmd->sidemove = -sinf(movedir) * cl_sidespeed;
cmd->sidemove = -sinf(movedir) * cl_sidespeed;
}
void bhop(usercmd_t* cmd) {
if (!CVAR_ON(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)cv_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);
}
}
@ -101,18 +90,15 @@ void bhop(usercmd_t* cmd) {
* https://github.com/deboogerxyz/ahc/blob/0492646e28dd7234a8cd431d37b152dc18a21b04/ahc.c#L377
*/
void correct_movement(usercmd_t* cmd, vec3_t old_angles) {
float old_y = old_angles.y + (old_angles.y < 0 ? 360 : 0);
float new_y = cmd->viewangles.y + (cmd->viewangles.y < 0 ? 360 : 0);
float delta = (new_y < old_y) ? fabsf(new_y - old_y)
: 360 - fabsf(new_y - old_y);
delta = 360 - delta;
float delta_y = fmodf(cmd->viewangles.y - old_angles.y + 540.0f, 360.0f) - 180.0f; // Normalized delta in [-180, 180)
float delta_rad = delta_y * DEG2RAD_CACHED;
float delta_cos = cosf(delta_rad);
float delta_sin = sinf(delta_rad);
float forward = cmd->forwardmove;
float side = cmd->sidemove;
float side = cmd->sidemove;
cmd->forwardmove =
cos(DEG2RAD(delta)) * forward + cos(DEG2RAD(delta + 90)) * side;
cmd->sidemove =
sin(DEG2RAD(delta)) * forward + sin(DEG2RAD(delta + 90)) * side;
}
cmd->forwardmove = delta_cos * forward - delta_sin * side;
cmd->sidemove = delta_sin * forward + delta_cos * side;
}

106
src/features/namechanger.c Normal file

@ -0,0 +1,106 @@
#include <stdint.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include "features.h"
#include "../include/globals.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/game_detection.h"
static int change_counter = 0;
#define NAME_CHANGE_INTERVAL 10
static int last_name_idx = -1;
void change_name(const char* new_name) {
if (!new_name) return;
char command[256];
snprintf(command, sizeof(command), "name \"%s\u0315 \"", new_name);
i_engine->pfnClientCmd(command);
}
std::vector<char*> get_valid_names(bool (*filter)(cl_entity_t*)) {
int max_players = 32;
std::vector<char*> valid_names;
for (int i = 0; i < max_players; i++) {
cl_entity_t* ent = get_player(i);
if (!ent) continue;
if (!filter || filter(ent)) {
valid_names.push_back(get_name(i));
}
}
return valid_names;
}
void change_name_from_list(std::vector<char*>& names) {
if (names.empty()) return;
last_name_idx = (last_name_idx + 1) % names.size();
char* name = names[last_name_idx];
if (name) {
change_name(name);
printf("Changing name to: %s\n", name);
}
}
void change_name_teammates() {
auto names = get_valid_names(is_friend);
std::random_shuffle(names.begin(), names.end());
change_name_from_list(names);
}
void change_name_enemies() {
auto names = get_valid_names([](cl_entity_t* ent) -> bool {
return !is_friend(ent);
});
std::random_shuffle(names.begin(), names.end());
change_name_from_list(names);
}
void change_name_all_players() {
auto names = get_valid_names(nullptr);
std::random_shuffle(names.begin(), names.end());
change_name_from_list(names);
}
void change_name_based_on_mode(usercmd_t* cmd) {
if (!g_settings.namechanger) return;
if (++change_counter < g_settings.namechanger_speed) {
return;
}
change_counter = 0;
int mode = 3;
if (g_settings.namechanger) {
mode = 3;
}
switch (mode) {
case 1:
change_name_teammates();
break;
case 2:
change_name_enemies();
break;
case 3:
change_name_all_players();
break;
default:
break;
}
}
void check_namechanger_mode_and_execute(usercmd_t* cmd) {
if (!g_settings.namechanger) return;
change_name_based_on_mode(cmd);
}

186
src/features/no_recoil.c Normal file

@ -0,0 +1,186 @@
#include "../include/sdk.h"
#include "../include/settings.h"
#include "../include/util.h"
#include "../include/globals.h"
#include "../features/features.h"
#include <stdio.h>
#include <time.h>
static time_t last_log_time = 0;
static vec3_t last_punch = {0, 0, 0};
static vec3_t previous_viewangles = {0, 0, 0};
#define WEAPON_GLOCK 17
#define WEAPON_DEAGLE 26
#define WEAPON_AK47 28
#define WEAPON_M4A1 22
#define WEAPON_AWP 33
#define AK47_RECOIL_VERT_MULT 2.8f
#define AK47_RECOIL_HORIZ_MULT 0.9f
#define DEFAULT_RECOIL_VERT_MULT 2.0f
#define DEFAULT_RECOIL_HORIZ_MULT 0.6f
static float ak47_pattern[] = {
0.0f,
2.2f,
3.0f,
3.5f,
3.9f,
4.0f,
3.8f,
3.5f,
3.2f,
2.9f,
2.7f,
2.5f,
2.2f,
2.0f,
1.9f,
1.7f,
1.6f,
1.5f,
1.4f,
1.3f,
1.2f,
1.1f,
1.0f,
0.9f,
0.8f,
0.8f,
0.7f,
0.7f,
0.6f,
0.6f
};
static int bullet_count = 0;
static float last_shot_time = 0.0f;
static int current_weapon_id = -1;
void no_recoil(usercmd_t* cmd) {
if (!is_alive(localplayer) || (!g_settings.aimbot_norecoil && !g_settings.aimbot_recoil_comp)) {
return;
}
if (!(cmd->buttons & IN_ATTACK)) {
if (g_flCurrentTime - last_shot_time > 0.2f) {
if (bullet_count > 0) {
i_engine->Con_Printf("Recoil: Reset spray pattern from %d bullets\n", bullet_count);
bullet_count = 0;
}
}
return;
}
vec3_t current_viewangles;
i_engine->GetViewAngles(current_viewangles);
bool is_ak47 = false;
bool is_high_recoil_weapon = false;
if (g_currentWeaponID == WEAPON_AK47) {
is_ak47 = true;
is_high_recoil_weapon = true;
}
else if (g_currentWeaponID == WEAPON_M4A1) {
is_high_recoil_weapon = true;
}
else if (g_flNextPrimaryAttack - g_flNextAttack < 0.15f) {
is_high_recoil_weapon = true;
if (g_flNextPrimaryAttack - g_flNextAttack < 0.11f) {
is_ak47 = true;
}
}
last_shot_time = g_flCurrentTime;
static float last_attack_time = 0.0f;
bool is_new_shot = g_flCurrentTime - last_attack_time > 0.05f;
if (is_new_shot) {
bullet_count++;
last_attack_time = g_flCurrentTime;
if (bullet_count > 1 && (bullet_count % 3 == 0 || bullet_count <= 5)) {
i_engine->Con_Printf("Recoil comp: Shot #%d, Weapon: %s\n",
bullet_count, is_ak47 ? "AK-47" : (is_high_recoil_weapon ? "High Recoil" : "Standard"));
}
}
vec3_t punch_angles;
vec_copy(punch_angles, g_punchAngles);
float vert_mult = 0.0f;
float horiz_mult = 0.0f;
float pattern_compensation = 0.0f;
if (g_settings.aimbot_norecoil) {
if (is_ak47) {
vert_mult = AK47_RECOIL_VERT_MULT;
horiz_mult = AK47_RECOIL_HORIZ_MULT;
if (bullet_count > 0 && bullet_count <= 30) {
pattern_compensation = ak47_pattern[bullet_count-1] * 0.6f;
}
}
else if (is_high_recoil_weapon) {
vert_mult = 2.2f;
horiz_mult = 0.8f;
}
else {
vert_mult = 1.9f;
horiz_mult = 0.7f;
}
cmd->viewangles[0] -= (punch_angles[0] * vert_mult);
cmd->viewangles[1] -= (punch_angles[1] * horiz_mult);
if (pattern_compensation > 0) {
cmd->viewangles[0] -= pattern_compensation;
if (is_ak47 && bullet_count <= 5) {
i_engine->Con_Printf("AK-47 pattern comp: Shot #%d, Compensation: %.2f degrees\n",
bullet_count, pattern_compensation);
}
}
}
else if (g_settings.aimbot_recoil_comp) {
if (is_ak47) {
vert_mult = 2.0f;
horiz_mult = 0.7f;
if (bullet_count > 0 && bullet_count <= 30) {
pattern_compensation = ak47_pattern[bullet_count-1] * 0.35f;
}
}
else if (is_high_recoil_weapon) {
vert_mult = 1.7f;
horiz_mult = 0.6f;
}
else {
vert_mult = 1.3f;
horiz_mult = 0.5f;
}
cmd->viewangles[0] -= (punch_angles[0] * vert_mult);
cmd->viewangles[1] -= (punch_angles[1] * horiz_mult);
if (pattern_compensation > 0) {
cmd->viewangles[0] -= pattern_compensation;
}
}
time_t current_time = time(NULL);
if (current_time - last_log_time >= 2) {
if (bullet_count > 0) {
i_engine->Con_Printf("Recoil control - Weapon: %s, Bullet: %d, VMult: %.1f, HMult: %.1f, Pattern: %.1f\n",
is_ak47 ? "AK-47" : (is_high_recoil_weapon ? "High Recoil" : "Standard"),
bullet_count, vert_mult, horiz_mult, pattern_compensation);
}
last_log_time = current_time;
}
ang_clamp(&cmd->viewangles);
}

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 no_recoil(usercmd_t* cmd);
#endif

138
src/features/thirdperson.c Normal file

@ -0,0 +1,138 @@
#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) {
i_engine->Con_Printf("Thirdperson key event: keynum=%d, down=%d, configured=%d\n",
keynum, down, g_settings.thirdperson_key);
if (!down) {
return false;
}
bool should_toggle = false;
if (keynum == 'C' || keynum == 'c' || keynum == 67 || keynum == 99) {
i_engine->Con_Printf("C key detected (keynum=%d)\n", keynum);
if (g_settings.thirdperson_key == 'C' || g_settings.thirdperson_key == 'c' ||
g_settings.thirdperson_key == 67 || g_settings.thirdperson_key == 99) {
should_toggle = true;
}
}
else if (keynum == g_settings.thirdperson_key) {
i_engine->Con_Printf("Configured key detected (keynum=%d)\n", keynum);
should_toggle = true;
}
if (should_toggle) {
thirdperson_toggle();
return true;
}
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

80
src/game_detection.c Normal file

@ -0,0 +1,80 @@
#include "include/game_detection.h"
#include <string.h>
#include <stdio.h>
static GameType current_game = GAME_UNKNOWN;
GameType get_current_game(void) {
if (current_game != GAME_UNKNOWN) {
return current_game;
}
FILE *fp = fopen("/proc/self/cmdline", "r");
if (fp) {
char buf[1024];
size_t size = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
fclose(fp);
if (size > 0) {
buf[size] = '\0';
char *gameTypeToken = NULL;
char *steamToken = NULL;
int tokensFound = 0;
for (char *token = buf; token < buf + size; token += strlen(token) + 1) {
tokensFound++;
if (strcmp(token, "-game") == 0) {
gameTypeToken = token + strlen(token) + 1;
} else if (strcmp(token, "-steam") == 0) {
steamToken = token;
}
}
if (gameTypeToken) {
if (strcmp(gameTypeToken, "cstrike") == 0) {
current_game = GAME_CS16;
} else if (strcmp(gameTypeToken, "dod") == 0) {
current_game = GAME_DAY_OF_DEFEAT;
} else if (strcmp(gameTypeToken, "dmc") == 0) {
current_game = GAME_DMC;
} else if (strcmp(gameTypeToken, "tfc") == 0) {
current_game = GAME_TFC;
} else if (strcmp(gameTypeToken, "SpaceLife") == 0) {
current_game = GAME_SL;
}
} else if (steamToken && tokensFound == 2) {
// If only `-steam` is found and no `-game`, with only two tokens, assume it's Half-Life 1
current_game = GAME_HALFLIFE;
}
}
}
return current_game;
}
int IsCS16(void) {
return get_current_game() == GAME_CS16;
}
int IsHalfLife(void) {
return get_current_game() == GAME_HALFLIFE;
}
int IsDayOfDefeat(void) {
return get_current_game() == GAME_DAY_OF_DEFEAT;
}
int IsTFC(void) {
return get_current_game() == GAME_TFC;
}
int IsDeathmatchClassic(void) {
return get_current_game() == GAME_DMC;
}
int IsSpaceLife(void) {
return get_current_game() == GAME_SL;
}

@ -1,8 +1,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"
@ -10,7 +9,13 @@
game_id this_game_id = HL;
vec3_t g_punchAngles = { 0, 0, 0 };
float g_flNextAttack = 0.f, g_flNextPrimaryAttack = 0.f;
int g_iClip = 0;
int g_currentWeaponID = -1;
double g_flCurrentTime = 0.0;
void* hw;
void** h_client;
@ -20,36 +25,29 @@ 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;
/*----------------------------------------------------------------------------*/
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("hl-cheat: globals_init: can't open hw.so\n");
printf("goldsource-cheat: globals_init: can't open hw.so\n");
return false;
}
h_client = (void**)dlsym(hw, "hClientDLL");
if (!h_client) {
printf("hl-cheat: globals_init: can't find hClientDLL\n");
printf("goldsource-cheat: globals_init: can't find hClientDLL\n");
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");
@ -62,14 +60,16 @@ bool globals_init(void) {
game_info = *(game_t**)dlsym(hw, "game");
scr_fov_value = (float*)dlsym(hw, "scr_fov_value");
if (!i_engine || !i_client || !i_pmove || !i_enginestudio ||
!i_studiomodelrenderer || !game_info) {
printf("hl-cheat: globals_init: couldn't load some symbols\n");
printf("goldsource-cheat: globals_init: couldn't load some symbols\n");
return false;
}
if (!protect_addr(i_studiomodelrenderer, PROT_READ | PROT_WRITE)) {
printf("hl-cheat: globals_init: couldn't unprotect address of SMR\n");
printf("goldsource-cheat: globals_init: couldn't unprotect address of SMR\n");
return false;
}

@ -1,11 +1,39 @@
#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"
#define IMGUI_IMPLEMENTATION
#include "include/imgui/imgui.h"
#include "include/imgui/backends/imgui_impl_opengl2.h"
#include "include/sdk/public/keydefs.h"
#include <dlfcn.h>
#include <GL/gl.h>
#include <string.h>
#include <unistd.h>
extern void* DetourFunction(void* orig, void* hook);
extern bool DetourRemove(void* orig, void* hook);
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,72 +41,244 @@ 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);
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);
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);
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);
/* Detour hooks */
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");
}
}
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) {
/* Check if we should uninject before doing anything else */
if (g_should_uninject) {
g_should_uninject = false;
self_unload();
return;
}
localplayer = i_engine->GetLocalPlayer();
ORIGINAL(CL_CreateMove, frametime, cmd, active);
vec3_t old_angles = cmd->viewangles;
float origForward = cmd->forwardmove;
float origSide = cmd->sidemove;
float origUp = cmd->upmove;
int origButtons = cmd->buttons;
/* Declared in globals.c */
localplayer = i_engine->GetLocalPlayer();
fov_adjust(cmd);
bhop(cmd);
aimbot(cmd);
bullet_tracers(cmd);
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 (s_lock_initialized) {
vec_copy(cmd->viewangles, s_locked_view_angles);
}
}
else {
if (g_menu_open && g_settings.menu_allow_movement) {
cmd->forwardmove = origForward;
cmd->sidemove = origSide;
cmd->upmove = origUp;
cmd->buttons = origButtons;
}
bhop(cmd);
no_recoil(cmd); // Apply recoil control before aimbot
aimbot(cmd);
bullet_tracers(cmd);
anti_aim(cmd);
check_namechanger_mode_and_execute(cmd);
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);
}
/*----------------------------------------------------------------------------*/
rgb_t rainbow_color(float time) {
const float frequency = 0.1f;
unsigned char r = (sin(frequency * time + 0) * 127.5f + 127.5f);
unsigned char g = (sin(frequency * time + 2.0f) * 127.5f + 127.5f);
unsigned char b = (sin(frequency * time + 4.0f) * 127.5f + 127.5f);
return (rgb_t){ r, g, b };
}
int h_HUD_Redraw(float time, int intermission) {
force_view_angles();
int ret = ORIGINAL(HUD_Redraw, time, intermission);
/* Watermark */
engine_draw_text(5, 5, "8dcc/hl-cheat", (rgb_t){ 255, 255, 255 });
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);
}
esp();
custom_crosshair();
if (g_menu_open && g_imgui_context) {
SCREENINFO scr_inf;
scr_inf.iSize = sizeof(SCREENINFO);
i_engine->pfnGetScreenInfo(&scr_inf);
int mouse_x, mouse_y;
i_engine->GetMousePosition(&mouse_x, &mouse_y);
ImGui::SetCurrentContext(g_imgui_context);
ImGuiIO& io = ImGui::GetIO();
io.MouseDown[0] = g_mouse_down[0];
io.MouseDown[1] = g_mouse_down[1];
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;
}
}
menu_render();
return ret;
}
@ -95,8 +295,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);
}
}
/*----------------------------------------------------------------------------*/
@ -106,11 +312,23 @@ void h_HUD_PostRunCmd(struct local_state_s* from, struct local_state_s* to,
unsigned int random_seed) {
ORIGINAL(HUD_PostRunCmd, from, to, cmd, runfuncs, time, random_seed);
g_flCurrentTime = time;
/* Store attack information to check if we can shoot */
if (runfuncs) {
g_flNextAttack = to->client.m_flNextAttack;
g_flNextPrimaryAttack =
to->weapondata[to->client.m_iId].m_flNextPrimaryAttack;
g_iClip = to->weapondata[to->client.m_iId].m_iClip;
// Track current weapon ID
int weaponId = to->client.m_iId;
// Update global weapon ID if it changed
if (g_currentWeaponID != weaponId) {
g_currentWeaponID = weaponId;
i_engine->Con_Printf("Weapon changed: ID=%d\n", g_currentWeaponID);
}
}
}
@ -155,16 +373,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 (cv_clmove->value != 0) {
for (int i = 0; i < (int)cv_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) {
if (keynum == 'C' || keynum == 'c' || keynum == 67 || keynum == 99 ||
keynum == g_settings.thirdperson_key || keynum == K_INS) {
i_engine->Con_Printf("Key event: down=%d, keynum=%d, binding=%s\n",
down, keynum, pszCurrentBinding ? pszCurrentBinding : "none");
}
if (g_menu_open) {
if (keynum == K_BACKSPACE || keynum == K_DEL ||
keynum == K_LEFTARROW || keynum == K_RIGHTARROW ||
keynum == K_UPARROW || keynum == K_DOWNARROW ||
keynum == K_HOME || keynum == K_END ||
keynum == K_ENTER || keynum == K_TAB ||
keynum == K_CTRL || keynum == K_SHIFT || keynum == K_ALT) {
menu_key_event(keynum, down);
return 0;
} else if (down && keynum >= 32 && keynum <= 126) {
menu_char_event(keynum);
}
}
extern bool g_waiting_for_key_bind;
if (g_waiting_for_key_bind && down) {
menu_key_event(keynum, down);
return 0;
}
if (thirdperson_key_event(keynum, down)) {
i_engine->Con_Printf("Thirdperson key event handled successfully\n");
return 0;
}
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;
}
CALL_ORIGINAL(detour_data_clmove, clmove_type);
if (g_menu_open) {
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;
}
if (keynum == K_ESCAPE && down) {
if (ho_HUD_Key_Event)
return ho_HUD_Key_Event(down, keynum, pszCurrentBinding);
}
if (g_settings.menu_allow_movement) {
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);
}
if (keynum == 'W' || keynum == 'A' || keynum == 'S' || keynum == 'D' ||
keynum == ' ' ||
keynum == K_CTRL ||
keynum == K_SHIFT) {
i_engine->Con_Printf("Passing direct movement key to game: %d\n", keynum);
if (ho_HUD_Key_Event)
return ho_HUD_Key_Event(down, keynum, pszCurrentBinding);
}
}
return 0;
}
if (ho_HUD_Key_Event) {
return ho_HUD_Key_Event(down, keynum, pszCurrentBinding);
}
return 0;
}
/*----------------------------------------------------------------------------*/
static void force_view_angles(void) {
static bool s_was_menu_open = false;
float current_time = i_engine->GetClientTime();
static float s_menu_close_time = 0.0f;
static bool s_is_restoring = false;
if (g_menu_open != s_was_menu_open) {
if (g_menu_open) {
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 {
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;
}
if (g_menu_open && s_lock_initialized) {
i_engine->SetViewAngles(s_locked_view_angles);
}
if (!g_menu_open && s_is_restoring) {
if (current_time - s_menu_close_time < 0.2f) {
i_engine->SetViewAngles(s_locked_view_angles);
} else {
s_is_restoring = false;
}
}
}

@ -1,46 +0,0 @@
#ifndef CVARS_H_
#define CVARS_H_
#include "sdk.h"
#include "globals.h"
#define CVAR_PREFIX "cv_"
#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
* -------+-------------------------------
* cv_* | cvar variable
*/
#define DECL_CVAR(name) cvar_t* cv_##name = NULL;
#define DECL_CVAR_EXTERN(name) extern cvar_t* cv_##name;
#define REGISTER_CVAR(name, value) \
cv_##name = \
i_engine->pfnRegisterVariable(CVAR_PREFIX #name, #value, CVAR_HACK_ID);
#define CVAR_ON(name) (cv_##name->value != 0.0f)
/*----------------------------------------------------------------------------*/
DECL_CVAR_EXTERN(bhop);
DECL_CVAR_EXTERN(autostrafe);
DECL_CVAR_EXTERN(aimbot);
DECL_CVAR_EXTERN(esp);
DECL_CVAR_EXTERN(chams);
DECL_CVAR_EXTERN(crosshair);
DECL_CVAR_EXTERN(tracers);
DECL_CVAR_EXTERN(clmove);
/*----------------------------------------------------------------------------*/
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_ */

@ -0,0 +1,22 @@
#ifndef _GAME_DETECT_H_
#define _GAME_DETECT_H_
typedef enum {
GAME_UNKNOWN = 0,
GAME_HALFLIFE,
GAME_CS16,
GAME_TFC,
GAME_DAY_OF_DEFEAT,
GAME_DMC,
GAME_SL
} GameType;
GameType get_current_game(void);
int IsCS16(void);
int IsHalfLife(void);
int IsDayOfDefeat(void);
int IsTFC(void);
int IsDeathmatchClassic(void);
int IsSpaceLife(void);
#endif

@ -1,4 +1,3 @@
#ifndef GLOBALS_H_
#define GLOBALS_H_
@ -9,6 +8,7 @@ enum game_id {
CS = 1, /* Counter-Strike 1.6 */
TF = 2, /* Team Fortress Classic */
DOD = 3, /* Day of Defeat */
SL = 4, /* Space Life: Finleys Revenge */
};
/*----------------------------------------------------------------------------*/
@ -36,6 +36,10 @@ enum game_id {
extern game_id this_game_id;
extern vec3_t g_punchAngles;
extern float g_flNextAttack, g_flNextPrimaryAttack;
extern float* scr_fov_value;
extern int g_iClip;
extern int g_currentWeaponID;
extern double g_flCurrentTime;
extern void* hw;
extern void** h_client; /* hClientDLL hander */

@ -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,8 +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_ */

37
src/include/mathutil.h Normal file

@ -0,0 +1,37 @@
#ifndef MATHUTIL_H_
#define MATHUTIL_H_ 1
#include "sdk.h"
#include "util.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)
/* 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_ */

26
src/include/menu.h Normal file

@ -0,0 +1,26 @@
#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);
void menu_char_event(int ascii);
extern bool g_menu_open;
extern bool g_imgui_initialized;
extern ImGuiContext* g_imgui_context;
extern bool g_waiting_for_key_bind;
extern const char* g_current_key_binding_action;
#ifdef __cplusplus
}
#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];

157
src/include/settings.h Normal file

@ -0,0 +1,157 @@
#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_smoothing_enabled;
bool aimbot_silent;
bool aimbot_autoshoot;
bool aimbot_require_key;
bool aimbot_norecoil;
bool aimbot_recoil_comp;
bool aimbot_friendly_fire;
bool aimbot_team_attack;
int aimbot_hitbox;
bool bhop;
bool autostrafe;
bool antiaim;
bool antiaim_view;
bool fakeduck;
bool clmove;
int aa_pitch_mode;
int aa_yaw_mode;
float aa_custom_pitch;
float aa_custom_yaw;
float aa_spin_speed;
float aa_jitter_range;
bool aa_lby_breaker;
bool aa_desync;
bool aa_on_attack;
bool aa_first_person;
bool fake_duck;
bool antiaim_enabled;
bool antiaim_pitch_enabled;
bool antiaim_yaw_enabled;
float antiaim_pitch;
float antiaim_yaw;
bool antiaim_fakeduck;
int antiaim_fakeduck_key;
bool antiaim_desync;
bool antiaim_legit;
int antiaim_pitch_mode;
int antiaim_yaw_mode;
float antiaim_custom_pitch;
float antiaim_custom_yaw;
float antiaim_spin_speed;
float antiaim_jitter_range;
bool antiaim_lby_breaker;
bool antiaim_on_attack;
bool namechanger;
float namechanger_speed;
bool menu_allow_movement;
bool thirdperson;
int thirdperson_key;
float thirdperson_dist;
bool blinker;
} cheat_settings_t;
extern cheat_settings_t g_settings;
void settings_init(void);
void settings_reset(void);
bool settings_save_to_file(const char* filename);
bool settings_load_from_file(const char* filename);
bool settings_set_as_default(void);
bool settings_create_root_default(void);
const char* get_config_dir(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_smoothing_enabled = true;
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';
// Initialize anti-aim defaults
g_settings.aa_pitch_mode = 0; // None
g_settings.aa_yaw_mode = 0; // None
g_settings.aa_custom_pitch = 0.0f;
g_settings.aa_custom_yaw = 0.0f;
g_settings.aa_spin_speed = 360.0f; // One rotation per second
g_settings.aa_jitter_range = 45.0f; // ±45 degrees jitter
g_settings.aa_lby_breaker = false;
g_settings.aa_desync = false;
g_settings.aa_on_attack = false;
g_settings.aa_first_person = false;
g_settings.fake_duck = false;
// Initialize new anti-aim settings
g_settings.antiaim_enabled = false;
g_settings.antiaim_pitch_enabled = false;
g_settings.antiaim_yaw_enabled = false;
g_settings.antiaim_pitch = 89.0f; // Default to look down
g_settings.antiaim_yaw = 180.0f; // Default to backward
g_settings.antiaim_fakeduck = false;
g_settings.antiaim_fakeduck_key = 0; // No key binding
g_settings.antiaim_desync = false;
g_settings.antiaim_legit = false;
g_settings.antiaim_view = false; // Don't show anti-aim in first person by default
// Initialize advanced anti-aim settings
g_settings.antiaim_pitch_mode = 1; // Down (89°)
g_settings.antiaim_yaw_mode = 1; // Backward (180°)
g_settings.antiaim_custom_pitch = 0.0f;
g_settings.antiaim_custom_yaw = 0.0f;
g_settings.antiaim_spin_speed = 360.0f; // One rotation per second
g_settings.antiaim_jitter_range = 45.0f; // ±45 degrees jitter
g_settings.antiaim_lby_breaker = false;
g_settings.antiaim_on_attack = false;
g_settings.menu_allow_movement = true;
g_settings.blinker = false;
}
#ifdef __cplusplus
}
#endif

@ -14,19 +14,28 @@ 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) \
(((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
#define gl_drawline_points(p0, p1, w, col) \
gl_drawline(p0[0], p0[1], p1[0], p1[1], w, col);
/* 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)
/*----------------------------------------------------------------------------*/
@ -42,8 +51,8 @@ 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);
@ -54,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,73 +1,205 @@
#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;
__attribute__((constructor)) /* Entry point when injected */
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);
}
}
void safe_unload_with_debug(void) {
debug_log("Starting safe unload with debug logging");
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);
debug_log("Resetting all settings to default values");
i_engine->pfnClientCmd("echo \"Step 0: Resetting all settings...\"");
settings_reset();
i_engine->pfnClientCmd("echo \"Step 1: Unhooking functions...\"");
debug_log("Unhooking all functions");
debug_log("Restoring OpenGL hooks");
debug_log("Restoring VMT hooks");
hooks_restore();
debug_log("Restoring globals");
globals_restore();
debug_log("Removing custom commands");
i_engine->pfnClientCmd("echo \"Step 2: Removing custom commands...\"");
debug_log("Waiting for hooks to settle");
i_engine->pfnClientCmd("echo \"Step 3: Waiting for hooks to settle...\"");
usleep(250000);
debug_log("Beginning library unload sequence");
i_engine->pfnClientCmd("echo \"Step 4: Unloading library...\"");
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\"");
}
void UNINJECT_CommandHandler(void) {
i_engine->pfnClientCmd("echo \"Uninjecting goldsource-cheat with debug logging...\"");
safe_unload_with_debug();
}
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))
void load(void) {
printf("hl-cheat injected!\n");
printf("goldsource-cheat injected!\n");
/* Initialize globals/interfaces */
if (!globals_init()) {
fprintf(stderr, "hl-cheat: load: error loading globals, aborting\n");
fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n");
self_unload();
return;
}
/* Create cvars for settings */
if (!cvars_init()) {
fprintf(stderr, "hl-cheat: load: error creating cvars, aborting\n");
self_unload();
return;
}
settings_init();
/* Hook functions */
if (!hooks_init()) {
fprintf(stderr, "hl-cheat: load: error hooking functions, aborting\n");
fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n");
self_unload();
return;
}
/* Get game version after injecting */
this_game_id = get_cur_game();
i_engine->pfnAddCommand("dz_uninject", UNINJECT_CommandHandler);
i_engine->pfnAddCommand("dz_menu", MENU_CommandHandler);
i_engine->pfnClientCmd("bind INS dz_menu");
i_engine->Con_Printf("Bound INSERT key to menu toggle\n");
i_engine->pfnClientCmd("echo \"hl-cheat loaded successfully!\"");
if (IsCS16()) {
i_engine->pfnClientCmd("play weapons/knife_deploy1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDayOfDefeat()) {
i_engine->pfnClientCmd("play weapons/kar_cock.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsTFC()) {
i_engine->pfnClientCmd("play misc/party2.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDeathmatchClassic()) {
i_engine->pfnClientCmd("play items/r_item1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else
{
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\"");
GameType game = get_current_game();
switch(game) {
case GAME_HALFLIFE:
i_engine->pfnClientCmd("echo \"Detected Game: Half-Life 1\"");
break;
case GAME_CS16:
i_engine->pfnClientCmd("echo \"Detected Game: Counter-Strike 1.6\"");
break;
case GAME_DAY_OF_DEFEAT:
i_engine->pfnClientCmd("echo \"Detected Game: Day of Defeat\"");
break;
case GAME_TFC:
i_engine->pfnClientCmd("echo \"Detected Game: Team Fortress Classic\"");
break;
case GAME_DMC:
i_engine->pfnClientCmd("echo \"Detected Game: Deathmatch Classic\"");
break;
case GAME_SL:
i_engine->pfnClientCmd("echo \"Detected Game: Space Life: Finley's Revenge\"");
break;
default:
i_engine->pfnClientCmd("echo \"Detected Game: Unknown Game\"");
break;
}
loaded = true;
}
__attribute__((destructor)) /* Entry point when unloaded */
void unload() {
__attribute__((destructor))
void unload(void) {
if (loaded) {
/* TODO: Remove our cvars */
settings_reset();
globals_restore();
hooks_restore();
GL_UNHOOK(glColor4f); /* Manually restore OpenGL hooks here */
}
printf("hl-cheat unloaded.\n\n");
printf("goldsource-cheat unloaded.\n\n");
}
void self_unload(void) {
/*
* RTLD_LAZY: If the symbol is never referenced, then it is never resolved.
* RTLD_NOLOAD: Don't load the shared object.
*/
void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD);
/* Close the call we just made to dlopen() */
dlclose(self);
/* Close the call our injector made */
dlclose(self);
if (self) {
dlclose(self);
dlclose(self);
}
}

968
src/menu.c Normal file

@ -0,0 +1,968 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#define IMGUI_IMPLEMENTATION
#include "include/menu.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/settings.h"
#include "include/hooks.h"
#include "include/util.h"
#include <GL/gl.h>
#include "include/sdk/public/keydefs.h"
extern const char* hitbox_names[];
extern int current_hitbox;
bool g_menu_open = false;
ImGuiContext* g_imgui_context = NULL;
bool g_imgui_initialized = false;
bool g_waiting_for_key_bind = false;
const char* g_current_key_binding_action = NULL;
static bool s_need_refresh_configs = true;
static char s_config_files[32][64] = {0};
static int s_config_file_count = 0;
static void render_fallback_menu(void);
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) {
printf("Initializing ImGui menu...\n");
i_engine->Con_Printf("Initializing ImGui menu...\n");
if (g_imgui_context) {
printf("ImGui context already exists, shutting down first\n");
menu_shutdown();
}
if (!check_gl_state()) {
printf("OpenGL not ready for ImGui initialization\n");
i_engine->Con_Printf("Warning: OpenGL state not clean, continuing anyway\n");
}
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");
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
io.MouseDrawCursor = false;
SCREENINFO scr_inf;
scr_inf.iSize = sizeof(SCREENINFO);
i_engine->pfnGetScreenInfo(&scr_inf);
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);
}
io.DisplaySize = ImVec2((float)scr_inf.iWidth, (float)scr_inf.iHeight);
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");
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);
g_menu_open = false;
g_imgui_initialized = true;
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");
}
g_menu_open = false;
i_client->IN_ActivateMouse();
i_engine->pfnClientCmd("bind mouse1 +attack; bind mouse2 +attack2");
}
extern "C" void menu_render(void) {
if (!g_menu_open)
return;
if (g_imgui_initialized && g_imgui_context) {
ImGui::SetCurrentContext(g_imgui_context);
SCREENINFO scr_inf;
scr_inf.iSize = sizeof(SCREENINFO);
i_engine->pfnGetScreenInfo(&scr_inf);
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;
}
ImGuiIO& io = ImGui::GetIO();
io.DisplaySize = ImVec2((float)scr_inf.iWidth, (float)scr_inf.iHeight);
io.DeltaTime = 1.0f / 60.0f;
ImGui_ImplOpenGL2_NewFrame();
ImGui::NewFrame();
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);
if (ImGui::Begin("GoldSource Cheat", &g_menu_open,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize)) {
if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None)) {
if (ImGui::BeginTabItem("Aimbot")) {
// Main aimbot settings section
ImGui::Text("Aimbot Settings");
ImGui::Separator();
if (ImGui::Checkbox("Enable Aimbot", &g_settings.aimbot_enabled)) {
}
if (g_settings.aimbot_enabled) {
// Target selection section
ImGui::Text("Target Selection:");
if (ImGui::SliderFloat("FOV", &g_settings.aimbot_fov, 0.1f, 180.0f, "%.1f")) {
// Ensure value stays within limits
g_settings.aimbot_fov = CLAMP(g_settings.aimbot_fov, 0.1f, 180.0f);
}
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Field of view for target selection.\nSmaller values = more precise targeting");
ImGui::EndTooltip();
}
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("Shoot Teammates", &g_settings.aimbot_team_attack);
// Aiming behavior section
ImGui::Separator();
ImGui::Text("Aiming Behavior:");
ImGui::Checkbox("Enable Smoothing", &g_settings.aimbot_smoothing_enabled);
if (g_settings.aimbot_smoothing_enabled) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Makes aim movement look more natural");
ImGui::EndTooltip();
}
if (ImGui::SliderFloat("Smoothing", &g_settings.aimbot_smooth, 1.0f, 100.0f, "%.1f")) {
// Ensure value stays within limits
g_settings.aimbot_smooth = CLAMP(g_settings.aimbot_smooth, 1.0f, 100.0f);
}
ImGui::Text("Lower = Faster | Higher = Smoother");
}
ImGui::Checkbox("Silent Aim", &g_settings.aimbot_silent);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Aim is only visible server-side, not in your view");
ImGui::EndTooltip();
}
// Recoil control section
ImGui::Separator();
ImGui::Text("Recoil Control:");
ImGui::Checkbox("No Recoil", &g_settings.aimbot_norecoil);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Completely removes recoil effect");
ImGui::EndTooltip();
}
ImGui::Checkbox("Recoil Compensation", &g_settings.aimbot_recoil_comp);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Dynamic recoil correction for weapons like AK-47\nAdjusts aim based on spray pattern");
ImGui::EndTooltip();
}
// Auto shoot section
ImGui::Separator();
ImGui::Text("Auto Functions:");
ImGui::Checkbox("Auto Shoot", &g_settings.aimbot_autoshoot);
if (g_settings.aimbot_autoshoot) {
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Auto Shoot automatically fires when aim is on target");
ImGui::EndTooltip();
}
ImGui::Indent(20);
ImGui::Checkbox("Require Fire Button", &g_settings.aimbot_require_key);
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("When enabled, auto-shoot will only fire if you're also pressing the fire button");
ImGui::EndTooltip();
}
ImGui::Unindent(20);
}
// Weapon info section
ImGui::Separator();
ImGui::Text("Current Weapon: %s (ID: %d)",
g_currentWeaponID == 7 ? "AK-47" :
g_currentWeaponID == 16 ? "M4A1" :
g_currentWeaponID == 1 ? "Desert Eagle" : "Unknown",
g_currentWeaponID);
}
ImGui::EndTabItem();
}
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")) {
}
ImGui::Checkbox("Chams", &g_settings.chams);
ImGui::Checkbox("Custom Crosshair", &g_settings.custom_crosshair);
ImGui::Checkbox("Bullet Tracers", &g_settings.tracers);
ImGui::EndTabItem();
}
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();
}
if (ImGui::BeginTabItem("Anti-Aim")) {
ImGui::Text("Anti-Aim Settings");
ImGui::Separator();
if (ImGui::Checkbox("Enable Anti-Aim", &g_settings.antiaim_enabled)) {
if (g_settings.antiaim_enabled) {
i_engine->Con_Printf("Anti-Aim enabled\n");
} else {
i_engine->Con_Printf("Anti-Aim disabled\n");
}
}
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Master switch for all anti-aim features");
ImGui::EndTooltip();
}
if (g_settings.antiaim_enabled) {
ImGui::Separator();
ImGui::Text("Pitch Control:");
if (ImGui::Checkbox("Enable Pitch Anti-Aim", &g_settings.antiaim_pitch_enabled)) {
if (g_settings.antiaim_pitch_enabled) {
i_engine->Con_Printf("Pitch Anti-Aim enabled\n");
} else {
i_engine->Con_Printf("Pitch Anti-Aim disabled\n");
}
}
if (g_settings.antiaim_pitch_enabled) {
const char* pitch_items[] = {"Fixed", "Down (89°)", "Up (-89°)", "Zero (0°)", "Jitter", "Custom"};
if (ImGui::Combo("Pitch Mode", &g_settings.antiaim_pitch_mode, pitch_items, 6)) {
// Reset custom pitch if mode changed
if (g_settings.antiaim_pitch_mode != 5) { // Not custom
g_settings.antiaim_custom_pitch = 0.0f;
}
}
// Show settings based on mode
if (g_settings.antiaim_pitch_mode == 0) { // Fixed
ImGui::SliderFloat("Pitch Angle", &g_settings.antiaim_pitch, -89.0f, 89.0f, "%.1f°");
}
else if (g_settings.antiaim_pitch_mode == 5) { // Custom
ImGui::SliderFloat("Custom Pitch", &g_settings.antiaim_custom_pitch, -89.0f, 89.0f, "%.1f°");
}
}
ImGui::Separator();
ImGui::Text("Yaw Control:");
if (ImGui::Checkbox("Enable Yaw Anti-Aim", &g_settings.antiaim_yaw_enabled)) {
if (g_settings.antiaim_yaw_enabled) {
i_engine->Con_Printf("Yaw Anti-Aim enabled\n");
} else {
i_engine->Con_Printf("Yaw Anti-Aim disabled\n");
}
}
if (g_settings.antiaim_yaw_enabled) {
const char* yaw_items[] = {"Fixed", "Backward (180°)", "Spin", "Jitter", "Sideways", "Custom"};
if (ImGui::Combo("Yaw Mode", &g_settings.antiaim_yaw_mode, yaw_items, 6)) {
// Reset custom yaw if mode changed
if (g_settings.antiaim_yaw_mode != 5) { // Not custom
g_settings.antiaim_custom_yaw = 0.0f;
}
}
// Show settings based on mode
if (g_settings.antiaim_yaw_mode == 0) { // Fixed
ImGui::SliderFloat("Yaw Angle", &g_settings.antiaim_yaw, -180.0f, 180.0f, "%.1f°");
}
else if (g_settings.antiaim_yaw_mode == 2) { // Spin
ImGui::SliderFloat("Spin Speed", &g_settings.antiaim_spin_speed, 10.0f, 1000.0f, "%.1f°/s");
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Controls how fast the spin rotates (degrees per second)");
ImGui::EndTooltip();
}
}
else if (g_settings.antiaim_yaw_mode == 3) { // Jitter
ImGui::SliderFloat("Jitter Range", &g_settings.antiaim_jitter_range, 5.0f, 180.0f, "%.1f°");
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Controls the maximum angle of random jitter (±degrees)");
ImGui::EndTooltip();
}
}
else if (g_settings.antiaim_yaw_mode == 5) { // Custom
ImGui::SliderFloat("Custom Yaw", &g_settings.antiaim_custom_yaw, -180.0f, 180.0f, "%.1f°");
}
}
ImGui::Separator();
ImGui::Text("Additional Options:");
ImGui::Checkbox("Anti-Aim When Shooting", &g_settings.antiaim_on_attack);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Continue anti-aim even when attacking (may affect accuracy)");
ImGui::EndTooltip();
}
ImGui::Checkbox("LBY Breaker", &g_settings.antiaim_lby_breaker);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Breaks lower body yaw for more effective anti-aim");
ImGui::EndTooltip();
}
ImGui::Checkbox("Desync", &g_settings.antiaim_desync);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Creates a desync between client and server angles.\nMakes you harder to hit but may cause visual glitches.");
ImGui::EndTooltip();
}
ImGui::Checkbox("Legit Anti-Aim", &g_settings.antiaim_legit);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Less obvious anti-aim that's harder to detect visually.\nLess effective than rage anti-aim but less noticeable.");
ImGui::EndTooltip();
}
ImGui::Checkbox("Show in First Person", &g_settings.antiaim_view);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("When enabled, you'll see your anti-aim from first person.\nWhen disabled, only others see your anti-aim.");
ImGui::EndTooltip();
}
ImGui::Checkbox("Fake Duck", &g_settings.antiaim_fakeduck);
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Rapidly switches between duck and stand positions.\nMakes you harder to hit while appearing ducked to others.");
ImGui::EndTooltip();
}
if (g_settings.antiaim_fakeduck) {
const char* key_name = "None";
if (g_settings.antiaim_fakeduck_key > 0) {
// Convert key code to name
switch(g_settings.antiaim_fakeduck_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: {
if (g_settings.antiaim_fakeduck_key >= 32 && g_settings.antiaim_fakeduck_key <= 126) {
static char chr[2] = {0};
chr[0] = (char)g_settings.antiaim_fakeduck_key;
key_name = chr;
} else {
static char code[32] = {0};
snprintf(code, sizeof(code), "Key %d", g_settings.antiaim_fakeduck_key);
key_name = code;
}
}
}
}
ImGui::Text("Fake Duck Key: %s", key_name);
if (g_waiting_for_key_bind && g_current_key_binding_action && strcmp(g_current_key_binding_action, "fakeduck") == 0) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.1f, 1.0f));
ImGui::Button("Press any key...", ImVec2(150, 25));
ImGui::PopStyleColor();
} else {
if (ImGui::Button("Bind Fake Duck Key", ImVec2(150, 25))) {
g_waiting_for_key_bind = true;
g_current_key_binding_action = "fakeduck";
i_engine->Con_Printf("Press any key to bind for fake duck\n");
}
}
ImGui::SameLine();
if (ImGui::Button("Clear##FakeDuckKey", ImVec2(80, 25))) {
g_settings.antiaim_fakeduck_key = 0;
i_engine->Con_Printf("Fake duck key binding cleared\n");
}
}
}
ImGui::EndTabItem();
}
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();
ImGui::Text("Menu Settings:");
ImGui::Checkbox("Allow Movement (WASD) With Menu Open", &g_settings.menu_allow_movement);
ImGui::Separator();
if (ImGui::Button("Reset Settings", ImVec2(150, 30))) {
settings_reset();
i_engine->pfnClientCmd("echo \"All settings have been reset to defaults.\"");
}
ImGui::SameLine();
ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.1f, 1.0f), "?");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text("Reset all settings to default values");
ImGui::EndTooltip();
}
ImGui::Separator();
if (ImGui::Button("Uninject Cheat", ImVec2(150, 30))) {
i_engine->pfnClientCmd("dz_uninject");
g_menu_open = false;
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("View")) {
ImGui::Text("Camera Settings:");
bool thirdperson_changed = ImGui::Checkbox("Third-Person View", &g_settings.thirdperson);
if (g_settings.thirdperson) {
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();
ImGui::SliderFloat("Camera Distance", &g_settings.thirdperson_dist, 30.0f, 800.0f, "%.1f");
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Camera distance updates in real-time");
ImGui::Separator();
ImGui::Text("Keybind for Third-Person Toggle:");
const char* key_name = "None";
if (g_settings.thirdperson_key > 0) {
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: {
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 {
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);
if (g_waiting_for_key_bind) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.1f, 1.0f));
ImGui::Button("Press any key...", ImVec2(150, 25));
ImGui::PopStyleColor();
} else {
if (ImGui::Button("Bind new key", ImVec2(150, 25))) {
g_waiting_for_key_bind = true;
g_current_key_binding_action = "thirdperson";
i_engine->Con_Printf("Press any key to bind for third-person toggle\n");
}
}
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();
}
if (ImGui::BeginTabItem("Config")) {
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Configuration System");
ImGui::Separator();
static char config_name[64] = "default";
ImGui::Text("Config Name:");
ImGui::PushItemWidth(200);
ImGui::InputText("##ConfigName", config_name, sizeof(config_name));
ImGui::PopItemWidth();
if (ImGui::Button("Save Config", ImVec2(120, 30))) {
if (settings_save_to_file(config_name)) {
ImGui::OpenPopup("ConfigSaved");
s_need_refresh_configs = true;
} else {
ImGui::OpenPopup("ConfigError");
}
}
ImGui::SameLine();
if (ImGui::Button("Load Config", ImVec2(120, 30))) {
if (settings_load_from_file(config_name)) {
ImGui::OpenPopup("ConfigLoaded");
} else {
ImGui::OpenPopup("ConfigError");
}
}
ImGui::SameLine();
if (ImGui::Button("Reset to Default", ImVec2(120, 30))) {
ImGui::OpenPopup("ConfirmReset");
}
ImGui::Separator();
if (ImGui::Button("Set as Default", ImVec2(120, 30))) {
if (settings_set_as_default()) {
ImGui::OpenPopup("DefaultSaved");
} else {
ImGui::OpenPopup("ConfigError");
}
}
ImGui::SameLine();
if (ImGui::Button("Delete Config", ImVec2(120, 30))) {
ImGui::OpenPopup("ConfirmDelete");
}
ImGui::Separator();
ImGui::Separator();
ImGui::Text("Available Configs:");
if (s_need_refresh_configs) {
memset(s_config_files, 0, sizeof(s_config_files));
s_config_file_count = 0;
const char* config_dir = get_config_dir();
if (config_dir) {
DIR* dir = opendir(config_dir);
if (dir) {
struct dirent* entry;
while ((entry = readdir(dir)) != NULL && s_config_file_count < 32) {
size_t len = strlen(entry->d_name);
if (len > 4 && strcmp(entry->d_name + len - 4, ".cfg") == 0) {
strncpy(s_config_files[s_config_file_count], entry->d_name, len - 4);
s_config_files[s_config_file_count][len - 4] = '\0';
s_config_file_count++;
}
}
closedir(dir);
}
}
s_need_refresh_configs = false;
}
if (ImGui::Button("Refresh List", ImVec2(120, 25))) {
s_need_refresh_configs = true;
}
ImGui::BeginChild("ConfigList", ImVec2(0, 150), true);
for (int i = 0; i < s_config_file_count; i++) {
if (ImGui::Selectable(s_config_files[i], false)) {
strncpy(config_name, s_config_files[i], sizeof(config_name) - 1);
config_name[sizeof(config_name) - 1] = '\0';
}
}
ImGui::EndChild();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
}
ImGui::Render();
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
} else {
render_fallback_menu();
}
}
static void render_fallback_menu(void) {
SCREENINFO scr_inf;
scr_inf.iSize = sizeof(SCREENINFO);
i_engine->pfnGetScreenInfo(&scr_inf);
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;
i_engine->pfnFillRGBA(x1, y1, x2-x1, y2-y1, 0, 0, 0, 230);
i_engine->pfnFillRGBA(x1, y1, x2-x1, 2, 255, 0, 0, 255);
i_engine->pfnFillRGBA(x1, y2-2, x2-x1, 2, 255, 0, 0, 255);
i_engine->pfnFillRGBA(x1, y1, 2, y2-y1, 255, 0, 0, 255);
i_engine->pfnFillRGBA(x2-2, y1, 2, y2-y1, 255, 0, 0, 255);
i_engine->pfnDrawSetTextColor(1.0f, 1.0f, 0.0f);
i_engine->pfnDrawConsoleString(x1+10, y1+10, "===== GoldSource Cheat Menu (Fallback) =====");
i_engine->pfnDrawSetTextColor(0.0f, 1.0f, 1.0f);
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;
if (g_settings.aimbot_smoothing_enabled) {
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;
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");
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");
}
extern "C" void menu_key_event(int keynum, int down) {
i_engine->Con_Printf("menu_key_event called: keynum=%d, down=%d, waiting_for_key=%d\n",
keynum, down, g_waiting_for_key_bind);
if (g_menu_open && g_imgui_initialized && g_imgui_context) {
ImGui::SetCurrentContext(g_imgui_context);
ImGuiIO& io = ImGui::GetIO();
switch (keynum) {
case K_TAB: io.AddKeyEvent(ImGuiKey_Tab, down); break;
case K_LEFTARROW: io.AddKeyEvent(ImGuiKey_LeftArrow, down); break;
case K_RIGHTARROW: io.AddKeyEvent(ImGuiKey_RightArrow, down); break;
case K_UPARROW: io.AddKeyEvent(ImGuiKey_UpArrow, down); break;
case K_DOWNARROW: io.AddKeyEvent(ImGuiKey_DownArrow, down); break;
case K_BACKSPACE: io.AddKeyEvent(ImGuiKey_Backspace, down); break;
case K_DEL: io.AddKeyEvent(ImGuiKey_Delete, down); break;
case K_ENTER: io.AddKeyEvent(ImGuiKey_Enter, down); break;
case K_HOME: io.AddKeyEvent(ImGuiKey_Home, down); break;
case K_END: io.AddKeyEvent(ImGuiKey_End, down); break;
case K_ESCAPE: io.AddKeyEvent(ImGuiKey_Escape, down); break;
case K_CTRL: io.AddKeyEvent(ImGuiKey_LeftCtrl, down); break;
case K_SHIFT: io.AddKeyEvent(ImGuiKey_LeftShift, down); break;
case K_ALT: io.AddKeyEvent(ImGuiKey_LeftAlt, down); break;
default: break;
}
}
if (g_waiting_for_key_bind && down && keynum != K_ESCAPE) {
i_engine->Con_Printf("Processing key bind: keynum=%d, action=%s\n",
keynum, g_current_key_binding_action ? g_current_key_binding_action : "none");
if (keynum != K_MWHEELDOWN && keynum != K_MWHEELUP && keynum != K_INS) {
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);
}
g_waiting_for_key_bind = false;
g_current_key_binding_action = NULL;
i_engine->Con_Printf("Key binding completed!\n");
return;
} else {
i_engine->Con_Printf("Ignored wheel/INS key: %d\n", keynum);
}
}
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) {
g_menu_open = !g_menu_open;
i_engine->Con_Printf("Menu %s\n", g_menu_open ? "opened" : "closed");
if (g_imgui_initialized && g_imgui_context) {
ImGui::SetCurrentContext(g_imgui_context);
ImGuiIO& io = ImGui::GetIO();
io.MouseDrawCursor = g_menu_open;
}
if (g_menu_open) {
i_client->IN_DeactivateMouse();
i_client->IN_ClearStates();
i_engine->pfnClientCmd("unbind mouse1; unbind mouse2");
i_engine->Con_Printf("Mouse deactivated for game, using ImGui cursor\n");
} else {
i_client->IN_ActivateMouse();
i_engine->pfnClientCmd("bind mouse1 +attack; bind mouse2 +attack2");
i_engine->Con_Printf("Mouse reactivated for game\n");
}
}
}
extern "C" void menu_char_event(int ascii) {
if (!g_menu_open || !g_imgui_initialized || !g_imgui_context)
return;
ImGui::SetCurrentContext(g_imgui_context);
ImGuiIO& io = ImGui::GetIO();
io.AddInputCharacter((unsigned int)ascii);
}

354
src/settings.c Normal file

@ -0,0 +1,354 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "include/settings.h"
#include "include/globals.h"
#include "include/game_detection.h"
cheat_settings_t g_settings;
static bool copy_file(const char* src_path, const char* dst_path) {
FILE* src = fopen(src_path, "rb");
if (!src) {
return false;
}
FILE* dst = fopen(dst_path, "wb");
if (!dst) {
fclose(src);
return false;
}
char buffer[4096];
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) {
if (fwrite(buffer, 1, bytes, dst) != bytes) {
fclose(src);
fclose(dst);
return false;
}
}
fclose(src);
fclose(dst);
return true;
}
bool create_root_default_config(void) {
cheat_settings_t preset;
memset(&preset, 0, sizeof(preset));
preset.esp_mode = ESP_BOX;
preset.chams = true;
preset.aimbot_enabled = true;
preset.aimbot_fov = 5.0f;
preset.aimbot_smoothing_enabled = true;
preset.bhop = true;
preset.autostrafe = true;
preset.thirdperson = false;
preset.thirdperson_key = 'C';
preset.thirdperson_dist = 150.0f;
preset.watermark = true;
preset.watermark_rainbow = true;
preset.fov = 90.0f;
preset.menu_allow_movement = true;
FILE* file = fopen("../default.cfg", "wb");
if (!file) {
i_engine->Con_Printf("Error: Could not create root default.cfg\n");
return false;
}
size_t written = fwrite(&preset, sizeof(preset), 1, file);
fclose(file);
if (written != 1) {
i_engine->Con_Printf("Error: Failed to write to root default.cfg\n");
return false;
}
i_engine->Con_Printf("Successfully created ../default.cfg with preset settings\n");
return true;
}
void settings_init(void) {
init_default_settings();
char cwd[1024] = {0};
if (getcwd(cwd, sizeof(cwd)) != NULL) {
i_engine->Con_Printf("Current working directory: %s\n", cwd);
}
const char* config_dir = get_config_dir();
if (!config_dir) {
i_engine->Con_Printf("Error: Could not get config directory, using defaults\n");
return;
}
char config_path[1024];
snprintf(config_path, sizeof(config_path), "%s/default.cfg", config_dir);
i_engine->Con_Printf("Config path: %s\n", config_path);
if (access(config_path, F_OK) == 0) {
i_engine->Con_Printf("Found config, loading from: %s\n", config_path);
if (settings_load_from_file("default")) {
i_engine->Con_Printf("Successfully loaded config\n");
} else {
i_engine->Con_Printf("Error loading config, using defaults\n");
}
}
else if (access("../default.cfg", F_OK) == 0) {
i_engine->Con_Printf("Found config in project dir, copying to user config...\n");
if (copy_file("../default.cfg", config_path)) {
i_engine->Con_Printf("Successfully copied project config to user directory\n");
if (settings_load_from_file("default")) {
i_engine->Con_Printf("Successfully loaded copied config\n");
} else {
i_engine->Con_Printf("Error loading copied config, using defaults\n");
}
} else {
i_engine->Con_Printf("Error copying project config, using defaults\n");
}
}
else {
i_engine->Con_Printf("No config found anywhere, creating default config with current settings\n");
if (settings_save_to_file("default")) {
i_engine->Con_Printf("Created new default config\n");
} else {
i_engine->Con_Printf("Error creating default config\n");
}
}
if (g_settings.thirdperson_key == 0) {
g_settings.thirdperson_key = 'C';
}
i_engine->Con_Printf("Settings initialized. Third-person key: %d\n", g_settings.thirdperson_key);
}
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_team_attack = false;
g_settings.aimbot_require_key = false;
g_settings.aimbot_smoothing_enabled = true;
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;
// Reset anti-aim settings
g_settings.antiaim_enabled = false;
g_settings.antiaim_pitch_enabled = false;
g_settings.antiaim_yaw_enabled = false;
g_settings.antiaim_pitch = 89.0f;
g_settings.antiaim_yaw = 180.0f;
g_settings.antiaim_fakeduck = false;
g_settings.antiaim_fakeduck_key = 0;
g_settings.antiaim_desync = false;
g_settings.antiaim_legit = false;
// Reset advanced anti-aim settings
g_settings.antiaim_pitch_mode = 1; // Down (89°)
g_settings.antiaim_yaw_mode = 1; // Backward (180°)
g_settings.antiaim_custom_pitch = 0.0f;
g_settings.antiaim_custom_yaw = 0.0f;
g_settings.antiaim_spin_speed = 360.0f; // One rotation per second
g_settings.antiaim_jitter_range = 45.0f; // ±45 degrees jitter
g_settings.antiaim_lby_breaker = false;
g_settings.antiaim_on_attack = 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\"");
}
const char* get_config_dir(void) {
static char config_dir[512] = {0};
if (config_dir[0] == '\0') {
const char* home = getenv("HOME");
if (!home) {
i_engine->Con_Printf("Error: Could not get HOME directory\n");
return NULL;
}
snprintf(config_dir, sizeof(config_dir), "%s/.config/dz-goldsrccheat", home);
struct stat st = {0};
if (stat(config_dir, &st) == -1) {
if (mkdir(config_dir, 0755) == -1) {
i_engine->Con_Printf("Error: Could not create config directory %s\n", config_dir);
return NULL;
}
i_engine->Con_Printf("Created config directory: %s\n", config_dir);
}
}
return config_dir;
}
bool settings_save_to_file(const char* filename) {
const char* config_dir = get_config_dir();
if (!config_dir) {
i_engine->Con_Printf("Error: Could not get config directory\n");
return false;
}
char filepath[1024];
snprintf(filepath, sizeof(filepath), "%s/%s.cfg", config_dir, filename);
FILE* file = fopen(filepath, "wb");
if (!file) {
i_engine->Con_Printf("Error: Could not open file for writing: %s\n", filepath);
return false;
}
// Simple direct binary write of the settings
size_t written = fwrite(&g_settings, sizeof(g_settings), 1, file);
fclose(file);
if (written != 1) {
i_engine->Con_Printf("Error: Failed to write settings to file: %s\n", filepath);
return false;
}
i_engine->Con_Printf("Settings saved to %s\n", filepath);
return true;
}
bool settings_load_from_file(const char* filename) {
const char* config_dir = get_config_dir();
if (!config_dir) {
i_engine->Con_Printf("Error: Could not get config directory\n");
return false;
}
char filepath[1024];
snprintf(filepath, sizeof(filepath), "%s/%s.cfg", config_dir, filename);
if (access(filepath, F_OK) != 0) {
i_engine->Con_Printf("Error: Config file does not exist: %s\n", filepath);
return false;
}
FILE* file = fopen(filepath, "rb");
if (!file) {
i_engine->Con_Printf("Error: Could not open file for reading: %s\n", filepath);
return false;
}
// Get file size for debugging
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
fseek(file, 0, SEEK_SET);
i_engine->Con_Printf("Loading config from %s, file size: %ld bytes, struct size: %zu bytes\n",
filepath, file_size, sizeof(cheat_settings_t));
// Simple direct binary read of the settings
size_t read = fread(&g_settings, sizeof(g_settings), 1, file);
fclose(file);
if (read != 1) {
i_engine->Con_Printf("Error: Failed to read settings from file: %s\n", filepath);
return false;
}
i_engine->Con_Printf("Settings loaded. Aimbot=%d, ESP=%d, Bhop=%d, ThirdPerson=%d, TPDist=%.1f\n",
g_settings.aimbot_enabled, g_settings.esp_mode, g_settings.bhop,
g_settings.thirdperson, g_settings.thirdperson_dist);
return true;
}
bool settings_set_as_default(void) {
return settings_save_to_file("default");
}
bool settings_create_root_default(void) {
return create_root_default_config();
}
// Add a simple function to copy config from ~/gitprojects/goldsource-cheat/default.cfg to ~/.config/dz-goldsrccheat/default.cfg
bool copy_project_config_to_user(void) {
const char* config_dir = get_config_dir();
if (!config_dir) {
i_engine->Con_Printf("Error: Could not get config directory\n");
return false;
}
char dst_path[1024];
snprintf(dst_path, sizeof(dst_path), "%s/default.cfg", config_dir);
// Check if source exists
if (access("../default.cfg", F_OK) != 0) {
i_engine->Con_Printf("Error: Source config ../default.cfg does not exist\n");
return false;
}
if (!copy_file("../default.cfg", dst_path)) {
i_engine->Con_Printf("Error: Failed to copy ../default.cfg to %s\n", dst_path);
return false;
}
i_engine->Con_Printf("Successfully copied project config to user directory\n");
return true;
}
// Add a simple function to copy config from ~/.config/dz-goldsrccheat/default.cfg to ~/gitprojects/goldsource-cheat/default.cfg
bool copy_user_config_to_project(void) {
const char* config_dir = get_config_dir();
if (!config_dir) {
i_engine->Con_Printf("Error: Could not get config directory\n");
return false;
}
char src_path[1024];
snprintf(src_path, sizeof(src_path), "%s/default.cfg", config_dir);
// Check if source exists
if (access(src_path, F_OK) != 0) {
i_engine->Con_Printf("Error: Source config %s does not exist\n", src_path);
return false;
}
if (!copy_file(src_path, "../default.cfg")) {
i_engine->Con_Printf("Error: Failed to copy %s to ../default.cfg\n", src_path);
return false;
}
i_engine->Con_Printf("Successfully copied user config to project directory\n");
return true;
}

@ -9,6 +9,7 @@
#include "include/util.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/game_detection.h"
cl_entity_t* get_player(int ent_idx) {
if (ent_idx < 0 || ent_idx > 32)
@ -35,36 +36,31 @@ bool is_friend(cl_entity_t* ent) {
if (!ent)
return false;
/* Check the current game because this method only works for some games */
switch (this_game_id) {
case TF: {
GameType game = get_current_game();
switch (game) {
case GAME_TFC: {
extra_player_info_t* info = (extra_player_info_t*)player_extra_info;
return info[ent->index].teamnumber ==
info[localplayer->index].teamnumber;
return info[ent->index].teamnumber == info[localplayer->index].teamnumber;
}
case CS: {
extra_player_info_cs_t* info =
(extra_player_info_cs_t*)player_extra_info;
return info[ent->index].teamnumber ==
info[localplayer->index].teamnumber;
case GAME_CS16: {
extra_player_info_cs_t* info = (extra_player_info_cs_t*)player_extra_info;
return info[ent->index].teamnumber == info[localplayer->index].teamnumber;
}
case DOD: {
extra_player_info_dod_t* info =
(extra_player_info_dod_t*)player_extra_info;
return info[ent->index].teamnumber ==
info[localplayer->index].teamnumber;
case GAME_DAY_OF_DEFEAT: {
extra_player_info_dod_t* info = (extra_player_info_dod_t*)player_extra_info;
return info[ent->index].teamnumber == info[localplayer->index].teamnumber;
}
case HL:
case GAME_HALFLIFE:
case GAME_DMC:
default:
return false;
}
}
bool can_shoot(void) {
return g_flNextAttack <= 0.0f && g_flNextPrimaryAttack <= 0.0f;
return g_iClip > 0 && g_flNextAttack <= 0.0f &&
g_flNextPrimaryAttack <= 0.0f;
}
char* get_name(int ent_idx) {
@ -74,26 +70,6 @@ char* get_name(int ent_idx) {
return info.name;
}
game_id get_cur_game(void) {
typedef void (*COM_ParseDirectoryFromCmd_t)(const char*, char*, int,
const char*);
COM_ParseDirectoryFromCmd_t COM_ParseDirectoryFromCmd =
(COM_ParseDirectoryFromCmd_t)dlsym(hw, "COM_ParseDirectoryFromCmd");
char game[FILENAME_MAX];
COM_ParseDirectoryFromCmd("-game", game, sizeof(game), "valve");
/* Get the current game we are playing */
if (game[0] == 'c' && game[1] == 's') /* cstrike */
return CS;
else if (*game == 'd') /* dod */
return DOD;
else if (*game == 't') /* tfc */
return TF;
else
return HL;
}
vec3_t vec3(float x, float y, float z) {
vec3_t ret;
@ -132,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) {
@ -187,10 +163,15 @@ bool world_to_screen(vec3_t vec, vec2_t screen) {
scr_inf.iSize = sizeof(SCREENINFO);
i_engine->pfnGetScreenInfo(&scr_inf);
/* If within bounds, transform to screen scale */
if (screen[0] < 1 && screen[1] < 1 && screen[0] > -1 && screen[1] > -1) {
if (IsDayOfDefeat()) {
printf("Before transformation: %f, %f, Depth: %f\n", screen[0], screen[1], screen[2]);
screen[0] = ((screen[0] + 1) * 0.5) * scr_inf.iWidth;
screen[1] = ((1 - screen[1]) * 0.5) * scr_inf.iHeight;
} else {
screen[0] = screen[0] * (scr_inf.iWidth / 2) + (scr_inf.iWidth / 2);
screen[1] = -screen[1] * (scr_inf.iHeight / 2) + (scr_inf.iHeight / 2);
}
return true;
}
@ -270,7 +251,7 @@ bool protect_addr(void* ptr, int new_flags) {
int pgsz = getpagesize();
if (mprotect(p, pgsz, new_flags) == -1) {
printf("hl-cheat: error protecting %p\n", ptr);
printf("goldsource-cheat: error protecting %p\n", ptr);
return false;
}