Compare commits
	
		
			58 Commits
		
	
	
		
			1f3e531610
			...
			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 | 
							
								
								
									
										24
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,11 +1,15 @@ | |||||||
|  |  | ||||||
| # Need to use g++ because the sdk headers use classes | # Need to use g++ because the sdk headers use classes | ||||||
| CC=g++ | CC=g++ | ||||||
| INCLUDES=-Isrc/include/sdk/common -Isrc/include/sdk/public -Isrc/include/sdk/pm_shared -Isrc/include/sdk/engine | 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 $(INCLUDES) | CFLAGS=-Wall -Wextra -Wno-write-strings -m32 -fPIC -fpermissive $(INCLUDES) | ||||||
| LDFLAGS=-lm | 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 | BIN=libhlcheat.so | ||||||
|  |  | ||||||
| .PHONY: clean all inject | .PHONY: clean all inject | ||||||
| @@ -28,6 +32,12 @@ inject: $(BIN) | |||||||
| $(BIN): $(OBJS) | $(BIN): $(OBJS) | ||||||
| 	$(CC) $(CFLAGS) -shared -o $@ $(OBJS) $(LDFLAGS) | 	$(CC) $(CFLAGS) -shared -o $@ $(OBJS) $(LDFLAGS) | ||||||
|  |  | ||||||
| $(OBJS): obj/%.c.o : src/%.c | obj/%.c.o: src/%.c | ||||||
| 	@mkdir -p obj/features/ | 	@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) | 	$(CC) $(CFLAGS) -c -o $@ $< $(LDFLAGS) | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								README.org
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								README.org
									
									
									
									
									
								
							| @@ -1,12 +1,15 @@ | |||||||
| #+title: Half-Life cheat | #+title: Half-Life cheat (Original author: [[https://github.com/8dcc/][8dcc]]) | ||||||
| #+options: toc:nil | #+options: toc:nil | ||||||
| #+startup: showeverything | #+startup: showeverything | ||||||
| #+author: Wizzard (Original arthur: [[https://github.com/8dcc/][8dcc]]) | #+author: Wizzard | ||||||
|  |  | ||||||
| *Linux cheat for goldsrc games.* | *Linux cheat for goldsrc games.* | ||||||
|  |  | ||||||
| #+TOC: headlines 2 | #+TOC: headlines 2 | ||||||
|  |  | ||||||
|  | * WARNING | ||||||
|  | TO USE THIS YOU MUST BE RUNNING THE LEGACY BETA | ||||||
|  |  | ||||||
| * Description | * Description | ||||||
| Simple linux cheat for most goldsrc games, made in C. | Simple linux cheat for most goldsrc games, made in C. | ||||||
|  |  | ||||||
| @@ -15,6 +18,7 @@ Supported games: | |||||||
| - [[https://store.steampowered.com/app/10/CounterStrike/][Counter-Strike 1.6]] | - [[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/20/Team_Fortress_Classic/][Team Fortress Classic]] | ||||||
| - [[https://store.steampowered.com/app/30/Day_of_Defeat/][Day of Defeat]] | - [[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 | 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. | possible without his help. Make sure to check out his repo too. | ||||||
| @@ -23,41 +27,58 @@ Also make sure to check out [[https://github.com/deboogerxyz/ahc][deboogerxyz/ah | |||||||
|  |  | ||||||
| * Features | * Features | ||||||
|  |  | ||||||
| | Feature    | Command       | Values (0..n)          | | | Feature     | Description                       | | ||||||
| |------------+---------------+------------------------| | |-------------|-----------------------------------| | ||||||
| | Bhop       | =dz_bhop=       | off/on                 | | | Bhop        | Automatically jump when landing   | | ||||||
| | Autostrafe | =dz_autostrafe= | off/rage/legit         | | | Autostrafe  | Automatic strafing movement       | | ||||||
| | Aimbot     | =dz_aimbot=     | off/fov*               | | | Aimbot      | Aim assistance with FOV control   | | ||||||
| | Autoshoot  | =dz_autoshoot=  | off/on*                | | | Autoshoot   | Automatically shoot at enemies    | | ||||||
| | ESP        | =dz_esp=        | off/3d-box/name/all    | | | ESP         | See enemies through walls         | | ||||||
| | Chams      | =dz_chams=      | off/players/hands/all* | | | Chams       | Colored player models             | | ||||||
| | Crosshair  | =dz_crosshair=  | off/length             | | | Crosshair   | Custom crosshair                  | | ||||||
| | Tracers    | =dz_tracers=    | off/on*                | | | 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 | #+begin_quote | ||||||
| *Note:* Aimbot FOV goes from 0 (off) to 180 (all enemies) | *Note:* Aimbot FOV goes from 0 (off) to 180 (all enemies) | ||||||
| #+end_quote | #+end_quote | ||||||
|  |  | ||||||
| #+begin_quote |  | ||||||
| *Note:* If =dz_autoshoot= is enabled, and =dz_aimbot= is enabled, it will stop |  | ||||||
| attacking if there is no visible target. |  | ||||||
| #+end_quote |  | ||||||
|  |  | ||||||
| #+begin_quote | #+begin_quote | ||||||
| *Note:* Chams color can be changed from the =h_glColor4f()= function inside | *Note:* Chams color can be changed from the =h_glColor4f()= function inside | ||||||
| [[https://git.deadzone.lol/Wizzard/goldsource-cheat/src/branch/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. | console variables than more customization at runtime. | ||||||
| #+end_quote | #+end_quote | ||||||
|  |  | ||||||
| #+begin_quote | #+begin_quote | ||||||
| *Note:* Bullet tracer color, width and time can be changed at the bottom of the | *Note:* Bullet tracer color, width and time can be changed at the bottom of the | ||||||
| =bullet_tracers()= function inside [[https://git.deadzone.lol/Wizzard/goldsource-cheat/src/branch/main/src/features/misc.c][src/features/misc.c]]. See previous chams note. | =bullet_tracers()= function inside [[https://git.deadzone.lol/Wizzard/goldsrc-cheat/src/branch/main/src/features/misc.c][src/features/misc.c]]. See previous chams note. | ||||||
| #+end_quote | #+end_quote | ||||||
|  |  | ||||||
| * Building | * Building | ||||||
| #+begin_src console | #+begin_src console | ||||||
| $ git clone --recurse-submodules https://git.deadzone.lol/Wizzard/goldsource-cheat | $ git clone --recurse-submodules https://git.deadzone.lol/Wizzard/goldsrc-cheat | ||||||
| $ cd goldsource-cheat | $ cd goldsource-cheat | ||||||
| $ make | $ make | ||||||
| ... | ... | ||||||
|   | |||||||
							
								
								
									
										
											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
									
								
								src/cvars.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/cvars.c
									
									
									
									
									
								
							| @@ -1,30 +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(autoshoot); |  | ||||||
| DECL_CVAR(esp); |  | ||||||
| DECL_CVAR(chams); |  | ||||||
| DECL_CVAR(crosshair); |  | ||||||
| DECL_CVAR(tracers); |  | ||||||
| DECL_CVAR(clmove); |  | ||||||
| DECL_CVAR(watermark); |  | ||||||
|  |  | ||||||
| bool cvars_init(void) { |  | ||||||
|     REGISTER_CVAR(bhop, 1); |  | ||||||
|     REGISTER_CVAR(autostrafe, 1); |  | ||||||
|     REGISTER_CVAR(aimbot, 0); |  | ||||||
|     REGISTER_CVAR(autoshoot, 0); /* Only works with aimbot enabled */ |  | ||||||
|     REGISTER_CVAR(esp, 3); |  | ||||||
|     REGISTER_CVAR(chams, 1); |  | ||||||
|     REGISTER_CVAR(crosshair, 0); |  | ||||||
|     REGISTER_CVAR(tracers, 1); |  | ||||||
|     REGISTER_CVAR(clmove, 0); |  | ||||||
|     REGISTER_CVAR(watermark, 1); |  | ||||||
|  |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
							
								
								
									
										101
									
								
								src/detour.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/detour.c
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <unistd.h>   /* getpagesize */ | #include <unistd.h>   /* getpagesize */ | ||||||
| #include <sys/mman.h> /* mprotect */ | #include <sys/mman.h> /* mprotect */ | ||||||
|  | #include <stdio.h>    /* printf */ | ||||||
|  |  | ||||||
| #include "include/detour.h" | #include "include/detour.h" | ||||||
|  |  | ||||||
| @@ -19,6 +20,11 @@ | |||||||
| #define PAGE_ALIGN(x)      ((x + PAGE_SIZE - 1) & PAGE_MASK) | #define PAGE_ALIGN(x)      ((x + PAGE_SIZE - 1) & PAGE_MASK) | ||||||
| #define PAGE_ALIGN_DOWN(x) (PAGE_ALIGN(x) - PAGE_SIZE) | #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) { | static bool protect_addr(void* ptr, int new_flags) { | ||||||
|     void* p  = (void*)PAGE_ALIGN_DOWN((detour_ptr_t)ptr); |     void* p  = (void*)PAGE_ALIGN_DOWN((detour_ptr_t)ptr); | ||||||
|     int pgsz = getpagesize(); |     int pgsz = getpagesize(); | ||||||
| @@ -49,6 +55,9 @@ static uint8_t def_jmp_bytes[] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| void detour_init(detour_data_t* data, void* orig, void* hook) { | void detour_init(detour_data_t* data, void* orig, void* hook) { | ||||||
|  |     if (!orig || !hook) | ||||||
|  |         return; | ||||||
|  |          | ||||||
|     data->detoured = false; |     data->detoured = false; | ||||||
|     data->orig     = orig; |     data->orig     = orig; | ||||||
|     data->hook     = hook; |     data->hook     = hook; | ||||||
| @@ -108,3 +117,95 @@ bool detour_del(detour_data_t* d) { | |||||||
|  |  | ||||||
|     return false; |     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,106 +1,417 @@ | |||||||
|  |  | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
| #include "features.h" |  | ||||||
| #include "../include/sdk.h" | #include "../include/sdk.h" | ||||||
| #include "../include/cvars.h" |  | ||||||
| #include "../include/util.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 HITBOX_HEAD      0 | ||||||
| #define HEAD_OFFSET 25.f | #define HITBOX_CHEST     1 | ||||||
|  | #define HITBOX_STOMACH   2 | ||||||
|  | #define HITBOX_PELVIS    3 | ||||||
|  | #define HITBOX_LEFTARM   4 | ||||||
|  | #define HITBOX_RIGHTARM  5 | ||||||
|  | #define HITBOX_LEFTLEG   6 | ||||||
|  | #define HITBOX_RIGHTLEG  7 | ||||||
|  | #define HITBOX_NEAREST   4 | ||||||
|  | #define MAX_HITBOXES     7 | ||||||
|  |  | ||||||
| /* Scale factor for aim punch */ | #define AIM_PUNCH_MULT 2.0f | ||||||
| #define AIM_PUNCH_MULT 2 |  | ||||||
|  |  | ||||||
| static bool is_visible(vec3_t start, vec3_t end) { | #define SMOOTHING_FACTOR 3.0f | ||||||
|     /* Syntax: PM_TraceLine(start, end, flags, usehulll, ignore_pe); */ |  | ||||||
|     pmtrace_t* tr = |  | ||||||
|       i_engine->PM_TraceLine(start, end, PM_TRACELINE_PHYSENTSONLY, 2, -1); |  | ||||||
|  |  | ||||||
|     /* We didn't hit a valid entity */ | #define PITCH 0 | ||||||
|     if (tr->ent <= 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; |         return false; | ||||||
|      |      | ||||||
|     /* Get entity index from physents, check if we can't get a valid player */ |     pmtrace_t* trace = i_engine->PM_TraceLine(eye_pos, hitbox->origin, PM_TRACELINE_PHYSENTSONLY, 2, -1); | ||||||
|     const int ent_idx = i_pmove->physents[tr->ent].info; |  | ||||||
|     if (!get_player(ent_idx)) |  | ||||||
|         return false; |  | ||||||
|      |      | ||||||
|     /* We hit a valid player */ |     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 true; | ||||||
|         } |         } | ||||||
|          |          | ||||||
| static vec3_t get_closest_delta(vec3_t viewangles) { |         return false; | ||||||
|     /* Compensate aim punch. We get g_punchAngles from CalcRefdef hook */ |     } | ||||||
|     viewangles.x += g_punchAngles.x * AIM_PUNCH_MULT; |  | ||||||
|     viewangles.y += g_punchAngles.y * AIM_PUNCH_MULT; |  | ||||||
|     viewangles.z += g_punchAngles.z * AIM_PUNCH_MULT; |  | ||||||
|      |      | ||||||
|     vec3_t view_height; |     return true; | ||||||
|     i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height); | } | ||||||
|     vec3_t local_eyes = vec_add(localplayer->origin, view_height); |  | ||||||
|  |  | ||||||
|     /* These 2 vars are used to store the best target across iterations. | typedef struct { | ||||||
|      * NOTE: The default value of best_fov will be the aimbot fov */ |     cl_entity_t* entity; | ||||||
|     float best_fov    = dz_aimbot->value; |     float fov; | ||||||
|     vec3_t best_delta = { 0, 0, 0 }; |     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++) { |     for (int i = 1; i <= i_engine->GetMaxClients(); i++) { | ||||||
|         cl_entity_t* ent = get_player(i); |         cl_entity_t* ent = get_player(i); | ||||||
|          |          | ||||||
|         if (!is_alive(ent) || is_friend(ent)) |         if (!ent || !is_alive(ent)) | ||||||
|             continue; |             continue; | ||||||
|              |              | ||||||
|         /* TODO: Get bones origin instead of calculating from ent origin */ |         if (!g_settings.aimbot_team_attack && is_friend(ent)) | ||||||
|         vec3_t head_pos = ent->origin; |  | ||||||
|         if (ent->curstate.usehull != 1) /* Get head if not crouched */ |  | ||||||
|             head_pos.z += HEAD_OFFSET; |  | ||||||
|  |  | ||||||
|         if (!is_visible(local_eyes, head_pos)) /* We can't see player */ |  | ||||||
|             continue; |             continue; | ||||||
|          |          | ||||||
|         const vec3_t enemy_angle = vec_to_ang(vec_sub(head_pos, local_eyes)); |         hitbox_t target_hitbox; | ||||||
|         const vec3_t delta       = vec_sub(enemy_angle, viewangles); |         bool hitbox_found = false; | ||||||
|         vec_norm(delta); |  | ||||||
|          |          | ||||||
|         float fov = hypotf(delta.x, delta.y); |         if (current_hitbox == HITBOX_NEAREST) { | ||||||
|         if (fov > 360.0f) |             const int hitbox_priority[] = {HITBOX_HEAD, HITBOX_CHEST, HITBOX_STOMACH, HITBOX_PELVIS}; | ||||||
|             fov = remainderf(fov, 360.0f); |  | ||||||
|         if (fov > 180.0f) |  | ||||||
|             fov = 360.0f - fov; |  | ||||||
|              |              | ||||||
|         if (fov < best_fov) { |             for (int h = 0; h < 4; h++) { | ||||||
|             best_fov = fov; |                 if (get_hitbox(ent, hitbox_priority[h], &target_hitbox)) { | ||||||
|             vec_copy(best_delta, delta); |                     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); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|     return best_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_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) { | void aimbot(usercmd_t* cmd) { | ||||||
|     if (!CVAR_ON(aimbot) || !(cmd->buttons & IN_ATTACK) || !can_shoot()) |     if (!g_settings.aimbot_enabled) | ||||||
|         return; |         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; |     vec3_t engine_viewangles; | ||||||
|     i_engine->GetViewAngles(engine_viewangles); |     i_engine->GetViewAngles(engine_viewangles); | ||||||
|      |      | ||||||
|     /* TODO: Add setting for lowest health */ |     if (g_settings.aimbot_smoothing_enabled && !g_settings.aimbot_silent) { | ||||||
|     vec3_t best_delta = get_closest_delta(engine_viewangles); |         vec3_t delta; | ||||||
|     if (!vec_is_zero(best_delta)) { |         delta.x = aim_angles.x - engine_viewangles.x; | ||||||
|         /* NOTE: We can divide the best delta here to add smoothing */ |         delta.y = aim_angles.y - engine_viewangles.y; | ||||||
|  |         delta.z = 0.0f; | ||||||
|          |          | ||||||
|         engine_viewangles.x += best_delta.x; |         if (delta.y > 180.0f) delta.y -= 360.0f; | ||||||
|         engine_viewangles.y += best_delta.y; |         if (delta.y < -180.0f) delta.y += 360.0f; | ||||||
|         engine_viewangles.z += best_delta.z; |          | ||||||
|     } else if (CVAR_ON(autoshoot)) { |         float smooth_factor = g_settings.aimbot_smooth; | ||||||
|         /* No valid target and we have autoshoot, don't shoot */ |          | ||||||
|         cmd->buttons &= ~IN_ATTACK; |         if (g_currentWeaponID == WEAPON_AK47 && shot_count > 1) { | ||||||
|  |             smooth_factor *= 0.7f; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|     vec_copy(cmd->viewangles, engine_viewangles); |         if (best_target.fov < g_settings.aimbot_fov * 0.5f) { | ||||||
|  |             smooth_factor *= 0.6f; | ||||||
|     /* NOTE: Uncomment to disable silent aim */ |         } | ||||||
|     /* i_engine->SetViewAngles(engine_viewangles); */ |          | ||||||
|  |         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); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     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 "features.h" | ||||||
| #include "../include/globals.h" | #include "../include/globals.h" | ||||||
| #include "../include/cvars.h" | #include "../include/settings.h" | ||||||
| #include "../include/util.h" | #include "../include/util.h" | ||||||
|  |  | ||||||
| #include <GL/gl.h> | #include <GL/gl.h> | ||||||
| @@ -15,7 +14,7 @@ enum chams_settings { | |||||||
| visible_flags visible_mode; | visible_flags visible_mode; | ||||||
|  |  | ||||||
| bool chams(void* this_ptr) { | bool chams(void* this_ptr) { | ||||||
|     const int setting = dz_chams->value == 5.0f ? 7 : dz_chams->value; |     const int setting = g_settings.chams ? PLAYER_CHAMS : DISABLED; | ||||||
|     if (setting == DISABLED) |     if (setting == DISABLED) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
| @@ -39,6 +38,9 @@ bool chams(void* this_ptr) { | |||||||
|  |  | ||||||
|     const bool friendly = is_friend(ent); |     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 */ |     /* If we got here it means we are rendering a valid player */ | ||||||
|     glDisable(GL_TEXTURE_2D); |     glDisable(GL_TEXTURE_2D); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,17 +1,11 @@ | |||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "features.h" | #include "features.h" | ||||||
| #include "../include/globals.h" | #include "../include/globals.h" | ||||||
| #include "../include/cvars.h" | #include "../include/settings.h" | ||||||
| #include "../include/util.h" | #include "../include/util.h" | ||||||
|  | #include "../include/game_detection.h" | ||||||
|  |  | ||||||
| /* For dz_esp */ | // ESP enums moved to settings.h as esp_mode_t | ||||||
| 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 */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| bool gl_draw3dbox(vec3_t o, int bh, int bw, int lw) { | 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) { | void esp(void) { | ||||||
|     const int setting = (int)dz_esp->value; |     const int setting = g_settings.esp_mode; | ||||||
|     if (setting == ESP_OFF) |     if (setting == ESP_OFF) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     /* Iterate all clients */ |  | ||||||
|     for (int i = 1; i <= i_engine->GetMaxClients(); i++) { |     for (int i = 1; i <= i_engine->GetMaxClients(); i++) { | ||||||
|         cl_entity_t* ent = get_player(i); |         cl_entity_t* ent = get_player(i); | ||||||
|  |  | ||||||
|         if (!valid_player(ent) || !is_alive(ent) || vec_is_zero(ent->origin)) |         if (!valid_player(ent) || !is_alive(ent) || vec_is_zero(ent->origin)) | ||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         const int bh = (ent->curstate.usehull == 1) ? 44 : 70; |         if (is_friend(ent) && !g_settings.esp_friendly) | ||||||
|         /* const int bw = 25; */ |             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)) |         if (setting & ESP_BOX && !gl_draw2dbox(ent->origin, bh)) | ||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         /* Rest of the loop is for name esp, if var is not enabled, continue */ |  | ||||||
|         if (!(setting & ESP_NAME)) |         if (!(setting & ESP_NAME)) | ||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         /* Draw name on top of the player. */ |         vec3_t name_pos = vec3(ent->origin.x, ent->origin.y, ent->origin.z + bh + 5); | ||||||
|         vec3_t top = vec3(ent->origin.x, ent->origin.y, ent->origin.z + bh); |         vec2_t s_name_pos; | ||||||
|         vec2_t s_top; |         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 }); | ||||||
|         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 }); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
|  |  | ||||||
| #ifndef FEATURES_H_ | #ifndef FEATURES_H_ | ||||||
| #define FEATURES_H_ | #define FEATURES_H_ | ||||||
|  |  | ||||||
| @@ -11,8 +10,13 @@ enum visible_flags { | |||||||
|     FRIEND_VISIBLE     = 3, |     FRIEND_VISIBLE     = 3, | ||||||
|     FRIEND_NOT_VISIBLE = 4, |     FRIEND_NOT_VISIBLE = 4, | ||||||
|     HANDS              = 5, |     HANDS              = 5, | ||||||
|  |     SCOPE              = 6, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
| /* src/features/movement.c */ | /* src/features/movement.c */ | ||||||
| @@ -29,8 +33,29 @@ bool chams(void* this_ptr); | |||||||
| /* src/features/aim.c */ | /* src/features/aim.c */ | ||||||
| void aimbot(usercmd_t* cmd); | void aimbot(usercmd_t* cmd); | ||||||
|  |  | ||||||
|  | /* src/features/no_recoil.c */ | ||||||
|  | void no_recoil(usercmd_t* cmd); | ||||||
|  |  | ||||||
| /* src/features/misc.c */ | /* src/features/misc.c */ | ||||||
| void custom_crosshair(void); | void custom_crosshair(void); | ||||||
| void bullet_tracers(usercmd_t* cmd); | void bullet_tracers(usercmd_t* cmd); | ||||||
|  |  | ||||||
|  | /* 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_ */ | #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 "features.h" | ||||||
| #include "../include/sdk.h" | #include "../include/sdk.h" | ||||||
| #include "../include/globals.h" | #include "../include/globals.h" | ||||||
| #include "../include/cvars.h" |  | ||||||
| #include "../include/util.h" | #include "../include/util.h" | ||||||
|  | #include "../include/game_detection.h" | ||||||
|  | #include "../include/settings.h" | ||||||
|  |  | ||||||
| void custom_crosshair(void) { | void custom_crosshair(void) { | ||||||
|     if (!CVAR_ON(crosshair)) |     if (!g_settings.custom_crosshair) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     /* Get window size, and then the center. */ |     /* Get window size, and then the center. */ | ||||||
| @@ -14,7 +14,7 @@ void custom_crosshair(void) { | |||||||
|     int my = game_info->m_height / 2; |     int my = game_info->m_height / 2; | ||||||
|  |  | ||||||
|     /* The real length is sqrt(2 * (len^2)) */ |     /* The real length is sqrt(2 * (len^2)) */ | ||||||
|     const int len   = dz_crosshair->value; |     const int len   = 5; | ||||||
|     const int gap   = 1; |     const int gap   = 1; | ||||||
|     const float w   = 1; |     const float w   = 1; | ||||||
|     const rgb_t col = { 255, 255, 255 }; |     const rgb_t col = { 255, 255, 255 }; | ||||||
| @@ -30,12 +30,35 @@ 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) { | void bullet_tracers(usercmd_t* cmd) { | ||||||
|     /* Only draw if we are holding attack and we can shoot */ |     if (!g_settings.tracers || !is_alive(localplayer)) | ||||||
|     if (!CVAR_ON(tracers) || !(cmd->buttons & IN_ATTACK) || !can_shoot() || |  | ||||||
|         !is_alive(localplayer)) |  | ||||||
|         return; |         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 */ |     /* Get player eye pos, start of tracer */ | ||||||
|     vec3_t view_height; |     vec3_t view_height; | ||||||
|     i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height); |     i_engine->pEventAPI->EV_LocalPlayerViewheight(view_height); | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <math.h> | #include <math.h> | ||||||
|  |  | ||||||
| #include "features.h" | #include "features.h" | ||||||
| #include "../include/sdk.h" | #include "../include/sdk.h" | ||||||
| #include "../include/globals.h" | #include "../include/globals.h" | ||||||
| #include "../include/cvars.h" | #include "../include/settings.h" | ||||||
| #include "../include/util.h" | #include "../include/util.h" | ||||||
|  |  | ||||||
| static void autostrafe_legit(usercmd_t* cmd) { | 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/deboogerxyz/ahc/blob/0492646e28dd7234a8cd431d37b152dc18a21b04/ahc.c#L201 | ||||||
|  *   https://github.com/NullHooks/NullHooks/blob/535351569ca599cadd21a286d88098b6dc057a46/src/core/features/movement/bhop.cpp#L73 |  *   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) { | static void autostrafe_rage(usercmd_t* cmd) { | ||||||
|     if (i_pmove->movetype != MOVETYPE_WALK) |     if (i_pmove->movetype != MOVETYPE_WALK) | ||||||
|         return; |         return; | ||||||
| @@ -48,12 +49,10 @@ static void autostrafe_rage(usercmd_t* cmd) { | |||||||
|  |  | ||||||
|     float best_delta = acosf(term); |     float best_delta = acosf(term); | ||||||
|  |  | ||||||
|     /* Use engine viewangles in case we do something nasty with cmd's angles */ |  | ||||||
|     vec3_t viewangles; |     vec3_t viewangles; | ||||||
|     i_engine->GetViewAngles(viewangles); |     i_engine->GetViewAngles(viewangles); | ||||||
|  |  | ||||||
|     /* Get our desired angles and delta */ |     float yaw = viewangles.y * DEG2RAD_CACHED; | ||||||
|     float yaw        = DEG2RAD(viewangles.y); |  | ||||||
|     float vel_dir = atan2f(i_pmove->velocity.y, i_pmove->velocity.x) - yaw; |     float vel_dir = atan2f(i_pmove->velocity.y, i_pmove->velocity.x) - yaw; | ||||||
|     float target_ang = atan2f(-cmd->sidemove, cmd->forwardmove); |     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); | ||||||
| @@ -65,7 +64,7 @@ static void autostrafe_rage(usercmd_t* cmd) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void bhop(usercmd_t* cmd) { | void bhop(usercmd_t* cmd) { | ||||||
|     if (!CVAR_ON(bhop) || i_pmove->movetype != MOVETYPE_WALK) |     if (!g_settings.bhop || i_pmove->movetype != MOVETYPE_WALK) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     static bool was_in_air = false; |     static bool was_in_air = false; | ||||||
| @@ -81,18 +80,8 @@ void bhop(usercmd_t* cmd) { | |||||||
|     was_in_air = (i_pmove->flags & FL_ONGROUND) == 0; |     was_in_air = (i_pmove->flags & FL_ONGROUND) == 0; | ||||||
|  |  | ||||||
|     /* Autostrafe if enabled. Check if we are in the air and holding space. */ |     /* Autostrafe if enabled. Check if we are in the air and holding space. */ | ||||||
|     if (is_jumping) { |     if (is_jumping && g_settings.autostrafe) { | ||||||
|         switch ((int)dz_autostrafe->value) { |  | ||||||
|             case 1: |  | ||||||
|         autostrafe_rage(cmd); |         autostrafe_rage(cmd); | ||||||
|                 break; |  | ||||||
|             case 2: |  | ||||||
|                 autostrafe_legit(cmd); |  | ||||||
|                 break; |  | ||||||
|             case 0: |  | ||||||
|             default: |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -101,18 +90,15 @@ void bhop(usercmd_t* cmd) { | |||||||
|  *   https://github.com/deboogerxyz/ahc/blob/0492646e28dd7234a8cd431d37b152dc18a21b04/ahc.c#L377 |  *   https://github.com/deboogerxyz/ahc/blob/0492646e28dd7234a8cd431d37b152dc18a21b04/ahc.c#L377 | ||||||
|  */ |  */ | ||||||
| void correct_movement(usercmd_t* cmd, vec3_t old_angles) { | void correct_movement(usercmd_t* cmd, vec3_t old_angles) { | ||||||
|     float old_y = old_angles.y + (old_angles.y < 0 ? 360 : 0); |     float delta_y = fmodf(cmd->viewangles.y - old_angles.y + 540.0f, 360.0f) - 180.0f; // Normalized delta in [-180, 180) | ||||||
|     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_rad = delta_y * DEG2RAD_CACHED; | ||||||
|  |     float delta_cos = cosf(delta_rad); | ||||||
|  |     float delta_sin = sinf(delta_rad); | ||||||
|  |  | ||||||
|     float forward = cmd->forwardmove; |     float forward = cmd->forwardmove; | ||||||
|     float side = cmd->sidemove; |     float side = cmd->sidemove; | ||||||
|  |  | ||||||
|     cmd->forwardmove = |     cmd->forwardmove = delta_cos * forward - delta_sin * side; | ||||||
|       cos(DEG2RAD(delta)) * forward + cos(DEG2RAD(delta + 90)) * side; |     cmd->sidemove = delta_sin * forward + delta_cos * side; | ||||||
|     cmd->sidemove = |  | ||||||
|       sin(DEG2RAD(delta)) * forward + sin(DEG2RAD(delta + 90)) * 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,8 +1,7 @@ | |||||||
|  |  | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||||
| #include <sys/mman.h> /* PROT_* */ | #include <sys/mman.h> | ||||||
|  |  | ||||||
| #include "include/globals.h" | #include "include/globals.h" | ||||||
| #include "include/sdk.h" | #include "include/sdk.h" | ||||||
| @@ -11,9 +10,12 @@ | |||||||
| game_id this_game_id = HL; | game_id this_game_id = HL; | ||||||
| vec3_t g_punchAngles = { 0, 0, 0 }; | vec3_t g_punchAngles = { 0, 0, 0 }; | ||||||
|  |  | ||||||
| /* Weapon info */ |  | ||||||
| float g_flNextAttack = 0.f, g_flNextPrimaryAttack = 0.f; | float g_flNextAttack = 0.f, g_flNextPrimaryAttack = 0.f; | ||||||
| int g_iClip = 0; | int g_iClip = 0; | ||||||
|  | int g_currentWeaponID = -1; | ||||||
|  |  | ||||||
|  | double g_flCurrentTime = 0.0; | ||||||
|  |  | ||||||
|  |  | ||||||
| void* hw; | void* hw; | ||||||
| void** h_client; | void** h_client; | ||||||
| @@ -23,23 +25,17 @@ DECL_INTF(playermove_t, pmove); | |||||||
| DECL_INTF(engine_studio_api_t, enginestudio); | DECL_INTF(engine_studio_api_t, enginestudio); | ||||||
| DECL_INTF(StudioModelRenderer_t, studiomodelrenderer); | DECL_INTF(StudioModelRenderer_t, studiomodelrenderer); | ||||||
|  |  | ||||||
| /* Game struct with some useful info */ |  | ||||||
| game_t* game_info; | game_t* game_info; | ||||||
|  |  | ||||||
| /* Array of extra_player_info's for each player */ |  | ||||||
| void* player_extra_info; | void* player_extra_info; | ||||||
|  |  | ||||||
| /* Updated in CL_CreateMove hook */ |  | ||||||
| cl_entity_t* localplayer = NULL; | cl_entity_t* localplayer = NULL; | ||||||
|  |  | ||||||
|  | float* scr_fov_value = NULL; | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
| bool globals_init(void) { | 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); |     hw = dlopen("hw.so", RTLD_LAZY | RTLD_NOLOAD); | ||||||
|     if (!hw) { |     if (!hw) { | ||||||
|         printf("goldsource-cheat: globals_init: can't open hw.so\n"); |         printf("goldsource-cheat: globals_init: can't open hw.so\n"); | ||||||
| @@ -52,7 +48,6 @@ bool globals_init(void) { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Get symbol addresses using dlsym and the handler we just opened */ |  | ||||||
|     i_engine       = (cl_enginefunc_t*)dlsym(hw, "cl_enginefuncs"); |     i_engine       = (cl_enginefunc_t*)dlsym(hw, "cl_enginefuncs"); | ||||||
|     i_client       = (cl_clientfunc_t*)dlsym(hw, "cl_funcs"); |     i_client       = (cl_clientfunc_t*)dlsym(hw, "cl_funcs"); | ||||||
|     i_pmove        = *(playermove_t**)dlsym(hw, "pmove"); |     i_pmove        = *(playermove_t**)dlsym(hw, "pmove"); | ||||||
| @@ -65,6 +60,8 @@ bool globals_init(void) { | |||||||
|  |  | ||||||
|     game_info = *(game_t**)dlsym(hw, "game"); |     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 || |     if (!i_engine || !i_client || !i_pmove || !i_enginestudio || | ||||||
|         !i_studiomodelrenderer || !game_info) { |         !i_studiomodelrenderer || !game_info) { | ||||||
|         printf("goldsource-cheat: globals_init: couldn't load some symbols\n"); |         printf("goldsource-cheat: globals_init: couldn't load some symbols\n"); | ||||||
|   | |||||||
							
								
								
									
										433
									
								
								src/hooks.c
									
									
									
									
									
								
							
							
						
						
									
										433
									
								
								src/hooks.c
									
									
									
									
									
								
							| @@ -1,11 +1,39 @@ | |||||||
|  | #include <stdio.h> | ||||||
|  | #include <math.h> | ||||||
|  |  | ||||||
|  | #include "include/settings.h" | ||||||
| #include "include/hooks.h" | #include "include/hooks.h" | ||||||
| #include "include/sdk.h" |  | ||||||
| #include "include/globals.h" |  | ||||||
| #include "include/util.h" | #include "include/util.h" | ||||||
| #include "include/cvars.h" | #include "include/sdk.h" | ||||||
| #include "include/detour.h"    /* 8dcc/detour-lib */ | #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 "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 */ | /* Normal VMT hooks */ | ||||||
| DECL_HOOK(CL_CreateMove); | DECL_HOOK(CL_CreateMove); | ||||||
| @@ -13,18 +41,45 @@ DECL_HOOK(HUD_Redraw); | |||||||
| DECL_HOOK(StudioRenderModel); | DECL_HOOK(StudioRenderModel); | ||||||
| DECL_HOOK(CalcRefdef); | DECL_HOOK(CalcRefdef); | ||||||
| DECL_HOOK(HUD_PostRunCmd); | DECL_HOOK(HUD_PostRunCmd); | ||||||
|  | key_event_func_t ho_HUD_Key_Event = NULL;  // Manually declare the hook | ||||||
|  |  | ||||||
| /* OpenGL hooks */ | // Manual declarations for third-person hooks | ||||||
| DECL_HOOK(glColor4f); | 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 */ | /* Detour hooks */ | ||||||
| static detour_data_t detour_data_clmove; | 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) { | 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 */ |     /* VMT hooking */ | ||||||
|     HOOK(i_client, CL_CreateMove); |     HOOK(i_client, CL_CreateMove); | ||||||
|     HOOK(i_client, HUD_Redraw); |     HOOK(i_client, HUD_Redraw); | ||||||
| @@ -32,56 +87,199 @@ bool hooks_init(void) { | |||||||
|     HOOK(i_client, CalcRefdef); |     HOOK(i_client, CalcRefdef); | ||||||
|     HOOK(i_client, HUD_PostRunCmd); |     HOOK(i_client, HUD_PostRunCmd); | ||||||
|      |      | ||||||
|     /* OpenGL hooks */ |     ho_CL_IsThirdPerson = i_client->CL_IsThirdPerson; | ||||||
|     GL_HOOK(glColor4f); |     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; | ||||||
|  |  | ||||||
|  |     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"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|      |      | ||||||
|     /* Detour hooks */ |  | ||||||
|     void* clmove_ptr = dlsym(hw, "CL_Move"); |     void* clmove_ptr = dlsym(hw, "CL_Move"); | ||||||
|     if (!clmove_ptr) |     if (!clmove_ptr) { | ||||||
|  |         i_engine->Con_Printf("Failed to find CL_Move\n"); | ||||||
|         return false; |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Initialize detour_data_clmove struct for detour, and add the hook */ |     /* Initialize detour_data_clmove struct for detour, and add the hook */ | ||||||
|     detour_init(&detour_data_clmove, clmove_ptr, (void*)h_CL_Move); |     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; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hooks_restore(void) { | void hooks_restore(void) { | ||||||
|  |     /* 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); |         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) { | 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); |     ORIGINAL(CL_CreateMove, frametime, cmd, active); | ||||||
|  |  | ||||||
|     vec3_t old_angles = cmd->viewangles; |     vec3_t old_angles = cmd->viewangles; | ||||||
|      |      | ||||||
|     /* Declared in globals.c */ |     float origForward = cmd->forwardmove; | ||||||
|     localplayer = i_engine->GetLocalPlayer(); |     float origSide = cmd->sidemove; | ||||||
|  |     float origUp = cmd->upmove; | ||||||
|  |     int origButtons = cmd->buttons; | ||||||
|  |  | ||||||
|  |     fov_adjust(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); |         bhop(cmd); | ||||||
|  |         no_recoil(cmd);  // Apply recoil control before aimbot | ||||||
|         aimbot(cmd); |         aimbot(cmd); | ||||||
|         bullet_tracers(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); |     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) { | int h_HUD_Redraw(float time, int intermission) { | ||||||
|  |     force_view_angles(); | ||||||
|  |      | ||||||
|     int ret = ORIGINAL(HUD_Redraw, time, intermission); |     int ret = ORIGINAL(HUD_Redraw, time, intermission); | ||||||
|  |  | ||||||
|     if (dz_watermark->value) { |     if (g_settings.watermark) { | ||||||
|         /* 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/goldsource-cheat", (rgb_t){ 0, 255, 255 }); |         engine_draw_text(5, 5, "https://git.deadzone.lol/Wizzard/goldsrc-cheat", color); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     esp(); |     esp(); | ||||||
|  |      | ||||||
|     custom_crosshair(); |     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; |     return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -98,7 +296,13 @@ void h_CalcRefdef(ref_params_t* params) { | |||||||
|     /* Store punch angles for CreateMove */ |     /* Store punch angles for CreateMove */ | ||||||
|     vec_copy(g_punchAngles, params->punchangle); |     vec_copy(g_punchAngles, params->punchangle); | ||||||
|      |      | ||||||
|  |     /* Call original CalcRefdef */ | ||||||
|     ORIGINAL(CalcRefdef, params); |     ORIGINAL(CalcRefdef, params); | ||||||
|  |      | ||||||
|  |     /* Apply third-person camera with direct view modification */ | ||||||
|  |     if (g_settings.thirdperson) { | ||||||
|  |         thirdperson_modify_view(params); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
| @@ -108,12 +312,23 @@ void h_HUD_PostRunCmd(struct local_state_s* from, struct local_state_s* to, | |||||||
|                       unsigned int random_seed) { |                       unsigned int random_seed) { | ||||||
|     ORIGINAL(HUD_PostRunCmd, from, to, cmd, runfuncs, time, random_seed); |     ORIGINAL(HUD_PostRunCmd, from, to, cmd, runfuncs, time, random_seed); | ||||||
|  |  | ||||||
|  |     g_flCurrentTime = time; | ||||||
|  |  | ||||||
|     /* Store attack information to check if we can shoot */ |     /* Store attack information to check if we can shoot */ | ||||||
|     if (runfuncs) { |     if (runfuncs) { | ||||||
|         g_flNextAttack = to->client.m_flNextAttack; |         g_flNextAttack = to->client.m_flNextAttack; | ||||||
|         g_flNextPrimaryAttack = |         g_flNextPrimaryAttack = | ||||||
|           to->weapondata[to->client.m_iId].m_flNextPrimaryAttack; |           to->weapondata[to->client.m_iId].m_flNextPrimaryAttack; | ||||||
|         g_iClip = to->weapondata[to->client.m_iId].m_iClip; |         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); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -158,16 +373,186 @@ void h_glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { | |||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ORIGINAL(glColor4f, r, g, b, a); |     /* This part is executed regardless of the visible_mode. | ||||||
|  |      * NOTE: Not calling original breaks chams. */ | ||||||
|  |     if (real_glColor4f) | ||||||
|  |         real_glColor4f(r, g, b, a); | ||||||
| } | } | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
| void h_CL_Move() { | /* | ||||||
|     if (dz_clmove->value != 0) { |  * Simple passthrough to thirdperson module | ||||||
|         for (int i = 0; i < (int)dz_clmove->value; i++) |  */ | ||||||
|             CALL_ORIGINAL(detour_data_clmove, clmove_type); | int h_CL_IsThirdPerson(void) { | ||||||
|  |     // We still need this to tell the engine we're in third person view | ||||||
|  |     return thirdperson_is_active(); | ||||||
| } | } | ||||||
|  |  | ||||||
|     CALL_ORIGINAL(detour_data_clmove, clmove_type); | /* | ||||||
|  |  * 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; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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,48 +0,0 @@ | |||||||
|  |  | ||||||
| #ifndef CVARS_H_ |  | ||||||
| #define CVARS_H_ |  | ||||||
|  |  | ||||||
| #include "sdk.h" |  | ||||||
| #include "globals.h" |  | ||||||
|  |  | ||||||
| #define CVAR_PREFIX  "dz_" |  | ||||||
| #define CVAR_HACK_ID 0x4000 /* (1<<14) One that is not in use by the game */ |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  *  DECL_CVAR: Declares cvar variable in source file. |  | ||||||
|  *  DECL_CVAR_EXTERN: Same but for headers. |  | ||||||
|  *  REGISTER_CVAR: Create the cvar, return cvar_t* |  | ||||||
|  *  CVAR_ON: Returns true if the cvar is non-zero |  | ||||||
|  * |  | ||||||
|  * prefix | meaning |  | ||||||
|  * -------+------------------------------- |  | ||||||
|  * dz_*   | cvar variable |  | ||||||
|  */ |  | ||||||
| #define DECL_CVAR(name) cvar_t* dz_##name = NULL; |  | ||||||
|  |  | ||||||
| #define DECL_CVAR_EXTERN(name) extern cvar_t* dz_##name; |  | ||||||
|  |  | ||||||
| #define REGISTER_CVAR(name, value) \ |  | ||||||
|     dz_##name =                    \ |  | ||||||
|       i_engine->pfnRegisterVariable(CVAR_PREFIX #name, #value, CVAR_HACK_ID); |  | ||||||
|  |  | ||||||
| #define CVAR_ON(name) (dz_##name->value != 0.0f) |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| DECL_CVAR_EXTERN(bhop); |  | ||||||
| DECL_CVAR_EXTERN(autostrafe); |  | ||||||
| DECL_CVAR_EXTERN(aimbot); |  | ||||||
| DECL_CVAR_EXTERN(autoshoot); |  | ||||||
| DECL_CVAR_EXTERN(esp); |  | ||||||
| DECL_CVAR_EXTERN(chams); |  | ||||||
| DECL_CVAR_EXTERN(crosshair); |  | ||||||
| DECL_CVAR_EXTERN(tracers); |  | ||||||
| DECL_CVAR_EXTERN(clmove); |  | ||||||
| DECL_CVAR_EXTERN(watermark); |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| 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_ | #ifndef GLOBALS_H_ | ||||||
| #define GLOBALS_H_ | #define GLOBALS_H_ | ||||||
|  |  | ||||||
| @@ -9,6 +8,7 @@ enum game_id { | |||||||
|     CS  = 1, /* Counter-Strike 1.6 */ |     CS  = 1, /* Counter-Strike 1.6 */ | ||||||
|     TF  = 2, /* Team Fortress Classic */ |     TF  = 2, /* Team Fortress Classic */ | ||||||
|     DOD = 3, /* Day of Defeat */ |     DOD = 3, /* Day of Defeat */ | ||||||
|  |     SL = 4, /* Space Life: Finleys Revenge */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
| @@ -36,7 +36,10 @@ enum game_id { | |||||||
| extern game_id this_game_id; | extern game_id this_game_id; | ||||||
| extern vec3_t g_punchAngles; | extern vec3_t g_punchAngles; | ||||||
| extern float g_flNextAttack, g_flNextPrimaryAttack; | extern float g_flNextAttack, g_flNextPrimaryAttack; | ||||||
|  | extern float* scr_fov_value; | ||||||
| extern int g_iClip; | extern int g_iClip; | ||||||
|  | extern int g_currentWeaponID; | ||||||
|  | extern double g_flCurrentTime; | ||||||
|  |  | ||||||
| extern void* hw; | extern void* hw; | ||||||
| extern void** h_client; /* hClientDLL hander */ | extern void** h_client; /* hClientDLL hander */ | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
|  |  | ||||||
| #ifndef HOOKS_H_ | #ifndef HOOKS_H_ | ||||||
| #define HOOKS_H_ | #define HOOKS_H_ | ||||||
|  |  | ||||||
| @@ -8,6 +7,12 @@ | |||||||
|  |  | ||||||
| #include <dlfcn.h> /* dlsym */ | #include <dlfcn.h> /* dlsym */ | ||||||
| #include <GL/gl.h> /* GLFloat */ | #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: |  * Table of prefixes: | ||||||
|  *   prefix | meaning |  *   prefix | meaning | ||||||
| @@ -51,18 +56,15 @@ | |||||||
|  * GL_HOOK: Hooks a OpenGL function. Example: |  * GL_HOOK: Hooks a OpenGL function. Example: | ||||||
|  * |  * | ||||||
|  *   GL_HOOK(glColor4f); |  *   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: Restores a OpenGL hook created by GL_HOOK. Example: | ||||||
|  * |  * | ||||||
|  *   GL_UNHOOK(glColor4f); |  *   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, ...)  \ | #define DECL_HOOK_EXTERN(type, name, ...)  \ | ||||||
|     typedef type (*name##_t)(__VA_ARGS__); \ |     typedef type (*name##_t)(__VA_ARGS__); \ | ||||||
| @@ -77,19 +79,27 @@ | |||||||
|  |  | ||||||
| #define ORIGINAL(name, ...) ho_##name(__VA_ARGS__); | #define ORIGINAL(name, ...) ho_##name(__VA_ARGS__); | ||||||
|  |  | ||||||
| #define GL_HOOK(name)                                \ | #define GL_HOOK(ret_type, name, ...) \ | ||||||
|     void** hp_##name = (void**)dlsym(hw, "q" #name); \ |     typedef ret_type (*name##_t)(__VA_ARGS__); \ | ||||||
|     ho_##name        = (name##_t)(*hp_##name);       \ |     name##_t h_##name; \ | ||||||
|     *hp_##name       = (void*)h_##name; |     name##_t o_##name; | ||||||
|  |  | ||||||
| #define GL_UNHOOK(name) \ | #define GL_UNHOOK(name) \ | ||||||
|     void** hp_##name = (void**)dlsym(hw, "q" #name); \ |     o_##name = h_##name; | ||||||
|     *hp_##name       = (void*)ho_##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); | /* OpenGL hooks */ | ||||||
| void hooks_restore(void); | 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 */ | /* VMT hooks */ | ||||||
| DECL_HOOK_EXTERN(void, CL_CreateMove, float, usercmd_t*, int); | DECL_HOOK_EXTERN(void, CL_CreateMove, float, usercmd_t*, int); | ||||||
| @@ -100,10 +110,16 @@ DECL_HOOK_EXTERN(void, HUD_PostRunCmd, struct local_state_s*, | |||||||
|                  struct local_state_s*, struct usercmd_s*, int, double, |                  struct local_state_s*, struct usercmd_s*, int, double, | ||||||
|                  unsigned int); |                  unsigned int); | ||||||
|  |  | ||||||
| /* OpenGL hooks */ |  | ||||||
| DECL_HOOK_EXTERN(void, glColor4f, GLfloat, GLfloat, GLfloat, GLfloat); |  | ||||||
|  |  | ||||||
| /* Detour hooks */ | /* Detour hooks */ | ||||||
| DECL_HOOK_EXTERN(void, CL_Move); | 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_ */ | #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,9 +1,10 @@ | |||||||
|  |  | ||||||
| #ifndef MAIN_H_ | #ifndef MAIN_H_ | ||||||
| #define MAIN_H_ | #define MAIN_H_ | ||||||
|  |  | ||||||
| void load(void); | void load(void); | ||||||
| void unload(void); | void unload(void); | ||||||
| void self_unload(void); | void self_unload(void); | ||||||
|  | void UNINJECT_CommandHandler(void); | ||||||
|  | void safe_unload_with_debug(void); | ||||||
|  |  | ||||||
| #endif /* MAIN_H_ */ | #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 */ | /* engine_studio_api_t */ | ||||||
| #include "sdk/common/r_studioint.h" | #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 float matrix_3x4[3][4]; | ||||||
| typedef matrix_3x4 bone_matrix[128]; | typedef matrix_3x4 bone_matrix[128]; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										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,19 +14,28 @@ typedef struct { | |||||||
|     uint8_t r, g, b; |     uint8_t r, g, b; | ||||||
| } rgb_t; | } 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 DEG2RAD(n) ((n)*M_PI / 180.0f) | ||||||
| #define RAD2DEG(n) ((n)*180.0f / M_PI) | #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) \ | #define gl_drawline_points(p0, p1, w, col) \ | ||||||
|     gl_drawline(p0[0], p0[1], p1[0], p1[1], 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 */ | /* Use indexes so it works for float[] as well as vec3_t */ | ||||||
| #define vec_copy(dst, src) \ | #define vec_copy(dst, src) \ | ||||||
|  |     do {                   \ | ||||||
|         dst[0] = src[0];   \ |         dst[0] = src[0];   \ | ||||||
|         dst[1] = src[1];   \ |         dst[1] = src[1];   \ | ||||||
|     dst[2] = src[2]; |         dst[2] = src[2];   \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
|  |  | ||||||
| @@ -42,8 +51,8 @@ vec3_t vec_add(vec3_t a, vec3_t b); | |||||||
| vec3_t vec_sub(vec3_t a, vec3_t b); | vec3_t vec_sub(vec3_t a, vec3_t b); | ||||||
| bool vec_is_zero(vec3_t v); | bool vec_is_zero(vec3_t v); | ||||||
| float vec_len2d(vec3_t v); | float vec_len2d(vec3_t v); | ||||||
| void vec_clamp(vec3_t v); | void ang_clamp(vec3_t* v); | ||||||
| void vec_norm(vec3_t v); | void vec_norm(vec3_t* v); | ||||||
| float angle_delta_rad(float a, float b); | float angle_delta_rad(float a, float b); | ||||||
| vec3_t vec_to_ang(vec3_t v); | vec3_t vec_to_ang(vec3_t v); | ||||||
| vec3_t matrix_3x4_origin(matrix_3x4 m); | vec3_t matrix_3x4_origin(matrix_3x4 m); | ||||||
|   | |||||||
							
								
								
									
										178
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -1,73 +1,205 @@ | |||||||
|  | #include <ctype.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <dlfcn.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/main.h" | ||||||
| #include "include/sdk.h" | #include "include/sdk.h" | ||||||
| #include "include/globals.h" | #include "include/globals.h" | ||||||
| #include "include/cvars.h" | #include "include/settings.h" | ||||||
| #include "include/hooks.h" | #include "include/hooks.h" | ||||||
| #include "include/util.h" | #include "include/util.h" | ||||||
|  | #include "include/game_detection.h" | ||||||
|  |  | ||||||
| static bool loaded = false; | 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) { | void load(void) { | ||||||
|     printf("goldsource-cheat injected!\n"); |     printf("goldsource-cheat injected!\n"); | ||||||
|  |  | ||||||
|     /* Initialize globals/interfaces */ |  | ||||||
|     if (!globals_init()) { |     if (!globals_init()) { | ||||||
|         fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n"); |         fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n"); | ||||||
|         self_unload(); |         self_unload(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Create cvars for settings */ |     settings_init(); | ||||||
|     if (!cvars_init()) { |  | ||||||
|         fprintf(stderr, "goldsource-cheat: load: error creating cvars, aborting\n"); |  | ||||||
|         self_unload(); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* Hook functions */ |  | ||||||
|     if (!hooks_init()) { |     if (!hooks_init()) { | ||||||
|         fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n"); |         fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n"); | ||||||
|         self_unload(); |         self_unload(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Get game version after injecting */ |     i_engine->pfnAddCommand("dz_uninject", UNINJECT_CommandHandler); | ||||||
|     this_game_id = get_cur_game(); |     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"); | ||||||
|  |  | ||||||
|  |     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 \"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; |     loaded = true; | ||||||
| } | } | ||||||
|  |  | ||||||
| __attribute__((destructor)) /* Entry point when unloaded */ | __attribute__((destructor)) | ||||||
| void unload(void) { | void unload(void) { | ||||||
|     if (loaded) { |     if (loaded) { | ||||||
|         /* TODO: Remove our cvars */ |         settings_reset(); | ||||||
|          |          | ||||||
|         globals_restore(); |         globals_restore(); | ||||||
|         hooks_restore(); |         hooks_restore(); | ||||||
|  |  | ||||||
|         GL_UNHOOK(glColor4f); /* Manually restore OpenGL hooks here */ |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     printf("goldsource-cheat unloaded.\n\n"); |     printf("goldsource-cheat unloaded.\n\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| void self_unload(void) { | void self_unload(void) { | ||||||
|     /* |  | ||||||
|      * RTLD_LAZY: If the symbol is never referenced, then it is never resolved. |  | ||||||
|      * RTLD_NOLOAD: Don't load the shared object. |  | ||||||
|      */ |  | ||||||
|     void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD); |     void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD); | ||||||
|      |      | ||||||
|     /* Close the call we just made to dlopen() */ |     if (self) { | ||||||
|         dlclose(self); |         dlclose(self); | ||||||
|  |  | ||||||
|     /* Close the call our injector made */ |  | ||||||
|         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; | ||||||
|  | }  | ||||||
							
								
								
									
										76
									
								
								src/util.c
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								src/util.c
									
									
									
									
									
								
							| @@ -9,6 +9,7 @@ | |||||||
| #include "include/util.h" | #include "include/util.h" | ||||||
| #include "include/sdk.h" | #include "include/sdk.h" | ||||||
| #include "include/globals.h" | #include "include/globals.h" | ||||||
|  | #include "include/game_detection.h" | ||||||
|  |  | ||||||
| cl_entity_t* get_player(int ent_idx) { | cl_entity_t* get_player(int ent_idx) { | ||||||
|     if (ent_idx < 0 || ent_idx > 32) |     if (ent_idx < 0 || ent_idx > 32) | ||||||
| @@ -35,29 +36,23 @@ bool is_friend(cl_entity_t* ent) { | |||||||
|     if (!ent) |     if (!ent) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|     /* Check the current game because this method only works for some games */ |     GameType game = get_current_game(); | ||||||
|     switch (this_game_id) { |      | ||||||
|         case TF: { |     switch (game) { | ||||||
|  |         case GAME_TFC: { | ||||||
|             extra_player_info_t* info = (extra_player_info_t*)player_extra_info; |             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: { |         case GAME_CS16: { | ||||||
|             extra_player_info_cs_t* info = |             extra_player_info_cs_t* info = (extra_player_info_cs_t*)player_extra_info; | ||||||
|               (extra_player_info_cs_t*)player_extra_info; |             return info[ent->index].teamnumber == info[localplayer->index].teamnumber; | ||||||
|  |  | ||||||
|             return info[ent->index].teamnumber == |  | ||||||
|                    info[localplayer->index].teamnumber; |  | ||||||
|         } |         } | ||||||
|         case DOD: { |         case GAME_DAY_OF_DEFEAT: { | ||||||
|             extra_player_info_dod_t* info = |             extra_player_info_dod_t* info = (extra_player_info_dod_t*)player_extra_info; | ||||||
|               (extra_player_info_dod_t*)player_extra_info; |             return info[ent->index].teamnumber == info[localplayer->index].teamnumber; | ||||||
|  |  | ||||||
|             return info[ent->index].teamnumber == |  | ||||||
|                    info[localplayer->index].teamnumber; |  | ||||||
|         } |         } | ||||||
|         case HL: |         case GAME_HALFLIFE: | ||||||
|  |         case GAME_DMC: | ||||||
|         default: |         default: | ||||||
|             return false; |             return false; | ||||||
|     } |     } | ||||||
| @@ -75,26 +70,6 @@ char* get_name(int ent_idx) { | |||||||
|     return info.name; |     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 vec3(float x, float y, float z) { | ||||||
|     vec3_t ret; |     vec3_t ret; | ||||||
|  |  | ||||||
| @@ -133,16 +108,16 @@ float vec_len2d(vec3_t v) { | |||||||
|     return sqrtf(v.x * v.x + v.y * v.y); |     return sqrtf(v.x * v.x + v.y * v.y); | ||||||
| } | } | ||||||
|  |  | ||||||
| void vec_clamp(vec3_t v) { | void ang_clamp(vec3_t* v) { | ||||||
|     v.x = CLAMP(v.x, -89.0f, 89.0f); |     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->y = CLAMP(remainderf(v->y, 360.0f), -180.0f, 180.0f); | ||||||
|     v.z = CLAMP(v.z, -50.0f, 50.0f); |     v->z = CLAMP(v->z, -50.0f, 50.0f); | ||||||
| } | } | ||||||
|  |  | ||||||
| void vec_norm(vec3_t v) { | void vec_norm(vec3_t* v) { | ||||||
|     v.x = isfinite(v.x) ? remainder(v.x, 360) : 0; |     v->x = isfinite(v->x) ? remainderf(v->x, 360.f) : 0.f; | ||||||
|     v.y = isfinite(v.y) ? remainder(v.y, 360) : 0; |     v->y = isfinite(v->y) ? remainderf(v->y, 360.f) : 0.f; | ||||||
|     v.z = 0.0f; |     v->z = 0.0f; | ||||||
| } | } | ||||||
|  |  | ||||||
| float angle_delta_rad(float a, float b) { | float angle_delta_rad(float a, float b) { | ||||||
| @@ -188,10 +163,15 @@ bool world_to_screen(vec3_t vec, vec2_t screen) { | |||||||
|     scr_inf.iSize = sizeof(SCREENINFO); |     scr_inf.iSize = sizeof(SCREENINFO); | ||||||
|     i_engine->pfnGetScreenInfo(&scr_inf); |     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 (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[0] = screen[0] * (scr_inf.iWidth / 2) + (scr_inf.iWidth / 2); | ||||||
|         screen[1] = -screen[1] * (scr_inf.iHeight / 2) + (scr_inf.iHeight / 2); |         screen[1] = -screen[1] * (scr_inf.iHeight / 2) + (scr_inf.iHeight / 2); | ||||||
|  |     } | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user