├── .gitignore ├── README.md ├── config.hpp ├── cracking.cpp ├── cracking.hpp ├── doit.sh ├── functions.hpp ├── gsc.cpp ├── gsc.hpp ├── gsc_astar.cpp ├── gsc_astar.hpp ├── gsc_car.cpp ├── gsc_car.hpp ├── gsc_math.cpp ├── gsc_math.hpp ├── gsc_memory.cpp ├── gsc_memory.hpp ├── gsc_mysql.cpp ├── gsc_mysql.hpp ├── gsc_player.cpp ├── gsc_player.hpp ├── gsc_tcc.cpp ├── gsc_tcc.hpp ├── gsc_utils.cpp ├── gsc_utils.hpp ├── java_embed.c ├── java_embed.h ├── libcod.cpp ├── plugins ├── bsp │ ├── bsp.c │ ├── bsp.so │ ├── doit.sh │ └── quake3 │ │ └── code │ │ ├── game │ │ ├── q_shared.h │ │ └── surfaceflags.h │ │ └── qcommon │ │ ├── cm_load.c │ │ ├── cm_local.h │ │ ├── cm_patch.c │ │ ├── cm_patch.h │ │ ├── cm_polylib.c │ │ ├── cm_polylib.h │ │ ├── cm_public.h │ │ ├── cm_test.c │ │ ├── cm_trace.c │ │ ├── qcommon.h │ │ └── qfiles.h └── print │ ├── doit.sh │ └── print.c ├── server.c ├── server.hpp └── test.c /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | objects_* 3 | libcod.tar 4 | *.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The Call of Duty extension *libcod* is adding new server-side functions to: 2 | 3 | - Call Of Duty 2 1.2 4 | - Call Of Duty 2 1.3 5 | - Call Of Duty 4 1.7 6 | 7 | Requirements: 8 | ``` 9 | dpkg --add-architecture i386 10 | apt-get update 11 | apt-get install gcc-multilib 12 | apt-get install libmysqlclient-dev:i386 13 | apt-get install g++-multilib 14 | ``` 15 | 16 | Precompiled shared libraries: http://killtube.org/downloads/libcod/ 17 | 18 | Starting the server: 19 | 20 | ```LD_PRELOAD=libcod2_1_3_nomysql.so ./cod2_lnxded +set fs_game ...``` 21 | 22 | Some enviroments need LD_LIBRARY_PATH also: 23 | 24 | ```LD_LIBRARY_PATH=. LD_PRELOAD=libcod2_1_3_nomysql.so ./cod2_lnxded +set fs_game ...``` 25 | 26 | Working with the source / Compiling: 27 | ``` 28 | ./doit.sh tar 29 | ./doit.sh base # compiles object files needed by every .so 30 | ./doit.sh cod1_1_5 # compiles object files for CoD 1 1.5 and linking them against base to the actual bin/libcod1_1_5.so 31 | ./doit.sh cod2_1_2 32 | ./doit.sh cod2_1_3 33 | ./doit.sh cod4_1_7 34 | ./doit.sh wrapper 35 | ``` 36 | 37 | Mods depending on *libcod*: 38 | - http://killtube.org/showthread.php?1533-DOWNLOAD-CoD2-Surf-Mod 39 | - http://killtube.org/showthread.php?1527-DOWNLOAD-CoD2-Basetdm-Mod 40 | - http://killtube.org/showthread.php?1593-DOWNLOAD-CoD2-Portal-Mod 41 | - Jump-Mod by IzNoGod 42 | 43 | Little overview of added functions: 44 | - MySQL 45 | - setVelocity, getVelocity, addVelocity (needed for the mods: portal, surf) 46 | - keyPressed-functions for left, right, forward, backward, leanleft, leanright, jump etc., (needed for: surf, doublejump made by IzNoGod) 47 | - blazing fast astar-implementation (needed for: zombots) 48 | - setAlive-function (needed for: zombots, so xmodels are damagable without damage-trigger... zombots in stockmaps) 49 | - disableGlobalPlayerCollision() 50 | 51 | Community / Help: http://killtube.org/forum.php 52 | 53 | Porting *libcod* to a new Call Of Duty: 54 | ```find . -name '*.c*' | xargs grep -n _VERSION``` -------------------------------------------------------------------------------- /config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_HPP_ 2 | #define _CONFIG_HPP_ 3 | 4 | /* 5 | DID MOST OF THIS TO HARDEN THE LIB FOR DECOMPILING 6 | countercheck: 7 | strings -a libcod2_ver_1_3.so | less 8 | strings libcod2_ver_1_3.so | less 9 | nm libcod2_ver_1_3.so | less 10 | nm -D libcod2_ver_1_3.so | less 11 | */ 12 | 13 | // that makes debugging easier after some months 14 | #define DEBUG_MYSQL 0 15 | #define DEBUG_GSC 0 16 | #define DEBUG_MEMORY 0 17 | #define DEBUG_CAR 1 18 | #define DEBUG_TCC 1 19 | 20 | // GSC MODULES 21 | #define COMPILE_MYSQL 1 22 | #define COMPILE_MYSQL_TESTS 1 23 | #define COMPILE_PLAYER 1 24 | #define COMPILE_ASTAR 1 25 | #define COMPILE_MEMORY 1 26 | #define COMPILE_CAR 0 27 | #define COMPILE_TCC 0 28 | #define COMPILE_UTILS 1 29 | 30 | #define COMPILE_RATELIMITER 1 31 | 32 | // LIB FEATURES 33 | #define COMPILE_DEBUG_SERVER 0 34 | 35 | #define DEBUG_PRINTF 1 36 | 37 | // GLOBAL MACROS 38 | #define STR(s) #s // stringify used for __FUNCTION__ 39 | #define INT(address) (*(int*)(address)) 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /cracking.cpp: -------------------------------------------------------------------------------- 1 | #include "cracking.hpp" 2 | 3 | int cracking_nop(int from, int to) 4 | { 5 | int i; 6 | for (i=from; i> 1; // its like dividing by 2 71 | //printf("len=%d neededBytes=%d\n", len, neededBytes); 72 | first = 1; 73 | pos = 0; 74 | for (i=0; ifrom = from; 126 | this->to = to; 127 | } 128 | void cHook::hook() { 129 | memcpy((void *)oldCode, (void *)from, 5); 130 | cracking_hook_function(from, to); 131 | } 132 | void cHook::unhook() { 133 | memcpy((void *)from, (void *)oldCode, 5); 134 | } 135 | 136 | 137 | int cracking_call_function(int func_address, char *args, unsigned char *data) { 138 | int data_pos = 0; 139 | unsigned char stack[128]; 140 | int stack_pos = 0; 141 | 142 | int mode_varargs = 0; 143 | int i; 144 | for (i=0; args[i]; i++) { 145 | if (args[i] == '.') { 146 | mode_varargs = 1; 147 | continue; 148 | } 149 | //printf("args[i=%d]=%c stack_pos=%.2d data=%.8p\n", i, args[i], stack_pos, *(int *)(data + data_pos)); 150 | *(int *)(stack + stack_pos) = *(int*)(data + data_pos); 151 | 152 | if (args[i] == 'f' && mode_varargs) { 153 | double tmp_double = (double)*(float *)(data + data_pos); 154 | memcpy(stack + stack_pos, &tmp_double, 8); 155 | } 156 | if (args[i] == 'd') { 157 | double tmp_double = *(double *)(data + data_pos); 158 | memcpy(stack + stack_pos, &tmp_double, 8); 159 | } 160 | 161 | stack_pos += 4; // even 1-byte-chars will be 4-byte-aligned on stack 162 | if (args[i] == 'f' && mode_varargs) 163 | stack_pos += 4; // use 8 bytes for varargs/float, aka double 164 | if (args[i] == 'd') 165 | stack_pos += 4; // use 8 bytes for normal double 166 | 167 | switch (args[i]) { 168 | case 'i': 169 | case 's': 170 | case 'f': data_pos += 4; break; 171 | case 'c': data_pos += 1; break; 172 | case 'd': data_pos += 8; break; 173 | } 174 | } 175 | 176 | // http://wiki.osdev.org/Inline_Assembly 177 | unsigned char *sp; 178 | asm("movl %%esp, %0" : "=g" (sp)); 179 | //printf("sp=%.8p\n", sp); 180 | 181 | memcpy(sp, stack, stack_pos); 182 | 183 | asm("movl %0, %%eax" : : "g" (func_address)); 184 | asm("call *%eax"); 185 | 186 | int ret; 187 | asm("movl %%eax, %0" : "=g" (ret)); 188 | return ret; 189 | } -------------------------------------------------------------------------------- /cracking.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _CRACKING_HPP_ 2 | #define _CRACKING_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | int cracking_nop(int from, int to); 11 | void cracking_hook_function(int from, int to); 12 | void cracking_hook_call(int from, int to); 13 | int cracking_write_hex(int address, char *hex); 14 | 15 | int singleHexToNumber(char hexchar); 16 | int hexToBuffer(char *hex, char *buffer, int bufferLen); 17 | 18 | int cracking_call_function(int func_address, char *args, unsigned char *data); 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | class cHook 25 | { 26 | public: 27 | int from; 28 | int to; 29 | unsigned char oldCode[5]; 30 | cHook(int from, int to); 31 | void hook(); 32 | void unhook(); 33 | }; 34 | #endif 35 | 36 | #endif -------------------------------------------------------------------------------- /doit.sh: -------------------------------------------------------------------------------- 1 | # 2 | # help: 3 | # -O1 = removes references to unused strings for printf_hide -> anti reversing | found "-O3 -s" but dunno the advantage 4 | # 5 | # ./doit.sh tar 6 | # ./doit.sh cod1_1_5 7 | # ./doit.sh cod2_1_2 8 | # ./doit.sh cod2_1_3 9 | # ./doit.sh cod4_1_7 10 | # ./doit.sh wrapper 11 | # 12 | 13 | mkdir -p bin 14 | mkdir -p objects_normal 15 | 16 | # clang warns about everything 17 | cc="gcc" 18 | 19 | #options="-I. -m32 -fPIC -fvisibility=hidden -O1" 20 | 21 | options="-I. -m32 -fPIC -Wno-write-strings" 22 | 23 | no_warning_spam="-Wall -Wno-write-strings -Wno-pointer-arith -Wno-format -Wno-parentheses -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable -Wno-return-type -Wno-sign-compare" 24 | options="$options $no_warning_spam" 25 | 26 | #objects_tcc="build/gsc_tcc.opp /home/kung/tcc/tcc-0.9.25/libtcc.a" 27 | 28 | tmp="/root/q3rally/q3rallysa/build"; 29 | objects_car="$tmp/q_shared.o $tmp/q_math.o $tmp/com_printf.o $tmp/bg_wheel_forces.o $tmp/bg_pmove.o $tmp/bg_physics.o $tmp/bg_misc.o" 30 | 31 | mysql_config="`mysql_config --cflags --libs`" 32 | mysql_link="" 33 | 34 | if [ -d "./vendors/lib" ]; then 35 | mysql_config="" 36 | mysql_link="-lmysqlclient -L./vendors/lib" 37 | fi 38 | 39 | # if dir $java_jdk exists: add java support to libcod 40 | # download url: https://jdk8.java.net/download.html 41 | java_jdk="/root/helper/openjdk8" 42 | java_lib="" 43 | java_header="" 44 | java_enable="false" 45 | 46 | # when the JDK is not found, force it to be off 47 | if [ ! -d $java_jdk ]; then 48 | java_enable="false" 49 | fi 50 | if [ "$java_enable" == "true" ]; then 51 | java_lib="-ljvm -L$java_jdk/jre/lib/i386/server/" 52 | java_header="-I$java_jdk/include/ -I$java_jdk/include/linux/" 53 | options="$options -DIS_JAVA_ENABLED" 54 | fi 55 | 56 | if [ "$1" == "" ] || [ "$1" == "tar" ]; then 57 | echo "##### TAR LIBCOD #####" 58 | 59 | rm libcod.tar 60 | 61 | #tar -cf libcod.tar json 62 | #tar -rf libcod.tar jsonrpc 63 | tar -cf libcod.tar plugins 64 | #tar -rf libcod.tar vendors 65 | 66 | tar -rf libcod.tar *.c 67 | tar -rf libcod.tar *.cpp 68 | tar -rf libcod.tar *.hpp 69 | 70 | tar -rf libcod.tar doit.sh 71 | echo "libcod.tar created: $?" 72 | fi 73 | 74 | if [ "$1" == "" ] || [ "$1" == "base" ]; then 75 | echo "##### COMPILE GSC_ASTAR.CPP #####" 76 | $cc $options -c gsc_astar.cpp -o objects_normal/gsc_astar.opp 77 | echo "##### COMPILE GSC_MYSQL.CPP #####" 78 | $cc $options -c gsc_mysql.cpp -o objects_normal/gsc_mysql.opp -lmysqlclient -L/usr/lib/mysql 79 | echo "##### COMPILE SERVER.C #####" 80 | $cc $options -c server.c -o objects_normal/server.opp -D SERVER_PORT=8000 81 | echo "##### COMPILE GSC_MEMORY.CPP #####" 82 | $cc $options -c gsc_memory.cpp -o objects_normal/gsc_memory.opp 83 | echo "##### COMPILE cracking.CPP #####" 84 | $cc $options -c cracking.cpp -o objects_normal/cracking.opp 85 | echo "##### COMPILE GSC_MATH.CPP #####" 86 | $cc $options -o objects_normal/gsc_math.opp -c gsc_math.cpp 87 | echo "##### COMPILE JAVA_EMBED.C #####" 88 | if [ "$java_enable" == "true" ]; then 89 | $cc $options -o objects_normal/java_embed.opp -c java_embed.c $java_header 90 | else 91 | echo "Ignore java_embed.c, because java_enable==false (e.g. because the dir \$java_jdk=$java_jdk does not exist)" 92 | fi 93 | fi 94 | 95 | if [ "$1" == "" ] || [ "$1" == "clean" ]; then 96 | echo "##### CLEAN OBJECTS #####" 97 | rm objects_* -r 98 | rm bin -r 99 | rm libcod.tar 100 | fi 101 | 102 | 103 | if [ "$1" == "" ] || [ "$1" == "tcc" ]; then 104 | mkdir -p objects_tcc 105 | 106 | echo "##### COMPILE gsc_tcc.cpp #####" 107 | $cc $options -c gsc_tcc.cpp -o objects_tcc/gsc_tcc.opp 108 | fi 109 | 110 | if [ "$1" == "" ] || [ "$1" == "car" ]; then 111 | mkdir -p objects_car 112 | 113 | echo "##### COMPILE GSC_CAR.CPP #####" 114 | $cc $options -c gsc_car.cpp -o objects_car/gsc_car.opp -I/root/q3rally/q3rallysa/ 115 | fi 116 | 117 | if [ "$1" == "" ] || [ "$1" == "cod2_1_3" ]; then 118 | constants="-D COD2_VERSION=COD2_VERSION_1_3 -D COD_VERSION=COD2_1_3" 119 | 120 | mkdir -p objects_$1 121 | echo "##### COMPILE $1 LIBCOD.CPP #####" 122 | $cc $options $constants -o objects_$1/libcod.opp -c libcod.cpp 123 | echo "##### COMPILE $1 GSC.CPP #####" 124 | $cc $options $constants -o objects_$1/gsc.opp -c gsc.cpp 125 | echo "##### COMPILE $1 GSC_PLAYER.CPP #####" 126 | $cc $options $constants -o objects_$1/gsc_player.opp -c gsc_player.cpp 127 | echo "##### COMPILE $1 GSC_UTILS.CPP #####" 128 | $cc $options $constants -o objects_$1/gsc_utils.opp -c gsc_utils.cpp 129 | 130 | echo "##### LINK lib$1.so #####" 131 | objects="$(ls objects_normal/*.opp) $(ls objects_$1/*.opp)" 132 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/lib$1.so $objects $objects_tcc -Os -s -ldl -Wall $java_lib $mysql_config 133 | fi 134 | # -Xlinker --defsym -Xlinker stackStart=0x08297500 135 | 136 | if [ "$1" == "" ] || [ "$1" == "cod2_1_2" ]; then 137 | constants="-D COD2_VERSION=COD2_VERSION_1_2 -D COD_VERSION=COD2_1_2" 138 | 139 | mkdir -p objects_$1 140 | echo "##### COMPILE $1 LIBCOD.CPP #####" 141 | $cc $options $constants -o objects_$1/libcod.opp -c libcod.cpp 142 | echo "##### COMPILE $1 GSC.CPP #####" 143 | $cc $options $constants -o objects_$1/gsc.opp -c gsc.cpp 144 | echo "##### COMPILE $1 GSC_PLAYER.CPP #####" 145 | $cc $options $constants -o objects_$1/gsc_player.opp -c gsc_player.cpp 146 | echo "##### COMPILE $1 GSC_UTILS.CPP #####" 147 | $cc $options $constants -o objects_$1/gsc_utils.opp -c gsc_utils.cpp 148 | 149 | echo "##### LINK lib$1.so #####" 150 | objects="$(ls objects_normal/*.opp) $(ls objects_$1/*.opp)" 151 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/lib$1.so $objects $objects_tcc -Os -s -ldl -Wall $java_lib $mysql_config 152 | fi 153 | 154 | if [ "$1" == "" ] || [ "$1" == "cod2_1_0" ]; then 155 | constants="-D COD2_VERSION=COD2_VERSION_1_0 -D COD_VERSION=COD2_1_0" 156 | 157 | mkdir -p objects_$1 158 | echo "##### COMPILE $1 LIBCOD.CPP #####" 159 | $cc $options $constants -o objects_$1/libcod.opp -c libcod.cpp 160 | echo "##### COMPILE $1 GSC.CPP #####" 161 | $cc $options $constants -o objects_$1/gsc.opp -c gsc.cpp 162 | echo "##### COMPILE $1 GSC_PLAYER.CPP #####" 163 | $cc $options $constants -o objects_$1/gsc_player.opp -c gsc_player.cpp 164 | echo "##### COMPILE $1 GSC_UTILS.CPP #####" 165 | $cc $options $constants -o objects_$1/gsc_utils.opp -c gsc_utils.cpp 166 | 167 | echo "##### LINK lib$1.so #####" 168 | objects="$(ls objects_normal/*.opp) $(ls objects_$1/*.opp)" 169 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/lib$1.so $objects $objects_tcc -Os -s -ldl -Wall $java_lib $mysql_config 170 | fi 171 | 172 | 173 | if [ "$1" == "" ] || [ "$1" == "cod1_1_5" ]; then 174 | constants="-D COD_VERSION=COD1_1_5" 175 | 176 | #echo "##### COMPILE CoD1 1.5 LIBCOD2.CPP #####" 177 | #$cc $options $constants -c libcod2.cpp -o libcod2.opp 178 | echo "##### COMPILE CoD1 1.5 GSC.CPP #####" 179 | $cc $options $constants -c gsc.cpp -o gsc.opp 180 | #echo "##### COMPILE CoD1 1.5 GSC_PLAYER.CPP #####" 181 | #$cc $options $constants -c gsc_player.cpp -o gsc_player.opp 182 | 183 | echo "##### LINK libcod1_1_5.so #####" 184 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/libcod1_1_5.so libcod2.opp gsc.opp gsc_player.opp gsc_astar.opp gsc_mysql.opp server.opp gsc_memory.opp cracking.opp $objects_tcc -Os -s -ldl -Wall $mysql_config 185 | fi 186 | 187 | 188 | if [ "$1" == "" ] || [ "$1" == "cod4_1_7" ]; then 189 | constants="-D COD_VERSION=COD4_1_7" 190 | 191 | mkdir -p objects_$1 192 | echo "##### COMPILE $1 LIBCOD.CPP #####" 193 | $cc $options $constants -o objects_$1/libcod.opp -c libcod.cpp 194 | echo "##### COMPILE $1 GSC.CPP #####" 195 | $cc $options $constants -o objects_$1/gsc.opp -c gsc.cpp 196 | echo "##### COMPILE $1 GSC_PLAYER.CPP #####" 197 | $cc $options $constants -o objects_$1/gsc_player.opp -c gsc_player.cpp 198 | echo "##### COMPILE $1 GSC_UTILS.CPP #####" 199 | $cc $options $constants -o objects_$1/gsc_utils.opp -c gsc_utils.cpp 200 | 201 | echo "##### LINK lib$1.so #####" 202 | objects="$(ls objects_normal/*.opp) $(ls objects_$1/*.opp)" 203 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/lib$1.so $objects $objects_tcc -Os -s -ldl -Wall $java_lib $mysql_config 204 | fi 205 | 206 | 207 | if [ "$1" == "" ] || [ "$1" == "cod4_1_7_l" ]; then 208 | constants="-D COD_VERSION=COD4_1_7_L" 209 | 210 | mkdir -p objects_$1 211 | echo "##### COMPILE $1 LIBCOD.CPP #####" 212 | $cc $options $constants -o objects_$1/libcod.opp -c libcod.cpp 213 | echo "##### COMPILE $1 GSC.CPP #####" 214 | $cc $options $constants -o objects_$1/gsc.opp -c gsc.cpp 215 | echo "##### COMPILE $1 GSC_PLAYER.CPP #####" 216 | $cc $options $constants -o objects_$1/gsc_player.opp -c gsc_player.cpp 217 | echo "##### COMPILE $1 GSC_UTILS.CPP #####" 218 | $cc $options $constants -o objects_$1/gsc_utils.opp -c gsc_utils.cpp 219 | 220 | echo "##### LINK lib$1.so #####" 221 | objects="$(ls objects_normal/*.opp) $(ls objects_$1/*.opp)" 222 | $cc -m32 -shared -L/lib32 $mysql_link -o bin/lib$1.so $objects $objects_tcc -Os -s -ldl -Wall $java_lib $mysql_config 223 | fi 224 | 225 | 226 | if [ "$1" == "wrapper" ]; then 227 | echo "##### WRAPPER: COMPILE wrapper_libcod2.cpp #####" 228 | cp wrapper_libcod2.cpp a.cpp # just for name hiding in the .opp/.so -.- 229 | $cc -m32 -fPIC -c a.cpp -o wrapper_libcod2.opp 230 | 231 | #strip wrapper_libcod2.opp 232 | 233 | # make the shared lib for the wrapper 234 | echo "##### WRAPPER: LINK wrapper_libcod2.so #####" 235 | $cc -m32 -shared -L/lib32 -o wrapper_libcod2.so wrapper_libcod2.opp 236 | 237 | 238 | cp wrapper_libcod2.so bin/libcod2.so 239 | #cp wrapper_libcod2.so /root/helper/game_cod2/libs/libcod2.so # other then "mv", "ld" can use it so (not just from game-libs-folder) 240 | fi 241 | -------------------------------------------------------------------------------- /functions.hpp: -------------------------------------------------------------------------------- 1 | #if !defined(_FUNCTIONS_HPP_) && (defined(COD2_VERSION) || defined(COD_VERSION)) 2 | #define _FUNCTIONS_HPP_ 3 | 4 | /* MAKE FUNCTIONS STATIC, SO THEY CAN BE IN EVERY FILE */ 5 | 6 | // CoD2 1.2 = 80601F2 7 | static int trap_Argc() 8 | { 9 | #if COD_VERSION == COD2_1_0 10 | return *(int *)0x0819BE80; 11 | #elif COD_VERSION == COD2_1_2 12 | return *(int *)0x0819E080; 13 | #elif COD_VERSION == COD2_1_3 14 | return *(int *)0x0819F100; 15 | #elif COD_VERSION == COD4_1_7 16 | return ((int *)0x08878D04)[*(int *)0x08878CC0]; 17 | #elif COD_VERSION == COD4_1_7_L 18 | return ((int *)0x08879A84)[*(int *)0x08879A40]; 19 | #else 20 | #warning trap_Argc() return *(int *)NULL; 21 | return *(int *)NULL; 22 | #endif 23 | } 24 | 25 | typedef char * (*Cmd_Argv_t)(int arg); 26 | #if COD_VERSION == COD2_1_0 27 | static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)0x0806001C; 28 | #elif COD_VERSION == COD2_1_2 29 | static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)0x08060228; 30 | #elif COD_VERSION == COD2_1_3 31 | static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)0x08060220; 32 | #else 33 | #warning static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)NULL; 34 | static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)NULL; 35 | #endif 36 | 37 | typedef int (*trap_Argv_t)(unsigned int param, char *buf, int bufLen); 38 | #if COD_VERSION == COD2_1_0 39 | static trap_Argv_t trap_Argv = (trap_Argv_t)0x08060074; 40 | #elif COD_VERSION == COD2_1_2 41 | static trap_Argv_t trap_Argv = (trap_Argv_t)0x08060280; 42 | #elif COD_VERSION == COD2_1_3 43 | static trap_Argv_t trap_Argv = (trap_Argv_t)0x08060278; 44 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 45 | static trap_Argv_t trap_Argv = (trap_Argv_t)0x08110E08; 46 | #else 47 | #warning static trap_Argv_t trap_Argv = (trap_Argv_t)NULL; 48 | static trap_Argv_t trap_Argv = (trap_Argv_t)NULL; 49 | #endif 50 | 51 | typedef int (*Com_Printf_t)(const char *format, ...); 52 | /// A Com_Printf that only shows up if the "developer" cvar is set 53 | typedef int (*Com_DPrintf_t)(const char *format, ...); 54 | #if COD_VERSION == COD2_1_0 55 | static Com_Printf_t Com_Printf = (Com_Printf_t)0x08060B2C; 56 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)0x08060B7C; 57 | #elif COD_VERSION == COD2_1_2 58 | static Com_Printf_t Com_Printf = (Com_Printf_t)0x08060DF2; 59 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)0x08060E42; 60 | #elif COD_VERSION == COD2_1_3 61 | static Com_Printf_t Com_Printf = (Com_Printf_t)0x08060DEA; 62 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)0x08060E3A; 63 | #elif COD_VERSION == COD4_1_7 64 | static Com_Printf_t Com_Printf = (Com_Printf_t)0x08122B0E; 65 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)0x08122D74; 66 | #elif COD_VERSION == COD4_1_7_L 67 | static Com_Printf_t Com_Printf = (Com_Printf_t)0x08122B2E; 68 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)0x08122D94; 69 | #else 70 | #warning static Com_Printf_t Com_Printf = (Com_Printf_t)NULL; 71 | #warning static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)NULL; 72 | static Com_Printf_t Com_Printf = (Com_Printf_t)NULL; 73 | static Com_DPrintf_t Com_DPrintf = (Com_DPrintf_t)NULL; 74 | #endif 75 | 76 | /* 77 | search for '\"%s\" is: \"%s^7\" default: \"%s^7\"\n' 78 | Now see code ref. Now you need find a function that only calls that function 79 | */ 80 | typedef int (*Cmd_ExecuteString_t)(const char *text); 81 | 82 | #if COD_VERSION == COD2_1_0 83 | static Cmd_ExecuteString_t Cmd_ExecuteString = (Cmd_ExecuteString_t)0x08060754; 84 | #elif COD_VERSION == COD2_1_2 85 | static Cmd_ExecuteString_t Cmd_ExecuteString = (Cmd_ExecuteString_t)0x080609D4; 86 | #elif COD_VERSION == COD2_1_3 87 | static Cmd_ExecuteString_t Cmd_ExecuteString = (Cmd_ExecuteString_t)0x080609CC; 88 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 89 | static Cmd_ExecuteString_t Cmd_ExecuteString = (Cmd_ExecuteString_t)0x08111F32; 90 | #else 91 | static Cmd_ExecuteString_t Cmd_ExecuteString = (Cmd_ExecuteString_t)NULL; 92 | #warning Cmd_ExecuteString_t Cmd_ExecuteString = NULL; 93 | #endif 94 | 95 | typedef int (*ClientCommand_t)(int clientNum); 96 | #if COD_VERSION == COD2_1_0 97 | static ClientCommand_t ClientCommand = (ClientCommand_t)0x080FE998; // search 'say_team' and see code xref function 98 | static int hook_ClientCommand_call = 0x0808F281; 99 | #elif COD_VERSION == COD2_1_2 100 | static ClientCommand_t ClientCommand = (ClientCommand_t)0x08100D1E; 101 | static int hook_ClientCommand_call = 0x08090B0C; 102 | #elif COD_VERSION == COD2_1_3 103 | static ClientCommand_t ClientCommand = (ClientCommand_t)0x08100E62; 104 | static int hook_ClientCommand_call = 0x08090BA0; 105 | #elif COD_VERSION == COD4_1_7 106 | static ClientCommand_t ClientCommand = (ClientCommand_t)0x080B070C; 107 | static int hook_ClientCommand_call = 0x08170E70; 108 | #elif COD_VERSION == COD4_1_7_L 109 | static ClientCommand_t ClientCommand = (ClientCommand_t)0x080B070C; 110 | static int hook_ClientCommand_call = 0x08170F20; 111 | #else 112 | #warning static ClientCommand_t ClientCommand = (ClientCommand_t)NULL; 113 | #warning static int hook_ClientCommand_call = NULL; 114 | static ClientCommand_t ClientCommand = (ClientCommand_t)NULL; 115 | static int hook_ClientCommand_call = (int)NULL; 116 | #endif 117 | 118 | typedef int (*Cvar_VariableValue_t)(const char *var_name); // search for 'sv_allowAnonymous' 119 | #if COD_VERSION == COD2_1_0 120 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)0x080B0BB6; 121 | #elif COD_VERSION == COD2_1_2 122 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)0x080B2E66; 123 | #elif COD_VERSION == COD2_1_3 124 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)0x080B2FAA; 125 | #elif COD_VERSION == COD4_1_7 126 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)0x0819E090; 127 | #elif COD_VERSION == COD4_1_7_L 128 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)0x0819E7C0; 129 | #else 130 | #warning static Cvar_VariableValue_t CvarVariableValue = NULL; 131 | static Cvar_VariableValue_t CvarVariableValue = (Cvar_VariableValue_t)NULL; 132 | #endif 133 | 134 | typedef char * (*Cvar_VariableString_t)(const char *var_name); 135 | #if COD_VERSION == COD2_1_0 136 | static Cvar_VariableString_t Cvar_VariableString = (Cvar_VariableString_t)0x080B0D96; 137 | #elif COD_VERSION == COD2_1_2 138 | static Cvar_VariableString_t Cvar_VariableString = (Cvar_VariableString_t)0x080B3046; 139 | #elif COD_VERSION == COD2_1_3 140 | static Cvar_VariableString_t Cvar_VariableString = (Cvar_VariableString_t)0x080B318A; 141 | #else 142 | #warning static Cvar_VariableValue_t CvarVariableValue = NULL; 143 | static Cvar_VariableString_t Cvar_VariableString = (Cvar_VariableString_t)NULL; 144 | #endif 145 | 146 | typedef int (*FS_ReadFile_t)(const char *qpath, void **buffer); 147 | #if COD_VERSION == COD2_1_0 148 | static FS_ReadFile_t FS_ReadFile = (FS_ReadFile_t)0x0809E892; 149 | #elif COD_VERSION == COD2_1_2 150 | static FS_ReadFile_t FS_ReadFile = (FS_ReadFile_t)0x080A0958; 151 | #elif COD_VERSION == COD2_1_3 152 | static FS_ReadFile_t FS_ReadFile = (FS_ReadFile_t)0x080A0A9C; 153 | #else 154 | #warning static FS_ReadFile_t FS_ReadFile = NULL; 155 | static FS_ReadFile_t FS_ReadFile = (FS_ReadFile_t)NULL; 156 | #endif 157 | 158 | // e.g. FS_LoadDir("/home/ns_test", "NsZombiesV4.3"); 159 | typedef int (*FS_LoadDir_t)(char *path, char *dir); 160 | #if COD_VERSION == COD2_1_0 161 | static FS_LoadDir_t FS_LoadDir = (FS_LoadDir_t)0x080A01A4; 162 | #elif COD_VERSION == COD2_1_2 163 | static FS_LoadDir_t FS_LoadDir = (FS_LoadDir_t)0x080A22D8; 164 | #elif COD_VERSION == COD2_1_3 165 | static FS_LoadDir_t FS_LoadDir = (FS_LoadDir_t)0x080A241C; 166 | #else 167 | #warning static FS_LoadDir_t FS_LoadDir = NULL; 168 | static FS_LoadDir_t FS_LoadDir = (FS_LoadDir_t)NULL; 169 | #endif 170 | 171 | #if COD_VERSION == COD2_1_0 172 | static int rconPasswordAddress = 0x0848B1C0; 173 | #elif COD_VERSION == COD2_1_2 174 | static int rconPasswordAddress = 0x0849E6C0; 175 | #elif COD_VERSION == COD2_1_3 176 | static int rconPasswordAddress = 0x0849F740; 177 | #else 178 | #warning static int rconPasswordAddress = NULL; 179 | static int rconPasswordAddress = (int)NULL; 180 | #endif 181 | 182 | #if COD_VERSION == COD2_1_0 183 | static int hook_findMap_call = 0x0808AD00; 184 | #elif COD_VERSION == COD2_1_2 185 | static int hook_findMap_call = 0x0808BCFC; 186 | #elif COD_VERSION == COD2_1_3 187 | static int hook_findMap_call = 0x0808BDC8; 188 | #else 189 | #warning static int hook_findMap_call = NULL; 190 | static int hook_findMap_call = (int)NULL; 191 | #endif 192 | 193 | #if COD_VERSION == COD2_1_0 194 | static int hook_AuthorizeState_call = 0x0808C8C0; 195 | #elif COD_VERSION == COD2_1_2 196 | static int hook_AuthorizeState_call = 0x0808DA52; 197 | #elif COD_VERSION == COD2_1_3 198 | static int hook_AuthorizeState_call = 0x0808DB12; 199 | #else 200 | #warning static int hook_AuthorizeState_call = NULL; 201 | static int hook_AuthorizeState_call = (int)NULL; 202 | #endif 203 | 204 | typedef enum { 205 | NA_BOT, 206 | NA_BAD, // an address lookup failed 207 | NA_LOOPBACK, 208 | NA_BROADCAST, 209 | NA_IP, 210 | NA_IPX, 211 | NA_BROADCAST_IPX 212 | } netadrtype_t; 213 | 214 | typedef struct { 215 | netadrtype_t type; 216 | unsigned char ip[4]; 217 | char ipx[10]; 218 | unsigned short port; 219 | } netadr_t; 220 | 221 | typedef struct { 222 | bool overflowed; // 0 223 | char *data; // 4 224 | int maxsize; // 8 225 | int cursize; // 12 226 | int readcount; // 16 227 | int bit; 228 | } msg_t; // 0x18 229 | 230 | typedef int (*SV_ConnectionlessPacket_t)(netadr_t from, msg_t * msg); 231 | #if COD_VERSION == COD2_1_0 232 | static SV_ConnectionlessPacket_t SV_ConnectionlessPacket = (SV_ConnectionlessPacket_t)0x08093F1E; 233 | #elif COD_VERSION == COD2_1_2 234 | static SV_ConnectionlessPacket_t SV_ConnectionlessPacket = (SV_ConnectionlessPacket_t)0x08095894; 235 | #elif COD_VERSION == COD2_1_3 236 | static SV_ConnectionlessPacket_t SV_ConnectionlessPacket = (SV_ConnectionlessPacket_t)0x0809594E; 237 | #else 238 | #warning static SV_ConnectionlessPacket_t SV_ConnectionlessPacket = NULL; 239 | static SV_ConnectionlessPacket_t SV_ConnectionlessPacket = (SV_ConnectionlessPacket_t)NULL; 240 | #endif 241 | 242 | typedef int (*NET_OutOfBandPrint_t)( int sock, netadr_t adr, const char *msg ); 243 | #if COD_VERSION == COD2_1_0 244 | static NET_OutOfBandPrint_t NET_OutOfBandPrint = (NET_OutOfBandPrint_t)0x0806C40C; 245 | #elif COD_VERSION == COD2_1_2 246 | static NET_OutOfBandPrint_t NET_OutOfBandPrint = (NET_OutOfBandPrint_t)0x0806C8D4; 247 | #elif COD_VERSION == COD2_1_3 248 | static NET_OutOfBandPrint_t NET_OutOfBandPrint = (NET_OutOfBandPrint_t)0x0806C8CC; 249 | #else 250 | #warning NET_OutOfBandPrint_t NET_OutOfBandPrint = NULL; 251 | static NET_OutOfBandPrint_t NET_OutOfBandPrint = (NET_OutOfBandPrint_t)NULL; 252 | #endif 253 | 254 | typedef int (*SV_FlushRedirect_t)(const char *outputbuf); 255 | #if COD_VERSION == COD2_1_0 256 | static SV_FlushRedirect_t SV_FlushRedirect = (SV_FlushRedirect_t)0x0809507C; 257 | #elif COD_VERSION == COD2_1_2 258 | static SV_FlushRedirect_t SV_FlushRedirect = (SV_FlushRedirect_t)0x08096F94; 259 | #elif COD_VERSION == COD2_1_3 260 | static SV_FlushRedirect_t SV_FlushRedirect = (SV_FlushRedirect_t)0x08097050; 261 | #else 262 | #warning SV_FlushRedirect_t SV_FlushRedirect = NULL; 263 | static SV_FlushRedirect_t SV_FlushRedirect = (SV_FlushRedirect_t)NULL; 264 | #endif 265 | 266 | typedef int (*SV_GameSendServerCommand_t)(int clientNum, signed int a2, const char *msg); 267 | #if COD_VERSION == COD2_1_0 268 | static SV_GameSendServerCommand_t SV_GameSendServerCommand = (SV_GameSendServerCommand_t)0x0808FE96; 269 | #elif COD_VERSION == COD2_1_2 270 | static SV_GameSendServerCommand_t SV_GameSendServerCommand = (SV_GameSendServerCommand_t)0x080916A6; 271 | #elif COD_VERSION == COD2_1_3 272 | static SV_GameSendServerCommand_t SV_GameSendServerCommand = (SV_GameSendServerCommand_t)0x080917AA; 273 | #else 274 | #warning static SV_GameSendServerCommand_t SV_GameSendServerCommand = NULL; 275 | static SV_GameSendServerCommand_t SV_GameSendServerCommand = (SV_GameSendServerCommand_t)NULL; 276 | #endif 277 | 278 | typedef int (*SV_DropClient_t)(int a1, char* message); 279 | #if COD_VERSION == COD2_1_0 280 | static SV_DropClient_t SV_DropClient = (SV_DropClient_t)0x0808DC8C; 281 | #elif COD_VERSION == COD2_1_2 282 | static SV_DropClient_t SV_DropClient = (SV_DropClient_t)0x0808EF9A; 283 | #elif COD_VERSION == COD2_1_3 284 | static SV_DropClient_t SV_DropClient = (SV_DropClient_t)0x0808F02E; 285 | #else 286 | #warning SV_DropClient_t SV_DropClient = (SV_DropClient_t)NULL; 287 | static SV_DropClient_t SV_DropClient = (SV_DropClient_t)NULL; 288 | #endif 289 | 290 | typedef int (*SV_WriteDownloadToClient_t)(int a1, int a2); 291 | #if COD_VERSION == COD2_1_0 292 | static SV_WriteDownloadToClient_t SV_WriteDownloadToClient = (SV_WriteDownloadToClient_t)0x0808E544; 293 | #elif COD_VERSION == COD2_1_2 294 | static SV_WriteDownloadToClient_t SV_WriteDownloadToClient = (SV_WriteDownloadToClient_t)0x0808FD2E; 295 | #elif COD_VERSION == COD2_1_3 296 | static SV_WriteDownloadToClient_t SV_WriteDownloadToClient = (SV_WriteDownloadToClient_t)0x0808FDC2; 297 | #else 298 | #warning static SV_WriteDownloadToClient_t SV_WriteDownloadToClient = (SV_WriteDownloadToClient_t)NULL; 299 | static SV_WriteDownloadToClient_t SV_WriteDownloadToClient = (SV_WriteDownloadToClient_t)NULL; 300 | #endif 301 | 302 | typedef int (*SV_BeginDownload_f_t)(int a1); 303 | static SV_BeginDownload_f_t SV_BeginDownload_f = (SV_BeginDownload_f_t)NULL; 304 | 305 | typedef int (*ClientUserinfoChanged_t)(int a1); 306 | #if COD_VERSION == COD2_1_0 307 | static ClientUserinfoChanged_t changeClientUserinfo = (ClientUserinfoChanged_t)0x080F6506; 308 | #elif COD_VERSION == COD2_1_2 309 | static ClientUserinfoChanged_t changeClientUserinfo = (ClientUserinfoChanged_t)0x080F8B1A; 310 | #elif COD_VERSION == COD2_1_3 311 | static ClientUserinfoChanged_t changeClientUserinfo = (ClientUserinfoChanged_t)0x080F8C5E; 312 | #else 313 | #warning ClientUserinfoChanged_t changeClientUserinfo = (ClientUserinfoChanged_t)NULL; 314 | static ClientUserinfoChanged_t changeClientUserinfo = (ClientUserinfoChanged_t)NULL; 315 | #endif 316 | 317 | typedef int (*Info_SetValueForKey_t)(char *s, const char *key, const char *value); 318 | #if COD_VERSION == COD2_1_0 319 | static Info_SetValueForKey_t Info_SetValueForKey = (Info_SetValueForKey_t)0x080B5FF6; 320 | #elif COD_VERSION == COD2_1_2 321 | static Info_SetValueForKey_t Info_SetValueForKey = (Info_SetValueForKey_t)0x080B848A; 322 | #elif COD_VERSION == COD2_1_3 323 | static Info_SetValueForKey_t Info_SetValueForKey = (Info_SetValueForKey_t)0x080B85CE; 324 | #else 325 | #warning Info_SetValueForKey_t Info_SetValueForKey = (Info_SetValueForKey_t)NULL; 326 | static Info_SetValueForKey_t Info_SetValueForKey = (Info_SetValueForKey_t)NULL; 327 | #endif 328 | 329 | typedef char* (*Info_ValueForKey_t)(char *s, const char *key); 330 | #if COD_VERSION == COD2_1_0 331 | static Info_ValueForKey_t Info_ValueForKey = (Info_ValueForKey_t)0x080B5B30; 332 | #elif COD_VERSION == COD2_1_2 333 | static Info_ValueForKey_t Info_ValueForKey = (Info_ValueForKey_t)0x080B7FC4; 334 | #elif COD_VERSION == COD2_1_3 335 | static Info_ValueForKey_t Info_ValueForKey = (Info_ValueForKey_t)0x080B8108; 336 | #else 337 | #warning Info_ValueForKey_t Info_ValueForKey = (Info_ValueForKey_t)NULL; 338 | static Info_ValueForKey_t Info_ValueForKey = (Info_ValueForKey_t)NULL; 339 | #endif 340 | 341 | typedef short (*codscript_call_callback_entity_t)(int self, int callback, int params); 342 | #if COD_VERSION == COD2_1_0 343 | static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)0x08118DF4; // search 'badMOD' 344 | #elif COD_VERSION == COD2_1_2 345 | static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)0x0811B128; 346 | #elif COD_VERSION == COD2_1_3 347 | static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)0x0811B284; 348 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 349 | static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)0x080C765C; 350 | #else 351 | #warning static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)NULL; 352 | static codscript_call_callback_entity_t codscript_call_callback_entity = (codscript_call_callback_entity_t)NULL; 353 | #endif 354 | 355 | typedef int (*codscript_callback_finish_t)(short callback_handle); 356 | #if COD_VERSION == COD2_1_0 357 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)0x08083B8E; 358 | #elif COD_VERSION == COD2_1_2 359 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)0x0808410A; 360 | #elif COD_VERSION == COD2_1_3 361 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)0x080841D6; 362 | #elif COD_VERSION == COD4_1_7 363 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)0x0815D042; 364 | #elif COD_VERSION == COD4_1_7_L 365 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)0x0815D062; 366 | #else 367 | #warning static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)NULL; 368 | static codscript_callback_finish_t codscript_callback_finish = (codscript_callback_finish_t)NULL; 369 | #endif 370 | 371 | #endif 372 | -------------------------------------------------------------------------------- /gsc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_HPP_ 2 | #define _GSC_HPP_ 3 | #define COD2_MAX_STRINGLENGTH 1024 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | // needs to be over the includes 10 | // example of versioning: 11 | /* 12 | #if COD2_VERSION == COD2_VERSION_1_2 13 | int *addressToCloserPointer = (int *)0x081872D0; 14 | #endif 15 | #if COD2_VERSION == COD2_VERSION_1_3 16 | int *addressToCloserPointer = (int *)0x081882F0; 17 | #endif 18 | */ 19 | 20 | #define COD2_VERSION_1_0 0 // depricated 21 | #define COD2_VERSION_1_2 2 // depricated 22 | #define COD2_VERSION_1_3 3 // depricated 23 | 24 | #define COD1_1_5 115 25 | #define COD2_1_0 210 26 | #define COD2_1_2 212 27 | #define COD2_1_3 213 28 | #define COD4_1_7 417 29 | #define COD4_1_7_L 4171 30 | 31 | //#define COD2_VERSION COD2_VERSION_1_2 32 | 33 | // gonna define that per command-line now, to build from script every version + select the correct with inbuilt if() 34 | //#define COD2_VERSION COD2_VERSION_1_3 35 | 36 | 37 | /* default stuff */ 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include // closer 500: dlcall 44 | #include // va_args 45 | 46 | #include "config.hpp" // DEBUG_MYSQL etc. 47 | 48 | #include "functions.hpp" 49 | 50 | #include "gsc_player.hpp" 51 | #include "gsc_astar.hpp" 52 | #include "gsc_mysql.hpp" 53 | #include "gsc_memory.hpp" 54 | #include "gsc_car.hpp" 55 | #include "gsc_tcc.hpp" 56 | #include "gsc_utils.hpp" 57 | #include "gsc_math.hpp" 58 | 59 | 60 | #include "cracking.hpp" // closer 900: nop 61 | 62 | /* 63 | static void printf_hide(const char *str, ...) 64 | { 65 | #if DEBUG_PRINTF == 1 66 | va_list args; 67 | va_start(args, str); 68 | vprintf(str, args); 69 | va_end(args); 70 | #endif 71 | } 72 | */ 73 | 74 | /* 75 | just search in winhex for "localized string" in the binary and go-to-fileoffset in IDA 76 | 77 | in cod4 search for "developer codepos" 78 | */ 79 | 80 | #if COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 || COD_VERSION == COD2_1_0 81 | #define STACK_UNDEFINED 0 82 | #define STACK_OBJECT 1 83 | #define STACK_STRING 2 84 | #define STACK_LOCALIZED_STRING 3 85 | #define STACK_VECTOR 4 86 | #define STACK_FLOAT 5 87 | #define STACK_INT 6 88 | #define STACK_CODEPOS 7 89 | #define STACK_PRECODEPOS 8 90 | #define STACK_FUNCTION 9 91 | #define STACK_STACK 10 92 | #define STACK_ANIMATION 11 93 | #define STACK_DEVELOPER_CODEPOS 12 94 | #define STACK_INCLUDE_CODEPOS 13 95 | #define STACK_THREAD_LIST 14 96 | #define STACK_THREAD_1 15 97 | #define STACK_THREAD_2 16 98 | #define STACK_THREAD_3 17 99 | #define STACK_THREAD_4 18 100 | #define STACK_STRUCT 19 101 | #define STACK_REMOVED_ENTITY 20 102 | #define STACK_ENTITY 21 103 | #define STACK_ARRAY 22 104 | #define STACK_REMOVED_THREAD 23 105 | 106 | #elif COD_VERSION == COD1_1_5 107 | 108 | #define STACK_UNDEFINED 0 109 | #define STACK_STRING 1 110 | #define STACK_LOCALIZED_STRING 2 111 | #define STACK_VECTOR 3 112 | #define STACK_FLOAT 4 113 | #define STACK_INT 5 114 | #define STACK_CODEPOS 6 115 | #define STACK_OBJECT 7 116 | #define STACK_KEY_VALUE 8 117 | #define STACK_FUNCTION 9 118 | #define STACK_STACK 10 119 | #define STACK_ANIMATION 11 120 | #define STACK_THREAD 12 121 | #define STACK_ENTITY 13 122 | #define STACK_STRUCT 14 123 | #define STACK_ARRAY 15 124 | #define STACK_DEAD_THREAD 16 125 | #define STACK_DEAD_ENTITY 17 126 | #define STACK_DEAD_OBJECT 18 127 | 128 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 129 | /* 130 | THOSE ARE CoD2 ones! 131 | 132 | WinHex: 1E3AE3 133 | 134 | */ 135 | #define STACK_UNDEFINED 0 136 | #define STACK_OBJECT 1 137 | #define STACK_STRING 2 138 | #define STACK_LOCALIZED_STRING 3 139 | #define STACK_VECTOR 4 140 | #define STACK_FLOAT 5 141 | #define STACK_INT 6 142 | #define STACK_CODEPOS 7 143 | #define STACK_PRECODEPOS 8 144 | #define STACK_FUNCTION 9 145 | #define STACK_STACK 10 146 | #define STACK_ANIMATION 11 147 | #define STACK_DEVELOPER_CODEPOS 12 148 | #define STACK_INCLUDE_CODEPOS 13 149 | #define STACK_THREAD_LIST 14 150 | #define STACK_THREAD_1 15 151 | #define STACK_THREAD_2 16 152 | #define STACK_THREAD_3 17 153 | #define STACK_THREAD_4 18 154 | #define STACK_STRUCT 19 155 | #define STACK_REMOVED_ENTITY 20 156 | #define STACK_ENTITY 21 157 | #define STACK_ARRAY 22 158 | #define STACK_REMOVED_THREAD 23 159 | #else 160 | // NO ERROR, because those are only available if code is compiled version-dependent! 161 | //#warning NO STACK TYPES 162 | #endif 163 | 164 | typedef struct 165 | { 166 | void *offsetData; 167 | int type; 168 | } aStackElement; 169 | 170 | int getStack(); 171 | int stackNew(); 172 | int stackPushUndefined(); 173 | 174 | int stackGetParamInt(int param, int *value); 175 | int stackGetParamString(int param, char **value); 176 | int stackGetParamVector(int param, float value[3]); 177 | int stackGetParamFloat(int param, float *value); 178 | int stackGetNumberOfParams(); 179 | int stackGetParamType(int param); 180 | char *stackGetParamTypeAsString(int param); 181 | int stackGetParams(char *params, ...); 182 | 183 | 184 | int stackReturnInt(int ret); // obsolete 185 | int stackPushInt(int ret); 186 | int stackReturnVector(float *ret); // obsolete 187 | int stackPushVector(float *ret); 188 | int stackPushFloat(float ret); 189 | int stackPushString(char *toPush); 190 | int stackPushEntity(int arg); 191 | int stackPushArray(); 192 | int stackPushArrayLast(); 193 | 194 | int stackCallScriptFunction(int self, int scriptFunction, int numberOfArgs); 195 | int stackSetKeyInArray(int precachedStringOffset); 196 | int cdecl_injected_closer(); 197 | int cdecl_injected_closer_stack_debug(); 198 | 199 | unsigned short get_var_by_idx(unsigned short index); 200 | unsigned short Scr_GetArray(int index); 201 | void Scr_GetArrayKeys(); 202 | 203 | int sub_8101B40(int self, int eInflictor, int eAttacker, float *vDir, float *vPoint, int iDamage, int iDFlags, int iMeansOfDeath, int iHitLoc, int psOffsetTime); 204 | int cdecl_cod2_player_damage_new(int self, int eInflictor, int eAttacker, float *vDir, float *vPoint, int iDamage, int iDFlags, int iMeansOfDeath, int iHitLoc, int psOffsetTime); 205 | 206 | // might put it in an extra file later, but atm its just one FS function 207 | // int FS_LoadDir(char *path, char *dir); 208 | 209 | 210 | // real functions and methods 211 | 212 | // functions 213 | typedef void (*Scr_FunctionCall)(); 214 | 215 | typedef struct { 216 | const char *name; 217 | Scr_FunctionCall call; 218 | int developer; 219 | } Scr_Function; 220 | 221 | typedef Scr_FunctionCall (*Scr_GetFunction_t)(const char **fname, int *fdev); 222 | 223 | Scr_FunctionCall Scr_GetCustomFunction(const char **fname, int *fdev); // could be made obsolete to remove the cracking_hook_call()-stuff 224 | 225 | // methods 226 | typedef void (*Scr_MethodCall)(int); 227 | 228 | typedef struct { 229 | const char* name; 230 | Scr_MethodCall call; 231 | int developer; 232 | } Scr_Method; 233 | 234 | typedef Scr_MethodCall (*Scr_GetMethod_t)(const char**, int*); 235 | 236 | Scr_MethodCall Scr_GetCustomMethod(const char **fname, int *fdev); // could be made obsolete to remove the cracking_hook_call()-stuff 237 | 238 | #ifdef __cplusplus 239 | } 240 | #endif 241 | 242 | #endif 243 | -------------------------------------------------------------------------------- /gsc_astar.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_astar.hpp" 2 | 3 | #if COMPILE_ASTAR == 1 4 | 5 | int gsc_graph_new() 6 | { 7 | int graph = GRAPH_new(); 8 | //printf("graph=%d", graph); 9 | return stackReturnInt(graph); 10 | } 11 | 12 | int gsc_graph_add_edge() // int GRAPH_add_edge(int graph, int first, int second); 13 | { 14 | int graph, first, second; 15 | 16 | int helper = 0; 17 | helper += stackGetParamInt(1, &graph); 18 | helper += stackGetParamInt(2, &first); 19 | helper += stackGetParamInt(3, &second); 20 | if (helper != 3) 21 | { 22 | printf("scriptengine> wrongs args for RAPH_add_edge(int graph, int first, int second);\n"); 23 | return stackReturnInt(0); 24 | } 25 | 26 | printf("GRAPH_add_edge(graph=%d, first=%d, second=%d);\n", graph, first, second); 27 | GRAPH_add_edge(graph, first, second); 28 | return stackReturnInt(1); 29 | } 30 | 31 | int gsc_graph_add_vertex() // int GRAPH_add_vertex(int graph, float x, float y, float z); 32 | { 33 | int graph; 34 | float x, y, z; 35 | int helper = 0; 36 | helper += stackGetParamInt(1, &graph); 37 | helper += stackGetParamFloat(2, &x); 38 | helper += stackGetParamFloat(3, &y); 39 | helper += stackGetParamFloat(4, &z); 40 | if (helper != 4) 41 | { 42 | printf("scriptengine> wrongs args for RAPH_add_vertex(int graph, float x, float y, float z);\n"); 43 | return stackReturnInt(0); 44 | } 45 | GRAPH_add_vertex(graph, x, y, z); 46 | printf("GRAPH_add_vertex(graph=%d, x=%.2f, y=%.2f, z=%.2f);\n", graph, x, y, z); 47 | return stackReturnInt(1); 48 | } 49 | 50 | int gsc_graph_delete() // int GRAPH_delete(int graph); 51 | { 52 | int graph; 53 | int helper = 0; 54 | helper += stackGetParamInt(1, &graph); 55 | if (helper != 1) 56 | { 57 | printf("scriptengine> wrongs args for: int GRAPH_delete(int graph)\n"); 58 | return stackReturnInt(0); 59 | } 60 | GRAPH_delete(graph); 61 | printf("GRAPH_delete(graph=%d);\n", graph); 62 | return stackReturnInt(1); 63 | } 64 | 65 | int gsc_graph_build() // int GRAPH_build(int graph); 66 | { 67 | int graph; 68 | int helper = 0; 69 | helper += stackGetParamInt(1, &graph); 70 | if (helper != 1) 71 | { 72 | printf("scriptengine> wrongs args for: int GRAPH_build(int graph)\n"); 73 | return stackReturnInt(0); 74 | } 75 | GRAPH_build(graph); 76 | printf("GRAPH_build(graph=%d);\n", graph); 77 | return stackReturnInt(1); 78 | } 79 | 80 | int gsc_graph_do_astar() // int *GRAPH_do_astar(int graph, int from, int to, int **outRet, int *outLen); 81 | { 82 | int graph, from, to; 83 | int helper = 0; 84 | helper += stackGetParamInt(1, &graph); 85 | helper += stackGetParamInt(2, &from); 86 | helper += stackGetParamInt(3, &to); 87 | if (helper != 3) 88 | { 89 | printf("scriptengine> wrongs args for: int GRAPH_do_astar(int graph, int from, int to)\n"); 90 | return stackReturnInt(0); 91 | } 92 | int *outRet, outLen; 93 | float cost; 94 | int ret = GRAPH_do_astar(graph, from, to, &outRet, &outLen, &cost); 95 | if (ret == 0) // just do as everything would be normal (empty results) 96 | { 97 | outLen = 0; 98 | cost = 0; 99 | } 100 | //printf("cost=%.2f\n", cost); 101 | 102 | int i; // useable out of this comment for the real array-creation 103 | #ifdef VERBOSE_GRAPH 104 | printf("GRAPH_do_astar(graph=%d, from=%d, to=%d, &outRet, &outLen);\n", graph, from, to); 105 | printf("route: "); 106 | 107 | for (i=0; i wrongs args for: int GRAPH_getNearestEdge(graph, pos)\n"); 171 | return stackReturnInt(0); 172 | } 173 | 174 | int wp1, wp2; 175 | GRAPH_getNearestEdge(graph, pos, &wp1, &wp2, NULL); 176 | 177 | // [0] == wp1 [1] == wp2 178 | int ret = stackPushArray(); // this will be an array with [0] and [1] 179 | 180 | 181 | int key1 = 0; // precached string "key1" 182 | int key2 = 0; 183 | memcpy(&key1, (void *)0x08853240, 2); // jeah it workes! 184 | memcpy(&key2, (void *)0x08853242, 2); 185 | 186 | stackPushInt(wp1); 187 | stackSetKeyInArray(key1); 188 | 189 | //ret = stackPushArray(); // [1] = cost 190 | //stackPushFloat(cost); 191 | stackPushInt(wp2); 192 | //stackPushArrayLast(); 193 | stackSetKeyInArray(key2); 194 | 195 | return ret; 196 | } 197 | 198 | #endif -------------------------------------------------------------------------------- /gsc_astar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_ASTAR_HPP_ 2 | #define _GSC_ASTAR_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | 17 | #if COMPILE_ASTAR == 1 18 | 19 | // LOOOOOOOOOOOOOL 20 | // i can leave this away and it compiles! 21 | // BUT THEN EVERYTHING IS INTEGER!!!! 22 | // SEARCHED SO LONG THE PROBLEM WHY FLOATES ARE MESSED UP 23 | extern int GRAPH_new(); // 8 24 | extern int GRAPH_add_edge(int graph, int first, int second); // 9 25 | extern int GRAPH_add_vertex(int graph, float x, float y, float z); // 10 26 | extern int GRAPH_delete(int graph); // 11 27 | extern int GRAPH_build(int graph); // 12 28 | extern int GRAPH_do_astar(int graph, int from, int to, int **outRet, int *outLen, float *outCost); // 13 29 | extern int GRAPH_getNearestEdge(int graph, float *pos, int *out_wp1, int *out_wp2, float **out_pos); // number 15 30 | extern int MATH_nearest_point_on_linesegment(float *from, float *to, float *toPoint, float *out_point); 31 | 32 | #endif 33 | 34 | int gsc_graph_new(); 35 | int gsc_graph_add_edge(); 36 | int gsc_graph_add_vertex(); 37 | int gsc_graph_delete(); 38 | int gsc_graph_build(); 39 | int gsc_graph_do_astar(); 40 | int gsc_graph_get_nearest_edge(); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif -------------------------------------------------------------------------------- /gsc_car.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_car.hpp" 2 | 3 | #if COMPILE_CAR == 0 4 | #warning gsc_car.cpp is not compiled 5 | #else 6 | 7 | // /root/q3rally/q3rallysa/engine/code/game 8 | // -I/root/q3rally/q3rallysa/ 9 | extern "C" 10 | { 11 | #include "engine/code/qcommon/q_shared.h" 12 | #include "engine/code/game/bg_public.h" 13 | #include "engine/code/game/bg_local.h" 14 | } 15 | #define DEBUG_CAR 1 16 | 17 | void my_trace(trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int passEntityNum, int contentMask) 18 | { 19 | results->startsolid = qfalse; 20 | results->allsolid = qfalse; 21 | 22 | // needed: fraction, plane(plane.normal), endpos, surfaceFlags 23 | 24 | //trace 0 00000000 25 | //printf("trace %d %.8x\n", passEntityNum, contentMask); 26 | } 27 | 28 | qboolean G_FrictionCalc_(const carPoint_t *point, float *sCOF, float *kCOF) 29 | { 30 | return qfalse; 31 | } 32 | int CG_PointContents_(const vec3_t point, int passEntityNum) 33 | { 34 | return 0; 35 | } 36 | 37 | void init_pm() 38 | { 39 | pm = (pmove_t *) malloc(sizeof(pmove_t)); 40 | memset(pm, 0, sizeof(pmove_t)); 41 | 42 | pm->ps = (playerState_t *) malloc(sizeof(playerState_t)); 43 | memset(pm->ps, 0, sizeof(playerState_t)); 44 | 45 | 46 | 47 | pm->ps->gravity = 800; 48 | pm->ps->viewangles[PITCH] = 0; 49 | pm->ps->viewangles[YAW] = 0; 50 | pm->ps->viewangles[ROLL] = 0; 51 | 52 | pm->ps->damageYaw = 0; 53 | pm->ps->damagePitch = 0; 54 | //pm->ps->damageRoll = 0; 55 | 56 | pm->ps->extra_eFlags = 0; 57 | 58 | //pm->cmd = (usercmd_t *) malloc(sizeof(usercmd_t)); 59 | pm->cmd.upmove = 100.0; 60 | pm->cmd.forwardmove = 100.0; 61 | pm->cmd.upmove = 100.0; 62 | 63 | pm->ps->stats[STAT_HEALTH] = 100; 64 | 65 | pm->manualShift = qfalse; 66 | pm->controlMode = CT_MOUSE; 67 | 68 | pm->car_frontweight_dist = 0.5; 69 | pm->car_body_elasticity = 0.05; 70 | pm->car_IT_xScale = 1.0; 71 | pm->car_IT_yScale = 1.0; 72 | pm->car_IT_zScale = 1.0; 73 | 74 | pm->car_swaybar = 20; 75 | 76 | pm->car_shock_up = 12; 77 | pm->car_shock_down = 11; 78 | 79 | pm->car_wheel = 2400; 80 | pm->car_wheel_damp = 140; 81 | 82 | pm->car_friction_scale = 1.10; 83 | 84 | pm->trace = my_trace; 85 | pm->frictionFunc = G_FrictionCalc_; 86 | pm->pointcontents = CG_PointContents_; 87 | 88 | pm->pDebug = 1; 89 | } 90 | 91 | int gsc_car_new() 92 | { 93 | float origin[3]; 94 | float viewangles[3]; 95 | float velocity[3]; 96 | 97 | 98 | static int first = 1; 99 | if (first) 100 | { 101 | printf("init_pm();\n"); 102 | init_pm(); 103 | first = 0; 104 | } 105 | 106 | int helper = 0; 107 | helper += stackGetParamVector(1, origin); 108 | helper += stackGetParamVector(2, viewangles); 109 | helper += stackGetParamVector(3, velocity); 110 | 111 | #if DEBUG_CAR 112 | printf("gsc_car_new(origin=(%.2f,%.2f,%.2f), viewangles=(%.2f,%.2f,%.2f), velocity(%.2f,%.2f,%.2f))\n", 113 | origin[0], origin[1], origin[2], 114 | viewangles[0], viewangles[1], viewangles[2], 115 | velocity[0], velocity[1], velocity[2] 116 | ); 117 | #endif 118 | 119 | if (helper != 3) 120 | { 121 | printf("scriptengine> wrongs args for gsc_car_new(origin, viewangles, velocity)\n"); 122 | return stackPushUndefined(); 123 | } 124 | 125 | car_t *car = (car_t *) malloc(sizeof(car_t)); 126 | 127 | /* 128 | vec3_t origin = {100,100,100}; 129 | vec3_t angles = {100,100,100}; 130 | vec3_t velocity = {0,0,10}; 131 | */ 132 | 133 | 134 | // instead of calling it myself, let PM_DriveMove do it 135 | //PM_InitializeVehicle(&car, origin, angles, velocity); 136 | //printf("car.initializeOnNextMove = %d\n", car.initializeOnNextMove); 137 | VectorCopy(origin, pm->ps->origin); 138 | VectorCopy(viewangles, pm->ps->viewangles); 139 | VectorCopy(velocity, pm->ps->velocity); 140 | /*VectorCopy(pm->ps->origin, origin); 141 | VectorCopy(pm->ps->viewangles, angles); 142 | VectorCopy(pm->ps->velocity, velocity);*/ 143 | car->initializeOnNextMove = qtrue; 144 | 145 | // initialize it the first time (maybe i shall call it myself to prevent the first run) 146 | PM_DriveMove(car, 0.20, qfalse); // includeBodies 147 | 148 | 149 | int ret = (int) car; 150 | return stackReturnInt(ret); 151 | } 152 | 153 | extern "C" void PM_DebugDynamics(carBody_t *body, carPoint_t *points); 154 | 155 | int gsc_car_update() 156 | { 157 | int car_address; 158 | 159 | 160 | int helper = 0; 161 | helper += stackGetParamInt(1, &car_address); 162 | 163 | #if DEBUG_CAR 164 | printf("gsc_car_update(car=%d)\n", car_address); 165 | #endif 166 | 167 | if (helper != 1) 168 | { 169 | printf("scriptengine> wrongs args for gsc_car_update(car)\n"); 170 | return stackPushUndefined(); 171 | } 172 | 173 | car_t *car = (car_t *) car_address; 174 | 175 | PM_DriveMove(car, 0.05, qfalse); // includeBodies 176 | 177 | PM_DebugDynamics(&(car->tBody), &(car->tPoints[0])); 178 | 179 | int ret = stackPushArray(); 180 | 181 | // ret[0] = origin 182 | stackPushVector(car->tBody.r); 183 | stackPushArrayLast(); 184 | 185 | // ret[1] = forward 186 | stackPushVector(car->tBody.forward); 187 | stackPushArrayLast(); 188 | 189 | return ret; 190 | } 191 | 192 | #endif -------------------------------------------------------------------------------- /gsc_car.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_CAR_HPP_ 2 | #define _GSC_CAR_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | #if COMPILE_CAR == 1 17 | int gsc_car_new(); 18 | int gsc_car_update(); 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif -------------------------------------------------------------------------------- /gsc_math.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_math.hpp" 2 | 3 | void gsc_math_sqrt() { 4 | float x; 5 | if ( ! stackGetParams("f", &x)) { 6 | printf("scriptengine> wrong param for sqrt(float x)\n"); 7 | stackPushUndefined(); 8 | return; 9 | } 10 | stackPushFloat(sqrt(x)); 11 | } 12 | 13 | void gsc_math_sqrtInv() { 14 | float x; 15 | if ( ! stackGetParams("f", &x)) { 16 | printf("scriptengine> wrong param for sqrtInv(float x)\n"); 17 | stackPushUndefined(); 18 | return; 19 | } 20 | // http://www.beyond3d.com/content/articles/8/ 21 | float xhalf = 0.5f*x; 22 | int i = *(int*)&x; 23 | i = 0x5f3759df - (i>>1); 24 | x = *(float*)&i; 25 | x = x*(1.5f - xhalf*x*x); 26 | 27 | stackPushFloat(x); 28 | } -------------------------------------------------------------------------------- /gsc_math.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_MATH_HPP_ 2 | #define _GSC_MATH_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | void gsc_math_sqrt(); 17 | void gsc_math_sqrtInv(); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif -------------------------------------------------------------------------------- /gsc_memory.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_memory.hpp" 2 | 3 | #if COMPILE_MEMORY == 0 4 | #warning gsc_memory.cpp is not compiled 5 | #else 6 | 7 | void gsc_memory_malloc() { 8 | int bytes; 9 | 10 | if ( ! stackGetParams("i", &bytes)) { 11 | printf("scriptengine> wrongs args for gsc_memory_malloc(bytes);\n"); 12 | stackPushUndefined(); 13 | return; 14 | } 15 | #if DEBUG_MEMORY 16 | printf("gsc_memory_malloc(bytes=%d)\n", bytes); 17 | #endif 18 | 19 | stackReturnInt((int) malloc(bytes)); 20 | } 21 | 22 | void gsc_memory_free() { 23 | int memory; 24 | 25 | if ( ! stackGetParams("i", &memory)) { 26 | printf("scriptengine> wrongs args for gsc_memory_free(memory);\n"); 27 | stackPushUndefined(); 28 | return; 29 | } 30 | #if DEBUG_MEMORY 31 | printf("gsc_memory_free(memory=%d)\n", memory); 32 | #endif 33 | 34 | free((void*)memory); 35 | stackReturnInt(0); 36 | } 37 | 38 | void gsc_memory_int_get() { 39 | int memory; 40 | 41 | if ( ! stackGetParams("i", &memory)) { 42 | printf("scriptengine> wrongs args for gsc_memory_int_get(memory);\n"); 43 | stackPushUndefined(); 44 | return; 45 | } 46 | #if DEBUG_MEMORY 47 | printf("gsc_memory_int_get(memory=%d)\n", memory); 48 | #endif 49 | 50 | stackReturnInt(*(int*)memory); 51 | } 52 | 53 | void gsc_memory_int_set() { 54 | int memory, value; 55 | 56 | if ( ! stackGetParams("ii", &memory, &value)) { 57 | printf("scriptengine> wrongs args for gsc_memory_int_set(memory, value);\n"); 58 | stackPushUndefined(); 59 | return; 60 | } 61 | #if DEBUG_MEMORY 62 | printf("gsc_memory_int_set(memory=%d, value=%d)\n", memory, value); 63 | #endif 64 | 65 | *(int*)memory = value; 66 | stackReturnInt(1); 67 | } 68 | 69 | void gsc_memory_memset() { 70 | int memory, value, bytes; 71 | 72 | if ( ! stackGetParams("iii", &memory, &value, &bytes)) { 73 | printf("scriptengine> wrongs args for gsc_memory_memset(memory, value, bytes);\n"); 74 | stackPushUndefined(); 75 | return; 76 | } 77 | #if DEBUG_MEMORY 78 | printf("gsc_memory_memset(memory=%d, value=%d, bytes=%d)\n", memory, value, bytes); 79 | #endif 80 | 81 | memset((void*)memory, value, bytes); 82 | stackReturnInt(1); 83 | } 84 | 85 | #include 86 | struct binarybuffer { 87 | int address; 88 | int pos; 89 | std::vector *strings; 90 | }; 91 | void gsc_binarybuffer_new() { 92 | int address; 93 | if ( ! stackGetParams("i", &address)) { 94 | printf("scriptengine> wrongs args for binarybuffer_new(address);\n"); 95 | stackPushUndefined(); 96 | return; 97 | } 98 | struct binarybuffer *bb = (struct binarybuffer *)malloc(sizeof(struct binarybuffer)); 99 | bb->address = address; 100 | bb->pos = 0; 101 | bb->strings = new std::vector(); 102 | stackPushInt((int)bb); 103 | } 104 | void gsc_binarybuffer_free() { 105 | struct binarybuffer *bb; 106 | if ( ! stackGetParams("i", &bb)) { 107 | printf("scriptengine> wrongs args for binarybuffer_free(binarybuffer);\n"); 108 | stackPushUndefined(); 109 | return; 110 | } 111 | for (std::vector::const_iterator i = bb->strings->begin(); i != bb->strings->end(); i++) 112 | free(*i); 113 | delete bb->strings; 114 | free(bb); 115 | stackReturnInt(1); 116 | } 117 | void gsc_binarybuffer_seek() { 118 | struct binarybuffer *bb; 119 | int pos; 120 | if ( ! stackGetParams("ii", &bb, &pos)) { 121 | printf("scriptengine> wrongs args for binarybuffer_seek(binarybuffer, pos);\n"); 122 | stackPushUndefined(); 123 | return; 124 | } 125 | bb->pos = pos; 126 | stackReturnInt(1); 127 | } 128 | void gsc_binarybuffer_write() { 129 | struct binarybuffer *bb; 130 | char *type; 131 | if ( ! stackGetParams("is", &bb, &type)) { 132 | printf("scriptengine> wrongs args for binarybuffer_write(binarybuffer, type [, value] );\n"); 133 | stackPushUndefined(); 134 | return; 135 | } 136 | switch (type[0]) { 137 | case 'i': { 138 | int tmp_int; 139 | stackGetParamInt(2, &tmp_int); 140 | *(int *)(bb->address + bb->pos) = tmp_int; 141 | #if DEBUG_MEMORY 142 | printf("type=i bb->address=%.8p + %d = %d\n", bb->address, bb->pos, *(int *)(bb->address + bb->pos)); 143 | #endif 144 | bb->pos += 4; 145 | break; 146 | } 147 | case 'f': { 148 | float tmp_float; 149 | stackGetParamFloat(2, &tmp_float); 150 | *(float *)(bb->address + bb->pos) = tmp_float; 151 | #if DEBUG_MEMORY 152 | printf("type=f bb->address=%.8p + %d = %f\n", bb->address, bb->pos, *(float *)(bb->address + bb->pos)); 153 | #endif 154 | bb->pos += 4; 155 | break; 156 | } 157 | case 'd': { 158 | float tmp_float; 159 | stackGetParamFloat(2, &tmp_float); 160 | *(double *)(bb->address + bb->pos) = (double)tmp_float; 161 | #if DEBUG_MEMORY 162 | printf("type=d bb->address=%.8p + %d = %f\n", bb->address, bb->pos, *(double *)(bb->address + bb->pos)); 163 | #endif 164 | bb->pos += 8; 165 | break; 166 | } 167 | case 's': { 168 | char *tmp_str; 169 | stackGetParamString(2, &tmp_str); 170 | char *copy = (char *)malloc(strlen(tmp_str) + 1); 171 | strcpy(copy, tmp_str); 172 | bb->strings->push_back(copy); 173 | *(char **)(bb->address + bb->pos) = copy; 174 | #if DEBUG_MEMORY 175 | printf("type=s bb->address=%.8p + %d = %s\n", bb->address, bb->pos, *(char **)(bb->address + bb->pos)); 176 | #endif 177 | bb->pos += 4; 178 | break; 179 | } 180 | case 'c': { 181 | char *tmp_str; 182 | stackGetParamString(2, &tmp_str); 183 | *(char *)(bb->address + bb->pos) = tmp_str[0]; 184 | #if DEBUG_MEMORY 185 | printf("type=c bb->address=%.8p + %d = %c\n", bb->address, bb->pos, *(char *)(bb->address + bb->pos)); 186 | #endif 187 | bb->pos += 1; 188 | break; 189 | } 190 | case 'v': { 191 | float tmp_vector[3]; 192 | stackGetParamVector(2, tmp_vector); 193 | *(float *)(bb->address + bb->pos + 0) = tmp_vector[0]; 194 | *(float *)(bb->address + bb->pos + 4) = tmp_vector[1]; 195 | *(float *)(bb->address + bb->pos + 8) = tmp_vector[2]; 196 | #if DEBUG_MEMORY 197 | printf("type=v bb->address=%.8p + %d = (%f,%f,%f)\n", bb->address, bb->pos, 198 | *(float *)(bb->address + bb->pos + 0), 199 | *(float *)(bb->address + bb->pos + 4), 200 | *(float *)(bb->address + bb->pos + 8) 201 | ); 202 | #endif 203 | bb->pos += 12; 204 | break; 205 | } 206 | } 207 | stackReturnInt(1); 208 | } 209 | void gsc_binarybuffer_read() { 210 | struct binarybuffer *bb; 211 | char *type; 212 | if ( ! stackGetParams("is", &bb, &type)) { 213 | printf("scriptengine> wrongs args for binarybuffer_read(binarybuffer, type);\n"); 214 | stackPushUndefined(); 215 | return; 216 | } 217 | switch (type[0]) { 218 | case 'i': { 219 | int tmp_int; 220 | tmp_int = *(int *)(bb->address + bb->pos); 221 | bb->pos += 4; 222 | stackPushInt(tmp_int); 223 | return; 224 | } 225 | case 'f': { 226 | float tmp_float; 227 | tmp_float = *(float *)(bb->address + bb->pos); 228 | bb->pos += 4; 229 | stackPushFloat(tmp_float); 230 | return; 231 | } 232 | case 'd': { 233 | float tmp_float; 234 | tmp_float = (float)*(double *)(bb->address + bb->pos); 235 | bb->pos += 8; 236 | stackPushFloat(tmp_float); 237 | return; 238 | } 239 | case 's': { 240 | char *tmp_str; 241 | tmp_str = *(char **)(bb->address + bb->pos); 242 | bb->pos += 4; 243 | stackPushString(tmp_str); 244 | return; 245 | } 246 | case 'c': { 247 | char tmp_str[2]; 248 | tmp_str[0] = *(char *)(bb->address + bb->pos); 249 | tmp_str[1] = '\0'; 250 | bb->pos += 1; 251 | stackPushString(tmp_str); 252 | return; 253 | } 254 | case 'v': { 255 | float *tmp_vector; 256 | tmp_vector = (float *)(bb->address + bb->pos + 0); 257 | bb->pos += 12; 258 | stackPushVector(tmp_vector); 259 | return; 260 | } 261 | } 262 | stackPushUndefined(); 263 | } 264 | #endif 265 | -------------------------------------------------------------------------------- /gsc_memory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_MEMORY_HPP_ 2 | #define _GSC_MEMORY_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | #if COMPILE_MEMORY == 1 17 | void gsc_memory_malloc(); 18 | void gsc_memory_free(); 19 | void gsc_memory_int_get(); 20 | void gsc_memory_int_set(); 21 | void gsc_memory_memset(); 22 | 23 | void gsc_binarybuffer_new(); 24 | void gsc_binarybuffer_free(); 25 | void gsc_binarybuffer_seek(); 26 | void gsc_binarybuffer_write(); 27 | void gsc_binarybuffer_read(); 28 | 29 | #endif 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /gsc_mysql.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_MYSQL_HPP_ 2 | #define _GSC_MYSQL_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | /* offsetof */ 17 | #include 18 | 19 | //#pragma GCC visibility push(hidden) 20 | 21 | //#define HIDDEN __attribute__((__visibility__("hidden"))) 22 | 23 | #define HIDDEN 24 | 25 | void gsc_mysql_init(); 26 | void gsc_mysql_real_connect(); 27 | void gsc_mysql_close(); 28 | void gsc_mysql_query(); 29 | void gsc_mysql_errno(); 30 | void gsc_mysql_error(); 31 | void gsc_mysql_affected_rows(); 32 | void gsc_mysql_store_result(); 33 | void gsc_mysql_num_rows(); 34 | void gsc_mysql_num_fields(); 35 | void gsc_mysql_field_seek(); 36 | void gsc_mysql_fetch_field(); 37 | void gsc_mysql_fetch_row(); 38 | void gsc_mysql_free_result(); 39 | void gsc_mysql_real_escape_string(); 40 | void gsc_mysql_async_create_query(); 41 | void gsc_mysql_async_create_query_nosave(); 42 | void gsc_mysql_async_getdone_list(); 43 | void gsc_mysql_async_getresult_and_free(); 44 | void gsc_mysql_async_initializer(); 45 | void gsc_mysql_reuse_connection(); 46 | 47 | /*HIDDEN*/ int gsc_mysql_stmt_init(); 48 | /*HIDDEN*/ int gsc_mysql_stmt_close(); 49 | /*HIDDEN*/ int gsc_mysql_stmt_get_stmt_id(); 50 | /*HIDDEN*/ int gsc_mysql_stmt_get_prefetch_rows(); 51 | /*HIDDEN*/ int gsc_mysql_stmt_get_param_count(); 52 | /*HIDDEN*/ int gsc_mysql_stmt_get_field_count(); 53 | /*HIDDEN*/ int gsc_mysql_stmt_prepare(); 54 | /*HIDDEN*/ int gsc_mysql_stmt_bind_param(); 55 | /*HIDDEN*/ int gsc_mysql_stmt_bind_result(); 56 | /*HIDDEN*/ int gsc_mysql_stmt_execute(); 57 | /*HIDDEN*/ int gsc_mysql_stmt_store_result(); 58 | /*HIDDEN*/ int gsc_mysql_stmt_fetch(); 59 | 60 | // test scenaries directly in cod2, no second... third ... fourth single project 61 | int gsc_mysql_test_0(); 62 | int gsc_mysql_test_1(); 63 | 64 | //#pragma GCC visibility pop 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif -------------------------------------------------------------------------------- /gsc_player.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_player.hpp" 2 | 3 | #if COMPILE_PLAYER == 1 4 | 5 | #if COD_VERSION == COD2_1_0 6 | int playerStates = 0x086F1480; // search 'winner' 7 | int sizeOfPlayer = 0x28A4; 8 | #elif COD_VERSION == COD2_1_2 9 | int playerStates = 0x08705480; // as in game initialisation "------- Game Initializati" 10 | int sizeOfPlayer = 0x28A4; 11 | // memset(&playerStates_8705480, 0, 0xA2900u); 12 | // then we need a bit math: 0xA2900 / 64 = 0x28A4 13 | #elif COD_VERSION == COD2_1_3 14 | // 8716558 pointed on that!! and that i found in setorigin() with ida decompiler 15 | // looked it up and it points to game_initialization_8109096() 16 | int playerStates = 0x087a2500; 17 | int sizeOfPlayer = 0x28A4; 18 | #elif COD_VERSION == COD4_1_7 19 | /* 20 | memset((void *)0x841F260, 0, 0x9D000u); 21 | v836f6c4 = 138539616; 22 | v836f8a4 = *(_DWORD *)(v84bc268 + 12); 23 | memset((void *)0x84BC3A0, 0, 0xC6100u); // bottom = playerstates 24 | */ 25 | int playerStates = 0x084BC3A0; 26 | int sizeOfPlayer = 0x3184; 27 | #elif COD_VERSION == COD4_1_7_L 28 | int playerStates = 0x084BD120; 29 | int sizeOfPlayer = 0x3184; 30 | #else 31 | #warning int playerStates int sizeOfPlayer 32 | int playerStates = NULL; 33 | int sizeOfPlayer = NULL; 34 | #endif 35 | 36 | #if COD_VERSION == COD2_1_0 37 | int gentities = 0x08665480; 38 | int gentities_size = 560; 39 | #elif COD_VERSION == COD2_1_2 40 | int gentities = 0x08679380; 41 | int gentities_size = 560; 42 | #elif COD_VERSION == COD2_1_3 43 | int gentities = 0x08716400; 44 | int gentities_size = 560; 45 | #elif COD_VERSION == COD4_1_7 46 | int gentities = 0x0841F260; 47 | int gentities_size = 628; 48 | #elif COD_VERSION == COD4_1_7_L 49 | int gentities = 0x0841FFE0; 50 | int gentities_size = 628; 51 | #else 52 | #warning int gentities int gentities_size 53 | int gentities = NULL; 54 | int gentities_size = NULL; 55 | #endif 56 | 57 | #define PLAYERSTATE(playerid) (playerStates + playerid * sizeOfPlayer) 58 | #if COD_VERSION == COD2_1_0 || COD_VERSION == COD2_1_2 || COD_VERSION == COD2_1_3 59 | #define PLAYERSTATE_VELOCITY(playerid) (PLAYERSTATE(playerid) + 0x20) 60 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 61 | #define PLAYERSTATE_VELOCITY(playerid) (PLAYERSTATE(playerid) + 40) 62 | #else 63 | #warning NO PLAYERSTATE_VELOCITY! 64 | #define PLAYERSTATE_VELOCITY(playerid) 0 65 | #endif 66 | 67 | #if COD_VERSION == COD2_1_0 68 | int playerinfo_base = 0x0841FB0C; 69 | int playerinfo_size = 0x78F14; 70 | #elif COD_VERSION == COD2_1_2 71 | int playerinfo_base = 0x0842200C; 72 | int playerinfo_size = 0x79064; 73 | #elif COD_VERSION == COD2_1_3 74 | int playerinfo_base = 0x0842308C; 75 | int playerinfo_size = 0xB1064; 76 | #elif COD_VERSION == COD4_1_7 77 | int playerinfo_base = 0x090B420C; 78 | int playerinfo_size = 0x2958F; 79 | #elif COD_VERSION == COD4_1_7_L 80 | int playerinfo_base = 0x090B4F8C; 81 | int playerinfo_size = 0x2958F; 82 | #else 83 | #warning PLAYERBASE() got no working addresses 84 | int playerinfo_base = 0x0; 85 | int playerinfo_size = 0x0; 86 | #endif 87 | 88 | #if COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 89 | #define PLAYERBASE(playerid) (playerinfo_base + playerid * playerinfo_size) 90 | #else 91 | #define PLAYERBASE(playerid) (*(int*)(playerinfo_base) + playerid * playerinfo_size) 92 | #endif 93 | 94 | int clientaddress_to_num(int address) { 95 | return (address - playerStates) / sizeOfPlayer; 96 | } 97 | 98 | int gentityaddress_to_num(int client) { 99 | return (client - gentities) / gentities_size; 100 | } 101 | 102 | void gsc_player_velocity_set(int id) { 103 | float velocity[3]; 104 | 105 | if ( ! stackGetParams("v", &velocity)) { 106 | printf("scriptengine> wrongs args for gsc_player_velocity_add(vector velocity);\n"); 107 | stackPushUndefined(); 108 | return; 109 | } 110 | 111 | float *player_0_velocity_x = (float *)(PLAYERSTATE_VELOCITY(id) + 0); 112 | float *player_0_velocity_y = (float *)(PLAYERSTATE_VELOCITY(id) + 4); 113 | float *player_0_velocity_z = (float *)(PLAYERSTATE_VELOCITY(id) + 8); 114 | 115 | *player_0_velocity_x = velocity[0]; 116 | *player_0_velocity_y = velocity[1]; 117 | *player_0_velocity_z = velocity[2]; 118 | 119 | stackReturnInt(1); 120 | } 121 | 122 | void gsc_player_clientuserinfochanged(int id) 123 | { 124 | stackPushInt(changeClientUserinfo(id)); 125 | } 126 | 127 | void gsc_player_velocity_add(int id) { 128 | float velocity[3]; 129 | 130 | if ( ! stackGetParams("v", &velocity)) { 131 | printf("scriptengine> wrongs args for gsc_player_velocity_add(vector velocity);\n"); 132 | stackPushUndefined(); 133 | return; 134 | } 135 | 136 | float *player_0_velocity_x = (float *)(PLAYERSTATE_VELOCITY(id) + 0); 137 | float *player_0_velocity_y = (float *)(PLAYERSTATE_VELOCITY(id) + 4); 138 | float *player_0_velocity_z = (float *)(PLAYERSTATE_VELOCITY(id) + 8); 139 | 140 | *player_0_velocity_x += velocity[0]; 141 | *player_0_velocity_y += velocity[1]; 142 | *player_0_velocity_z += velocity[2]; 143 | 144 | stackReturnInt(1); 145 | } 146 | 147 | void gsc_get_userinfo(int id) 148 | { 149 | char* key; 150 | char* val; 151 | if(!stackGetParamString(0, &key)) 152 | { 153 | printf("First param needs to be a string for get_userinfo\n"); 154 | stackPushUndefined(); 155 | return; 156 | } 157 | 158 | int entity = PLAYERBASE(id); 159 | val = Info_ValueForKey((char*)entity+12, key); 160 | 161 | if(strlen(val)) 162 | stackPushString(val); 163 | else 164 | stackPushUndefined(); 165 | } 166 | 167 | void gsc_set_userinfo(int id) 168 | { 169 | char* key; 170 | char* value; 171 | if(!stackGetParamString(0, &key)) 172 | { 173 | printf("First param needs to be a string for get_userinfo\n"); 174 | stackPushUndefined(); 175 | return; 176 | } 177 | if(!stackGetParamString(1, &value)) 178 | { 179 | printf("second param needs to be a string for get_userinfo\n"); 180 | stackPushUndefined(); 181 | return; 182 | } 183 | 184 | int entity = PLAYERBASE(id); 185 | Info_SetValueForKey((char*)entity + 12, key, value); 186 | stackPushUndefined(); 187 | } 188 | 189 | void gsc_player_velocity_get(int id) { 190 | //int currentPlayer = playerStates + id * sizeOfPlayer; 191 | float *vectorVelocity = (float *)PLAYERSTATE_VELOCITY(id); // (currentPlayer + 0x20); 192 | stackReturnVector(vectorVelocity); 193 | } 194 | 195 | // aimButtonPressed (toggleads or +speed/-speed) 196 | void gsc_player_button_ads(int id) { 197 | int currentPlayer = playerStates + id * sizeOfPlayer; 198 | unsigned char *aim_address = (unsigned char *)(currentPlayer + 0x26CD); 199 | int aimButtonPressed = *aim_address & 0xF0; // just the first 4 bits tell the state 200 | stackReturnInt(aimButtonPressed); 201 | } 202 | 203 | void gsc_player_button_left(int id) { 204 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 205 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26FD); 206 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 207 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FA7); 208 | #else 209 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 210 | unsigned char *aim_address = (unsigned char *)(NULL); 211 | #endif 212 | int leftButtonPressed = (*aim_address & 0x81)==0x81; 213 | stackReturnInt(leftButtonPressed); 214 | } 215 | 216 | void gsc_player_button_right(int id) { 217 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 218 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26FD); 219 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 220 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FA7); 221 | #else 222 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 223 | unsigned char *aim_address = (unsigned char *)(NULL); 224 | #endif 225 | 226 | int rightButtonPressed = (*aim_address & 0x7F)==0x7F; 227 | stackReturnInt(rightButtonPressed); 228 | } 229 | 230 | void gsc_player_button_forward(int id) { 231 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 232 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26FC); 233 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 234 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FA6); 235 | #else 236 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 237 | unsigned char *aim_address = (unsigned char *)(NULL); 238 | #endif 239 | 240 | int forwardButtonPressed = (*aim_address & 0x7F)==0x7F; 241 | stackReturnInt(forwardButtonPressed); 242 | } 243 | 244 | void gsc_player_button_back(int id) { 245 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 246 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26FC); 247 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 248 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FA6); 249 | #else 250 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 251 | unsigned char *aim_address = (unsigned char *)(NULL); 252 | #endif 253 | 254 | int backButtonPressed = (*aim_address & 0x81)==0x81; 255 | stackReturnInt(backButtonPressed); 256 | } 257 | 258 | void gsc_player_button_leanleft(int id) { 259 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 260 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26E8); 261 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 262 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FB4); 263 | #else 264 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 265 | unsigned char *aim_address = (unsigned char *)(NULL); 266 | #endif 267 | 268 | int leanleftButtonPressed = (*aim_address & 0x40)==0x40; 269 | stackReturnInt(leanleftButtonPressed); 270 | } 271 | 272 | void gsc_player_button_leanright(int id) { 273 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 274 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26E8); 275 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 276 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FB4); 277 | #else 278 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 279 | unsigned char *aim_address = (unsigned char *)(NULL); 280 | #endif 281 | 282 | int leanrightButtonPressed = (*aim_address & 0x80)==0x80; 283 | stackReturnInt(leanrightButtonPressed); 284 | } 285 | 286 | void gsc_player_button_jump(int id) { 287 | #if COD2_VERSION == COD2_VERSION_1_0 || COD2_VERSION == COD2_VERSION_1_2 || COD2_VERSION == COD2_VERSION_1_3 288 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x26E9); 289 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 290 | unsigned char *aim_address = (unsigned char *)(PLAYERSTATE(id) + 0x2FB5); 291 | #else 292 | #warning unsigned char *aim_address = (unsigned char *)(NULL); 293 | unsigned char *aim_address = (unsigned char *)(NULL); 294 | #endif 295 | 296 | int jumpButtonPressed = (*aim_address & 0x04)==0x04; 297 | stackReturnInt(jumpButtonPressed); 298 | } 299 | 300 | /* 301 | CoD2 = 26E8 == leanleft:40 leanright:80 302 | CoD4 = 26E9 == jump:04 303 | CoD2 = 26FC == forward:7f backward:81 304 | CoD2 = 26FD == left:81 right:7f 305 | 306 | CoD4 = 2FA6 == forward:7f backward:81 307 | CoD4 = 2FA7 == left:81 right:7f 308 | CoD4 = 2FB4 == leanleft:40 leanright:80 309 | CoD4 = 2FB5 == jump:04 310 | */ 311 | 312 | void gsc_player_stance_get(int id) { 313 | int entity = gentities + id * gentities_size; 314 | unsigned char *stance_address = (unsigned char *)(entity + 8); 315 | int code = *stance_address & 0x0F; // just the last 4 bits tell the state 316 | 317 | char *stance = ""; 318 | switch (code) { 319 | case 0: stance = "stand"; break; // also in spec 320 | case 2: stance = "stand"; break; 321 | case 4: stance = "duck"; break; 322 | case 6: stance = "duck"; break; 323 | case 8: stance = "lie"; break; 324 | case 10: stance = "lie"; break; 325 | default: printf("unknown stance for player id=%d, code=%d\n", id, code); 326 | } 327 | 328 | stackPushString(stance); 329 | } 330 | 331 | void gsc_player_spectatorclient_get(int id) { 332 | int spectatorClient = *(unsigned char *)(PLAYERSTATE(id) + 0xCC); 333 | 334 | //printf("spectator client: %x=%d\n", entity, spectatorClient); 335 | 336 | // ups, its ALWAYS returning a real id 337 | // when i have 2 bots, then i got id 2, when i spec "myself" it will return 2, also when i play myself 338 | //if ( ! spectatorClient) 339 | // return stackPushUndefined(); 340 | 341 | stackPushEntity(gentities + spectatorClient * gentities_size); 342 | } 343 | 344 | void gsc_player_getip(int id) { 345 | #if COD_VERSION == COD2_1_0 346 | int info_ip_offset = 0x6E5C8; 347 | #elif COD_VERSION == COD2_1_2 348 | int info_ip_offset = 0x6E6D8; 349 | #elif COD_VERSION == COD2_1_3 350 | int info_ip_offset = 0x6E6D8; 351 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 352 | int info_ip_offset = 0x9; 353 | #else 354 | #warning gsc_player_getip() got no working addresses 355 | int info_ip_offset = 0x0; 356 | #endif 357 | 358 | char tmp[64]; 359 | unsigned int ip_a, ip_b, ip_c, ip_d; 360 | 361 | #if COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 362 | char iphex[9]; 363 | snprintf(iphex, 9, "%08x", ((int *)PLAYERBASE(id))[info_ip_offset]); 364 | sscanf(iphex, "%2x%2x%2x%2x", &ip_d, &ip_c, &ip_b, &ip_a); 365 | #else 366 | int info_player = PLAYERBASE(id); 367 | ip_a = *(unsigned char *)(info_player + info_ip_offset + 0); 368 | ip_b = *(unsigned char *)(info_player + info_ip_offset + 1); // dafuq, its +1 but in IDA its +4 step :S 369 | ip_c = *(unsigned char *)(info_player + info_ip_offset + 2); 370 | ip_d = *(unsigned char *)(info_player + info_ip_offset + 3); 371 | //int port = *(unsigned char *)(info_player + info_ip_offset + 16); 372 | //snprintf(tmp, 64, "%d.%d.%d.%d:%d", ip_a, ip_b, ip_c, ip_d, port); 373 | #endif 374 | snprintf(tmp, 64, "%d.%d.%d.%d", ip_a, ip_b, ip_c, ip_d); 375 | 376 | stackPushString(tmp); 377 | } 378 | 379 | void gsc_player_getping(int id) { 380 | #if COD_VERSION == COD2_1_0 381 | int info_ping_offset = 0x6E5A4; 382 | #elif COD_VERSION == COD2_1_2 383 | int info_ping_offset = 0x6E6B4; 384 | #elif COD_VERSION == COD2_1_3 385 | int info_ping_offset = 0x6E6B4; 386 | #elif COD_VERSION == COD4_1_7 || COD_VERSION == COD4_1_7_L 387 | int info_ping_offset = 0x804EC; 388 | #else 389 | #warning gsc_player_getport() got no working addresses 390 | int info_ping_offset = 0x0; 391 | #endif 392 | 393 | int ping = *(unsigned int *)(PLAYERBASE(id) + info_ping_offset); 394 | stackPushInt(ping); 395 | } 396 | 397 | void gsc_player_ClientCommand(int id) { 398 | stackPushInt(ClientCommand(id)); 399 | } 400 | 401 | int getSVSTime() 402 | { 403 | #if COD_VERSION == COD2_1_0 404 | int info_start = *(int *)0x0841FB04; 405 | #elif COD_VERSION == COD2_1_2 406 | int info_start = *(int *)0x08422004; 407 | #elif COD_VERSION == COD2_1_3 408 | int info_start = *(int *)0x08423084; 409 | #else 410 | #warning getSVSTime() got no working addresses 411 | int info_start = *(int *)0x0; 412 | #endif 413 | return info_start; 414 | } 415 | 416 | void gsc_player_getLastConnectTime(int id) { 417 | #if COD_VERSION == COD2_1_0 418 | int info_connecttime_offset = 0x20D14; 419 | #elif COD_VERSION == COD2_1_2 420 | int info_connecttime_offset = 0x20E24; 421 | #elif COD_VERSION == COD2_1_3 422 | int info_connecttime_offset = 0x20E24; 423 | #else 424 | #warning gsc_player_getLastConnectTime() got no working addresses 425 | int info_connecttime_offset = 0x0; 426 | #endif 427 | 428 | int lastconnect = getSVSTime() - *(unsigned int *)(PLAYERBASE(id) + info_connecttime_offset); 429 | stackPushInt(lastconnect); 430 | } 431 | 432 | int getLastPacketTime(int id) { 433 | #if COD_VERSION == COD2_1_0 434 | int info_lastmsg_offset = 0x20D10; 435 | #elif COD_VERSION == COD2_1_2 436 | int info_lastmsg_offset = 0x20E20; 437 | #elif COD_VERSION == COD2_1_3 438 | int info_lastmsg_offset = 0x20E20; 439 | #else 440 | #warning getLastPacketTime() got no working addresses 441 | int info_lastmsg_offset = 0x0; 442 | #endif 443 | 444 | return (PLAYERBASE(id) + info_lastmsg_offset); 445 | } 446 | 447 | void gsc_player_getLastMSG(int id) { 448 | int lastmsg = getSVSTime() - *(unsigned int *)getLastPacketTime(id); 449 | stackPushInt(lastmsg); 450 | } 451 | 452 | void gsc_player_getclientstate(int id) { 453 | int info_player = PLAYERBASE(id); 454 | stackPushInt(*(int*)info_player); 455 | } 456 | 457 | int getAddressType(int id) { 458 | #if COD_VERSION == COD2_1_0 459 | int info_addresstype_offset = 0x6E5C4; 460 | #elif COD_VERSION == COD2_1_2 461 | int info_addresstype_offset = 0x6E6D4; 462 | #elif COD_VERSION == COD2_1_3 463 | int info_addresstype_offset = 0x6E6D4; 464 | #else 465 | #warning gsc_player_addresstype() got no working addresses 466 | int info_addresstype_offset = 0x0; 467 | #endif 468 | 469 | int addrtype = *(unsigned int *)(PLAYERBASE(id) + info_addresstype_offset); 470 | } 471 | 472 | void gsc_player_addresstype(int id) { 473 | stackPushInt(getAddressType(id)); 474 | } 475 | 476 | void gsc_player_renameclient(int id) { 477 | char * key; 478 | 479 | if ( ! stackGetParams("s", &key)) { 480 | printf("scriptengine> ERROR: gsc_player_renameclient(): param \"key\"[1] has to be an string!\n"); 481 | stackPushUndefined(); 482 | return; 483 | } 484 | 485 | int info_player = PLAYERBASE(id); 486 | Info_SetValueForKey((char *)(info_player + 12), "name", key); 487 | char * name = (char *)(info_player + 134216); 488 | memcpy(&name[0], key, 32); 489 | name[31] = '\0'; 490 | printf("name = %s\n", name); 491 | 492 | stackPushInt(1); 493 | } 494 | 495 | void gsc_player_outofbandprint(int id) { 496 | char* cmd; // print\ninsert test message here!!!\n 497 | 498 | if ( ! stackGetParams("s", &cmd)) { 499 | printf("scriptengine> ERROR: gsc_player_outofbandprint(): param \"cmd\"[1] has to be an string!\n"); 500 | stackPushUndefined(); 501 | return; 502 | } 503 | 504 | #if COD_VERSION == COD2_1_0 505 | int remoteaddress_offset = 452036; 506 | #else 507 | int remoteaddress_offset = 452308; 508 | #endif 509 | 510 | int info_player = PLAYERBASE(id); 511 | netadr_t * from = (netadr_t*)(info_player + remoteaddress_offset); 512 | NET_OutOfBandPrint(0, *from, cmd); // 0 = SERVER, 1 = CLIENT 513 | 514 | stackReturnInt(1); 515 | } 516 | 517 | void gsc_player_connectionlesspacket(int id) { 518 | char* cmd; // rcon pass status 519 | 520 | if ( ! stackGetParams("s", &cmd)) { 521 | printf("scriptengine> ERROR: gsc_player_connectionlesspacket(): param \"cmd\"[1] has to be an string!\n"); 522 | stackPushUndefined(); 523 | return; 524 | } 525 | 526 | char message[1024]; 527 | message[0] = -1; 528 | message[1] = -1; 529 | message[2] = -1; 530 | message[3] = -1; 531 | message[4] = 0; 532 | strcat(message, cmd); 533 | msg_t msg; 534 | msg.data = message; 535 | msg.maxsize = 131072; 536 | msg.cursize = strlen(msg.data)+1; 537 | msg.readcount = 0; 538 | msg.overflowed = false; 539 | msg.bit = 0; 540 | 541 | #if COD_VERSION == COD2_1_0 542 | int remoteaddress_offset = 452036; 543 | #else 544 | int remoteaddress_offset = 452308; 545 | #endif 546 | 547 | int info_player = PLAYERBASE(id); 548 | netadr_t * from = (netadr_t*)(info_player + remoteaddress_offset); 549 | SV_ConnectionlessPacket(*from, &msg); 550 | 551 | stackReturnInt(1); 552 | } 553 | 554 | void gsc_player_resetNextReliableTime(int id) { 555 | #if COD_VERSION == COD2_1_0 556 | int offset = 134412; 557 | #else 558 | int offset = 134684; 559 | #endif 560 | 561 | *(int *)(PLAYERBASE(id) + offset) = 0; 562 | stackPushInt(0); 563 | } 564 | 565 | void gsc_player_ismantling(int id) { 566 | int flags = PLAYERSTATE(id) + 0xc; 567 | 568 | if(*(int*)flags & 4) //oi m8 im mantling 569 | stackPushInt(1); 570 | else 571 | stackPushInt(0); 572 | } 573 | 574 | void gsc_player_isonladder(int id) { 575 | int flags = PLAYERSTATE(id) + 0xc; 576 | 577 | if(*(int*)flags & 32) 578 | stackPushInt(1); 579 | else 580 | stackPushInt(0); 581 | } 582 | 583 | typedef long double (*calc_player_speed_t)(int a1, int a2); 584 | #if COD_VERSION == COD2_1_0 585 | calc_player_speed_t calc_player_speed = (calc_player_speed_t)0x080DF534; 586 | #elif COD_VERSION == COD2_1_2 587 | calc_player_speed_t calc_player_speed = (calc_player_speed_t)0x080E1B14; 588 | #elif COD_VERSION == COD2_1_3 589 | calc_player_speed_t calc_player_speed = (calc_player_speed_t)0x080E1C58; 590 | #else 591 | #warning calc_player_speed_t calc_player_speed = NULL; 592 | calc_player_speed_t calc_player_speed = (calc_player_speed_t)NULL; 593 | #endif 594 | 595 | typedef void (*calc_client_speed_t)(int client); 596 | #if COD_VERSION == COD2_1_0 597 | calc_client_speed_t calc_client_speed = (calc_client_speed_t)0x0811FB7A; 598 | #elif COD_VERSION == COD2_1_2 599 | calc_client_speed_t calc_client_speed = (calc_client_speed_t)0x08121EAE; 600 | #elif COD_VERSION == COD2_1_3 601 | calc_client_speed_t calc_client_speed = (calc_client_speed_t)0x0812200A; 602 | #else 603 | #warning calc_client_speed_t calc_client_speed = NULL; 604 | calc_client_speed_t calc_client_speed = (calc_client_speed_t)NULL; 605 | #endif 606 | 607 | float player_movespeedscale[64] = {0}; 608 | int player_g_speed[64] = {0}; 609 | int player_g_gravity[64] = {0}; 610 | 611 | long double hook_player_setmovespeed(int client, int a2) { 612 | float speed = calc_player_speed(client, a2); 613 | int id = clientaddress_to_num(*(int*)client); 614 | 615 | if(speed > 0 && player_movespeedscale[id] > 0 && player_movespeedscale[id] != 1) 616 | return speed * player_movespeedscale[id]; 617 | else 618 | return speed; 619 | } 620 | 621 | void gsc_player_setmovespeedscale(int id) { 622 | float scale; 623 | if ( ! stackGetParams("f", &scale)) { 624 | printf("scriptengine> ERROR: gsc_player_setmovespeedscale(): param \"scale\"[1] has to be an float!\n"); 625 | stackPushUndefined(); 626 | return; 627 | } 628 | 629 | if (scale <= 0) { 630 | printf("scriptengine> ERROR: gsc_player_setmovespeedscale(): param \"scale\"[1] must be above zero!\n"); 631 | stackPushUndefined(); 632 | return; 633 | } 634 | 635 | player_movespeedscale[id] = scale; 636 | stackPushInt(1); 637 | } 638 | 639 | void gsc_player_setg_gravity(int id) { 640 | int gravity; 641 | if ( ! stackGetParams("i", &gravity)) { 642 | printf("scriptengine> ERROR: gsc_player_setg_gravity(): param \"gravity\"[1] has to be an int!\n"); 643 | stackPushUndefined(); 644 | return; 645 | } 646 | 647 | if (gravity < 0) { 648 | printf("scriptengine> ERROR: gsc_player_setg_gravity(): param \"gravity\"[1] must be equal or above zero!\n"); 649 | stackPushUndefined(); 650 | return; 651 | } 652 | 653 | player_g_gravity[id] = gravity; 654 | stackPushInt(1); 655 | } 656 | 657 | void gsc_player_setg_speed(int id) { 658 | int speed; 659 | if ( ! stackGetParams("i", &speed)) { 660 | printf("scriptengine> ERROR: gsc_player_setg_speed(): param \"speed\"[1] has to be an int!\n"); 661 | stackPushUndefined(); 662 | return; 663 | } 664 | 665 | if (speed < 0) { 666 | printf("scriptengine> ERROR: gsc_player_setg_speed(): param \"speed\"[1] must be equal or above zero!\n"); 667 | stackPushUndefined(); 668 | return; 669 | } 670 | 671 | player_g_speed[id] = speed; 672 | stackPushInt(1); 673 | } 674 | 675 | void hook_player_g_speed(int client) { 676 | int player = *(int *)(client + 344); 677 | int id = gentityaddress_to_num(client); 678 | 679 | int newgravity = player_g_gravity[id]; 680 | if(newgravity > 0) 681 | *(int *)(player + 72) = newgravity; 682 | 683 | int newspeed = player_g_speed[id]; 684 | if(newspeed > 0) 685 | *(int *)(player + 80) = newspeed; 686 | 687 | calc_client_speed(client); 688 | } 689 | 690 | void gsc_player_setweaponfiremeleedelay(int id) { 691 | int delay; 692 | if ( ! stackGetParams("i", &delay)) { 693 | printf("scriptengine> ERROR: gsc_player_setweaponfiremeleedelay(): param \"delay\"[1] has to be an int!\n"); 694 | stackPushUndefined(); 695 | return; 696 | } 697 | 698 | if(delay < 0) { 699 | printf("scriptengine> ERROR: gsc_player_setweaponfiremeleedelay(): param \"delay\"[1] must be equal or above zero!\n"); 700 | stackPushUndefined(); 701 | return; 702 | } 703 | 704 | int state = PLAYERSTATE(id); 705 | int* weapondelay = (int *)(state + 0x34); 706 | *weapondelay = delay; 707 | *(int *)(state + 216) = 11; 708 | } 709 | 710 | // entity functions (could be in own file, but atm not many pure entity functions) 711 | 712 | void gsc_entity_setalive(int id) { // as in isAlive? 713 | int isAlive; 714 | 715 | if ( ! stackGetParams("i", &isAlive)) { 716 | printf("scriptengine> ERROR: gsc_player_setalive(): param \"isAlive\"[1] has to be an integer!\n"); 717 | stackPushUndefined(); 718 | return; 719 | } 720 | 721 | *(char *)(gentities + gentities_size*id + 353) = isAlive; 722 | stackReturnInt(1); 723 | } 724 | 725 | void gsc_entity_setbounds(int id) { 726 | float width, height; 727 | 728 | if ( ! stackGetParams("ff", &width, &height)) { 729 | printf("scriptengine> ERROR: please specify width and height to gsc_entity_setbounds()\n"); 730 | stackPushUndefined(); 731 | return; 732 | } 733 | 734 | *(float*)(gentities + gentities_size*id + 280) = height; 735 | *(float*)(gentities + gentities_size*id + 276) = width; 736 | *(float*)(gentities + gentities_size*id + 272) = width; 737 | *(float*)(gentities + gentities_size*id + 264) = -width; 738 | *(float*)(gentities + gentities_size*id + 260) = -width; 739 | 740 | printf("id=%d height=%f width=%f\n", id, height, width); 741 | stackReturnInt(1); 742 | } 743 | 744 | void gsc_free_slot() { 745 | int id = 0; 746 | if(!stackGetParamInt(0, &id)) { 747 | printf("Param 0 needs to be an int for free_slot\n"); 748 | stackPushUndefined(); 749 | return; 750 | } 751 | int entity = PLAYERBASE(id); 752 | *(int*)entity = 0; //CS_FREE 753 | stackPushUndefined(); 754 | } 755 | 756 | void gsc_kick_slot() { 757 | int id; 758 | char* msg; 759 | char* reason; 760 | 761 | if ( ! stackGetParams("is", &id, &msg)) { 762 | printf("scriptengine> ERROR: gsc_kick_slot(): param \"id\"[1] has to be an int!\n"); 763 | printf("scriptengine> ERROR: gsc_kick_slot(): param \"msg\"[2] has to be an string!\n"); 764 | stackPushUndefined(); 765 | return; 766 | } 767 | 768 | if(getAddressType(id) == NA_LOOPBACK) { 769 | stackReturnInt(0); 770 | return; // host 771 | } 772 | 773 | #if COD_VERSION == COD2_1_0 774 | int guid_offset = 0x765F4; 775 | #elif COD_VERSION == COD2_1_2 776 | int guid_offset = 0x76704; 777 | #elif COD_VERSION == COD2_1_3 778 | int guid_offset = 0xAE704; 779 | #else 780 | #warning gsc_kick_slot() got no working addresses for guid_offset 781 | int guid_offset = 0x0; 782 | #endif 783 | 784 | int entity = PLAYERBASE(id); 785 | char* name = Info_ValueForKey((char*)entity+12, "name"); // read before drop client resets the userinfo 786 | int guid = *(int*)(entity + guid_offset); 787 | SV_DropClient(entity, msg); 788 | int * lastPacketTime = (int*)getLastPacketTime(id); 789 | *lastPacketTime = getSVSTime(); // in case there is a funny zombie (copied from Q3) 790 | 791 | if(!stackGetParamString(2, &reason)) { 792 | Com_Printf("%s (guid %i) was kicked\n", name, guid); 793 | stackReturnInt(1); 794 | return; 795 | } 796 | 797 | Com_Printf("%s (guid %i) was kicked for %s\n", name, guid, reason); 798 | stackReturnInt(1); 799 | } 800 | 801 | #endif 802 | -------------------------------------------------------------------------------- /gsc_player.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_PLAYER_HPP_ 2 | #define _GSC_PLAYER_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | int clientaddress_to_num(int address); 17 | 18 | void gsc_player_velocity_set(int id); 19 | void gsc_player_velocity_add(int id); 20 | void gsc_player_velocity_get(int id); 21 | 22 | void gsc_player_button_ads(int id); 23 | void gsc_player_button_left(int id); 24 | void gsc_player_button_right(int id); 25 | void gsc_player_button_forward(int id); 26 | void gsc_player_button_back(int id); 27 | void gsc_player_button_leanleft(int id); 28 | void gsc_player_button_leanright(int id); 29 | void gsc_player_button_jump(int id); 30 | 31 | int gsc_player_state_alive_set(); 32 | 33 | void gsc_player_stance_get(int id); 34 | 35 | void gsc_player_spectatorclient_get(int id); 36 | void gsc_get_userinfo(int id); 37 | void gsc_set_userinfo(int id); 38 | void gsc_player_getip(int id); 39 | void gsc_player_getping(int id); 40 | void gsc_player_clientuserinfochanged(int id); 41 | 42 | void gsc_player_ClientCommand(int id); 43 | 44 | void gsc_player_getLastConnectTime(int id); 45 | void gsc_player_getLastMSG(int id); 46 | void gsc_player_getclientstate(int id); 47 | 48 | void gsc_player_addresstype(int id); 49 | void gsc_player_renameclient(int id); 50 | void gsc_player_outofbandprint(int id); 51 | void gsc_player_connectionlesspacket(int id); 52 | void gsc_player_resetNextReliableTime(int id); 53 | void gsc_player_ismantling(int id); 54 | void gsc_player_isonladder(int id); 55 | long double hook_player_setmovespeed(int client, int a2); 56 | void hook_player_g_speed(int client); 57 | void gsc_player_setmovespeedscale(int id); 58 | void gsc_player_setg_speed(int id); 59 | void gsc_player_setg_gravity(int id); 60 | void gsc_player_setweaponfiremeleedelay(int id); 61 | 62 | // entity functions 63 | void gsc_entity_setalive(int id); 64 | void gsc_entity_setbounds(int id); 65 | 66 | // player functions without entity 67 | void gsc_free_slot(); 68 | void gsc_kick_slot(); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /gsc_tcc.cpp: -------------------------------------------------------------------------------- 1 | #include "gsc_tcc.hpp" 2 | 3 | #if COMPILE_TCC != 0 4 | 5 | int gsc_tcc_new() 6 | { 7 | TCCState *s; 8 | 9 | #if DEBUG_TCC 10 | printf("%s()\n", __FUNCTION__); 11 | #endif 12 | 13 | s = tcc_new(); 14 | s->nostdlib = 1; 15 | return stackReturnInt((int) s); 16 | } 17 | 18 | int gsc_tcc_add_include_path() 19 | { 20 | TCCState *s; 21 | char *pathname; 22 | 23 | int helper = 0; 24 | helper += stackGetParamInt(1, (int *)&s); 25 | helper += stackGetParamString(2, &pathname); 26 | 27 | #if DEBUG_TCC 28 | printf("%s(TCCState *s=%.8p, char *pathname=\"%s\")\n", __FUNCTION__, s, pathname); 29 | #endif 30 | 31 | if (helper != 2) 32 | { 33 | printf("scriptengine> wrongs args for %s(TCCState *s=%.8p, char *pathname=\"%s\")\n", __FUNCTION__, s, pathname); 34 | return stackPushUndefined(); 35 | } 36 | 37 | int ret = (int) tcc_add_include_path(s, pathname); 38 | return stackReturnInt(ret); 39 | } 40 | 41 | #include 42 | 43 | TCCState *global_s; 44 | char *global_filename; 45 | int global_ret; 46 | 47 | void *thread_for_tcc_add_file(void *arg) 48 | { 49 | //global_ret = tcc_add_file(global_s, global_filename); 50 | 51 | TCCState *s; 52 | 53 | s = tcc_new(); 54 | s->nostdlib = 1; 55 | tcc_add_include_path(s, "/usr/include"); 56 | tcc_add_include_path(s, "include"); 57 | //tcc_add_library(s, "c"); // libc 58 | tcc_add_file(s, "first.c"); 59 | //tcc_run(s, 0, (char **)NULL); 60 | //tcc_delete(s); 61 | printf("test"); 62 | } 63 | int tcc_add_file_thread(TCCState *s, char *filename) 64 | { 65 | global_s = s; 66 | global_filename = filename; 67 | pthread_t thread1; 68 | 69 | 70 | 71 | 72 | pthread_attr_t settings; 73 | 74 | int stacksize; 75 | 76 | int ret = pthread_attr_init(&settings); 77 | if (ret != 0) 78 | { 79 | printf("> [ERROR] pthread_attr_init() failed.\n"); 80 | return 0; 81 | } 82 | 83 | stacksize = 1024*1024*20; 84 | 85 | ret = pthread_attr_setstacksize(&settings, stacksize); 86 | if (ret != 0) 87 | { 88 | printf("> [ERROR] pthread_attr_setstacksize failed.\n"); 89 | return 0; 90 | } 91 | 92 | printf("> [INFO] Stack-Size set to %d Bytes (%.2f KB, %.2f MB)\n", stacksize, (float)(stacksize/1024), (float)((stacksize/1024)/1024)); 93 | 94 | 95 | 96 | 97 | 98 | 99 | pthread_create (&thread1, &settings, thread_for_tcc_add_file, NULL); 100 | //pthread_join(thread1, NULL); 101 | return global_ret; 102 | } 103 | 104 | int gsc_tcc_add_file() 105 | { 106 | TCCState *s; 107 | char *filename; 108 | 109 | int helper = 0; 110 | helper += stackGetParamInt(1, (int *)&s); 111 | helper += stackGetParamString(2, &filename); 112 | 113 | #if DEBUG_TCC 114 | printf("%s(TCCState *s=%.8p, char *filename=\"%s\")\n", __FUNCTION__, s, filename); 115 | #endif 116 | 117 | if (helper != 2) 118 | { 119 | printf("scriptengine> wrongs args for %s(TCCState *s=%.8p, char *filename=\"%s\")\n", __FUNCTION__, s, filename); 120 | return stackPushUndefined(); 121 | } 122 | 123 | int ret = (int) tcc_add_file_thread(s, filename); 124 | return stackReturnInt(ret); 125 | } 126 | 127 | int gsc_tcc_run() 128 | { 129 | TCCState *s; 130 | 131 | int helper = 0; 132 | helper += stackGetParamInt(1, (int *)&s); 133 | 134 | #if DEBUG_TCC 135 | printf("%s(TCCState *s=%.8p)\n", __FUNCTION__, s); 136 | #endif 137 | 138 | if (helper != 1) 139 | { 140 | printf("scriptengine> wrongs args for %s(TCCState *s=%.8p)\n", __FUNCTION__, s); 141 | return stackPushUndefined(); 142 | } 143 | 144 | int ret = (int) tcc_run(s, 0, (char **)NULL); 145 | return stackReturnInt(ret); 146 | } 147 | 148 | int gsc_tcc_delete() 149 | { 150 | TCCState *s; 151 | 152 | int helper = 0; 153 | helper += stackGetParamInt(1, (int *)&s); 154 | 155 | #if DEBUG_TCC 156 | printf("%s(TCCState *s=%.8p)\n", __FUNCTION__, s); 157 | #endif 158 | 159 | if (helper != 1) 160 | { 161 | printf("scriptengine> wrongs args for %s(TCCState *s=%.8p)\n", __FUNCTION__, s); 162 | return stackPushUndefined(); 163 | } 164 | 165 | tcc_delete(s); 166 | return stackPushUndefined(); 167 | } 168 | #endif -------------------------------------------------------------------------------- /gsc_tcc.hpp: -------------------------------------------------------------------------------- 1 | #if COMPILE_TCC == 0 2 | #define _GSC_TCC_HPP_ 3 | #endif 4 | 5 | 6 | #ifndef _GSC_TCC_HPP_ 7 | #define _GSC_TCC_HPP_ 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /* default stuff */ 14 | #include 15 | #include 16 | #include 17 | 18 | /* gsc functions */ 19 | #include "gsc.hpp" 20 | 21 | /* tcc functions */ 22 | #include "tcc/tcc.h" 23 | #include "tcc/libtcc.h" 24 | 25 | int gsc_tcc_new(); 26 | int gsc_tcc_add_include_path(); 27 | int gsc_tcc_add_file(); 28 | int gsc_tcc_run(); 29 | int gsc_tcc_delete(); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif -------------------------------------------------------------------------------- /gsc_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_UTILS_HPP_ 2 | #define _GSC_UTILS_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* gsc functions */ 14 | #include "gsc.hpp" 15 | 16 | /* link unlink */ 17 | #include 18 | 19 | void gsc_utils_disableGlobalPlayerCollision(); 20 | void gsc_utils_getAscii(); 21 | void gsc_utils_toupper(); 22 | void gsc_utils_system(); 23 | void gsc_utils_file_link(); 24 | void gsc_utils_file_unlink(); 25 | void gsc_utils_file_exists(); 26 | void gsc_utils_FS_LoadDir(); 27 | void gsc_utils_getType(); 28 | void gsc_utils_stringToFloat(); 29 | void gsc_utils_rundll(); 30 | void gsc_utils_ExecuteString(); 31 | void gsc_utils_sendgameservercommand(); 32 | void gsc_utils_scandir(); 33 | void gsc_G_FindConfigstringIndex(); 34 | void gsc_G_FindConfigstringIndexOriginal(); 35 | 36 | void gsc_add_language(); 37 | void gsc_load_languages(); 38 | void gsc_get_language_item(); 39 | void gsc_themetext(); 40 | 41 | void gsc_utils_fopen(); 42 | void gsc_utils_fread(); 43 | void gsc_utils_fwrite(); 44 | void gsc_utils_fclose(); 45 | void gsc_utils_sprintf(); 46 | 47 | void gsc_call_function_raw(); 48 | 49 | void gsc_dlopen(); 50 | void gsc_dlsym(); 51 | void gsc_dlclose(); 52 | 53 | void gsc_utils_init(); 54 | void gsc_utils_free(); 55 | int hook_findWeaponIndex(char* weapon); 56 | void gsc_utils_resetignoredweapons(); 57 | void gsc_utils_ignoreweapon(); 58 | void gsc_utils_setdefaultweapon(); 59 | void gsc_utils_getweaponmaxammo(); 60 | void gsc_utils_getweapondamage(); 61 | void gsc_utils_setweapondamage(); 62 | void gsc_utils_getweaponmeleedamage(); 63 | void gsc_utils_setweaponmeleedamage(); 64 | void gsc_utils_getweaponfiretime(); 65 | void gsc_utils_setweaponfiretime(); 66 | void gsc_utils_getweaponmeleetime(); 67 | void gsc_utils_setweaponmeleetime(); 68 | void gsc_utils_getweaponreloadtime(); 69 | void gsc_utils_setweaponreloadtime(); 70 | void gsc_utils_getweaponreloademptytime(); 71 | void gsc_utils_setweaponreloademptytime(); 72 | void gsc_utils_getweaponhitlocmultiplier(); 73 | void gsc_utils_setweaponhitlocmultiplier(); 74 | void gsc_utils_getloadedweapons(); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /java_embed.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | cd ~/openjdk8/jdk1.8.0_20/bin/embed2 5 | 6 | gcc -c java.c -o java.o -m32 -I/root/openjdk8/jdk1.8.0_20/include/ -I/root/openjdk8/jdk1.8.0_20/include/linux/ 7 | gcc java.cpp -m32 -I/root/openjdk8/jdk1.8.0_20/include/ -I/root/openjdk8/jdk1.8.0_20/include/linux/ -ljvm -L/root/openjdk8/jdk1.8.0_20/jre/lib/i386/server/ 8 | LD_PRELOAD=/root/openjdk8/jdk1.8.0_20/jre/lib/i386/server/libjvm.so ./a.out 9 | LD_LIBRARY_PATH=/root/openjdk8/jdk1.8.0_20/jre/lib/i386/server/ ./a.out 10 | 11 | ../javac Libcod.java 12 | */ 13 | 14 | JNIEXPORT void JNICALL JNI_OnLoad_Libcod(JNIEnv *env, jobject thisObj) { 15 | printf("JNI_OnLoad_Libcod\n"); 16 | printf("JNI_OnLoad_Libcod\n"); 17 | printf("JNI_OnLoad_Libcod\n"); 18 | printf("JNI_OnLoad_Libcod\n"); 19 | } 20 | 21 | JNIEXPORT void JNICALL Java_Libcod_sayHello(JNIEnv *env, jobject thisObj) { 22 | printf("NATIVE FUNCTION CALLELD\n"); 23 | } 24 | 25 | int embed_java() { 26 | JavaVM *jvm = NULL; 27 | JNIEnv *env = NULL; 28 | JavaVMInitArgs vmArgs; 29 | JavaVMOption options[2]; int n = 0; 30 | //options[n++].optionString = "jdk.nashorn.tools.Shell"; 31 | options[n++].optionString = "-Djava.class.path=."; 32 | options[n++].optionString = "-Djava.library.path=."; 33 | 34 | vmArgs.version = JNI_VERSION_1_8; 35 | vmArgs.nOptions = n; 36 | vmArgs.options = options; 37 | vmArgs.ignoreUnrecognized = 0; 38 | 39 | //printf("dlsym(\"JNI_CreateJavaVM\") = %.8p\n", dlsym(NULL, "JNI_CreateJavaVM")); 40 | 41 | JNI_CreateJavaVM(&jvm, (void**)&env, &vmArgs); 42 | printf("[JAVA] jvm=%.8p env=%.8p\n", jvm, env); 43 | 44 | 45 | jclass class_shell; 46 | jmethodID method_main; 47 | 48 | char *init_class; 49 | init_class = "jdk/nashorn/tools/Shell"; // would load the jjs-REPL-Shell 50 | init_class = "Init"; 51 | class_shell = (*env)->FindClass(env, init_class); 52 | if ( ! class_shell) { 53 | printf("[JAVA] Could not find class: %s\n", init_class); 54 | return 0; 55 | } 56 | printf("[JAVA] class_shell: %p\n", class_shell); 57 | 58 | 59 | static JNINativeMethod methods[] = { 60 | {"sayHello", "()V", (void *)&Java_Libcod_sayHello}, 61 | //{"wait", "(J)V", (void *)&JVM_MonitorWait}, 62 | //{"notify", "()V", (void *)&JVM_MonitorNotify}, 63 | //{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll}, 64 | //{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone}, 65 | }; 66 | 67 | (*env)->RegisterNatives(env, class_shell, methods, sizeof(methods)/sizeof(methods[0])); 68 | 69 | method_main = (*env)->GetStaticMethodID(env, class_shell, "main", "([Ljava/lang/String;)V"); 70 | if ( ! method_main) { 71 | printf("[JAVA] Could not find static method: main(String[])\n"); 72 | return 0; 73 | } 74 | printf("[JAVA] method_main: %.8p\n", method_main); 75 | 76 | jobjectArray applicationArgs; 77 | jstring applicationArg0; 78 | applicationArgs = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), NULL); 79 | applicationArg0 = (*env)->NewStringUTF(env, "From-C-program"); 80 | (*env)->SetObjectArrayElement(env, applicationArgs, 0, applicationArg0); 81 | (*env)->CallStaticVoidMethod(env, class_shell, method_main); 82 | 83 | 84 | //jvm->DestroyJavaVM(); 85 | 86 | return 0; 87 | } -------------------------------------------------------------------------------- /java_embed.h: -------------------------------------------------------------------------------- 1 | #ifndef _JAVA_EMBED_H_ 2 | #define _JAVA_EMBED_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int embed_java(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /plugins/bsp/bsp.c: -------------------------------------------------------------------------------- 1 | #include // time back when it crashed without dl_close(), i read it doesnt crash with a "_" in the function name // oh yeah, it needs a _ in name, otherwise it crashes! #include "quake3/code/qcommon/cm_local.h" typedef struct { char a,bb; //int a; int b; int c; int d; int e; int f; int g; int h; int i; int j; int k; char cc,dd; } cLeaf_tt; void printLeaf(cLeaf_tt *leaf) { /* printf("cLeaf_tt 0x%.X\n", leaf); printf("int cluster = %d\n", leaf->cluster); printf("int area = %d\n", leaf->area); printf("\n"); printf("int firstLeafBrush = %d\n", leaf->firstLeafBrush); printf("int numLeafBrushes = %d\n", leaf->numLeafBrushes); printf("\n"); printf("int firstLeafSurface = %d\n", leaf->firstLeafSurface); printf("int numLeafSurfaces = %d\n", leaf->numLeafSurfaces); */ /* printf("cLeaf_tt=0x%.X", leaf); printf(" cluster=%d", leaf->cluster); printf(" area=%d", leaf->area); printf(" firstLeafBrush=%d", leaf->firstLeafBrush); printf(" numLeafBrushes=%d", leaf->numLeafBrushes); printf(" firstLeafSurface=%d", leaf->firstLeafSurface); printf(" numLeafSurfaces=%d", leaf->numLeafSurfaces); printf("\n"); */ int i; printf("%d ", leaf->a); printf("%d ", leaf->b); printf("%d ", leaf->c); printf("%d ", leaf->d); printf("%d ", leaf->e); printf("%d ", leaf->f); printf("%d ", leaf->g); printf("%d ", leaf->h); printf("%d ", leaf->i); printf("%d ", leaf->j); printf("%d ", leaf->k); printf("\n"); } printPlane(cplane_t *plane) { //printf("distance: %.2f\n", plane->dist); printf("distance: %.2f ", ((float *)plane)[0]); printf("distance: %.2f ", ((float *)plane)[1]); printf("distance: %.2f : ", ((float *)plane)[2]); printf("distance: %.2f\n", ((float *)plane)[3]); } typedef struct { cplane_t *plane; int16_t children[2]; } aNode; // closer 500,bsp.so,print_cm int print_cm() { clipMap_t *cm = (clipMap_t *)0x08188E44; cLeaf_tt *leafs = (cLeaf_tt *)0x08188DE8; int *numLeafs = (int *)0x08188DE4; printf("name: %s\n", cm->name); int i; /* printf("numLeafs: %d size: %d\n", *numLeafs, sizeof(cLeaf_tt)); for (i=0; i<*numLeafs && i<20; i++) printLeaf(leafs + i); */ /* cplane_t *planes = (cplane_t *) 0x08188EDC; for (i=0; i<200; i++) printPlane(planes+i); */ aNode *nodes = (aNode *) 0x08188DE0; int *numNodes = (int *) 0x08188DDC; for (i=0; i<*numNodes; i++) { printf("%3i plane=0x%.8x children[0]=%6i children[1]=%6i\n", i, nodes[i].plane, nodes[i].children[0], nodes[i].children[1] ); } } -------------------------------------------------------------------------------- /plugins/bsp/bsp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kungfooman/libcod/f89b31fdbc5575a0579fe1c3dc908ae4ef702581/plugins/bsp/bsp.so -------------------------------------------------------------------------------- /plugins/bsp/doit.sh: -------------------------------------------------------------------------------- 1 | cd $(dirname $0) # join dir of this script 2 | 3 | gcc -m32 -fPIC -c bsp.c -o bsp.o 4 | gcc -m32 -shared -o bsp.so bsp.o 5 | cp bsp.so ../../.. -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/game/surfaceflags.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | // 23 | // This file must be identical in the quake and utils directories 24 | 25 | // contents flags are seperate bits 26 | // a given brush can contribute multiple content bits 27 | 28 | // these definitions also need to be in q_shared.h! 29 | 30 | #define CONTENTS_SOLID 1 // an eye is never valid in a solid 31 | #define CONTENTS_LAVA 8 32 | #define CONTENTS_SLIME 16 33 | #define CONTENTS_WATER 32 34 | #define CONTENTS_FOG 64 35 | 36 | #define CONTENTS_NOTTEAM1 0x0080 37 | #define CONTENTS_NOTTEAM2 0x0100 38 | #define CONTENTS_NOBOTCLIP 0x0200 39 | 40 | #define CONTENTS_AREAPORTAL 0x8000 41 | 42 | #define CONTENTS_PLAYERCLIP 0x10000 43 | #define CONTENTS_MONSTERCLIP 0x20000 44 | //bot specific contents types 45 | #define CONTENTS_TELEPORTER 0x40000 46 | #define CONTENTS_JUMPPAD 0x80000 47 | #define CONTENTS_CLUSTERPORTAL 0x100000 48 | #define CONTENTS_DONOTENTER 0x200000 49 | #define CONTENTS_BOTCLIP 0x400000 50 | #define CONTENTS_MOVER 0x800000 51 | 52 | #define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity 53 | 54 | #define CONTENTS_BODY 0x2000000 // should never be on a brush, only in game 55 | #define CONTENTS_CORPSE 0x4000000 56 | #define CONTENTS_DETAIL 0x8000000 // brushes not used for the bsp 57 | #define CONTENTS_STRUCTURAL 0x10000000 // brushes used for the bsp 58 | #define CONTENTS_TRANSLUCENT 0x20000000 // don't consume surface fragments inside 59 | #define CONTENTS_TRIGGER 0x40000000 60 | #define CONTENTS_NODROP 0x80000000 // don't leave bodies or items (death fog, lava) 61 | 62 | #define SURF_NODAMAGE 0x1 // never give falling damage 63 | #define SURF_SLICK 0x2 // effects game physics 64 | #define SURF_SKY 0x4 // lighting from environment map 65 | #define SURF_LADDER 0x8 66 | #define SURF_NOIMPACT 0x10 // don't make missile explosions 67 | #define SURF_NOMARKS 0x20 // don't leave missile marks 68 | #define SURF_FLESH 0x40 // make flesh sounds and effects 69 | #define SURF_NODRAW 0x80 // don't generate a drawsurface at all 70 | #define SURF_HINT 0x100 // make a primary bsp splitter 71 | #define SURF_SKIP 0x200 // completely ignore, allowing non-closed brushes 72 | #define SURF_NOLIGHTMAP 0x400 // surface doesn't need a lightmap 73 | #define SURF_POINTLIGHT 0x800 // generate lighting info at vertexes 74 | #define SURF_METALSTEPS 0x1000 // clanking footsteps 75 | #define SURF_NOSTEPS 0x2000 // no footstep sounds 76 | #define SURF_NONSOLID 0x4000 // don't collide against curves with this set 77 | #define SURF_LIGHTFILTER 0x8000 // act as a light filter during q3map -light 78 | #define SURF_ALPHASHADOW 0x10000 // do per-pixel light shadow casting in q3map 79 | #define SURF_NODLIGHT 0x20000 // don't dlight even if solid (solid lava, skies) 80 | #define SURF_DUST 0x40000 // leave a dust trail when walking on this surface 81 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_load.c: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | // cmodel.c -- model loading 23 | 24 | #include "cm_local.h" 25 | 26 | #ifdef BSPC 27 | 28 | #include "../bspc/l_qfiles.h" 29 | 30 | void SetPlaneSignbits (cplane_t *out) { 31 | int bits, j; 32 | 33 | // for fast box on planeside test 34 | bits = 0; 35 | for (j=0 ; j<3 ; j++) { 36 | if (out->normal[j] < 0) { 37 | bits |= 1<signbits = bits; 41 | } 42 | #endif //BSPC 43 | 44 | // to allow boxes to be treated as brush models, we allocate 45 | // some extra indexes along with those needed by the map 46 | #define BOX_BRUSHES 1 47 | #define BOX_SIDES 6 48 | #define BOX_LEAFS 2 49 | #define BOX_PLANES 12 50 | 51 | #define LL(x) x=LittleLong(x) 52 | 53 | 54 | clipMap_t cm; 55 | int c_pointcontents; 56 | int c_traces, c_brush_traces, c_patch_traces; 57 | 58 | 59 | byte *cmod_base; 60 | 61 | #ifndef BSPC 62 | cvar_t *cm_noAreas; 63 | cvar_t *cm_noCurves; 64 | cvar_t *cm_playerCurveClip; 65 | #endif 66 | 67 | cmodel_t box_model; 68 | cplane_t *box_planes; 69 | cbrush_t *box_brush; 70 | 71 | 72 | 73 | void CM_InitBoxHull (void); 74 | void CM_FloodAreaConnections (void); 75 | 76 | 77 | /* 78 | =============================================================================== 79 | 80 | MAP LOADING 81 | 82 | =============================================================================== 83 | */ 84 | 85 | /* 86 | ================= 87 | CMod_LoadShaders 88 | ================= 89 | */ 90 | void CMod_LoadShaders( lump_t *l ) { 91 | dshader_t *in, *out; 92 | int i, count; 93 | 94 | in = (void *)(cmod_base + l->fileofs); 95 | if (l->filelen % sizeof(*in)) { 96 | Com_Error (ERR_DROP, "CMod_LoadShaders: funny lump size"); 97 | } 98 | count = l->filelen / sizeof(*in); 99 | 100 | if (count < 1) { 101 | Com_Error (ERR_DROP, "Map with no shaders"); 102 | } 103 | cm.shaders = Hunk_Alloc( count * sizeof( *cm.shaders ), h_high ); 104 | cm.numShaders = count; 105 | 106 | Com_Memcpy( cm.shaders, in, count * sizeof( *cm.shaders ) ); 107 | 108 | out = cm.shaders; 109 | for ( i=0 ; icontentFlags = LittleLong( out->contentFlags ); 111 | out->surfaceFlags = LittleLong( out->surfaceFlags ); 112 | } 113 | } 114 | 115 | 116 | /* 117 | ================= 118 | CMod_LoadSubmodels 119 | ================= 120 | */ 121 | void CMod_LoadSubmodels( lump_t *l ) { 122 | dmodel_t *in; 123 | cmodel_t *out; 124 | int i, j, count; 125 | int *indexes; 126 | 127 | in = (void *)(cmod_base + l->fileofs); 128 | if (l->filelen % sizeof(*in)) 129 | Com_Error (ERR_DROP, "CMod_LoadSubmodels: funny lump size"); 130 | count = l->filelen / sizeof(*in); 131 | 132 | if (count < 1) 133 | Com_Error (ERR_DROP, "Map with no models"); 134 | cm.cmodels = Hunk_Alloc( count * sizeof( *cm.cmodels ), h_high ); 135 | cm.numSubModels = count; 136 | 137 | if ( count > MAX_SUBMODELS ) { 138 | Com_Error( ERR_DROP, "MAX_SUBMODELS exceeded" ); 139 | } 140 | 141 | for ( i=0 ; imins[j] = LittleFloat (in->mins[j]) - 1; 148 | out->maxs[j] = LittleFloat (in->maxs[j]) + 1; 149 | } 150 | 151 | if ( i == 0 ) { 152 | continue; // world model doesn't need other info 153 | } 154 | 155 | // make a "leaf" just to hold the model's brushes and surfaces 156 | out->leaf.numLeafBrushes = LittleLong( in->numBrushes ); 157 | indexes = Hunk_Alloc( out->leaf.numLeafBrushes * 4, h_high ); 158 | out->leaf.firstLeafBrush = indexes - cm.leafbrushes; 159 | for ( j = 0 ; j < out->leaf.numLeafBrushes ; j++ ) { 160 | indexes[j] = LittleLong( in->firstBrush ) + j; 161 | } 162 | 163 | out->leaf.numLeafSurfaces = LittleLong( in->numSurfaces ); 164 | indexes = Hunk_Alloc( out->leaf.numLeafSurfaces * 4, h_high ); 165 | out->leaf.firstLeafSurface = indexes - cm.leafsurfaces; 166 | for ( j = 0 ; j < out->leaf.numLeafSurfaces ; j++ ) { 167 | indexes[j] = LittleLong( in->firstSurface ) + j; 168 | } 169 | } 170 | } 171 | 172 | 173 | /* 174 | ================= 175 | CMod_LoadNodes 176 | 177 | ================= 178 | */ 179 | void CMod_LoadNodes( lump_t *l ) { 180 | dnode_t *in; 181 | int child; 182 | cNode_t *out; 183 | int i, j, count; 184 | 185 | in = (void *)(cmod_base + l->fileofs); 186 | if (l->filelen % sizeof(*in)) 187 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 188 | count = l->filelen / sizeof(*in); 189 | 190 | if (count < 1) 191 | Com_Error (ERR_DROP, "Map has no nodes"); 192 | cm.nodes = Hunk_Alloc( count * sizeof( *cm.nodes ), h_high ); 193 | cm.numNodes = count; 194 | 195 | out = cm.nodes; 196 | 197 | for (i=0 ; iplane = cm.planes + LittleLong( in->planeNum ); 200 | for (j=0 ; j<2 ; j++) 201 | { 202 | child = LittleLong (in->children[j]); 203 | out->children[j] = child; 204 | } 205 | } 206 | 207 | } 208 | 209 | /* 210 | ================= 211 | CM_BoundBrush 212 | 213 | ================= 214 | */ 215 | void CM_BoundBrush( cbrush_t *b ) { 216 | b->bounds[0][0] = -b->sides[0].plane->dist; 217 | b->bounds[1][0] = b->sides[1].plane->dist; 218 | 219 | b->bounds[0][1] = -b->sides[2].plane->dist; 220 | b->bounds[1][1] = b->sides[3].plane->dist; 221 | 222 | b->bounds[0][2] = -b->sides[4].plane->dist; 223 | b->bounds[1][2] = b->sides[5].plane->dist; 224 | } 225 | 226 | 227 | /* 228 | ================= 229 | CMod_LoadBrushes 230 | 231 | ================= 232 | */ 233 | void CMod_LoadBrushes( lump_t *l ) { 234 | dbrush_t *in; 235 | cbrush_t *out; 236 | int i, count; 237 | 238 | in = (void *)(cmod_base + l->fileofs); 239 | if (l->filelen % sizeof(*in)) { 240 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 241 | } 242 | count = l->filelen / sizeof(*in); 243 | 244 | cm.brushes = Hunk_Alloc( ( BOX_BRUSHES + count ) * sizeof( *cm.brushes ), h_high ); 245 | cm.numBrushes = count; 246 | 247 | out = cm.brushes; 248 | 249 | for ( i=0 ; isides = cm.brushsides + LittleLong(in->firstSide); 251 | out->numsides = LittleLong(in->numSides); 252 | 253 | out->shaderNum = LittleLong( in->shaderNum ); 254 | if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) { 255 | Com_Error( ERR_DROP, "CMod_LoadBrushes: bad shaderNum: %i", out->shaderNum ); 256 | } 257 | out->contents = cm.shaders[out->shaderNum].contentFlags; 258 | 259 | CM_BoundBrush( out ); 260 | } 261 | 262 | } 263 | 264 | /* 265 | ================= 266 | CMod_LoadLeafs 267 | ================= 268 | */ 269 | void CMod_LoadLeafs (lump_t *l) 270 | { 271 | int i; 272 | cLeaf_t *out; 273 | dleaf_t *in; 274 | int count; 275 | 276 | in = (void *)(cmod_base + l->fileofs); 277 | if (l->filelen % sizeof(*in)) 278 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 279 | count = l->filelen / sizeof(*in); 280 | 281 | if (count < 1) 282 | Com_Error (ERR_DROP, "Map with no leafs"); 283 | 284 | cm.leafs = Hunk_Alloc( ( BOX_LEAFS + count ) * sizeof( *cm.leafs ), h_high ); 285 | cm.numLeafs = count; 286 | 287 | out = cm.leafs; 288 | for ( i=0 ; icluster = LittleLong (in->cluster); 291 | out->area = LittleLong (in->area); 292 | out->firstLeafBrush = LittleLong (in->firstLeafBrush); 293 | out->numLeafBrushes = LittleLong (in->numLeafBrushes); 294 | out->firstLeafSurface = LittleLong (in->firstLeafSurface); 295 | out->numLeafSurfaces = LittleLong (in->numLeafSurfaces); 296 | 297 | if (out->cluster >= cm.numClusters) 298 | cm.numClusters = out->cluster + 1; 299 | if (out->area >= cm.numAreas) 300 | cm.numAreas = out->area + 1; 301 | } 302 | 303 | cm.areas = Hunk_Alloc( cm.numAreas * sizeof( *cm.areas ), h_high ); 304 | cm.areaPortals = Hunk_Alloc( cm.numAreas * cm.numAreas * sizeof( *cm.areaPortals ), h_high ); 305 | } 306 | 307 | /* 308 | ================= 309 | CMod_LoadPlanes 310 | ================= 311 | */ 312 | void CMod_LoadPlanes (lump_t *l) 313 | { 314 | int i, j; 315 | cplane_t *out; 316 | dplane_t *in; 317 | int count; 318 | int bits; 319 | 320 | in = (void *)(cmod_base + l->fileofs); 321 | if (l->filelen % sizeof(*in)) 322 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 323 | count = l->filelen / sizeof(*in); 324 | 325 | if (count < 1) 326 | Com_Error (ERR_DROP, "Map with no planes"); 327 | cm.planes = Hunk_Alloc( ( BOX_PLANES + count ) * sizeof( *cm.planes ), h_high ); 328 | cm.numPlanes = count; 329 | 330 | out = cm.planes; 331 | 332 | for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); 338 | if (out->normal[j] < 0) 339 | bits |= 1<dist = LittleFloat (in->dist); 343 | out->type = PlaneTypeForNormal( out->normal ); 344 | out->signbits = bits; 345 | } 346 | } 347 | 348 | /* 349 | ================= 350 | CMod_LoadLeafBrushes 351 | ================= 352 | */ 353 | void CMod_LoadLeafBrushes (lump_t *l) 354 | { 355 | int i; 356 | int *out; 357 | int *in; 358 | int count; 359 | 360 | in = (void *)(cmod_base + l->fileofs); 361 | if (l->filelen % sizeof(*in)) 362 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 363 | count = l->filelen / sizeof(*in); 364 | 365 | cm.leafbrushes = Hunk_Alloc( (count + BOX_BRUSHES) * sizeof( *cm.leafbrushes ), h_high ); 366 | cm.numLeafBrushes = count; 367 | 368 | out = cm.leafbrushes; 369 | 370 | for ( i=0 ; ifileofs); 388 | if (l->filelen % sizeof(*in)) 389 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 390 | count = l->filelen / sizeof(*in); 391 | 392 | cm.leafsurfaces = Hunk_Alloc( count * sizeof( *cm.leafsurfaces ), h_high ); 393 | cm.numLeafSurfaces = count; 394 | 395 | out = cm.leafsurfaces; 396 | 397 | for ( i=0 ; ifileofs); 416 | if ( l->filelen % sizeof(*in) ) { 417 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 418 | } 419 | count = l->filelen / sizeof(*in); 420 | 421 | cm.brushsides = Hunk_Alloc( ( BOX_SIDES + count ) * sizeof( *cm.brushsides ), h_high ); 422 | cm.numBrushSides = count; 423 | 424 | out = cm.brushsides; 425 | 426 | for ( i=0 ; iplaneNum ); 428 | out->plane = &cm.planes[num]; 429 | out->shaderNum = LittleLong( in->shaderNum ); 430 | if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) { 431 | Com_Error( ERR_DROP, "CMod_LoadBrushSides: bad shaderNum: %i", out->shaderNum ); 432 | } 433 | out->surfaceFlags = cm.shaders[out->shaderNum].surfaceFlags; 434 | } 435 | } 436 | 437 | 438 | /* 439 | ================= 440 | CMod_LoadEntityString 441 | ================= 442 | */ 443 | void CMod_LoadEntityString( lump_t *l ) { 444 | cm.entityString = Hunk_Alloc( l->filelen, h_high ); 445 | cm.numEntityChars = l->filelen; 446 | Com_Memcpy (cm.entityString, cmod_base + l->fileofs, l->filelen); 447 | } 448 | 449 | /* 450 | ================= 451 | CMod_LoadVisibility 452 | ================= 453 | */ 454 | #define VIS_HEADER 8 455 | void CMod_LoadVisibility( lump_t *l ) { 456 | int len; 457 | byte *buf; 458 | 459 | len = l->filelen; 460 | if ( !len ) { 461 | cm.clusterBytes = ( cm.numClusters + 31 ) & ~31; 462 | cm.visibility = Hunk_Alloc( cm.clusterBytes, h_high ); 463 | Com_Memset( cm.visibility, 255, cm.clusterBytes ); 464 | return; 465 | } 466 | buf = cmod_base + l->fileofs; 467 | 468 | cm.vised = qtrue; 469 | cm.visibility = Hunk_Alloc( len, h_high ); 470 | cm.numClusters = LittleLong( ((int *)buf)[0] ); 471 | cm.clusterBytes = LittleLong( ((int *)buf)[1] ); 472 | Com_Memcpy (cm.visibility, buf + VIS_HEADER, len - VIS_HEADER ); 473 | } 474 | 475 | //================================================================== 476 | 477 | 478 | /* 479 | ================= 480 | CMod_LoadPatches 481 | ================= 482 | */ 483 | #define MAX_PATCH_VERTS 1024 484 | void CMod_LoadPatches( lump_t *surfs, lump_t *verts ) { 485 | drawVert_t *dv, *dv_p; 486 | dsurface_t *in; 487 | int count; 488 | int i, j; 489 | int c; 490 | cPatch_t *patch; 491 | vec3_t points[MAX_PATCH_VERTS]; 492 | int width, height; 493 | int shaderNum; 494 | 495 | in = (void *)(cmod_base + surfs->fileofs); 496 | if (surfs->filelen % sizeof(*in)) 497 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 498 | cm.numSurfaces = count = surfs->filelen / sizeof(*in); 499 | cm.surfaces = Hunk_Alloc( cm.numSurfaces * sizeof( cm.surfaces[0] ), h_high ); 500 | 501 | dv = (void *)(cmod_base + verts->fileofs); 502 | if (verts->filelen % sizeof(*dv)) 503 | Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size"); 504 | 505 | // scan through all the surfaces, but only load patches, 506 | // not planar faces 507 | for ( i = 0 ; i < count ; i++, in++ ) { 508 | if ( LittleLong( in->surfaceType ) != MST_PATCH ) { 509 | continue; // ignore other surfaces 510 | } 511 | // FIXME: check for non-colliding patches 512 | 513 | cm.surfaces[ i ] = patch = Hunk_Alloc( sizeof( *patch ), h_high ); 514 | 515 | // load the full drawverts onto the stack 516 | width = LittleLong( in->patchWidth ); 517 | height = LittleLong( in->patchHeight ); 518 | c = width * height; 519 | if ( c > MAX_PATCH_VERTS ) { 520 | Com_Error( ERR_DROP, "ParseMesh: MAX_PATCH_VERTS" ); 521 | } 522 | 523 | dv_p = dv + LittleLong( in->firstVert ); 524 | for ( j = 0 ; j < c ; j++, dv_p++ ) { 525 | points[j][0] = LittleFloat( dv_p->xyz[0] ); 526 | points[j][1] = LittleFloat( dv_p->xyz[1] ); 527 | points[j][2] = LittleFloat( dv_p->xyz[2] ); 528 | } 529 | 530 | shaderNum = LittleLong( in->shaderNum ); 531 | patch->contents = cm.shaders[shaderNum].contentFlags; 532 | patch->surfaceFlags = cm.shaders[shaderNum].surfaceFlags; 533 | 534 | // create the internal facet structure 535 | patch->pc = CM_GeneratePatchCollide( width, height, points ); 536 | } 537 | } 538 | 539 | //================================================================== 540 | 541 | unsigned CM_LumpChecksum(lump_t *lump) { 542 | return LittleLong (Com_BlockChecksum (cmod_base + lump->fileofs, lump->filelen)); 543 | } 544 | 545 | unsigned CM_Checksum(dheader_t *header) { 546 | unsigned checksums[16]; 547 | checksums[0] = CM_LumpChecksum(&header->lumps[LUMP_SHADERS]); 548 | checksums[1] = CM_LumpChecksum(&header->lumps[LUMP_LEAFS]); 549 | checksums[2] = CM_LumpChecksum(&header->lumps[LUMP_LEAFBRUSHES]); 550 | checksums[3] = CM_LumpChecksum(&header->lumps[LUMP_LEAFSURFACES]); 551 | checksums[4] = CM_LumpChecksum(&header->lumps[LUMP_PLANES]); 552 | checksums[5] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHSIDES]); 553 | checksums[6] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHES]); 554 | checksums[7] = CM_LumpChecksum(&header->lumps[LUMP_MODELS]); 555 | checksums[8] = CM_LumpChecksum(&header->lumps[LUMP_NODES]); 556 | checksums[9] = CM_LumpChecksum(&header->lumps[LUMP_SURFACES]); 557 | checksums[10] = CM_LumpChecksum(&header->lumps[LUMP_DRAWVERTS]); 558 | 559 | return LittleLong(Com_BlockChecksum(checksums, 11 * 4)); 560 | } 561 | 562 | /* 563 | ================== 564 | CM_LoadMap 565 | 566 | Loads in the map and all submodels 567 | ================== 568 | */ 569 | void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) { 570 | int *buf; 571 | int i; 572 | dheader_t header; 573 | int length; 574 | static unsigned last_checksum; 575 | 576 | if ( !name || !name[0] ) { 577 | Com_Error( ERR_DROP, "CM_LoadMap: NULL name" ); 578 | } 579 | 580 | #ifndef BSPC 581 | cm_noAreas = Cvar_Get ("cm_noAreas", "0", CVAR_CHEAT); 582 | cm_noCurves = Cvar_Get ("cm_noCurves", "0", CVAR_CHEAT); 583 | cm_playerCurveClip = Cvar_Get ("cm_playerCurveClip", "1", CVAR_ARCHIVE|CVAR_CHEAT ); 584 | #endif 585 | Com_DPrintf( "CM_LoadMap( %s, %i )\n", name, clientload ); 586 | 587 | if ( !strcmp( cm.name, name ) && clientload ) { 588 | *checksum = last_checksum; 589 | return; 590 | } 591 | 592 | // free old stuff 593 | Com_Memset( &cm, 0, sizeof( cm ) ); 594 | CM_ClearLevelPatches(); 595 | 596 | if ( !name[0] ) { 597 | cm.numLeafs = 1; 598 | cm.numClusters = 1; 599 | cm.numAreas = 1; 600 | cm.cmodels = Hunk_Alloc( sizeof( *cm.cmodels ), h_high ); 601 | *checksum = 0; 602 | return; 603 | } 604 | 605 | // 606 | // load the file 607 | // 608 | #ifndef BSPC 609 | length = FS_ReadFile( name, (void **)&buf ); 610 | #else 611 | length = LoadQuakeFile((quakefile_t *) name, (void **)&buf); 612 | #endif 613 | 614 | if ( !buf ) { 615 | Com_Error (ERR_DROP, "Couldn't load %s", name); 616 | } 617 | 618 | last_checksum = LittleLong (Com_BlockChecksum (buf, length)); 619 | *checksum = last_checksum; 620 | 621 | header = *(dheader_t *)buf; 622 | for (i=0 ; i= cm.numSubModels ) { 702 | Com_Error (ERR_DROP, "CM_InlineModel: bad number"); 703 | } 704 | return index; 705 | } 706 | 707 | int CM_NumClusters( void ) { 708 | return cm.numClusters; 709 | } 710 | 711 | int CM_NumInlineModels( void ) { 712 | return cm.numSubModels; 713 | } 714 | 715 | char *CM_EntityString( void ) { 716 | return cm.entityString; 717 | } 718 | 719 | int CM_LeafCluster( int leafnum ) { 720 | if (leafnum < 0 || leafnum >= cm.numLeafs) { 721 | Com_Error (ERR_DROP, "CM_LeafCluster: bad number"); 722 | } 723 | return cm.leafs[leafnum].cluster; 724 | } 725 | 726 | int CM_LeafArea( int leafnum ) { 727 | if ( leafnum < 0 || leafnum >= cm.numLeafs ) { 728 | Com_Error (ERR_DROP, "CM_LeafArea: bad number"); 729 | } 730 | return cm.leafs[leafnum].area; 731 | } 732 | 733 | //======================================================================= 734 | 735 | 736 | /* 737 | =================== 738 | CM_InitBoxHull 739 | 740 | Set up the planes and nodes so that the six floats of a bounding box 741 | can just be stored out and get a proper clipping hull structure. 742 | =================== 743 | */ 744 | void CM_InitBoxHull (void) 745 | { 746 | int i; 747 | int side; 748 | cplane_t *p; 749 | cbrushside_t *s; 750 | 751 | box_planes = &cm.planes[cm.numPlanes]; 752 | 753 | box_brush = &cm.brushes[cm.numBrushes]; 754 | box_brush->numsides = 6; 755 | box_brush->sides = cm.brushsides + cm.numBrushSides; 756 | box_brush->contents = CONTENTS_BODY; 757 | 758 | box_model.leaf.numLeafBrushes = 1; 759 | // box_model.leaf.firstLeafBrush = cm.numBrushes; 760 | box_model.leaf.firstLeafBrush = cm.numLeafBrushes; 761 | cm.leafbrushes[cm.numLeafBrushes] = cm.numBrushes; 762 | 763 | for (i=0 ; i<6 ; i++) 764 | { 765 | side = i&1; 766 | 767 | // brush sides 768 | s = &cm.brushsides[cm.numBrushSides+i]; 769 | s->plane = cm.planes + (cm.numPlanes+i*2+side); 770 | s->surfaceFlags = 0; 771 | 772 | // planes 773 | p = &box_planes[i*2]; 774 | p->type = i>>1; 775 | p->signbits = 0; 776 | VectorClear (p->normal); 777 | p->normal[i>>1] = 1; 778 | 779 | p = &box_planes[i*2+1]; 780 | p->type = 3 + (i>>1); 781 | p->signbits = 0; 782 | VectorClear (p->normal); 783 | p->normal[i>>1] = -1; 784 | 785 | SetPlaneSignbits( p ); 786 | } 787 | } 788 | 789 | /* 790 | =================== 791 | CM_TempBoxModel 792 | 793 | To keep everything totally uniform, bounding boxes are turned into small 794 | BSP trees instead of being compared directly. 795 | Capsules are handled differently though. 796 | =================== 797 | */ 798 | clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule ) { 799 | 800 | VectorCopy( mins, box_model.mins ); 801 | VectorCopy( maxs, box_model.maxs ); 802 | 803 | if ( capsule ) { 804 | return CAPSULE_MODEL_HANDLE; 805 | } 806 | 807 | box_planes[0].dist = maxs[0]; 808 | box_planes[1].dist = -maxs[0]; 809 | box_planes[2].dist = mins[0]; 810 | box_planes[3].dist = -mins[0]; 811 | box_planes[4].dist = maxs[1]; 812 | box_planes[5].dist = -maxs[1]; 813 | box_planes[6].dist = mins[1]; 814 | box_planes[7].dist = -mins[1]; 815 | box_planes[8].dist = maxs[2]; 816 | box_planes[9].dist = -maxs[2]; 817 | box_planes[10].dist = mins[2]; 818 | box_planes[11].dist = -mins[2]; 819 | 820 | VectorCopy( mins, box_brush->bounds[0] ); 821 | VectorCopy( maxs, box_brush->bounds[1] ); 822 | 823 | return BOX_MODEL_HANDLE; 824 | } 825 | 826 | /* 827 | =================== 828 | CM_ModelBounds 829 | =================== 830 | */ 831 | void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) { 832 | cmodel_t *cmod; 833 | 834 | cmod = CM_ClipHandleToModel( model ); 835 | VectorCopy( cmod->mins, mins ); 836 | VectorCopy( cmod->maxs, maxs ); 837 | } 838 | 839 | 840 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_local.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | 23 | #include "../game/q_shared.h" 24 | #include "qcommon.h" 25 | #include "cm_polylib.h" 26 | 27 | #define MAX_SUBMODELS 256 28 | #define BOX_MODEL_HANDLE 255 29 | #define CAPSULE_MODEL_HANDLE 254 30 | 31 | 32 | typedef struct { 33 | cplane_t *plane; 34 | int children[2]; // negative numbers are leafs 35 | } cNode_t; 36 | 37 | typedef struct { 38 | int cluster; 39 | int area; 40 | 41 | int firstLeafBrush; 42 | int numLeafBrushes; 43 | 44 | int firstLeafSurface; 45 | int numLeafSurfaces; 46 | } cLeaf_t; 47 | 48 | typedef struct cmodel_s { 49 | vec3_t mins, maxs; 50 | cLeaf_t leaf; // submodels don't reference the main tree 51 | } cmodel_t; 52 | 53 | typedef struct { 54 | cplane_t *plane; 55 | int surfaceFlags; 56 | int shaderNum; 57 | } cbrushside_t; 58 | 59 | typedef struct { 60 | int shaderNum; // the shader that determined the contents 61 | int contents; 62 | vec3_t bounds[2]; 63 | int numsides; 64 | cbrushside_t *sides; 65 | int checkcount; // to avoid repeated testings 66 | } cbrush_t; 67 | 68 | 69 | typedef struct { 70 | int checkcount; // to avoid repeated testings 71 | int surfaceFlags; 72 | int contents; 73 | struct patchCollide_s *pc; 74 | } cPatch_t; 75 | 76 | 77 | typedef struct { 78 | int floodnum; 79 | int floodvalid; 80 | } cArea_t; 81 | 82 | typedef struct { 83 | char name[MAX_QPATH]; 84 | 85 | int numShaders; 86 | dshader_t *shaders; 87 | 88 | int numBrushSides; 89 | cbrushside_t *brushsides; 90 | 91 | int numPlanes; 92 | cplane_t *planes; 93 | 94 | int numNodes; 95 | cNode_t *nodes; 96 | 97 | int numLeafs; 98 | cLeaf_t *leafs; 99 | 100 | int numLeafBrushes; 101 | int *leafbrushes; 102 | 103 | int numLeafSurfaces; 104 | int *leafsurfaces; 105 | 106 | int numSubModels; 107 | cmodel_t *cmodels; 108 | 109 | int numBrushes; 110 | cbrush_t *brushes; 111 | 112 | int numClusters; 113 | int clusterBytes; 114 | byte *visibility; 115 | qboolean vised; // if false, visibility is just a single cluster of ffs 116 | 117 | int numEntityChars; 118 | char *entityString; 119 | 120 | int numAreas; 121 | cArea_t *areas; 122 | int *areaPortals; // [ numAreas*numAreas ] reference counts 123 | 124 | int numSurfaces; 125 | cPatch_t **surfaces; // non-patches will be NULL 126 | 127 | int floodvalid; 128 | int checkcount; // incremented on each trace 129 | } clipMap_t; 130 | 131 | 132 | // keep 1/8 unit away to keep the position valid before network snapping 133 | // and to avoid various numeric issues 134 | #define SURFACE_CLIP_EPSILON (0.125) 135 | 136 | extern clipMap_t cm; 137 | extern int c_pointcontents; 138 | extern int c_traces, c_brush_traces, c_patch_traces; 139 | extern cvar_t *cm_noAreas; 140 | extern cvar_t *cm_noCurves; 141 | extern cvar_t *cm_playerCurveClip; 142 | 143 | // cm_test.c 144 | 145 | // Used for oriented capsule collision detection 146 | typedef struct 147 | { 148 | qboolean use; 149 | float radius; 150 | float halfheight; 151 | vec3_t offset; 152 | } sphere_t; 153 | 154 | typedef struct { 155 | vec3_t start; 156 | vec3_t end; 157 | vec3_t size[2]; // size of the box being swept through the model 158 | vec3_t offsets[8]; // [signbits][x] = either size[0][x] or size[1][x] 159 | float maxOffset; // longest corner length from origin 160 | vec3_t extents; // greatest of abs(size[0]) and abs(size[1]) 161 | vec3_t bounds[2]; // enclosing box of start and end surrounding by size 162 | vec3_t modelOrigin;// origin of the model tracing through 163 | int contents; // ored contents of the model tracing through 164 | qboolean isPoint; // optimized case 165 | trace_t trace; // returned from trace call 166 | sphere_t sphere; // sphere for oriendted capsule collision 167 | } traceWork_t; 168 | 169 | typedef struct leafList_s { 170 | int count; 171 | int maxcount; 172 | qboolean overflowed; 173 | int *list; 174 | vec3_t bounds[2]; 175 | int lastLeaf; // for overflows where each leaf can't be stored individually 176 | void (*storeLeafs)( struct leafList_s *ll, int nodenum ); 177 | } leafList_t; 178 | 179 | 180 | int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ); 181 | 182 | void CM_StoreLeafs( leafList_t *ll, int nodenum ); 183 | void CM_StoreBrushes( leafList_t *ll, int nodenum ); 184 | 185 | void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ); 186 | 187 | cmodel_t *CM_ClipHandleToModel( clipHandle_t handle ); 188 | 189 | // cm_patch.c 190 | 191 | struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ); 192 | void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ); 193 | qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ); 194 | void CM_ClearLevelPatches( void ); 195 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_patch.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | 23 | //#define CULL_BBOX 24 | 25 | /* 26 | 27 | This file does not reference any globals, and has these entry points: 28 | 29 | void CM_ClearLevelPatches( void ); 30 | struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, const vec3_t *points ); 31 | void CM_TraceThroughPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ); 32 | qboolean CM_PositionTestInPatchCollide( traceWork_t *tw, const struct patchCollide_s *pc ); 33 | void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, flaot *points) ); 34 | 35 | 36 | Issues for collision against curved surfaces: 37 | 38 | Surface edges need to be handled differently than surface planes 39 | 40 | Plane expansion causes raw surfaces to expand past expanded bounding box 41 | 42 | Position test of a volume against a surface is tricky. 43 | 44 | Position test of a point against a surface is not well defined, because the surface has no volume. 45 | 46 | 47 | Tracing leading edge points instead of volumes? 48 | Position test by tracing corner to corner? (8*7 traces -- ouch) 49 | 50 | coplanar edges 51 | triangulated patches 52 | degenerate patches 53 | 54 | endcaps 55 | degenerate 56 | 57 | WARNING: this may misbehave with meshes that have rows or columns that only 58 | degenerate a few triangles. Completely degenerate rows and columns are handled 59 | properly. 60 | */ 61 | 62 | 63 | #define MAX_FACETS 1024 64 | #define MAX_PATCH_PLANES 2048 65 | 66 | typedef struct { 67 | float plane[4]; 68 | int signbits; // signx + (signy<<1) + (signz<<2), used as lookup during collision 69 | } patchPlane_t; 70 | 71 | typedef struct { 72 | int surfacePlane; 73 | int numBorders; // 3 or four + 6 axial bevels + 4 or 3 * 4 edge bevels 74 | int borderPlanes[4+6+16]; 75 | int borderInward[4+6+16]; 76 | qboolean borderNoAdjust[4+6+16]; 77 | } facet_t; 78 | 79 | typedef struct patchCollide_s { 80 | vec3_t bounds[2]; 81 | int numPlanes; // surface planes plus edge planes 82 | patchPlane_t *planes; 83 | int numFacets; 84 | facet_t *facets; 85 | } patchCollide_t; 86 | 87 | 88 | #define MAX_GRID_SIZE 129 89 | 90 | typedef struct { 91 | int width; 92 | int height; 93 | qboolean wrapWidth; 94 | qboolean wrapHeight; 95 | vec3_t points[MAX_GRID_SIZE][MAX_GRID_SIZE]; // [width][height] 96 | } cGrid_t; 97 | 98 | #define SUBDIVIDE_DISTANCE 16 //4 // never more than this units away from curve 99 | #define PLANE_TRI_EPSILON 0.1 100 | #define WRAP_POINT_EPSILON 0.1 101 | 102 | 103 | struct patchCollide_s *CM_GeneratePatchCollide( int width, int height, vec3_t *points ); 104 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_polylib.c: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | 23 | // this is only used for visualization tools in cm_ debug functions 24 | 25 | 26 | #include "cm_local.h" 27 | 28 | 29 | // counters are only bumped when running single threaded, 30 | // because they are an awefull coherence problem 31 | int c_active_windings; 32 | int c_peak_windings; 33 | int c_winding_allocs; 34 | int c_winding_points; 35 | 36 | void pw(winding_t *w) 37 | { 38 | int i; 39 | for (i=0 ; inumpoints ; i++) 40 | printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); 41 | } 42 | 43 | 44 | /* 45 | ============= 46 | AllocWinding 47 | ============= 48 | */ 49 | winding_t *AllocWinding (int points) 50 | { 51 | winding_t *w; 52 | int s; 53 | 54 | c_winding_allocs++; 55 | c_winding_points += points; 56 | c_active_windings++; 57 | if (c_active_windings > c_peak_windings) 58 | c_peak_windings = c_active_windings; 59 | 60 | s = sizeof(vec_t)*3*points + sizeof(int); 61 | w = Z_Malloc (s); 62 | Com_Memset (w, 0, s); 63 | return w; 64 | } 65 | 66 | void FreeWinding (winding_t *w) 67 | { 68 | if (*(unsigned *)w == 0xdeaddead) 69 | Com_Error (ERR_FATAL, "FreeWinding: freed a freed winding"); 70 | *(unsigned *)w = 0xdeaddead; 71 | 72 | c_active_windings--; 73 | Z_Free (w); 74 | } 75 | 76 | /* 77 | ============ 78 | RemoveColinearPoints 79 | ============ 80 | */ 81 | int c_removed; 82 | 83 | void RemoveColinearPoints (winding_t *w) 84 | { 85 | int i, j, k; 86 | vec3_t v1, v2; 87 | int nump; 88 | vec3_t p[MAX_POINTS_ON_WINDING]; 89 | 90 | nump = 0; 91 | for (i=0 ; inumpoints ; i++) 92 | { 93 | j = (i+1)%w->numpoints; 94 | k = (i+w->numpoints-1)%w->numpoints; 95 | VectorSubtract (w->p[j], w->p[i], v1); 96 | VectorSubtract (w->p[i], w->p[k], v2); 97 | VectorNormalize2(v1,v1); 98 | VectorNormalize2(v2,v2); 99 | if (DotProduct(v1, v2) < 0.999) 100 | { 101 | VectorCopy (w->p[i], p[nump]); 102 | nump++; 103 | } 104 | } 105 | 106 | if (nump == w->numpoints) 107 | return; 108 | 109 | c_removed += w->numpoints - nump; 110 | w->numpoints = nump; 111 | Com_Memcpy (w->p, p, nump*sizeof(p[0])); 112 | } 113 | 114 | /* 115 | ============ 116 | WindingPlane 117 | ============ 118 | */ 119 | void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) 120 | { 121 | vec3_t v1, v2; 122 | 123 | VectorSubtract (w->p[1], w->p[0], v1); 124 | VectorSubtract (w->p[2], w->p[0], v2); 125 | CrossProduct (v2, v1, normal); 126 | VectorNormalize2(normal, normal); 127 | *dist = DotProduct (w->p[0], normal); 128 | 129 | } 130 | 131 | /* 132 | ============= 133 | WindingArea 134 | ============= 135 | */ 136 | vec_t WindingArea (winding_t *w) 137 | { 138 | int i; 139 | vec3_t d1, d2, cross; 140 | vec_t total; 141 | 142 | total = 0; 143 | for (i=2 ; inumpoints ; i++) 144 | { 145 | VectorSubtract (w->p[i-1], w->p[0], d1); 146 | VectorSubtract (w->p[i], w->p[0], d2); 147 | CrossProduct (d1, d2, cross); 148 | total += 0.5 * VectorLength ( cross ); 149 | } 150 | return total; 151 | } 152 | 153 | /* 154 | ============= 155 | WindingBounds 156 | ============= 157 | */ 158 | void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs) 159 | { 160 | vec_t v; 161 | int i,j; 162 | 163 | mins[0] = mins[1] = mins[2] = MAX_MAP_BOUNDS; 164 | maxs[0] = maxs[1] = maxs[2] = -MAX_MAP_BOUNDS; 165 | 166 | for (i=0 ; inumpoints ; i++) 167 | { 168 | for (j=0 ; j<3 ; j++) 169 | { 170 | v = w->p[i][j]; 171 | if (v < mins[j]) 172 | mins[j] = v; 173 | if (v > maxs[j]) 174 | maxs[j] = v; 175 | } 176 | } 177 | } 178 | 179 | /* 180 | ============= 181 | WindingCenter 182 | ============= 183 | */ 184 | void WindingCenter (winding_t *w, vec3_t center) 185 | { 186 | int i; 187 | float scale; 188 | 189 | VectorCopy (vec3_origin, center); 190 | for (i=0 ; inumpoints ; i++) 191 | VectorAdd (w->p[i], center, center); 192 | 193 | scale = 1.0/w->numpoints; 194 | VectorScale (center, scale, center); 195 | } 196 | 197 | /* 198 | ================= 199 | BaseWindingForPlane 200 | ================= 201 | */ 202 | winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist) 203 | { 204 | int i, x; 205 | vec_t max, v; 206 | vec3_t org, vright, vup; 207 | winding_t *w; 208 | 209 | // find the major axis 210 | 211 | max = -MAX_MAP_BOUNDS; 212 | x = -1; 213 | for (i=0 ; i<3; i++) 214 | { 215 | v = fabs(normal[i]); 216 | if (v > max) 217 | { 218 | x = i; 219 | max = v; 220 | } 221 | } 222 | if (x==-1) 223 | Com_Error (ERR_DROP, "BaseWindingForPlane: no axis found"); 224 | 225 | VectorCopy (vec3_origin, vup); 226 | switch (x) 227 | { 228 | case 0: 229 | case 1: 230 | vup[2] = 1; 231 | break; 232 | case 2: 233 | vup[0] = 1; 234 | break; 235 | } 236 | 237 | v = DotProduct (vup, normal); 238 | VectorMA (vup, -v, normal, vup); 239 | VectorNormalize2(vup, vup); 240 | 241 | VectorScale (normal, dist, org); 242 | 243 | CrossProduct (vup, normal, vright); 244 | 245 | VectorScale (vup, MAX_MAP_BOUNDS, vup); 246 | VectorScale (vright, MAX_MAP_BOUNDS, vright); 247 | 248 | // project a really big axis aligned box onto the plane 249 | w = AllocWinding (4); 250 | 251 | VectorSubtract (org, vright, w->p[0]); 252 | VectorAdd (w->p[0], vup, w->p[0]); 253 | 254 | VectorAdd (org, vright, w->p[1]); 255 | VectorAdd (w->p[1], vup, w->p[1]); 256 | 257 | VectorAdd (org, vright, w->p[2]); 258 | VectorSubtract (w->p[2], vup, w->p[2]); 259 | 260 | VectorSubtract (org, vright, w->p[3]); 261 | VectorSubtract (w->p[3], vup, w->p[3]); 262 | 263 | w->numpoints = 4; 264 | 265 | return w; 266 | } 267 | 268 | /* 269 | ================== 270 | CopyWinding 271 | ================== 272 | */ 273 | winding_t *CopyWinding (winding_t *w) 274 | { 275 | int size; 276 | winding_t *c; 277 | 278 | c = AllocWinding (w->numpoints); 279 | size = (int)((winding_t *)0)->p[w->numpoints]; 280 | Com_Memcpy (c, w, size); 281 | return c; 282 | } 283 | 284 | /* 285 | ================== 286 | ReverseWinding 287 | ================== 288 | */ 289 | winding_t *ReverseWinding (winding_t *w) 290 | { 291 | int i; 292 | winding_t *c; 293 | 294 | c = AllocWinding (w->numpoints); 295 | for (i=0 ; inumpoints ; i++) 296 | { 297 | VectorCopy (w->p[w->numpoints-1-i], c->p[i]); 298 | } 299 | c->numpoints = w->numpoints; 300 | return c; 301 | } 302 | 303 | 304 | /* 305 | ============= 306 | ClipWindingEpsilon 307 | ============= 308 | */ 309 | void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 310 | vec_t epsilon, winding_t **front, winding_t **back) 311 | { 312 | vec_t dists[MAX_POINTS_ON_WINDING+4]; 313 | int sides[MAX_POINTS_ON_WINDING+4]; 314 | int counts[3]; 315 | static vec_t dot; // VC 4.2 optimizer bug if not static 316 | int i, j; 317 | vec_t *p1, *p2; 318 | vec3_t mid; 319 | winding_t *f, *b; 320 | int maxpts; 321 | 322 | counts[0] = counts[1] = counts[2] = 0; 323 | 324 | // determine sides for each point 325 | for (i=0 ; inumpoints ; i++) 326 | { 327 | dot = DotProduct (in->p[i], normal); 328 | dot -= dist; 329 | dists[i] = dot; 330 | if (dot > epsilon) 331 | sides[i] = SIDE_FRONT; 332 | else if (dot < -epsilon) 333 | sides[i] = SIDE_BACK; 334 | else 335 | { 336 | sides[i] = SIDE_ON; 337 | } 338 | counts[sides[i]]++; 339 | } 340 | sides[i] = sides[0]; 341 | dists[i] = dists[0]; 342 | 343 | *front = *back = NULL; 344 | 345 | if (!counts[0]) 346 | { 347 | *back = CopyWinding (in); 348 | return; 349 | } 350 | if (!counts[1]) 351 | { 352 | *front = CopyWinding (in); 353 | return; 354 | } 355 | 356 | maxpts = in->numpoints+4; // cant use counts[0]+2 because 357 | // of fp grouping errors 358 | 359 | *front = f = AllocWinding (maxpts); 360 | *back = b = AllocWinding (maxpts); 361 | 362 | for (i=0 ; inumpoints ; i++) 363 | { 364 | p1 = in->p[i]; 365 | 366 | if (sides[i] == SIDE_ON) 367 | { 368 | VectorCopy (p1, f->p[f->numpoints]); 369 | f->numpoints++; 370 | VectorCopy (p1, b->p[b->numpoints]); 371 | b->numpoints++; 372 | continue; 373 | } 374 | 375 | if (sides[i] == SIDE_FRONT) 376 | { 377 | VectorCopy (p1, f->p[f->numpoints]); 378 | f->numpoints++; 379 | } 380 | if (sides[i] == SIDE_BACK) 381 | { 382 | VectorCopy (p1, b->p[b->numpoints]); 383 | b->numpoints++; 384 | } 385 | 386 | if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) 387 | continue; 388 | 389 | // generate a split point 390 | p2 = in->p[(i+1)%in->numpoints]; 391 | 392 | dot = dists[i] / (dists[i]-dists[i+1]); 393 | for (j=0 ; j<3 ; j++) 394 | { // avoid round off error when possible 395 | if (normal[j] == 1) 396 | mid[j] = dist; 397 | else if (normal[j] == -1) 398 | mid[j] = -dist; 399 | else 400 | mid[j] = p1[j] + dot*(p2[j]-p1[j]); 401 | } 402 | 403 | VectorCopy (mid, f->p[f->numpoints]); 404 | f->numpoints++; 405 | VectorCopy (mid, b->p[b->numpoints]); 406 | b->numpoints++; 407 | } 408 | 409 | if (f->numpoints > maxpts || b->numpoints > maxpts) 410 | Com_Error (ERR_DROP, "ClipWinding: points exceeded estimate"); 411 | if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) 412 | Com_Error (ERR_DROP, "ClipWinding: MAX_POINTS_ON_WINDING"); 413 | } 414 | 415 | 416 | /* 417 | ============= 418 | ChopWindingInPlace 419 | ============= 420 | */ 421 | void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon) 422 | { 423 | winding_t *in; 424 | vec_t dists[MAX_POINTS_ON_WINDING+4]; 425 | int sides[MAX_POINTS_ON_WINDING+4]; 426 | int counts[3]; 427 | static vec_t dot; // VC 4.2 optimizer bug if not static 428 | int i, j; 429 | vec_t *p1, *p2; 430 | vec3_t mid; 431 | winding_t *f; 432 | int maxpts; 433 | 434 | in = *inout; 435 | counts[0] = counts[1] = counts[2] = 0; 436 | 437 | // determine sides for each point 438 | for (i=0 ; inumpoints ; i++) 439 | { 440 | dot = DotProduct (in->p[i], normal); 441 | dot -= dist; 442 | dists[i] = dot; 443 | if (dot > epsilon) 444 | sides[i] = SIDE_FRONT; 445 | else if (dot < -epsilon) 446 | sides[i] = SIDE_BACK; 447 | else 448 | { 449 | sides[i] = SIDE_ON; 450 | } 451 | counts[sides[i]]++; 452 | } 453 | sides[i] = sides[0]; 454 | dists[i] = dists[0]; 455 | 456 | if (!counts[0]) 457 | { 458 | FreeWinding (in); 459 | *inout = NULL; 460 | return; 461 | } 462 | if (!counts[1]) 463 | return; // inout stays the same 464 | 465 | maxpts = in->numpoints+4; // cant use counts[0]+2 because 466 | // of fp grouping errors 467 | 468 | f = AllocWinding (maxpts); 469 | 470 | for (i=0 ; inumpoints ; i++) 471 | { 472 | p1 = in->p[i]; 473 | 474 | if (sides[i] == SIDE_ON) 475 | { 476 | VectorCopy (p1, f->p[f->numpoints]); 477 | f->numpoints++; 478 | continue; 479 | } 480 | 481 | if (sides[i] == SIDE_FRONT) 482 | { 483 | VectorCopy (p1, f->p[f->numpoints]); 484 | f->numpoints++; 485 | } 486 | 487 | if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) 488 | continue; 489 | 490 | // generate a split point 491 | p2 = in->p[(i+1)%in->numpoints]; 492 | 493 | dot = dists[i] / (dists[i]-dists[i+1]); 494 | for (j=0 ; j<3 ; j++) 495 | { // avoid round off error when possible 496 | if (normal[j] == 1) 497 | mid[j] = dist; 498 | else if (normal[j] == -1) 499 | mid[j] = -dist; 500 | else 501 | mid[j] = p1[j] + dot*(p2[j]-p1[j]); 502 | } 503 | 504 | VectorCopy (mid, f->p[f->numpoints]); 505 | f->numpoints++; 506 | } 507 | 508 | if (f->numpoints > maxpts) 509 | Com_Error (ERR_DROP, "ClipWinding: points exceeded estimate"); 510 | if (f->numpoints > MAX_POINTS_ON_WINDING) 511 | Com_Error (ERR_DROP, "ClipWinding: MAX_POINTS_ON_WINDING"); 512 | 513 | FreeWinding (in); 514 | *inout = f; 515 | } 516 | 517 | 518 | /* 519 | ================= 520 | ChopWinding 521 | 522 | Returns the fragment of in that is on the front side 523 | of the cliping plane. The original is freed. 524 | ================= 525 | */ 526 | winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) 527 | { 528 | winding_t *f, *b; 529 | 530 | ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b); 531 | FreeWinding (in); 532 | if (b) 533 | FreeWinding (b); 534 | return f; 535 | } 536 | 537 | 538 | /* 539 | ================= 540 | CheckWinding 541 | 542 | ================= 543 | */ 544 | void CheckWinding (winding_t *w) 545 | { 546 | int i, j; 547 | vec_t *p1, *p2; 548 | vec_t d, edgedist; 549 | vec3_t dir, edgenormal, facenormal; 550 | vec_t area; 551 | vec_t facedist; 552 | 553 | if (w->numpoints < 3) 554 | Com_Error (ERR_DROP, "CheckWinding: %i points",w->numpoints); 555 | 556 | area = WindingArea(w); 557 | if (area < 1) 558 | Com_Error (ERR_DROP, "CheckWinding: %f area", area); 559 | 560 | WindingPlane (w, facenormal, &facedist); 561 | 562 | for (i=0 ; inumpoints ; i++) 563 | { 564 | p1 = w->p[i]; 565 | 566 | for (j=0 ; j<3 ; j++) 567 | if (p1[j] > MAX_MAP_BOUNDS || p1[j] < -MAX_MAP_BOUNDS) 568 | Com_Error (ERR_DROP, "CheckFace: BUGUS_RANGE: %f",p1[j]); 569 | 570 | j = i+1 == w->numpoints ? 0 : i+1; 571 | 572 | // check the point is on the face plane 573 | d = DotProduct (p1, facenormal) - facedist; 574 | if (d < -ON_EPSILON || d > ON_EPSILON) 575 | Com_Error (ERR_DROP, "CheckWinding: point off plane"); 576 | 577 | // check the edge isnt degenerate 578 | p2 = w->p[j]; 579 | VectorSubtract (p2, p1, dir); 580 | 581 | if (VectorLength (dir) < ON_EPSILON) 582 | Com_Error (ERR_DROP, "CheckWinding: degenerate edge"); 583 | 584 | CrossProduct (facenormal, dir, edgenormal); 585 | VectorNormalize2 (edgenormal, edgenormal); 586 | edgedist = DotProduct (p1, edgenormal); 587 | edgedist += ON_EPSILON; 588 | 589 | // all other points must be on front side 590 | for (j=0 ; jnumpoints ; j++) 591 | { 592 | if (j == i) 593 | continue; 594 | d = DotProduct (w->p[j], edgenormal); 595 | if (d > edgedist) 596 | Com_Error (ERR_DROP, "CheckWinding: non-convex"); 597 | } 598 | } 599 | } 600 | 601 | 602 | /* 603 | ============ 604 | WindingOnPlaneSide 605 | ============ 606 | */ 607 | int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist) 608 | { 609 | qboolean front, back; 610 | int i; 611 | vec_t d; 612 | 613 | front = qfalse; 614 | back = qfalse; 615 | for (i=0 ; inumpoints ; i++) 616 | { 617 | d = DotProduct (w->p[i], normal) - dist; 618 | if (d < -ON_EPSILON) 619 | { 620 | if (front) 621 | return SIDE_CROSS; 622 | back = qtrue; 623 | continue; 624 | } 625 | if (d > ON_EPSILON) 626 | { 627 | if (back) 628 | return SIDE_CROSS; 629 | front = qtrue; 630 | continue; 631 | } 632 | } 633 | 634 | if (back) 635 | return SIDE_BACK; 636 | if (front) 637 | return SIDE_FRONT; 638 | return SIDE_ON; 639 | } 640 | 641 | 642 | /* 643 | ================= 644 | AddWindingToConvexHull 645 | 646 | Both w and *hull are on the same plane 647 | ================= 648 | */ 649 | #define MAX_HULL_POINTS 128 650 | void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ) { 651 | int i, j, k; 652 | float *p, *copy; 653 | vec3_t dir; 654 | float d; 655 | int numHullPoints, numNew; 656 | vec3_t hullPoints[MAX_HULL_POINTS]; 657 | vec3_t newHullPoints[MAX_HULL_POINTS]; 658 | vec3_t hullDirs[MAX_HULL_POINTS]; 659 | qboolean hullSide[MAX_HULL_POINTS]; 660 | qboolean outside; 661 | 662 | if ( !*hull ) { 663 | *hull = CopyWinding( w ); 664 | return; 665 | } 666 | 667 | numHullPoints = (*hull)->numpoints; 668 | Com_Memcpy( hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t) ); 669 | 670 | for ( i = 0 ; i < w->numpoints ; i++ ) { 671 | p = w->p[i]; 672 | 673 | // calculate hull side vectors 674 | for ( j = 0 ; j < numHullPoints ; j++ ) { 675 | k = ( j + 1 ) % numHullPoints; 676 | 677 | VectorSubtract( hullPoints[k], hullPoints[j], dir ); 678 | VectorNormalize2( dir, dir ); 679 | CrossProduct( normal, dir, hullDirs[j] ); 680 | } 681 | 682 | outside = qfalse; 683 | for ( j = 0 ; j < numHullPoints ; j++ ) { 684 | VectorSubtract( p, hullPoints[j], dir ); 685 | d = DotProduct( dir, hullDirs[j] ); 686 | if ( d >= ON_EPSILON ) { 687 | outside = qtrue; 688 | } 689 | if ( d >= -ON_EPSILON ) { 690 | hullSide[j] = qtrue; 691 | } else { 692 | hullSide[j] = qfalse; 693 | } 694 | } 695 | 696 | // if the point is effectively inside, do nothing 697 | if ( !outside ) { 698 | continue; 699 | } 700 | 701 | // find the back side to front side transition 702 | for ( j = 0 ; j < numHullPoints ; j++ ) { 703 | if ( !hullSide[ j % numHullPoints ] && hullSide[ (j + 1) % numHullPoints ] ) { 704 | break; 705 | } 706 | } 707 | if ( j == numHullPoints ) { 708 | continue; 709 | } 710 | 711 | // insert the point here 712 | VectorCopy( p, newHullPoints[0] ); 713 | numNew = 1; 714 | 715 | // copy over all points that aren't double fronts 716 | j = (j+1)%numHullPoints; 717 | for ( k = 0 ; k < numHullPoints ; k++ ) { 718 | if ( hullSide[ (j+k) % numHullPoints ] && hullSide[ (j+k+1) % numHullPoints ] ) { 719 | continue; 720 | } 721 | copy = hullPoints[ (j+k+1) % numHullPoints ]; 722 | VectorCopy( copy, newHullPoints[numNew] ); 723 | numNew++; 724 | } 725 | 726 | numHullPoints = numNew; 727 | Com_Memcpy( hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t) ); 728 | } 729 | 730 | FreeWinding( *hull ); 731 | w = AllocWinding( numHullPoints ); 732 | w->numpoints = numHullPoints; 733 | *hull = w; 734 | Com_Memcpy( w->p, hullPoints, numHullPoints * sizeof(vec3_t) ); 735 | } 736 | 737 | 738 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_polylib.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | 23 | // this is only used for visualization tools in cm_ debug functions 24 | 25 | typedef struct 26 | { 27 | int numpoints; 28 | vec3_t p[4]; // variable sized 29 | } winding_t; 30 | 31 | #define MAX_POINTS_ON_WINDING 64 32 | 33 | #define SIDE_FRONT 0 34 | #define SIDE_BACK 1 35 | #define SIDE_ON 2 36 | #define SIDE_CROSS 3 37 | 38 | #define CLIP_EPSILON 0.1f 39 | 40 | #define MAX_MAP_BOUNDS 65535 41 | 42 | // you can define on_epsilon in the makefile as tighter 43 | #ifndef ON_EPSILON 44 | #define ON_EPSILON 0.1f 45 | #endif 46 | 47 | winding_t *AllocWinding (int points); 48 | vec_t WindingArea (winding_t *w); 49 | void WindingCenter (winding_t *w, vec3_t center); 50 | void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 51 | vec_t epsilon, winding_t **front, winding_t **back); 52 | winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); 53 | winding_t *CopyWinding (winding_t *w); 54 | winding_t *ReverseWinding (winding_t *w); 55 | winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); 56 | void CheckWinding (winding_t *w); 57 | void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); 58 | void RemoveColinearPoints (winding_t *w); 59 | int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist); 60 | void FreeWinding (winding_t *w); 61 | void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); 62 | 63 | void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ); 64 | 65 | void ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon); 66 | // frees the original if clipped 67 | 68 | void pw(winding_t *w); 69 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_public.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | 23 | #include "qfiles.h" 24 | 25 | 26 | void CM_LoadMap( const char *name, qboolean clientload, int *checksum); 27 | void CM_ClearMap( void ); 28 | clipHandle_t CM_InlineModel( int index ); // 0 = world, 1 + are bmodels 29 | clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule ); 30 | 31 | void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ); 32 | 33 | int CM_NumClusters (void); 34 | int CM_NumInlineModels( void ); 35 | char *CM_EntityString (void); 36 | 37 | // returns an ORed contents mask 38 | int CM_PointContents( const vec3_t p, clipHandle_t model ); 39 | int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles ); 40 | 41 | void CM_BoxTrace ( trace_t *results, const vec3_t start, const vec3_t end, 42 | vec3_t mins, vec3_t maxs, 43 | clipHandle_t model, int brushmask, int capsule ); 44 | void CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end, 45 | vec3_t mins, vec3_t maxs, 46 | clipHandle_t model, int brushmask, 47 | const vec3_t origin, const vec3_t angles, int capsule ); 48 | 49 | byte *CM_ClusterPVS (int cluster); 50 | 51 | int CM_PointLeafnum( const vec3_t p ); 52 | 53 | // only returns non-solid leafs 54 | // overflow if return listsize and if *lastLeaf != list[listsize-1] 55 | int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, 56 | int listsize, int *lastLeaf ); 57 | 58 | int CM_LeafCluster (int leafnum); 59 | int CM_LeafArea (int leafnum); 60 | 61 | void CM_AdjustAreaPortalState( int area1, int area2, qboolean open ); 62 | qboolean CM_AreasConnected( int area1, int area2 ); 63 | 64 | int CM_WriteAreaBits( byte *buffer, int area ); 65 | 66 | // cm_tag.c 67 | int CM_LerpTag( orientation_t *tag, clipHandle_t model, int startFrame, int endFrame, 68 | float frac, const char *tagName ); 69 | 70 | 71 | // cm_marks.c 72 | int CM_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, 73 | int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ); 74 | 75 | // cm_patch.c 76 | void CM_DrawDebugSurface( void (*drawPoly)(int color, int numPoints, float *points) ); 77 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/cm_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | #include "cm_local.h" 23 | 24 | 25 | /* 26 | ================== 27 | CM_PointLeafnum_r 28 | 29 | ================== 30 | */ 31 | int CM_PointLeafnum_r( const vec3_t p, int num ) { 32 | float d; 33 | cNode_t *node; 34 | cplane_t *plane; 35 | 36 | while (num >= 0) 37 | { 38 | node = cm.nodes + num; 39 | plane = node->plane; 40 | 41 | if (plane->type < 3) 42 | d = p[plane->type] - plane->dist; 43 | else 44 | d = DotProduct (plane->normal, p) - plane->dist; 45 | if (d < 0) 46 | num = node->children[1]; 47 | else 48 | num = node->children[0]; 49 | } 50 | 51 | c_pointcontents++; // optimize counter 52 | 53 | return -1 - num; 54 | } 55 | 56 | int CM_PointLeafnum( const vec3_t p ) { 57 | if ( !cm.numNodes ) { // map not loaded 58 | return 0; 59 | } 60 | return CM_PointLeafnum_r (p, 0); 61 | } 62 | 63 | 64 | /* 65 | ====================================================================== 66 | 67 | LEAF LISTING 68 | 69 | ====================================================================== 70 | */ 71 | 72 | 73 | void CM_StoreLeafs( leafList_t *ll, int nodenum ) { 74 | int leafNum; 75 | 76 | leafNum = -1 - nodenum; 77 | 78 | // store the lastLeaf even if the list is overflowed 79 | if ( cm.leafs[ leafNum ].cluster != -1 ) { 80 | ll->lastLeaf = leafNum; 81 | } 82 | 83 | if ( ll->count >= ll->maxcount) { 84 | ll->overflowed = qtrue; 85 | return; 86 | } 87 | ll->list[ ll->count++ ] = leafNum; 88 | } 89 | 90 | void CM_StoreBrushes( leafList_t *ll, int nodenum ) { 91 | int i, k; 92 | int leafnum; 93 | int brushnum; 94 | cLeaf_t *leaf; 95 | cbrush_t *b; 96 | 97 | leafnum = -1 - nodenum; 98 | 99 | leaf = &cm.leafs[leafnum]; 100 | 101 | for ( k = 0 ; k < leaf->numLeafBrushes ; k++ ) { 102 | brushnum = cm.leafbrushes[leaf->firstLeafBrush+k]; 103 | b = &cm.brushes[brushnum]; 104 | if ( b->checkcount == cm.checkcount ) { 105 | continue; // already checked this brush in another leaf 106 | } 107 | b->checkcount = cm.checkcount; 108 | for ( i = 0 ; i < 3 ; i++ ) { 109 | if ( b->bounds[0][i] >= ll->bounds[1][i] || b->bounds[1][i] <= ll->bounds[0][i] ) { 110 | break; 111 | } 112 | } 113 | if ( i != 3 ) { 114 | continue; 115 | } 116 | if ( ll->count >= ll->maxcount) { 117 | ll->overflowed = qtrue; 118 | return; 119 | } 120 | ((cbrush_t **)ll->list)[ ll->count++ ] = b; 121 | } 122 | #if 0 123 | // store patches? 124 | for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) { 125 | patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstleafsurface + k ] ]; 126 | if ( !patch ) { 127 | continue; 128 | } 129 | } 130 | #endif 131 | } 132 | 133 | /* 134 | ============= 135 | CM_BoxLeafnums 136 | 137 | Fills in a list of all the leafs touched 138 | ============= 139 | */ 140 | void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ) { 141 | cplane_t *plane; 142 | cNode_t *node; 143 | int s; 144 | 145 | while (1) { 146 | if (nodenum < 0) { 147 | ll->storeLeafs( ll, nodenum ); 148 | return; 149 | } 150 | 151 | node = &cm.nodes[nodenum]; 152 | plane = node->plane; 153 | s = BoxOnPlaneSide( ll->bounds[0], ll->bounds[1], plane ); 154 | if (s == 1) { 155 | nodenum = node->children[0]; 156 | } else if (s == 2) { 157 | nodenum = node->children[1]; 158 | } else { 159 | // go down both 160 | CM_BoxLeafnums_r( ll, node->children[0] ); 161 | nodenum = node->children[1]; 162 | } 163 | 164 | } 165 | } 166 | 167 | /* 168 | ================== 169 | CM_BoxLeafnums 170 | ================== 171 | */ 172 | int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastLeaf) { 173 | leafList_t ll; 174 | 175 | cm.checkcount++; 176 | 177 | VectorCopy( mins, ll.bounds[0] ); 178 | VectorCopy( maxs, ll.bounds[1] ); 179 | ll.count = 0; 180 | ll.maxcount = listsize; 181 | ll.list = list; 182 | ll.storeLeafs = CM_StoreLeafs; 183 | ll.lastLeaf = 0; 184 | ll.overflowed = qfalse; 185 | 186 | CM_BoxLeafnums_r( &ll, 0 ); 187 | 188 | *lastLeaf = ll.lastLeaf; 189 | return ll.count; 190 | } 191 | 192 | /* 193 | ================== 194 | CM_BoxBrushes 195 | ================== 196 | */ 197 | int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ) { 198 | leafList_t ll; 199 | 200 | cm.checkcount++; 201 | 202 | VectorCopy( mins, ll.bounds[0] ); 203 | VectorCopy( maxs, ll.bounds[1] ); 204 | ll.count = 0; 205 | ll.maxcount = listsize; 206 | ll.list = (void *)list; 207 | ll.storeLeafs = CM_StoreBrushes; 208 | ll.lastLeaf = 0; 209 | ll.overflowed = qfalse; 210 | 211 | CM_BoxLeafnums_r( &ll, 0 ); 212 | 213 | return ll.count; 214 | } 215 | 216 | 217 | //==================================================================== 218 | 219 | 220 | /* 221 | ================== 222 | CM_PointContents 223 | 224 | ================== 225 | */ 226 | int CM_PointContents( const vec3_t p, clipHandle_t model ) { 227 | int leafnum; 228 | int i, k; 229 | int brushnum; 230 | cLeaf_t *leaf; 231 | cbrush_t *b; 232 | int contents; 233 | float d; 234 | cmodel_t *clipm; 235 | 236 | if (!cm.numNodes) { // map not loaded 237 | return 0; 238 | } 239 | 240 | if ( model ) { 241 | clipm = CM_ClipHandleToModel( model ); 242 | leaf = &clipm->leaf; 243 | } else { 244 | leafnum = CM_PointLeafnum_r (p, 0); 245 | leaf = &cm.leafs[leafnum]; 246 | } 247 | 248 | contents = 0; 249 | for (k=0 ; knumLeafBrushes ; k++) { 250 | brushnum = cm.leafbrushes[leaf->firstLeafBrush+k]; 251 | b = &cm.brushes[brushnum]; 252 | 253 | // see if the point is in the brush 254 | for ( i = 0 ; i < b->numsides ; i++ ) { 255 | d = DotProduct( p, b->sides[i].plane->normal ); 256 | // FIXME test for Cash 257 | // if ( d >= b->sides[i].plane->dist ) { 258 | if ( d > b->sides[i].plane->dist ) { 259 | break; 260 | } 261 | } 262 | 263 | if ( i == b->numsides ) { 264 | contents |= b->contents; 265 | } 266 | } 267 | 268 | return contents; 269 | } 270 | 271 | /* 272 | ================== 273 | CM_TransformedPointContents 274 | 275 | Handles offseting and rotation of the end points for moving and 276 | rotating entities 277 | ================== 278 | */ 279 | int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles) { 280 | vec3_t p_l; 281 | vec3_t temp; 282 | vec3_t forward, right, up; 283 | 284 | // subtract origin offset 285 | VectorSubtract (p, origin, p_l); 286 | 287 | // rotate start and end into the models frame of reference 288 | if ( model != BOX_MODEL_HANDLE && 289 | (angles[0] || angles[1] || angles[2]) ) 290 | { 291 | AngleVectors (angles, forward, right, up); 292 | 293 | VectorCopy (p_l, temp); 294 | p_l[0] = DotProduct (temp, forward); 295 | p_l[1] = -DotProduct (temp, right); 296 | p_l[2] = DotProduct (temp, up); 297 | } 298 | 299 | return CM_PointContents( p_l, model ); 300 | } 301 | 302 | 303 | 304 | /* 305 | =============================================================================== 306 | 307 | PVS 308 | 309 | =============================================================================== 310 | */ 311 | 312 | byte *CM_ClusterPVS (int cluster) { 313 | if (cluster < 0 || cluster >= cm.numClusters || !cm.vised ) { 314 | return cm.visibility; 315 | } 316 | 317 | return cm.visibility + cluster * cm.clusterBytes; 318 | } 319 | 320 | 321 | 322 | /* 323 | =============================================================================== 324 | 325 | AREAPORTALS 326 | 327 | =============================================================================== 328 | */ 329 | 330 | void CM_FloodArea_r( int areaNum, int floodnum) { 331 | int i; 332 | cArea_t *area; 333 | int *con; 334 | 335 | area = &cm.areas[ areaNum ]; 336 | 337 | if ( area->floodvalid == cm.floodvalid ) { 338 | if (area->floodnum == floodnum) 339 | return; 340 | Com_Error (ERR_DROP, "FloodArea_r: reflooded"); 341 | } 342 | 343 | area->floodnum = floodnum; 344 | area->floodvalid = cm.floodvalid; 345 | con = cm.areaPortals + areaNum * cm.numAreas; 346 | for ( i=0 ; i < cm.numAreas ; i++ ) { 347 | if ( con[i] > 0 ) { 348 | CM_FloodArea_r( i, floodnum ); 349 | } 350 | } 351 | } 352 | 353 | /* 354 | ==================== 355 | CM_FloodAreaConnections 356 | 357 | ==================== 358 | */ 359 | void CM_FloodAreaConnections( void ) { 360 | int i; 361 | cArea_t *area; 362 | int floodnum; 363 | 364 | // all current floods are now invalid 365 | cm.floodvalid++; 366 | floodnum = 0; 367 | 368 | for (i = 0 ; i < cm.numAreas ; i++) { 369 | area = &cm.areas[i]; 370 | if (area->floodvalid == cm.floodvalid) { 371 | continue; // already flooded into 372 | } 373 | floodnum++; 374 | CM_FloodArea_r (i, floodnum); 375 | } 376 | 377 | } 378 | 379 | /* 380 | ==================== 381 | CM_AdjustAreaPortalState 382 | 383 | ==================== 384 | */ 385 | void CM_AdjustAreaPortalState( int area1, int area2, qboolean open ) { 386 | if ( area1 < 0 || area2 < 0 ) { 387 | return; 388 | } 389 | 390 | if ( area1 >= cm.numAreas || area2 >= cm.numAreas ) { 391 | Com_Error (ERR_DROP, "CM_ChangeAreaPortalState: bad area number"); 392 | } 393 | 394 | if ( open ) { 395 | cm.areaPortals[ area1 * cm.numAreas + area2 ]++; 396 | cm.areaPortals[ area2 * cm.numAreas + area1 ]++; 397 | } else { 398 | cm.areaPortals[ area1 * cm.numAreas + area2 ]--; 399 | cm.areaPortals[ area2 * cm.numAreas + area1 ]--; 400 | if ( cm.areaPortals[ area2 * cm.numAreas + area1 ] < 0 ) { 401 | Com_Error (ERR_DROP, "CM_AdjustAreaPortalState: negative reference count"); 402 | } 403 | } 404 | 405 | CM_FloodAreaConnections (); 406 | } 407 | 408 | /* 409 | ==================== 410 | CM_AreasConnected 411 | 412 | ==================== 413 | */ 414 | qboolean CM_AreasConnected( int area1, int area2 ) { 415 | #ifndef BSPC 416 | if ( cm_noAreas->integer ) { 417 | return qtrue; 418 | } 419 | #endif 420 | 421 | if ( area1 < 0 || area2 < 0 ) { 422 | return qfalse; 423 | } 424 | 425 | if (area1 >= cm.numAreas || area2 >= cm.numAreas) { 426 | Com_Error (ERR_DROP, "area >= cm.numAreas"); 427 | } 428 | 429 | if (cm.areas[area1].floodnum == cm.areas[area2].floodnum) { 430 | return qtrue; 431 | } 432 | return qfalse; 433 | } 434 | 435 | 436 | /* 437 | ================= 438 | CM_WriteAreaBits 439 | 440 | Writes a bit vector of all the areas 441 | that are in the same flood as the area parameter 442 | Returns the number of bytes needed to hold all the bits. 443 | 444 | The bits are OR'd in, so you can CM_WriteAreaBits from multiple 445 | viewpoints and get the union of all visible areas. 446 | 447 | This is used to cull non-visible entities from snapshots 448 | ================= 449 | */ 450 | int CM_WriteAreaBits (byte *buffer, int area) 451 | { 452 | int i; 453 | int floodnum; 454 | int bytes; 455 | 456 | bytes = (cm.numAreas+7)>>3; 457 | 458 | #ifndef BSPC 459 | if (cm_noAreas->integer || area == -1) 460 | #else 461 | if ( area == -1) 462 | #endif 463 | { // for debugging, send everything 464 | Com_Memset (buffer, 255, bytes); 465 | } 466 | else 467 | { 468 | floodnum = cm.areas[area].floodnum; 469 | for (i=0 ; i>3] |= 1<<(i&7); 473 | } 474 | } 475 | 476 | return bytes; 477 | } 478 | 479 | -------------------------------------------------------------------------------- /plugins/bsp/quake3/code/qcommon/qfiles.h: -------------------------------------------------------------------------------- 1 | /* 2 | =========================================================================== 3 | Copyright (C) 1999-2005 Id Software, Inc. 4 | 5 | This file is part of Quake III Arena source code. 6 | 7 | Quake III Arena source code is free software; you can redistribute it 8 | and/or modify it under the terms of the GNU General Public License as 9 | published by the Free Software Foundation; either version 2 of the License, 10 | or (at your option) any later version. 11 | 12 | Quake III Arena source code is distributed in the hope that it will be 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Foobar; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | =========================================================================== 21 | */ 22 | #ifndef __QFILES_H__ 23 | #define __QFILES_H__ 24 | 25 | // 26 | // qfiles.h: quake file formats 27 | // This file must be identical in the quake and utils directories 28 | // 29 | 30 | // surface geometry should not exceed these limits 31 | #define SHADER_MAX_VERTEXES 1000 32 | #define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES) 33 | 34 | 35 | // the maximum size of game relative pathnames 36 | #define MAX_QPATH 64 37 | 38 | /* 39 | ======================================================================== 40 | 41 | QVM files 42 | 43 | ======================================================================== 44 | */ 45 | 46 | #define VM_MAGIC 0x12721444 47 | typedef struct { 48 | int vmMagic; 49 | 50 | int instructionCount; 51 | 52 | int codeOffset; 53 | int codeLength; 54 | 55 | int dataOffset; 56 | int dataLength; 57 | int litLength; // ( dataLength - litLength ) should be byteswapped on load 58 | int bssLength; // zero filled memory appended to datalength 59 | } vmHeader_t; 60 | 61 | 62 | /* 63 | ======================================================================== 64 | 65 | PCX files are used for 8 bit images 66 | 67 | ======================================================================== 68 | */ 69 | 70 | typedef struct { 71 | char manufacturer; 72 | char version; 73 | char encoding; 74 | char bits_per_pixel; 75 | unsigned short xmin,ymin,xmax,ymax; 76 | unsigned short hres,vres; 77 | unsigned char palette[48]; 78 | char reserved; 79 | char color_planes; 80 | unsigned short bytes_per_line; 81 | unsigned short palette_type; 82 | char filler[58]; 83 | unsigned char data; // unbounded 84 | } pcx_t; 85 | 86 | 87 | /* 88 | ======================================================================== 89 | 90 | TGA files are used for 24/32 bit images 91 | 92 | ======================================================================== 93 | */ 94 | 95 | typedef struct _TargaHeader { 96 | unsigned char id_length, colormap_type, image_type; 97 | unsigned short colormap_index, colormap_length; 98 | unsigned char colormap_size; 99 | unsigned short x_origin, y_origin, width, height; 100 | unsigned char pixel_size, attributes; 101 | } TargaHeader; 102 | 103 | 104 | 105 | /* 106 | ======================================================================== 107 | 108 | .MD3 triangle model file format 109 | 110 | ======================================================================== 111 | */ 112 | 113 | #define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I') 114 | #define MD3_VERSION 15 115 | 116 | // limits 117 | #define MD3_MAX_LODS 3 118 | #define MD3_MAX_TRIANGLES 8192 // per surface 119 | #define MD3_MAX_VERTS 4096 // per surface 120 | #define MD3_MAX_SHADERS 256 // per surface 121 | #define MD3_MAX_FRAMES 1024 // per model 122 | #define MD3_MAX_SURFACES 32 // per model 123 | #define MD3_MAX_TAGS 16 // per frame 124 | 125 | // vertex scales 126 | #define MD3_XYZ_SCALE (1.0/64) 127 | 128 | typedef struct md3Frame_s { 129 | vec3_t bounds[2]; 130 | vec3_t localOrigin; 131 | float radius; 132 | char name[16]; 133 | } md3Frame_t; 134 | 135 | typedef struct md3Tag_s { 136 | char name[MAX_QPATH]; // tag name 137 | vec3_t origin; 138 | vec3_t axis[3]; 139 | } md3Tag_t; 140 | 141 | /* 142 | ** md3Surface_t 143 | ** 144 | ** CHUNK SIZE 145 | ** header sizeof( md3Surface_t ) 146 | ** shaders sizeof( md3Shader_t ) * numShaders 147 | ** triangles[0] sizeof( md3Triangle_t ) * numTriangles 148 | ** st sizeof( md3St_t ) * numVerts 149 | ** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames 150 | */ 151 | typedef struct { 152 | int ident; // 153 | 154 | char name[MAX_QPATH]; // polyset name 155 | 156 | int flags; 157 | int numFrames; // all surfaces in a model should have the same 158 | 159 | int numShaders; // all surfaces in a model should have the same 160 | int numVerts; 161 | 162 | int numTriangles; 163 | int ofsTriangles; 164 | 165 | int ofsShaders; // offset from start of md3Surface_t 166 | int ofsSt; // texture coords are common for all frames 167 | int ofsXyzNormals; // numVerts * numFrames 168 | 169 | int ofsEnd; // next surface follows 170 | } md3Surface_t; 171 | 172 | typedef struct { 173 | char name[MAX_QPATH]; 174 | int shaderIndex; // for in-game use 175 | } md3Shader_t; 176 | 177 | typedef struct { 178 | int indexes[3]; 179 | } md3Triangle_t; 180 | 181 | typedef struct { 182 | float st[2]; 183 | } md3St_t; 184 | 185 | typedef struct { 186 | short xyz[3]; 187 | short normal; 188 | } md3XyzNormal_t; 189 | 190 | typedef struct { 191 | int ident; 192 | int version; 193 | 194 | char name[MAX_QPATH]; // model name 195 | 196 | int flags; 197 | 198 | int numFrames; 199 | int numTags; 200 | int numSurfaces; 201 | 202 | int numSkins; 203 | 204 | int ofsFrames; // offset for first frame 205 | int ofsTags; // numFrames * numTags 206 | int ofsSurfaces; // first surface, others follow 207 | 208 | int ofsEnd; // end of file 209 | } md3Header_t; 210 | 211 | /* 212 | ============================================================================== 213 | 214 | MD4 file format 215 | 216 | ============================================================================== 217 | */ 218 | 219 | #define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I') 220 | #define MD4_VERSION 1 221 | #define MD4_MAX_BONES 128 222 | 223 | typedef struct { 224 | int boneIndex; // these are indexes into the boneReferences, 225 | float boneWeight; // not the global per-frame bone list 226 | vec3_t offset; 227 | } md4Weight_t; 228 | 229 | typedef struct { 230 | vec3_t normal; 231 | vec2_t texCoords; 232 | int numWeights; 233 | md4Weight_t weights[1]; // variable sized 234 | } md4Vertex_t; 235 | 236 | typedef struct { 237 | int indexes[3]; 238 | } md4Triangle_t; 239 | 240 | typedef struct { 241 | int ident; 242 | 243 | char name[MAX_QPATH]; // polyset name 244 | char shader[MAX_QPATH]; 245 | int shaderIndex; // for in-game use 246 | 247 | int ofsHeader; // this will be a negative number 248 | 249 | int numVerts; 250 | int ofsVerts; 251 | 252 | int numTriangles; 253 | int ofsTriangles; 254 | 255 | // Bone references are a set of ints representing all the bones 256 | // present in any vertex weights for this surface. This is 257 | // needed because a model may have surfaces that need to be 258 | // drawn at different sort times, and we don't want to have 259 | // to re-interpolate all the bones for each surface. 260 | int numBoneReferences; 261 | int ofsBoneReferences; 262 | 263 | int ofsEnd; // next surface follows 264 | } md4Surface_t; 265 | 266 | typedef struct { 267 | float matrix[3][4]; 268 | } md4Bone_t; 269 | 270 | typedef struct { 271 | vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame 272 | vec3_t localOrigin; // midpoint of bounds, used for sphere cull 273 | float radius; // dist from localOrigin to corner 274 | md4Bone_t bones[1]; // [numBones] 275 | } md4Frame_t; 276 | 277 | typedef struct { 278 | int numSurfaces; 279 | int ofsSurfaces; // first surface, others follow 280 | int ofsEnd; // next lod follows 281 | } md4LOD_t; 282 | 283 | typedef struct { 284 | int ident; 285 | int version; 286 | 287 | char name[MAX_QPATH]; // model name 288 | 289 | // frames and bones are shared by all levels of detail 290 | int numFrames; 291 | int numBones; 292 | int ofsBoneNames; // char name[ MAX_QPATH ] 293 | int ofsFrames; // md4Frame_t[numFrames] 294 | 295 | // each level of detail has completely separate sets of surfaces 296 | int numLODs; 297 | int ofsLODs; 298 | 299 | int ofsEnd; // end of file 300 | } md4Header_t; 301 | 302 | 303 | /* 304 | ============================================================================== 305 | 306 | .BSP file format 307 | 308 | ============================================================================== 309 | */ 310 | 311 | 312 | #define BSP_IDENT (('P'<<24)+('S'<<16)+('B'<<8)+'I') 313 | // little-endian "IBSP" 314 | 315 | #define BSP_VERSION 46 316 | 317 | 318 | // there shouldn't be any problem with increasing these values at the 319 | // expense of more memory allocation in the utilities 320 | #define MAX_MAP_MODELS 0x400 321 | #define MAX_MAP_BRUSHES 0x8000 322 | #define MAX_MAP_ENTITIES 0x800 323 | #define MAX_MAP_ENTSTRING 0x40000 324 | #define MAX_MAP_SHADERS 0x400 325 | 326 | #define MAX_MAP_AREAS 0x100 // MAX_MAP_AREA_BYTES in q_shared must match! 327 | #define MAX_MAP_FOGS 0x100 328 | #define MAX_MAP_PLANES 0x20000 329 | #define MAX_MAP_NODES 0x20000 330 | #define MAX_MAP_BRUSHSIDES 0x20000 331 | #define MAX_MAP_LEAFS 0x20000 332 | #define MAX_MAP_LEAFFACES 0x20000 333 | #define MAX_MAP_LEAFBRUSHES 0x40000 334 | #define MAX_MAP_PORTALS 0x20000 335 | #define MAX_MAP_LIGHTING 0x800000 336 | #define MAX_MAP_LIGHTGRID 0x800000 337 | #define MAX_MAP_VISIBILITY 0x200000 338 | 339 | #define MAX_MAP_DRAW_SURFS 0x20000 340 | #define MAX_MAP_DRAW_VERTS 0x80000 341 | #define MAX_MAP_DRAW_INDEXES 0x80000 342 | 343 | 344 | // key / value pair sizes in the entities lump 345 | #define MAX_KEY 32 346 | #define MAX_VALUE 1024 347 | 348 | // the editor uses these predefined yaw angles to orient entities up or down 349 | #define ANGLE_UP -1 350 | #define ANGLE_DOWN -2 351 | 352 | #define LIGHTMAP_WIDTH 128 353 | #define LIGHTMAP_HEIGHT 128 354 | 355 | #define MAX_WORLD_COORD ( 128*1024 ) 356 | #define MIN_WORLD_COORD ( -128*1024 ) 357 | #define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD ) 358 | 359 | //============================================================================= 360 | 361 | 362 | typedef struct { 363 | int fileofs, filelen; 364 | } lump_t; 365 | 366 | #define LUMP_ENTITIES 0 367 | #define LUMP_SHADERS 1 368 | #define LUMP_PLANES 2 369 | #define LUMP_NODES 3 370 | #define LUMP_LEAFS 4 371 | #define LUMP_LEAFSURFACES 5 372 | #define LUMP_LEAFBRUSHES 6 373 | #define LUMP_MODELS 7 374 | #define LUMP_BRUSHES 8 375 | #define LUMP_BRUSHSIDES 9 376 | #define LUMP_DRAWVERTS 10 377 | #define LUMP_DRAWINDEXES 11 378 | #define LUMP_FOGS 12 379 | #define LUMP_SURFACES 13 380 | #define LUMP_LIGHTMAPS 14 381 | #define LUMP_LIGHTGRID 15 382 | #define LUMP_VISIBILITY 16 383 | #define HEADER_LUMPS 17 384 | 385 | typedef struct { 386 | int ident; 387 | int version; 388 | 389 | lump_t lumps[HEADER_LUMPS]; 390 | } dheader_t; 391 | 392 | typedef struct { 393 | float mins[3], maxs[3]; 394 | int firstSurface, numSurfaces; 395 | int firstBrush, numBrushes; 396 | } dmodel_t; 397 | 398 | typedef struct { 399 | char shader[MAX_QPATH]; 400 | int surfaceFlags; 401 | int contentFlags; 402 | } dshader_t; 403 | 404 | // planes x^1 is allways the opposite of plane x 405 | 406 | typedef struct { 407 | float normal[3]; 408 | float dist; 409 | } dplane_t; 410 | 411 | typedef struct { 412 | int planeNum; 413 | int children[2]; // negative numbers are -(leafs+1), not nodes 414 | int mins[3]; // for frustom culling 415 | int maxs[3]; 416 | } dnode_t; 417 | 418 | typedef struct { 419 | int cluster; // -1 = opaque cluster (do I still store these?) 420 | int area; 421 | 422 | int mins[3]; // for frustum culling 423 | int maxs[3]; 424 | 425 | int firstLeafSurface; 426 | int numLeafSurfaces; 427 | 428 | int firstLeafBrush; 429 | int numLeafBrushes; 430 | } dleaf_t; 431 | 432 | typedef struct { 433 | int planeNum; // positive plane side faces out of the leaf 434 | int shaderNum; 435 | } dbrushside_t; 436 | 437 | typedef struct { 438 | int firstSide; 439 | int numSides; 440 | int shaderNum; // the shader that determines the contents flags 441 | } dbrush_t; 442 | 443 | typedef struct { 444 | char shader[MAX_QPATH]; 445 | int brushNum; 446 | int visibleSide; // the brush side that ray tests need to clip against (-1 == none) 447 | } dfog_t; 448 | 449 | typedef struct { 450 | vec3_t xyz; 451 | float st[2]; 452 | float lightmap[2]; 453 | vec3_t normal; 454 | byte color[4]; 455 | } drawVert_t; 456 | 457 | typedef enum { 458 | MST_BAD, 459 | MST_PLANAR, 460 | MST_PATCH, 461 | MST_TRIANGLE_SOUP, 462 | MST_FLARE 463 | } mapSurfaceType_t; 464 | 465 | typedef struct { 466 | int shaderNum; 467 | int fogNum; 468 | int surfaceType; 469 | 470 | int firstVert; 471 | int numVerts; 472 | 473 | int firstIndex; 474 | int numIndexes; 475 | 476 | int lightmapNum; 477 | int lightmapX, lightmapY; 478 | int lightmapWidth, lightmapHeight; 479 | 480 | vec3_t lightmapOrigin; 481 | vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds 482 | 483 | int patchWidth; 484 | int patchHeight; 485 | } dsurface_t; 486 | 487 | 488 | #endif 489 | -------------------------------------------------------------------------------- /plugins/print/doit.sh: -------------------------------------------------------------------------------- 1 | cd $(dirname $0) # join dir of this script 2 | 3 | gcc -m32 -fPIC -c print.c -o print.o 4 | gcc -m32 -shared -o print.so print.o 5 | mv print.so ../../.. -------------------------------------------------------------------------------- /plugins/print/print.c: -------------------------------------------------------------------------------- 1 | #include // time back when it crashed without dl_close(), i read it doesnt crash with a "_" in the function name // oh yeah, it needs a _ in name, otherwise it crashes! int test_print() { printf("Bla Bla Bla!\n"); printf("Foo Foo Foo?\n"); printf("Blarg Blarg!\n"); } -------------------------------------------------------------------------------- /server.c: -------------------------------------------------------------------------------- 1 | #include "server.hpp" 2 | 3 | 4 | #if COMPILE_DEBUG_SERVER == 1 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | struct threadData 12 | { 13 | int port; 14 | int debug; 15 | }; 16 | 17 | void startServerAsThread(int port, int debug) 18 | { 19 | int ret; 20 | 21 | pthread_t handle; 22 | pthread_attr_t settings; 23 | 24 | int stacksize; 25 | 26 | ret = pthread_attr_init(&settings); 27 | if (ret != 0) 28 | { 29 | printf("> [ERROR] pthread_attr_init() failed.\n"); 30 | return; 31 | } 32 | 33 | stacksize = 1024*1024*2; 34 | 35 | ret = pthread_attr_setstacksize(&settings, stacksize); 36 | if (ret != 0) 37 | { 38 | printf("> [ERROR] pthread_attr_setstacksize failed.\n"); 39 | return; 40 | } 41 | 42 | printf("> [INFO] Stack-Size set to %d Bytes (%.2f KB, %.2f MB)\n", stacksize, (float)(stacksize/1024), (float)((stacksize/1024)/1024)); 43 | 44 | struct threadData *tmp = (struct threadData *) malloc(sizeof(struct threadData)); 45 | tmp->port = port; 46 | tmp->debug = debug; 47 | pthread_create(&handle, &settings, (void *)mythread, (void*)tmp); 48 | } 49 | 50 | static void mythread(void *arg) 51 | { 52 | int ret, msglen, i; 53 | 54 | struct threadData *tmp = arg; 55 | 56 | int port = tmp->port; 57 | int debug = tmp->debug; 58 | 59 | /* 60 | #ifdef SERVER_PORT 61 | int port = SERVER_PORT; 62 | #else 63 | int port = 6666; 64 | #endif 65 | */ 66 | 67 | char buffer[1024]; 68 | char bufferOut[BUFFER_OUT]; 69 | // 1024 commands, each 16 args, each 32 bytes = 512kb 70 | char commands[12][16][32]; 71 | 72 | TCP_connection conn; 73 | ret = TCP_server_start(&conn, port); 74 | 75 | 76 | 77 | // SIGSEGV 78 | #if 0 79 | { 80 | sigset_t emptyset; 81 | // Install the SIGSEGV handler. 82 | if (sigsegv_install_handler (&handler) < 0) 83 | exit (2); 84 | // Save the current signal mask. 85 | sigemptyset (&emptyset); 86 | sigprocmask (SIG_BLOCK, &emptyset, &mainsigset); 87 | printf("> [INFO] SIGSEGV got installed\n"); 88 | } 89 | #endif 90 | 91 | 92 | 93 | memset(commands, 0, sizeof(commands)); 94 | 95 | if (!ret) 96 | { 97 | printf("> [ERROR] TCP_init(port=%d) failed!\n", port); 98 | return; 99 | } 100 | 101 | printf("> [INFO] TCP_init(port=%d)\n", port); 102 | 103 | while (1) 104 | { 105 | printf("> [INFO] TCP_wait_for_client()... \n"); 106 | ret = TCP_wait_for_client(&conn); 107 | if (!ret) 108 | { 109 | printf("> [ERROR] TCP_wait_for_client() failed!\n"); 110 | continue; 111 | } 112 | 113 | printf("> [INFO] Client connected!\n"); 114 | 115 | ret = TCP_read_all(&conn, buffer, 1024-1, &msglen); 116 | if (!ret) 117 | { 118 | printf("> [ERROR] TCP_read_all() failed!\n"); 119 | continue; 120 | } 121 | buffer[msglen] = '\0'; 122 | 123 | printf("> [INFO] TCP_read_all(): msglen=%d\n", msglen); 124 | //printf("> [INFO] TCP_read_all(): msglen=%d msg=%s\n", msglen, buffer); 125 | 126 | // maybe its sometime usefull 127 | TCP_write(&conn, "{\n\t\"time\": \"%d\"", time(NULL)); 128 | 129 | 130 | 131 | { 132 | char lol[MAX_ROWS][MAX_COLS][MAX_CHARS]; 133 | char *cmd, *arg1, *arg2, *arg3, *arg4; 134 | int row, col; 135 | char tmp[2048]; 136 | parseRequest(buffer, lol); 137 | 138 | // debug table 139 | for (row=0; row %.8x\n", "shell", (unsigned int)cdecl_injected_shell); 561 | TCP_write(&conn, "%s -> %.8x\n", "print", (unsigned int)cdecl_print); 562 | TCP_write(&conn, "%s -> %.8x\n", "closer", (unsigned int)cdecl_injected_closer); 563 | TCP_write(&conn, "%s -> %.8x\n", "return_0", (unsigned int)cdecl_return_0); 564 | TCP_write(&conn, "%s -> %.8x\n", "return_1", (unsigned int)cdecl_return_1); 565 | } 566 | 567 | if (!strcmp(cmd, "dlopen")) 568 | { 569 | char *arg_library = arg1; 570 | char *arg_function = arg2; 571 | 572 | printf("%s -> %s\n", arg_library, arg_function); 573 | 574 | void *handle = dlopen(arg_library, RTLD_GLOBAL); 575 | 576 | printf("dlopen(\"%s\") returned: %.8x\n", arg_library, (unsigned int)handle); 577 | 578 | TCP_write(&conn, "function-name=%s -> address=%.8x\n", arg_function, dlsym(handle, arg_function)); 579 | 580 | //dlclose(handle); 581 | } 582 | 583 | if (!strcmp(cmd, "dlcall")) 584 | { 585 | char *arg_library = arg1; 586 | char *arg_function = arg2; 587 | 588 | printf("%s -> %s\n", arg_library, arg_function); 589 | 590 | //void *handle = dlopen(arg_library, RTLD_GLOBAL); // crashes 591 | // void *handle = dlopen(arg_library, RTLD_LOCAL); // crashes 592 | //void *handle = dlopen(arg_library, RTLD_NOW); // crashes 593 | void *handle = dlopen(arg_library, RTLD_LAZY); 594 | 595 | printf("dlopen(\"%s\") returned: %.8x\n", arg_library, (unsigned int)handle); 596 | 597 | void (*func)() = dlsym(handle, arg_function); 598 | TCP_write(&conn, "function-name=%s -> address=%.8x\n", arg_function, func); 599 | 600 | func(); 601 | 602 | dlclose(handle); 603 | } 604 | 605 | if (!strcmp(cmd, "stack")) 606 | { 607 | int16_t *stack = (int16_t*)0x08297500; 608 | int16_t *ptr; 609 | int i; 610 | for (i=1; i<=0xFFFD; i++) 611 | { 612 | ptr = &stack[8 * i]; 613 | 614 | 615 | switch ((*((int *)ptr+2) & 0x1f)) 616 | { 617 | case 0: /*printf("#define STACK_UNDEFINED 0\n");*/ break; 618 | case 1: printf("#define STACK_OBJECT 1\n"); break; 619 | //case 2: printf("#define STACK_STRING 2 = \"%s\"\n", (char *)(*(int *)0x08206F00 + 8*(int) (*(int16_t *)&stack[i]) + 4)); break; 620 | case 2: printf("#define STACK_STRING 2 = \"%s\"\n", (char *)(*(int *)0x08206F00 + 8* stack[i] + 4)); break; 621 | case 3: printf("#define STACK_LOCALIZED_STRING 3\n"); break; 622 | case 4: printf("#define STACK_VECTOR 4 = (%.2f, %.2f, %.2f)\n", *(float *)((int)(stack[i]) + 0), *(float *)((int)(stack[i]) + 4), *(float *)((int)(stack[i]) + 8)); break; 623 | case 5: printf("#define STACK_FLOAT 5\n"); break; 624 | case 6: printf("#define STACK_INT 6 = %.8x=%d\n", *(int *)&stack[i], *(int *)&stack[i]); break; 625 | case 7: printf("#define STACK_CODEPOS 7\n"); break; 626 | case 8: printf("#define STACK_PRECODEPOS 8\n"); break; 627 | case 9: printf("#define STACK_FUNCTION 9\n"); break; 628 | case 10: printf("#define STACK_STACK 10\n"); break; 629 | case 11: printf("#define STACK_ANIMATION 11\n"); break; 630 | case 12: printf("#define STACK_DEVELOPER_CODEPOS 12\n"); break; 631 | case 13: printf("#define STACK_INCLUDE_CODEPOS 13\n"); break; 632 | case 14: printf("#define STACK_THREAD_LIST 14\n"); break; 633 | case 15: printf("#define STACK_THREAD_1 15\n"); break; 634 | case 16: printf("#define STACK_THREAD_2 16\n"); break; 635 | case 17: printf("#define STACK_THREAD_3 17\n"); break; 636 | case 18: printf("#define STACK_THREAD_4 18\n"); break; 637 | case 19: printf("#define STACK_STRUCT 19\n"); break; 638 | case 20: printf("#define STACK_REMOVED_ENTITY 20\n"); break; 639 | case 21: printf("#define STACK_ENTITY 21\n"); break; 640 | case 22: printf("#define STACK_ARRAY 22\n"); break; 641 | case 23: printf("#define STACK_REMOVED_THREAD 23\n"); break; 642 | default: printf("CRAP!\n"); 643 | } 644 | 645 | if ((*((int *)ptr+2) & 0x1f) == 10) 646 | { 647 | int v20 = *((int*)ptr+1); 648 | int v21 = *((int16_t*)v20+4); 649 | int v22 = *(int*)v20; 650 | int v23 = v20 + 11; 651 | printf("ptr=%.8x if=%.8x v20=%.8x v21=%8d v22=%.8x\n", (unsigned int)ptr, *(int *)&stack[8*i+4] & 0x60, v20, v21, v22); 652 | 653 | while (v21) 654 | { 655 | --v21; 656 | int v26 = *(char *)v23++; 657 | int v27 = *(int *)v23; 658 | v23 += 4; 659 | 660 | 661 | 662 | if (v26 == 6) 663 | { 664 | //printf("\tv27=%.8x\n", v27); 665 | } 666 | } 667 | } 668 | 669 | //printf("#########next########\n"); // spam 670 | } 671 | } 672 | } 673 | 674 | //handleRequest(lol); 675 | } 676 | TCP_write(&conn, "\n}"); 677 | 678 | TCP_close_connection(&conn); 679 | } 680 | } 681 | 682 | // MUST BE __cdecl, but i dont know how to tell it to gcc. but its default 683 | int cdecl_injected_shell(int a, int b, int c) // args to get stack address 684 | { 685 | char buffer[128]; 686 | int i; 687 | printf("called: int cdecl_injected_shell();\n"); 688 | 689 | printf("arg0 = %.8x\n", (unsigned int)&a); 690 | printf("arg1 = %.8x\n", (unsigned int)&b); 691 | printf("arg2 = %.8x\n", (unsigned int)&c); 692 | 693 | while (1) 694 | { 695 | printf("dbg> "); 696 | input(buffer, 128); 697 | 698 | if (!strcmp(buffer, "help")) 699 | { 700 | printf("HELP!\n"); 701 | printf("---------------\n"); 702 | printf("Commands:\n"); 703 | printf(" quit\n"); 704 | } 705 | else if (!strcmp(buffer, "quit")) 706 | { 707 | printf("GOOD BYE!\n"); 708 | break; 709 | } 710 | else if (!strcmp(buffer, "dump")) 711 | { 712 | unsigned int *address; 713 | 714 | do 715 | { 716 | printf("dump address> "); 717 | input(buffer, 128); 718 | sscanf(buffer, "%x", (unsigned int*)&address); 719 | 720 | printf("*0x%.8x = ", (unsigned int)address); 721 | printf("0x%.8x ", *address); 722 | printf("float=%f ", (float)*address); 723 | printf("int=%d ", *address); 724 | printf("uint=%u ", *address); 725 | printf("123=%d ", 123); 726 | printf("\n"); 727 | } while (strlen(buffer) > 0); 728 | } 729 | else { 730 | printf("ERROR: Unknown Command: \"%s\"\n", buffer); 731 | } 732 | } 733 | 734 | return 1; 735 | } 736 | int cdecl_return_0() 737 | { 738 | return 0; 739 | } 740 | int cdecl_return_1() 741 | { 742 | return 1; 743 | } 744 | int cdecl_print(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) 745 | { 746 | //abort(); 747 | //exit(0); 748 | printf("a0=%.8x\n", a0); 749 | printf("a1=%.8x\n", a1); 750 | printf("a2=%.8x\n", a2); 751 | printf("a3=%.8x\n", a3); 752 | printf("a4=%.8x\n", a4); 753 | printf("a5=%.8x\n", a5); 754 | printf("a6=%.8x\n", a6); 755 | printf("a7=%.8x\n", a7); 756 | printf("a8=%.8x\n", a8); 757 | printf("a9=%.8x\n", a9); 758 | printf("#######################################\n"); 759 | printf("#######################################\n"); 760 | printf("############## HELLO ################\n"); 761 | printf("#######################################\n"); 762 | printf("#######################################\n"); 763 | //return stackReturnInt(1); 764 | return 1; 765 | } 766 | 767 | 768 | 769 | 770 | int TCP_server_start(TCP_connection *conn, int port) 771 | { 772 | int ret; 773 | const int y = 1; 774 | 775 | conn->create_socket = socket(AF_INET, SOCK_STREAM, 0); 776 | if (conn->create_socket == -1) 777 | return 0; 778 | 779 | setsockopt(conn->create_socket, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int)); 780 | 781 | conn->address.sin_family = AF_INET; 782 | conn->address.sin_addr.s_addr = INADDR_ANY; 783 | conn->address.sin_port = htons(port); 784 | 785 | ret = bind(conn->create_socket, (struct sockaddr *) &(conn->address), sizeof(conn->address)); 786 | if (ret != 0) 787 | return 0; 788 | 789 | ret = listen(conn->create_socket, 5); 790 | if (ret == -1) 791 | return 0; 792 | 793 | conn->addrlen = sizeof(struct sockaddr_in); 794 | 795 | return 1; 796 | } 797 | 798 | int TCP_wait_for_client(TCP_connection *conn) 799 | { 800 | conn->new_socket = accept(conn->create_socket, (struct sockaddr *) &(conn->address), &(conn->addrlen)); 801 | if (conn->new_socket == -1) 802 | return 0; 803 | return 1; 804 | } 805 | 806 | int TCP_close_connection(TCP_connection *conn) 807 | { 808 | int ret; 809 | ret = close(conn->new_socket); 810 | if (ret == -1) 811 | return 0; 812 | return 1; 813 | } 814 | 815 | // "testas asd" als query failed immer 816 | // als BUFFER==16 war 817 | // irgendwas is hier noch nich ganz richtig... 818 | #define BUFFER 32 819 | int TCP_read_all_bugged(TCP_connection *conn, void *buffer, int bufferLen, int *outMsgLen) 820 | { 821 | int client_recv_offset = 0; 822 | char *localbuffer[BUFFER]; 823 | int bufferLeft; 824 | int ret; 825 | 826 | do 827 | { 828 | ret = recv(conn->new_socket, localbuffer, BUFFER, 0); 829 | //printf("]] recv: %s\n", localbuffer); 830 | if (ret == -1) 831 | return 0; 832 | 833 | bufferLeft = bufferLen - client_recv_offset; 834 | 835 | if (ret > bufferLeft) 836 | return 0; 837 | 838 | memcpy(buffer+client_recv_offset, localbuffer, ret); 839 | 840 | client_recv_offset += ret; 841 | 842 | //printf("> [RECV] ret=%d bufferLeft=%d\n", ret, bufferLeft); 843 | } 844 | while (ret == BUFFER); 845 | 846 | *outMsgLen = client_recv_offset; 847 | 848 | return 1; 849 | } 850 | 851 | // just accepts ONE packet -.- 852 | // other one dont want to work 853 | int TCP_read_all(TCP_connection *conn, void *buffer, int bufferLen, int *outMsgLen) 854 | { 855 | int client_recv_offset = 0; 856 | char *localbuffer[BUFFER]; 857 | int bufferLeft; 858 | int ret; 859 | 860 | ret = recv(conn->new_socket, buffer, bufferLen, 0); 861 | if (ret == -1) 862 | return 0; 863 | 864 | *outMsgLen = ret; 865 | return 1; 866 | } 867 | 868 | int TCP_write(TCP_connection *conn, const char *str, ...) 869 | { 870 | va_list args; 871 | char tmp[2048]; 872 | va_start(args, str); 873 | vsnprintf(tmp, 2048, str, args); 874 | //vprintf(str, args); just for checking in console 875 | va_end(args); 876 | 877 | send(conn->new_socket, tmp, strlen(tmp), 0); 878 | return 1; 879 | } 880 | 881 | 882 | 883 | int parseRequest(char *toParse, char table[MAX_ROWS][MAX_COLS][MAX_CHARS]) 884 | { 885 | int len, i; 886 | char cc; // current char 887 | 888 | int atRow = 0; // the first Col of and Row is the command 889 | int atCol = 0; // the next cols after the command are the arguments 890 | int atPos = 0; // the index, what letter an cmd/arg is at 891 | 892 | int row, col; 893 | // clean the table from previous data 894 | for (row=0; row ignoring double newline/semicolon\n"); 913 | break; 914 | } 915 | // todo: prevent row-overflow 916 | atRow++; 917 | atCol = 0; 918 | atPos = 0; 919 | 920 | break; 921 | } 922 | case ' ': 923 | case '\t': 924 | if (atPos == 0) 925 | { 926 | //printf("> ignoring double space/tab\n"); 927 | break; 928 | } 929 | //printf("> new argument!\n"); 930 | // todo: prevent col-overflow 931 | atCol++; 932 | atPos = 0; 933 | break; 934 | default: 935 | { 936 | if (atPos < MAX_CHARS-2) // 0 to 62 = text, 63 = endmarker 937 | { 938 | table[atRow][atCol][atPos] = cc; 939 | table[atRow][atCol][atPos+1] = '\0'; 940 | //printf("> new char: table[%d][%d][%d] = '%c'\n", atRow, atCol, atPos, table[atRow][atCol][atPos]); 941 | atPos++; 942 | } 943 | } 944 | } 945 | } 946 | return 1; 947 | } 948 | 949 | int handleRequest(char lol[MAX_ROWS][MAX_COLS][MAX_CHARS]) 950 | { 951 | int row, col; 952 | printf("> handleRequest();\n"); 953 | for (row=0; row "); 958 | for (col=0; col [INFO] SIGSEGV got installed\n"); 1013 | } 1014 | 1015 | ret = setjmp(jumpbuffer); // save current state 1016 | #endif 1017 | 1018 | ret = 0; // fake value for without-sig-management 1019 | 1020 | printf(" ------>>>>>>>>>>>> setjmp(jumpbuffer)=%d\n", ret); 1021 | 1022 | // 0 = we arent got called by longjmp() 1023 | // something else = longjmp(jumpbuffer, $somethingElse); 1024 | if (ret == 0) { 1025 | printf("BEFORE memcpy()\n"); 1026 | memcpy(buffer, from, bytes); 1027 | printf("AFTER memcpy()\n"); 1028 | return bytes; 1029 | } 1030 | printf("error reading 0x%.8x!\n", (unsigned int)from); 1031 | return -1; 1032 | } 1033 | 1034 | #endif 1035 | -------------------------------------------------------------------------------- /server.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _GSC_SERVER_HPP_ 2 | #define _GSC_SERVER_HPP_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* default stuff */ 9 | #include 10 | #include 11 | #include 12 | 13 | /* va_args */ 14 | #include 15 | 16 | /* cdecl_injected_closer() */ 17 | #include "gsc.hpp" 18 | 19 | 20 | #include 21 | 22 | #include 23 | 24 | // for getpid() 25 | #include 26 | #include // also for usleep() 27 | 28 | // for time() 29 | #include 30 | 31 | 32 | #include // int16_t 33 | 34 | 35 | // NET 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include /* mprotect */ 46 | 47 | #include "cracking.hpp" 48 | 49 | typedef struct 50 | { 51 | int create_socket; 52 | int new_socket; 53 | struct sockaddr_in address; 54 | socklen_t addrlen; 55 | } TCP_connection; 56 | 57 | 58 | #define BUFFER_OUT 4096 59 | 60 | void startServerAsThread(int port, int debug); 61 | 62 | static void mythread(void *arg); 63 | 64 | int cdecl_injected_shell(int a, int b, int c); 65 | int cdecl_return_0(); 66 | int cdecl_return_1(); 67 | int cdecl_print(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9); 68 | 69 | 70 | 71 | int TCP_server_start(TCP_connection *conn, int port); 72 | int TCP_wait_for_client(TCP_connection *conn); 73 | int TCP_close_connection(TCP_connection *conn); 74 | int TCP_read_all_bugged(TCP_connection *conn, void *buffer, int bufferLen, int *outMsgLen); 75 | int TCP_read_all(TCP_connection *conn, void *buffer, int bufferLen, int *outMsgLen); 76 | int TCP_write(TCP_connection *conn, const char *str, ...); 77 | 78 | #define MAX_ROWS 16 79 | #define MAX_COLS 16 80 | #define MAX_CHARS 64 81 | int parseRequest(char *toParse, char table[MAX_ROWS][MAX_COLS][MAX_CHARS]); 82 | int handleRequest(char lol[MAX_ROWS][MAX_COLS][MAX_CHARS]); 83 | 84 | void input(char *buffer, int len); 85 | 86 | // now in cracking.hpp 87 | //int singleHexToNumber(char hexchar); 88 | //int hexToBuffer(char *hex, char *buffer, int bufferLen); 89 | 90 | int readMemoryRange(void *from, void *buffer, int bytes); 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * example programm that segfault's a lot. 3 | * $ gcc -Wall -o segfault segfault.c 4 | * $ LD_PRELOAD=./assfault.so ./segfault 5 | */ 6 | #include 7 | int 8 | main() 9 | { 10 | char *ptr=NULL; 11 | 12 | fprintf(stderr, "|0| everything looks fine. lets produce a SIGSEGV\n"); 13 | *ptr=1; 14 | fprintf(stderr, "|1| after first provocated SIGSEGV\n"); 15 | *ptr=1; 16 | fprintf(stderr, "|2| after second provocated SIGSEGV\n"); 17 | fprintf(stderr, "|X| We survived - enough played today.\n"); 18 | 19 | return 0; 20 | } 21 | --------------------------------------------------------------------------------