Compare commits
	
		
			86 Commits
		
	
	
		
			bone_posit
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1da95a4c35 | |||
| 40f014de59 | |||
| 0b9c748444 | |||
| dcdd090677 | |||
| f885095c39 | |||
| 51c3b979ea | |||
| 6a640a716c | |||
| 66b4abf888 | |||
| 5bf0dfce70 | |||
| cbea54c5ce | |||
| 1d94704814 | |||
| 2ca8c26f8f | |||
| 3fa74e6ab0 | |||
| 1ccab9d518 | |||
| c5a0ec15e9 | |||
| 07b05f02c4 | |||
| 0c63d7c969 | |||
| e53e7c5d37 | |||
|  | 184e52dcbc | ||
|  | 3738e6cd7c | ||
|  | 543c00e294 | ||
|  | 21d9cac264 | ||
|  | 8a5b96505b | ||
|  | 72dc42006f | ||
|  | 1c4bc57713 | ||
|  | d9339d0d5a | ||
|  | 44e5dc34c0 | ||
|  | 17b4e4e3a3 | ||
|  | 0b0664e4cf | ||
|  | d3b6c64003 | ||
|  | f93a21ce16 | ||
|  | 87208744e1 | ||
|  | f7fc075c4a | ||
|  | f26da3e84f | ||
|  | e440b15a9d | ||
|  | 1d99e0758a | ||
|  | 9a109b3882 | ||
|  | 36459f0d6a | ||
|  | 3bd0fe52da | ||
|  | 88bdad24b1 | ||
|  | a898563249 | ||
|  | 2401ecf71e | ||
| 4b54871340 | |||
|  | a09d80fbfa | ||
|  | 7fc0a14ae6 | ||
|  | 7239d610a8 | ||
|  | 3aaf7c8346 | ||
|  | a5234c16a3 | ||
|  | f38678d727 | ||
|  | e43cea56f8 | ||
|  | c5e985bc42 | ||
|  | c1ff555e17 | ||
|  | b7bac66484 | ||
|  | a688d94e9d | ||
|  | deccfca8e3 | ||
|  | b29f71e597 | ||
|  | c7ee48dfa6 | ||
|  | a7b30ca7f8 | ||
|  | 1f3e531610 | ||
|  | 0e7f955c7d | ||
|  | f0485a3f36 | ||
|  | 02888c1158 | ||
|  | b9851de177 | ||
|  | 56f8ae79d7 | ||
|  | f9db9ff1b6 | ||
|  | 29a40f63da | ||
|  | b7c6e74dd4 | ||
|  | 510243c46d | ||
|  | fb6ed02dd4 | ||
|  | 42a7961142 | ||
|  | da6cf86910 | ||
|  | 3414d131f4 | ||
|  | 83278b9983 | ||
|  | 4bb21a4ca6 | ||
|  | 51c302f492 | ||
|  | 865a02a8cd | ||
|  | d09fdf66b5 | ||
|  | 87e6b34eee | ||
|  | cd3fde56a3 | ||
|  | 3d3ebd7c5a | ||
|  | 7cf0b30495 | ||
|  | 70a69c1fc8 | ||
|  | e26d5639c2 | ||
|  | 0625638e31 | ||
|  | 56fa55a751 | ||
|  | bb6c9efc50 | 
							
								
								
									
										24
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Makefile
									
									
									
									
									
								
							| @@ -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) | ||||
|   | ||||
							
								
								
									
										73
									
								
								README.org
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								README.org
									
									
									
									
									
								
							| @@ -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,15 +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             | | ||||
| | 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) | ||||
| @@ -33,14 +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://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 | ||||
| @@ -49,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 | ||||
|  | ||||
| @@ -62,5 +101,5 @@ $ ./injector.sh | ||||
|  | ||||
| ... | ||||
|  | ||||
| hl-cheat loaded! | ||||
| goldsource-cheat loaded! | ||||
| #+end_src | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								default.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								default.cfg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										217
									
								
								inject-debug.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										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 | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/cvars.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/cvars.c
									
									
									
									
									
								
							| @@ -1,24 +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(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(clmove, 0); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
							
								
								
									
										101
									
								
								src/detour.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/detour.c
									
									
									
									
									
								
							| @@ -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,74 +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 | ||||
|  | ||||
| static vec3_t get_closest_delta(vec3_t viewangles) { | ||||
|     vec3_t view_height; | ||||
|     i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height); | ||||
|     vec3_t local_eyes = vec_add(localplayer->origin, view_height); | ||||
|     /* TODO: Compensate aim punch */ | ||||
| #define AIM_PUNCH_MULT 2.0f | ||||
|  | ||||
|     /* 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 }; | ||||
| #define SMOOTHING_FACTOR 3.0f | ||||
|  | ||||
| #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; | ||||
|     } | ||||
|  | ||||
|     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; | ||||
|      | ||||
|     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; | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|     cl_entity_t* entity; | ||||
|     float fov; | ||||
|     vec3_t aim_point; | ||||
|     bool is_visible; | ||||
|     int priority; | ||||
|     float distance; | ||||
| } target_t; | ||||
|  | ||||
| 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)); | ||||
|         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; | ||||
|              | ||||
|         if (!g_settings.aimbot_team_attack && is_friend(ent)) | ||||
|             continue; | ||||
|          | ||||
|         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
									
								
							
							
						
						
									
										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,7 +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
									
								
							
							
						
						
									
										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 }; | ||||
| @@ -29,3 +29,53 @@ void custom_crosshair(void) { | ||||
|     gl_drawline(mx - gap, my + gap, mx - gap - len, my + gap + len, w, col); | ||||
|     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) { | ||||
|     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); | ||||
|  | ||||
|     const int tracer_len = 3000; | ||||
|     vec3_t end; | ||||
|     end.x = local_eyes.x + fwd.x * tracer_len; | ||||
|     end.y = local_eyes.y + fwd.y * tracer_len; | ||||
|     end.z = local_eyes.z + fwd.z * tracer_len; | ||||
|  | ||||
|     /* NOTE: Change tracer settings here */ | ||||
|     const float w    = 0.8; | ||||
|     const float time = 2; | ||||
|     draw_tracer(local_eyes, end, (rgb_t){ 66, 165, 245 }, 1, w, time); | ||||
| } | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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  | ||||
							
								
								
									
										28
									
								
								src/features/thirdperson.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/features/thirdperson.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
							
							
						
						
									
										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,14 +1,21 @@ | ||||
|  | ||||
| #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" | ||||
| #include "include/util.h" | ||||
|  | ||||
| enum game_id this_game_id = HL; | ||||
| 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; | ||||
| @@ -18,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"); | ||||
| @@ -60,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; | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										471
									
								
								src/hooks.c
									
									
									
									
									
								
							
							
						
						
									
										471
									
								
								src/hooks.c
									
									
									
									
									
								
							| @@ -1,79 +1,284 @@ | ||||
| #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); | ||||
| 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); | ||||
|     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; | ||||
| } | ||||
| @@ -87,6 +292,48 @@ 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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /*----------------------------------------------------------------------------*/ | ||||
|  | ||||
| void h_HUD_PostRunCmd(struct local_state_s* from, struct local_state_s* to, | ||||
|                       struct usercmd_s* cmd, int runfuncs, double time, | ||||
|                       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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /*----------------------------------------------------------------------------*/ | ||||
|  | ||||
| void h_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { | ||||
|     /* This visible_mode variable is changed inside the chams() function, which | ||||
|      * is called from the StudioRenderModel hook. | ||||
| @@ -126,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,45 +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(clmove); | ||||
|  | ||||
| /*----------------------------------------------------------------------------*/ | ||||
|  | ||||
| bool cvars_init(void); | ||||
|  | ||||
| #endif /* CVARS_H_ */ | ||||
							
								
								
									
										14
									
								
								src/include/entityutil.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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_ */ | ||||
							
								
								
									
										22
									
								
								src/include/game_detection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/include/game_detection.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 */ | ||||
| }; | ||||
|  | ||||
| /*----------------------------------------------------------------------------*/ | ||||
| @@ -34,6 +34,12 @@ 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,29 +79,47 @@ | ||||
|  | ||||
| #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); | ||||
| DECL_HOOK_EXTERN(int, HUD_Redraw, float, int); | ||||
| DECL_HOOK_EXTERN(void, StudioRenderModel, void*); | ||||
|  | ||||
| /* OpenGL hooks */ | ||||
| DECL_HOOK_EXTERN(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat); | ||||
| DECL_HOOK_EXTERN(void, CalcRefdef, ref_params_t*); | ||||
| DECL_HOOK_EXTERN(void, HUD_PostRunCmd, struct local_state_s*, | ||||
|                  struct local_state_s*, struct usercmd_s*, int, double, | ||||
|                  unsigned int); | ||||
|  | ||||
| /* 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_ */ | ||||
|   | ||||
							
								
								
									
										321
									
								
								src/include/imgui/backends/imgui_impl_opengl2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								src/include/imgui/backends/imgui_impl_opengl2.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										41
									
								
								src/include/imgui/backends/imgui_impl_opengl2.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/include/imgui/backends/imgui_impl_opengl2.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										141
									
								
								src/include/imgui/imconfig.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/include/imgui/imconfig.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										3777
									
								
								src/include/imgui/imgui.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4831
									
								
								src/include/imgui/imgui_draw.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4831
									
								
								src/include/imgui/imgui_draw.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3638
									
								
								src/include/imgui/imgui_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3638
									
								
								src/include/imgui/imgui_internal.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4525
									
								
								src/include/imgui/imgui_tables.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4525
									
								
								src/include/imgui/imgui_tables.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10452
									
								
								src/include/imgui/imgui_widgets.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10452
									
								
								src/include/imgui/imgui_widgets.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										627
									
								
								src/include/imgui/imstb_rectpack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										627
									
								
								src/include/imgui/imstb_rectpack.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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. | ||||
| ------------------------------------------------------------------------------ | ||||
| */ | ||||
							
								
								
									
										1469
									
								
								src/include/imgui/imstb_textedit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1469
									
								
								src/include/imgui/imstb_textedit.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5085
									
								
								src/include/imgui/imstb_truetype.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5085
									
								
								src/include/imgui/imstb_truetype.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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]; | ||||
|  | ||||
| @@ -62,7 +94,7 @@ typedef struct cl_clientfuncs_s { | ||||
|     void (*CL_CameraOffset)(float* ofs); | ||||
|     struct kbutton_s* (*KB_Find)(const char* name); | ||||
|     void (*CAM_Think)(void); | ||||
|     void (*V_CalcRefdef)(struct ref_params_s* pparams); | ||||
|     void (*CalcRefdef)(struct ref_params_s* pparams); | ||||
|     int (*HUD_AddEntity)(int type, struct cl_entity_s* ent, | ||||
|                          const char* modelname); | ||||
|  | ||||
|   | ||||
							
								
								
									
										157
									
								
								src/include/settings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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,18 +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.x = src.x;         \ | ||||
|     dst.y = src.y;         \ | ||||
|     dst.z = src.z; | ||||
|     do {                   \ | ||||
|         dst[0] = src[0];   \ | ||||
|         dst[1] = src[1];   \ | ||||
|         dst[2] = src[2];   \ | ||||
|     } while (0) | ||||
|  | ||||
| /*----------------------------------------------------------------------------*/ | ||||
|  | ||||
| @@ -33,6 +43,7 @@ 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); | ||||
| game_id get_cur_game(void); | ||||
| vec3_t vec3(float x, float y, float z); | ||||
| @@ -40,15 +51,16 @@ 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); | ||||
| bool world_to_screen(vec3_t vec, vec2_t screen); | ||||
| void engine_draw_text(int x, int y, char* s, rgb_t c); | ||||
| void draw_tracer(vec3_t start, vec3_t end, rgb_t c, float a, float w, float t); | ||||
| 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_ */ | ||||
							
								
								
									
										198
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										198
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										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; | ||||
| }  | ||||
							
								
								
									
										96
									
								
								src/util.c
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								src/util.c
									
									
									
									
									
								
							| @@ -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,34 +36,33 @@ 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_iClip > 0 && g_flNextAttack <= 0.0f && | ||||
|            g_flNextPrimaryAttack <= 0.0f; | ||||
| } | ||||
|  | ||||
| char* get_name(int ent_idx) { | ||||
|     hud_player_info_t info; | ||||
|     i_engine->pfnGetPlayerInfo(ent_idx, &info); | ||||
| @@ -70,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; | ||||
|  | ||||
| @@ -128,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) { | ||||
| @@ -183,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; | ||||
|     } | ||||
| @@ -204,6 +189,19 @@ void engine_draw_text(int x, int y, char* s, rgb_t c) { | ||||
|     i_engine->pfnDrawConsoleString(x, y, s); | ||||
| } | ||||
|  | ||||
| void draw_tracer(vec3_t start, vec3_t end, rgb_t c, float a, float w, | ||||
|                  float time) { | ||||
|     static const char* MDL_STR = "sprites/laserbeam.spr"; | ||||
|     static int beam_idx = i_engine->pEventAPI->EV_FindModelIndex(MDL_STR); | ||||
|  | ||||
|     float r = c.r / 255.f; | ||||
|     float g = c.g / 255.f; | ||||
|     float b = c.b / 255.f; | ||||
|  | ||||
|     i_engine->pEfxAPI->R_BeamPoints(start, end, beam_idx, time, w, 0, a, 0, 0, | ||||
|                                     0, r, g, b); | ||||
| } | ||||
|  | ||||
| void gl_drawbox(int x, int y, int w, int h, rgb_t c) { | ||||
|     /* Line width */ | ||||
|     const int lw = 1; | ||||
| @@ -253,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; | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user