Changeset 124:1950c7262178
- Timestamp:
- 04/26/08 01:24:46 (2 years ago)
- Parents:
- 123:f8fbc6efbe8c (diff), 120:741877695bd7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Branch:
- mergetrem
- Files:
-
- 1 removed
- 59 modified
-
Makefile (modified) (9 diffs)
-
Makefile (modified) (14 diffs)
-
misc/server.cfg (deleted)
-
src/cgame/cg_animmapobj.c (modified) (2 diffs)
-
src/cgame/cg_animmapobj.c (modified) (2 diffs)
-
src/cgame/cg_buildable.c (modified) (1 diff)
-
src/cgame/cg_buildable.c (modified) (2 diffs)
-
src/cgame/cg_local.h (modified) (1 diff)
-
src/cgame/cg_local.h (modified) (3 diffs)
-
src/cgame/cg_main.c (modified) (3 diffs)
-
src/cgame/cg_main.c (modified) (1 diff)
-
src/cgame/cg_players.c (modified) (1 diff)
-
src/cgame/cg_players.c (modified) (2 diffs)
-
src/cgame/cg_predict.c (modified) (1 diff)
-
src/cgame/cg_predict.c (modified) (1 diff)
-
src/cgame/cg_weapons.c (modified) (1 diff)
-
src/cgame/cg_weapons.c (modified) (7 diffs)
-
src/client/cl_main.c (modified) (4 diffs)
-
src/client/cl_main.c (modified) (4 diffs)
-
src/game/bg_misc.c (modified) (22 diffs)
-
src/game/bg_misc.c (modified) (11 diffs)
-
src/game/bg_pmove.c (modified) (12 diffs)
-
src/game/bg_pmove.c (modified) (12 diffs)
-
src/game/bg_public.h (modified) (10 diffs)
-
src/game/bg_public.h (modified) (2 diffs)
-
src/game/g_active.c (modified) (18 diffs)
-
src/game/g_active.c (modified) (12 diffs)
-
src/game/g_admin.c (modified) (38 diffs)
-
src/game/g_admin.c (modified) (84 diffs)
-
src/game/g_admin.h (modified) (5 diffs)
-
src/game/g_admin.h (modified) (2 diffs)
-
src/game/g_buildable.c (modified) (24 diffs)
-
src/game/g_buildable.c (modified) (34 diffs)
-
src/game/g_client.c (modified) (21 diffs)
-
src/game/g_client.c (modified) (4 diffs)
-
src/game/g_cmds.c (modified) (70 diffs)
-
src/game/g_cmds.c (modified) (56 diffs)
-
src/game/g_combat.c (modified) (11 diffs)
-
src/game/g_combat.c (modified) (5 diffs)
-
src/game/g_local.h (modified) (23 diffs)
-
src/game/g_local.h (modified) (1 diff)
-
src/game/g_main.c (modified) (37 diffs)
-
src/game/g_main.c (modified) (9 diffs)
-
src/game/g_svcmds.c (modified) (2 diffs)
-
src/game/g_svcmds.c (modified) (1 diff)
-
src/qcommon/common.c (modified) (4 diffs)
-
src/qcommon/common.c (modified) (3 diffs)
-
src/qcommon/cvar.c (modified) (1 diff)
-
src/qcommon/cvar.c (modified) (1 diff)
-
src/qcommon/files.c (modified) (3 diffs)
-
src/qcommon/files.c (modified) (3 diffs)
-
src/qcommon/msg.c (modified) (8 diffs)
-
src/qcommon/q_shared.h (modified) (10 diffs)
-
src/qcommon/q_shared.h (modified) (2 diffs)
-
src/qcommon/qcommon.h (modified) (3 diffs)
-
src/qcommon/qcommon.h (modified) (2 diffs)
-
src/server/sv_init.c (modified) (1 diff)
-
src/server/sv_init.c (modified) (2 diffs)
-
src/ui/ui_main.c (modified) (1 diff)
-
src/ui/ui_main.c (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r120 r124 213 213 endif 214 214 215 OPTIMIZE = -O 3 -ffast-math-funroll-loops -fomit-frame-pointer215 OPTIMIZE = -O2 -funroll-loops -fomit-frame-pointer 216 216 217 217 ifeq ($(ARCH),x86_64) 218 OPTIMIZE = -O 3 -fomit-frame-pointer -ffast-math-funroll-loops \218 OPTIMIZE = -O2 -fomit-frame-pointer -funroll-loops \ 219 219 -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 220 220 -fstrength-reduce … … 223 223 else 224 224 ifeq ($(ARCH),x86) 225 OPTIMIZE = -O 3 -march=i586 -fomit-frame-pointer -ffast-math\225 OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 226 226 -funroll-loops -falign-loops=2 -falign-jumps=2 \ 227 227 -falign-functions=2 -fstrength-reduce … … 295 295 296 296 ifeq ($(ARCH),ppc) 297 OPTIMIZE += -faltivec -O 3297 OPTIMIZE += -faltivec -O2 298 298 endif 299 299 ifeq ($(ARCH),x86) … … 342 342 $(LIBSDIR)/macosx/libSDL-1.2.0.dylib 343 343 344 OPTIMIZE += -f fast-math -falign-loops=16344 OPTIMIZE += -falign-loops=16 345 345 346 346 ifneq ($(HAVE_VM_COMPILED),true) … … 397 397 endif 398 398 399 OPTIMIZE = -O 3 -march=i586 -fno-omit-frame-pointer -ffast-math\399 OPTIMIZE = -O2 -march=i586 -fno-omit-frame-pointer \ 400 400 -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ 401 401 -fstrength-reduce … … 469 469 ifeq ($(ARCH),axp) 470 470 BASE_CFLAGS += -DNO_VM_COMPILED 471 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3 -ffast-math-funroll-loops \471 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -funroll-loops \ 472 472 -fomit-frame-pointer -fexpensive-optimizations 473 473 else 474 474 ifeq ($(ARCH),x86) 475 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3-mtune=pentiumpro \476 -march=pentium -fomit-frame-pointer -pipe -ffast-math\475 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -mtune=pentiumpro \ 476 -march=pentium -fomit-frame-pointer -pipe \ 477 477 -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 478 478 -funroll-loops -fstrength-reduce … … 650 650 -pipe -DUSE_ICON $(shell sdl-config --cflags) 651 651 652 OPTIMIZE = -O 3 -ffast-math-funroll-loops652 OPTIMIZE = -O2 -funroll-loops 653 653 654 654 ifeq ($(ARCH),sparc) 655 OPTIMIZE = -O 3 -ffast-math-falign-loops=2 \655 OPTIMIZE = -O2 -falign-loops=2 \ 656 656 -falign-jumps=2 -falign-functions=2 -fstrength-reduce \ 657 657 -mtune=ultrasparc -mv8plus -mno-faster-structs \ … … 659 659 else 660 660 ifeq ($(ARCH),x86) 661 OPTIMIZE = -O 3 -march=i586 -fomit-frame-pointer -ffast-math\661 OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 662 662 -funroll-loops -falign-loops=2 -falign-jumps=2 \ 663 663 -falign-functions=2 -fstrength-reduce … … 696 696 BASE_CFLAGS=-DNO_VM_COMPILED 697 697 DEBUG_CFLAGS=$(BASE_CFLAGS) -g 698 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3698 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 699 699 700 700 SHLIBEXT=so -
Makefile
r123 r124 7 7 COMPILE_PLATFORM=$(shell uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]') 8 8 9 COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/) 10 11 ifeq ($(COMPILE_PLATFORM),sunos) 12 # Solaris uname and GNU uname differ 13 COMPILE_ARCH=$(shell uname -p | sed -e s/i.86/x86/) 14 endif 9 15 ifeq ($(COMPILE_PLATFORM),darwin) 10 16 # Apple does some things a little differently... 11 17 COMPILE_ARCH=$(shell uname -p | sed -e s/i.86/x86/) 12 else 13 COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/) 14 endif 15 16 BUILD_CLIENT = 17 BUILD_CLIENT_SMP = 18 BUILD_SERVER = 19 BUILD_GAME_SO = 20 BUILD_GAME_QVM = 18 endif 19 20 ifndef BUILD_CLIENT 21 BUILD_CLIENT = 22 endif 23 ifndef BUILD_CLIENT_SMP 24 BUILD_CLIENT_SMP = 25 endif 26 ifndef BUILD_SERVER 27 BUILD_SERVER = 28 endif 29 ifndef BUILD_GAME_SO 30 BUILD_GAME_SO = 31 endif 32 ifndef BUILD_GAME_QVM 33 BUILD_GAME_QVM = 34 endif 21 35 22 36 ifneq ($(PLATFORM),darwin) … … 272 286 ifeq ($(PLATFORM),darwin) 273 287 HAVE_VM_COMPILED=true 274 BASE_CFLAGS=275 288 CLIENT_LDFLAGS= 276 LDFLAGS=277 289 OPTIMIZE= 278 ifeq ($(BUILD_MACOSX_UB),ppc) 279 CC=gcc-3.3 280 BASE_CFLAGS += -arch ppc -DSMP \ 281 -DMAC_OS_X_VERSION_MIN_REQUIRED=1020 -nostdinc \ 282 -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks \ 283 -I/Developer/SDKs/MacOSX10.2.8.sdk/usr/include/gcc/darwin/3.3 \ 284 -isystem /Developer/SDKs/MacOSX10.2.8.sdk/usr/include 285 # when using the 10.2 SDK we are not allowed the two-level namespace so 286 # in order to get the OpenAL dlopen() stuff to work without major 287 # modifications, the controversial -m linker flag must be used. this 288 # throws a ton of multiply defined errors which cannot be suppressed. 289 LDFLAGS += -arch ppc \ 290 -L/Developer/SDKs/MacOSX10.2.8.sdk/usr/lib/gcc/darwin/3.3 \ 291 -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks \ 292 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.2.8.sdk,-m 293 ARCH=ppc 294 295 # OS X 10.2 sdk lacks dlopen() so ded would need libSDL anyway 296 BUILD_SERVER=0 297 298 # because of a problem with linking on 10.2 this will generate multiply 299 # defined symbol errors. The errors can be turned into warnings with 300 # the -m linker flag, but you can't shut up the warnings 301 USE_OPENAL_DLOPEN=1 302 else 303 ifeq ($(BUILD_MACOSX_UB),x86) 304 CC=gcc-4.0 305 BASE_CFLAGS += -arch i386 -DSMP \ 306 -mmacosx-version-min=10.4 \ 307 -DMAC_OS_X_VERSION_MIN_REQUIRED=1040 -nostdinc \ 308 -F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks \ 309 -I/Developer/SDKs/MacOSX10.4u.sdk/usr/lib/gcc/i686-apple-darwin8/4.0.1/include \ 310 -isystem /Developer/SDKs/MacOSX10.4u.sdk/usr/include 311 LDFLAGS = -arch i386 -mmacosx-version-min=10.4 \ 312 -L/Developer/SDKs/MacOSX10.4u.sdk/usr/lib/gcc/i686-apple-darwin8/4.0.1 \ 313 -F/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks \ 314 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk 315 ARCH=x86 316 BUILD_SERVER=0 317 else 318 # for whatever reason using the headers in the MacOSX SDKs tend to throw 319 # errors even though they are identical to the system ones which don't 320 # therefore we shut up warning flags when running the universal build 321 # script as much as possible. 322 BASE_CFLAGS += -Wall -Wimplicit -Wstrict-prototypes 323 endif 324 endif 290 291 # building the QVMs on MacOSX is broken, atm. 292 BUILD_GAME_QVM=0 293 294 BASE_CFLAGS = -Wall -Wimplicit -Wstrict-prototypes 325 295 326 296 ifeq ($(ARCH),ppc) … … 335 305 336 306 BASE_CFLAGS += -fno-strict-aliasing -DMACOS_X -fno-common -pipe 337 338 # Always include debug symbols...you can strip the binary later...339 BASE_CFLAGS += -gfull340 307 341 308 ifeq ($(USE_OPENAL),1) … … 633 600 ############################################################################# 634 601 635 ifeq ($(PLATFORM),irix )602 ifeq ($(PLATFORM),irix64) 636 603 637 604 ARCH=mips #default to MIPS 638 605 639 BASE_CFLAGS=-Dstricmp=strcasecmp -Xcpluscomm -woff 1185 -mips3 \ 640 -nostdinc -I. -I$(ROOT)/usr/include -DNO_VM_COMPILED 641 RELEASE_CFLAGS=$(BASE_CFLAGS) -O2 606 CC = c99 607 MKDIR = mkdir -p 608 609 BASE_CFLAGS=-Dstricmp=strcasecmp -Xcpluscomm -woff 1185 \ 610 -I. $(shell sdl-config --cflags) -I$(ROOT)/usr/include -DNO_VM_COMPILED 611 RELEASE_CFLAGS=$(BASE_CFLAGS) -O3 642 612 DEBUG_CFLAGS=$(BASE_CFLAGS) -g 643 613 … … 646 616 SHLIBLDFLAGS=-shared 647 617 648 LDFLAGS=-ldl -lm 649 CLIENT_LDFLAGS=-L/usr/X11/$(LIB) -lGL -lX11 -lXext -lm 618 LDFLAGS=-ldl -lm -lgen 619 # FIXME: The X libraries probably aren't necessary? 620 CLIENT_LDFLAGS=-L/usr/X11/$(LIB) $(shell sdl-config --libs) -lGL \ 621 -lX11 -lXext -lm 650 622 651 623 else # ifeq IRIX … … 694 666 LDFLAGS += -m32 695 667 BASE_CFLAGS += -I/usr/X11/include/NVIDIA 668 CLIENT_LDFLAGS += -L/usr/X11/lib/NVIDIA -R/usr/X11/lib/NVIDIA 696 669 endif 697 670 endif … … 714 687 BOTCFLAGS=-O0 715 688 716 CLIENT_LDFLAGS =$(shell sdl-config --libs) -lGL689 CLIENT_LDFLAGS +=$(shell sdl-config --libs) -lGL 717 690 718 691 else # ifeq sunos … … 820 793 define DO_AS 821 794 $(echo_cmd) "AS $<" 822 $(Q)$(CC) $(CFLAGS) - DELF -x assembler-with-cpp -o $@ -c $<795 $(Q)$(CC) $(CFLAGS) -x assembler-with-cpp -o $@ -c $< 823 796 endef 824 797 … … 857 830 # Create the build directories, check libraries and print out 858 831 # an informational message, then start building 859 targets: makedirs libversioncheck832 targets: makedirs 860 833 @echo "" 861 834 @echo "Building Tremulous in $(B):" … … 868 841 @echo " CFLAGS:" 869 842 @for i in $(CFLAGS); \ 843 do \ 844 echo " $$i"; \ 845 done 846 @echo "" 847 @echo " LDFLAGS:" 848 @for i in $(LDFLAGS); \ 870 849 do \ 871 850 echo " $$i"; \ … … 1033 1012 $(echo_cmd) "LD $@" 1034 1013 $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ 1035 1036 1037 #############################################################################1038 # LIBRARY VERSION CHECKS1039 #############################################################################1040 1041 MINSDL_MAJOR = 11042 MINSDL_MINOR = 21043 MINSDL_PATCH = 71044 1045 BASE_CFLAGS += -DMINSDL_MAJOR=$(MINSDL_MAJOR) \1046 -DMINSDL_MINOR=$(MINSDL_MINOR) \1047 -DMINSDL_PATCH=$(MINSDL_PATCH)1048 1049 libversioncheck:1050 @/bin/echo -e "#include \"SDL_version.h\"\n" \1051 "#if SDL_VERSION_ATLEAST(" \1052 "$(MINSDL_MAJOR),$(MINSDL_MINOR),$(MINSDL_PATCH)" \1053 ")\nMINSDL_PASSED\n#endif" | \1054 $(CC) $(BASE_CFLAGS) -E - | grep -q MINSDL_PASSED || \1055 ( /bin/echo "SDL version" \1056 "$(MINSDL_MAJOR).$(MINSDL_MINOR).$(MINSDL_PATCH)" \1057 "or greater required" && exit 1 )1058 1014 1059 1015 … … 1189 1145 $(B)/client/sdl_snd.o \ 1190 1146 \ 1147 $(B)/client/con_passive.o \ 1148 $(B)/client/con_log.o \ 1191 1149 $(B)/client/sys_main.o 1192 1150 … … 1287 1245 $(B)/ded/null_snddma.o \ 1288 1246 \ 1247 $(B)/ded/con_log.o \ 1289 1248 $(B)/ded/sys_main.o 1290 1249 … … 1608 1567 1609 1568 .PHONY: all clean clean2 clean-debug clean-release copyfiles \ 1610 debug default dist distclean libversioncheckmakedirs \1569 debug default dist distclean makedirs \ 1611 1570 release targets \ 1612 1571 toolsclean toolsclean2 toolsclean-debug toolsclean-release -
src/cgame/cg_animmapobj.c
r120 r124 76 76 77 77 //setup animation 78 anim.firstFrame = es-> misc;78 anim.firstFrame = es->powerups; 79 79 anim.numFrames = es->weapon; 80 80 anim.reversed = !es->legsAnim; … … 169 169 170 170 //setup animation 171 anim.firstFrame = es-> misc;171 anim.firstFrame = es->powerups; 172 172 anim.numFrames = es->weapon; 173 173 anim.reversed = qfalse; -
src/cgame/cg_animmapobj.c
r122 r124 32 32 static void CG_DoorAnimation( centity_t *cent, int *old, int *now, float *backLerp ) 33 33 { 34 CG_RunLerpFrame( ¢->lerpFrame );34 CG_RunLerpFrame( ¢->lerpFrame, 1.0f ); 35 35 36 36 *old = cent->lerpFrame.oldFrame; … … 118 118 } 119 119 120 CG_RunLerpFrame( ¢->lerpFrame );120 CG_RunLerpFrame( ¢->lerpFrame, 1.0f ); 121 121 cent->miscTime = cg.time; 122 122 } -
src/cgame/cg_buildable.c
r120 r124 1130 1130 return qfalse; 1131 1131 1132 for( i = 0; i < MAX_ MISC; i++ )1133 { 1134 if( ps-> misc[ i ] == entityNum )1132 for( i = 0; i < MAX_POWERUPS; i++ ) 1133 { 1134 if( ps->powerups[ i ] == entityNum ) 1135 1135 return qtrue; 1136 1136 } -
src/cgame/cg_buildable.c
r122 r124 428 428 static void CG_RunBuildableLerpFrame( centity_t *cent ) 429 429 { 430 int f, numFrames;431 430 buildable_t buildable = cent->currentState.modelindex; 432 431 lerpFrame_t *lf = ¢->lerpFrame; 433 animation_t *anim;434 432 buildableAnimNumber_t newAnimation = cent->buildableAnim & ~( ANIM_TOGGLEBIT|ANIM_FORCEBIT ); 435 436 // debugging tool to get no animations437 if( cg_animSpeed.integer == 0 )438 {439 lf->oldFrame = lf->frame = lf->backlerp = 0;440 return;441 }442 433 443 434 // see if the animation sequence is switching … … 467 458 cg_buildables[ buildable ].sounds[ lf->animationNumber ].sound ); 468 459 469 // if we have passed the current frame, move it to 470 // oldFrame and calculate a new frame 471 if( cg.time >= lf->frameTime ) 472 { 473 lf->oldFrame = lf->frame; 474 lf->oldFrameTime = lf->frameTime; 475 476 // get the next frame based on the animation 477 anim = lf->animation; 478 if( !anim->frameLerp ) 479 return; // shouldn't happen 480 481 if ( cg.time < lf->animationTime ) 482 lf->frameTime = lf->animationTime; // initial lerp 483 else 484 lf->frameTime = lf->oldFrameTime + anim->frameLerp; 485 486 f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; 487 numFrames = anim->numFrames; 488 if(anim->flipflop) 489 numFrames *= 2; 490 491 if( f >= numFrames ) 492 { 493 f -= numFrames; 494 if( anim->loopFrames ) 495 { 496 f %= anim->loopFrames; 497 f += anim->numFrames - anim->loopFrames; 498 } 499 else 500 { 501 f = numFrames - 1; 502 // the animation is stuck at the end, so it 503 // can immediately transition to another sequence 504 lf->frameTime = cg.time; 505 cent->buildableAnim = cent->currentState.torsoAnim; 506 } 507 } 508 509 if( anim->reversed ) 510 lf->frame = anim->firstFrame + anim->numFrames - 1 - f; 511 else if( anim->flipflop && f >= anim->numFrames ) 512 lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); 513 else 514 lf->frame = anim->firstFrame + f; 515 516 if( cg.time > lf->frameTime ) 517 { 518 lf->frameTime = cg.time; 519 if( cg_debugAnim.integer ) 520 CG_Printf( "Clamp lf->frameTime\n"); 521 } 522 } 523 524 if( lf->frameTime > cg.time + 200 ) 525 lf->frameTime = cg.time; 526 527 if( lf->oldFrameTime > cg.time ) 528 lf->oldFrameTime = cg.time; 529 530 // calculate current lerp value 531 if( lf->frameTime == lf->oldFrameTime ) 532 lf->backlerp = 0; 533 else 534 lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); 460 CG_RunLerpFrame( lf, 1.0f ); 461 462 // animation ended 463 if( lf->frameTime == cg.time ) 464 cent->buildableAnim = cent->currentState.torsoAnim; 535 465 } 536 466 -
src/cgame/cg_local.h
r120 r124 1388 1388 extern markPoly_t cg_markPolys[ MAX_MARK_POLYS ]; 1389 1389 1390 extern vmCvar_t cg_version; 1390 1391 extern vmCvar_t cg_centertime; 1391 1392 extern vmCvar_t cg_runpitch; -
src/cgame/cg_local.h
r123 r124 563 563 typedef struct 564 564 { 565 lerpFrame_t legs, torso, flag, nonseg;565 lerpFrame_t legs, torso, nonseg, weapon; 566 566 int painTime; 567 567 int painDirection; // flip from 0 to 1 … … 809 809 qhandle_t barrelModel; 810 810 qhandle_t flashModel; 811 812 animation_t animations[ MAX_WEAPON_ANIMATIONS ]; 813 qboolean noDrift; 811 814 812 815 vec3_t weaponMidpoint; // so it will rotate centered instead of by tag … … 1631 1634 // cg_animation.c 1632 1635 // 1633 void CG_RunLerpFrame( lerpFrame_t *lf );1636 void CG_RunLerpFrame( lerpFrame_t *lf, float scale ); 1634 1637 1635 1638 // -
src/cgame/cg_main.c
r120 r124 24 24 // cg_main.c -- initialization and primary entry point for cgame 25 25 26 27 26 #include "cg_local.h" 27 28 #include "../qcommon/q_shared.h" 28 29 29 30 #include "../ui/ui_shared.h" … … 101 102 buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; 102 103 104 vmCvar_t cg_version; 103 105 vmCvar_t cg_teslaTrailTime; 104 106 vmCvar_t cg_railTrailTime; … … 239 241 static cvarTable_t cvarTable[ ] = 240 242 { 243 { &cg_version, "cg_version", FULL_VERSION, CVAR_ROM | CVAR_USERINFO }, 241 244 { &cg_ignore, "cg_ignore", "0", 0 }, // used for debugging 242 245 { &cg_autoswitch, "cg_autoswitch", "1", CVAR_ARCHIVE }, -
src/cgame/cg_main.c
r123 r124 632 632 qboolean CG_FileExists( char *filename ) 633 633 { 634 fileHandle_t f; 635 636 if( trap_FS_FOpenFile( filename, &f, FS_READ ) > 0 ) 637 { 638 //file exists so close it 639 trap_FS_FCloseFile( f ); 640 641 return qtrue; 642 } 643 else 644 return qfalse; 634 return trap_FS_FOpenFile( filename, NULL, FS_READ ); 645 635 } 646 636 -
src/cgame/cg_players.c
r120 r124 1866 1866 float shadowPlane; 1867 1867 entityState_t *es = ¢->currentState; 1868 pClass_t class = ( es-> misc>> 8 ) & 0xFF;1868 pClass_t class = ( es->powerups >> 8 ) & 0xFF; 1869 1869 float scale; 1870 1870 vec3_t tempAxis[ 3 ], tempAxis2[ 3 ]; -
src/cgame/cg_players.c
r123 r124 108 108 // load the file 109 109 len = trap_FS_FOpenFile( filename, &f, FS_READ ); 110 if( len < =0 )110 if( len < 0 ) 111 111 return qfalse; 112 112 … … 842 842 static void CG_RunPlayerLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale ) 843 843 { 844 int f, numFrames;845 animation_t *anim;846 847 // debugging tool to get no animations848 if( cg_animSpeed.integer == 0 )849 {850 lf->oldFrame = lf->frame = lf->backlerp = 0;851 return;852 }853 854 844 // see if the animation sequence is switching 855 845 if( newAnimation != lf->animationNumber || !lf->animation ) 856 {857 846 CG_SetLerpFrameAnimation( ci, lf, newAnimation ); 858 } 859 860 // if we have passed the current frame, move it to 861 // oldFrame and calculate a new frame 862 if( cg.time >= lf->frameTime ) 863 { 864 lf->oldFrame = lf->frame; 865 lf->oldFrameTime = lf->frameTime; 866 867 // get the next frame based on the animation 868 anim = lf->animation; 869 if( !anim->frameLerp ) 870 return; // shouldn't happen 871 872 if( cg.time < lf->animationTime ) 873 lf->frameTime = lf->animationTime; // initial lerp 874 else 875 lf->frameTime = lf->oldFrameTime + anim->frameLerp; 876 877 f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; 878 f *= speedScale; // adjust for haste, etc 879 numFrames = anim->numFrames; 880 881 if( anim->flipflop ) 882 numFrames *= 2; 883 884 if( f >= numFrames ) 885 { 886 f -= numFrames; 887 if( anim->loopFrames ) 888 { 889 f %= anim->loopFrames; 890 f += anim->numFrames - anim->loopFrames; 891 } 892 else 893 { 894 f = numFrames - 1; 895 // the animation is stuck at the end, so it 896 // can immediately transition to another sequence 897 lf->frameTime = cg.time; 898 } 899 } 900 901 if( anim->reversed ) 902 lf->frame = anim->firstFrame + anim->numFrames - 1 - f; 903 else if( anim->flipflop && f>=anim->numFrames ) 904 lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); 905 else 906 lf->frame = anim->firstFrame + f; 907 908 if( cg.time > lf->frameTime ) 909 { 910 lf->frameTime = cg.time; 911 912 if( cg_debugAnim.integer ) 913 CG_Printf( "Clamp lf->frameTime\n" ); 914 } 915 } 916 917 if( lf->frameTime > cg.time + 200 ) 918 lf->frameTime = cg.time; 919 920 if( lf->oldFrameTime > cg.time ) 921 lf->oldFrameTime = cg.time; 922 923 // calculate current lerp value 924 if( lf->frameTime == lf->oldFrameTime ) 925 lf->backlerp = 0; 926 else 927 lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); 847 848 CG_RunLerpFrame( lf, speedScale ); 928 849 } 929 850 -
src/cgame/cg_predict.c
r120 r124 139 139 140 140 if( i == cg_numSolidEntities ) 141 BG_FindBBoxForClass( ( ent-> misc>> 8 ) & 0xFF, bmins, bmaxs, NULL, NULL, NULL );141 BG_FindBBoxForClass( ( ent->powerups >> 8 ) & 0xFF, bmins, bmaxs, NULL, NULL, NULL ); 142 142 143 143 cmodel = trap_CM_TempBoxModel( bmins, bmaxs ); -
src/cgame/cg_predict.c
r123 r124 177 177 } 178 178 else if( trace.startsolid ) 179 { 179 180 tr->startsolid = qtrue; 181 tr->entityNum = ent->number; 182 } 180 183 181 184 if( tr->allsolid ) -
src/cgame/cg_weapons.c
r120 r124 1349 1349 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 1350 1350 { 1351 int ammo, clips; 1352 1351 1353 if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) 1352 1354 continue; 1353 1355 1354 if( !ps->ammo && !ps->clips && !BG_FindInfinteAmmoForWeapon( i ) ) 1356 BG_UnpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips ); 1357 1358 if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( i ) ) 1355 1359 colinfo[ numItems ] = 1; 1356 1360 else -
src/cgame/cg_weapons.c
r123 r124 77 77 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 78 78 CG_RegisterUpgrade( i ); 79 } 80 81 82 /* 83 ====================== 84 CG_ParseWeaponAnimationFile 85 86 Read a configuration file containing animation counts and rates 87 models/weapons/rifle/animation.cfg, etc 88 ====================== 89 */ 90 static qboolean CG_ParseWeaponAnimationFile( const char *filename, weaponInfo_t *weapon ) 91 { 92 char *text_p; 93 int len; 94 int i; 95 char *token; 96 float fps; 97 char text[ 20000 ]; 98 fileHandle_t f; 99 animation_t *animations; 100 101 animations = weapon->animations; 102 103 // load the file 104 len = trap_FS_FOpenFile( filename, &f, FS_READ ); 105 if( len <= 0 ) 106 return qfalse; 107 108 if( len >= sizeof( text ) - 1 ) 109 { 110 CG_Printf( "File %s too long\n", filename ); 111 return qfalse; 112 } 113 114 trap_FS_Read( text, len, f ); 115 text[ len ] = 0; 116 trap_FS_FCloseFile( f ); 117 118 // parse the text 119 text_p = text; 120 121 // read information for each frame 122 for( i = WANIM_NONE + 1; i < MAX_WEAPON_ANIMATIONS; i++ ) 123 { 124 125 token = COM_Parse( &text_p ); 126 if( !*token ) 127 break; 128 129 if( !Q_stricmp( token, "noDrift" ) ) 130 { 131 weapon->noDrift = qtrue; 132 continue; 133 } 134 135 animations[ i ].firstFrame = atoi( token ); 136 137 token = COM_Parse( &text_p ); 138 if( !*token ) 139 break; 140 141 animations[ i ].numFrames = atoi( token ); 142 animations[ i ].reversed = qfalse; 143 animations[ i ].flipflop = qfalse; 144 145 // if numFrames is negative the animation is reversed 146 if( animations[ i ].numFrames < 0 ) 147 { 148 animations[ i ].numFrames = -animations[ i ].numFrames; 149 animations[ i ].reversed = qtrue; 150 } 151 152 token = COM_Parse( &text_p ); 153 if ( !*token ) 154 break; 155 156 animations[i].loopFrames = atoi( token ); 157 158 token = COM_Parse( &text_p ); 159 if( !*token ) 160 break; 161 162 fps = atof( token ); 163 if( fps == 0 ) 164 fps = 1; 165 166 animations[ i ].frameLerp = 1000 / fps; 167 animations[ i ].initialLerp = 1000 / fps; 168 } 169 170 if( i != MAX_WEAPON_ANIMATIONS ) 171 { 172 CG_Printf( "Error parsing animation file: %s\n", filename ); 173 return qfalse; 174 } 175 176 return qtrue; 79 177 } 80 178 … … 430 528 // load the file 431 529 len = trap_FS_FOpenFile( filename, &f, FS_READ ); 432 if( len < =0 )530 if( len < 0 ) 433 531 return qfalse; 434 532 … … 618 716 Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path ); 619 717 718 Com_sprintf( path, MAX_QPATH, "models/weapons/%s/animation.cfg", BG_FindNameForWeapon( weaponNum ) ); 719 720 if( !CG_ParseWeaponAnimationFile( path, weaponInfo ) ) 721 Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path ); 722 620 723 // calc midpoint for rotation 621 724 trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs ); … … 657 760 658 761 /* 762 =============== 763 CG_SetWeaponLerpFrameAnimation 764 765 may include ANIM_TOGGLEBIT 766 =============== 767 */ 768 static void CG_SetWeaponLerpFrameAnimation( weapon_t weapon, lerpFrame_t *lf, int newAnimation ) 769 { 770 animation_t *anim; 771 772 lf->animationNumber = newAnimation; 773 newAnimation &= ~ANIM_TOGGLEBIT; 774 775 if( newAnimation < 0 || newAnimation >= MAX_WEAPON_ANIMATIONS ) 776 CG_Error( "Bad animation number: %i", newAnimation ); 777 778 anim = &cg_weapons[ weapon ].animations[ newAnimation ]; 779 780 lf->animation = anim; 781 lf->animationTime = lf->frameTime + anim->initialLerp; 782 783 if( cg_debugAnim.integer ) 784 CG_Printf( "Anim: %i\n", newAnimation ); 785 } 786 787 /* 788 =============== 789 CG_WeaponAnimation 790 =============== 791 */ 792 static void CG_WeaponAnimation( centity_t *cent, int *old, int *now, float *backLerp ) 793 { 794 lerpFrame_t *lf = ¢->pe.weapon; 795 entityState_t *es = ¢->currentState; 796 797 // see if the animation sequence is switching 798 if( es->weaponAnim != lf->animationNumber || !lf->animation ) 799 CG_SetWeaponLerpFrameAnimation( es->weapon, lf, es->weaponAnim ); 800 801 CG_RunLerpFrame( lf, 1.0f ); 802 803 *old = lf->oldFrame; 804 *now = lf->frame; 805 *backLerp = lf->backlerp; 806 } 807 808 /* 659 809 ================= 660 810 CG_MapTorsoToWeaponFrame … … 691 841 static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) 692 842 { 693 float scale; 694 int delta; 695 float fracsin; 696 float bob; 843 float scale; 844 int delta; 845 float fracsin; 846 float bob; 847 weaponInfo_t *weapon; 848 849 weapon = &cg_weapons[ cg.predictedPlayerState.weapon ]; 697 850 698 851 VectorCopy( cg.refdef.vieworg, origin ); … … 717 870 718 871 // drop the weapon when landing 719 if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ))872 if( weapon->noDrift ) 720 873 { 721 874 delta = cg.time - cg.landTime; … … 861 1014 if( !noGunModel ) 862 1015 { 1016 CG_WeaponAnimation( cent, &gun.oldframe, &gun.frame, &gun.backlerp ); 863 1017 CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" ); 864 1018 -
src/client/cl_main.c
r120 r124 31 31 cvar_t *cl_noprint; 32 32 cvar_t *cl_motd; 33 33 cvar_t *cl_master; 34 34 cvar_t *rcon_client_password; 35 35 cvar_t *rconAddress; … … 986 986 return; 987 987 } 988 Com_Printf( "Resolving %s\n", MASTER_SERVER_NAME);989 if ( !NET_StringToAdr( MASTER_SERVER_NAME, &cls.updateServer ) ) {988 Com_Printf( "Resolving %s\n", cl_master->string ); 989 if ( !NET_StringToAdr( cl_master->string, &cls.updateServer ) ) { 990 990 Com_Printf( "Couldn't resolve address\n" ); 991 991 return; 992 992 } 993 993 cls.updateServer.port = BigShort( PORT_MASTER ); 994 Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", MASTER_SERVER_NAME,994 Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", cl_master->string, 995 995 cls.updateServer.ip[0], cls.updateServer.ip[1], 996 996 cls.updateServer.ip[2], cls.updateServer.ip[3], … … 2619 2619 cl_noprint = Cvar_Get( "cl_noprint", "0", 0 ); 2620 2620 cl_motd = Cvar_Get ("cl_motd", "1", 0); 2621 2621 cl_master = Cvar_Get("cl_master","master.tremulous.net",CVAR_ARCHIVE); 2622 2622 cl_timeout = Cvar_Get ("cl_timeout", "200", 0); 2623 2623 … … 3219 3219 3220 3220 if( cls.masterNum == 1 ) { 3221 NET_StringToAdr( cl_master->string, &to ); 3221 3222 cls.nummplayerservers = -1; 3222 3223 cls.pingUpdateSource = AS_MPLAYER; 3223 3224 } 3224 3225 else { 3226 NET_StringToAdr( cl_master->string, &to ); 3225 3227 cls.numglobalservers = -1; 3226 3228 cls.pingUpdateSource = AS_GLOBAL; -
src/client/cl_main.c
r123 r124 38 38 cvar_t *cl_maxpackets; 39 39 cvar_t *cl_packetdup; 40 cvar_t *cl_master; 40 41 cvar_t *cl_timeNudge; 41 42 cvar_t *cl_showTimeDelta; … … 934 935 // Stop recording any video 935 936 if( CL_VideoRecording( ) ) { 937 // Finish rendering current frame 938 SCR_UpdateScreen( ); 936 939 CL_CloseAVI( ); 937 940 } … … 2619 2622 cl_timeout = Cvar_Get ("cl_timeout", "200", 0); 2620 2623 2624 cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE); 2621 2625 cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); 2622 2626 cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); … … 3211 3215 // reset the list, waiting for response 3212 3216 // -1 is used to distinguish a "no response" 3217 3218 NET_StringToAdr( cl_master->string, &to ); 3213 3219 3214 3220 if( cls.masterNum == 1 ) { -
src/game/bg_misc.c
r120 r124 72 72 qfalse, //qboolean dccTest; 73 73 qfalse, //qboolean transparentTest; 74 qfalse //qboolean reactorTest; 74 qfalse, //qboolean reactorTest; 75 qfalse //qboolean replacable; 75 76 }, 76 77 { … … 110 111 qfalse, //qboolean dccTest; 111 112 qfalse, //qboolean transparentTest; 112 qfalse //qboolean reactorTest; 113 qfalse, //qboolean reactorTest; 114 qfalse //qboolean replacable; 113 115 }, 114 116 { … … 151 153 qfalse, //qboolean dccTest; 152 154 qtrue, //qboolean transparentTest; 153 qfalse //qboolean reactorTest; 155 qfalse, //qboolean reactorTest; 156 qtrue //qboolean replacable; 154 157 }, 155 158 { … … 190 193 qfalse, //qboolean dccTest; 191 194 qfalse, //qboolean transparentTest; 192 qfalse //qboolean reactorTest; 195 qfalse, //qboolean reactorTest; 196 qfalse //qboolean replacable; 193 197 }, 194 198 { … … 228 232 qfalse, //qboolean dccTest; 229 233 qfalse, //qboolean transparentTest; 230 qfalse //qboolean reactorTest; 234 qfalse, //qboolean reactorTest; 235 qfalse //qboolean replacable; 231 236 }, 232 237 { … … 267 272 qfalse, //qboolean dccTest; 268 273 qtrue, //qboolean transparentTest; 269 qfalse //qboolean reactorTest; 274 qfalse, //qboolean reactorTest; 275 qfalse //qboolean replacable; 270 276 }, 271 277 { … … 306 312 qfalse, //qboolean dccTest; 307 313 qfalse, //qboolean transparentTest; 308 qtrue //qboolean reactorTest; 314 qtrue, //qboolean reactorTest; 315 qtrue //qboolean replacable; 309 316 }, 310 317 { … … 345 352 qfalse, //qboolean dccTest; 346 353 qfalse, //qboolean transparentTest; 347 qtrue //qboolean reactorTest; 354 qtrue, //qboolean reactorTest; 355 qfalse //qboolean replacable; 348 356 }, 349 357 { … … 384 392 qfalse, //qboolean dccTest; 385 393 qtrue, //qboolean transparentTest; 386 qfalse //qboolean reactorTest; 394 qfalse, //qboolean reactorTest; 395 qfalse //qboolean replacable; 387 396 }, 388 397 { … … 423 432 qfalse, //qboolean dccTest; 424 433 qtrue, //qboolean transparentTest; 425 qfalse //qboolean reactorTest; 434 qfalse, //qboolean reactorTest; 435 qtrue //qboolean replacable; 426 436 }, 427 437 { … … 464 474 qfalse, //qboolean dccTest; 465 475 qtrue, //qboolean transparentTest; 466 qfalse //qboolean reactorTest; 476 qfalse, //qboolean reactorTest; 477 qfalse //qboolean replacable; 467 478 }, 468 479 { … … 503 514 qtrue, //qboolean dccTest; 504 515 qtrue, //qboolean transparentTest; 505 qfalse //qboolean reactorTest; 516 qfalse, //qboolean reactorTest; 517 qfalse //qboolean replacable; 506 518 }, 507 519 { … … 542 554 qfalse, //qboolean dccTest; 543 555 qfalse, //qboolean transparentTest; 544 qfalse //qboolean reactorTest; 556 qfalse, //qboolean reactorTest; 557 qtrue //qboolean replacable; 545 558 }, 546 559 { … … 581 594 qfalse, //qboolean dccTest; 582 595 qfalse, //qboolean transparentTest; 583 qfalse //qboolean reactorTest; 596 qfalse, //qboolean reactorTest; 597 qtrue //qboolean replacable; 584 598 }, 585 599 { … … 620 634 qfalse, //qboolean dccTest; 621 635 qfalse, //qboolean transparentTest; 622 qtrue //qboolean reactorTest; 636 qtrue, //qboolean reactorTest; 637 qtrue //qboolean replacable; 623 638 }, 624 639 { … … 638 653 0.0, //float bounce; 639 654 REPEATER_BP, //int buildPoints; 640 ( 1 << S 2 )|( 1 << S3 ), //int stages655 ( 1 << S1)|( 1 << S2 )|( 1 << S3 ), //int stages 641 656 REPEATER_HEALTH, //int health; 642 657 0, //int regenRate; … … 659 674 qfalse, //qboolean dccTest; 660 675 qfalse, //qboolean transparentTest; 661 qfalse //qboolean reactorTest; 676 qfalse, //qboolean reactorTest; 677 qtrue //qboolean replacable; 662 678 } 663 679 }; … … 1369 1385 } 1370 1386 1387 return qfalse; 1388 } 1389 1390 /* 1391 ============== 1392 BG_FindReplaceableTestForBuildable 1393 ============== 1394 */ 1395 qboolean BG_FindReplaceableTestForBuildable( int bclass ) 1396 { 1397 int i; 1398 1399 for( i = 0; i < bg_numBuildables; i++ ) 1400 { 1401 if( bg_buildableList[ i ].buildNum == bclass ) 1402 { 1403 return bg_buildableList[ i ].replaceable; 1404 } 1405 } 1371 1406 return qfalse; 1372 1407 } … … 4990 5025 } 4991 5026 4992 // use miscfield to store team/class info:4993 s-> misc= ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 );5027 // use powerups field to store team/class info: 5028 s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); 4994 5029 4995 5030 // have to get the surfNormal through somehow... … … 5101 5136 } 5102 5137 5103 // use miscfield to store team/class info:5104 s-> misc= ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 );5138 // use powerups field to store team/class info: 5139 s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 ); 5105 5140 5106 5141 // have to get the surfNormal through somehow... … … 5120 5155 /* 5121 5156 ======================== 5157 BG_UnpackAmmoArray 5158 5159 Extract the ammo quantity from the array 5160 ======================== 5161 */ 5162 void BG_UnpackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int *ammo, int *clips ) 5163 { 5164 int ammoarray[ 32 ]; 5165 int i; 5166 5167 for( i = 0; i <= 15; i++ ) 5168 ammoarray[ i ] = psAmmo[ i ]; 5169 5170 for( i = 16; i <= 31; i++ ) 5171 ammoarray[ i ] = psAmmo2[ i - 16 ]; 5172 5173 if( ammo != NULL ) 5174 *ammo = ammoarray[ weapon ] & 0x0FFF; 5175 5176 if( clips != NULL ) 5177 *clips = ( ammoarray[ weapon ] >> 12 ) & 0x0F; 5178 } 5179 5180 /* 5181 ======================== 5182 BG_PackAmmoArray 5183 5184 Pack the ammo quantity into the array 5185 ======================== 5186 */ 5187 void BG_PackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int ammo, int clips ) 5188 { 5189 int weaponvalue; 5190 5191 weaponvalue = ammo | ( clips << 12 ); 5192 5193 if( weapon <= 15 ) 5194 psAmmo[ weapon ] = weaponvalue; 5195 else if( weapon >= 16 ) 5196 psAmmo2[ weapon - 16 ] = weaponvalue; 5197 } 5198 5199 /* 5200 ======================== 5122 5201 BG_WeaponIsFull 5123 5202 … … 5125 5204 ======================== 5126 5205 */ 5127 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips)5206 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] ) 5128 5207 { 5129 5208 int maxAmmo, maxClips; 5209 int ammo, clips; 5130 5210 5131 5211 BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); 5212 BG_UnpackAmmoArray( weapon, psAmmo, psAmmo2, &ammo, &clips ); 5132 5213 5133 5214 if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) ) -
src/game/bg_misc.c
r122 r124 1734 1734 0.0f, //float fallDamage; 1735 1735 LEVEL0_REGEN, //int regenRate; 1736 SCA_WALLCLIMBER|SCA_NOWEAPONDRIFT| 1737 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1736 SCA_WALLCLIMBER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1738 1737 WP_ALEVEL0, //weapon_t startWeapon 1739 1738 0.0f, //float buildDist; … … 1775 1774 0.0f, //float fallDamage; 1776 1775 LEVEL1_REGEN, //int regenRate; 1777 SCA_NOWEAPONDRIFT| 1778 SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; 1776 SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; 1779 1777 WP_ALEVEL1, //weapon_t startWeapon 1780 1778 0.0f, //float buildDist; … … 1817 1815 0.0f, //float fallDamage; 1818 1816 LEVEL1_UPG_REGEN, //int regenRate; 1819 SCA_NOWEAPONDRIFT|SCA_FOVWARPS| 1820 SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; 1817 SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE, //int abilities; 1821 1818 WP_ALEVEL1_UPG, //weapon_t startWeapon 1822 1819 0.0f, //float buildDist; … … 1858 1855 0.0f, //float fallDamage; 1859 1856 LEVEL2_REGEN, //int regenRate; 1860 SCA_NOWEAPONDRIFT|SCA_WALLJUMPER| 1861 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1857 SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1862 1858 WP_ALEVEL2, //weapon_t startWeapon 1863 1859 0.0f, //float buildDist; … … 1899 1895 0.0f, //float fallDamage; 1900 1896 LEVEL2_UPG_REGEN, //int regenRate; 1901 SCA_NOWEAPONDRIFT|SCA_WALLJUMPER| 1902 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1897 SCA_WALLJUMPER|SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1903 1898 WP_ALEVEL2_UPG, //weapon_t startWeapon 1904 1899 0.0f, //float buildDist; … … 1941 1936 0.0f, //float fallDamage; 1942 1937 LEVEL3_REGEN, //int regenRate; 1943 SCA_NOWEAPONDRIFT| 1944 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1938 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1945 1939 WP_ALEVEL3, //weapon_t startWeapon 1946 1940 0.0f, //float buildDist; … … 1983 1977 0.0f, //float fallDamage; 1984 1978 LEVEL3_UPG_REGEN, //int regenRate; 1985 SCA_NOWEAPONDRIFT| 1986 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1979 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 1987 1980 WP_ALEVEL3_UPG, //weapon_t startWeapon 1988 1981 0.0f, //float buildDist; … … 2025 2018 0.0f, //float fallDamage; 2026 2019 LEVEL4_REGEN, //int regenRate; 2027 SCA_NOWEAPONDRIFT| 2028 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 2020 SCA_FOVWARPS|SCA_ALIENSENSE, //int abilities; 2029 2021 WP_ALEVEL4, //weapon_t startWeapon 2030 2022 0.0f, //float buildDist; … … 2065 2057 1.0f, //float fallDamage; 2066 2058 0, //int regenRate; 2067 SCA_TAKESFALLDAMAGE| 2068 SCA_CANUSELADDERS, //int abilities; 2059 SCA_TAKESFALLDAMAGE|SCA_CANUSELADDERS, //int abilities; 2069 2060 WP_NONE, //special-cased in g_client.c //weapon_t startWeapon 2070 2061 110.0f, //float buildDist; … … 4985 4976 s->legsAnim = ps->legsAnim; 4986 4977 s->torsoAnim = ps->torsoAnim; 4978 s->weaponAnim = ps->weaponAnim; 4987 4979 s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number 4988 4980 // so corpses can also reference the proper config … … 5093 5085 s->legsAnim = ps->legsAnim; 5094 5086 s->torsoAnim = ps->torsoAnim; 5087 s->weaponAnim = ps->weaponAnim; 5095 5088 s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number 5096 5089 // so corpses can also reference the proper config -
src/game/bg_pmove.c
r120 r124 538 538 return qfalse; 539 539 540 // we were pouncing, but we've landed 541 if( pm->ps->groundEntityNum != ENTITYNUM_NONE 542 && ( pm->ps->pm_flags & PMF_CHARGE ) ) 543 { 544 pm->ps->weaponTime += LEVEL3_POUNCE_TIME; 545 pm->ps->pm_flags &= ~PMF_CHARGE; 546 } 547 548 // we're building up for a pounce 540 549 if( pm->cmd.buttons & BUTTON_ATTACK2 ) 541 {542 pm->ps->pm_flags &= ~PMF_CHARGE;543 550 return qfalse; 544 } 545 551 552 // already a pounce in progress 546 553 if( pm->ps->pm_flags & PMF_CHARGE ) 547 554 return qfalse; … … 2695 2702 { 2696 2703 int addTime = 200; //default addTime - should never be used 2697 int maxClips;2704 int ammo, clips, maxClips; 2698 2705 qboolean attack1 = qfalse; 2699 2706 qboolean attack2 = qfalse; … … 2721 2728 } 2722 2729 2723 // make weapon function 2730 2731 // no bite during pounce 2732 if( ( pm->ps->weapon == WP_ALEVEL3 || pm->ps->weapon == WP_ALEVEL3_UPG ) 2733 && ( pm->cmd.buttons & BUTTON_ATTACK ) 2734 && ( pm->ps->pm_flags & PMF_CHARGE ) ) 2735 { 2736 return; 2737 } 2738 2724 2739 if( pm->ps->weaponTime > 0 ) 2725 2740 pm->ps->weaponTime -= pml.msec; … … 2795 2810 // start the animation even if out of ammo 2796 2811 2812 BG_UnpackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, &ammo, &clips); 2797 2813 BG_FindAmmoForWeapon( pm->ps->weapon, NULL, &maxClips ); 2798 2814 2799 2815 // check for out of ammo 2800 if( ! pm->ps->ammo && !pm->ps->clips && !BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) )2816 if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) 2801 2817 { 2802 2818 PM_AddEvent( EV_NOAMMO ); … … 2814 2830 if( maxClips > 0 ) 2815 2831 { 2816 pm->ps->clips--;2817 BG_FindAmmoForWeapon( pm->ps->weapon, & pm->ps->ammo, NULL );2832 clips--; 2833 BG_FindAmmoForWeapon( pm->ps->weapon, &ammo, NULL ); 2818 2834 } 2819 2835 2820 2836 if( BG_FindUsesEnergyForWeapon( pm->ps->weapon ) && 2821 2837 BG_InventoryContainsUpgrade( UP_BATTPACK, pm->ps->stats ) ) 2822 pm->ps->ammo = (int)( (float)pm->ps->ammo * BATTPACK_MODIFIER ); 2838 ammo = (int)( (float)ammo * BATTPACK_MODIFIER ); 2839 2840 BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips ); 2823 2841 2824 2842 //allow some time for the weapon to be raised … … 2829 2847 2830 2848 // check for end of clip 2831 if( ( ! pm->ps->ammo || pm->ps->pm_flags & PMF_WEAPON_RELOAD ) && pm->ps->clips )2849 if( ( !ammo || pm->ps->pm_flags & PMF_WEAPON_RELOAD ) && clips ) 2832 2850 { 2833 2851 pm->ps->pm_flags &= ~PMF_WEAPON_RELOAD; … … 2949 2967 { 2950 2968 //hacky special case for slowblob 2951 if( pm->ps->weapon == WP_ALEVEL3_UPG && ! pm->ps->ammo )2969 if( pm->ps->weapon == WP_ALEVEL3_UPG && !ammo ) 2952 2970 { 2953 2971 PM_AddEvent( EV_NOAMMO ); … … 3092 3110 if( pm->ps->weapon == WP_LUCIFER_CANNON && attack1 && !attack2 ) 3093 3111 { 3094 pm->ps->ammo -= (int)( ceil( ( (float)pm->ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE ) * 10.0f ) );3112 ammo -= (int)( ceil( ( (float)pm->ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE ) * 10.0f ) ); 3095 3113 3096 3114 //stay on the safe side 3097 if( pm->ps->ammo < 0 )3098 pm->ps->ammo = 0;3115 if( ammo < 0 ) 3116 ammo = 0; 3099 3117 } 3100 3118 else 3101 pm->ps->ammo--; 3119 ammo--; 3120 3121 BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips ); 3102 3122 } 3103 3123 else if( pm->ps->weapon == WP_ALEVEL3_UPG && attack3 ) 3104 3124 { 3105 3125 //special case for slowblob 3106 pm->ps->ammo--; 3126 ammo--; 3127 BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips ); 3107 3128 } 3108 3129 … … 3306 3327 void PmoveSingle( pmove_t *pmove ) 3307 3328 { 3329 int ammo, clips; 3308 3330 pm = pmove; 3331 3332 BG_UnpackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, &ammo, &clips ); 3309 3333 3310 3334 // this counter lets us debug movement problems with a journal … … 3334 3358 if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 3335 3359 ( pm->cmd.buttons & BUTTON_ATTACK ) && 3336 ( ( pm->ps->ammo > 0 || pm->ps->clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) )3360 ( ( ammo > 0 || clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) ) 3337 3361 pm->ps->eFlags |= EF_FIRING; 3338 3362 else … … 3342 3366 if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 3343 3367 ( pm->cmd.buttons & BUTTON_ATTACK2 ) && 3344 ( ( pm->ps->ammo > 0 || pm->ps->clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) )3368 ( ( ammo > 0 || clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) ) 3345 3369 pm->ps->eFlags |= EF_FIRING2; 3346 3370 else … … 3350 3374 if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 3351 3375 ( pm->cmd.buttons & BUTTON_USE_HOLDABLE ) && 3352 ( ( pm->ps->ammo > 0 || pm->ps->clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) )3376 ( ( ammo > 0 || clips > 0 ) || BG_FindInfinteAmmoForWeapon( pm->ps->weapon ) ) ) 3353 3377 pm->ps->eFlags |= EF_FIRING3; 3354 3378 else -
src/game/bg_pmove.c
r122 r124 104 104 /* 105 105 =================== 106 PM_StartWeaponAnim 107 =================== 108 */ 109 static void PM_StartWeaponAnim( int anim ) 110 { 111 if( pm->ps->pm_type >= PM_DEAD ) 112 return; 113 114 pm->ps->weaponAnim = ( ( pm->ps->torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) 115 | anim; 116 } 117 118 /* 119 =================== 106 120 PM_StartLegsAnim 107 121 =================== … … 167 181 168 182 PM_StartTorsoAnim( anim ); 183 } 184 185 /* 186 =================== 187 PM_ContinueWeaponAnim 188 =================== 189 */ 190 static void PM_ContinueWeaponAnim( int anim ) 191 { 192 if( ( pm->ps->weaponAnim & ~ANIM_TOGGLEBIT ) == anim ) 193 return; 194 195 PM_StartWeaponAnim( anim ); 169 196 } 170 197 … … 2585 2612 static void PM_BeginWeaponChange( int weapon ) 2586 2613 { 2587 if( weapon < WP_NONE || weapon >= WP_NUM_WEAPONS )2588 return; 2589 2590 if( !BG_InventoryContainsWeapon( weapon, pm->ps->stats ) && weapon != WP_NONE)2614 if( weapon <= WP_NONE || weapon >= WP_NUM_WEAPONS ) 2615 return; 2616 2617 if( !BG_InventoryContainsWeapon( weapon, pm->ps->stats ) ) 2591 2618 return; 2592 2619 … … 2607 2634 2608 2635 if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) ) 2636 { 2609 2637 PM_StartTorsoAnim( TORSO_DROP ); 2638 PM_StartWeaponAnim( WANIM_DROP ); 2639 } 2610 2640 } 2611 2641 … … 2632 2662 2633 2663 if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) ) 2664 { 2634 2665 PM_StartTorsoAnim( TORSO_RAISE ); 2666 PM_StartWeaponAnim( WANIM_RAISE ); 2667 } 2635 2668 } 2636 2669 … … 2644 2677 static void PM_TorsoAnimation( void ) 2645 2678 { 2646 if( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL )2647 return;2648 2649 2679 if( pm->ps->weaponstate == WEAPON_READY ) 2650 2680 { 2651 if( pm->ps->weapon == WP_BLASTER ) 2652 PM_ContinueTorsoAnim( TORSO_STAND2 ); 2653 else 2654 PM_ContinueTorsoAnim( TORSO_STAND ); 2681 if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) ) 2682 { 2683 if( pm->ps->weapon == WP_BLASTER ) 2684 PM_ContinueTorsoAnim( TORSO_STAND2 ); 2685 else 2686 PM_ContinueTorsoAnim( TORSO_STAND ); 2687 } 2688 2689 PM_ContinueWeaponAnim( WANIM_IDLE ); 2655 2690 } 2656 2691 } … … 2768 2803 } 2769 2804 2805 PM_ContinueWeaponAnim( WANIM_IDLE ); 2806 2770 2807 return; 2771 2808 } … … 2805 2842 //allow some time for the weapon to be raised 2806 2843 pm->ps->weaponstate = WEAPON_RAISING; 2807 PM_StartTorsoAnim( TORSO_RAISE );2808 2844 pm->ps->weaponTime += 250; 2809 2845 return; … … 2819 2855 //drop the weapon 2820 2856 PM_StartTorsoAnim( TORSO_DROP ); 2857 PM_StartWeaponAnim( WANIM_RELOAD ); 2821 2858 2822 2859 addTime = BG_FindReloadTimeForWeapon( pm->ps->weapon ); … … 3004 3041 { 3005 3042 PM_StartTorsoAnim( TORSO_ATTACK ); 3043 PM_StartWeaponAnim( WANIM_ATTACK1 ); 3006 3044 } 3007 3045 break; … … 3009 3047 case WP_BLASTER: 3010 3048 PM_StartTorsoAnim( TORSO_ATTACK2 ); 3049 PM_StartWeaponAnim( WANIM_ATTACK1 ); 3011 3050 break; 3012 3051 3013 3052 default: 3014 3053 PM_StartTorsoAnim( TORSO_ATTACK ); 3054 PM_StartWeaponAnim( WANIM_ATTACK1 ); 3015 3055 break; 3016 3056 } … … 3025 3065 3026 3066 if( num == 0 ) 3067 { 3027 3068 PM_ForceLegsAnim( NSPA_ATTACK1 ); 3069 PM_StartWeaponAnim( WANIM_ATTACK1 ); 3070 } 3028 3071 else if( num == 1 ) 3072 { 3029 3073 PM_ForceLegsAnim( NSPA_ATTACK2 ); 3074 PM_StartWeaponAnim( WANIM_ATTACK2 ); 3075 } 3030 3076 else if( num == 2 ) 3077 { 3031 3078 PM_ForceLegsAnim( NSPA_ATTACK3 ); 3079 PM_StartWeaponAnim( WANIM_ATTACK3 ); 3080 } 3032 3081 } 3033 3082 else 3034 3083 { 3035 3084 if( attack1 ) 3085 { 3036 3086 PM_ForceLegsAnim( NSPA_ATTACK1 ); 3087 PM_StartWeaponAnim( WANIM_ATTACK1 ); 3088 } 3037 3089 else if( attack2 ) 3090 { 3038 3091 PM_ForceLegsAnim( NSPA_ATTACK2 ); 3092 PM_StartWeaponAnim( WANIM_ATTACK2 ); 3093 } 3039 3094 else if( attack3 ) 3095 { 3040 3096 PM_ForceLegsAnim( NSPA_ATTACK3 ); 3097 PM_StartWeaponAnim( WANIM_ATTACK3 ); 3098 } 3041 3099 } 3042 3100 -
src/game/bg_public.h
r120 r124 34 34 35 35 #define VOTE_TIME 30000 // 30 seconds before vote times out 36 37 #define WARMUPMESSAGE_TIME 1000 // 1 second between two warmup messages 36 38 37 39 #define MINS_Z -24 … … 433 435 } buildableTeam_t; 434 436 435 #define B_HEALTH_BITS 12437 #define B_HEALTH_BITS 5 436 438 #define B_HEALTH_MASK ((1<<B_HEALTH_BITS)-1) 437 439 438 #define B_ MARKED_TOGGLEBIT 0x00001000439 #define B_SPAWNED_TOGGLEBIT 0x00002000440 #define B_POWERED_TOGGLEBIT 0x00004000441 #define B_ DCCED_TOGGLEBIT 0x00008000440 #define B_DCCED_TOGGLEBIT 0x00000000 441 #define B_SPAWNED_TOGGLEBIT 0x00000020 442 #define B_POWERED_TOGGLEBIT 0x00000040 443 #define B_MARKED_TOGGLEBIT 0x00000080 442 444 443 445 … … 564 566 MN_A_TEAMFULL, 565 567 MN_H_TEAMFULL, 566 MN_A_TEAMCHANGEBUILDTIMER,567 MN_H_TEAMCHANGEBUILDTIMER,568 568 569 569 //alien stuff … … 576 576 MN_A_TOOCLOSE, 577 577 MN_A_NOOVMND_EVOLVE, 578 MN_A_EVOLVEBUILDTIMER,579 578 580 579 //alien build … … 596 595 MN_H_NOFUNDS, 597 596 MN_H_ITEMHELD, 598 MN_H_NOENERGYAMMOHERE,599 MN_H_NOARMOURYHERE,600 MN_H_NOROOMBSUITON,601 MN_H_NOROOMBSUITOFF,602 MN_H_ARMOURYBUILDTIMER,603 597 604 598 //human build … … 612 606 MN_H_TNODEWARN, 613 607 MN_H_RPTWARN, 614 MN_H_RPTWARN2 608 MN_H_RPTWARN2, 609 // Balance mod 610 MN_H_RECHARGING, 611 MN_H_NOTELEPORT, 615 612 } dynMenu_t; 616 613 … … 883 880 MOD_ASPAWN, 884 881 MOD_ATUBE, 885 MOD_OVERMIND 882 MOD_OVERMIND, 883 884 MOD_SLAP 886 885 } meansOfDeath_t; 887 886 … … 1027 1026 qboolean transparentTest; 1028 1027 qboolean reactorTest; 1028 qboolean replaceable; 1029 1029 } buildableAttributes_t; 1030 1030 … … 1100 1100 } upgradeAttributes_t; 1101 1101 1102 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips ); 1102 void BG_UnpackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int *ammo, int *clips ); 1103 void BG_PackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int ammo, int clips ); 1104 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] ); 1103 1105 void BG_AddWeaponToInventory( int weapon, int stats[ ] ); 1104 1106 void BG_RemoveWeaponFromInventory( int weapon, int stats[ ] ); … … 1154 1156 int BG_FindDCCTestForBuildable( int bclass ); 1155 1157 int BG_FindUniqueTestForBuildable( int bclass ); 1158 qboolean BG_FindReplaceableTestForBuildable( int bclass ); 1156 1159 qboolean BG_FindTransparentTestForBuildable( int bclass ); 1157 1160 void BG_InitBuildableOverrides( void ); -
src/game/bg_public.h
r122 r124 226 226 #define SCA_TAKESFALLDAMAGE 0x00000002 227 227 #define SCA_CANZOOM 0x00000004 228 #define SCA_NOWEAPONDRIFT 0x00000008 229 #define SCA_FOVWARPS 0x00000010 230 #define SCA_ALIENSENSE 0x00000020 231 #define SCA_CANUSELADDERS 0x00000040 232 #define SCA_WALLJUMPER 0x00000080 228 #define SCA_FOVWARPS 0x00000008 229 #define SCA_ALIENSENSE 0x00000010 230 #define SCA_CANUSELADDERS 0x00000020 231 #define SCA_WALLJUMPER 0x00000040 233 232 234 233 #define SS_WALLCLIMBING 0x00000001 … … 743 742 MAX_BUILDABLE_ANIMATIONS 744 743 } buildableAnimNumber_t; 744 745 typedef enum 746 { 747 WANIM_NONE, 748 749 WANIM_IDLE, 750 751 WANIM_DROP, 752 WANIM_RELOAD, 753 WANIM_RAISE, 754 755 WANIM_ATTACK1, 756 WANIM_ATTACK2, 757 WANIM_ATTACK3, 758 759 MAX_WEAPON_ANIMATIONS 760 } weaponAnimNumber_t; 745 761 746 762 typedef struct animation_s -
src/game/g_active.c
r120 r124 376 376 pmove_t pm; 377 377 gclient_t *client; 378 qboolean doPmove = qtrue; 378 379 379 380 client = ent->client; … … 382 383 client->buttons = ucmd->buttons; 383 384 384 if( client->sess.spectatorState != SPECTATOR_FOLLOW ) 385 { 386 if( client->sess.spectatorState == SPECTATOR_LOCKED ) 387 client->ps.pm_type = PM_FREEZE; 388 else 389 client->ps.pm_type = PM_SPECTATOR; 390 385 if( client->sess.spectatorState == SPECTATOR_LOCKED || client->sess.spectatorState == SPECTATOR_FOLLOW ) 386 client->ps.pm_type = PM_FREEZE; 387 else 388 client->ps.pm_type = PM_SPECTATOR; 389 390 if ( client->sess.spectatorState == SPECTATOR_FOLLOW ) 391 { 392 gclient_t *cl; 393 if ( client->sess.spectatorClient >= 0 ) 394 { 395 cl = &level.clients[ client->sess.spectatorClient ]; 396 if ( cl->sess.sessionTeam != TEAM_SPECTATOR ) 397 doPmove = qfalse; 398 } 399 } 400 401 if (doPmove) 402 { 391 403 client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); 392 404 … … 551 563 552 564 if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) && BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) ) 565 { 566 //don't run when jetpack on 553 567 client->ps.stats[ STAT_STATE ] &= ~SS_SPEEDBOOST; 568 } 554 569 555 570 if( ( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST ) && !crouched ) … … 666 681 if( client->ps.weapon == WP_LUCIFER_CANNON ) 667 682 { 683 int ammo; 684 685 BG_UnpackAmmoArray( WP_LUCIFER_CANNON, client->ps.ammo, client->ps.powerups, &ammo, NULL ); 686 668 687 if( client->ps.stats[ STAT_MISC ] < LCANNON_TOTAL_CHARGE && ucmd->buttons & BUTTON_ATTACK ) 669 688 client->ps.stats[ STAT_MISC ] += ( 100.0f / LCANNON_CHARGE_TIME ) * LCANNON_TOTAL_CHARGE; … … 672 691 client->ps.stats[ STAT_MISC ] = LCANNON_TOTAL_CHARGE; 673 692 674 if( client->ps.stats[ STAT_MISC ] > ( client->ps.ammo * LCANNON_TOTAL_CHARGE ) / 10 )675 client->ps.stats[ STAT_MISC ] = client->ps.ammo * LCANNON_TOTAL_CHARGE / 10;693 if( client->ps.stats[ STAT_MISC ] > ( ammo * LCANNON_TOTAL_CHARGE ) / 10 ) 694 client->ps.stats[ STAT_MISC ] = ammo * LCANNON_TOTAL_CHARGE / 10; 676 695 } 677 696 … … 695 714 696 715 // Let the client know which buildables will be removed by building 697 for( i = 0; i < MAX_ MISC; i++ )716 for( i = 0; i < MAX_POWERUPS; i++ ) 698 717 { 699 718 if( i < level.numBuildablesForRemoval ) 700 client->ps. misc[ i ] = level.markedBuildables[ i ]->s.number;719 client->ps.powerups[ i ] = level.markedBuildables[ i ]->s.number; 701 720 else 702 client->ps. misc[ i ] = 0;721 client->ps.powerups[ i ] = 0; 703 722 } 704 723 } 705 724 else 706 725 { 707 for( i = 0; i < MAX_ MISC; i++ )708 client->ps. misc[ i ] = 0;726 for( i = 0; i < MAX_POWERUPS; i++ ) 727 client->ps.powerups[ i ] = 0; 709 728 } 710 729 730 case WP_BLASTER: 711 731 //update build timer 712 732 if( client->ps.stats[ STAT_MISC ] > 0 ) … … 732 752 { 733 753 ent->client->medKitHealthToRestore--; 734 ent->health++;754 do_health( ent,1 ); 735 755 } 736 756 else … … 747 767 { 748 768 ent->client->medKitHealthToRestore--; 749 ent->health++;769 do_health( ent,1 ); 750 770 751 771 client->medKitIncrementTime = level.time + … … 762 782 { 763 783 client->time1000 -= 1000; 784 785 //jetpack power management 786 if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) ) 787 { 788 if(BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) ) 789 { 790 if(g_jetpackLimit.integer > 0) 791 { 792 //decrease jetpack power 793 if(client->jetpack_power > 0) 794 { 795 client->jetpack_power--; 796 797 //if no power, can't reactive jetpack for a moment 798 if(client->jetpack_power == 0) 799 client->jetpack_beat = g_jetpackLimit.integer / 10; 800 } 801 } 802 } 803 else 804 { 805 //recover jetpack 806 if(client->jetpack_beat > 0) 807 client->jetpack_beat--; 808 else if( level.reactorPresent && client->jetpack_power < g_jetpackLimit.integer) 809 client->jetpack_power++; 810 } 811 } 764 812 765 813 //client is poison clouded … … 825 873 if( ent->health > 0 && ent->health < client->ps.stats[ STAT_MAX_HEALTH ] && 826 874 ( ent->lastDamageTime + ALIEN_REGEN_DAMAGE_TIME ) < level.time ) 827 ent->health += BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ) * modifier;875 do_health( ent,BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ) * modifier ); 828 876 829 877 if( ent->health > client->ps.stats[ STAT_MAX_HEALTH ] ) … … 852 900 if( client->ps.weapon == WP_ALEVEL3_UPG ) 853 901 { 854 int maxAmmo;902 int ammo, maxAmmo; 855 903 856 904 BG_FindAmmoForWeapon( WP_ALEVEL3_UPG, &maxAmmo, NULL ); 857 858 if( client->ps.ammo < maxAmmo ) 859 client->ps.ammo++; 905 BG_UnpackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, &ammo, NULL ); 906 907 if( ammo < maxAmmo ) 908 { 909 ammo++; 910 BG_PackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, ammo, 0 ); 911 } 860 912 } 861 913 } … … 1330 1382 msec = 200; 1331 1383 1332 client->unlaggedTime = ucmd->serverTime; 1384 if( ucmd->serverTime < level.time - g_unlagged.integer ) 1385 client->unlaggedTime = level.time - g_unlagged.integer; 1386 else 1387 client->unlaggedTime = ucmd->serverTime; 1333 1388 1334 1389 if( pmove_msec.integer < 8 ) … … 1361 1416 SpectatorThink( ent, ucmd ); 1362 1417 return; 1418 } 1419 1420 if (g_freeFunds.integer) 1421 { 1422 // give full evo/credits 1423 if (client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS) 1424 { 1425 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS; 1426 } 1427 else 1428 { 1429 client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS; 1430 } 1363 1431 } 1364 1432 … … 1474 1542 } 1475 1543 1476 //switch jetpack off if no reactor 1477 if( !level.reactorPresent ) 1544 //switch jetpack off if no power 1545 if( g_jetpackLimit.integer && (client->jetpack_beat || !client->jetpack_power)) 1546 { 1478 1547 BG_DeactivateUpgrade( UP_JETPACK, client->ps.stats ); 1548 1549 trap_SendServerCommand( ent - g_entities, 1550 "print \"Your jetpack is out of power\n\"" ); 1551 } 1479 1552 } 1480 1553 … … 1766 1839 cl = &level.clients[ clientNum ]; 1767 1840 1768 if( cl->pers.connected == CON_CONNECTED && cl->sess.sessionTeam != TEAM_SPECTATOR)1841 if( cl->pers.connected == CON_CONNECTED ) 1769 1842 { 1770 1843 flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) | … … 1776 1849 ent->client->ps.ping = ping; 1777 1850 ent->client->ps.pm_flags |= PMF_FOLLOW; 1851 ent->client->ps.pm_flags &= ~PMF_QUEUED; 1778 1852 ent->client->ps.eFlags = flags; 1779 1853 } … … 1794 1868 { 1795 1869 clientPersistant_t *pers; 1870 1871 if (ent->client->pers.floodTimer) 1872 { 1873 ent->client->pers.floodTimer -= 5; 1874 if (ent->client->pers.floodTimer < 0) 1875 ent->client->pers.floodTimer = 0; 1876 } 1796 1877 1797 1878 if( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) … … 1839 1920 } 1840 1921 1841 1922 void do_health( gentity_t *ent, int quantity ) 1923 { 1924 int i = 0; 1925 1926 if( ent->health == ent->client->ps.stats[ STAT_MAX_HEALTH ] ) 1927 return; 1928 1929 ent->health += quantity; 1930 if( ent->health >= ent->client->ps.stats[ STAT_MAX_HEALTH ] ) 1931 { 1932 ent->health = ent->client->ps.stats[ STAT_MAX_HEALTH ]; 1933 for( i = 0; i < MAX_CLIENTS; i++ ) 1934 ent->credits[ i ] = 0; 1935 } 1936 } 1937 -
src/game/g_active.c
r123 r124 202 202 203 203 // alien mass is directly related to their health points 204 // human mass is 200, double for bsuit 204 // human mass is 200, double for bsuit 205 205 if( ent->client->pers.teamSelection == PTE_ALIENS ) 206 206 { … … 270 270 // see G_UnlaggedDetectCollisions(), this is the inverse of that. 271 271 // if our movement is blocked by another player's real position, 272 // don't use the unlagged position for them because they are 272 // don't use the unlagged position for them because they are 273 273 // blocking or server-side Pmove() from reaching it 274 274 if( other->client && other->client->unlaggedCalc.used ) … … 1054 1054 G_UnlaggedStore 1055 1055 1056 Called on every server frame. Stores position data for the client at that 1057 into client->unlaggedHist[] and the time into level.unlaggedTimes[]. 1056 Called on every server frame. Stores position data for the client at that 1057 into client->unlaggedHist[] and the time into level.unlaggedTimes[]. 1058 1058 This data is used by G_UnlaggedCalc() 1059 1059 ============== … … 1064 1064 gentity_t *ent; 1065 1065 unlagged_t *save; 1066 1066 1067 1067 if( !g_unlagged.integer ) 1068 1068 return; 1069 level.unlaggedIndex++; 1069 level.unlaggedIndex++; 1070 1070 if( level.unlaggedIndex >= MAX_UNLAGGED_MARKERS ) 1071 1071 level.unlaggedIndex = 0; 1072 1072 1073 1073 level.unlaggedTimes[ level.unlaggedIndex ] = level.time; 1074 1074 1075 1075 for( i = 0; i < level.maxclients; i++ ) 1076 1076 { 1077 1077 ent = &g_entities[ i ]; 1078 1078 save = &ent->client->unlaggedHist[ level.unlaggedIndex ]; 1079 save->used = qfalse; 1079 save->used = qfalse; 1080 1080 if( !ent->r.linked || !( ent->r.contents & CONTENTS_BODY ) ) 1081 1081 continue; 1082 1082 if( ent->client->pers.connected != CON_CONNECTED ) 1083 continue; 1083 continue; 1084 1084 VectorCopy( ent->r.mins, save->mins ); 1085 1085 VectorCopy( ent->r.maxs, save->maxs ); … … 1092 1092 ============== 1093 1093 G_UnlaggedClear 1094 1094 1095 1095 Mark all unlaggedHist[] markers for this client invalid. Useful for 1096 1096 preventing teleporting and death. … … 1124 1124 if( !g_unlagged.integer ) 1125 1125 return; 1126 1126 1127 1127 // clear any calculated values from a previous run 1128 1128 for( i = 0; i < level.maxclients; i++ ) … … 1156 1156 if( frameMsec > 0 ) 1157 1157 { 1158 lerp = ( float )( time - level.unlaggedTimes[ startIndex ] ) 1159 / ( float )frameMsec;1160 } 1161 1158 lerp = ( float )( time - level.unlaggedTimes[ startIndex ] ) / 1159 ( float )frameMsec; 1160 } 1161 1162 1162 for( i = 0; i < level.maxclients; i++ ) 1163 1163 { … … 1200 1200 int i = 0; 1201 1201 gentity_t *ent; 1202 1202 1203 1203 if( !g_unlagged.integer ) 1204 1204 return; 1205 1205 1206 1206 for( i = 0; i < level.maxclients; i++ ) 1207 1207 { … … 1236 1236 gentity_t *ent; 1237 1237 unlagged_t *calc; 1238 1238 1239 1239 if( !g_unlagged.integer ) 1240 1240 return; 1241 1241 1242 1242 for( i = 0; i < level.maxclients; i++ ) 1243 1243 { … … 1260 1260 1261 1261 if( Distance( muzzle, calc->origin ) > range + maxRadius ) 1262 continue; 1262 continue; 1263 1263 } 1264 1264 … … 1828 1828 gclient_t *cl; 1829 1829 int clientNum, flags; 1830 int score, ping; 1830 1831 1831 1832 // if we are doing a chase cam or a remote view, grab the latest info … … 1842 1843 flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) | 1843 1844 ( ent->client->ps.eFlags & ( EF_VOTED | EF_TEAMVOTED ) ); 1845 score = ent->client->ps.persistant[ PERS_SCORE ]; 1846 ping = ent->client->ps.ping; 1844 1847 ent->client->ps = cl->ps; 1845 ent->client->ps.eFlags = flags; 1848 ent->client->ps.persistant[ PERS_SCORE ] = score; 1849 ent->client->ps.ping = ping; 1846 1850 ent->client->ps.pm_flags |= PMF_FOLLOW; 1847 1851 ent->client->ps.pm_flags &= ~PMF_QUEUED; 1852 ent->client->ps.eFlags = flags; 1848 1853 } 1849 1854 } -
src/game/g_admin.c
r120 r124 76 76 }, 77 77 78 {"info", G_admin_info, "H", 79 "read the server's information files", 80 "(^5subject^7)" 81 }, 82 78 83 {"kick", G_admin_kick, "k", 79 84 "kick a player with an optional reason", … … 83 88 {"listadmins", G_admin_listadmins, "D", 84 89 "display a list of all server admins and their levels", 85 "(^5name|start admin#^7) "90 "(^5name|start admin#^7) (^5minimum level to display^7)" 86 91 }, 87 92 … … 135 140 "" 136 141 }, 142 143 {"register", G_admin_register, "R", 144 "Registers your name to protect it from being used by others or updates your admin name to your current name.", 145 "" 146 }, 137 147 138 148 {"rename", G_admin_rename, "N", … … 142 152 143 153 {"restart", G_admin_restart, "r", 144 "restart the current map (optionally using named layout )",145 "(^5layout^7) "154 "restart the current map (optionally using named layout or keeping/switching teams)", 155 "(^5layout^7) (^5keepteams|switchteams^7)" 146 156 }, 147 157 … … 156 166 }, 157 167 168 {"slap", G_admin_slap, "x", 169 "assert your authoritay!", 170 "[^3name|slot^7] (damage)" 171 }, 172 158 173 {"spec999", G_admin_spec999, "P", 159 174 "move 999 pingers to the spectator team", … … 177 192 "unmute a muted player", 178 193 "[^3name|slot#^7]" 194 }, 195 196 { 197 "warn", G_admin_warn, "w", 198 "Warn a player to cease or face admin intervention", 199 "[^3name|slot#^7] [reason]" 179 200 } 180 201 }; … … 189 210 g_admin_namelog_t *g_admin_namelog[ MAX_ADMIN_NAMELOGS ]; 190 211 191 qboolean G_admin_permission( gentity_t *ent, char flag ) 212 213 qboolean G_admin_guid_permission( char *guid, char flag ) 192 214 { 193 215 int i; … … 195 217 char *flags; 196 218 197 // console always wins198 if( !ent )199 return qtrue;200 201 219 for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ ) 202 220 { 203 if( !Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) )221 if( !Q_stricmp( guid, g_admin_admins[ i ]->guid ) ) 204 222 { 205 223 flags = g_admin_admins[ i ]->flags; … … 263 281 } 264 282 283 qboolean G_admin_permission( gentity_t *ent, char flag ) 284 { 285 // console always wins 286 if( !ent ) 287 return qtrue; 288 289 return G_admin_guid_permission( ent->client->pers.guid, flag ); 290 } 291 265 292 qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len ) 266 293 { … … 269 296 char testName[ MAX_NAME_LENGTH ] = {""}; 270 297 char name2[ MAX_NAME_LENGTH ] = {""}; 298 int alphaCount = 0; 271 299 272 300 G_SanitiseName( name, name2 ); … … 274 302 if( !Q_stricmp( name2, "UnnamedPlayer" ) ) 275 303 return qtrue; 304 305 if( !Q_stricmp( name2, "console" ) ) 306 { 307 Q_strncpyz( err, va( "The name '%s^7' is invalid here", name2 ), 308 len ); 309 return qfalse; 310 } 276 311 277 312 for( i = 0; i < level.maxclients; i++ ) … … 292 327 return qfalse; 293 328 } 329 } 330 331 if( '0' <= name2[ 0 ] && name2[ 0 ] <= '9' ) 332 { 333 Q_strncpyz( err, "Names cannot begin with a number. Please choose another.", len ); 334 return qfalse; 335 } 336 337 for( i = 0; name2[ i ] !='\0'; i++) 338 { 339 if( Q_isalpha( name2[ i ] ) ) 340 alphaCount++; 341 if( name2[ i ] == '/' ) 342 { 343 if( name2[ i + 1 ] == '/' || name2[ i + 1 ] == '*' ) 344 { 345 Q_strncpyz( err, "Names cannot contain '//' or '/*'. Please choose another.", len ); 346 return qfalse; 347 } 348 } 349 } 350 351 if( alphaCount == 0 ) 352 { 353 Q_strncpyz( err, va( "The name '%s^7' does not include at least one letter. Please choose another.", name ), len ); 354 return qfalse; 294 355 } 295 356 … … 305 366 Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) ) 306 367 { 307 Q_strncpyz( err, va( "The name '%s^7' belongs to an admin ,"308 " please use another name", name ), len );368 Q_strncpyz( err, va( "The name '%s^7' belongs to an admin. " 369 "Please choose another.", name ), len ); 309 370 return qfalse; 310 371 } … … 561 622 Q_strncpyz( g_admin_levels[ 3 ]->name, "^2Junior Admin", 562 623 sizeof( l->name ) ); 563 Q_strncpyz( g_admin_levels[ 3 ]->flags, "iahCpPkm $", sizeof( l->flags ) );624 Q_strncpyz( g_admin_levels[ 3 ]->flags, "iahCpPkm?$", sizeof( l->flags ) ); 564 625 565 626 Q_strncpyz( g_admin_levels[ 4 ]->name, "^3Senior Admin", 566 627 sizeof( l->name ) ); 567 Q_strncpyz( g_admin_levels[ 4 ]->flags, "iahCpPkmBbe$ ", sizeof( l->flags ) );628 Q_strncpyz( g_admin_levels[ 4 ]->flags, "iahCpPkmBbe$?", sizeof( l->flags ) ); 568 629 569 630 Q_strncpyz( g_admin_levels[ 5 ]->name, "^1Server Operator", … … 724 785 } 725 786 726 static int admin_listadmins( gentity_t *ent, int start, char *search )787 static int admin_listadmins( gentity_t *ent, int start, char *search, int minlevel ) 727 788 { 728 789 int drawn = 0; … … 784 845 drawn < MAX_ADMIN_LISTITEMS; i++ ) 785 846 { 786 if( search[ 0 ] ) 787 { 788 G_SanitiseName( g_admin_admins[ i ]->name, name ); 789 if( !strstr( name, search ) ) 790 continue; 791 792 // verify we don't have the same guid/name pair in connected players 793 // since we don't want to draw the same player twice 794 dup = qfalse; 795 for( j = 0; j < level.maxclients; j++ ) 796 { 797 vic = &g_entities[ j ]; 798 if( !vic->client || vic->client->pers.connected != CON_CONNECTED ) 847 if( g_admin_admins[ i ]->level >= minlevel ) 848 { 849 if( search[ 0 ] ) 850 { 851 G_SanitiseName( g_admin_admins[ i ]->name, name ); 852 if( !strstr( name, search ) ) 799 853 continue; 800 G_SanitiseName( vic->client->pers.netname, name2 ); 801 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) && 802 strstr( name2, search ) ) 854 855 // verify we don't have the same guid/name pair in connected players 856 // since we don't want to draw the same player twice 857 dup = qfalse; 858 for( j = 0; j < level.maxclients; j++ ) 803 859 { 804 dup = qtrue; 860 vic = &g_entities[ j ]; 861 if( !vic->client || vic->client->pers.connected != CON_CONNECTED ) 862 continue; 863 G_SanitiseName( vic->client->pers.netname, name2 ); 864 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) && 865 strstr( name2, search ) ) 866 { 867 dup = qtrue; 868 break; 869 } 870 } 871 if( dup ) 872 continue; 873 } 874 for( j = 0; j <= 8; j++ ) 875 guid_stub[ j ] = g_admin_admins[ i ]->guid[ j + 24 ]; 876 guid_stub[ j ] = '\0'; 877 878 lname[ 0 ] = '\0'; 879 Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 880 for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) 881 { 882 if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level ) 883 { 884 G_DecolorString( g_admin_levels[ j ]->name, lname ); 885 Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is", 886 ( admin_level_maxname + strlen( g_admin_levels[ j ]->name ) 887 - strlen( lname ) ) ); 888 Com_sprintf( lname, sizeof( lname ), lname_fmt, 889 g_admin_levels[ j ]->name ); 805 890 break; 806 891 } 807 892 } 808 if( dup ) 809 continue; 810 } 811 for( j = 0; j <= 8; j++ ) 812 guid_stub[ j ] = g_admin_admins[ i ]->guid[ j + 24 ]; 813 guid_stub[ j ] = '\0'; 814 815 lname[ 0 ] = '\0'; 816 Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 817 for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) 818 { 819 if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level ) 820 { 821 G_DecolorString( g_admin_levels[ j ]->name, lname ); 822 Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is", 823 ( admin_level_maxname + strlen( g_admin_levels[ j ]->name ) 824 - strlen( lname ) ) ); 825 Com_sprintf( lname, sizeof( lname ), lname_fmt, 826 g_admin_levels[ j ]->name ); 827 break; 828 } 829 } 830 ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n", 831 ( i + MAX_CLIENTS ), 832 g_admin_admins[ i ]->level, 833 lname, 834 guid_stub, 835 g_admin_admins[ i ]->name ) ); 836 drawn++; 893 ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n", 894 ( i + MAX_CLIENTS ), 895 g_admin_admins[ i ]->level, 896 lname, 897 guid_stub, 898 g_admin_admins[ i ]->name ) ); 899 drawn++; 900 } 837 901 } 838 902 ADMBP_end(); … … 955 1019 if( admin_command_permission( ent, cmd ) ) 956 1020 { 1021 int j; 1022 trap_Cvar_Register( NULL, "arg_all", "", CVAR_TEMP | CVAR_ROM | CVAR_USER_CREATED ); 1023 trap_Cvar_Set( "arg_all", G_SayConcatArgs( skip + 1 ) ); 1024 trap_Cvar_Register( NULL, "arg_count", "", CVAR_TEMP | CVAR_ROM | CVAR_USER_CREATED ); 1025 trap_Cvar_Set( "arg_count", va( "%i", G_SayArgc() - ( skip + 1 ) ) ); 1026 trap_Cvar_Register( NULL, "arg_client", "", CVAR_TEMP | CVAR_ROM | CVAR_USER_CREATED ); 1027 trap_Cvar_Set( "arg_client", (ent) ? ent->client->pers.netname : "console" ); 1028 for (j = G_SayArgc() - ( skip + 1 ); j; j--) 1029 { 1030 char this_arg[ MAX_CVAR_VALUE_STRING ]; 1031 trap_Cvar_Register( NULL, va( "arg_%i", j ), "", CVAR_TEMP | CVAR_ROM | CVAR_USER_CREATED ); 1032 G_SayArgv( j + skip, this_arg, sizeof( this_arg ) ); 1033 trap_Cvar_Set( va( "arg_%i", j ), this_arg ); 1034 } 957 1035 trap_SendConsoleCommand( EXEC_APPEND, g_admin_commands[ i ]->exec ); 958 1036 admin_log( ent, cmd, skip ); … … 1470 1548 ADMP( "^3!setlevel:^7 more than one match. Use the admin number " 1471 1549 "instead:\n" ); 1472 admin_listadmins( ent, 0, name );1550 admin_listadmins( ent, 0, name, 0 ); 1473 1551 return qfalse; 1474 1552 } … … 1530 1608 char *ip, 1531 1609 int seconds, 1532 char *reason ) 1610 char *reason, 1611 int index ) 1533 1612 { 1534 1613 g_admin_ban_t *b = NULL; … … 1565 1644 else 1566 1645 Q_strncpyz( b->reason, reason, sizeof( b->reason ) ); 1567 for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ ) 1568 ; 1569 if( i == MAX_ADMIN_BANS ) 1570 { 1571 ADMP( "^3!ban: ^7too many bans\n" ); 1572 G_Free( b ); 1573 return qfalse; 1574 } 1646 1647 if (index == ADM_NEW_BAN) { 1648 for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ ) ; 1649 if( i == MAX_ADMIN_BANS ) 1650 { 1651 ADMP( "^3!ban: ^7too many bans\n" ); 1652 G_Free( b ); 1653 return qfalse; 1654 } 1655 } else i = index; 1575 1656 g_admin_bans[ i ] = b; 1576 1657 return qtrue; 1577 1658 } 1578 1659 1660 qboolean G_admin_slap( gentity_t *ent, int skiparg ) 1661 { 1662 int pids[ MAX_CLIENTS ], found, damage = 0; 1663 char name[ MAX_NAME_LENGTH ], err[ MAX_STRING_CHARS ], 1664 command[ MAX_ADMIN_CMD_LEN ], *cmd; 1665 gentity_t *vic; 1666 vec3_t dir; 1667 1668 if( level.intermissiontime ) return qfalse; 1669 1670 if( G_SayArgc() < 2 + skiparg ) 1671 { 1672 ADMP( "^3!slap: ^7usage: slap [name|slot#]\n" ); 1673 return qfalse; 1674 } 1675 G_SayArgv( skiparg, command, sizeof( command ) ); 1676 cmd = command; 1677 if( cmd && *cmd == '!' ) 1678 cmd++; 1679 G_SayArgv( 1 + skiparg, name, sizeof( name ) ); 1680 if( ( found = G_ClientNumbersFromString( name, pids, MAX_CLIENTS ) ) != 1 ) 1681 { 1682 G_MatchOnePlayer( pids, found, err, sizeof( err ) ); 1683 ADMP( va( "^3!slap: ^7%s\n", err ) ); 1684 return qfalse; 1685 } 1686 if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) ) 1687 { 1688 ADMP( "^3!slap: ^7sorry, but your intended victim has a higher admin" 1689 " level than you\n" ); 1690 return qfalse; 1691 } 1692 vic = &g_entities[ pids[ 0 ] ]; 1693 1694 // cant slap spectators 1695 if( vic->client->pers.teamSelection == PTE_NONE || 1696 vic->client->pers.classSelection == PCL_NONE ) { 1697 ADMP( "^3!slap: ^7can't slap thin air\n" ); 1698 return qfalse; 1699 } 1700 1701 // cant slap console? 1702 if( !vic ) { 1703 ADMP( "^3!slap: ^7bad target\n" ); 1704 return qfalse; 1705 } 1706 1707 // knockback in a random direction 1708 dir[0] = crandom(); 1709 dir[1] = crandom(); 1710 dir[2] = random(); 1711 if( (g_slapKnockback.integer) && vic->client ) 1712 { 1713 vec3_t ndir; 1714 vec3_t kvel; 1715 float mass; 1716 1717 mass = 200; 1718 1719 // Normalize (g_slapKnockback.integer) 1720 VectorCopy( dir, ndir ); 1721 VectorNormalize( ndir ); 1722 1723 // Halve (g_slapKnockback.integer) for bsuits 1724 if( vic->client && 1725 vic->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS && 1726 BG_InventoryContainsUpgrade( UP_BATTLESUIT, vic->client->ps.stats ) ) 1727 mass += 400; 1728 1729 // Halve (g_slapKnockback.integer) for crouching players 1730 if(vic->client->ps.pm_flags&PMF_DUCKED) (g_slapKnockback.integer) /= 2.f; 1731 1732 VectorScale( ndir, g_knockback.value * (g_slapKnockback.integer) / mass, kvel ); 1733 VectorAdd( vic->client->ps.velocity, kvel, vic->client->ps.velocity ); 1734 1735 // set the timer so that the other client can't cancel 1736 // out the movement immediately 1737 if( !vic->client->ps.pm_time ) 1738 { 1739 int t; 1740 1741 t = (g_slapKnockback.integer) * 2; 1742 if( t < 50 ) 1743 t = 50; 1744 1745 if( t > 200 ) 1746 t = 200; 1747 1748 vic->client->ps.pm_time = t; 1749 vic->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; 1750 } 1751 } 1752 1753 if( vic != ent ) 1754 trap_SendServerCommand( vic-g_entities, 1755 va( "cp \"%s^7 is not amused\n\"", 1756 ent ? ent->client->pers.netname : "console" ) ); 1757 1758 if( g_slapDamage.integer > 0 ) { 1759 1760 // !slap (name) [damage] syntax 1761 if( G_SayArgc() > 2 + skiparg ) { 1762 char dmg_str[ MAX_STRING_CHARS ]; 1763 G_SayArgv( 2 + skiparg, dmg_str, sizeof( dmg_str ) ); 1764 damage = atoi(dmg_str); 1765 if( damage < 0 ) damage = 0; 1766 } else { 1767 damage = BG_FindHealthForClass( vic->client->ps.stats[ STAT_PCLASS ] ) * 1768 ( g_slapDamage.integer > 100 ? 100 : g_slapDamage.integer ) / 100; 1769 1770 if( damage < 1 ) 1771 damage = 1; 1772 } 1773 1774 G_Damage( vic, NULL, NULL, NULL, NULL, damage, DAMAGE_NO_ARMOR, MOD_SLAP ); 1775 } 1776 1777 return qtrue; 1778 } 1579 1779 1580 1780 qboolean G_admin_kick( gentity_t *ent, int skiparg ) … … 1615 1815 vic->client->pers.guid, 1616 1816 vic->client->pers.ip, g_adminTempBan.integer, 1617 "automatic temp ban created by kick" ); 1817 "automatic temp ban created by kick", 1818 ADM_NEW_BAN ); 1618 1819 if( g_admin.string[ 0 ] ) 1619 1820 admin_writeconfig(); … … 1641 1842 char duration[ 32 ]; 1642 1843 int modifier = 1; 1643 int logmatch = -1, logmatches = 0 ;1844 int logmatch = -1, logmatches = 0, banmatches = 0, banmatch = -1; 1644 1845 int i, j; 1645 1846 qboolean exactmatch = qfalse; … … 1647 1848 char s2[ MAX_NAME_LENGTH ]; 1648 1849 char guid_stub[ 9 ]; 1850 qtime_t qt; 1851 int t; 1649 1852 1650 1853 if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) && … … 1670 1873 G_SanitiseName( search, s2 ); 1671 1874 G_SayArgv( 2 + skiparg, secs, sizeof( secs ) ); 1875 1876 t = trap_RealTime( &qt ); 1672 1877 1673 1878 // support "w" (weeks), "d" (days), "h" (hours), and "m" (minutes) modifiers … … 1732 1937 { 1733 1938 // skip players in the namelog who have already been banned 1734 if( g_admin_namelog[ i ]->banned )1735 continue;1939 if( g_admin_namelog[ i ]->banned ) 1940 continue; 1736 1941 1737 1942 if( !Q_stricmp( g_admin_namelog[ i ]->ip, search ) ) … … 1760 1965 return qfalse; 1761 1966 } 1762 if( logmatches > 1 ) 1967 1968 // looking for banned clients that match the pattern, and for an eventually ban slot provided 1969 for ( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && !exactmatch; i++ ) 1970 { 1971 if( g_admin_bans[ i ]->expires != 0 && ( g_admin_bans[ i ]->expires - t ) < 1 ) 1972 continue; 1973 G_SanitiseName(g_admin_bans[i]->name, n2); 1974 if ( strstr(n2, s2) || 1975 !Q_stricmp(g_admin_bans[i]->ip, s2) || 1976 !Q_stricmp(g_admin_bans[i]->guid, s2 ) ) 1977 { 1978 banmatches++; 1979 banmatch = i; 1980 } 1981 if (!Q_stricmp (va( "%db", i), s2 ) ) 1982 { 1983 banmatches = 1; 1984 banmatch = i; 1985 exactmatch = qtrue; 1986 } 1987 } 1988 1989 G_admin_duration( ( seconds ) ? seconds : -1, 1990 duration, sizeof( duration ) ); 1991 1992 if( logmatches + banmatches > 1 ) 1763 1993 { 1764 1994 ADMBP_begin(); … … 1786 2016 } 1787 2017 } 2018 2019 for ( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && banmatches>=0; i++ ) { 2020 G_SanitiseName(g_admin_bans[i]->name, n2); 2021 if( g_admin_bans[ i ]->expires != 0 && ( g_admin_bans[ i ]->expires - t ) < 1 ) continue; 2022 if (strstr(n2, s2)) { 2023 for( j = 0; j <= 8; j++ ) guid_stub[ j ] = g_admin_bans[ i ]->guid[ j + 24 ]; 2024 guid_stub[ j ] = '\0'; 2025 ADMBP( va( "%-2s (*%s) %15s ^7'%s^7'\n", 2026 va( "%db", i ), 2027 guid_stub, 2028 g_admin_bans[ i ]->ip, 2029 g_admin_bans[ i ]->name )); 2030 } 2031 } 1788 2032 ADMBP_end(); 1789 2033 return qfalse; 1790 2034 } 1791 1792 G_admin_duration( ( seconds ) ? seconds : -1, 1793 duration, sizeof( duration ) ); 1794 1795 if( ent && !admin_higher_guid( ent->client->pers.guid, 1796 g_admin_namelog[ logmatch ]->guid ) ) 1797 { 1798 1799 ADMP( "^3!ban: ^7sorry, but your intended victim has a higher admin" 1800 " level than you\n" ); 1801 return qfalse; 1802 } 1803 1804 admin_create_ban( ent, 1805 g_admin_namelog[ logmatch ]->name[ 0 ], 1806 g_admin_namelog[ logmatch ]->guid, 1807 g_admin_namelog[ logmatch ]->ip, 1808 seconds, reason ); 1809 1810 g_admin_namelog[ logmatch ]->banned = qtrue; 1811 1812 if( !g_admin.string[ 0 ] ) 1813 ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 1814 else 1815 admin_writeconfig(); 1816 1817 if( g_admin_namelog[ logmatch ]->slot == -1 ) 1818 { 1819 // client is already disconnected so stop here 2035 else if( banmatch != -1 ) 2036 { 2037 ADMP( "^3!ban: ^7client already banned, ban adjusted\n" ); 2038 2039 admin_create_ban( ent, 2040 g_admin_bans[banmatch]->name, 2041 g_admin_bans[banmatch]->guid, 2042 g_admin_bans[banmatch]->ip, 2043 seconds, reason, banmatch ); 2044 2045 if( !g_admin.string[ 0 ] ) 2046 ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 2047 else 2048 admin_writeconfig(); 2049 1820 2050 AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 1821 2051 "duration: %s, reason: %s\n\"", 1822 g_admin_ namelog[ logmatch ]->name[ 0 ],2052 g_admin_bans[banmatch]->name, 1823 2053 ( ent ) ? ent->client->pers.netname : "console", 1824 2054 duration, 1825 2055 ( *reason ) ? reason : "banned by admin" ) ); 2056 2057 return qtrue; 2058 } 2059 else if (!logmatches) 2060 { 2061 2062 ADMP( "^3!ban: ^7no player found by that name, IP, or slot number\n" ); 2063 return qfalse; 2064 2065 } 2066 else 2067 { 2068 if( ent && !admin_higher_guid( ent->client->pers.guid, 2069 g_admin_namelog[ logmatch ]->guid ) ) 2070 { 2071 2072 ADMP( "^3!ban: ^7sorry, but your intended victim has a higher admin" 2073 " level than you\n" ); 2074 return qfalse; 2075 } 2076 2077 admin_create_ban( ent, 2078 g_admin_namelog[ logmatch ]->name[ 0 ], 2079 g_admin_namelog[ logmatch ]->guid, 2080 g_admin_namelog[ logmatch ]->ip, 2081 seconds, reason, banmatch ); 2082 2083 g_admin_namelog[ logmatch ]->banned = qtrue; 2084 2085 if( !g_admin.string[ 0 ] ) 2086 ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 2087 else 2088 admin_writeconfig(); 2089 2090 if( g_admin_namelog[ logmatch ]->slot == -1 ) 2091 { 2092 // client is already disconnected so stop here 2093 AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 2094 "duration: %s, reason: %s\n\"", 2095 g_admin_namelog[ logmatch ]->name[ 0 ], 2096 ( ent ) ? ent->client->pers.netname : "console", 2097 duration, 2098 ( *reason ) ? reason : "banned by admin" ) ); 2099 return qtrue; 2100 } 2101 2102 trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot, 2103 va( "disconnect \"You have been banned.\n" 2104 "admin:\n%s^7\nduration:\n%s\nreason:\n%s\"", 2105 ( ent ) ? ent->client->pers.netname : "console", 2106 duration, 2107 ( *reason ) ? reason : "kicked by admin" ) ); 2108 2109 trap_DropClient( g_admin_namelog[ logmatch ]->slot, 2110 va( "has been banned by %s^7 duration: %s, reason: %s", 2111 ( ent ) ? ent->client->pers.netname : "console", 2112 duration, 2113 ( *reason ) ? reason : "banned by admin" ) ); 1826 2114 return qtrue; 1827 } 1828 1829 trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot, 1830 va( "disconnect \"You have been banned.\n" 1831 "admin:\n%s^7\nduration:\n%s\nreason:\n%s\"", 1832 ( ent ) ? ent->client->pers.netname : "console", 1833 duration, 1834 ( *reason ) ? reason : "kicked by admin" ) ); 1835 1836 trap_DropClient( g_admin_namelog[ logmatch ]->slot, 1837 va( "has been banned by %s^7 duration: %s, reason: %s", 1838 ( ent ) ? ent->client->pers.netname : "console", 1839 duration, 1840 ( *reason ) ? reason : "banned by admin" ) ); 1841 return qtrue; 2115 2116 } 1842 2117 } 1843 2118 … … 2102 2377 qboolean numeric = qtrue; 2103 2378 int drawn = 0; 2379 int minlevel = 1; 2380 2381 if( G_SayArgc() == 3 + skiparg ) 2382 { 2383 G_SayArgv( 2 + skiparg, s, sizeof( s ) ); 2384 if( s[ 0 ] >= '0' && s[ 0] <= '9' ) 2385 { 2386 minlevel = atoi( s ); 2387 if( minlevel < 1 ) 2388 minlevel = 1; 2389 } 2390 } 2104 2391 2105 2392 for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ ) 2106 2393 { 2107 if( g_admin_admins[ i ]->level == 0 ) 2108 continue; 2109 found++; 2394 if( g_admin_admins[ i ]->level >= minlevel ) 2395 found++; 2110 2396 } 2111 2397 if( !found ) 2112 2398 { 2113 ADMP( "^3!listadmins: ^7no admins defined\n" ); 2114 return qfalse; 2115 } 2116 2117 if( G_SayArgc() == 2 + skiparg ) 2399 if( minlevel > 1 ) 2400 { 2401 ADMP( va( "^3!listadmins: ^7no admins level %i or greater found\n", minlevel ) ); 2402 } 2403 else 2404 { 2405 ADMP( "^3!listadmins: ^7no admins defined\n" ); 2406 } 2407 return qfalse; 2408 } 2409 2410 if( G_SayArgc() >= 2 + skiparg ) 2118 2411 { 2119 2412 G_SayArgv( 1 + skiparg, s, sizeof( s ) ); … … 2139 2432 start = 0; 2140 2433 2141 if( start >= found ) 2142 { 2143 ADMP( va( "^3!listadmins: ^7listing %d admins\n", found ) ); 2144 return qfalse; 2145 } 2146 2147 drawn = admin_listadmins( ent, start, search ); 2434 drawn = admin_listadmins( ent, start, search, minlevel ); 2148 2435 2149 2436 if( search[ 0 ] ) 2150 2437 { 2151 ADMP( va( "^3!listadmins:^7 found %d admins matching '%s^7'\n", 2152 drawn, search ) ); 2438 if( drawn <= 20 ) 2439 { 2440 ADMP( va( "^3!listadmins:^7 found %d admins level %i or greater matching '%s^7'\n", 2441 drawn, minlevel, search ) ); 2442 } 2443 else 2444 { 2445 ADMP( va( "^3!listadmins:^7 found >20 admins level %i or greater matching '%s^7. Try a more narrow search.'\n", 2446 minlevel, search ) ); 2447 } 2153 2448 } 2154 2449 else 2155 2450 { 2156 2451 ADMBP_begin(); 2157 ADMBP( va( "^3!listadmins:^7 showing admin %d - %d of %d. ", 2452 ADMBP( va( "^3!listadmins:^7 showing admins level %i or greater %d - %d of %d. ", 2453 minlevel, 2158 2454 ( found ) ? ( start + 1 ) : 0, 2159 2455 ( ( start + MAX_ADMIN_LISTITEMS ) > found ) ? … … 2162 2458 if( ( start + MAX_ADMIN_LISTITEMS ) < found ) 2163 2459 { 2164 ADMBP( va( "run '!listadmins %d' to see more", 2165 ( start + MAX_ADMIN_LISTITEMS + 1 ) ) ); 2460 if( minlevel > 1) 2461 { 2462 ADMBP( va( "run '!listadmins %d %d' to see more", 2463 ( start + MAX_ADMIN_LISTITEMS + 1 ), minlevel ) ); 2464 } 2465 else 2466 { 2467 ADMBP( va( "run '!listadmins %d' to see more", 2468 ( start + MAX_ADMIN_LISTITEMS + 1 ) ) ); 2469 } 2166 2470 } 2167 2471 ADMBP( "\n" ); … … 2523 2827 if( !G_admin_permission( ent, g_admin_cmds[ i ].flag[ 0 ] ) ) 2524 2828 { 2525 ADMBP( va( "^3!help: ^7you have nopermission to use '%s'\n",2829 ADMBP( va( "^3!help: ^7you do not have permission to use '%s'\n", 2526 2830 g_admin_cmds[ i ].keyword ) ); 2527 2831 ADMBP_end(); … … 2563 2867 } 2564 2868 2869 qboolean G_admin_info( gentity_t *ent, int skiparg ) 2870 { 2871 int length; 2872 char filename[ MAX_OSPATH ], infoname[32]; 2873 char info[ MAX_STRING_CHARS ], message[ MAX_STRING_CHARS ]; 2874 fileHandle_t handle; 2875 if( G_SayArgc() < 2 + skiparg ) //if no subject use default 2876 Q_strncpyz( infoname, "default", 8 ); 2877 else //what subject? 2878 G_SayArgv( 1 + skiparg, infoname, sizeof( infoname ) ); 2879 Com_sprintf( filename, MAX_OSPATH, "info/info-%s.txt", infoname ); 2880 length = trap_FS_FOpenFile( filename, &handle, FS_READ ); 2881 if( !handle || !length ) //file not found or length 0 2882 { 2883 ADMP( va( "^3!info: %s not found, using default\n", infoname ) ); 2884 length = trap_FS_FOpenFile( "info/info-default.txt", &handle, FS_READ ); 2885 } 2886 if( handle && length ) //we have something printable 2887 { 2888 if( length > MAX_STRING_CHARS ) length = MAX_STRING_CHARS; 2889 trap_FS_Read( message, length, handle ); 2890 trap_FS_FCloseFile( handle ); 2891 message[length] = '\0'; 2892 G_admin_info_parse( message, info, MAX_STRING_CHARS ); 2893 ADMP( va( "%s\n", info ) ); 2894 } 2895 else 2896 { 2897 ADMP( "^3!info: no server info found\n" ); 2898 return qfalse; 2899 } //FAIL 2900 return qtrue; 2901 } 2902 2903 void G_admin_info_parse( char *unparsed, char *dest, int maxlength ) 2904 { //get unparsed, turn ${cvar} into value and do some escapes, 2905 //write maxlength chars to dest (including null-termination), 2906 //so only maxlength - 1 of useful stuff 2907 //not necessarily just for !info, needs more general name (and location) 2908 char cvarName[ 64 ], cvarValue[ MAX_CVAR_VALUE_STRING ], 2909 parsedCvar[ MAX_CVAR_VALUE_STRING ]; 2910 int i, j, cursor = 0; //i is our position in dest, cursor in unparsed 2911 if( unparsed == dest ) return; // this should never happen but can cause 2912 // a SIGSEGV if it does, so make sure 2913 for( i = 0; cursor <= strlen( unparsed ) && i < maxlength; i++ ) 2914 { //until we run out of space or unparsed 2915 if( unparsed[cursor] == '\\' ) 2916 { //some escaping 2917 if( unparsed[cursor + 1] == 'n' ) 2918 { 2919 dest[i] = '\n'; 2920 cursor++; //skip over this next loop 2921 } 2922 else if( unparsed[cursor + 1] == '\\' ) 2923 { 2924 dest[i] = '\\'; 2925 cursor++; //skip me 2926 } 2927 else if( unparsed[cursor + 1] == '$' ) 2928 { 2929 dest[i] = '$'; 2930 cursor++; //skip me 2931 } 2932 } 2933 else if( unparsed[cursor] == '$' ) 2934 { //read variable 2935 cursor += 2; //skip the ${ 2936 for( j = 0; j < 64 && unparsed[cursor] != '}'; j++ ) 2937 { //read into cvarName until } 2938 cvarName[ j ] = unparsed[cursor]; 2939 cursor++; //and skip over it 2940 } // I could probably do this with an sprintf instead but what difference 2941 // does it make? 2942 cvarName[ j ] = '\0'; //YOU ARE TERMINATED 2943 trap_Cvar_VariableStringBuffer( cvarName, cvarValue, MAX_CVAR_VALUE_STRING ); 2944 G_admin_info_parse( cvarValue, parsedCvar, MAX_STRING_CHARS ); 2945 //erk recursion, possible high CPU use? 2946 Com_sprintf( dest, maxlength, "%s%s", dest, parsedCvar ); 2947 i += strlen( parsedCvar ) - 1; //-1 so we overwrite the null-termination 2948 } 2949 else 2950 dest[i] = unparsed[cursor]; //nothing special so just copy it 2951 cursor++; //move to the next unparsed 2952 } 2953 dest[ maxlength ] = '\0'; //I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE 2954 } 2955 2565 2956 qboolean G_admin_admintest( gentity_t *ent, int skiparg ) 2566 2957 { … … 2701 3092 } 2702 3093 3094 3095 3096 qboolean G_admin_register(gentity_t *ent, int skiparg ){ 3097 int level = 0; 3098 3099 level = G_admin_level(ent); 3100 3101 if( level == 0 ) 3102 level = 1; 3103 3104 if( !Q_stricmp( ent->client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ) 3105 { 3106 ADMP( va( "^3!register: ^7 You cannot register for name protection until you update your client. Please replace your client executable with the one at http://trem.tjw.org/backport/ and reconnect. Updating your client will also allow you to have faster map downloads.\n" ) ); 3107 return qfalse; 3108 } 3109 3110 if( Q_strncmp( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string) -1 ) == 0 ) 3111 { 3112 ADMP( va( "^3!register: ^7 You cannot register for name protection until you change your name. \n" ) ); 3113 return qfalse; 3114 } 3115 3116 trap_SendConsoleCommand( EXEC_APPEND,va( "!setlevel %d %d;",ent - g_entities, level) ); 3117 ClientUserinfoChanged( ent - g_entities ); 3118 3119 AP( va( "print \"^3!register: ^7%s^7 is now a protected nickname.\n\"", ent->client->pers.netname) ); 3120 3121 return qtrue; 3122 } 3123 3124 3125 3126 3127 3128 qboolean G_admin_autoregister( gentity_t *ent ) { 3129 3130 int level; 3131 3132 if( !g_autoRegister.integer ) { 3133 return qtrue; 3134 } 3135 3136 level = 0; 3137 3138 level = G_admin_level(ent); 3139 if( level == 0 ) 3140 level = 1; 3141 3142 if( !Q_stricmp( ent->client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ) 3143 { 3144 return qfalse; 3145 } 3146 3147 if( Q_strncmp( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string) -1 ) == 0 ) 3148 { 3149 return qfalse; 3150 } 3151 trap_SendConsoleCommand( EXEC_APPEND,va( "!setlevel %d %d;",ent - g_entities, level) ); 3152 ClientUserinfoChanged( ent - g_entities ); 3153 3154 AP( va( "print \"^3!register: ^7%s^7 is now a protected nickname.\n\"", ent->client->pers.netname) ); 3155 3156 return qtrue; 3157 } 3158 3159 3160 2703 3161 qboolean G_admin_rename( gentity_t *ent, int skiparg ) 2704 3162 { … … 2746 3204 trap_SetUserinfo( pids[ 0 ], userinfo ); 2747 3205 ClientUserinfoChanged( pids[ 0 ] ); 2748 AP( va( "print \"^3!rename: ^7%s^7 has been renamed to %s^7 by %s\n\"", 2749 oldname, 2750 newname, 2751 ( ent ) ? ent->client->pers.netname : "console" ) ); 3206 if( strcmp( oldname, level.clients[ pids[ 0 ] ].pers.netname ) ) 3207 AP( va( "print \"^3!rename: ^7%s^7 has been renamed to %s^7 by %s\n\"", 3208 oldname, 3209 level.clients[ pids[ 0 ] ].pers.netname, 3210 ( ent ) ? ent->client->pers.netname : "console" ) ); 2752 3211 return qtrue; 2753 3212 } … … 2756 3215 { 2757 3216 char layout[ MAX_CVAR_VALUE_STRING ] = { "" }; 3217 char teampref[ MAX_CVAR_VALUE_STRING ] = { "" }; 3218 int i; 3219 gclient_t *cl; 2758 3220 2759 3221 if( G_SayArgc( ) > 1 + skiparg ) … … 2764 3226 G_SayArgv( skiparg + 1, layout, sizeof( layout ) ); 2765 3227 2766 if( !Q_stricmp( layout, "*BUILTIN*" ) || 2767 trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, layout ), 2768 NULL, FS_READ ) > 0 ) 2769 { 2770 trap_Cvar_Set( "g_layouts", layout ); 2771 } 2772 else 2773 { 2774 ADMP( va( "^3!restart: ^7layout '%s' does not exist\n", layout ) ); 2775 return qfalse; 2776 } 2777 } 2778 2779 trap_SendConsoleCommand( EXEC_APPEND, "map_restart" ); 2780 AP( va( "print \"^3!restart: ^7map restarted by %s %s\n\"", 3228 if( Q_stricmp( layout, "keepteams" ) && Q_stricmp( layout, "switchteams" ) ) 3229 { 3230 if( !Q_stricmp( layout, "*BUILTIN*" ) || 3231 trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, layout ), 3232 NULL, FS_READ ) > 0 ) 3233 { 3234 trap_Cvar_Set( "g_layouts", layout ); 3235 } 3236 else 3237 { 3238 ADMP( va( "^3!restart: ^7layout '%s' does not exist\n", layout ) ); 3239 return qfalse; 3240 } 3241 } 3242 else 3243 { 3244 strcpy(layout,""); 3245 G_SayArgv( skiparg + 1, teampref, sizeof( teampref ) ); 3246 } 3247 } 3248 3249 if( G_SayArgc( ) > 2 + skiparg ) 3250 { 3251 G_SayArgv( skiparg + 2, teampref, sizeof( teampref ) ); 3252 } 3253 3254 3255 if( !Q_stricmp( teampref, "keepteams" ) ) 3256 { 3257 for( i = 0; i < g_maxclients.integer; i++ ) 3258 { 3259 cl = level.clients + i; 3260 if( cl->pers.connected != CON_CONNECTED ) 3261 continue; 3262 3263 if( cl->pers.teamSelection == PTE_NONE ) 3264 continue; 3265 3266 cl->sess.restartTeam = cl->pers.teamSelection; 3267 } 3268 } 3269 else if(!Q_stricmp( teampref, "switchteams" ) ) 3270 { 3271 for( i = 0; i < g_maxclients.integer; i++ ) 3272 { 3273 cl = level.clients + i; 3274 if( cl->pers.connected != CON_CONNECTED ) 3275 continue; 3276 3277 if( cl->pers.teamSelection == PTE_NONE ) 3278 continue; 3279 3280 if( cl->pers.teamSelection == PTE_ALIENS ) 3281 cl->sess.restartTeam = PTE_HUMANS; 3282 else if(cl->pers.teamSelection == PTE_HUMANS ) 3283 cl->sess.restartTeam = PTE_ALIENS; 3284 } 3285 } 3286 3287 trap_SendConsoleCommand( EXEC_APPEND, "restartmap" ); 3288 3289 if(teampref[ 0 ]) 3290 strcpy(teampref,va( "(with teams option: '%s')", teampref )); 3291 3292 AP( va( "print \"^3!restart: ^7map restarted by %s %s %s\n\"", 2781 3293 ( ent ) ? ent->client->pers.netname : "console", 2782 ( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "" ) ); 3294 ( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "", 3295 teampref ) ); 2783 3296 return qtrue; 2784 3297 } … … 2835 3348 if( g_admin_namelog[ i ]->slot > -1 ) 2836 3349 ADMBP( "^3" ); 2837 ADMBP( va( "%-2s (*%s) %15s^7 ",2838 ( g_admin_namelog[ i ]->slot > -1 ) ?3350 ADMBP( va( "%-2s (*%s) %15s^7 %1s%1s", 3351 (g_admin_namelog[ i ]->slot > -1 ) ? 2839 3352 va( "%d", g_admin_namelog[ i ]->slot ) : "-", 2840 guid_stub, g_admin_namelog[ i ]->ip ) ); 3353 guid_stub, g_admin_namelog[ i ]->ip, 3354 ( g_entities[ g_admin_namelog[ i ]->slot ].client && 3355 g_entities[ g_admin_namelog[ i ]->slot ].client->pers.muted ? "M" : " " ), 3356 ( g_entities[ g_admin_namelog[ i ]->slot ].client && 3357 g_entities[ g_admin_namelog[ i ]->slot ].client->pers.denyBuild ? "B" : " " ) ) ); 2841 3358 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 2842 3359 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) … … 2941 3458 } 2942 3459 3460 //!Warn by Gate (Daniel Evans) 3461 qboolean G_admin_warn( gentity_t *ent, int skiparg ) 3462 { 3463 //mostly copy and paste with the proper lines altered from !mute and !kick 3464 int pids[ MAX_CLIENTS ], found; 3465 char name[ MAX_NAME_LENGTH ], *reason, err[ MAX_STRING_CHARS ]; 3466 int minargc; 3467 gentity_t *vic; 3468 3469 minargc = 3 + skiparg; 3470 if( G_admin_permission( ent, ADMF_UNACCOUNTABLE ) ) 3471 minargc = 2 + skiparg; 3472 3473 if( G_SayArgc() < minargc ) 3474 { 3475 ADMP( "^3!warn: ^7usage: warn [name] [reason]\n" ); 3476 return qfalse; 3477 } 3478 G_SayArgv( 1 + skiparg, name, sizeof( name ) ); 3479 reason = G_SayConcatArgs( 2 + skiparg ); 3480 3481 if( ( found = G_ClientNumbersFromString( name, pids, MAX_CLIENTS ) ) != 1 ) 3482 { 3483 G_MatchOnePlayer( pids, found, err, sizeof( err ) ); 3484 ADMP( va( "^3!warn: ^7%s\n", err ) ); 3485 return qfalse; 3486 } 3487 if( !admin_higher( ent, &g_entities[ pids[ 0 ] ] ) ) 3488 { 3489 ADMP( "^3!warn: ^7sorry, but your intended victim has a higher admin" 3490 " level than you.\n" ); 3491 return qfalse; 3492 } 3493 3494 vic = &g_entities[ pids[ 0 ] ]; 3495 //next line is the onscreen warning 3496 CPx( pids[ 0 ],va("cp \"^7%s\n^7%s%s\"", g_adminWarnMessage.string, (*reason)? "REASON: ^1" : "" ,(*reason)? reason : "") ); 3497 AP( va( "print \"^3!warn: ^7%s^7 has been warned by %s. %s%s\n\"", 3498 vic->client->pers.netname, 3499 ( ent ) ? ent->client->pers.netname : "console", //console announcement 3500 (*reason) ? "Reason: " : "", 3501 (*reason) ? reason : "" ) ); 3502 3503 ClientUserinfoChanged( pids[ 0 ] ); 3504 return qtrue; 3505 } 3506 2943 3507 /* 2944 3508 ================ -
src/game/g_admin.c
r122 r124 12 12 The functionality of this code mimics the behaviour of the currently 13 13 inactive project shrubet (http://www.etstats.com/shrubet/index.php?ver=2) 14 by Ryan Mannion. However, shrubet was a closed-source project and 14 by Ryan Mannion. However, shrubet was a closed-source project and 15 15 none of it's code has been copied, only it's functionality. 16 16 … … 37 37 38 38 // note: list ordered alphabetically 39 g_admin_cmd_t g_admin_cmds[ ] = 39 g_admin_cmd_t g_admin_cmds[ ] = 40 40 { 41 41 {"admintest", G_admin_admintest, "a", … … 48 48 "[^3name|slot#^7]" 49 49 }, 50 50 51 51 {"allready", G_admin_allready, "y", 52 52 "makes everyone ready in intermission", … … 85 85 "(^5reason^7)" 86 86 }, 87 87 88 88 {"listadmins", G_admin_listadmins, "D", 89 89 "display a list of all server admins and their levels", 90 90 "(^5name|start admin#^7) (^5minimum level to display^7)" 91 91 }, 92 92 93 93 {"listlayouts", G_admin_listlayouts, "L", 94 94 "display a list of all available layouts for a map", … … 100 100 "" 101 101 }, 102 102 103 103 {"lock", G_admin_lock, "K", 104 104 "lock a team to prevent anyone from joining it", 105 105 "[^3a|h^7]" 106 106 }, 107 107 108 108 {"map", G_admin_map, "M", 109 109 "load a map (and optionally force layout)", … … 115 115 "[^3name|slot#^7]" 116 116 }, 117 117 118 118 {"namelog", G_admin_namelog, "e", 119 119 "display a list of names used by recently connected players", … … 183 183 "[^3ban slot#^7]" 184 184 }, 185 185 186 186 {"unlock", G_admin_unlock, "K", 187 187 "unlock a locked team", … … 232 232 if( *flags == flag ) 233 233 return qfalse; 234 elseif( *flags == '+' )234 if( *flags == '+' ) 235 235 break; 236 236 } … … 244 244 } 245 245 // flags with significance only for individuals ( 246 // like ADMF_INCOGNITO and ADMF_IMMUTABLE are NOT covered 246 // like ADMF_INCOGNITO and ADMF_IMMUTABLE are NOT covered 247 247 // by the '*' wildcard. They must be specified manually. 248 switch( flag ) 249 { 250 case ADMF_INCOGNITO: 251 case ADMF_IMMUTABLE: 252 return qfalse; 253 default: 254 return qtrue; 255 } 248 return ( flag != ADMF_INCOGNITO && flag != ADMF_IMMUTABLE ); 256 249 } 257 250 flags++; … … 277 270 } 278 271 // flags with significance only for individuals ( 279 // like ADMF_INCOGNITO and ADMF_IMMUTABLE are NOT covered 272 // like ADMF_INCOGNITO and ADMF_IMMUTABLE are NOT covered 280 273 // by the '*' wildcard. They must be specified manually. 281 switch( flag ) 282 { 283 case ADMF_INCOGNITO: 284 case ADMF_IMMUTABLE: 285 return qfalse; 286 default: 287 return qtrue; 288 } 274 return ( flag != ADMF_INCOGNITO && flag != ADMF_IMMUTABLE ); 289 275 } 290 276 flags++; … … 314 300 G_SanitiseName( name, name2 ); 315 301 316 if( !Q_stricmp( name2, "UnnamedPlayer" ) ) 302 if( !Q_stricmp( name2, "UnnamedPlayer" ) ) 317 303 return qtrue; 318 304 … … 327 313 { 328 314 client = &level.clients[ i ]; 329 if( client->pers.connected != CON_CONNECTING 330 && client->pers.connected != CON_CONNECTED ) 331 { 315 if( client->pers.connected == CON_DISCONNECTED ) 332 316 continue; 333 }334 317 335 318 // can rename ones self to the same name using different colors … … 459 442 fileHandle_t f; 460 443 int len, i, j; 461 qtime_t qt;462 444 int t; 463 445 char levels[ MAX_STRING_CHARS ] = {""}; … … 469 451 return; 470 452 } 471 t = trap_RealTime( &qt);453 t = trap_RealTime( NULL ); 472 454 len = trap_FS_FOpenFile( g_admin.string, &f, FS_WRITE ); 473 455 if( len < 0 ) … … 510 492 // if expires is 0, then it's a perm ban 511 493 if( g_admin_bans[ i ]->expires != 0 && 512 ( g_admin_bans[ i ]->expires - t ) < 1 )494 ( g_admin_bans[ i ]->expires - t ) < 1 ) 513 495 continue; 514 496 … … 554 536 static void admin_readconfig_string( char **cnf, char *s, int size ) 555 537 { 556 char * t;538 char *t; 557 539 558 540 //COM_MatchToken(cnf, "="); … … 572 554 while( t[ 0 ] ) 573 555 { 574 if( ( s[ 0 ] == '\0' && strlen( t ) <= size ) 575 ||( strlen( t ) + strlen( s ) < size ) )556 if( ( s[ 0 ] == '\0' && strlen( t ) <= size ) || 557 ( strlen( t ) + strlen( s ) < size ) ) 576 558 { 577 559 … … 588 570 static void admin_readconfig_int( char **cnf, int *v ) 589 571 { 590 char * t;572 char *t; 591 573 592 574 //COM_MatchToken(cnf, "="); … … 610 592 static void admin_default_levels( void ) 611 593 { 612 g_admin_level_t * l;594 g_admin_level_t *l; 613 595 int i; 614 596 … … 640 622 Q_strncpyz( g_admin_levels[ 3 ]->name, "^2Junior Admin", 641 623 sizeof( l->name ) ); 642 Q_strncpyz( g_admin_levels[ 3 ]->flags, "iahCpPkm? ", sizeof( l->flags ) );643 624 Q_strncpyz( g_admin_levels[ 3 ]->flags, "iahCpPkm?$", sizeof( l->flags ) ); 625 644 626 Q_strncpyz( g_admin_levels[ 4 ]->name, "^3Senior Admin", 645 627 sizeof( l->name ) ); 646 Q_strncpyz( g_admin_levels[ 4 ]->flags, "iahCpPkmBbe ?", sizeof( l->flags ) );647 628 Q_strncpyz( g_admin_levels[ 4 ]->flags, "iahCpPkmBbe$?", sizeof( l->flags ) ); 629 648 630 Q_strncpyz( g_admin_levels[ 5 ]->name, "^1Server Operator", 649 631 sizeof( l->name ) ); … … 687 669 if( !ent ) 688 670 return qtrue; 689 level = ent->client->pers.adminLevel;671 level = ent->client->pers.adminLevel; 690 672 for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ ) 691 673 { … … 718 700 719 701 if( !g_adminLog.string[ 0 ] ) 720 return ;702 return; 721 703 722 704 … … 725 707 { 726 708 G_Printf( "admin_log: error could not open %s\n", g_adminLog.string ); 727 return ;709 return; 728 710 } 729 711 … … 815 797 int l = 0; 816 798 qboolean dup = qfalse; 817 799 818 800 ADMBP_begin(); 819 801 … … 825 807 if( vic->client && vic->client->pers.connected != CON_CONNECTED ) 826 808 continue; 827 809 828 810 l = vic->client->pers.adminLevel; 829 811 … … 835 817 guid_stub[ j ] = vic->client->pers.guid[ j + 24 ]; 836 818 guid_stub[ j ] = '\0'; 837 838 lname[ 0 ] = '\0'; 819 820 lname[ 0 ] = '\0'; 839 821 Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 840 822 for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) … … 860 842 } 861 843 862 for( i = start; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] 863 && drawn < MAX_ADMIN_LISTITEMS; i++ ) 864 if( g_admin_admins[ i ]->level >= minlevel ) 865 { 866 if( search[ 0 ] ) 867 { 868 G_SanitiseName( g_admin_admins[ i ]->name, name ); 869 if( !strstr( name, search ) ) 870 continue; 844 for( i = start; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ] && 845 drawn < MAX_ADMIN_LISTITEMS; i++ ) 846 { 847 if( g_admin_admins[ i ]->level >= minlevel ) 848 { 849 if( search[ 0 ] ) 850 { 851 G_SanitiseName( g_admin_admins[ i ]->name, name ); 852 if( !strstr( name, search ) ) 853 continue; 871 854 872 // verify we don't have the same guid/name pair in connected players873 // since we don't want to draw the same player twice874 dup = qfalse;875 for( j = 0; j < level.maxclients; j++ )876 {877 vic = &g_entities[ j ];878 if( !vic->client || vic->client->pers.connected != CON_CONNECTED )879 continue;880 G_SanitiseName( vic->client->pers.netname, name2 );881 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid )882 &&strstr( name2, search ) )883 {884 dup = qtrue;885 break;886 }887 }888 if( dup )889 continue;890 }891 for( j = 0; j <= 8; j++ )892 guid_stub[ j ] = g_admin_admins[ i ]->guid[ j + 24 ];893 guid_stub[ j ] = '\0';855 // verify we don't have the same guid/name pair in connected players 856 // since we don't want to draw the same player twice 857 dup = qfalse; 858 for( j = 0; j < level.maxclients; j++ ) 859 { 860 vic = &g_entities[ j ]; 861 if( !vic->client || vic->client->pers.connected != CON_CONNECTED ) 862 continue; 863 G_SanitiseName( vic->client->pers.netname, name2 ); 864 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) && 865 strstr( name2, search ) ) 866 { 867 dup = qtrue; 868 break; 869 } 870 } 871 if( dup ) 872 continue; 873 } 874 for( j = 0; j <= 8; j++ ) 875 guid_stub[ j ] = g_admin_admins[ i ]->guid[ j + 24 ]; 876 guid_stub[ j ] = '\0'; 894 877 895 lname[ 0 ] = '\0'; 896 Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 897 for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) 898 { 899 if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level ) 900 { 901 G_DecolorString( g_admin_levels[ j ]->name, lname ); 902 Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is", 903 ( admin_level_maxname + strlen( g_admin_levels[ j ]->name ) 904 - strlen( lname ) ) ); 905 Com_sprintf( lname, sizeof( lname ), lname_fmt, 906 g_admin_levels[ j ]->name ); 907 break; 908 } 909 } 910 ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n", 911 ( i + MAX_CLIENTS ), 912 g_admin_admins[ i ]->level, 913 lname, 914 guid_stub, 915 g_admin_admins[ i ]->name ) ); 916 drawn++; 917 } 878 lname[ 0 ] = '\0'; 879 Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 880 for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) 881 { 882 if( g_admin_levels[ j ]->level == g_admin_admins[ i ]->level ) 883 { 884 G_DecolorString( g_admin_levels[ j ]->name, lname ); 885 Com_sprintf( lname_fmt, sizeof( lname_fmt ), "%%%is", 886 ( admin_level_maxname + strlen( g_admin_levels[ j ]->name ) 887 - strlen( lname ) ) ); 888 Com_sprintf( lname, sizeof( lname ), lname_fmt, 889 g_admin_levels[ j ]->name ); 890 break; 891 } 892 } 893 ADMBP( va( "%4i %4i %s^7 (*%s) %s^7\n", 894 ( i + MAX_CLIENTS ), 895 g_admin_admins[ i ]->level, 896 lname, 897 guid_stub, 898 g_admin_admins[ i ]->name ) ); 899 drawn++; 900 } 901 } 918 902 ADMBP_end(); 919 903 return drawn; … … 948 932 char *guid, *ip; 949 933 int i; 950 qtime_t qt;951 934 int t; 952 953 *reason = '\0'; 954 t = trap_RealTime( &qt );935 936 *reason = '\0'; 937 t = trap_RealTime( NULL ); 955 938 if( !*userinfo ) 956 939 return qfalse; … … 978 961 duration 979 962 ); 980 G_Printf( "Banned player tried to connect from IP %s\n", ip);963 G_Printf( "Banned player tried to connect from IP %s\n", ip ); 981 964 return qtrue; 982 965 } … … 994 977 duration 995 978 ); 996 G_Printf( "Banned player tried to connect with GUID %s\n", guid);979 G_Printf( "Banned player tried to connect with GUID %s\n", guid ); 997 980 return qtrue; 998 981 } … … 1112 1095 } 1113 1096 1114 if( !Q_stricmp( client->pers.ip, g_admin_namelog[ i ]->ip ) 1115 &&!Q_stricmp( client->pers.guid, g_admin_namelog[ i ]->guid ) )1116 { 1117 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES 1118 &&g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )1097 if( !Q_stricmp( client->pers.ip, g_admin_namelog[ i ]->ip ) && 1098 !Q_stricmp( client->pers.guid, g_admin_namelog[ i ]->guid ) ) 1099 { 1100 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 1101 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 1119 1102 { 1120 1103 G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 ); 1121 if( !Q_stricmp( n1, n2 ) ) 1104 if( !Q_stricmp( n1, n2 ) ) 1122 1105 break; 1123 1106 } … … 1142 1125 namelog = G_Alloc( sizeof( g_admin_namelog_t ) ); 1143 1126 memset( namelog, 0, sizeof( namelog ) ); 1144 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES ; j++ )1127 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES; j++ ) 1145 1128 namelog->name[ j ][ 0 ] = '\0'; 1146 1129 Q_strncpyz( namelog->ip, client->pers.ip, sizeof( namelog->ip ) ); … … 1154 1137 qboolean G_admin_readconfig( gentity_t *ent, int skiparg ) 1155 1138 { 1156 g_admin_level_t * l = NULL;1139 g_admin_level_t *l = NULL; 1157 1140 g_admin_admin_t *a = NULL; 1158 1141 g_admin_ban_t *b = NULL; … … 1176 1159 } 1177 1160 1178 len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ) ;1161 len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ); 1179 1162 if( len < 0 ) 1180 1163 { … … 1378 1361 else if( !Q_stricmp( t, "[command]" ) ) 1379 1362 { 1380 if( bc >= MAX_ADMIN_COMMANDS )1363 if( cc >= MAX_ADMIN_COMMANDS ) 1381 1364 return qfalse; 1382 1365 c = G_Alloc( sizeof( g_admin_command_t ) ); … … 1390 1373 } 1391 1374 if( level_open ) 1392 {1393 1394 1375 g_admin_levels[ lc++ ] = l; 1395 }1396 1376 if( admin_open ) 1397 1377 g_admin_admins[ ac++ ] = a; … … 1409 1389 char n[ MAX_NAME_LENGTH ] = {""}; 1410 1390 int i = 0; 1411 1412 // max printable name length for formatting 1391 1392 // max printable name length for formatting 1413 1393 for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ ) 1414 1394 { … … 1424 1404 { 1425 1405 qtime_t qt; 1426 int t; 1427 1428 t = trap_RealTime( &qt ); 1406 1407 trap_RealTime( &qt ); 1429 1408 ADMP( va( "^3!time: ^7local time is %02i:%02i:%02i\n", 1430 1409 qt.tm_hour, qt.tm_min, qt.tm_sec ) ); … … 1459 1438 l = atoi( lstr ); 1460 1439 G_SanitiseName( testname, name ); 1461 for( i = 0; i < sizeof( name ) && name[ i ] ; i++ )1462 { 1463 if( name[ i ] < '0' || name[ i ] > '9')1440 for( i = 0; i < sizeof( name ) && name[ i ]; i++ ) 1441 { 1442 if( !isdigit( name[ i ] ) ) 1464 1443 { 1465 1444 numeric = qfalse; … … 1496 1475 } 1497 1476 1498 if( numeric && id >= 0 && id < level.maxclients )1477 if( numeric && id >= 0 && id < level.maxclients ) 1499 1478 vic = &g_entities[ id ]; 1500 1479 1501 if( vic && vic->client && vic->client->pers.connected == CON_CONNECTED ) 1502 { 1503 vic = &g_entities[ id ]; 1480 if( vic && vic->client && vic->client->pers.connected == CON_CONNECTED ) 1481 { 1504 1482 Q_strncpyz( adminname, vic->client->pers.netname, sizeof( adminname ) ); 1505 1483 Q_strncpyz( guid, vic->client->pers.guid, sizeof( guid ) ); … … 1544 1522 continue; 1545 1523 G_SanitiseName( vic->client->pers.netname, testname2 ); 1546 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) 1547 && strstr( testname2, name ) )1524 if( !Q_stricmp( vic->client->pers.guid, g_admin_admins[ i ]->guid ) && 1525 strstr( testname2, name ) ) 1548 1526 { 1549 1527 dup = qtrue; … … 1566 1544 return qfalse; 1567 1545 } 1568 elseif( matches > 1 )1546 if( matches > 1 ) 1569 1547 { 1570 1548 ADMP( "^3!setlevel:^7 more than one match. Use the admin number " … … 1611 1589 } 1612 1590 1613 AP( va( 1591 AP( va( 1614 1592 "print \"^3!setlevel: ^7%s^7 was given level %d admin rights by %s\n\"", 1615 1593 adminname, l, ( ent ) ? ent->client->pers.netname : "console" ) ); 1616 1594 if( vic ) 1617 1595 vic->client->pers.adminLevel = l; 1618 1596 1619 1597 if( !g_admin.string[ 0 ] ) 1620 1598 ADMP( "^3!setlevel: ^7WARNING g_admin not set, not saving admin record " … … 1842 1820 admin_writeconfig(); 1843 1821 } 1844 1822 1845 1823 trap_SendServerCommand( pids[ 0 ], 1846 1824 va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\"", … … 1910 1888 else if( secs[ lastchar ] == 'm' ) 1911 1889 modifier = 60; 1912 else if( secs[ lastchar ] < '0' || secs[ lastchar ] > '9')1890 else if( !isdigit( secs[ lastchar ] ) ) 1913 1891 secs[ lastchar ] = '\0'; 1914 1892 } … … 1945 1923 continue; 1946 1924 1947 if( !Q_stricmp( va( "%d", g_admin_namelog[ i ]->slot ), s 2) )1925 if( !Q_stricmp( va( "%d", g_admin_namelog[ i ]->slot ), search ) ) 1948 1926 { 1949 1927 logmatches = 1; … … 1962 1940 continue; 1963 1941 1964 if( !Q_stricmp( g_admin_namelog[ i ]->ip, s 2) )1942 if( !Q_stricmp( g_admin_namelog[ i ]->ip, search ) ) 1965 1943 { 1966 1944 logmatches = 1; … … 1969 1947 break; 1970 1948 } 1971 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 1972 { 1973 G_SanitiseName(g_admin_namelog[ i ]->name[ j ], n2); 1949 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 1950 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 1951 { 1952 G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 ); 1974 1953 if( strstr( n2, s2 ) ) 1975 1954 { 1976 1955 if( logmatch != i ) 1977 1956 logmatches++; 1978 logmatch = i; 1979 } 1980 } 1981 } 1982 1957 logmatch = i; 1958 } 1959 } 1960 } 1961 1962 if( !logmatches ) 1963 { 1964 ADMP( "^3!ban: ^7no player found by that name, IP, or slot number\n" ); 1965 return qfalse; 1966 } 1967 1983 1968 // looking for banned clients that match the pattern, and for an eventually ban slot provided 1984 for ( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && !exactmatch; i++ ) { 1985 if( g_admin_bans[ i ]->expires != 0 && ( g_admin_bans[ i ]->expires - t ) < 1 ) continue; 1969 for ( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && !exactmatch; i++ ) 1970 { 1971 if( g_admin_bans[ i ]->expires != 0 && ( g_admin_bans[ i ]->expires - t ) < 1 ) 1972 continue; 1986 1973 G_SanitiseName(g_admin_bans[i]->name, n2); 1987 if (strstr(n2, s2) || !Q_stricmp(g_admin_bans[i]->ip, s2) || !Q_stricmp(g_admin_bans[i]->guid, s2)) { 1974 if ( strstr(n2, s2) || 1975 !Q_stricmp(g_admin_bans[i]->ip, s2) || 1976 !Q_stricmp(g_admin_bans[i]->guid, s2 ) ) 1977 { 1988 1978 banmatches++; 1989 1979 banmatch = i; 1990 1980 } 1991 if (!Q_stricmp (va( "%db", i), s2)) { 1981 if (!Q_stricmp (va( "%db", i), s2 ) ) 1982 { 1992 1983 banmatches = 1; 1993 1984 banmatch = i; … … 2008 1999 guid_stub[ j ] = g_admin_namelog[ i ]->guid[ j + 24 ]; 2009 2000 guid_stub[ j ] = '\0'; 2010 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES 2011 &&g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ )2012 { 2013 G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2);2001 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 2002 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 2003 { 2004 G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 ); 2014 2005 if( strstr( n2, s2 ) ) 2015 2006 { … … 2017 2008 ADMBP( "^3" ); 2018 2009 ADMBP( va( "%-2s (*%s) %15s ^7'%s^7'\n", 2019 ( g_admin_namelog[ i ]->slot > -1) ?2010 ( g_admin_namelog[ i ]->slot > -1 ) ? 2020 2011 va( "%d", g_admin_namelog[ i ]->slot ) : "-", 2021 2012 guid_stub, … … 2065 2056 2066 2057 return qtrue; 2067 } else if (!logmatches) { 2058 } 2059 else if (!logmatches) 2060 { 2068 2061 2069 2062 ADMP( "^3!ban: ^7no player found by that name, IP, or slot number\n" ); 2070 2063 return qfalse; 2071 2064 2072 } else { 2073 2074 if( ent && !admin_higher_guid( ent->client->pers.guid, 2075 g_admin_namelog[ logmatch ]->guid ) ) 2076 { 2077 2078 ADMP( "^3!ban: ^7sorry, but your intended victim has a higher admin" 2079 " level than you\n" ); 2080 return qfalse; 2081 } 2082 2083 admin_create_ban( ent, 2084 g_admin_namelog[ logmatch ]->name[ 0 ], 2085 g_admin_namelog[ logmatch ]->guid, 2086 g_admin_namelog[ logmatch ]->ip, 2087 seconds, reason, ADM_NEW_BAN ); 2088 2089 g_admin_namelog[ logmatch ]->banned = qtrue; 2090 2091 if( !g_admin.string[ 0 ] ) 2092 ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 2065 } 2093 2066 else 2094 admin_writeconfig(); 2095 2096 if(g_admin_namelog[ logmatch ]->slot == -1 ) 2097 { 2098 // client is already disconnected so stop here 2099 AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 2100 "duration: %s, reason: %s\n\"", 2067 { 2068 if( ent && !admin_higher_guid( ent->client->pers.guid, 2069 g_admin_namelog[ logmatch ]->guid ) ) 2070 { 2071 2072 ADMP( "^3!ban: ^7sorry, but your intended victim has a higher admin" 2073 " level than you\n" ); 2074 return qfalse; 2075 } 2076 2077 admin_create_ban( ent, 2101 2078 g_admin_namelog[ logmatch ]->name[ 0 ], 2102 ( ent ) ? ent->client->pers.netname : "console", 2103 duration, 2104 ( *reason ) ? reason : "banned by admin" ) ); 2079 g_admin_namelog[ logmatch ]->guid, 2080 g_admin_namelog[ logmatch ]->ip, 2081 seconds, reason, banmatch ); 2082 2083 g_admin_namelog[ logmatch ]->banned = qtrue; 2084 2085 if( !g_admin.string[ 0 ] ) 2086 ADMP( "^3!ban: ^7WARNING g_admin not set, not saving ban to a file\n" ); 2087 else 2088 admin_writeconfig(); 2089 2090 if( g_admin_namelog[ logmatch ]->slot == -1 ) 2091 { 2092 // client is already disconnected so stop here 2093 AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 2094 "duration: %s, reason: %s\n\"", 2095 g_admin_namelog[ logmatch ]->name[ 0 ], 2096 ( ent ) ? ent->client->pers.netname : "console", 2097 duration, 2098 ( *reason ) ? reason : "banned by admin" ) ); 2099 return qtrue; 2100 } 2101 2102 trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot, 2103 va( "disconnect \"You have been banned.\n" 2104 "admin:\n%s^7\nduration:\n%s\nreason:\n%s\"", 2105 ( ent ) ? ent->client->pers.netname : "console", 2106 duration, 2107 ( *reason ) ? reason : "kicked by admin" ) ); 2108 2109 trap_DropClient( g_admin_namelog[ logmatch ]->slot, 2110 va( "has been banned by %s^7 duration: %s, reason: %s", 2111 ( ent ) ? ent->client->pers.netname : "console", 2112 duration, 2113 ( *reason ) ? reason : "banned by admin" ) ); 2105 2114 return qtrue; 2106 }2107 2108 trap_SendServerCommand( g_admin_namelog[ logmatch ]->slot,2109 va( "disconnect \"You have been banned.\n"2110 "admin:\n%s^7\nduration:\n%s\nreason:\n%s\"",2111 ( ent ) ? ent->client->pers.netname : "console",2112 duration,2113 ( *reason ) ? reason : "kicked by admin" ) );2114 2115 trap_DropClient( g_admin_namelog[ logmatch ]->slot,2116 va( "has been banned by %s^7 duration: %s, reason: %s",2117 ( ent ) ? ent->client->pers.netname : "console",2118 duration,2119 ( *reason ) ? reason : "banned by admin" ) );2120 return qtrue;2121 2115 2122 2116 } … … 2127 2121 int bnum; 2128 2122 char bs[ 4 ]; 2129 qtime_t qt; 2130 int t; 2131 2132 t = trap_RealTime( &qt ); 2123 2133 2124 if( G_SayArgc() < 2 + skiparg ) 2134 2125 { … … 2148 2139 return qfalse; 2149 2140 } 2150 g_admin_bans[ bnum - 1 ]->expires = t;2141 g_admin_bans[ bnum - 1 ]->expires = trap_RealTime( NULL ); 2151 2142 AP( va( "print \"^3!unban: ^7ban #%d for %s^7 has been removed by %s\n\"", 2152 2143 bnum, … … 2218 2209 char map[ MAX_QPATH ]; 2219 2210 char layout[ MAX_QPATH ] = { "" }; 2220 2211 2221 2212 if( G_SayArgc( ) < 2 + skiparg ) 2222 2213 { … … 2313 2304 ( ent ) ? ent->client->pers.netname : "console" ) ); 2314 2305 } 2315 ClientUserinfoChanged( pids[ 0 ] );2316 2306 return qtrue; 2317 2307 } … … 2376 2366 ( ent ) ? ent->client->pers.netname : "console" ) ); 2377 2367 } 2378 ClientUserinfoChanged( pids[ 0 ] );2379 2368 return qtrue; 2380 2369 } … … 2383 2372 { 2384 2373 int i, found = 0; 2385 qtime_t qt;2386 int t;2387 2374 char search[ MAX_NAME_LENGTH ] = {""}; 2388 2375 char s[ MAX_NAME_LENGTH ] = {""}; … … 2392 2379 int minlevel = 1; 2393 2380 2394 t = trap_RealTime( &qt );2395 2396 2381 if( G_SayArgc() == 3 + skiparg ) 2397 2382 { … … 2428 2413 for( i = 0; i < sizeof( s ) && s[ i ]; i++ ) 2429 2414 { 2430 if( s[ i ] >= '0' && s[ i ] <= '9')2415 if( isdigit( s[ i ] ) ) 2431 2416 continue; 2432 numeric = qfalse; 2433 } 2434 if( numeric ) 2417 numeric = qfalse; 2418 } 2419 if( numeric ) 2435 2420 { 2436 2421 start = atoi( s ); … … 2498 2483 char layout[ MAX_QPATH ] = { "" }; 2499 2484 int i = 0; 2500 2501 if( G_SayArgc( ) == 2 + skiparg ) 2502 G_SayArgv( 1 + skiparg, map, sizeof( map ) );2485 2486 if( G_SayArgc( ) == 2 + skiparg ) 2487 G_SayArgv( 1 + skiparg, map, sizeof( map ) ); 2503 2488 else 2504 2489 trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); 2505 2490 2506 2491 count = G_LayoutList( map, list, sizeof( list ) ); 2507 2492 ADMBP_begin( ); … … 2545 2530 2546 2531 ADMBP_begin(); 2547 ADMBP( va( "^3!listplayers ^7:%d players connected:\n",2532 ADMBP( va( "^3!listplayers: ^7%d players connected:\n", 2548 2533 level.numConnectedClients ) ); 2549 2534 for( i = 0; i < level.maxclients; i++ ) … … 2595 2580 if( !Q_stricmp( g_admin_admins[ j ]->guid, p->pers.guid ) ) 2596 2581 { 2597 2598 2582 // don't gather aka or level info if the admin is incognito 2599 if( G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) )2583 if( ent && G_admin_permission( &g_entities[ i ], ADMF_INCOGNITO ) ) 2600 2584 { 2601 2585 break; … … 2629 2613 } 2630 2614 2631 ADMBP( va( "%2i %s%s^7 %-2i %s^7 (*%s) ^1%1s%1s^7 %s^7 %s%s^7%s\n", 2632 i, 2633 c, 2634 t, 2635 l, 2636 ( *lname ) ? lname2 : "", 2637 guid_stub, 2638 muted, 2639 denied, 2640 p->pers.netname, 2641 ( *n ) ? "(a.k.a. " : "", 2642 n, 2643 ( *n ) ? ")" : "" 2644 ) ); 2615 if( G_admin_permission( ent, ADMF_SEESFULLLISTPLAYERS ) ) 2616 { 2617 ADMBP( va( "%2i %s%s^7 %-2i %s^7 (*%s) ^1%1s%1s^7 %s^7 %s%s^7%s\n", 2618 i, 2619 c, 2620 t, 2621 l, 2622 ( *lname ) ? lname2 : "", 2623 guid_stub, 2624 muted, 2625 denied, 2626 p->pers.netname, 2627 ( *n ) ? "(a.k.a. " : "", 2628 n, 2629 ( *n ) ? ")" : "" ) ); 2630 } 2631 else 2632 { 2633 ADMBP( va( "%2i %s%s^7 ^1%1s%1s^7 %s^7\n", 2634 i, 2635 c, 2636 t, 2637 muted, 2638 denied, 2639 p->pers.netname ) ); 2640 } 2645 2641 } 2646 2642 ADMBP_end(); … … 2651 2647 { 2652 2648 int i, found = 0; 2653 qtime_t qt;2654 2649 int t; 2655 2650 char duration[ 32 ]; … … 2666 2661 char n2[ MAX_NAME_LENGTH ] = {""}; 2667 2662 2668 t = trap_RealTime( &qt);2663 t = trap_RealTime( NULL ); 2669 2664 2670 2665 for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ ) 2671 2666 { 2672 if( g_admin_bans[ i ]->expires != 0 2673 &&( g_admin_bans[ i ]->expires - t ) < 1 )2667 if( g_admin_bans[ i ]->expires != 0 && 2668 ( g_admin_bans[ i ]->expires - t ) < 1 ) 2674 2669 { 2675 2670 continue; … … 2692 2687 start = 0; 2693 2688 2694 for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ] 2695 &&( i - start ) < MAX_ADMIN_SHOWBANS; i++ )2689 for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && 2690 ( i - start ) < MAX_ADMIN_SHOWBANS; i++ ) 2696 2691 { 2697 2692 G_DecolorString( g_admin_bans[ i ]->name, n1 ); … … 2711 2706 } 2712 2707 ADMBP_begin(); 2713 for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ] 2714 &&( i - start ) < MAX_ADMIN_SHOWBANS; i++ )2715 { 2716 if( g_admin_bans[ i ]->expires != 0 2717 &&( g_admin_bans[ i ]->expires - t ) < 1 )2708 for( i = start; i < MAX_ADMIN_BANS && g_admin_bans[ i ] && 2709 ( i - start ) < MAX_ADMIN_SHOWBANS; i++ ) 2710 { 2711 if( g_admin_bans[ i ]->expires != 0 && 2712 ( g_admin_bans[ i ]->expires - t ) < 1 ) 2718 2713 continue; 2719 2714 … … 2738 2733 Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is", 2739 2734 ( max_name + strlen( g_admin_bans[ i ]->name ) - strlen( n1 ) ) ); 2740 Com_sprintf( n1, sizeof( n1 ), name_fmt, g_admin_bans[ i ]->name ); 2735 Com_sprintf( n1, sizeof( n1 ), name_fmt, g_admin_bans[ i ]->name ); 2741 2736 2742 2737 G_DecolorString( g_admin_bans[ i ]->banner, n2 ); 2743 2738 Com_sprintf( banner_fmt, sizeof( banner_fmt ), "%%%is", 2744 2739 ( max_banner + strlen( g_admin_bans[ i ]->banner ) - strlen( n2 ) ) ); 2745 Com_sprintf( n2, sizeof( n2 ), banner_fmt, g_admin_bans[ i ]->banner ); 2740 Com_sprintf( n2, sizeof( n2 ), banner_fmt, g_admin_bans[ i ]->banner ); 2746 2741 2747 2742 ADMBP( va( "%4i %s^7 %-15s %-8s %s^7 %-10s\n \\__ %s\n", … … 3025 3020 } 3026 3021 AP( va( "print \"^3!allready:^7 %s^7 says everyone is READY now\n\"", 3027 ( ent ) ? ent->client->pers.netname : "console" ) ); 3022 ( ent ) ? ent->client->pers.netname : "console" ) ); 3028 3023 return qtrue; 3029 3024 } … … 3034 3029 if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] ) 3035 3030 { 3036 ADMP( "^3!cancelvote ^7:no vote in progress\n" );3031 ADMP( "^3!cancelvote: ^7no vote in progress\n" ); 3037 3032 return qfalse; 3038 3033 } … … 3055 3050 if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] ) 3056 3051 { 3057 ADMP( "^3!passvote ^7:no vote in progress\n" );3052 ADMP( "^3!passvote: ^7no vote in progress\n" ); 3058 3053 return qfalse; 3059 3054 } … … 3090 3085 G_ChangeTeam( vic, PTE_NONE ); 3091 3086 AP( va( "print \"^3!spec999: ^7%s^7 moved ^7%s^7 to spectators\n\"", 3092 ( ent ) ? ent->client->pers.netname : "console", 3087 ( ent ) ? ent->client->pers.netname : "console", 3093 3088 vic->client->pers.netname ) ); 3094 3089 } … … 3189 3184 return qfalse; 3190 3185 } 3191 victim = &g_entities[ pids[ 0 ] ] ;3186 victim = &g_entities[ pids[ 0 ] ]; 3192 3187 if( !admin_higher( ent, victim ) ) 3193 3188 { … … 3334 3329 { 3335 3330 found = qfalse; 3336 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 3331 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 3337 3332 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 3338 3333 { … … 3361 3356 ( g_entities[ g_admin_namelog[ i ]->slot ].client && 3362 3357 g_entities[ g_admin_namelog[ i ]->slot ].client->pers.denyBuild ? "B" : " " ) ) ); 3363 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 3358 for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 3364 3359 g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 3365 3360 { 3366 3361 ADMBP( va( " '%s^7'", g_admin_namelog[ i ]->name[ j ] ) ); 3367 3362 } 3368 ADMBP( "\n" ); 3369 } 3363 ADMBP( "\n" ); 3364 } 3370 3365 ADMBP( va( "^3!namelog:^7 %d recent clients found\n", printed ) ); 3371 3366 ADMBP_end(); … … 3401 3396 return qfalse; 3402 3397 } 3403 else 3404 level.alienTeamLocked = qtrue; 3398 level.alienTeamLocked = qtrue; 3405 3399 } 3406 3400 else if( team == PTE_HUMANS ) { … … 3410 3404 return qfalse; 3411 3405 } 3412 else 3413 level.humanTeamLocked = qtrue; 3406 level.humanTeamLocked = qtrue; 3414 3407 } 3415 3408 … … 3418 3411 ( ent ) ? ent->client->pers.netname : "console" ) ); 3419 3412 return qtrue; 3420 } 3413 } 3421 3414 3422 3415 qboolean G_admin_unlock( gentity_t *ent, int skiparg ) … … 3440 3433 return qfalse; 3441 3434 } 3442 3435 3443 3436 if( team == PTE_ALIENS ) 3444 3437 { … … 3448 3441 return qfalse; 3449 3442 } 3450 else 3451 level.alienTeamLocked = qfalse; 3443 level.alienTeamLocked = qfalse; 3452 3444 } 3453 3445 else if( team == PTE_HUMANS ) { … … 3457 3449 return qfalse; 3458 3450 } 3459 else 3460 level.humanTeamLocked = qfalse; 3451 level.humanTeamLocked = qfalse; 3461 3452 } 3462 3453 … … 3465 3456 ( ent ) ? ent->client->pers.netname : "console" ) ); 3466 3457 return qtrue; 3467 } 3458 } 3468 3459 3469 3460 //!Warn by Gate (Daniel Evans) … … 3524 3515 void G_admin_print( gentity_t *ent, char *m ) 3525 3516 { 3526 3527 3517 if( ent ) 3528 3518 trap_SendServerCommand( ent - level.gentities, va( "print \"%s\"", m ) ); … … 3530 3520 { 3531 3521 char m2[ MAX_STRING_CHARS ]; 3532 G_DecolorString( m, m2 ); 3533 G_Printf( m2 ); 3522 if( !trap_Cvar_VariableIntegerValue( "com_ansiColor" ) ) 3523 { 3524 G_DecolorString( m, m2 ); 3525 G_Printf( m2 ); 3526 } 3527 else 3528 G_Printf( m ); 3534 3529 } 3535 3530 } -
src/game/g_admin.h
r120 r124 42 42 #define MAX_ADMIN_BAN_REASON 50 43 43 44 45 #define ADM_NEW_BAN -1 46 44 47 /* 45 48 * 1 - cannot be vote kicked, vote muted … … 71 74 #define ADMF_IMMUTABLE '!' 72 75 #define ADMF_INCOGNITO '@' 76 #define ADMF_ADMINCHAT '?' 77 #define ADMF_PINGOVERRIDE '%' 78 79 #define ADMF_VIP '#' 73 80 #define ADMF_SEESFULLLISTPLAYERS '$' 74 81 … … 136 143 g_admin_namelog_t; 137 144 145 qboolean G_admin_autoregister( gentity_t *ent ); 138 146 qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen ); 139 147 qboolean G_admin_cmd_check( gentity_t *ent, qboolean say ); 140 148 qboolean G_admin_readconfig( gentity_t *ent, int skiparg ); 141 149 qboolean G_admin_permission( gentity_t *ent, char flag ); 150 qboolean G_admin_guid_permission( char *guid, char flag ); 142 151 qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len ); 143 152 void G_admin_namelog_update( gclient_t *ent, qboolean disconnect ); … … 164 173 qboolean G_admin_passvote( gentity_t *ent, int skiparg ); 165 174 qboolean G_admin_spec999( gentity_t *ent, int skiparg ); 175 qboolean G_admin_register( gentity_t *ent, int skiparg ); 166 176 qboolean G_admin_rename( gentity_t *ent, int skiparg ); 167 177 qboolean G_admin_restart( gentity_t *ent, int skiparg ); … … 170 180 qboolean G_admin_lock( gentity_t *ent, int skiparg ); 171 181 qboolean G_admin_unlock( gentity_t *ent, int skiparg ); 182 qboolean G_admin_warn( gentity_t *ent, int skiparg ); 183 qboolean G_admin_info( gentity_t *ent, int skiparg ); 184 185 qboolean G_admin_slap( gentity_t *ent, int skiparg ); 186 187 void G_admin_info_parse( char *unparsed, char *dest, int maxlength ); 172 188 173 189 void G_admin_print( gentity_t *ent, char *m ); -
src/game/g_admin.h
r50 r124 59 59 * ! - admin commands cannot be used on them 60 60 * @ - does not show up as an admin in !listplayers 61 * $ - sees all information in !listplayers 61 62 */ 62 63 #define ADMF_IMMUNITY '1' … … 77 78 78 79 #define ADMF_VIP '#' 80 #define ADMF_SEESFULLLISTPLAYERS '$' 79 81 80 82 #define MAX_ADMIN_LISTITEMS 20 -
src/game/g_buildable.c
r120 r124 152 152 153 153 #define POWER_REFRESH_TIME 2000 154 155 /* 156 ================ 157 G_FindGenerator 158 159 return the nearest generator, or NULL if isn't 160 ================ 161 */ 162 gentity_t* G_FindGenerator( buildableTeam_t team, vec3_t origin ) 163 { 164 gentity_t *ent; 165 gentity_t *closestPower = NULL; 166 int distance = 0; 167 int i; 168 int minDistance = 10000; 169 int main_generator = 0; 170 171 vec3_t temp_v; 172 173 //iterate through entities 174 for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 175 { 176 if( ent->s.eType != ET_BUILDABLE ) 177 continue; 178 179 //if entity is a power item calculate the distance to it 180 if( ((( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) && team == PTE_HUMANS) || 181 ((ent->s.modelindex == BA_A_OVERMIND || ent->s.modelindex == BA_A_SPAWN ) && team == PTE_ALIENS )) && 182 ent->spawned ) 183 { 184 VectorSubtract( origin, ent->s.origin, temp_v ); 185 distance = VectorLength( temp_v ); 186 187 if( 188 (ent->powered && 189 ent->s.modelindex == BA_H_REACTOR && 190 distance <= REACTOR_BASESIZE ) || 191 (ent->spawned && 192 ent->s.modelindex == BA_A_OVERMIND && 193 distance <= CREEP_BASESIZE) 194 ) 195 { 196 main_generator = 1; 197 closestPower = ent; 198 minDistance = distance; 199 } 200 else if( !main_generator && distance < minDistance && 201 ((team == PTE_HUMANS && ent->powered ) || 202 (team == PTE_ALIENS && ent->spawned )) && 203 (( ent->s.modelindex == BA_H_REPEATER && 204 distance <= REPEATER_BASESIZE ) || 205 ( ent->s.modelindex == BA_A_SPAWN && 206 distance <= CREEP_BASESIZE ) ) ) 207 { 208 closestPower = ent; 209 minDistance = distance; 210 } 211 } 212 } 213 214 return closestPower; 215 } 154 216 155 217 /* … … 168 230 int minDistance = REPEATER_BASESIZE + 1; 169 231 vec3_t temp_v; 232 int main_generator = 0; 170 233 171 234 if( self->biteam != BIT_HUMANS ) … … 184 247 185 248 //iterate through entities 186 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ )249 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 187 250 { 188 251 if( ent->s.eType != ET_BUILDABLE ) … … 199 262 if( ent->s.modelindex == BA_H_REACTOR && distance <= REACTOR_BASESIZE ) 200 263 { 201 self->parentNode = ent; 202 return qtrue; 264 main_generator = 1; 265 closestPower = ent; 266 minDistance = distance; 203 267 } 204 if( distance < minDistance ) 268 else if( !main_generator && distance < minDistance && 269 ent->s.modelindex == BA_H_REPEATER && 270 distance <= REPEATER_BASESIZE ) 205 271 { 206 272 closestPower = ent; … … 403 469 int minDistance = 10000; 404 470 vec3_t temp_v; 471 int main_generator = 0; 405 472 406 473 //don't check for creep if flying through the air … … 421 488 VectorSubtract( self->s.origin, ent->s.origin, temp_v ); 422 489 distance = VectorLength( temp_v ); 423 if( distance < minDistance ) 490 491 if( ent->s.modelindex == BA_A_OVERMIND && distance < CREEP_BASESIZE ) 492 { 493 main_generator = 1; 494 closestSpawn = ent; 495 minDistance = distance; 496 } 497 else if( !main_generator && distance < minDistance ) 424 498 { 425 499 closestSpawn = ent; … … 664 738 attacker->client->pers.netname ) ); 665 739 } 666 G_LogPrintf( "Decon: %i %i %i: %s destroyed%s by %s\n",740 G_LogPrintf( "Decon: %i %i %i: %s ^3destroyed^7 %s by %s\n", 667 741 attacker->client->ps.clientNum, self->s.modelindex, mod, 668 742 attacker->client->pers.netname, … … 899 973 attacker->client->pers.netname ) ); 900 974 } 901 G_LogPrintf( "Decon: %i %i %i: %s destroyed%s by %s\n",975 G_LogPrintf( "Decon: %i %i %i: %s ^3destroyed^7 %s by %s\n", 902 976 attacker->client->ps.clientNum, self->s.modelindex, mod, 903 977 attacker->client->pers.netname, … … 966 1040 } 967 1041 968 //do some damage 969 G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage, 970 self->splashRadius, self, self->splashMethodOfDeath, PTE_ALIENS ); 1042 if (g_noBaseAttack.integer) 1043 { 1044 // you should not attack the base, then get hurt ! 1045 G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage*g_quadfactor.integer, 1046 self->splashRadius, self, self->splashMethodOfDeath, PTE_ALIENS ); 1047 } 1048 else 1049 { 1050 //do some damage 1051 G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage, 1052 self->splashRadius, self, self->splashMethodOfDeath, PTE_ALIENS ); 1053 } 971 1054 } 972 1055 … … 1335 1418 attacker->client->pers.netname ) ); 1336 1419 } 1337 G_LogPrintf( "Decon: %i %i %i: %s destroyed%s by %s\n",1420 G_LogPrintf( "Decon: %i %i %i: %s ^3destroyed^7 %s by %s\n", 1338 1421 attacker->client->ps.clientNum, self->s.modelindex, mod, 1339 1422 attacker->client->pers.netname, … … 1711 1794 } 1712 1795 1796 1797 /* 1798 ================ 1799 HSpawn_Activate 1800 1801 Called when a human activates a spawn to teleport in Balance Mod 1802 ================ 1803 */ 1804 void HSpawn_Activate(gentity_t *self,gentity_t *other,gentity_t *activator) { 1805 if(self->spawned) { 1806 1807 // Only humans can activate this 1808 if(activator->client->ps.stats[STAT_PTEAM]!=PTE_HUMANS) return; 1809 1810 // Must be powered 1811 if(!self->powered) { 1812 G_TriggerMenu(activator->client->ps.clientNum,MN_H_NOTPOWERED); 1813 return; 1814 } 1815 1816 // If this is powered then find the next suitable spawn and respawn 1817 if(self->clientSpawnTime<=0) { 1818 vec3_t spawn_origin,spawn_angles; 1819 gentity_t *spot=self; 1820 while((spot=G_Find(spot,FOFS(classname), 1821 BG_FindEntityNameForBuildable(BA_H_SPAWN)))!=self) { 1822 if(spot==NULL||!spot->powered||!spot->spawned||spot->health<=0|| 1823 !spot->s.groundEntityNum||spot->clientSpawnTime>0|| 1824 G_CheckSpawnPoint(spot->s.number,spot->s.origin, 1825 spot->s.origin2,BA_H_SPAWN,spawn_origin)!=NULL) 1826 continue; 1827 1828 // Setup spawn angles (from ClientSpawn) 1829 VectorCopy(spot->s.angles,spawn_angles); 1830 spawn_angles[ROLL] = 0; 1831 spawn_angles[ YAW ] += 180.0f; 1832 AngleNormalize360( spawn_angles[ YAW ] ); 1833 1834 // Both spawns have been used 1835 self->clientSpawnTime = HUMAN_SPAWN_TELEPORT_TIME; 1836 spot->clientSpawnTime = HUMAN_SPAWN_TELEPORT_TIME; 1837 1838 // Prevent lerping 1839 activator->client->ps.eFlags ^= EF_TELEPORT_BIT; 1840 1841 // Copy vectors 1842 G_SetOrigin(activator,spawn_origin); 1843 VectorCopy(spawn_origin,activator->client->ps.origin); 1844 SetClientViewAngle(activator,spawn_angles); 1845 1846 // Play the spawn sound effect 1847 G_AddPredictableEvent(activator,EV_PLAYER_RESPAWN,0); 1848 1849 return; 1850 } 1851 } 1852 } 1853 } 1854 1855 1713 1856 /* 1714 1857 ================ … … 1856 1999 self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; 1857 2000 1858 self->enemy->health++;2001 do_health( self->enemy,1 ); 1859 2002 1860 2003 //if they're completely healed, give them a medkit … … 1888 2031 float accuracyTolerance, angularSpeed; 1889 2032 1890 if( self->lev1Grabbed ) 2033 if (g_noBaseAttack.integer) 2034 { 2035 // don't attack base, turret are *fast* 2036 accuracyTolerance = MGTURRET_DCC_ACCURACYTOLERANCE*2; 2037 angularSpeed = MGTURRET_DCC_ANGULARSPEED*2; 2038 } 2039 else if( self->lev1Grabbed ) 1891 2040 { 1892 2041 //can't turn fast if grabbed … … 2090 2239 //find a dcc for self 2091 2240 self->dcced = G_FindDCC( self ); 2241 if (g_noBaseAttack.integer) 2242 self->dcced = qtrue; 2092 2243 2093 2244 //if the current target is not valid find a new one … … 2306 2457 attacker->client->pers.netname ) ); 2307 2458 } 2308 G_LogPrintf( "Decon: %i %i %i: %s destroyed%s by %s\n",2459 G_LogPrintf( "Decon: %i %i %i: %s ^3destroyed^7 %s by %s\n", 2309 2460 attacker->client->ps.clientNum, self->s.modelindex, mod, 2310 2461 attacker->client->pers.netname, … … 2695 2846 G_FreeEntity( ent ); 2696 2847 } 2848 } 2849 2850 /* 2851 =============== 2852 G_SufficientGeneratorBPAvailable 2853 2854 Determine if nearest generator has enough build points can 2855 be released for the buildable 2856 =============== 2857 */ 2858 static qboolean G_SufficientGeneratorBPAvailable( gentity_t* generator, 2859 int buildPoints ) 2860 { 2861 return generator->buildpoints >= buildPoints; 2697 2862 } 2698 2863 … … 3072 3237 reason = tempReason; 3073 3238 3239 if( g_zoneBuildPoints.integer && 3240 buildable != BA_A_SPAWN && 3241 buildable != BA_A_OVERMIND && 3242 buildable != BA_H_REACTOR && 3243 buildable != BA_H_REPEATER ) 3244 { 3245 tempent = G_FindGenerator(ent->client->ps.stats[ STAT_PTEAM ], origin); 3246 if( reason == IBE_NONE && 3247 (!tempent || !G_SufficientGeneratorBPAvailable(tempent, buildPoints)) 3248 ) 3249 { 3250 if(ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS) 3251 reason = IBE_NOPOWER; 3252 else 3253 reason = IBE_NOASSERT; 3254 } 3255 } 3256 3074 3257 //this item does not fit here 3075 3258 if( reason == IBE_NONE && ( tr2.fraction < 1.0 || tr3.fraction < 1.0 ) ) … … 3152 3335 built->buildTime = built->s.time = level.time; 3153 3336 3154 // build instantly in cheat mode 3155 if( builder->client && g_cheats.integer)3337 // build instantly in cheat mode or in fastbuild mode 3338 if( builder->client && (g_cheats.integer || g_fastBuild.integer) ) 3156 3339 { 3157 3340 built->health = BG_FindHealthForBuildable( buildable ); … … 3167 3350 built->think = ASpawn_Think; 3168 3351 built->pain = ASpawn_Pain; 3352 built->buildpoints = g_eggBuildPoints.integer; 3169 3353 break; 3170 3354 … … 3204 3388 built->think = AOvermind_Think; 3205 3389 built->pain = ASpawn_Pain; 3390 built->buildpoints = g_overmindBuildPoints.integer; 3206 3391 break; 3207 3392 … … 3216 3401 built->die = HSpawn_Die; 3217 3402 built->think = HSpawn_Think; 3403 built->use = HSpawn_Activate; 3218 3404 break; 3219 3405 … … 3249 3435 built->use = HRepeater_Use; 3250 3436 built->powered = built->active = qtrue; 3437 built->buildpoints = g_reactorBuildPoints.integer; 3251 3438 break; 3252 3439 … … 3256 3443 built->use = HRepeater_Use; 3257 3444 built->count = -1; 3445 built->buildpoints = g_repeaterBuildPoints.integer; 3258 3446 break; 3259 3447 … … 3319 3507 3320 3508 trap_LinkEntity( built ); 3509 3510 if( builder->client ) { 3511 G_TeamCommand( builder->client->pers.teamSelection, 3512 va( "print \"%s is ^2being built^7 by %s^7\n\"", 3513 BG_FindHumanNameForBuildable( built->s.modelindex ), 3514 builder->client->pers.netname ) ); 3515 G_LogPrintf("Build: %i %i 0: %s^7 is ^2building^7 %s\n", 3516 builder->client->ps.clientNum, 3517 built->s.modelindex, 3518 builder->client->pers.netname, 3519 BG_FindNameForBuildable( built->s.modelindex ) ); 3520 } 3321 3521 3322 3522 return built; -
src/game/g_buildable.c
r122 r124 98 98 return NULL; 99 99 } 100 else 101 return &g_entities[ tr.entityNum ]; 102 } 103 else if( spawn == BA_H_SPAWN ) 100 return &g_entities[ tr.entityNum ]; 101 } 102 if( spawn == BA_H_SPAWN ) 104 103 { 105 104 BG_FindBBoxForClass( PCL_HUMAN, cmins, cmaxs, NULL, NULL, NULL ); … … 122 121 return NULL; 123 122 } 124 else 125 return &g_entities[ tr.entityNum ]; 123 return &g_entities[ tr.entityNum ]; 126 124 } 127 125 … … 141 139 gentity_t *ent; 142 140 143 for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )141 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 144 142 { 145 143 if( ent->s.eType != ET_BUILDABLE ) … … 230 228 gentity_t *closestPower = NULL; 231 229 int distance = 0; 232 int minDistance = 10000;230 int minDistance = REPEATER_BASESIZE + 1; 233 231 vec3_t temp_v; 234 232 int main_generator = 0; … … 256 254 //if entity is a power item calculate the distance to it 257 255 if( ( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) && 258 ent->spawned )256 ent->spawned && ent->powered ) 259 257 { 260 258 VectorSubtract( self->s.origin, ent->s.origin, temp_v ); … … 262 260 263 261 // Always prefer a reactor if there is one in range 264 if( ent->s.modelindex == BA_H_REACTOR && 265 distance <= REACTOR_BASESIZE && 266 ent->powered ) 262 if( ent->s.modelindex == BA_H_REACTOR && distance <= REACTOR_BASESIZE ) 267 263 { 268 264 main_generator = 1; … … 270 266 minDistance = distance; 271 267 } 272 else if( !main_generator && distance < minDistance && ent->powered &&268 else if( !main_generator && distance < minDistance && 273 269 ent->s.modelindex == BA_H_REPEATER && 274 270 distance <= REPEATER_BASESIZE ) … … 286 282 return qtrue; 287 283 } 288 else 289 return qfalse; 284 return qfalse; 290 285 } 291 286 … … 309 304 if( G_FindPower( &dummy ) ) 310 305 return dummy.parentNode; 311 else 312 return NULL; 306 return NULL; 313 307 } 314 308 … … 327 321 if( ent ) 328 322 return ent->s.modelindex; 329 else 330 return BA_NONE; 323 return BA_NONE; 331 324 } 332 325 … … 359 352 360 353 //iterate through entities 361 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )354 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 362 355 { 363 356 if( ent->s.eType != ET_BUILDABLE ) … … 378 371 } 379 372 380 //if there was no nearby DCC give up 381 if( !foundDCC ) 382 return qfalse; 383 384 self->dccNode = closestDCC; 385 386 return qtrue; 373 if( foundDCC ) 374 self->dccNode = closestDCC; 375 376 return foundDCC; 387 377 } 388 378 … … 429 419 430 420 //iterate through entities 431 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )421 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 432 422 { 433 423 if( ent->s.eType != ET_BUILDABLE ) … … 488 478 if( ( self->parentNode == NULL ) || !self->parentNode->inuse ) 489 479 { 490 for ( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )480 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 491 481 { 492 482 if( ent->s.eType != ET_BUILDABLE ) … … 518 508 return qtrue; 519 509 } 520 else 521 return qfalse; 510 return qfalse; 522 511 } 523 512 … … 829 818 void AOvermind_Think( gentity_t *self ) 830 819 { 831 int entityList[ MAX_GENTITIES ]; 832 vec3_t range = { OVERMIND_ATTACK_RANGE, OVERMIND_ATTACK_RANGE, OVERMIND_ATTACK_RANGE }; 833 vec3_t mins, maxs; 834 int i, num; 835 gentity_t *enemy; 820 vec3_t range = { OVERMIND_ATTACK_RANGE, OVERMIND_ATTACK_RANGE, OVERMIND_ATTACK_RANGE }; 821 vec3_t mins, maxs; 822 int i; 836 823 837 824 VectorAdd( self->s.origin, range, maxs ); … … 841 828 { 842 829 //do some damage 843 num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 844 for( i = 0; i < num; i++ ) 845 { 846 enemy = &g_entities[ entityList[ i ] ]; 847 848 if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 849 { 850 self->timestamp = level.time; 851 G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage, 852 self->splashRadius, self, MOD_OVERMIND, PTE_ALIENS ); 853 G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse ); 854 } 830 if( G_SelectiveRadiusDamage( self->s.pos.trBase, self, self->splashDamage, 831 self->splashRadius, self, MOD_OVERMIND, PTE_ALIENS ) ) 832 { 833 self->timestamp = level.time; 834 G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse ); 855 835 } 856 836 … … 1268 1248 } 1269 1249 1270 if( tr.fraction < 1.0f ) 1271 return qtrue; 1272 else 1273 return qfalse; 1250 return ( tr.fraction < 1.0f ); 1274 1251 } 1275 1252 … … 1329 1306 activator->client->ps.eFlags |= EF_NODRAW; 1330 1307 G_UnlaggedClear( activator ); 1308 1309 // Cancel pending suicides 1310 activator->suicideTime = 0; 1331 1311 1332 1312 activator->client->ps.stats[ STAT_STATE ] |= SS_HOVELING; … … 1750 1730 VectorSubtract( self->s.origin, range, mins ); 1751 1731 1752 if( self->spawned && ( self->health > 0 ) ) 1753 { 1754 //do some damage 1732 //do some damage 1733 if( self->spawned && ( self->health > 0 ) && 1734 G_SelectiveRadiusDamage( self->s.pos.trBase, self, REACTOR_ATTACK_DAMAGE, 1735 REACTOR_ATTACK_RANGE, self, MOD_REACTOR, PTE_HUMANS ) ) 1736 { 1737 self->timestamp = level.time; 1738 //detect alien targets and draw tesla trails 1755 1739 num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 1756 1740 for( i = 0; i < num; i++ ) … … 1760 1744 if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 1761 1745 { 1762 self->timestamp = level.time;1763 G_SelectiveRadiusDamage( self->s.pos.trBase, self, REACTOR_ATTACK_DAMAGE,1764 REACTOR_ATTACK_RANGE, self, MOD_REACTOR, PTE_HUMANS );1765 1766 1746 tent = G_TempEntity( enemy->s.pos.trBase, EV_TESLATRAIL ); 1767 1747 … … 2804 2784 if( aMatches && !bMatches ) 2805 2785 return -1; 2806 elseif( !aMatches && bMatches )2786 if( !aMatches && bMatches ) 2807 2787 return 1; 2808 2788 … … 2812 2792 if( aMatches && !bMatches ) 2813 2793 return -1; 2814 elseif( !aMatches && bMatches )2794 if( !aMatches && bMatches ) 2815 2795 return 1; 2816 2796 … … 2825 2805 if( aMatches && !bMatches ) 2826 2806 return -1; 2827 elseif( !aMatches && bMatches )2807 if( !aMatches && bMatches ) 2828 2808 return 1; 2829 2809 … … 2938 2918 2939 2919 // Check for buildable<->buildable collisions 2940 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )2920 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 2941 2921 { 2942 2922 if( ent->s.eType != ET_BUILDABLE ) … … 2956 2936 2957 2937 // Build a list of buildable entities 2958 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ )2938 for( i = MAX_CLIENTS, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 2959 2939 { 2960 2940 if( ent->s.eType != ET_BUILDABLE ) … … 3071 3051 3072 3052 // Make sure we're not removing the last spawn 3073 if( ( remainingSpawns - spawnCount ) < 1 )3053 if( !g_cheats.integer && remainingSpawns > 0 && ( remainingSpawns - spawnCount ) < 1 ) 3074 3054 return bpError; 3075 3055 … … 3077 3057 if( pointsYielded < buildPoints ) 3078 3058 return bpError; 3079 else 3080 return IBE_NONE; 3059 return IBE_NONE; 3081 3060 } 3082 3061 … … 3322 3301 // initial base layout created by server 3323 3302 3324 if( builder->s.origin2[ 0 ] 3325 || builder->s.origin2[ 1 ]3326 ||builder->s.origin2[ 2 ] )3303 if( builder->s.origin2[ 0 ] || 3304 builder->s.origin2[ 1 ] || 3305 builder->s.origin2[ 2 ] ) 3327 3306 { 3328 3307 VectorCopy( builder->s.origin2, normal ); … … 3747 3726 } 3748 3727 3749 G_Printf( "layoutsave: saving layout to %s\n", fileName );3728 G_Printf( "layoutsave: saving layout to %s\n", fileName ); 3750 3729 3751 3730 for( i = MAX_CLIENTS; i < level.num_entities; i++ ) … … 3857 3836 l = &layouts2[ 0 ]; 3858 3837 layouts[ 0 ] = '\0'; 3859 s = COM_ParseExt( &l, qfalse ); 3860 while( *s ) 3861 { 3838 while( 1 ) 3839 { 3840 s = COM_ParseExt( &l, qfalse ); 3841 if( !*s ) 3842 break; 3843 3862 3844 if( !Q_stricmp( s, "*BUILTIN*" ) ) 3863 3845 { … … 3865 3847 Q_strcat( layouts, sizeof( layouts ), " " ); 3866 3848 cnt++; 3867 s = COM_ParseExt( &l, qfalse );3868 3849 continue; 3869 3850 } … … 3878 3859 else 3879 3860 G_Printf( S_COLOR_YELLOW "WARNING: layout \"%s\" does not exist\n", s ); 3880 s = COM_ParseExt( &l, qfalse );3881 3861 } 3882 3862 if( !cnt ) … … 3891 3871 Q_strncpyz( layouts2, layouts, sizeof( layouts2 ) ); 3892 3872 l = &layouts2[ 0 ]; 3893 s = COM_ParseExt( &l, qfalse ); 3894 while( *s ) 3895 { 3873 while( 1 ) 3874 { 3875 s = COM_ParseExt( &l, qfalse ); 3876 if( !*s ) 3877 break; 3878 3879 Q_strncpyz( level.layout, s, sizeof( level.layout ) ); 3896 3880 cnt++; 3897 3881 if( cnt >= layoutNum ) 3898 3882 break; 3899 s = COM_ParseExt( &l, qfalse ); 3900 } 3901 Q_strncpyz( level.layout, s, sizeof( level.layout ) ); 3902 G_Printf("using layout \"%s\" from list ( %s)\n", level.layout, layouts ); 3883 } 3884 G_Printf( "using layout \"%s\" from list (%s)\n", level.layout, layouts ); 3903 3885 } 3904 3886 -
src/game/g_client.c
r120 r124 82 82 /* 83 83 =============== 84 G_CheckGUID 85 =============== 86 */ 87 qboolean G_ValidGUID(char *in) 88 { 89 int count = 0; 90 while( *in ) 91 { 92 count ++; 93 //check that the char is an alphanumeric one (with uppercased letter) 94 if( !((*in >= '0' && *in <= '9') || (*in >= 'A' && *in <= 'F')) ) 95 return qfalse; 96 97 in++; 98 } 99 100 if( count != 32 ) 101 return qfalse; 102 103 return qtrue; 104 } 105 106 /* 107 =============== 84 108 G_AddCreditToClient 85 109 =============== … … 90 114 return; 91 115 92 //if we're already at the max and trying to add credit then stop 116 client->ps.persistant[ PERS_CREDIT ] += credit; 117 93 118 if( cap ) 94 119 { 95 120 if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 96 121 { 97 if( client->ps.persistant[ PERS_CREDIT ] >= ALIEN_MAX_KILLS && 98 credit > 0 ) 99 return; 122 if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS ) 123 { 124 if( g_autoDonate.integer ) 125 G_Donate(client, client->ps.persistant[ PERS_CREDIT ] - ALIEN_MAX_KILLS); 126 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS; 127 } 100 128 } 101 129 else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 102 130 { 103 if( client->ps.persistant[ PERS_CREDIT ] >= HUMAN_MAX_CREDITS &&104 credit > 0 )105 return;106 }107 }108 109 client->ps.persistant[ PERS_CREDIT ] += credit;110 111 if( cap )112 {113 if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )114 {115 if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS )116 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS;117 }118 else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )119 {120 131 if( client->ps.persistant[ PERS_CREDIT ] > HUMAN_MAX_CREDITS ) 132 { 133 if( g_autoDonate.integer ) 134 G_Donate(client, client->ps.persistant[ PERS_CREDIT ] - HUMAN_MAX_CREDITS); 121 135 client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS; 136 } 122 137 } 123 138 } … … 583 598 584 599 //sinking bodies can't be infested 585 ent->killedBy = ent->s. misc= MAX_CLIENTS;600 ent->killedBy = ent->s.powerups = MAX_CLIENTS; 586 601 ent->timestamp = level.time; 587 602 } … … 657 672 body->classname = "alienCorpse"; 658 673 659 body->s. misc= MAX_CLIENTS;674 body->s.powerups = MAX_CLIENTS; 660 675 661 676 body->think = BodySink; … … 867 882 868 883 /* 884 =================== 885 G_NextNewbieName 886 887 Generate a unique, known-good name for an UnnamedPlayer 888 =================== 889 */ 890 char *G_NextNewbieName( gentity_t *ent ) 891 { 892 char newname[ MAX_NAME_LENGTH ]; 893 char namePrefix[ MAX_NAME_LENGTH - 4 ]; 894 char err[ MAX_STRING_CHARS ]; 895 896 if( g_newbieNamePrefix.string[ 0 ] ) 897 Q_strncpyz( namePrefix, g_newbieNamePrefix.string , sizeof( namePrefix ) ); 898 else 899 strcpy( namePrefix, "Newbie#" ); 900 901 while( level.numNewbies < 10000 ) 902 { 903 strcpy( newname, va( "%s%i", namePrefix, level.numNewbies ) ); 904 if ( G_admin_name_check( ent, newname, err, sizeof( err ) ) ) 905 { 906 return va( "%s", newname ); 907 } 908 level.numNewbies++; // Only increments if the last requested name was used. 909 } 910 return "UnnamedPlayer"; 911 } 912 913 914 /* 869 915 ====================== 870 916 G_NonSegModel … … 944 990 char err[ MAX_STRING_CHARS ]; 945 991 qboolean revertName = qfalse; 992 qboolean showRenameMsg = qtrue; 946 993 gclient_t *client; 947 994 char c1[ MAX_INFO_STRING ]; … … 972 1019 if( strcmp( oldname, newname ) ) 973 1020 { 974 // in case we need to revert and there's no oldname 975 if( client->pers.connected != CON_CONNECTED ) 976 Q_strncpyz( oldname, "UnnamedPlayer", sizeof( oldname ) ); 977 978 if( client->pers.nameChangeTime && 1021 1022 if( !strlen( oldname ) && client->pers.connected != CON_CONNECTED ) 1023 showRenameMsg = qfalse; 1024 // in case we need to revert and there's no oldname 1025 ClientCleanName( va( "%s", client->pers.netname ), oldname, sizeof( oldname ) ); 1026 1027 if( g_newbieNumbering.integer ) 1028 { 1029 if( !strcmp( newname, "UnnamedPlayer" ) ) 1030 Q_strncpyz( newname, G_NextNewbieName( ent ), sizeof( newname ) ); 1031 if( !strcmp( oldname, "UnnamedPlayer" ) ) 1032 Q_strncpyz( oldname, G_NextNewbieName( ent ), sizeof( oldname ) ); 1033 } 1034 1035 if( client->pers.muted ) 1036 { 1037 trap_SendServerCommand( ent - g_entities, 1038 "print \"You cannot change your name while you are muted\n\"" ); 1039 revertName = qtrue; 1040 } 1041 else if( client->pers.nameChangeTime && 979 1042 ( level.time - client->pers.nameChangeTime ) 980 1043 <= ( g_minNameChangePeriod.value * 1000 ) ) … … 1010 1073 Q_strncpyz( client->pers.netname, newname, 1011 1074 sizeof( client->pers.netname ) ); 1075 Info_SetValueForKey( userinfo, "name", newname ); 1076 trap_SetUserinfo( clientNum, userinfo ); 1012 1077 if( client->pers.connected == CON_CONNECTED ) 1013 1078 { … … 1024 1089 } 1025 1090 1026 if( client->pers.connected == CON_CONNECTED)1091 if( client->pers.connected >= CON_CONNECTING && showRenameMsg ) 1027 1092 { 1028 1093 if( strcmp( oldname, client->pers.netname ) ) 1029 1094 { 1030 1095 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE 1031 " renamed to %s \n\"", oldname, client->pers.netname ) );1032 G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s \" -> \"%s\"\n", clientNum,1096 " renamed to %s" S_COLOR_WHITE "\n\"", oldname, client->pers.netname ) ); 1097 G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s^7\" -> \"%s^7\"\n", clientNum, 1033 1098 client->pers.ip, client->pers.guid, oldname, client->pers.netname ); 1034 1099 G_admin_namelog_update( client, qfalse ); … … 1048 1113 1049 1114 // set model 1050 if( client->ps.stats[ STAT_PCLASS ] == PCL_HUMAN _BSUIT)1115 if( client->ps.stats[ STAT_PCLASS ] == PCL_HUMAN && BG_InventoryContainsUpgrade( UP_BATTLESUIT, client->ps.stats ) ) 1051 1116 { 1052 1117 Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_HUMAN_BSUIT ), … … 1160 1225 char reason[ MAX_STRING_CHARS ] = {""}; 1161 1226 int i; 1227 int used_privateSlots; 1228 int privateClients; 1162 1229 1163 1230 ent = &g_entities[ clientNum ]; … … 1174 1241 } 1175 1242 1243 privateClients = trap_Cvar_VariableIntegerValue( "sv_privateClients" ); 1244 if( firstTime && clientNum >= privateClients && !G_admin_guid_permission( value, ADMF_VIP ) ) 1245 { 1246 // not flag ADMF_VIP, not already connected player after mapchange, and not privateClient... 1247 // may be refused, because too many players in game 1248 used_privateSlots = 0; 1249 for( i = 0 ; i < privateClients; i++ ) 1250 { 1251 if( level.clients[ i ].pers.connected != CON_DISCONNECTED ) 1252 { 1253 used_privateSlots++; 1254 } 1255 } 1256 1257 if( ( level.numConnectedClients - used_privateSlots ) >= ( level.maxclients - privateClients - g_hiddenClients.integer ) ) 1258 { 1259 // not flag ADMF_VIP and maxPlayers exceeded 1260 return "Server is full"; 1261 } 1262 } 1176 1263 1177 1264 // IP filtering … … 1206 1293 1207 1294 // add guid to session so we don't have to keep parsing userinfo everywhere 1208 if( ! guid[0])1295 if( !G_ValidGUID(guid) ) 1209 1296 { 1210 1297 Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", … … 1228 1315 // get and distribute relevent paramters 1229 1316 ClientUserinfoChanged( clientNum ); 1230 G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s \"\n", clientNum,1317 G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 1231 1318 client->pers.ip, client->pers.guid, client->pers.netname ); 1232 1319 … … 1284 1371 // locate ent at a spawn point 1285 1372 1373 client->pers.classSelection = PCL_NONE; 1286 1374 ClientSpawn( ent, NULL, NULL, NULL ); 1287 1375 … … 1291 1379 G_admin_namelog_update( client, qfalse ); 1292 1380 1381 // autoregister client if possible 1382 G_admin_autoregister( ent ); 1383 1293 1384 // request the clients PTR code 1294 1385 trap_SendServerCommand( ent - g_entities, "ptrcrequest" ); … … 1298 1389 // count current clients and rank for scoreboard 1299 1390 CalculateRanks( ); 1391 } 1392 1393 /* 1394 ================== 1395 ClientPingOverride 1396 1397 Called by server every time a client connects to check 1398 whether it is immune to ping restrictions. 1399 ================== 1400 */ 1401 int ClientPingOverride( void ) 1402 { 1403 char userinfo[ MAX_INFO_STRING ]; 1404 // create a temporary gentity 1405 gentity_t ent; 1406 gclient_t client; 1407 ent.client = &client; 1408 1409 // userinfo for the client is not yet availible so just use Argv(1) 1410 trap_Argv( 1, userinfo, sizeof( userinfo ) ); 1411 Q_strncpyz( client.pers.guid, Info_ValueForKey( userinfo, "cl_guid" ), sizeof( client.pers.guid ) ); 1412 if ( !client.pers.guid[0] ) 1413 return 0; 1414 1415 return G_admin_permission( &ent, ADMF_PINGOVERRIDE ); 1300 1416 } 1301 1417 … … 1345 1461 client->sess.spectatorState = SPECTATOR_LOCKED; 1346 1462 } 1463 1464 1465 // if this is after !restart keepteams or !restart switchteams, apply said selection 1466 if ( client->sess.restartTeam != PTE_NONE ) { 1467 G_ChangeTeam( ent, client->sess.restartTeam ); 1468 client->sess.restartTeam = PTE_NONE; 1469 } 1470 1471 1347 1472 1348 1473 if( origin != NULL ) … … 1469 1594 BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); 1470 1595 BG_AddWeaponToInventory( weapon, client->ps.stats ); 1471 client->ps.ammo = maxAmmo; 1472 client->ps.clips = maxClips; 1596 BG_PackAmmoArray( weapon, client->ps.ammo, client->ps.powerups, maxAmmo, maxClips ); 1473 1597 1474 1598 ent->client->ps.stats[ STAT_PCLASS ] = ent->client->pers.classSelection; … … 1494 1618 1495 1619 client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA; 1620 1621 client->jetpack_beat = 0; 1622 client->jetpack_power = g_jetpackLimit.integer; 1496 1623 1497 1624 G_SetOrigin( ent, spawn_origin ); … … 1656 1783 } 1657 1784 1658 G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s \"\n", clientNum,1785 G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 1659 1786 ent->client->pers.ip, ent->client->pers.guid, ent->client->pers.netname ); 1660 1787 -
src/game/g_client.c
r123 r124 818 818 { 819 819 int len, colorlessLen; 820 char ch;821 820 char *p; 822 821 int spaces; … … 831 830 spaces = 0; 832 831 833 while( 1 ) 834 { 835 ch = *in++; 836 if( !ch ) 837 break; 838 832 for( ; *in; in++ ) 833 { 839 834 // don't allow leading spaces 840 if( !*p && ch== ' ' )835 if( colorlessLen == 0 && *in == ' ' ) 841 836 continue; 842 837 843 838 // check colors 844 if( ch == Q_COLOR_ESCAPE && ( ( *in && *in != Q_COLOR_ESCAPE ) || !*in ) ) 845 { 839 if( Q_IsColorString( in ) ) 840 { 841 in++; 842 843 // don't allow black in a name, period 844 if( ColorIndex( *in ) == 0 ) 845 continue; 846 846 847 // make sure room in dest for both chars 847 848 if( len > outSize - 2 ) 848 849 break; 849 850 850 *out++ = ch; 851 *out++ = Q_COLOR_ESCAPE; 852 *out++ = *in; 851 853 len += 2; 852 853 // solo trailing carat is not a color prefix854 if( !*in ) {855 *out++ = COLOR_WHITE;856 break;857 }858 859 // don't allow black in a name, period860 if( ColorIndex( *in ) == 0 )861 *out++ = COLOR_WHITE;862 else863 *out++ = *in;864 865 in++;866 854 continue; 867 855 } 868 856 869 857 // don't allow too many consecutive spaces 870 if( ch== ' ' )858 if( *in == ' ' ) 871 859 { 872 860 spaces++; … … 880 868 break; 881 869 882 *out++ = ch;870 *out++ = *in; 883 871 colorlessLen++; 884 872 len++; … … 947 935 } 948 936 949 if( len < =0 )937 if( len < 0 ) 950 938 return qfalse; 951 939 -
src/game/g_cmds.c
r120 r124 382 382 maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 383 383 384 client->ps.ammo = maxAmmo; 385 client->ps.clips = maxClips; 384 BG_PackAmmoArray( client->ps.weapon, client->ps.ammo, client->ps.powerups, maxAmmo, maxClips ); 386 385 } 387 386 } … … 618 617 ent->client->pers.joinedATeam = qtrue; 619 618 ent->client->pers.teamChangeTime = level.time; 620 621 619 //update ClientInfo 622 620 ClientUserinfoChanged( ent->client->ps.clientNum ); 621 CalculateRanks( ); 623 622 } 624 623 … … 636 635 int aliens = level.numAlienClients; 637 636 int humans = level.numHumanClients; 637 int warmup; 638 638 639 639 // stop team join spam 640 640 if( level.time - ent->client->pers.teamChangeTime < 1000 ) 641 641 return; 642 643 // do warm up 644 if( g_doWarmup.integer ) 645 { 646 warmup = g_warmup.integer - ( ( level.time - level.startTime ) / 1000) - 1; 647 if( warmup > 0 ) 648 { 649 trap_SendServerCommand( ent - g_entities, va( "print \"team: you can't join" 650 " a team during warm up (%d seconds remaining)\n\"", warmup ) ); 651 return; 652 } 653 } 642 654 643 655 if( oldteam == PTE_ALIENS ) … … 655 667 } 656 668 657 if( !Q_stricmp( s, "spectate" ) ) 658 team = PTE_NONE; 659 else if( !force && oldteam == PTE_NONE && g_maxGameClients.integer && 669 // g_maxGameClients stuff 670 if( !force && oldteam == PTE_NONE && g_maxGameClients.integer && 660 671 level.numPlayingClients >= g_maxGameClients.integer ) 661 672 { … … 665 676 return; 666 677 } 678 679 //guard against build timer exploit 680 if( ent->client->pers.teamSelection != PTE_NONE && 681 ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 || 682 ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG || 683 BG_InventoryContainsWeapon( WP_HBUILD, ent->client->ps.stats ) || 684 BG_InventoryContainsWeapon( WP_HBUILD2, ent->client->ps.stats ) ) && 685 ent->client->ps.stats[ STAT_MISC ] > 0 ) 686 { 687 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot change teams until build timer expires\n\"" ) ); 688 return; 689 } 690 691 if( !Q_stricmp( s, "spectate" ) ) 692 team = PTE_NONE; 667 693 else if( !Q_stricmp( s, "aliens" ) ) 668 694 { … … 673 699 return; 674 700 } 675 if( level.humanTeamLocked ) 676 { 677 // if only one team has been locked, let people join the other 678 // regardless of balance 679 force = qtrue; 680 } 681 682 if( !force && g_teamForceBalance.integer && aliens > humans ) 683 { 684 G_TriggerMenu( ent - g_entities, MN_A_TEAMFULL ); 701 702 if( !force && !level.humanTeamLocked && g_teamForceBalance.integer && aliens > humans ) 703 { 704 trap_SendServerCommand( ent-g_entities, va("print \"team: The alien team has too many players.\n\"" ) ); 685 705 return; 686 706 } … … 696 716 return; 697 717 } 698 if( level.alienTeamLocked ) 699 { 700 // if only one team has been locked, let people join the other 701 // regardless of balance 702 force = qtrue; 703 } 704 705 if( !force && g_teamForceBalance.integer && humans > aliens ) 706 { 707 G_TriggerMenu( ent - g_entities, MN_H_TEAMFULL ); 718 if( !force && !level.alienTeamLocked && g_teamForceBalance.integer && humans > aliens ) 719 { 720 trap_SendServerCommand( ent-g_entities, va("print \"team: The human team has too many players.\n\"" ) ); 708 721 return; 709 722 } … … 715 728 if( level.humanTeamLocked && level.alienTeamLocked ) 716 729 team = PTE_NONE; 717 else if( humans > aliens )730 else if(humans > aliens ) 718 731 team = PTE_ALIENS; 719 732 else if( humans < aliens ) … … 734 747 735 748 // stop team join spam 736 if( oldteam == team ) 737 return; 738 739 //guard against build timer exploit 740 if( oldteam != PTE_NONE && 741 ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 || 742 ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG || 743 BG_InventoryContainsWeapon( WP_HBUILD, ent->client->ps.stats ) || 744 BG_InventoryContainsWeapon( WP_HBUILD2, ent->client->ps.stats ) ) && 745 ent->client->ps.stats[ STAT_MISC ] > 0 ) 746 { 747 if( ent->client->pers.teamSelection == PTE_ALIENS ) 748 G_TriggerMenu( ent->client->ps.clientNum, MN_A_TEAMCHANGEBUILDTIMER ); 749 if( ent->client->pers.teamSelection == team ) 750 return; 751 752 G_ChangeTeam( ent, team ); 753 754 if( team == PTE_ALIENS ) 755 { 756 if ( oldteam == PTE_HUMANS ) 757 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " abandoned humans and joined the aliens\n\"", ent->client->pers.netname ) ); 749 758 else 750 G_TriggerMenu( ent->client->ps.clientNum, MN_H_TEAMCHANGEBUILDTIMER ); 751 return; 752 } 753 754 755 G_ChangeTeam( ent, team ); 756 757 if( team == PTE_ALIENS ) 758 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the aliens\n\"", ent->client->pers.netname ) ); 759 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the aliens\n\"", ent->client->pers.netname ) ); 760 } 759 761 else if( team == PTE_HUMANS ) 760 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the humans\n\"", ent->client->pers.netname ) ); 762 { 763 if ( oldteam == PTE_ALIENS ) 764 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " abandoned aliens and joined the humans\n\"", ent->client->pers.netname ) ); 765 else 766 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the humans\n\"", ent->client->pers.netname ) ); 767 } 768 else if( team == PTE_NONE ) 769 { 770 if ( oldteam == PTE_HUMANS ) 771 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " left the humans\n\"", ent->client->pers.netname ) ); 772 else 773 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " left the aliens\n\"", ent->client->pers.netname ) ); 774 } 761 775 } 762 776 … … 767 781 ================== 768 782 */ 769 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message ) 770 { 783 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message, const char *prefix ) 784 { 785 qboolean toSend = qtrue, usePrefix = qfalse; 786 771 787 qboolean ignore = qfalse; 772 788 … … 783 799 return; 784 800 785 if( mode == SAY_TEAM && !OnSameTeam( ent, other ) ) 786 { 787 if( other->client->pers.teamSelection != PTE_NONE ) 788 return; 789 790 if( !G_admin_permission( other, ADMF_SPEC_ALLCHAT ) ) 791 return; 801 if( ( mode == SAY_TEAM || mode == SAY_ACTION_T ) && !OnSameTeam( ent, other ) ) 802 { 803 toSend = qfalse; 804 805 if( other->client->ps.stats[ STAT_PTEAM ] == PTE_NONE && 806 G_admin_permission( other, ADMF_SPEC_ALLCHAT ) ) { 807 usePrefix = qtrue; 808 toSend = qtrue; 809 } 810 811 // spec following someone in talker's steam may see 812 // that teamchat if g_specsSeeTeamchat is enabled 813 if( other->client->ps.stats[ STAT_PTEAM ] == ent->client->ps.stats[ STAT_PTEAM ] && 814 ent->client->pers.teamSelection != PTE_NONE && g_specsSeeTeamchat.integer ) 815 toSend = qtrue; 792 816 793 817 // specs with ADMF_SPEC_ALLCHAT flag can see team chat 794 818 } 819 820 if( mode == SAY_ADMINS && !G_admin_permission( other, ADMF_ADMINCHAT) ) 821 return; 822 823 if( mode == SAY_ALL ) 824 usePrefix = qtrue; 795 825 796 826 if( BG_ClientListTest( &other->client->sess.ignoreList, ent-g_entities ) ) 797 827 ignore = qtrue; 798 799 trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%c%c%s\"", 800 mode == SAY_TEAM ? "tchat" : "chat", 801 ( ignore ) ? "[skipnotify]" : "", 802 name, Q_COLOR_ESCAPE, color, message ) ); 828 829 if( toSend ) 830 { 831 trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%s%c%c%s\"", 832 ( mode == SAY_TEAM || mode == SAY_ACTION_T ) ? "tchat" : "chat", 833 ( ignore ) ? "[skipnotify]" : "", 834 usePrefix ? prefix : "", 835 name, Q_COLOR_ESCAPE, color, message ) ); 836 } 803 837 } 804 838 … … 840 874 default: 841 875 case SAY_ALL: 842 G_LogPrintf( "say: %s: %s\n", ent->client->pers.netname, chatText ); 843 Com_sprintf( name, sizeof( name ), "%s%s%c%c"EC": ", prefix, 876 if(ent->client->pers.teamSelection == PTE_NONE && G_admin_level(ent)<g_minLevelToSpecMM1.integer) 877 { 878 trap_SendServerCommand( ent-g_entities,va( "print \"Sorry, but your admin level is not permitted to speak to all while spectating.\n\"") ); 879 return; 880 } 881 G_LogPrintf( "say: %s%s^7: ^2%s^7\n", prefix, ent->client->pers.netname, chatText ); 882 Com_sprintf( name, sizeof( name ), "%s%c%c"EC": ", 844 883 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 845 884 color = COLOR_GREEN; 846 885 break; 847 886 887 case SAY_ACTION: 888 G_LogPrintf( "action: %s: %s\n", ent->client->pers.netname, chatText ); 889 Com_sprintf( name, sizeof( name ), "^2%s^7%s%s%c%c"EC" ", g_actionPrefix.string, prefix, 890 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 891 color = COLOR_WHITE; 892 break; 893 case SAY_ACTION_T: 894 G_LogPrintf( "actionteam: %s: %s\n", ent->client->pers.netname, chatText ); 895 if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) 896 Com_sprintf( name, sizeof( name ), EC"^5%s^7%s%c%c"EC"(%s)"EC" ", g_actionPrefix.string, 897 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, location ); 898 else 899 Com_sprintf( name, sizeof( name ), EC"^5%s^7%s%c%c"EC""EC" ", g_actionPrefix.string, 900 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 901 color = COLOR_WHITE; 902 break; 903 848 904 case SAY_TEAM: 849 G_LogPrintf( "sayteam: %s : %s\n", ent->client->pers.netname, chatText );905 G_LogPrintf( "sayteam: %s%s^7: ^5%s^7\n", prefix, ent->client->pers.netname, chatText ); 850 906 if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) 851 907 Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC") (%s)"EC": ", … … 854 910 Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC")"EC": ", 855 911 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 856 color = COLOR_CYAN; 912 913 if( ent->client->pers.teamSelection == PTE_NONE ) 914 color = COLOR_YELLOW; 915 else 916 color = COLOR_CYAN; 917 857 918 break; 858 919 … … 867 928 color = COLOR_MAGENTA; 868 929 break; 930 931 case SAY_ADMINS: 932 if( G_admin_permission( ent, ADMF_ADMINCHAT ) ) //Differentiate between inter-admin chatter and user-admin alerts 933 { 934 G_LogPrintf( "say_admins: [ADMIN]%s: %s\n", ent->client->pers.netname, chatText ); 935 Com_sprintf( name, sizeof( name ), "%s[ADMIN]%s%c%c"EC": ", prefix, 936 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 937 color = COLOR_MAGENTA; 938 } 939 else 940 { 941 G_LogPrintf( "say_admins: [PLAYER]%s: %s\n", ent->client->pers.netname, chatText ); 942 Com_sprintf( name, sizeof( name ), "%s[PLAYER]%s%c%c"EC": ", prefix, 943 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 944 color = COLOR_MAGENTA; 945 } 946 break; 869 947 } 870 948 871 949 Q_strncpyz( text, chatText, sizeof( text ) ); 872 950 951 //R1's simple flood protection (lowered in g_client timer actions) 952 if ( g_floodProtection.integer && !G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) 953 { 954 if ( ent->client->pers.floodTimer >= 100 ) return; 955 ent->client->pers.floodTimer += g_floodProtection.integer; 956 } 957 958 873 959 if( target ) 874 960 { 875 G_SayTo( ent, target, mode, color, name, text ); 876 return; 877 } 878 879 // echo the text to the console 880 if( g_dedicated.integer ) 881 G_Printf( "%s%s\n", name, text); 961 G_SayTo( ent, target, mode, color, name, text, prefix ); 962 return; 963 } 882 964 883 965 // send it to all the apropriate clients … … 885 967 { 886 968 other = &g_entities[ j ]; 887 G_SayTo( ent, other, mode, color, name, text );969 G_SayTo( ent, other, mode, color, name, text, prefix ); 888 970 } 889 971 … … 904 986 char *p; 905 987 char *args; 988 int offset = 0; 906 989 int mode = SAY_ALL; 907 990 … … 909 992 if( Q_stricmpn( args, "say_team ", 9 ) == 0 ) 910 993 mode = SAY_TEAM; 994 if( Q_stricmpn( args, "say_admins ", 11 ) == 0 || Q_stricmpn( args, "a ", 2 ) == 0) 995 mode = SAY_ADMINS; 911 996 912 997 // support parsing /m out of say text since some people have a hard … … 920 1005 return; 921 1006 } 1007 1008 if( !Q_stricmpn( args, "say /a ", 7) || 1009 !Q_stricmpn( args, "say_team /a ", 12) || 1010 !Q_stricmpn( args, "say /say_admins ", 16) || 1011 !Q_stricmpn( args, "say_team /say_admins ", 21) ) 1012 { 1013 mode = SAY_ADMINS; 1014 offset =3; 1015 } 1016 1017 if( mode == SAY_ADMINS) 1018 if(!G_admin_permission( ent, ADMF_ADMINCHAT ) ) 1019 { 1020 if( !g_publicSayadmins.integer ) 1021 { 1022 ADMP( "Sorry, but public use of say_admins has been disabled.\n" ); 1023 return; 1024 } 1025 else 1026 { 1027 ADMP( "Your message has been sent to any available admins and to the server logs.\n" ); 1028 } 1029 } 1030 1031 if( g_allowDonate.integer ) 1032 { 1033 args = G_SayConcatArgs(0); 1034 if( !Q_stricmpn( args, "say /donate", 11 ) || 1035 !Q_stricmpn( args, "say_team /donate", 16 ) ) 1036 { 1037 Cmd_Donate_f( ent ); 1038 return; 1039 } 1040 } 922 1041 923 1042 if( trap_Argc( ) < 2 ) 924 1043 return; 925 1044 1045 if( g_allowShare.integer ) 1046 { 1047 args = G_SayConcatArgs(0); 1048 if( !Q_stricmpn( args, "say /share", 10 ) || 1049 !Q_stricmpn( args, "say_team /share", 15 ) ) 1050 { 1051 Cmd_Share_f( ent ); 1052 return; 1053 } 1054 } 1055 1056 if( g_allowActions.integer && !Q_stricmpn( args, "say /me ", 8 ) ) 1057 { 1058 mode = SAY_ACTION; 1059 offset = 4; 1060 } 1061 1062 if( g_allowActions.integer && !Q_stricmpn( args, "say_team /me ", 13 ) ) 1063 { 1064 mode = SAY_ACTION_T; 1065 offset = 4; 1066 } 1067 926 1068 p = ConcatArgs( 1 ); 1069 p += offset; 927 1070 928 1071 G_Say( ent, NULL, mode, p ); … … 956 1099 p = ConcatArgs( 2 ); 957 1100 958 G_LogPrintf( "tell: %s to %s: %s\n", ent->client->pers.netname, target->client->pers.netname, p );1101 G_LogPrintf( "tell: %s^7 to %s^7: ^6%s^7\n", ent->client->pers.netname, target->client->pers.netname, p ); 959 1102 G_Say( ent, target, SAY_TELL, p ); 960 1103 // don't tell to the player self if it was already directed to this player … … 1052 1195 1053 1196 if( clientNum != -1 && 1054 level.clients[ clientNum ].pers.connected == CON_DISCONNECTED )1197 level.clients[ clientNum ].pers.connected != CON_CONNECTED ) 1055 1198 { 1056 1199 clientNum = -1; … … 1120 1263 "Un-Mute player \'%s\'", name ); 1121 1264 } 1122 else if( !Q_stricmp( arg1, " map_restart" ) )1265 else if( !Q_stricmp( arg1, "restartmap" ) ) 1123 1266 { 1124 1267 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s", arg1 ); … … 1139 1282 sizeof( level.voteDisplayString ), "Change to map '%s'", arg2 ); 1140 1283 } 1141 else if( !Q_stricmp( arg1, " draw" ) )1142 { 1143 Com_sprintf( level.voteString, sizeof( level.voteString ), " evacuation" );1284 else if( !Q_stricmp( arg1, "nextmap" ) ) 1285 { 1286 Com_sprintf( level.voteString, sizeof( level.voteString ), "advanceMapRotation" ); 1144 1287 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), 1145 " End match in a draw" );1288 "Skip to next map in rotation" ); 1146 1289 } 1147 1290 else … … 1149 1292 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" ); 1150 1293 trap_SendServerCommand( ent-g_entities, "print \"Valid vote commands are: " 1151 "map, map_restart, draw, kick, mute and unmute\n" );1294 "map, restartmap, nextmap, kick, mute and unmute\n" ); 1152 1295 return; 1153 1296 } … … 1155 1298 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE 1156 1299 " called a vote\n\"", ent->client->pers.netname ) ); 1300 G_Printf( "'%s^7' called a vote for '%s'\n", ent->client->pers.netname, 1301 level.voteString ) ; 1157 1302 1158 1303 ent->client->pers.voteCount++; … … 1475 1620 } 1476 1621 1622 #define EVOLVE_TRACE_HEIGHT 128.0f 1477 1623 #define AS_OVER_RT3 ((ALIENSENSE_RANGE*0.5f)/M_ROOT3) 1478 1624 … … 1545 1691 int clientNum; 1546 1692 int i; 1693 trace_t tr, tr2; 1547 1694 vec3_t infestOrigin; 1548 1695 int allowedClasses[ PCL_NUM_CLASSES ]; … … 1550 1697 pClass_t currentClass = ent->client->ps.stats[ STAT_PCLASS ]; 1551 1698 pClass_t newClass; 1699 1552 1700 int numLevels; 1701 vec3_t fromMins, fromMaxs, toMins, toMaxs; 1702 vec3_t temp; 1703 1553 1704 int entityList[ MAX_GENTITIES ]; 1554 1705 vec3_t range = { AS_OVER_RT3, AS_OVER_RT3, AS_OVER_RT3 }; … … 1556 1707 int num; 1557 1708 gentity_t *other; 1709 qboolean humanNear = qfalse; 1558 1710 1559 1711 if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ) … … 1583 1735 return; 1584 1736 } 1737 else if( g_grangerMode.integer && newClass == PCL_ALIEN_BUILDER0_UPG && !level.overmindPresent) 1738 { 1739 newClass = PCL_ALIEN_BUILDER0; 1740 } 1585 1741 1586 1742 //if we are not currently spectating, we are attempting evolution … … 1590 1746 ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) 1591 1747 { 1592 trap_SendServerCommand( ent-g_entities, "print \"You cannot evolve while wallwalking\n\"");1748 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot evolve while wallwalking\n\"" ) ); 1593 1749 return; 1594 1750 } 1595 1751 1596 1752 //check there are no humans nearby 1597 1753 VectorAdd( ent->client->ps.origin, range, maxs ); 1598 1754 VectorSubtract( ent->client->ps.origin, range, mins ); 1599 1755 1600 1756 num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 1601 1757 for( i = 0; i < num; i++ ) … … 1606 1762 ( other->s.eType == ET_BUILDABLE && other->biteam == BIT_HUMANS ) ) 1607 1763 { 1608 G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); 1609 return; 1764 humanNear = qtrue; 1610 1765 } 1766 //If its the OM, then ignore all humans. 1767 if(other->s.eType == ET_BUILDABLE && other->s.modelindex == BA_A_OVERMIND) 1768 { 1769 humanNear = qfalse; 1770 break; 1771 } 1772 } 1773 1774 if(humanNear == qtrue) 1775 { 1776 G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); 1777 return; 1611 1778 } 1612 1779 … … 1622 1789 ent->client->ps.stats[ STAT_MISC ] > 0 ) 1623 1790 { 1624 G_TriggerMenu( ent->client->ps.clientNum, MN_A_EVOLVEBUILDTIMER ); 1791 trap_SendServerCommand( ent-g_entities, 1792 va( "print \"You cannot evolve until build timer expires\n\"" ) ); 1625 1793 return; 1626 1794 } … … 1630 1798 (short)ent->client->ps.persistant[ PERS_CREDIT ], 0 ); 1631 1799 1632 if( G_RoomForClassChange( ent, newClass, infestOrigin ) ) 1800 BG_FindBBoxForClass( currentClass, 1801 fromMins, fromMaxs, NULL, NULL, NULL ); 1802 BG_FindBBoxForClass( newClass, 1803 toMins, toMaxs, NULL, NULL, NULL ); 1804 1805 VectorCopy( ent->s.pos.trBase, infestOrigin ); 1806 1807 infestOrigin[ 2 ] += ( fabs( toMins[ 2 ] ) - fabs( fromMins[ 2 ] ) ) + 1.0f; 1808 VectorCopy( infestOrigin, temp ); 1809 temp[ 2 ] += EVOLVE_TRACE_HEIGHT; 1810 1811 //compute a place up in the air to start the real trace 1812 trap_Trace( &tr, infestOrigin, toMins, toMaxs, temp, ent->s.number, MASK_SHOT ); 1813 VectorCopy( infestOrigin, temp ); 1814 temp[ 2 ] += ( EVOLVE_TRACE_HEIGHT * tr.fraction ) - 1.0f; 1815 1816 //trace down to the ground so that we can evolve on slopes 1817 trap_Trace( &tr, temp, toMins, toMaxs, infestOrigin, ent->s.number, MASK_SHOT ); 1818 VectorCopy( tr.endpos, infestOrigin ); 1819 1820 //make REALLY sure 1821 trap_Trace( &tr2, ent->s.pos.trBase, NULL, NULL, infestOrigin, ent->s.number, MASK_SHOT ); 1822 1823 //check there is room to evolve 1824 if( !tr.startsolid && tr2.fraction == 1.0f ) 1633 1825 { 1634 1826 //...check we can evolve to that class 1635 if( numLevels >= 0&&1827 if( (numLevels >= 0 || g_freeFunds.integer) && 1636 1828 BG_FindStagesForClass( newClass, g_alienStage.integer ) && 1637 1829 BG_ClassIsAllowed( newClass ) ) 1638 1830 { 1831 G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 1832 1639 1833 ent->client->pers.evolveHealthFraction = (float)ent->client->ps.stats[ STAT_HEALTH ] / 1640 1834 (float)BG_FindHealthForClass( currentClass ); … … 1645 1839 ent->client->pers.evolveHealthFraction = 1.0f; 1646 1840 1647 //remove credit 1648 G_AddCreditToClient( ent->client, -(short)numLevels, qtrue ); 1841 //remove credit if not freefunds 1842 if (!g_freeFunds.integer) 1843 G_AddCreditToClient( ent->client, -(short)numLevels, qtrue ); 1649 1844 ent->client->pers.classSelection = newClass; 1650 1845 ClientUserinfoChanged( clientNum ); … … 1672 1867 BG_ClassIsAllowed( newClass ) ) 1673 1868 { 1869 G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 1870 1674 1871 ent->client->pers.classSelection = 1675 1872 ent->client->ps.stats[ STAT_PCLASS ] = newClass; … … 1707 1904 return; 1708 1905 } 1906 1907 G_LogOnlyPrintf("ClientTeamClass: %i human %s\n", clientNum, s); 1709 1908 1710 1909 G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ); … … 1783 1982 1784 1983 // Don't allow destruction of buildables that cannot be rebuilt 1785 if( G_TimeTilSuddenDeath( ) <= 0 && 1786 BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) 1787 { 1984 if( level.suddenDeath && traceEnt->health > 0 && 1985 ( ( g_suddenDeathMode.integer == SDMODE_SELECTIVE && 1986 !BG_FindReplaceableTestForBuildable( traceEnt->s.modelindex ) ) || 1987 ( g_suddenDeathMode.integer == SDMODE_BP && 1988 BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) || 1989 g_suddenDeathMode.integer == SDMODE_NO_BUILD ) ) 1990 { 1991 trap_SendServerCommand( ent-g_entities, 1992 "print \"During Sudden Death you can only decon buildings that " 1993 "can be rebuilt\n\"" ); 1788 1994 return; 1789 1995 } … … 1811 2017 ent->client->pers.netname ) ); 1812 2018 1813 G_LogPrintf( "Decon: %i %i 0: %s deconstructed%s\n",2019 G_LogPrintf( "Decon: %i %i 0: %s ^3deconstructed^7 %s\n", 1814 2020 ent->client->ps.clientNum, 1815 2021 traceEnt->s.modelindex, … … 1819 2025 G_FreeEntity( traceEnt ); 1820 2026 1821 if( !g_cheats.integer ) 2027 // cheat or fast build -> no build timer 2028 if( !g_cheats.integer && !g_fastBuild.integer ) 1822 2029 ent->client->ps.stats[ STAT_MISC ] += 1823 2030 BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 2; 1824 2031 } 2032 } 2033 else 2034 { 2035 // We *can* deconstrute building on fire :) 2036 G_LogPrintf( "Decon: %i %i 0: %s ^3deconstructed^7 %s\n", 2037 ent->client->ps.clientNum, 2038 traceEnt->s.modelindex, 2039 ent->client->pers.netname, 2040 BG_FindNameForBuildable( traceEnt->s.modelindex ) ); 2041 2042 if( !deconstruct ) 2043 G_Damage( traceEnt, ent, ent, forward, tr.endpos, 10000, 0, MOD_SUICIDE ); 2044 else 2045 G_FreeEntity( traceEnt ); 2046 2047 // cheat or fast build -> no build timer 2048 if( !g_cheats.integer && !g_fastBuild.integer ) 2049 ent->client->ps.stats[ STAT_MISC ] += 2050 BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 2; 1825 2051 } 1826 2052 } … … 1894 2120 //special case to allow switching between 1895 2121 //the blaster and the primary weapon 2122 ent->client->ps.weaponTime = 0; 1896 2123 1897 2124 if( ent->client->ps.weapon != WP_BLASTER ) … … 1961 2188 !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 1962 2189 { 1963 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOENERGYAMMOHERE ); 2190 trap_SendServerCommand( ent-g_entities, va( 2191 "print \"You must be near a reactor, repeater or armoury\n\"" ) ); 1964 2192 return; 1965 2193 } … … 1970 2198 if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 1971 2199 { 1972 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOARMOURYHERE);2200 trap_SendServerCommand( ent-g_entities, va( "print \"You must be near a powered armoury\n\"" ) ); 1973 2201 return; 1974 2202 } … … 1984 2212 } 1985 2213 1986 //can afford this? 1987 if( BG_FindPriceForWeapon( weapon ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] )2214 //can afford this? (if free funds then go buy, it's free !) 2215 if( !g_freeFunds.integer && BG_FindPriceForWeapon( weapon ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] ) 1988 2216 { 1989 2217 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); … … 2027 2255 maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 2028 2256 2029 ent->client->ps.ammo = maxAmmo;2030 ent->client->ps.clips = maxClips;2257 BG_PackAmmoArray( weapon, ent->client->ps.ammo, ent->client->ps.powerups, 2258 maxAmmo, maxClips ); 2031 2259 2032 2260 G_ForceWeaponChange( ent, weapon ); … … 2036 2264 2037 2265 //subtract from funds 2038 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ), qfalse ); 2266 if (!g_freeFunds.integer) // buy it for free 2267 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ), qfalse ); 2039 2268 } 2040 2269 else if( upgrade != UP_NONE ) … … 2048 2277 2049 2278 //can afford this? 2050 if( BG_FindPriceForUpgrade( upgrade ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] )2279 if( !g_freeFunds.integer && BG_FindPriceForUpgrade( upgrade ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] ) 2051 2280 { 2052 2281 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); … … 2092 2321 if( !G_RoomForClassChange( ent, PCL_HUMAN_BSUIT, newOrigin ) ) 2093 2322 { 2094 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITON);2323 trap_SendServerCommand( ent-g_entities, va( "print \"Not enough room here to put on a Battle Suit\n\"") ); 2095 2324 return; 2096 2325 } … … 2108 2337 2109 2338 //subtract from funds 2110 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2339 if (!g_freeFunds.integer) 2340 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2111 2341 } 2112 2342 else … … 2136 2366 if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 2137 2367 { 2138 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOARMOURYHERE);2368 trap_SendServerCommand( ent-g_entities, va( "print \"You must be near a powered armoury\n\"" ) ); 2139 2369 return; 2140 2370 } … … 2159 2389 ent->client->ps.stats[ STAT_MISC ] > 0 ) 2160 2390 { 2161 G_TriggerMenu( ent->client->ps.clientNum, MN_H_ARMOURYBUILDTIMER);2391 trap_SendServerCommand( ent-g_entities, va( "print \"Cannot sell until build timer expires\n\"" ) ); 2162 2392 return; 2163 2393 } … … 2166 2396 2167 2397 //add to funds 2168 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ), qfalse ); 2398 if (!g_freeFunds.integer) // yes free funds but not get 9999 credits :) 2399 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ), qfalse ); 2169 2400 } 2170 2401 … … 2191 2422 if( !G_RoomForClassChange( ent, PCL_HUMAN, newOrigin ) ) 2192 2423 { 2193 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITOFF);2424 trap_SendServerCommand( ent-g_entities, va( "print \"Not enough room here to take off your Battle Suit\n\"") ); 2194 2425 return; 2195 2426 } … … 2206 2437 2207 2438 //add to funds 2208 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2439 if (!g_freeFunds.integer) 2440 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2209 2441 } 2210 2442 } … … 2217 2449 ent->client->ps.stats[ STAT_MISC ] > 0 ) 2218 2450 { 2219 G_TriggerMenu( ent->client->ps.clientNum, MN_H_ARMOURYBUILDTIMER);2451 trap_SendServerCommand( ent-g_entities, va( "print \"Cannot sell until build timer expires\n\"" ) ); 2220 2452 continue; 2221 2453 } … … 2227 2459 2228 2460 //add to funds 2229 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ), qfalse ); 2461 if (!g_freeFunds.integer) 2462 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ), qfalse ); 2230 2463 } 2231 2464 … … 2243 2476 BG_FindPurchasableForUpgrade( i ) ) 2244 2477 { 2245 2246 // shouldn't really need to test for this, but just to be safe2247 if( i == UP_BATTLESUIT )2248 {2249 vec3_t newOrigin;2250 2251 if( !G_RoomForClassChange( ent, PCL_HUMAN, newOrigin ) )2252 {2253 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITOFF );2254 continue;2255 }2256 VectorCopy( newOrigin, ent->s.pos.trBase );2257 ent->client->ps.stats[ STAT_PCLASS ] = PCL_HUMAN;2258 }2259 2260 2478 BG_RemoveUpgradeFromInventory( i, ent->client->ps.stats ); 2261 2479 … … 2271 2489 !BG_FindInfinteAmmoForWeapon( j ) ) 2272 2490 { 2273 ent->client->ps.ammo = 0; 2274 ent->client->ps.clips = 0; 2491 BG_PackAmmoArray( j, ent->client->ps.ammo, ent->client->ps.powerups, 0, 0 ); 2275 2492 } 2276 2493 } … … 2278 2495 2279 2496 //add to funds 2280 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ), qfalse ); 2497 if (!g_freeFunds.integer) 2498 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ), qfalse ); 2281 2499 } 2282 2500 } … … 2313 2531 2314 2532 buildable = BG_FindBuildNumForName( s ); 2533 2534 if( level.suddenDeath ) 2535 { 2536 if( g_suddenDeathMode.integer == SDMODE_SELECTIVE && 2537 !BG_FindReplaceableTestForBuildable( buildable ) ) 2538 { 2539 trap_SendServerCommand( ent-g_entities, 2540 "print \"Only essential buildings can be rebuilt in Sudden Death\n\"" ); 2541 return; 2542 } 2543 else if( g_suddenDeathMode.integer == SDMODE_NO_BUILD ) 2544 { 2545 trap_SendServerCommand( ent-g_entities, 2546 "print \"Building is not allowed during Sudden Death\n\"" ); 2547 } 2548 } 2549 2550 if(g_repeaterOnReactor.integer && buildable == BA_H_REACTOR && level.reactorPresent) 2551 buildable = BA_H_REPEATER; 2552 2315 2553 team = ent->client->ps.stats[ STAT_PTEAM ]; 2316 2554 … … 2379 2617 } 2380 2618 2619 /* 2620 ================= 2621 Cmd_Share_f 2622 ================= 2623 */ 2624 void Cmd_Share_f( gentity_t *ent ) 2625 { 2626 int i, clientNum = 0, creds = 0, skipargs = 0; 2627 int clientNums[ MAX_CLIENTS ] = { -1 }; 2628 char cmd[ 12 ]; 2629 char arg1[ MAX_STRING_TOKENS ]; 2630 char arg2[ MAX_STRING_TOKENS ]; 2631 pTeam_t team; 2632 2633 if( !ent || !ent->client || ( ent->client->pers.teamSelection == PTE_NONE ) ) 2634 { 2635 return; 2636 } 2637 2638 if( !g_allowShare.integer ) 2639 { 2640 return; 2641 } 2642 2643 team = ent->client->pers.teamSelection; 2644 2645 G_SayArgv( 0, cmd, sizeof( cmd ) ); 2646 if( !Q_stricmp( cmd, "say" ) || !Q_stricmp( cmd, "say_team" ) ) 2647 { 2648 skipargs = 1; 2649 G_SayArgv( 1, cmd, sizeof( cmd ) ); 2650 } 2651 2652 // target player name is in arg1 2653 G_SayArgv( 1+skipargs, arg1, sizeof( arg1 ) ); 2654 // amount to be shared is in arg2 2655 G_SayArgv( 2+skipargs, arg2, sizeof( arg2 ) ); 2656 2657 if( arg1[0] && !strchr( arg1, ';' ) && Q_stricmp( arg1, "target_in_aim" ) ) 2658 { 2659 //check arg1 is a number 2660 for( i = 0; arg1[ i ]; i++ ) 2661 { 2662 if( arg1[ i ] < '0' || arg1[ i ] > '9' ) 2663 { 2664 clientNum = -1; 2665 break; 2666 } 2667 } 2668 2669 if( clientNum >= 0 ) 2670 { 2671 clientNum = atoi( arg1 ); 2672 } 2673 else if( G_ClientNumbersFromString( arg1, clientNums, MAX_CLIENTS ) == 1 ) 2674 { 2675 // there was one partial name match 2676 clientNum = clientNums[ 0 ]; 2677 } 2678 else 2679 { 2680 // look for an exact name match before bailing out 2681 clientNum = G_ClientNumberFromString( ent, arg1 ); 2682 if( clientNum == -1 ) 2683 { 2684 trap_SendServerCommand( ent-g_entities, 2685 "print \"share: invalid player name specified.\n\"" ); 2686 return; 2687 } 2688 } 2689 } 2690 else // arg1 not set 2691 { 2692 vec3_t forward, end; 2693 trace_t tr; 2694 gentity_t *traceEnt; 2695 2696 2697 // trace a teammate 2698 AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL ); 2699 VectorMA( ent->client->ps.origin, 8192 * 16, forward, end ); 2700 2701 trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); 2702 traceEnt = &g_entities[ tr.entityNum ]; 2703 2704 if( tr.fraction < 1.0f && traceEnt->client && 2705 ( traceEnt->client->pers.teamSelection == team ) ) 2706 { 2707 clientNum = traceEnt - g_entities; 2708 } 2709 else 2710 { 2711 trap_SendServerCommand( ent-g_entities, 2712 va( "print \"share: aim at a teammate to share %s.\n\"", 2713 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) ); 2714 return; 2715 } 2716 } 2717 2718 // verify target player team 2719 if( ( clientNum < 0 ) || ( clientNum >= level.maxclients ) || 2720 ( level.clients[ clientNum ].pers.teamSelection != team ) ) 2721 { 2722 trap_SendServerCommand( ent-g_entities, 2723 "print \"share: not a valid player of your team.\n\"" ); 2724 return; 2725 } 2726 2727 if( !arg2[0] || strchr( arg2, ';' ) ) 2728 { 2729 // default credit count 2730 if( team == PTE_HUMANS ) 2731 { 2732 creds = FREEKILL_HUMAN; 2733 } 2734 else if( team == PTE_ALIENS ) 2735 { 2736 creds = FREEKILL_ALIEN; 2737 } 2738 } 2739 else 2740 { 2741 //check arg2 is a number 2742 for( i = 0; arg2[ i ]; i++ ) 2743 { 2744 if( arg2[ i ] < '0' || arg2[ i ] > '9' ) 2745 { 2746 trap_SendServerCommand( ent-g_entities, 2747 "print \"usage: share [name|slot#] [amount]\n\"" ); 2748 break; 2749 } 2750 } 2751 2752 // credit count from parameter 2753 creds = atoi( arg2 ); 2754 } 2755 2756 // player specified "0" to transfer 2757 if( creds <= 0 ) 2758 { 2759 trap_SendServerCommand( ent-g_entities, 2760 "print \"Ooh, you are a generous one, indeed!\n\"" ); 2761 return; 2762 } 2763 2764 // transfer only credits the player really has 2765 if( creds > ent->client->ps.persistant[ PERS_CREDIT ] ) 2766 { 2767 creds = ent->client->ps.persistant[ PERS_CREDIT ]; 2768 } 2769 2770 // player has no credits 2771 if( creds <= 0 ) 2772 { 2773 trap_SendServerCommand( ent-g_entities, 2774 "print \"Earn some first, lazy gal!\n\"" ); 2775 return; 2776 } 2777 2778 // allow transfers only up to the credit/evo limit 2779 if( ( team == PTE_HUMANS ) && 2780 ( creds > HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) ) 2781 { 2782 creds = HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ]; 2783 } 2784 else if( ( team == PTE_ALIENS ) && 2785 ( creds > ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) ) 2786 { 2787 creds = ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ]; 2788 } 2789 2790 // target cannot take any more credits 2791 if( creds <= 0 ) 2792 { 2793 trap_SendServerCommand( ent-g_entities, 2794 va( "print \"share: player cannot receive any more %s.\n\"", 2795 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) ); 2796 return; 2797 } 2798 2799 // transfer credits 2800 ent->client->ps.persistant[ PERS_CREDIT ] -= creds; 2801 trap_SendServerCommand( ent-g_entities, 2802 va( "print \"share: transferred %d %s to %s^7.\n\"", creds, 2803 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints", 2804 level.clients[ clientNum ].pers.netname ) ); 2805 level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] += creds; 2806 trap_SendServerCommand( clientNum, 2807 va( "print \"You have received %d %s from %s^7.\n\"", creds, 2808 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints", 2809 ent->client->pers.netname ) ); 2810 2811 G_LogPrintf( "Share: %i %i %i %d: %s^7 transferred %d%s to %s^7\n", 2812 ent->client->ps.clientNum, 2813 clientNum, 2814 team, 2815 creds, 2816 ent->client->pers.netname, 2817 creds, 2818 ( team == PTE_HUMANS ) ? "c" : "e", 2819 level.clients[ clientNum ].pers.netname ); 2820 } 2821 2381 2822 2382 2823 /* … … 2489 2930 2490 2931 // can't follow another spectator 2491 if( level.clients[ clientnum ]. sess.sessionTeam == TEAM_SPECTATOR)2932 if( level.clients[ clientnum ].pers.teamSelection == PTE_NONE ) 2492 2933 continue; 2493 2934 … … 2502 2943 } 2503 2944 2945 /* 2946 ================= 2947 Cmd_Donate_f 2948 2949 Alms for the poor 2950 ================= 2951 */ 2952 void Cmd_Donate_f( gentity_t *ent ) 2953 { 2954 int divisor; 2955 char s[20]; 2956 int skipargs = 0; 2957 int value; 2958 2959 if( !ent->client || !g_allowDonate.integer ) return; 2960 2961 if( ent->client->pers.teamSelection == PTE_ALIENS ) 2962 divisor = level.numAlienClients-1; 2963 else if( ent->client->pers.teamSelection == PTE_HUMANS ) 2964 divisor = level.numHumanClients-1; 2965 else 2966 return; 2967 2968 if(ent->client->pers.teamSelection == PTE_NONE ) 2969 { 2970 trap_SendServerCommand( ent-g_entities, 2971 va( "print \"donate: spectators cannot be so gracious\n\"" ) ); 2972 return; 2973 } 2974 2975 if( divisor < 1 ) { 2976 trap_SendServerCommand( ent-g_entities, 2977 "print \"donate: get yourself some teammates first\n\"" ); 2978 return; 2979 } 2980 2981 G_SayArgv ( 0, s, sizeof( s ) ); 2982 if ( !Q_stricmp( s, "say" ) || !Q_stricmp( s, "say_team" ) ) 2983 { 2984 skipargs = 1; 2985 G_SayArgv ( 1, s, sizeof( s )); //usefull ? 2986 } 2987 2988 G_SayArgv( 1 + skipargs, s, sizeof( s ) ); 2989 value = atoi(s); 2990 if( value <= 0 ) { 2991 trap_SendServerCommand( ent-g_entities, 2992 "print \"donate: very funny\n\"" ); 2993 return; 2994 } 2995 2996 G_Donate(ent->client, value); 2997 } 2998 2504 2999 /* 2505 3000 ================= … … 2517 3012 /* 2518 3013 ================= 2519 Cmd_Follow_f 3014 Cmd_Follow_f (with r1 changes in here) 2520 3015 ================= 2521 3016 */ … … 2760 3255 { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2761 3256 { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 3257 { "say_admins", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 3258 { "a", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2762 3259 { "m", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 2763 3260 { "mt", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 2764 3261 { "me", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2765 3262 { "score", CMD_INTERMISSION, ScoreboardMessage }, 2766 3263 … … 2779 3276 { "ptrcverify", 0, Cmd_PTRCVerify_f }, 2780 3277 { "ptrcrestore", 0, Cmd_PTRCRestore_f }, 3278 { "share", CMD_TEAM, Cmd_Share_f }, 3279 { "donate", CMD_TEAM, Cmd_Donate_f }, 2781 3280 2782 3281 { "follow", CMD_NOTEAM, Cmd_Follow_f }, … … 3020 3519 gentity_t *tmpent; 3021 3520 3521 if ( g_floodProtection.integer && !G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) 3522 { 3523 if ( ent->client->pers.floodTimer >= 100 ) return; 3524 ent->client->pers.floodTimer += g_floodProtection.integer; 3525 } 3526 3022 3527 if( !g_privateMessages.integer && ent ) 3023 3528 { … … 3074 3579 3075 3580 color = teamonly ? COLOR_CYAN : COLOR_YELLOW; 3581 3582 if( !Q_stricmp( name, "console" ) ) 3583 { 3584 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3585 ADMP( va( "^%csent to Console.\n", color ) ); 3586 3587 G_LogPrintf( "privmsg: %s^7: Console: ^6%s^7\n", 3588 ( ent ) ? ent->client->pers.netname : "Console", msg ); 3589 3590 return; 3591 } 3076 3592 3077 3593 Q_strncpyz( str, … … 3089 3605 trap_SendServerCommand( pids[ i ], va( 3090 3606 "chat \"%s^%c -> ^7%s^7: (%d recipients): ^%c%s^7\" %i", 3091 ( ent ) ? ent->client->pers.netname : " console",3607 ( ent ) ? ent->client->pers.netname : "Console", 3092 3608 color, 3093 3609 name, … … 3096 3612 msg, 3097 3613 ent ? ent-g_entities : -1 ) ); 3098 if( ent ) 3099 { 3100 trap_SendServerCommand( pids[ i ], va( 3101 "print \">> to reply, say: /m %d [your message] <<\n\"", 3102 ( ent - g_entities ) ) ); 3103 } 3104 trap_SendServerCommand( pids[ i ], va( 3614 3615 trap_SendServerCommand( pids[ i ], va( 3105 3616 "cp \"^%cprivate message from ^7%s^7\"", color, 3106 ( ent ) ? ent->client->pers.netname : " console" ) );3617 ( ent ) ? ent->client->pers.netname : "Console" ) ); 3107 3618 } 3108 3619 … … 3112 3623 else 3113 3624 { 3114 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3625 if( ent ) 3626 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3627 3115 3628 ADMP( va( "%s\n", str ) ); 3116 3117 G_LogPrintf( "%s: %s: %s: %s\n",3118 ( teamonly ) ? "tprivmsg" : "privmsg",3119 ( ent ) ? ent->client->pers.netname : "console",3120 name, msg );3121 3629 } 3122 3630 -
src/game/g_cmds.c
r123 r124 54 54 } 55 55 56 if( *in == 27 || *in == '^')56 if( *in == 27 || Q_IsColorString( in ) ) 57 57 { 58 58 in += 2; // skip color code … … 194 194 return 0; 195 195 } 196 196 197 197 // now look for name matches 198 198 G_SanitiseName( s, s2 ); … … 536 536 continue; 537 537 538 // clean up projectiles539 if( ent->s.eType == ET_MISSILE && ent->r.ownerNum == self->s.number )540 G_FreeEntity( ent );541 538 if( ent->client && ent->client->pers.connected == CON_CONNECTED ) 542 539 { … … 557 554 ent->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; 558 555 } 556 else if( ent->s.eType == ET_MISSILE && ent->r.ownerNum == self->s.number ) 557 G_FreeEntity( ent ); 559 558 } 560 559 } … … 568 567 { 569 568 pTeam_t oldTeam = ent->client->pers.teamSelection; 570 569 571 570 if( oldTeam == newTeam ) 572 571 return; … … 578 577 // when switching teams 579 578 if( G_admin_permission( ent, ADMF_TEAMCHANGEFREE ) || 580 ( ( oldTeam == PTE_HUMANS || oldTeam == PTE_ALIENS ) 581 &&( level.time - ent->client->pers.teamChangeTime ) > 60000 ) )579 ( ( oldTeam == PTE_HUMANS || oldTeam == PTE_ALIENS ) && 580 ( level.time - ent->client->pers.teamChangeTime ) > 60000 ) ) 582 581 { 583 582 if( oldTeam == PTE_NONE ) 584 583 { 585 584 // ps.persistant[] from a spectator cannot be trusted 586 ent->client->ps.persistant[ PERS_SCORE ] = ent->client->pers.savedScore;587 585 ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.savedCredit; 588 586 } … … 598 596 // save values before the client enters the spectator team and their 599 597 // ps.persistant[] values become trashed 600 ent->client->pers.savedScore = ent->client->ps.persistant[ PERS_SCORE ];601 598 ent->client->pers.savedCredit = ent->client->ps.persistant[ PERS_CREDIT ]; 602 599 } … … 612 609 ent->client->ps.persistant[ PERS_CREDIT ] = 0; 613 610 ent->client->ps.persistant[ PERS_SCORE ] = 0; 614 ent->client->pers.savedScore = 0;615 611 ent->client->pers.savedCredit = 0; 616 612 } … … 664 660 trap_Argv( 1, s, sizeof( s ) ); 665 661 666 if( !s trlen( s ))667 { 668 trap_SendServerCommand( ent-g_entities, va( "print \"team: %i\n\"",662 if( !s[ 0 ] ) 663 { 664 trap_SendServerCommand( ent-g_entities, va( "print \"team: %i\n\"", 669 665 oldteam ) ); 670 666 return; … … 700 696 { 701 697 trap_SendServerCommand( ent-g_entities, 702 va( "print \"Alien team has been ^1LOCKED\n\"" ));703 return; 698 "print \"Alien team has been ^1LOCKED\n\"" ); 699 return; 704 700 } 705 701 … … 717 713 { 718 714 trap_SendServerCommand( ent-g_entities, 719 va( "print \"Human team has been ^1LOCKED\n\"" ));720 return; 715 "print \"Human team has been ^1LOCKED\n\"" ); 716 return; 721 717 } 722 718 if( !force && !level.alienTeamLocked && g_teamForceBalance.integer && humans > aliens ) … … 854 850 char location[ 64 ]; 855 851 856 if (g_chatTeamPrefix.integer)857 { 858 switch( ent->client->pers.teamSelection )852 if( g_chatTeamPrefix.integer ) 853 { 854 switch( ent->client->pers.teamSelection ) 859 855 { 860 856 default: … … 973 969 G_SayTo( ent, other, mode, color, name, text, prefix ); 974 970 } 975 971 976 972 if( g_adminParseSay.integer ) 977 973 { … … 1002 998 // time figuring out what the console is. 1003 999 if( !Q_stricmpn( args, "say /m ", 7 ) || 1004 !Q_stricmpn( args, "say_team /m ", 12 ) || 1005 !Q_stricmpn( args, "say /mt ", 8 ) || 1000 !Q_stricmpn( args, "say_team /m ", 12 ) || 1001 !Q_stricmpn( args, "say /mt ", 8 ) || 1006 1002 !Q_stricmpn( args, "say_team /mt ", 13 ) ) 1007 1003 { … … 1146 1142 } 1147 1143 1148 if( g_voteLimit.integer > 0 1149 && ent->client->pers.voteCount >= g_voteLimit.integer1150 &&!G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) )1144 if( g_voteLimit.integer > 0 && 1145 ent->client->pers.voteCount >= g_voteLimit.integer && 1146 !G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) ) 1151 1147 { 1152 1148 trap_SendServerCommand( ent-g_entities, va( … … 1190 1186 { 1191 1187 // there was only one partial name match 1192 clientNum = clientNums[ 0 ]; 1188 clientNum = clientNums[ 0 ]; 1193 1189 } 1194 1190 else 1195 1191 { 1196 // look for an exact name match (sets clientNum to -1 if it fails) 1192 // look for an exact name match (sets clientNum to -1 if it fails) 1197 1193 clientNum = G_ClientNumberFromString( ent, arg2 ); 1198 1194 } … … 1217 1213 } 1218 1214 } 1219 1215 1220 1216 if( !Q_stricmp( arg1, "kick" ) ) 1221 1217 { … … 1313 1309 ent->client->pers.vote = qtrue; 1314 1310 1315 for( i = 0 ; i < level.maxclients; i++ )1311 for( i = 0; i < level.maxclients; i++ ) 1316 1312 level.clients[i].ps.eFlags &= ~EF_VOTED; 1317 1313 … … 1367 1363 int clientNum = -1; 1368 1364 char name[ MAX_NETNAME ]; 1369 1365 1370 1366 team = ent->client->pers.teamSelection; 1371 1367 … … 1385 1381 } 1386 1382 1387 if( g_voteLimit.integer > 0 1388 && ent->client->pers.voteCount >= g_voteLimit.integer1389 &&!G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) )1383 if( g_voteLimit.integer > 0 && 1384 ent->client->pers.voteCount >= g_voteLimit.integer && 1385 !G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) ) 1390 1386 { 1391 1387 trap_SendServerCommand( ent-g_entities, va( … … 1404 1400 return; 1405 1401 } 1406 1402 1407 1403 // detect clientNum for partial name match votes 1408 1404 if( !Q_stricmp( arg1, "kick" ) || … … 1422 1418 { 1423 1419 // there was only one partial name match 1424 clientNum = clientNums[ 0 ]; 1420 clientNum = clientNums[ 0 ]; 1425 1421 } 1426 1422 else 1427 1423 { 1428 // look for an exact name match (sets clientNum to -1 if it fails) 1424 // look for an exact name match (sets clientNum to -1 if it fails) 1429 1425 clientNum = G_ClientNumberFromString( ent, arg2 ); 1430 1426 } … … 1436 1432 clientNum = -1; 1437 1433 } 1438 1434 1439 1435 if( clientNum != -1 && 1440 1436 level.clients[ clientNum ].pers.connected == CON_DISCONNECTED ) … … 1540 1536 ent->client->pers.teamVote = qtrue; 1541 1537 1542 for( i = 0 ; i < level.maxclients; i++ )1538 for( i = 0; i < level.maxclients; i++ ) 1543 1539 { 1544 1540 if( level.clients[ i ].ps.stats[ STAT_PTEAM ] == team ) … … 1606 1602 if( trap_Argc( ) != 5 ) 1607 1603 { 1608 trap_SendServerCommand( ent-g_entities, va( "print \"usage: setviewpos x y z yaw\n\"" ));1604 trap_SendServerCommand( ent-g_entities, "print \"usage: setviewpos x y z yaw\n\"" ); 1609 1605 return; 1610 1606 } … … 1612 1608 VectorClear( angles ); 1613 1609 1614 for( i = 0 ; i < 3; i++ )1610 for( i = 0; i < 3; i++ ) 1615 1611 { 1616 1612 trap_Argv( i + 1, buffer, sizeof( buffer ) ); … … 1682 1678 1683 1679 //check there is room to evolve 1684 if( !tr.startsolid && tr.fraction == 1.0f ) 1685 return qtrue; 1686 else 1687 return qfalse; 1680 return ( !tr.startsolid && tr.fraction == 1.0f ); 1688 1681 } 1689 1682 … … 1739 1732 if( newClass == PCL_NONE ) 1740 1733 { 1741 trap_SendServerCommand( ent-g_entities, va( "print \"Unknown class\n\"" ));1734 trap_SendServerCommand( ent-g_entities, "print \"Unknown class\n\"" ); 1742 1735 return; 1743 1736 } … … 1750 1743 if( ent->client->pers.classSelection != PCL_NONE ) 1751 1744 { 1752 1753 if( !level.overmindPresent)1754 { 1755 G_TriggerMenu( clientNum, MN_A_NOOVMND_EVOLVE);1745 if( ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING ) || 1746 ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) 1747 { 1748 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot evolve while wallwalking\n\"" ) ); 1756 1749 return; 1757 1750 } … … 1784 1777 return; 1785 1778 } 1786 1787 if( ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING ) || 1788 ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) 1789 { 1790 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot evolve while wallwalking\n\"" ) ); 1779 1780 if( !level.overmindPresent ) 1781 { 1782 G_TriggerMenu( clientNum, MN_A_NOOVMND_EVOLVE ); 1791 1783 return; 1792 1784 } 1793 1794 1785 1795 1786 //guard against selling the HBUILD weapons exploit … … 1855 1846 VectorCopy( infestOrigin, ent->s.pos.trBase ); 1856 1847 ClientSpawn( ent, ent, ent->s.pos.trBase, ent->s.apos.trBase ); 1857 return;1858 1848 } 1859 1849 else 1860 1850 { 1861 1851 trap_SendServerCommand( ent-g_entities, 1862 va( "print \"You cannot evolve from your current class\n\"" ) ); 1863 return; 1852 "print \"You cannot evolve from your current class\n\"" ); 1864 1853 } 1865 1854 } … … 1867 1856 { 1868 1857 G_TriggerMenu( clientNum, MN_A_NOEROOM ); 1869 return;1870 1858 } 1871 1859 } … … 1887 1875 } 1888 1876 } 1889 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot spawn as this class\n\"" ) ); 1890 return; 1877 trap_SendServerCommand( ent-g_entities, "print \"You cannot spawn as this class\n\"" ); 1891 1878 } 1892 1879 } … … 1896 1883 if( ent->client->pers.classSelection != PCL_NONE ) 1897 1884 { 1898 trap_SendServerCommand( ent-g_entities, va( "print \"You must be dead to use the class command\n\"" ));1885 trap_SendServerCommand( ent-g_entities, "print \"You must be dead to use the class command\n\"" ); 1899 1886 return; 1900 1887 } … … 1914 1901 { 1915 1902 ent->client->pers.classSelection = PCL_NONE; 1916 trap_SendServerCommand( ent-g_entities, va( "print \"Unknown starting item\n\"" ));1903 trap_SendServerCommand( ent-g_entities, "print \"Unknown starting item\n\"" ); 1917 1904 return; 1918 1905 } … … 2016 2003 if( traceEnt->health > 0 ) 2017 2004 { 2018 if( g_markDeconstruct.integer ) 2005 if( !deconstruct ) 2006 G_Damage( traceEnt, ent, ent, forward, tr.endpos, 10000, 0, MOD_SUICIDE ); 2007 else if( g_markDeconstruct.integer ) 2019 2008 { 2020 2009 traceEnt->deconstruct = qtrue; // Mark buildable for deconstruction … … 2034 2023 BG_FindNameForBuildable( traceEnt->s.modelindex ) ); 2035 2024 2036 if( !deconstruct ) 2037 G_Damage( traceEnt, ent, ent, forward, tr.endpos, 10000, 0, MOD_SUICIDE ); 2038 else 2039 G_FreeEntity( traceEnt ); 2025 G_FreeEntity( traceEnt ); 2040 2026 2041 2027 // cheat or fast build -> no build timer … … 2124 2110 { 2125 2111 char s[ MAX_TOKEN_CHARS ]; 2126 int upgrade, weapon , i;2112 int upgrade, weapon; 2127 2113 2128 2114 trap_Argv( 1, s, sizeof( s ) ); … … 2139 2125 weapon = WP_BLASTER; 2140 2126 else 2141 { 2142 //find a held weapon which isn't the blaster 2143 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 2144 { 2145 if( i == WP_BLASTER ) 2146 continue; 2147 2148 if( BG_InventoryContainsWeapon( i, ent->client->ps.stats ) ) 2149 { 2150 weapon = i; 2151 break; 2152 } 2153 } 2154 2155 if( i == WP_NUM_WEAPONS ) 2156 weapon = WP_BLASTER; 2157 } 2127 weapon = WP_NONE; 2158 2128 2159 2129 G_ForceWeaponChange( ent, weapon ); … … 2259 2229 { 2260 2230 //shouldn't need a fancy dialog 2261 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy alien items\n\"" ));2231 trap_SendServerCommand( ent-g_entities, "print \"You can't buy alien items\n\"" ); 2262 2232 return; 2263 2233 } … … 2266 2236 if( !BG_FindPurchasableForWeapon( weapon ) ) 2267 2237 { 2268 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy this item\n\"" ));2238 trap_SendServerCommand( ent-g_entities, "print \"You can't buy this item\n\"" ); 2269 2239 return; 2270 2240 } … … 2273 2243 if( !BG_FindStagesForWeapon( weapon, g_humanStage.integer ) || !BG_WeaponIsAllowed( weapon ) ) 2274 2244 { 2275 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy this item\n\"" ));2245 trap_SendServerCommand( ent-g_entities, "print \"You can't buy this item\n\"" ); 2276 2246 return; 2277 2247 } … … 2323 2293 { 2324 2294 //shouldn't need a fancy dialog 2325 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy alien items\n\"" ));2295 trap_SendServerCommand( ent-g_entities, "print \"You can't buy alien items\n\"" ); 2326 2296 return; 2327 2297 } … … 2330 2300 if( !BG_FindPurchasableForUpgrade( upgrade ) ) 2331 2301 { 2332 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy this item\n\"" ));2302 trap_SendServerCommand( ent-g_entities, "print \"You can't buy this item\n\"" ); 2333 2303 return; 2334 2304 } … … 2337 2307 if( !BG_FindStagesForUpgrade( upgrade, g_humanStage.integer ) || !BG_UpgradeIsAllowed( upgrade ) ) 2338 2308 { 2339 trap_SendServerCommand( ent-g_entities, va( "print \"You can't buy this item\n\"" ));2309 trap_SendServerCommand( ent-g_entities, "print \"You can't buy this item\n\"" ); 2340 2310 return; 2341 2311 } … … 2372 2342 else 2373 2343 { 2374 trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ));2344 trap_SendServerCommand( ent-g_entities, "print \"Unknown item\n\"" ); 2375 2345 } 2376 2346 … … 2408 2378 if( !BG_FindPurchasableForWeapon( weapon ) ) 2409 2379 { 2410 trap_SendServerCommand( ent-g_entities, va( "print \"You can't sell this weapon\n\"" ));2380 trap_SendServerCommand( ent-g_entities, "print \"You can't sell this weapon\n\"" ); 2411 2381 return; 2412 2382 } … … 2439 2409 if( !BG_FindPurchasableForUpgrade( upgrade ) ) 2440 2410 { 2441 trap_SendServerCommand( ent-g_entities, va( "print \"You can't sell this item\n\"" ));2411 trap_SendServerCommand( ent-g_entities, "print \"You can't sell this item\n\"" ); 2442 2412 return; 2443 2413 } … … 2531 2501 } 2532 2502 else 2533 trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ));2503 trap_SendServerCommand( ent-g_entities, "print \"Unknown item\n\"" ); 2534 2504 2535 2505 //update ClientInfo … … 2644 2614 } 2645 2615 else 2646 trap_SendServerCommand( ent-g_entities, va( "print \"Cannot build this item\n\"" ));2616 trap_SendServerCommand( ent-g_entities, "print \"Cannot build this item\n\"" ); 2647 2617 } 2648 2618 … … 3124 3094 trap_Argv( 1, s, sizeof( s ) ); 3125 3095 3126 if( !s trlen( s ))3096 if( !s[ 0 ] ) 3127 3097 return; 3128 3098 … … 3168 3138 trap_Argv( 1, s, sizeof( s ) ); 3169 3139 3170 if( !s trlen( s ))3140 if( !s[ 0 ] ) 3171 3141 return; 3172 3142 … … 3219 3189 { 3220 3190 trap_SendServerCommand( ent-g_entities, va( "print \"[skipnotify]" 3221 " %s: usage \\%s [clientNum | partial name match]\n\"", cmd, cmd ) );3191 "usage: %s [clientNum | partial name match]\n\"", cmd ) ); 3222 3192 return; 3223 3193 } 3224 3194 3225 3195 Q_strncpyz( name, ConcatArgs( 1 ), sizeof( name ) ); 3226 matches = G_ClientNumbersFromString( name, pids, MAX_CLIENTS ); 3196 matches = G_ClientNumbersFromString( name, pids, MAX_CLIENTS ); 3227 3197 if( matches < 1 ) 3228 3198 { … … 3431 3401 if( *s == ' ' ) 3432 3402 { 3433 s++; 3403 s++; 3434 3404 if( *s != ' ' ) 3435 3405 { … … 3521 3491 3522 3492 void G_DecolorString( char *in, char *out ) 3523 { 3493 { 3524 3494 while( *in ) { 3525 if( *in == 27 || *in == '^') {3495 if( *in == 27 || Q_IsColorString( in ) ) { 3526 3496 in++; 3527 3497 if( *in ) … … 3584 3554 int count = 0; 3585 3555 3586 for( i =0; i < pcount; i++ )3556 for( i = 0; i < pcount; i++ ) 3587 3557 { 3588 3558 tmpent = &g_entities[ pids[ i ] ]; -
src/game/g_combat.c
r120 r124 40 40 { 41 41 if( !ent->client ) 42 return;43 44 // no scoring during pre-match warmup45 if( level.warmupTime )46 42 return; 47 43 … … 122 118 "MOD_ASPAWN", 123 119 "MOD_ATUBE", 124 "MOD_OVERMIND" 120 "MOD_OVERMIND", 121 122 "MOD_SLAP" 125 123 }; 126 124 … … 139 137 float totalDamage = 0.0f; 140 138 gentity_t *player; 139 qboolean tk = qfalse; 141 140 142 141 … … 148 147 149 148 // stop any following clients 150 for( i = 0; i < level.maxclients; i++ ) 151 { 152 if( level.clients[ i ].sess.sessionTeam == TEAM_SPECTATOR && 153 level.clients[ i ].sess.spectatorState == SPECTATOR_FOLLOW && 154 level.clients[ i ].sess.spectatorClient == self->client->ps.clientNum ) 155 { 156 if( !G_FollowNewClient( &g_entities[ i ], 1 ) ) 157 G_StopFollowing( &g_entities[ i ] ); 158 } 159 } 149 // r1: removed, annoying. 160 150 161 151 self->client->ps.pm_type = PM_DEAD; … … 167 157 168 158 if( attacker->client ) 159 { 169 160 killerName = attacker->client->pers.netname; 161 tk = ( attacker != self && attacker->client->ps.stats[ STAT_PTEAM ] 162 == self->client->ps.stats[ STAT_PTEAM ] ); 163 } 170 164 else 171 165 killerName = "<non-client>"; … … 188 182 obit = modNames[ meansOfDeath ]; 189 183 190 G_LogPrintf("Kill: %i %i %i: %s killed %sby %s\n",184 G_LogPrintf("Kill: %i %i %i: %s^7 killed %s^7 by %s\n", 191 185 killer, self->s.number, meansOfDeath, killerName, 192 186 self->client->pers.netname, obit ); … … 200 194 201 195 // broadcast the death event to everyone 202 ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); 203 ent->s.eventParm = meansOfDeath; 204 ent->s.otherEntityNum = self->s.number; 205 ent->s.otherEntityNum2 = killer; 206 ent->r.svFlags = SVF_BROADCAST; // send to everyone 196 if( !tk ) 197 { 198 ent = G_TempEntity( self->r.currentOrigin, EV_OBITUARY ); 199 ent->s.eventParm = meansOfDeath; 200 ent->s.otherEntityNum = self->s.number; 201 ent->s.otherEntityNum2 = killer; 202 ent->r.svFlags = SVF_BROADCAST; // send to everyone 203 } 204 else 205 { 206 // tjw: obviously this is a hack and belongs in the client, but 207 // this works as a temporary fix. 208 trap_SendServerCommand( -1, 209 va( "print \"%s^7 was killed by ^1TEAMMATE^7 %s\n\"", 210 self->client->pers.netname, attacker->client->pers.netname ) ); 211 trap_SendServerCommand( attacker - g_entities, 212 va( "cp \"You killed ^1TEAMMATE^7 %s\"", self->client->pers.netname ) ); 213 } 207 214 208 215 self->enemy = attacker; … … 396 403 397 404 // clear misc 398 memset( self->client->ps. misc, 0, sizeof( self->client->ps.misc) );405 memset( self->client->ps.powerups, 0, sizeof( self->client->ps.powerups ) ); 399 406 400 407 { … … 944 951 } 945 952 953 954 // don't attack buildable when noBaseAttack, you can't destroy them 955 if (g_noBaseAttack.integer && targ->s.eType == ET_BUILDABLE) 956 return; 957 958 946 959 client = targ->client; 947 960 … … 1017 1030 if( targ != attacker && OnSameTeam( targ, attacker ) ) 1018 1031 { 1019 if( !g_friendlyFire.integer ) 1032 if( g_dretchPunt.integer && 1033 targ->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_LEVEL0 ) 1034 { 1035 vec3_t dir, push; 1036 1037 VectorSubtract( targ->r.currentOrigin, attacker->r.currentOrigin, dir ); 1038 VectorNormalizeFast( dir ); 1039 VectorScale( dir, ( damage * 10.0f ), push ); 1040 push[2] = 64.0f; 1041 VectorAdd( targ->client->ps.velocity, push, targ->client->ps.velocity ); 1042 return; 1043 } 1044 else if( !g_friendlyFireMovementAttacks.integer && (mod == MOD_LEVEL4_CHARGE || mod == MOD_LEVEL3_POUNCE )){ 1045 // don't do friendly fire on movement attacks 1046 return; 1047 } 1048 else if( !g_friendlyFire.integer ) 1020 1049 { 1021 1050 if( !g_friendlyFireHumans.integer && … … 1037 1066 { 1038 1067 if( !g_friendlyBuildableFire.integer ) 1068 return; 1069 // don't do friendly fire on movement attacks 1070 if( !g_friendlyFireMovementAttacks.integer && 1071 (mod == MOD_LEVEL4_CHARGE || mod == MOD_LEVEL3_POUNCE ) ) 1039 1072 return; 1040 1073 } -
src/game/g_combat.c
r122 r124 1048 1048 else if( !g_friendlyFire.integer ) 1049 1049 { 1050 if( !g_friendlyFireHumans.integer 1051 &&targ->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )1050 if( !g_friendlyFireHumans.integer && 1051 targ->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 1052 1052 { 1053 1053 return; 1054 1054 } 1055 if( !g_friendlyFireAliens.integer 1056 &&targ->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )1055 if( !g_friendlyFireAliens.integer && 1056 targ->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 1057 1057 { 1058 1058 return; … … 1061 1061 } 1062 1062 1063 // If target is buildable on the same team as the attacking client1064 if( targ->s.eType == ET_BUILDABLE && attacker->client &&1065 targ->biteam == attacker->client->pers.teamSelection )1066 {1067 if( !g_friendlyBuildableFire.integer )1068 return;1063 // If target is buildable on the same team as the attacking client 1064 if( targ->s.eType == ET_BUILDABLE && attacker->client && 1065 targ->biteam == attacker->client->pers.teamSelection ) 1066 { 1067 if( !g_friendlyBuildableFire.integer ) 1068 return; 1069 1069 // don't do friendly fire on movement attacks 1070 if( !g_friendlyFireMovementAttacks.integer && (mod == MOD_LEVEL4_CHARGE || mod == MOD_LEVEL3_POUNCE )) 1070 if( !g_friendlyFireMovementAttacks.integer && 1071 (mod == MOD_LEVEL4_CHARGE || mod == MOD_LEVEL3_POUNCE ) ) 1071 1072 return; 1072 }1073 } 1073 1074 1074 1075 // check for godmode 1075 if ( targ->flags & FL_GODMODE )1076 if( targ->flags & FL_GODMODE ) 1076 1077 return; 1077 1078 } … … 1294 1295 points = damage * ( 1.0 - dist / radius ); 1295 1296 1296 if( CanDamage( ent, origin ) ) 1297 if( CanDamage( ent, origin ) && ent->client && 1298 ent->client->ps.stats[ STAT_PTEAM ] != team ) 1297 1299 { 1298 1300 VectorSubtract( ent->r.currentOrigin, origin, dir ); … … 1300 1302 // get knocked into the air more 1301 1303 dir[ 2 ] += 24; 1302 G_SelectiveDamage( ent, NULL, attacker, dir, origin, 1303 (int)points, DAMAGE_RADIUS|DAMAGE_NO_LOCDAMAGE, mod, team ); 1304 hitClient = qtrue; 1305 G_Damage( ent, NULL, attacker, dir, origin, 1306 (int)points, DAMAGE_RADIUS|DAMAGE_NO_LOCDAMAGE, mod ); 1304 1307 } 1305 1308 } … … 1371 1374 // get knocked into the air more 1372 1375 dir[ 2 ] += 24; 1376 hitClient = qtrue; 1373 1377 G_Damage( ent, NULL, attacker, dir, origin, 1374 1378 (int)points, DAMAGE_RADIUS|DAMAGE_NO_LOCDAMAGE, mod ); -
src/game/g_local.h
r120 r124 199 199 qboolean active; // for power repeater, but could be useful elsewhere 200 200 qboolean powered; // for human buildables 201 int buildpoints; // buildpoints remains to this generator 201 202 int builtBy; // clientNum of person that built this 202 203 gentity_t *dccNode; // controlling dcc … … 295 296 { 296 297 team_t sessionTeam; 298 pTeam_t restartTeam; //for !restart keepteams and !restart switchteams 297 299 int spectatorTime; // for determining next-in-line to play 298 300 spectatorState_t spectatorState; … … 356 358 qboolean denyBuild; 357 359 int adminLevel; 360 int floodTimer; 358 361 } clientPersistant_t; 359 362 … … 460 463 int unlaggedTime; 461 464 465 int jetpack_beat; // waiting time before turn on jetpack when power down 466 int jetpack_power; 462 467 }; 463 468 … … 532 537 int num_entities; // current number, <= MAX_GENTITIES 533 538 534 int warmupTime; // restart match at this time535 536 539 fileHandle_t logFile; 537 540 … … 557 560 int numPlayingClients; // connected, non-spectators 558 561 int sortedClients[MAX_CLIENTS]; // sorted by score 562 int numNewbies; // number of UnnamedPlayers who have been renamed this round. 559 563 560 564 int snd_fry; // sound index for standing in lava 561 562 int warmupModificationCount; // for detecting if g_warmup is changed563 565 564 566 // voting state … … 634 636 pTeam_t lastWin; 635 637 638 int suddenDeathABuildPoints; 639 int suddenDeathHBuildPoints; 640 qboolean suddenDeath; 636 641 timeWarning_t suddenDeathWarning; 637 642 timeWarning_t timelimitWarning; … … 654 659 655 660 char layout[ MAX_QPATH ]; 661 662 int warmupMessageTime; // last warmup message level.time 656 663 657 664 pTeam_t surrenderTeam; … … 694 701 void G_MatchOnePlayer( int *plist, int num, char *err, int len ); 695 702 int G_ClientNumbersFromString( char *s, int *plist, int max ); 703 void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ); 696 704 int G_SayArgc( void ); 697 705 qboolean G_SayArgv( int n, char *buffer, int bufferLength ); … … 702 710 void G_SanitiseName( char *in, char *out ); 703 711 void G_PrivateMessage( gentity_t *ent ); 712 void Cmd_Share_f( gentity_t *ent ); 713 void Cmd_Donate_f( gentity_t *ent ); 704 714 705 715 // … … 745 755 buildable_t spawn, vec3_t spawnOrigin ); 746 756 757 gentity_t* G_FindGenerator( buildableTeam_t team, vec3_t origin ); 747 758 buildable_t G_IsPowered( vec3_t origin ); 748 759 qboolean G_IsDCCBuilt( void ); … … 914 925 void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod ); 915 926 qboolean SpotWouldTelefrag( gentity_t *spot ); 927 char *G_NextNewbieName( gentity_t *ent ); 916 928 917 929 // … … 943 955 void G_RunThink( gentity_t *ent ); 944 956 void QDECL G_LogPrintf( const char *fmt, ... ); 957 void QDECL G_LogOnlyPrintf( const char *fmt, ... ); 945 958 void SendScoreboardMessageToAllClients( void ); 946 959 void QDECL G_Printf( const char *fmt, ... ); … … 952 965 void LogExit( const char *string ); 953 966 int G_TimeTilSuddenDeath( void ); 967 void G_Donate( gclient_t *client, short value ); 954 968 955 969 // … … 961 975 void ClientBegin( int clientNum ); 962 976 void ClientCommand( int clientNum ); 977 int ClientPingOverride( void ); 963 978 964 979 // … … 1099 1114 extern vmCvar_t g_dedicated; 1100 1115 extern vmCvar_t g_cheats; 1116 extern vmCvar_t g_version; 1101 1117 extern vmCvar_t g_maxclients; // allow this many total, including spectators 1102 1118 extern vmCvar_t g_maxGameClients; // allow this many active … … 1105 1121 extern vmCvar_t g_minNameChangePeriod; 1106 1122 extern vmCvar_t g_maxNameChanges; 1123 extern vmCvar_t g_newbieNumbering; 1124 extern vmCvar_t g_newbieNamePrefix; 1107 1125 1108 1126 extern vmCvar_t g_timelimit; 1109 1127 extern vmCvar_t g_suddenDeathTime; 1128 extern vmCvar_t g_suddenDeathMode; 1110 1129 extern vmCvar_t g_friendlyFire; 1111 1130 extern vmCvar_t g_friendlyFireHumans; 1112 1131 extern vmCvar_t g_friendlyFireAliens; 1113 1132 extern vmCvar_t g_friendlyBuildableFire; 1133 extern vmCvar_t g_friendlyFireMovementAttacks; 1114 1134 extern vmCvar_t g_password; 1115 1135 extern vmCvar_t g_needpass; … … 1128 1148 extern vmCvar_t g_warmup; 1129 1149 extern vmCvar_t g_doWarmup; 1150 extern vmCvar_t g_warmupMessage; 1130 1151 extern vmCvar_t g_blood; 1131 1152 extern vmCvar_t g_allowVote; … … 1139 1160 extern vmCvar_t pmove_msec; 1140 1161 extern vmCvar_t g_rankings; 1162 extern vmCvar_t g_allowShare; 1163 extern vmCvar_t g_allowDonate; 1164 extern vmCvar_t g_grangerMode; 1165 extern vmCvar_t g_repeaterOnReactor; 1166 extern vmCvar_t g_jetpackLimit; 1167 extern vmCvar_t g_autoDonate; 1141 1168 extern vmCvar_t g_enableDust; 1142 1169 extern vmCvar_t g_enableBreath; … … 1145 1172 extern vmCvar_t g_humanBuildPoints; 1146 1173 extern vmCvar_t g_alienBuildPoints; 1174 extern vmCvar_t g_reactorBuildPoints; 1175 extern vmCvar_t g_repeaterBuildPoints; 1176 extern vmCvar_t g_overmindBuildPoints; 1177 extern vmCvar_t g_eggBuildPoints; 1178 extern vmCvar_t g_zoneBuildPoints; 1147 1179 extern vmCvar_t g_humanStage; 1148 1180 extern vmCvar_t g_humanKills; … … 1169 1201 extern vmCvar_t g_initialMapRotation; 1170 1202 extern vmCvar_t g_chatTeamPrefix; 1203 extern vmCvar_t g_specsSeeTeamchat; 1171 1204 1172 1205 extern vmCvar_t g_shove; … … 1182 1215 extern vmCvar_t g_adminNameProtect; 1183 1216 extern vmCvar_t g_adminTempBan; 1184 1217 extern vmCvar_t g_minLevelToSpecMM1; 1218 extern vmCvar_t g_adminWarnMessage; 1185 1219 extern vmCvar_t g_privateMessages; 1220 extern vmCvar_t g_publicSayadmins; 1221 extern vmCvar_t g_allowActions; 1222 extern vmCvar_t g_actionPrefix; 1223 extern vmCvar_t g_floodProtection; 1224 extern vmCvar_t g_autoRegister; 1225 1226 extern vmCvar_t g_slapKnockback; 1227 extern vmCvar_t g_slapDamage; 1228 1229 extern vmCvar_t g_hiddenClients; 1230 1231 extern vmCvar_t g_dretchPunt; 1232 1233 extern vmCvar_t g_freeFunds; 1234 extern vmCvar_t g_fastBuild; 1235 extern vmCvar_t g_noBaseAttack; 1236 extern vmCvar_t g_cheatAdminLevel; // an admin above or equal this level can use cheat, disable if 0 1237 1238 extern vmCvar_t g_playerVotePercent; 1239 extern vmCvar_t g_globalVotePercent; 1186 1240 1187 1241 void trap_Printf( const char *fmt ); … … 1233 1287 void trap_SnapVector( float *v ); 1234 1288 void trap_SendGameStat( const char *data ); 1289 1290 void do_health( gentity_t *ent, int quantity ); -
src/game/g_local.h
r123 r124 346 346 347 347 // used to save persistant[] values while in SPECTATOR_FOLLOW mode 348 int savedScore;349 348 int savedCredit; 350 349 -
src/game/g_main.c
r120 r124 23 23 24 24 #include "g_local.h" 25 26 #include "../qcommon/q_shared.h" 25 27 26 28 level_locals_t level; … … 40 42 gclient_t g_clients[ MAX_CLIENTS ]; 41 43 44 vmCvar_t g_version; 42 45 vmCvar_t g_fraglimit; 43 46 vmCvar_t g_timelimit; 44 47 vmCvar_t g_suddenDeathTime; 48 vmCvar_t g_suddenDeathMode; 45 49 vmCvar_t g_capturelimit; 46 50 vmCvar_t g_friendlyFire; … … 48 52 vmCvar_t g_friendlyFireHumans; 49 53 vmCvar_t g_friendlyBuildableFire; 54 vmCvar_t g_friendlyFireMovementAttacks; 50 55 vmCvar_t g_password; 51 56 vmCvar_t g_needpass; … … 68 73 vmCvar_t g_warmup; 69 74 vmCvar_t g_doWarmup; 75 vmCvar_t g_warmupMessage; 70 76 vmCvar_t g_restarted; 71 77 vmCvar_t g_logFile; … … 82 88 vmCvar_t g_smoothClients; 83 89 vmCvar_t pmove_fixed; 90 vmCvar_t g_rankings; 84 91 vmCvar_t pmove_msec; 85 vmCvar_t g_rankings;86 92 vmCvar_t g_listEntity; 87 93 vmCvar_t g_minCommandPeriod; 88 94 vmCvar_t g_minNameChangePeriod; 89 95 vmCvar_t g_maxNameChanges; 90 96 vmCvar_t g_newbieNumbering; 97 vmCvar_t g_newbieNamePrefix; 98 99 vmCvar_t g_reactorBuildPoints; 100 vmCvar_t g_repeaterBuildPoints; 101 vmCvar_t g_overmindBuildPoints; 102 vmCvar_t g_eggBuildPoints; 103 vmCvar_t g_zoneBuildPoints; 91 104 vmCvar_t g_humanBuildPoints; 92 105 vmCvar_t g_alienBuildPoints; … … 119 132 vmCvar_t g_mapConfigs; 120 133 vmCvar_t g_chatTeamPrefix; 134 vmCvar_t g_specsSeeTeamchat; 121 135 122 136 vmCvar_t g_layouts; … … 127 141 vmCvar_t g_adminParseSay; 128 142 vmCvar_t g_adminNameProtect; 143 vmCvar_t g_autoRegister; 129 144 vmCvar_t g_adminTempBan; 145 vmCvar_t g_minLevelToSpecMM1; 146 vmCvar_t g_adminWarnMessage; 130 147 131 148 vmCvar_t g_privateMessages; 149 vmCvar_t g_publicSayadmins; 150 vmCvar_t g_floodProtection; 151 152 vmCvar_t g_slapKnockback; 153 vmCvar_t g_slapDamage; 132 154 133 155 vmCvar_t g_tag; 156 157 vmCvar_t g_allowActions; 158 vmCvar_t g_actionPrefix; 159 160 vmCvar_t g_hiddenClients; 161 162 vmCvar_t g_dretchPunt; 163 164 vmCvar_t g_allowShare; 165 vmCvar_t g_allowDonate; 166 vmCvar_t g_autoDonate; 167 168 169 vmCvar_t g_freeFunds; 170 vmCvar_t g_fastBuild; 171 vmCvar_t g_noBaseAttack; 172 vmCvar_t g_cheatAdminLevel; // an admin above or equal this level can use cheat, disable if 0 173 174 vmCvar_t g_grangerMode; 175 vmCvar_t g_repeaterOnReactor; 176 vmCvar_t g_jetpackLimit; 177 178 vmCvar_t g_playerVotePercent; 179 vmCvar_t g_globalVotePercent; 134 180 135 181 static cvarTable_t gameCvarTable[ ] = … … 148 194 // latched vars 149 195 150 { &g_maxclients, "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse }, 196 { &g_version, "g_version", FULL_VERSION, CVAR_SERVERINFO | CVAR_ROM, 0, qfalse }, 197 198 { &g_maxclients, "sv_maxclients", "12", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse }, 199 { &g_maxGameClients, "g_maxGameClients", "0", CVAR_SERVERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qfalse }, 151 200 152 201 // change anytime vars … … 155 204 { &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 156 205 { &g_suddenDeathTime, "g_suddenDeathTime", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 206 { &g_suddenDeathMode, "g_suddenDeathMode", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 207 { &g_playerVotePercent, "g_playerVotePercent", "55", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 208 { &g_globalVotePercent, "g_globalVotePercent", "65", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 157 209 158 210 { &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse }, 159 211 160 { &g_friendlyFire, "g_friendlyFire", "0", CVAR_ARCHIVE, 0, qtrue }, 161 { &g_friendlyFireAliens, "g_friendlyFireAliens", "0", CVAR_ARCHIVE, 0, qtrue }, 162 { &g_friendlyFireHumans, "g_friendlyFireHumans", "0", CVAR_ARCHIVE, 0, qtrue }, 163 { &g_friendlyBuildableFire, "g_friendlyBuildableFire", "0", CVAR_ARCHIVE, 0, qtrue }, 212 { &g_friendlyFire, "g_friendlyFire", "1", CVAR_ARCHIVE, 0, qtrue }, 213 { &g_friendlyFireAliens, "g_friendlyFireAliens", "1", CVAR_ARCHIVE, 0, qtrue }, 214 { &g_friendlyFireHumans, "g_friendlyFireHumans", "1", CVAR_ARCHIVE, 0, qtrue }, 215 { &g_friendlyBuildableFire, "g_friendlyBuildableFire", "1", CVAR_ARCHIVE, 0, qtrue }, 216 { &g_friendlyFireMovementAttacks, "g_friendlyFireMovementAttacks", "1", CVAR_ARCHIVE, 0, qtrue }, 164 217 165 218 { &g_teamAutoJoin, "g_teamAutoJoin", "0", CVAR_ARCHIVE }, 166 { &g_teamForceBalance, "g_teamForceBalance", " 0", CVAR_ARCHIVE },219 { &g_teamForceBalance, "g_teamForceBalance", "1", CVAR_ARCHIVE }, 167 220 168 221 { &g_warmup, "g_warmup", "20", CVAR_ARCHIVE, 0, qtrue }, 169 { &g_doWarmup, "g_doWarmup", "0", 0, 0, qtrue }, 222 { &g_doWarmup, "g_doWarmup", "1", CVAR_ARCHIVE, 0, qtrue }, 223 { &g_warmupMessage, "g_warmupMessage", "", CVAR_ARCHIVE, 0, qtrue }, 170 224 { &g_logFile, "g_logFile", "games.log", CVAR_ARCHIVE, 0, qfalse }, 171 225 { &g_logFileSync, "g_logFileSync", "0", CVAR_ARCHIVE, 0, qfalse }, … … 197 251 198 252 { &g_allowVote, "g_allowVote", "1", CVAR_ARCHIVE, 0, qfalse }, 199 { &g_voteLimit, "g_voteLimit", " 5", CVAR_ARCHIVE, 0, qfalse },253 { &g_voteLimit, "g_voteLimit", "2", CVAR_ARCHIVE, 0, qfalse }, 200 254 { &g_listEntity, "g_listEntity", "0", 0, 0, qfalse }, 201 255 { &g_minCommandPeriod, "g_minCommandPeriod", "500", 0, 0, qfalse}, 202 256 { &g_minNameChangePeriod, "g_minNameChangePeriod", "5", 0, 0, qfalse}, 203 257 { &g_maxNameChanges, "g_maxNameChanges", "5", 0, 0, qfalse}, 258 { &g_newbieNumbering, "g_newbieNumbering", "0", CVAR_ARCHIVE, 0, qfalse}, 259 { &g_newbieNamePrefix, "g_newbieNamePrefix", "Newbie#", CVAR_ARCHIVE, 0, qfalse}, 204 260 205 261 { &g_smoothClients, "g_smoothClients", "1", 0, 0, qfalse}, … … 209 265 { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse }, 210 266 { &g_alienBuildPoints, "g_alienBuildPoints", DEFAULT_ALIEN_BUILDPOINTS, 0, 0, qfalse }, 267 { &g_zoneBuildPoints, "g_zoneBuildPoints", "0", 0, 0, qfalse }, 268 { &g_reactorBuildPoints, "g_reactorBuildPoints", "100", 0, 0, qfalse }, 269 { &g_repeaterBuildPoints, "g_repeaterBuildPoints", "50", 0, 0, qfalse }, 270 { &g_overmindBuildPoints, "g_overmindBuildPoints", "100", 0, 0, qfalse }, 271 { &g_eggBuildPoints, "g_eggBuildPoints", "50", 0, 0, qfalse }, 211 272 { &g_humanStage, "g_humanStage", "0", 0, 0, qfalse }, 212 273 { &g_humanKills, "g_humanKills", "0", 0, 0, qfalse }, … … 219 280 { &g_alienStage2Threshold, "g_alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, 0, 0, qfalse }, 220 281 { &g_alienStage3Threshold, "g_alienStage3Threshold", DEFAULT_ALIEN_STAGE3_THRESH, 0, 0, qfalse }, 221 222 { &g_unlagged, "g_unlagged", "1 ", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse },282 283 { &g_unlagged, "g_unlagged", "1000", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, 223 284 224 285 { &g_disabledEquipment, "g_disabledEquipment", "", CVAR_ROM, 0, qfalse }, … … 226 287 { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse }, 227 288 228 { &g_chatTeamPrefix, "g_chatTeamPrefix", "0", CVAR_ARCHIVE, 0, qfalse }, 229 230 { &g_markDeconstruct, "g_markDeconstruct", "1", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, 289 { &g_chatTeamPrefix, "g_chatTeamPrefix", "1", CVAR_ARCHIVE, 0, qfalse }, 290 { &g_specsSeeTeamchat, "g_specsSeeTeamchat", "1", CVAR_ARCHIVE, 0, qfalse }, 291 292 { &g_markDeconstruct, "g_markDeconstruct", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, 231 293 232 294 { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, … … 235 297 { &g_initialMapRotation, "g_initialMapRotation", "", CVAR_ARCHIVE, 0, qfalse }, 236 298 { &g_shove, "g_shove", "0.0", CVAR_ARCHIVE, 0, qfalse }, 237 { &g_mapConfigs, "g_mapConfigs", "", CVAR_ARCHIVE, 0, qfalse }, 299 300 { &g_mapConfigs, "g_mapConfigs", "mapconfigs", CVAR_ARCHIVE, 0, qfalse }, 238 301 { NULL, "g_mapConfigsLoaded", "0", CVAR_ROM, 0, qfalse }, 239 302 … … 246 309 { &g_adminNameProtect, "g_adminNameProtect", "1", CVAR_ARCHIVE, 0, qfalse }, 247 310 { &g_adminTempBan, "g_adminTempBan", "120", CVAR_ARCHIVE, 0, qfalse }, 248 311 { &g_adminWarnMessage, "g_adminWarnMessage", "You have been warned by an administrator.\n Cease imeediately or face admin action!\n", CVAR_ARCHIVE, 0, qfalse }, 312 { &g_autoRegister, "g_autoRegister", "0", CVAR_ARCHIVE, 0, qfalse }, 313 249 314 { &g_privateMessages, "g_privateMessages", "1", CVAR_ARCHIVE, 0, qfalse }, 315 { &g_publicSayadmins, "g_publicSayadmins", "1", CVAR_ARCHIVE, 0, qfalse }, 316 { &g_minLevelToSpecMM1, "g_minLevelToSpecMM1", "0", CVAR_ARCHIVE, 0, qfalse }, 317 { &g_floodProtection, "g_floodProtection", "150", CVAR_ARCHIVE, 0, qfalse }, 318 319 { &g_slapKnockback, "g_slapKnockback", "200", CVAR_ARCHIVE, 0, qfalse}, 320 { &g_slapDamage, "g_slapDamage", "5", CVAR_ARCHIVE, 0, qfalse}, 250 321 251 322 { &g_tag, "g_tag", "main", CVAR_INIT, 0, qfalse }, 252 323 253 { &g_rankings, "g_rankings", "0", 0, 0, qfalse} 324 { &g_hiddenClients, "g_hiddenClients", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, 0, qfalse }, 325 326 { &g_dretchPunt, "g_dretchPunt", "1", CVAR_ARCHIVE, 0, qfalse }, 327 328 { &g_rankings, "g_rankings", "0", 0, 0, qfalse}, 329 330 { &g_freeFunds, "g_freeFunds", "0", 0, 0, qfalse}, 331 { &g_fastBuild, "g_fastBuild", "0", 0, 0, qfalse}, 332 { &g_noBaseAttack, "g_noBaseAttack", "0", 0, 0, qfalse}, 333 { &g_cheatAdminLevel, "g_cheatAdminLevel", "0", CVAR_SERVERINFO, 0, qfalse}, 334 335 { &g_allowDonate, "g_allowDonate", "1", CVAR_ARCHIVE, 0, qfalse}, 336 { &g_autoDonate, "g_autoDonate", "1", CVAR_ARCHIVE, 0, qfalse}, 337 { &g_allowShare, "g_allowShare", "1", CVAR_ARCHIVE, 0, qfalse}, 338 { &g_grangerMode, "g_grangerMode", "0", 0, 0, qfalse }, 339 { &g_repeaterOnReactor, "g_repeaterOnReactor", "1", 0, 0, qfalse }, 340 { &g_jetpackLimit, "g_jetpackLimit", "40", 0, 0, qfalse }, 341 { &g_allowActions, "g_allowActions", "1", CVAR_ARCHIVE, 0, qfalse }, 342 { &g_actionPrefix, "g_actionPrefix", "***", CVAR_ARCHIVE, 0, qfalse } 254 343 }; 255 344 … … 316 405 case GAME_CONSOLE_COMMAND: 317 406 return ConsoleCommand( ); 407 408 case GAME_PING_OVERRIDE: 409 return ClientPingOverride( ); 318 410 } 319 411 … … 443 535 if( remapped ) 444 536 G_RemapTeamShaders( ); 445 446 // check some things447 level.warmupModificationCount = g_warmup.modificationCount;448 537 } 449 538 … … 553 642 { 554 643 char serverinfo[ MAX_INFO_STRING ]; 644 qtime_t qt; 645 int t; 646 555 647 556 648 trap_GetServerinfo( serverinfo, sizeof( serverinfo ) ); … … 558 650 G_LogPrintf( "------------------------------------------------------------\n" ); 559 651 G_LogPrintf( "InitGame: %s\n", serverinfo ); 652 653 t = trap_RealTime( &qt ); 654 G_LogPrintf("RealTime: %04i/%02i/%02i %02i:%02i:%02i\n", 655 qt.tm_year+1900, qt.tm_mon+1, qt.tm_mday, 656 qt.tm_hour, qt.tm_min, qt.tm_sec ); 657 560 658 } 561 659 } … … 629 727 trap_Cvar_Set( "g_alienKills", 0 ); 630 728 trap_Cvar_Set( "g_humanKills", 0 ); 729 730 731 //reset training var 732 trap_Cvar_Set( "g_freeFunds", 0); 733 trap_Cvar_Set( "g_fastBuild", 0); 734 trap_Cvar_Set( "g_noBaseAttack", 0); 735 trap_Cvar_Set( "g_cheatAdminLevel", 0); 631 736 632 737 G_Printf( "-----------------------------------\n" ); … … 1045 1150 int localHTP = g_humanBuildPoints.integer, 1046 1151 localATP = g_alienBuildPoints.integer; 1047 1048 if( g_suddenDeathTime.integer && !level.warmupTime ) 1152 int buildPoints; 1153 1154 if( g_suddenDeathTime.integer ) 1049 1155 { 1050 1156 if( G_TimeTilSuddenDeath( ) <= 0 ) 1051 1157 { 1052 localHTP = 0; 1053 localATP = 0; 1054 1055 //warn about sudden death 1158 //begin sudden death 1056 1159 if( level.suddenDeathWarning < TW_PASSED ) 1057 1160 { 1058 1161 trap_SendServerCommand( -1, "cp \"Sudden Death!\"" ); 1162 localHTP = 0; 1163 localATP = 0; 1164 1165 if( g_suddenDeathMode.integer == SDMODE_SELECTIVE ) { 1166 for( i = 1, ent = g_entities + i; i < level.num_entities; i++, ent++ ) 1167 { 1168 if( ent->s.eType != ET_BUILDABLE ) 1169 continue; 1170 1171 if( BG_FindReplaceableTestForBuildable( ent->s.modelindex ) ) 1172 { 1173 int t = BG_FindTeamForBuildable( ent->s.modelindex ); 1174 1175 if( t == BIT_HUMANS ) 1176 localHTP += BG_FindBuildPointsForBuildable( ent->s.modelindex ); 1177 else if( t == BIT_ALIENS ) 1178 localATP += BG_FindBuildPointsForBuildable( ent->s.modelindex ); 1179 } 1180 } 1181 } 1182 level.suddenDeathHBuildPoints = localHTP; 1183 level.suddenDeathABuildPoints = localATP; 1184 level.suddenDeath = qtrue; 1185 1059 1186 level.suddenDeathWarning = TW_PASSED; 1060 1187 } … … 1071 1198 } 1072 1199 } 1200 1201 if( level.suddenDeath ) 1202 { 1203 localHTP = level.suddenDeathHBuildPoints; 1204 localATP = level.suddenDeathABuildPoints; 1205 } 1073 1206 else 1074 1207 { … … 1083 1216 level.overmindPresent = qfalse; 1084 1217 1218 for( i = 1, ent = g_entities + i ; i < level.num_entities && g_zoneBuildPoints.integer ; i++, ent++ ) 1219 { 1220 buildable = ent->s.modelindex; 1221 1222 if(buildable == BA_H_REACTOR) 1223 ent->buildpoints = g_reactorBuildPoints.integer; 1224 else if(buildable == BA_H_REPEATER) 1225 ent->buildpoints = g_repeaterBuildPoints.integer; 1226 else if(buildable == BA_A_OVERMIND) 1227 ent->buildpoints = g_overmindBuildPoints.integer; 1228 else if(buildable == BA_A_SPAWN) 1229 ent->buildpoints = g_eggBuildPoints.integer; 1230 } 1231 1085 1232 for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ ) 1086 1233 { … … 1101 1248 level.overmindPresent = qtrue; 1102 1249 1103 if( BG_FindTeamForBuildable( buildable ) == BIT_HUMANS)1250 if( !level.suddenDeath || BG_FindReplaceableTestForBuildable( buildable ) ) 1104 1251 { 1105 level.humanBuildPoints -= BG_FindBuildPointsForBuildable( buildable ); 1106 1107 if( ent->powered ) 1108 level.humanBuildPointsPowered -= BG_FindBuildPointsForBuildable( buildable ); 1109 } 1110 else 1111 { 1112 level.alienBuildPoints -= BG_FindBuildPointsForBuildable( buildable ); 1252 buildPoints = BG_FindBuildPointsForBuildable( buildable ); 1253 1254 if(g_zoneBuildPoints.integer && ent->parentNode && ent->s.modelindex != BA_A_SPAWN) 1255 { 1256 if(ent->parentNode->buildpoints >= buildPoints) 1257 ent->parentNode->buildpoints -= buildPoints; 1258 else 1259 ent->powered = 0; 1260 } 1261 1262 if( BG_FindTeamForBuildable( buildable ) == BIT_HUMANS ) 1263 { 1264 level.humanBuildPoints -= buildPoints; 1265 if( ent->powered ) 1266 level.humanBuildPointsPowered -= buildPoints; 1267 } 1268 else 1269 { 1270 level.alienBuildPoints -= buildPoints; 1271 } 1113 1272 } 1114 1273 } … … 1416 1575 1417 1576 // clean up powerup info 1418 memset( ent->client->ps. misc, 0, sizeof( ent->client->ps.misc) );1577 memset( ent->client->ps.powerups, 0, sizeof( ent->client->ps.powerups ) ); 1419 1578 1420 1579 ent->client->ps.eFlags = 0; … … 1482 1641 G_ClearVotes( ); 1483 1642 1643 // reset warmup messages 1644 level.warmupMessageTime = 0; 1645 1484 1646 FindIntermissionPoint( ); 1485 1647 … … 1520 1682 G_AdvanceMapRotation( ); 1521 1683 else 1522 trap_SendConsoleCommand( EXEC_APPEND, " map_restart\n" );1684 trap_SendConsoleCommand( EXEC_APPEND, "restartmap\n" ); 1523 1685 1524 1686 level.restarted = qtrue; … … 1577 1739 if( g_dedicated.integer ) 1578 1740 G_Printf( "%s", string + 7 ); 1741 1742 if( !level.logFile ) 1743 return; 1744 1745 trap_FS_Write( string, strlen( string ), level.logFile ); 1746 } 1747 1748 /* 1749 ================= 1750 G_LogOnlyPrintf 1751 1752 Print to the logfile only (not console) with a time stamp if it is open 1753 ================= 1754 */ 1755 void QDECL G_LogOnlyPrintf( const char *fmt, ... ) 1756 { 1757 va_list argptr; 1758 char string[ 1024 ]; 1759 int min, tens, sec; 1760 1761 sec = level.time / 1000; 1762 1763 min = sec / 60; 1764 sec -= min * 60; 1765 tens = sec / 10; 1766 sec -= tens * 10; 1767 1768 Com_sprintf( string, sizeof( string ), "%3i:%i%i ", min, tens, sec ); 1769 1770 va_start( argptr, fmt ); 1771 vsprintf( string +7 , fmt,argptr ); 1772 va_end( argptr ); 1579 1773 1580 1774 if( !level.logFile ) … … 1869 2063 } 1870 2064 1871 if( g_timelimit.integer && !level.warmupTime)2065 if( g_timelimit.integer ) 1872 2066 { 1873 2067 if( level.time - level.startTime >= g_timelimit.integer * 60000 ) … … 2027 2221 void CheckVote( void ) 2028 2222 { 2223 double percent; 2224 2029 2225 if( level.voteExecuteTime && level.voteExecuteTime < level.time ) 2030 2226 { … … 2032 2228 2033 2229 trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) ); 2034 if( !Q_stricmp( level.voteString, " map_restart" ) ||2230 if( !Q_stricmp( level.voteString, "restartmap" ) || 2035 2231 !Q_stricmpn( level.voteString, "map", 3 ) ) 2036 2232 { … … 2038 2234 } 2039 2235 } 2236 2237 if (strstr(level.voteString, "mute") || strstr(level.voteString, "unmute") || strstr(level.voteString, "kick")) 2238 percent = g_playerVotePercent.integer; 2239 else 2240 percent = g_globalVotePercent.integer; 2040 2241 2041 2242 if( !level.voteTime ) 2042 2243 return; 2043 2244 2245 // warning: not sure about > or >= 2246 2044 2247 if( level.time - level.voteTime >= VOTE_TIME ) 2045 2248 { 2046 if( level.voteYes > level.voteNo)2249 if( level.voteYes >= rint ( (level.numVotingClients * percent) / 100 ) ) 2047 2250 { 2048 2251 // execute the command, then remove the vote … … 2058 2261 else 2059 2262 { 2060 if( level.voteYes > level.numVotingClients / 2)2263 if( level.voteYes >= rint ( (level.numVotingClients * percent) / 100 ) ) 2061 2264 { 2062 2265 // execute the command, then remove the vote … … 2064 2267 level.voteExecuteTime = level.time + 3000; 2065 2268 } 2066 else if( level.voteNo > = ceil( (float)level.numVotingClients / 2) )2269 else if( level.voteNo > rint ( (level.numVotingClients * (100 - percent) ) / 100 ) ) 2067 2270 { 2068 2271 // same behavior as a timeout … … 2078 2281 level.voteTime = 0; 2079 2282 trap_SetConfigstring( CS_VOTE_TIME, "" ); 2283 } 2284 2285 2286 /* 2287 ================== 2288 CheckWarmup 2289 ================== 2290 */ 2291 void CheckWarmup( void ) 2292 { 2293 if( g_doWarmup.integer && 2294 level.time - level.startTime < g_warmup.integer * 1000 && 2295 level.time - level.warmupMessageTime >= WARMUPMESSAGE_TIME ) 2296 { 2297 int secs; 2298 2299 level.warmupMessageTime = level.time; 2300 secs = g_warmup.integer - ((level.time - level.startTime) / 1000) - 1; 2301 2302 if( secs > 0 ) { 2303 char *color = ""; 2304 2305 if( secs > 9 ) 2306 color = "^2"; 2307 else if( secs > 3 ) 2308 color = "^3"; 2309 else if( secs > 0 ) 2310 color = "^1"; 2311 2312 trap_SendConsoleCommand( EXEC_APPEND, va( "cp ^7%s%s%d\n", g_warmupMessage.string, color, secs ) ); 2313 } else if( ! secs ) { 2314 trap_SendConsoleCommand( EXEC_APPEND, va( "cp ^2Fight!\n" ) ); 2315 } 2316 2317 } 2080 2318 } 2081 2319 … … 2364 2602 CheckVote( ); 2365 2603 2604 // cancel if there's a warmup message to print 2605 CheckWarmup( ); 2606 2366 2607 // check team votes 2367 2608 CheckTeamVote( PTE_HUMANS ); … … 2380 2621 } 2381 2622 2623 /* 2624 ================= 2625 G_Donate 2626 2627 Alms for the poor 2628 ================= 2629 */ 2630 2631 int G_Donate_money_cmp(const void *a, const void *b) 2632 { 2633 const int *ia = a, *ib = b; 2634 if(level.clients[*ia].ps.persistant[PERS_CREDIT] < level.clients[*ib].ps.persistant[PERS_CREDIT]) 2635 return -1; 2636 else if(level.clients[*ia].ps.persistant[PERS_CREDIT] > level.clients[*ib].ps.persistant[PERS_CREDIT]) 2637 return 1; 2638 else 2639 return 0; 2640 } 2641 2642 void G_Donate(gclient_t *client, short value) 2643 { 2644 int amounts[MAX_CLIENTS]; 2645 int minorder[MAX_CLIENTS]; 2646 int div = 0; 2647 int min_order_size; 2648 short credits; 2649 short gain; 2650 short bonus; 2651 int donated; 2652 int i; 2653 int i_cl = 0; 2654 int max; 2655 char type[10]; 2656 2657 if(value > client->ps.persistant[PERS_CREDIT]) 2658 value = client->ps.persistant[PERS_CREDIT]; 2659 2660 if(value <= 0) 2661 return; 2662 2663 if(client->pers.teamSelection == PTE_ALIENS) 2664 { 2665 max = ALIEN_MAX_KILLS; 2666 Q_strncpyz(type, "evo(s)", 10); 2667 } 2668 else if(client->pers.teamSelection == PTE_HUMANS) 2669 { 2670 max = HUMAN_MAX_CREDITS; 2671 Q_strncpyz(type, "credit(s)", 10); 2672 } 2673 else 2674 return; 2675 2676 credits = value; 2677 2678 for(i = 0; i < level.maxclients; i++) 2679 { 2680 if(&level.clients[i] == client) 2681 { 2682 i_cl = i; 2683 continue; 2684 } 2685 if( level.clients[i].pers.connected != CON_CONNECTED || 2686 level.clients[i].pers.teamSelection != client->pers.teamSelection || 2687 level.clients[i].ps.persistant[ PERS_CREDIT ] >= max 2688 ) 2689 amounts[i] = -1; 2690 else 2691 { 2692 amounts[i] = 0; 2693 minorder[div] = i; 2694 div++; 2695 } 2696 } 2697 2698 if(div < 1) 2699 return; 2700 2701 min_order_size = div; 2702 qsort(minorder, min_order_size, sizeof(int), G_Donate_money_cmp); 2703 2704 donated = qfalse; 2705 while(credits && div) 2706 { 2707 bonus = credits / div; 2708 2709 if(credits % div != 0) 2710 bonus++; 2711 2712 for( i = 0; i < min_order_size; i++) 2713 { 2714 if( 2715 level.clients[minorder[i]].ps.persistant[ PERS_CREDIT ] + amounts[minorder[i]] < max 2716 ) 2717 { 2718 gain = bonus; 2719 if(level.clients[minorder[i]].ps.persistant[PERS_CREDIT] + amounts[minorder[i]] + gain > max) 2720 { 2721 gain = max - (level.clients[minorder[i]].ps.persistant[PERS_CREDIT] + amounts[minorder[i]]); 2722 div--; 2723 } 2724 if(gain > credits) 2725 gain = credits; 2726 amounts[minorder[i]] += gain; 2727 credits -= gain; 2728 } 2729 } 2730 donated = qtrue; 2731 } 2732 2733 for(i = 0; i < min_order_size; i++) 2734 { 2735 if(amounts[minorder[i]] != -1 && amounts[minorder[i]] > 0) 2736 { 2737 level.clients[minorder[i]].ps.persistant[PERS_CREDIT] += amounts[minorder[i]]; 2738 2739 trap_SendServerCommand( minorder[i], 2740 va( "print \"%s^7 donated %d %s to you, don't forget to say 'thank you'!\n\"", 2741 client->pers.netname, amounts[minorder[i]], type ) ); 2742 } 2743 } 2744 2745 if(donated) 2746 { 2747 client->ps.persistant[PERS_CREDIT] -= value-credits; 2748 trap_SendServerCommand( i_cl, 2749 va( "print \"Donated %d %s to the cause.\n\"", 2750 value-credits, type ) ); 2751 } 2752 } 2753 -
src/game/g_main.c
r122 r124 287 287 { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse }, 288 288 289 { &g_chatTeamPrefix, "g_chatTeamPrefix", "1", CVAR_ARCHIVE },290 { &g_specsSeeTeamchat, "g_specsSeeTeamchat", "1", CVAR_ARCHIVE },289 { &g_chatTeamPrefix, "g_chatTeamPrefix", "1", CVAR_ARCHIVE, 0, qfalse }, 290 { &g_specsSeeTeamchat, "g_specsSeeTeamchat", "1", CVAR_ARCHIVE, 0, qfalse }, 291 291 292 292 { &g_markDeconstruct, "g_markDeconstruct", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, … … 592 592 trap_SendConsoleCommand( EXEC_APPEND, 593 593 va( "exec \"%s/default.cfg\"\n", g_mapConfigs.string ) ); 594 594 595 595 trap_SendConsoleCommand( EXEC_APPEND, 596 596 va( "exec \"%s/%s.cfg\"\n", g_mapConfigs.string, mapname ) ); … … 671 671 trap_Cvar_Set( "g_mapConfigsLoaded", "0" ); 672 672 673 if ( g_admin.string[ 0 ] ) { 674 G_admin_readconfig( NULL, 0 ); 675 } 673 G_admin_readconfig( NULL, 0 ); 676 674 677 675 // initialize all entities for this game … … 847 845 if( ca->ps.persistant[ PERS_SCORE ] > cb->ps.persistant[ PERS_SCORE ] ) 848 846 return -1; 849 elseif( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] )847 if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] ) 850 848 return 1; 851 else 852 return 0; 849 return 0; 853 850 } 854 851 … … 911 908 return clientNum; 912 909 } 913 else 914 return -1; 910 return -1; 915 911 } 916 912 … … 1440 1436 1441 1437 level.numConnectedClients = 0; 1442 level.numNonSpectatorClients = 0;1443 1438 level.numPlayingClients = 0; 1444 1439 level.numVotingClients = 0; // don't count bots … … 1464 1459 { 1465 1460 level.numPlayingClients++; 1466 if( level.clients[ i ].sess.sessionTeam != TEAM_SPECTATOR )1467 level.numNonSpectatorClients++;1468 1469 1461 if( level.clients[ i ].pers.teamSelection == PTE_ALIENS ) 1470 1462 { … … 1482 1474 } 1483 1475 } 1476 level.numNonSpectatorClients = level.numLiveAlienClients + 1477 level.numLiveHumanClients; 1484 1478 level.numteamVotingClients[ 0 ] = level.numHumanClients; 1485 1479 level.numteamVotingClients[ 1 ] = level.numAlienClients; … … 2586 2580 } 2587 2581 2588 // save position information for all active clients 2582 // save position information for all active clients 2589 2583 G_UnlaggedStore( ); 2590 2584 -
src/game/g_svcmds.c
r120 r124 541 541 Q_strncpyz( layouts, s, sizeof( layouts ) ); 542 542 trap_Cvar_Set( "g_layouts", layouts ); 543 trap_SendConsoleCommand( EXEC_APPEND, " map_restart\n" );543 trap_SendConsoleCommand( EXEC_APPEND, "restartmap\n" ); 544 544 level.restarted = qtrue; 545 545 } … … 732 732 return qtrue; 733 733 } 734 734 else if( !Q_stricmp( cmd, "a" ) || !Q_stricmp( cmd, "say_admins" )) 735 { 736 G_Say( NULL, NULL, SAY_ADMINS, ConcatArgs( 1 ) ); 737 return qtrue; 738 } 735 739 G_Printf( "unknown command: %s\n", cmd ); 736 740 return qtrue; -
src/game/g_svcmds.c
r122 r124 345 345 gentity_t *check; 346 346 347 check = g_entities + 1;348 349 for( e = 1; e < level.num_entities; e++, check++ )347 check = g_entities; 348 349 for( e = 0; e < level.num_entities; e++, check++ ) 350 350 { 351 351 if( !check->inuse ) -
src/qcommon/common.c
r120 r124 34 34 35 35 int demo_protocols[] = 36 { PROTOCOL_VERSION, 0 };36 { 66, 67, 68, 69, 0 }; 37 37 38 38 #define MAX_NUM_ARGVS 50 … … 2374 2374 */ 2375 2375 void Com_Init( char *commandLine ) { 2376 char *s;2377 2376 2378 2377 Com_Printf( "%s %s %s\n", Q3_VERSION, PLATFORM_STRING, __DATE__ ); … … 2481 2480 Cmd_AddCommand ("writeconfig", Com_WriteConfig_f ); 2482 2481 2483 s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); 2484 com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); 2482 com_version = Cvar_Get ("version", FULL_VERSION, CVAR_ROM | CVAR_SERVERINFO ); 2485 2483 2486 2484 Sys_Init(); … … 2698 2696 } while ( msec < minMsec ); 2699 2697 Cbuf_Execute (); 2698 Cdelay_Frame (); 2700 2699 2701 2700 if (com_altivec->modified) -
src/qcommon/common.c
r123 r124 244 244 static int errorCount; 245 245 int currentTime; 246 247 Cvar_Set( "com_errorCode", va( "%i", code ) ); 246 248 247 249 // when we are running automated scripts, make sure we … … 3154 3156 else 3155 3157 { 3158 int completionOffset; 3159 3156 3160 if( completionString[0] == '\\' || completionString[0] == '/' ) 3157 3161 completionString++; … … 3172 3176 return; // no matches 3173 3177 3174 Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) - 3175 strlen( completionString ) ], shortestMatch, 3176 sizeof( completionField->buffer ) ); 3178 completionOffset = strlen( completionField->buffer ) - strlen( completionString ); 3179 3180 Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch, 3181 sizeof( completionField->buffer ) - completionOffset ); 3177 3182 3178 3183 completionField->cursor = strlen( completionField->buffer ); -
src/qcommon/cvar.c
r120 r124 836 836 for (var = cvar_vars ; var ; var = var->next) { 837 837 if (var->flags & bit) { 838 Info_SetValueForKey (info, var->name, var->string); 838 if (!strcmp (var->name, "sv_maxclients")) { 839 cvar_t *g_hiddenClients = Cvar_Get ("g_hiddenClients", "0", 0); 840 Info_SetValueForKey (info, var->name, 841 va ("%i", var->integer - g_hiddenClients->integer)); 842 } else { 843 Info_SetValueForKey (info, var->name, var->string); 844 } 839 845 } 840 846 } -
src/qcommon/cvar.c
r123 r124 286 286 287 287 var->flags = flags; 288 // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) 289 cvar_modifiedFlags |= var->flags; 288 290 289 291 hash = generateHashValue(var_name); -
src/qcommon/files.c
r120 r124 98 98 e.g. the qpath "sound/newstuff/test.wav" would be searched for in the following places: 99 99 100 home path + current game's directory 100 101 home path + current game's zip files 101 home path + current game's directory102 base path + current game's directory 102 103 base path + current game's zip files 103 basepath + current game's directory104 cd path + current game's directory 104 105 cd path + current game's zip files 105 cd path + current game's directory 106 106 107 home path + base game's directory 107 108 home path + base game's zip file 108 home path + base game's directory109 base path + base game's directory 109 110 base path + base game's zip file 110 basepath + base game's directory111 cd path + base game's directory 111 112 cd path + base game's zip file 112 cd path + base game's directory 113 113 114 home path + BASEGAME's directory 114 115 home path + BASEGAME's zip file 115 home path + BASEGAME's directory116 base path + BASEGAME's directory 116 117 base path + BASEGAME's zip file 117 basepath + BASEGAME's directory118 cd path + BASEGAME's directory 118 119 cd path + BASEGAME's zip file 119 cd path + BASEGAME's directory120 120 121 121 server download, to be written to home path + current game's directory … … 2411 2411 Q_strncpyz( fs_gamedir, dir, sizeof( fs_gamedir ) ); 2412 2412 2413 //2414 // add the directory to the search path2415 //2416 search = Z_Malloc (sizeof(searchpath_t));2417 search->dir = Z_Malloc( sizeof( *search->dir ) );2418 2419 Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) );2420 Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) );2421 search->next = fs_searchpaths;2422 fs_searchpaths = search;2423 2424 2413 // find all pak files in this directory 2425 2414 pakfile = FS_BuildOSPath( path, dir, "" ); … … 2442 2431 fs_searchpaths = search; 2443 2432 } 2433 2434 // 2435 // add the directory to the search path 2436 // 2437 search = Z_Malloc (sizeof(searchpath_t)); 2438 search->dir = Z_Malloc( sizeof( *search->dir ) ); 2439 2440 Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) ); 2441 Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) ); 2442 search->next = fs_searchpaths; 2443 fs_searchpaths = search; 2444 2444 2445 2445 // done -
src/qcommon/files.c
r123 r124 236 236 static cvar_t *fs_debug; 237 237 static cvar_t *fs_homepath; 238 239 #ifdef MACOS_X 240 // Also search the .app bundle for .pk3 files 241 static cvar_t *fs_apppath; 242 #endif 243 238 244 static cvar_t *fs_basepath; 239 245 static cvar_t *fs_basegame; … … 2387 2393 ================ 2388 2394 */ 2389 staticvoid FS_AddGameDirectory( const char *path, const char *dir ) {2395 void FS_AddGameDirectory( const char *path, const char *dir ) { 2390 2396 searchpath_t *sp; 2391 2397 int i; … … 2714 2720 } 2715 2721 // fs_homepath is somewhat particular to *nix systems, only add if relevant 2722 2723 #ifdef MACOS_X 2724 fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT ); 2725 // Make MacOSX also include the base path included with the .app bundle 2726 if (fs_apppath->string[0]) 2727 FS_AddGameDirectory(fs_apppath->string, gameName); 2728 #endif 2729 2716 2730 // NOTE: same filtering below for mods and basegame 2717 2731 if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) { -
src/qcommon/msg.c
r120 r124 809 809 { NETF(eType), 8 }, 810 810 { NETF(torsoAnim), 8 }, 811 { NETF(weaponAnim), 8 },812 811 { NETF(eventParm), 8 }, 813 812 { NETF(legsAnim), 8 }, … … 825 824 { NETF(origin[2]), 0 }, 826 825 { NETF(solid), 24 }, 827 { NETF( misc), MAX_MISC},826 { NETF(powerups), MAX_POWERUPS }, 828 827 { NETF(modelindex), 8 }, 829 828 { NETF(otherEntityNum2), GENTITYNUM_BITS }, 830 829 { NETF(loopSound), 8 }, 831 { NETF(generic1), 16},830 { NETF(generic1), 8 }, 832 831 { NETF(origin2[2]), 0 }, 833 832 { NETF(origin2[0]), 0 }, … … 1127 1126 { PSF(eventSequence), 16 }, 1128 1127 { PSF(torsoAnim), 8 }, 1129 { PSF(weaponAnim), 8 },1130 1128 { PSF(movementDir), 4 }, 1131 1129 { PSF(events[0]), 8 }, … … 1146 1144 { PSF(damagePitch), 8 }, 1147 1145 { PSF(damageCount), 8 }, 1148 { PSF(ammo), 12 }, 1149 { PSF(clips), 4 }, 1150 { PSF(generic1), 16 }, 1146 { PSF(generic1), 8 }, 1151 1147 { PSF(pm_type), 8 }, 1152 1148 { PSF(delta_angles[0]), 16 }, … … 1176 1172 int statsbits; 1177 1173 int persistantbits; 1178 int miscbits; 1174 int ammobits; 1175 int powerupbits; 1179 1176 int numFields; 1180 1177 int c; … … 1256 1253 } 1257 1254 } 1258 miscbits = 0; 1259 for (i=0 ; i<MAX_MISC ; i++) { 1260 if (to->misc[i] != from->misc[i]) { 1261 miscbits |= 1<<i; 1262 } 1263 } 1264 1265 if (!statsbits && !persistantbits && !miscbits) { 1255 ammobits = 0; 1256 for (i=0 ; i<MAX_WEAPONS ; i++) { 1257 if (to->ammo[i] != from->ammo[i]) { 1258 ammobits |= 1<<i; 1259 } 1260 } 1261 powerupbits = 0; 1262 for (i=0 ; i<MAX_POWERUPS ; i++) { 1263 if (to->powerups[i] != from->powerups[i]) { 1264 powerupbits |= 1<<i; 1265 } 1266 } 1267 1268 if (!statsbits && !persistantbits && !ammobits && !powerupbits) { 1266 1269 MSG_WriteBits( msg, 0, 1 ); // no change 1267 1270 oldsize += 4; … … 1292 1295 1293 1296 1294 if ( miscbits ) {1297 if ( ammobits ) { 1295 1298 MSG_WriteBits( msg, 1, 1 ); // changed 1296 MSG_WriteBits( msg, miscbits, MAX_MISC ); 1297 for (i=0 ; i<MAX_MISC ; i++) 1298 if (miscbits & (1<<i) ) 1299 MSG_WriteLong( msg, to->misc[i] ); 1299 MSG_WriteBits( msg, ammobits, MAX_WEAPONS ); 1300 for (i=0 ; i<MAX_WEAPONS ; i++) 1301 if (ammobits & (1<<i) ) 1302 MSG_WriteShort (msg, to->ammo[i]); 1303 } else { 1304 MSG_WriteBits( msg, 0, 1 ); // no change 1305 } 1306 1307 1308 if ( powerupbits ) { 1309 MSG_WriteBits( msg, 1, 1 ); // changed 1310 MSG_WriteBits( msg, powerupbits, MAX_POWERUPS ); 1311 for (i=0 ; i<MAX_POWERUPS ; i++) 1312 if (powerupbits & (1<<i) ) 1313 MSG_WriteLong( msg, to->powerups[i] ); 1300 1314 } else { 1301 1315 MSG_WriteBits( msg, 0, 1 ); // no change … … 1411 1425 } 1412 1426 1413 // parse misc data1427 // parse ammo 1414 1428 if ( MSG_ReadBits( msg, 1 ) ) { 1415 LOG("PS_ MISC");1416 bits = MSG_ReadBits (msg, MAX_ MISC);1417 for (i=0 ; i<MAX_ MISC; i++) {1429 LOG("PS_AMMO"); 1430 bits = MSG_ReadBits (msg, MAX_WEAPONS); 1431 for (i=0 ; i<MAX_WEAPONS ; i++) { 1418 1432 if (bits & (1<<i) ) { 1419 to->misc[i] = MSG_ReadLong(msg); 1433 to->ammo[i] = MSG_ReadShort(msg); 1434 } 1435 } 1436 } 1437 1438 // parse powerups 1439 if ( MSG_ReadBits( msg, 1 ) ) { 1440 LOG("PS_POWERUPS"); 1441 bits = MSG_ReadBits (msg, MAX_POWERUPS); 1442 for (i=0 ; i<MAX_POWERUPS ; i++) { 1443 if (bits & (1<<i) ) { 1444 to->powerups[i] = MSG_ReadLong(msg); 1420 1445 } 1421 1446 } -
src/qcommon/q_shared.h
r120 r124 29 29 30 30 #define PRODUCT_NAME "tremulous" 31 #define PRODUCT_VERSION "1.1.0" 31 32 #ifndef PRODUCT_VERSION 33 #define PRODUCT_VERSION "DnC-Eggy" 34 #endif 32 35 33 36 #ifdef SVN_VERSION … … 39 42 #define CLIENT_WINDOW_TITLE "Tremulous " PRODUCT_VERSION 40 43 #define CLIENT_WINDOW_MIN_TITLE "Tremulous" 44 45 #define FULL_VERSION Q3_VERSION " " PLATFORM_STRING " " __DATE__ 41 46 42 47 #define MAX_TEAMNAME 32 … … 91 96 **********************************************************************/ 92 97 98 #ifdef Q3_VM 99 93 100 #include "../game/bg_lib.h" 94 101 95 # ifndef Q3_VM102 #else 96 103 97 104 #include <assert.h> … … 336 343 337 344 #define Q_COLOR_ESCAPE '^' 338 #define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1)) ) // ^[0-9a-zA-Z]345 #define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE ) 339 346 340 347 #define COLOR_BLACK '0' … … 1013 1020 #define MAX_STATS 16 1014 1021 #define MAX_PERSISTANT 16 1015 #define MAX_ MISC161022 #define MAX_POWERUPS 16 1016 1023 #define MAX_WEAPONS 16 1017 1024 … … 1087 1094 int stats[MAX_STATS]; 1088 1095 int persistant[MAX_PERSISTANT]; // stats that aren't cleared on death 1089 int misc[MAX_MISC]; // misc data 1090 int ammo; // ammo held 1091 int clips; // clips held 1096 int powerups[MAX_POWERUPS]; // level.time that the powerup runs out 1097 int ammo[MAX_WEAPONS]; 1092 1098 1093 1099 int generic1; … … 1153 1159 TR_SINE, // value = base + sin( time / duration ) * delta 1154 1160 TR_GRAVITY, 1155 TR_BUOYANCY 1161 TR_BUOYANCY //TA: what the hell is this doing in here anyway? 1156 1162 } trType_t; 1157 1163 … … 1207 1213 1208 1214 // for players 1209 int misc;// bit flags1215 int powerups; // bit flags 1210 1216 int weapon; // determines weapon and flash model, etc 1211 1217 int legsAnim; // mask off ANIM_TOGGLEBIT … … 1278 1284 1279 1285 // server browser sources 1280 // AS_MPLAYER is no longer used1281 #define AS_GLOBAL 01286 // TTimo: AS_MPLAYER is no longer used 1287 #define AS_GLOBAL 2 1282 1288 #define AS_MPLAYER 1 1283 #define AS_LOCAL 21289 #define AS_LOCAL 0 1284 1290 #define AS_FAVORITES 3 1285 1291 … … 1319 1325 #define MAX_SERVERSTATUSREQUESTS 16 1320 1326 1321 #define SAY_ALL 0 1322 #define SAY_TEAM 1 1323 #define SAY_TELL 2 1327 #define SAY_ALL 0 1328 #define SAY_TEAM 1 1329 #define SAY_TELL 2 1330 #define SAY_ACTION 3 1331 #define SAY_ACTION_T 4 1332 #define SAY_ADMINS 5 1324 1333 1325 1334 #endif // __Q_SHARED_H -
src/qcommon/q_shared.h
r123 r124 1060 1060 int torsoAnim; // mask off ANIM_TOGGLEBIT 1061 1061 1062 int weaponAnim; // mask off ANIM_TOGGLEBIT 1063 1062 1064 int movementDir; // a number 0 to 7 that represents the reletive angle 1063 1065 // of movement to the view angle (axial and diagonals) … … 1215 1217 int legsAnim; // mask off ANIM_TOGGLEBIT 1216 1218 int torsoAnim; // mask off ANIM_TOGGLEBIT 1219 int weaponAnim; // mask off ANIM_TOGGLEBIT 1217 1220 1218 1221 int generic1; -
src/qcommon/qcommon.h
r120 r124 222 222 */ 223 223 224 #define PROTOCOL_VERSION 70224 #define PROTOCOL_VERSION 69 225 225 226 226 // maintain a list of compatible protocols for demo playing … … 365 365 // Do not call inside a command function, or current args will be destroyed. 366 366 367 void Cdelay_Frame (void); 368 //Check if a delayed command have to be executed and decreases the remaining 369 //delay time for all of them 370 367 371 //=========================================================================== 368 372 … … 404 408 void Cmd_TokenizeString( const char *text ); 405 409 void Cmd_TokenizeStringIgnoreQuotes( const char *text_in ); 410 void Cmd_TokenizeStringParseCvar( const char *text_in ); 406 411 // Takes a null terminated string. Does not need to be /n terminated. 407 412 // breaks the string up into arg tokens. -
src/qcommon/qcommon.h
r123 r124 544 544 void FS_Restart( int checksumFeed ); 545 545 // shutdown and restart the filesystem so changes to fs_gamedir can take effect 546 547 void FS_AddGameDirectory( const char *path, const char *dir ); 546 548 547 549 char **FS_ListFiles( const char *directory, const char *extension, int *numfiles ); … … 1022 1024 void Sys_SetDefaultInstallPath(const char *path); 1023 1025 char *Sys_DefaultInstallPath(void); 1026 1027 #ifdef MACOS_X 1028 char *Sys_DefaultAppPath(void); 1029 #endif 1030 1024 1031 void Sys_SetDefaultHomePath(const char *path); 1025 1032 char *Sys_DefaultHomePath(void); -
src/server/sv_init.c
r120 r124 622 622 sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO); 623 623 Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE); 624 sv_wwwDownload = Cvar_Get ("sv_wwwDownload", "1", 625 CVAR_SYSTEMINFO|CVAR_ARCHIVE); 626 sv_wwwBaseURL = Cvar_Get ("sv_wwwBaseURL", "", 627 CVAR_SYSTEMINFO|CVAR_ARCHIVE); 624 628 sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 ); 625 629 sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE ); -
src/server/sv_init.c
r36 r124 281 281 } 282 282 svs.initialized = qtrue; 283 284 // Don't respect sv_killserver unless a server is actually running 285 if ( sv_killserver->integer ) { 286 Cvar_Set( "sv_killserver", "0" ); 287 } 283 288 284 289 Cvar_Set( "sv_running", "1" ); … … 657 662 if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { 658 663 SV_SendServerCommand( cl, "print \"%s\n\"\n", message ); 659 SV_SendServerCommand( cl, "disconnect ");664 SV_SendServerCommand( cl, "disconnect \"%s\"", message ); 660 665 } 661 666 // force a snapshot to be sent -
src/ui/ui_main.c
r120 r124 42 42 }; 43 43 44 static const char *netSources[ ] = 45 { 44 static const char *netSources[] = { 45 "LAN", 46 "Mplayer", 46 47 "Internet", 47 "Mplayer",48 "LAN",49 48 "Favorites" 50 49 }; -
src/ui/ui_main.c
r123 r124 51 51 static const int numNetSources = sizeof( netSources ) / sizeof( const char* ); 52 52 53 static const char *netnames[ ] =53 static const char *netnames[ ] = 54 54 { 55 55 "???", … … 389 389 static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) 390 390 { 391 char * p, *score, *ping, *name;391 char *p, *score, *ping, *name; 392 392 int i, len; 393 393 … … 462 462 { 463 463 if( *p == '\\' ) 464 * p++ = '\0';464 *p++ = '\0'; 465 465 466 466 if( !p ) … … 1607 1607 static const char *UI_OwnerDrawText( int ownerDraw ) 1608 1608 { 1609 const char * s = NULL;1609 const char *s = NULL; 1610 1610 1611 1611 switch( ownerDraw ) … … 1661 1661 static int UI_OwnerDrawWidth( int ownerDraw, float scale ) 1662 1662 { 1663 const char * s = NULL;1663 const char *s = NULL; 1664 1664 1665 1665 switch( ownerDraw ) … … 2196 2196 2197 2197 while( iterator[ 0 ] != ' ' ) 2198 * bufPointer++ = *iterator++;2198 *bufPointer++ = *iterator++; 2199 2199 2200 2200 *bufPointer++ = '\n'; … … 2209 2209 2210 2210 while( iterator[ 0 ] != ' ' ) 2211 * bufPointer++ = *iterator++;2211 *bufPointer++ = *iterator++; 2212 2212 2213 2213 *bufPointer++ = '\n'; … … 2725 2725 static void UI_RunMenuScript( char **args ) 2726 2726 { 2727 const char * name, *name2;2727 const char *name, *name2; 2728 2728 char buff[1024]; 2729 2729 const char *cmd; … … 2880 2880 trap_FS_Read( text, len, f ); 2881 2881 text[ len ] = 0; 2882 2883 Com_sprintf( command, 32, "ptrcrestore %s", text ); 2884 2885 trap_Cmd_ExecuteText( EXEC_APPEND, command ); 2886 } 2887 if( len > -1 ) 2882 2888 trap_FS_FCloseFile( f ); 2883 2884 Com_sprintf( command, 32, "ptrcrestore %s", text );2885 2886 trap_Cmd_ExecuteText( EXEC_APPEND, command );2887 }2888 2889 } 2889 2890 else if( Q_stricmp( name, "Say" ) == 0 ) … … 3288 3289 else if( feederID == FEEDER_TREMHUMANBUILD ) 3289 3290 return uiInfo.humanBuildCount; 3291 else if( feederID == FEEDER_RESOLUTIONS ) 3292 return uiInfo.numResolutions; 3290 3293 3291 3294 return 0; … … 3317 3320 static char hostname[1024]; 3318 3321 static char clientBuff[32]; 3322 static char resolution[MAX_STRING_CHARS]; 3319 3323 static int lastColumn = -1; 3320 3324 static int lastTime = 0; 3321 *handle = -1; 3325 3326 if( handle ) 3327 *handle = -1; 3322 3328 3323 3329 if( feederID == FEEDER_MAPS ) … … 3501 3507 return uiInfo.humanBuildList[ index ].text; 3502 3508 } 3509 else if( feederID == FEEDER_RESOLUTIONS ) 3510 { 3511 int i; 3512 int w = trap_Cvar_VariableValue( "r_width" ); 3513 int h = trap_Cvar_VariableValue( "r_height" ); 3514 3515 for( i = 0; i < uiInfo.numResolutions; i++ ) 3516 { 3517 if( w == uiInfo.resolutions[ i ].w && h == uiInfo.resolutions[ i ].h ) 3518 { 3519 Com_sprintf( resolution, sizeof( resolution ), "%dx%d", w, h ); 3520 return resolution; 3521 } 3522 } 3523 3524 Com_sprintf( resolution, sizeof( resolution ), "Custom (%dx%d)", w, h ); 3525 return resolution; 3526 } 3503 3527 3504 3528 return ""; … … 3551 3575 else if( feederID == FEEDER_SERVERS ) 3552 3576 { 3553 const char * mapName = NULL;3577 const char *mapName = NULL; 3554 3578 uiInfo.serverStatus.currentServer = index; 3555 3579 trap_LAN_GetServerInfo( ui_netSource.integer, uiInfo.serverStatus.displayServers[index], … … 3625 3649 else if( feederID == FEEDER_TREMHUMANBUILD ) 3626 3650 uiInfo.humanBuildIndex = index; 3651 else if( feederID == FEEDER_RESOLUTIONS ) 3652 { 3653 trap_Cvar_Set( "r_width", va( "%d", uiInfo.resolutions[ index ].w ) ); 3654 trap_Cvar_Set( "r_height", va( "%d", uiInfo.resolutions[ index ].h ) ); 3655 } 3656 } 3657 3658 static int UI_FeederInitialise( float feederID ) 3659 { 3660 if( feederID == FEEDER_RESOLUTIONS ) 3661 { 3662 int i; 3663 int w = trap_Cvar_VariableValue( "r_width" ); 3664 int h = trap_Cvar_VariableValue( "r_height" ); 3665 3666 for( i = 0; i < uiInfo.numResolutions; i++ ) 3667 { 3668 if( w == uiInfo.resolutions[ i ].w && h == uiInfo.resolutions[ i ].h ) 3669 return i; 3670 } 3671 } 3672 3673 return 0; 3627 3674 } 3628 3675 … … 3684 3731 } 3685 3732 3733 /* 3734 ================= 3735 UI_ParseResolutions 3736 ================= 3737 */ 3738 void UI_ParseResolutions( void ) 3739 { 3740 char buf[ MAX_STRING_CHARS ]; 3741 char w[ 16 ], h[ 16 ]; 3742 char *p; 3743 const char *out; 3744 char *s = NULL; 3745 3746 trap_Cvar_VariableStringBuffer( "r_availableModes", buf, sizeof( buf ) ); 3747 p = buf; 3748 uiInfo.numResolutions = 0; 3749 3750 while( String_Parse( &p, &out ) ) 3751 { 3752 Q_strncpyz( w, out, sizeof( w ) ); 3753 s = strchr( w, 'x' ); 3754 if( !s ) 3755 return; 3756 3757 *s++ = '\0'; 3758 Q_strncpyz( h, s, sizeof( h ) ); 3759 3760 uiInfo.resolutions[ uiInfo.numResolutions ].w = atoi( w ); 3761 uiInfo.resolutions[ uiInfo.numResolutions ].h = atoi( h ); 3762 uiInfo.numResolutions++; 3763 } 3764 } 3686 3765 3687 3766 /* … … 3743 3822 uiInfo.uiDC.feederItemText = &UI_FeederItemText; 3744 3823 uiInfo.uiDC.feederSelection = &UI_FeederSelection; 3824 uiInfo.uiDC.feederInitialise = &UI_FeederInitialise; 3745 3825 uiInfo.uiDC.setBinding = &trap_Key_SetBinding; 3746 3826 uiInfo.uiDC.getBindingBuf = &trap_Key_GetBindingBuf; … … 3785 3865 3786 3866 trap_Cvar_Register( NULL, "debug_protocol", "", 0 ); 3867 3868 UI_ParseResolutions( ); 3787 3869 } 3788 3870 … … 3797 3879 if( Menu_Count() > 0 ) 3798 3880 { 3799 menuDef_t * menu = Menu_GetFocused();3881 menuDef_t *menu = Menu_GetFocused(); 3800 3882 3801 3883 if( menu ) … … 4105 4187 void UI_DrawConnectScreen( qboolean overlay ) 4106 4188 { 4107 char * s;4189 char *s; 4108 4190 uiClientState_t cstate; 4109 4191 char info[MAX_INFO_VALUE];
