Changeset 124:1950c7262178

Show
Ignore:
Timestamp:
04/26/08 01:24:46 (2 years ago)
Author:
mdoison@…
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
Message:

merge head with tremulous r1060

Files:
1 removed
59 modified

Legend:

Unmodified
Added
Removed
  • Makefile

    r120 r124  
    213213  endif 
    214214 
    215   OPTIMIZE = -O3 -ffast-math -funroll-loops -fomit-frame-pointer 
     215  OPTIMIZE = -O2 -funroll-loops -fomit-frame-pointer 
    216216 
    217217  ifeq ($(ARCH),x86_64) 
    218     OPTIMIZE = -O3 -fomit-frame-pointer -ffast-math -funroll-loops \ 
     218    OPTIMIZE = -O2 -fomit-frame-pointer -funroll-loops \ 
    219219      -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 
    220220      -fstrength-reduce 
     
    223223  else 
    224224  ifeq ($(ARCH),x86) 
    225     OPTIMIZE = -O3 -march=i586 -fomit-frame-pointer -ffast-math \ 
     225    OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 
    226226      -funroll-loops -falign-loops=2 -falign-jumps=2 \ 
    227227      -falign-functions=2 -fstrength-reduce 
     
    295295 
    296296  ifeq ($(ARCH),ppc) 
    297     OPTIMIZE += -faltivec -O3 
     297    OPTIMIZE += -faltivec -O2 
    298298  endif 
    299299  ifeq ($(ARCH),x86) 
     
    342342    $(LIBSDIR)/macosx/libSDL-1.2.0.dylib 
    343343 
    344   OPTIMIZE += -ffast-math -falign-loops=16 
     344  OPTIMIZE += -falign-loops=16 
    345345 
    346346  ifneq ($(HAVE_VM_COMPILED),true) 
     
    397397  endif 
    398398 
    399   OPTIMIZE = -O3 -march=i586 -fno-omit-frame-pointer -ffast-math \ 
     399  OPTIMIZE = -O2 -march=i586 -fno-omit-frame-pointer \ 
    400400    -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ 
    401401    -fstrength-reduce 
     
    469469  ifeq ($(ARCH),axp) 
    470470    BASE_CFLAGS += -DNO_VM_COMPILED 
    471     RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 -ffast-math -funroll-loops \ 
     471    RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -funroll-loops \ 
    472472      -fomit-frame-pointer -fexpensive-optimizations 
    473473  else 
    474474  ifeq ($(ARCH),x86) 
    475     RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 -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 \ 
    477477      -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 
    478478      -funroll-loops -fstrength-reduce 
     
    650650    -pipe -DUSE_ICON $(shell sdl-config --cflags) 
    651651 
    652   OPTIMIZE = -O3 -ffast-math -funroll-loops 
     652  OPTIMIZE = -O2 -funroll-loops 
    653653 
    654654  ifeq ($(ARCH),sparc) 
    655     OPTIMIZE = -O3 -ffast-math -falign-loops=2 \ 
     655    OPTIMIZE = -O2 -falign-loops=2 \ 
    656656      -falign-jumps=2 -falign-functions=2 -fstrength-reduce \ 
    657657      -mtune=ultrasparc -mv8plus -mno-faster-structs \ 
     
    659659  else 
    660660  ifeq ($(ARCH),x86) 
    661     OPTIMIZE = -O3 -march=i586 -fomit-frame-pointer -ffast-math \ 
     661    OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 
    662662      -funroll-loops -falign-loops=2 -falign-jumps=2 \ 
    663663      -falign-functions=2 -fstrength-reduce 
     
    696696  BASE_CFLAGS=-DNO_VM_COMPILED 
    697697  DEBUG_CFLAGS=$(BASE_CFLAGS) -g 
    698   RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 
     698  RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 
    699699 
    700700  SHLIBEXT=so 
  • Makefile

    r123 r124  
    77COMPILE_PLATFORM=$(shell uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]') 
    88 
     9COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/) 
     10 
     11ifeq ($(COMPILE_PLATFORM),sunos) 
     12  # Solaris uname and GNU uname differ 
     13  COMPILE_ARCH=$(shell uname -p | sed -e s/i.86/x86/) 
     14endif 
    915ifeq ($(COMPILE_PLATFORM),darwin) 
    1016  # Apple does some things a little differently... 
    1117  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   = 
     18endif 
     19 
     20ifndef BUILD_CLIENT 
     21  BUILD_CLIENT     = 
     22endif 
     23ifndef BUILD_CLIENT_SMP 
     24  BUILD_CLIENT_SMP = 
     25endif 
     26ifndef BUILD_SERVER 
     27  BUILD_SERVER     = 
     28endif 
     29ifndef BUILD_GAME_SO 
     30  BUILD_GAME_SO    = 
     31endif 
     32ifndef BUILD_GAME_QVM 
     33  BUILD_GAME_QVM   = 
     34endif 
    2135 
    2236ifneq ($(PLATFORM),darwin) 
     
    272286ifeq ($(PLATFORM),darwin) 
    273287  HAVE_VM_COMPILED=true 
    274   BASE_CFLAGS= 
    275288  CLIENT_LDFLAGS= 
    276   LDFLAGS= 
    277289  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 
    325295 
    326296  ifeq ($(ARCH),ppc) 
     
    335305 
    336306  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 += -gfull 
    340307 
    341308  ifeq ($(USE_OPENAL),1) 
     
    633600############################################################################# 
    634601 
    635 ifeq ($(PLATFORM),irix) 
     602ifeq ($(PLATFORM),irix64) 
    636603 
    637604  ARCH=mips  #default to MIPS 
    638605 
    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 
    642612  DEBUG_CFLAGS=$(BASE_CFLAGS) -g 
    643613 
     
    646616  SHLIBLDFLAGS=-shared 
    647617 
    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 
    650622 
    651623else # ifeq IRIX 
     
    694666    LDFLAGS += -m32 
    695667    BASE_CFLAGS += -I/usr/X11/include/NVIDIA 
     668    CLIENT_LDFLAGS += -L/usr/X11/lib/NVIDIA -R/usr/X11/lib/NVIDIA 
    696669  endif 
    697670  endif 
     
    714687  BOTCFLAGS=-O0 
    715688 
    716   CLIENT_LDFLAGS=$(shell sdl-config --libs) -lGL 
     689  CLIENT_LDFLAGS +=$(shell sdl-config --libs) -lGL 
    717690 
    718691else # ifeq sunos 
     
    820793define DO_AS 
    821794$(echo_cmd) "AS $<" 
    822 $(Q)$(CC) $(CFLAGS) -DELF -x assembler-with-cpp -o $@ -c $< 
     795$(Q)$(CC) $(CFLAGS) -x assembler-with-cpp -o $@ -c $< 
    823796endef 
    824797 
     
    857830# Create the build directories, check libraries and print out 
    858831# an informational message, then start building 
    859 targets: makedirs libversioncheck 
     832targets: makedirs 
    860833        @echo "" 
    861834        @echo "Building Tremulous in $(B):" 
     
    868841        @echo "  CFLAGS:" 
    869842        @for i in $(CFLAGS); \ 
     843        do \ 
     844                echo "    $$i"; \ 
     845        done 
     846        @echo "" 
     847        @echo "  LDFLAGS:" 
     848        @for i in $(LDFLAGS); \ 
    870849        do \ 
    871850                echo "    $$i"; \ 
     
    10331012        $(echo_cmd) "LD $@" 
    10341013        $(Q)$(CC) $(TOOLS_LDFLAGS) -o $@ $^ 
    1035  
    1036  
    1037 ############################################################################# 
    1038 # LIBRARY VERSION CHECKS 
    1039 ############################################################################# 
    1040  
    1041 MINSDL_MAJOR  = 1 
    1042 MINSDL_MINOR  = 2 
    1043 MINSDL_PATCH  = 7 
    1044  
    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 ) 
    10581014 
    10591015 
     
    11891145  $(B)/client/sdl_snd.o \ 
    11901146  \ 
     1147  $(B)/client/con_passive.o \ 
     1148  $(B)/client/con_log.o \ 
    11911149  $(B)/client/sys_main.o 
    11921150 
     
    12871245  $(B)/ded/null_snddma.o \ 
    12881246  \ 
     1247  $(B)/ded/con_log.o \ 
    12891248  $(B)/ded/sys_main.o 
    12901249 
     
    16081567 
    16091568.PHONY: all clean clean2 clean-debug clean-release copyfiles \ 
    1610         debug default dist distclean libversioncheck makedirs \ 
     1569        debug default dist distclean makedirs \ 
    16111570        release targets \ 
    16121571        toolsclean toolsclean2 toolsclean-debug toolsclean-release 
  • src/cgame/cg_animmapobj.c

    r120 r124  
    7676 
    7777  //setup animation 
    78   anim.firstFrame   = es->misc; 
     78  anim.firstFrame   = es->powerups; 
    7979  anim.numFrames    = es->weapon; 
    8080  anim.reversed     = !es->legsAnim; 
     
    169169 
    170170  //setup animation 
    171   anim.firstFrame = es->misc; 
     171  anim.firstFrame = es->powerups; 
    172172  anim.numFrames = es->weapon; 
    173173  anim.reversed = qfalse; 
  • src/cgame/cg_animmapobj.c

    r122 r124  
    3232static void CG_DoorAnimation( centity_t *cent, int *old, int *now, float *backLerp ) 
    3333{ 
    34   CG_RunLerpFrame( &cent->lerpFrame ); 
     34  CG_RunLerpFrame( &cent->lerpFrame, 1.0f ); 
    3535 
    3636  *old      = cent->lerpFrame.oldFrame; 
     
    118118    } 
    119119 
    120     CG_RunLerpFrame( &cent->lerpFrame ); 
     120    CG_RunLerpFrame( &cent->lerpFrame, 1.0f ); 
    121121    cent->miscTime = cg.time; 
    122122  } 
  • src/cgame/cg_buildable.c

    r120 r124  
    11301130    return qfalse; 
    11311131 
    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 ) 
    11351135      return qtrue; 
    11361136  } 
  • src/cgame/cg_buildable.c

    r122 r124  
    428428static void CG_RunBuildableLerpFrame( centity_t *cent ) 
    429429{ 
    430   int                   f, numFrames; 
    431430  buildable_t           buildable = cent->currentState.modelindex; 
    432431  lerpFrame_t           *lf = &cent->lerpFrame; 
    433   animation_t           *anim; 
    434432  buildableAnimNumber_t newAnimation = cent->buildableAnim & ~( ANIM_TOGGLEBIT|ANIM_FORCEBIT ); 
    435  
    436   // debugging tool to get no animations 
    437   if( cg_animSpeed.integer == 0 ) 
    438   { 
    439     lf->oldFrame = lf->frame = lf->backlerp = 0; 
    440     return; 
    441   } 
    442433 
    443434  // see if the animation sequence is switching 
     
    467458      cg_buildables[ buildable ].sounds[ lf->animationNumber ].sound ); 
    468459 
    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; 
    535465} 
    536466 
  • src/cgame/cg_local.h

    r120 r124  
    13881388extern  markPoly_t      cg_markPolys[ MAX_MARK_POLYS ]; 
    13891389 
     1390extern  vmCvar_t    cg_version; 
    13901391extern  vmCvar_t    cg_centertime; 
    13911392extern  vmCvar_t    cg_runpitch; 
  • src/cgame/cg_local.h

    r123 r124  
    563563typedef struct 
    564564{ 
    565   lerpFrame_t legs, torso, flag, nonseg; 
     565  lerpFrame_t legs, torso, nonseg, weapon; 
    566566  int         painTime; 
    567567  int         painDirection;  // flip from 0 to 1 
     
    809809  qhandle_t         barrelModel; 
    810810  qhandle_t         flashModel; 
     811 
     812  animation_t       animations[ MAX_WEAPON_ANIMATIONS ]; 
     813  qboolean          noDrift; 
    811814 
    812815  vec3_t            weaponMidpoint;   // so it will rotate centered instead of by tag 
     
    16311634// cg_animation.c 
    16321635// 
    1633 void        CG_RunLerpFrame( lerpFrame_t *lf ); 
     1636void        CG_RunLerpFrame( lerpFrame_t *lf, float scale ); 
    16341637 
    16351638// 
  • src/cgame/cg_main.c

    r120 r124  
    2424// cg_main.c -- initialization and primary entry point for cgame 
    2525 
    26  
    2726#include "cg_local.h" 
     27 
     28#include "../qcommon/q_shared.h" 
    2829 
    2930#include "../ui/ui_shared.h" 
     
    101102buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; 
    102103 
     104vmCvar_t  cg_version; 
    103105vmCvar_t  cg_teslaTrailTime; 
    104106vmCvar_t  cg_railTrailTime; 
     
    239241static cvarTable_t cvarTable[ ] = 
    240242{ 
     243  { &cg_version, "cg_version", FULL_VERSION, CVAR_ROM | CVAR_USERINFO }, 
    241244  { &cg_ignore, "cg_ignore", "0", 0 },  // used for debugging 
    242245  { &cg_autoswitch, "cg_autoswitch", "1", CVAR_ARCHIVE }, 
  • src/cgame/cg_main.c

    r123 r124  
    632632qboolean CG_FileExists( char *filename ) 
    633633{ 
    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 ); 
    645635} 
    646636 
  • src/cgame/cg_players.c

    r120 r124  
    18661866  float         shadowPlane; 
    18671867  entityState_t *es = &cent->currentState; 
    1868   pClass_t      class = ( es->misc >> 8 ) & 0xFF; 
     1868  pClass_t      class = ( es->powerups >> 8 ) & 0xFF; 
    18691869  float         scale; 
    18701870  vec3_t        tempAxis[ 3 ], tempAxis2[ 3 ]; 
  • src/cgame/cg_players.c

    r123 r124  
    108108  // load the file 
    109109  len = trap_FS_FOpenFile( filename, &f, FS_READ ); 
    110   if( len <= 0 ) 
     110  if( len < 0 ) 
    111111    return qfalse; 
    112112 
     
    842842static void CG_RunPlayerLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale ) 
    843843{ 
    844   int         f, numFrames; 
    845   animation_t *anim; 
    846  
    847   // debugging tool to get no animations 
    848   if( cg_animSpeed.integer == 0 ) 
    849   { 
    850     lf->oldFrame = lf->frame = lf->backlerp = 0; 
    851     return; 
    852   } 
    853  
    854844  // see if the animation sequence is switching 
    855845  if( newAnimation != lf->animationNumber || !lf->animation ) 
    856   { 
    857846    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 ); 
    928849} 
    929850 
  • src/cgame/cg_predict.c

    r120 r124  
    139139 
    140140      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 ); 
    142142 
    143143      cmodel = trap_CM_TempBoxModel( bmins, bmaxs ); 
  • src/cgame/cg_predict.c

    r123 r124  
    177177    } 
    178178    else if( trace.startsolid ) 
     179    { 
    179180      tr->startsolid = qtrue; 
     181      tr->entityNum = ent->number; 
     182    } 
    180183 
    181184    if( tr->allsolid ) 
  • src/cgame/cg_weapons.c

    r120 r124  
    13491349  for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 
    13501350  { 
     1351    int ammo, clips; 
     1352 
    13511353    if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) 
    13521354      continue; 
    13531355 
    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 ) ) 
    13551359      colinfo[ numItems ] = 1; 
    13561360    else 
  • src/cgame/cg_weapons.c

    r123 r124  
    7777  for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 
    7878    CG_RegisterUpgrade( i ); 
     79} 
     80 
     81 
     82/* 
     83====================== 
     84CG_ParseWeaponAnimationFile 
     85 
     86Read a configuration file containing animation counts and rates 
     87models/weapons/rifle/animation.cfg, etc 
     88====================== 
     89*/ 
     90static 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; 
    79177} 
    80178 
     
    430528  // load the file 
    431529  len = trap_FS_FOpenFile( filename, &f, FS_READ ); 
    432   if( len <= 0 ) 
     530  if( len < 0 ) 
    433531    return qfalse; 
    434532 
     
    618716    Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path ); 
    619717 
     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 
    620723  // calc midpoint for rotation 
    621724  trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs ); 
     
    657760 
    658761/* 
     762=============== 
     763CG_SetWeaponLerpFrameAnimation 
     764 
     765may include ANIM_TOGGLEBIT 
     766=============== 
     767*/ 
     768static 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=============== 
     789CG_WeaponAnimation 
     790=============== 
     791*/ 
     792static void CG_WeaponAnimation( centity_t *cent, int *old, int *now, float *backLerp ) 
     793{ 
     794  lerpFrame_t   *lf = &cent->pe.weapon; 
     795  entityState_t *es = &cent->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/* 
    659809================= 
    660810CG_MapTorsoToWeaponFrame 
     
    691841static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) 
    692842{ 
    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 ]; 
    697850 
    698851  VectorCopy( cg.refdef.vieworg, origin ); 
     
    717870 
    718871  // drop the weapon when landing 
    719   if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ) ) 
     872  if( weapon->noDrift ) 
    720873  { 
    721874    delta = cg.time - cg.landTime; 
     
    8611014  if( !noGunModel ) 
    8621015  { 
     1016    CG_WeaponAnimation( cent, &gun.oldframe, &gun.frame, &gun.backlerp ); 
    8631017    CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" ); 
    8641018 
  • src/client/cl_main.c

    r120 r124  
    3131cvar_t  *cl_noprint; 
    3232cvar_t  *cl_motd; 
    33  
     33cvar_t  *cl_master; 
    3434cvar_t  *rcon_client_password; 
    3535cvar_t  *rconAddress; 
     
    986986                return; 
    987987        } 
    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  ) ) { 
    990990                Com_Printf( "Couldn't resolve address\n" ); 
    991991                return; 
    992992        } 
    993993        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, 
    995995                cls.updateServer.ip[0], cls.updateServer.ip[1], 
    996996                cls.updateServer.ip[2], cls.updateServer.ip[3], 
     
    26192619        cl_noprint = Cvar_Get( "cl_noprint", "0", 0 ); 
    26202620        cl_motd = Cvar_Get ("cl_motd", "1", 0); 
    2621  
     2621  cl_master = Cvar_Get("cl_master","master.tremulous.net",CVAR_ARCHIVE); 
    26222622        cl_timeout = Cvar_Get ("cl_timeout", "200", 0); 
    26232623 
     
    32193219 
    32203220        if( cls.masterNum == 1 ) { 
     3221                NET_StringToAdr( cl_master->string, &to ); 
    32213222                cls.nummplayerservers = -1; 
    32223223                cls.pingUpdateSource = AS_MPLAYER; 
    32233224        } 
    32243225        else { 
     3226                NET_StringToAdr( cl_master->string, &to ); 
    32253227                cls.numglobalservers = -1; 
    32263228                cls.pingUpdateSource = AS_GLOBAL; 
  • src/client/cl_main.c

    r123 r124  
    3838cvar_t  *cl_maxpackets; 
    3939cvar_t  *cl_packetdup; 
     40cvar_t  *cl_master; 
    4041cvar_t  *cl_timeNudge; 
    4142cvar_t  *cl_showTimeDelta; 
     
    934935        // Stop recording any video 
    935936        if( CL_VideoRecording( ) ) { 
     937                // Finish rendering current frame 
     938                SCR_UpdateScreen( ); 
    936939                CL_CloseAVI( ); 
    937940        } 
     
    26192622        cl_timeout = Cvar_Get ("cl_timeout", "200", 0); 
    26202623 
     2624        cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE); 
    26212625        cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); 
    26222626        cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); 
     
    32113215        // reset the list, waiting for response 
    32123216        // -1 is used to distinguish a "no response" 
     3217 
     3218        NET_StringToAdr( cl_master->string, &to ); 
    32133219 
    32143220        if( cls.masterNum == 1 ) { 
  • src/game/bg_misc.c

    r120 r124  
    7272    qfalse,                //qboolean  dccTest; 
    7373    qfalse,                //qboolean  transparentTest; 
    74     qfalse                 //qboolean  reactorTest; 
     74    qfalse,                //qboolean  reactorTest; 
     75    qfalse                 //qboolean  replacable; 
    7576  }, 
    7677  { 
     
    110111    qfalse,                //qboolean  dccTest; 
    111112    qfalse,                //qboolean  transparentTest; 
    112     qfalse                 //qboolean  reactorTest; 
     113    qfalse,                //qboolean  reactorTest; 
     114    qfalse                 //qboolean  replacable; 
    113115  }, 
    114116  { 
     
    151153    qfalse,                //qboolean  dccTest; 
    152154    qtrue,                 //qboolean  transparentTest; 
    153     qfalse                 //qboolean  reactorTest; 
     155    qfalse,                //qboolean  reactorTest; 
     156    qtrue                  //qboolean  replacable; 
    154157  }, 
    155158  { 
     
    190193    qfalse,                //qboolean  dccTest; 
    191194    qfalse,                //qboolean  transparentTest; 
    192     qfalse                 //qboolean  reactorTest; 
     195    qfalse,                //qboolean  reactorTest; 
     196    qfalse                 //qboolean  replacable; 
    193197  }, 
    194198  { 
     
    228232    qfalse,                //qboolean  dccTest; 
    229233    qfalse,                //qboolean  transparentTest; 
    230     qfalse                 //qboolean  reactorTest; 
     234    qfalse,                //qboolean  reactorTest; 
     235    qfalse                 //qboolean  replacable; 
    231236  }, 
    232237  { 
     
    267272    qfalse,                //qboolean  dccTest; 
    268273    qtrue,                 //qboolean  transparentTest; 
    269     qfalse                 //qboolean  reactorTest; 
     274    qfalse,                //qboolean  reactorTest; 
     275    qfalse                 //qboolean  replacable; 
    270276  }, 
    271277  { 
     
    306312    qfalse,                //qboolean  dccTest; 
    307313    qfalse,                //qboolean  transparentTest; 
    308     qtrue                  //qboolean  reactorTest; 
     314    qtrue,                 //qboolean  reactorTest; 
     315    qtrue                  //qboolean  replacable; 
    309316  }, 
    310317  { 
     
    345352    qfalse,                //qboolean  dccTest; 
    346353    qfalse,                //qboolean  transparentTest; 
    347     qtrue                  //qboolean  reactorTest; 
     354    qtrue,                 //qboolean  reactorTest; 
     355    qfalse                 //qboolean  replacable; 
    348356  }, 
    349357  { 
     
    384392    qfalse,                //qboolean  dccTest; 
    385393    qtrue,                 //qboolean  transparentTest; 
    386     qfalse                 //qboolean  reactorTest; 
     394    qfalse,                //qboolean  reactorTest; 
     395    qfalse                 //qboolean  replacable; 
    387396  }, 
    388397  { 
     
    423432    qfalse,                //qboolean  dccTest; 
    424433    qtrue,                 //qboolean  transparentTest; 
    425     qfalse                 //qboolean  reactorTest; 
     434    qfalse,                //qboolean  reactorTest; 
     435    qtrue                  //qboolean  replacable; 
    426436  }, 
    427437  { 
     
    464474    qfalse,                //qboolean  dccTest; 
    465475    qtrue,                 //qboolean  transparentTest; 
    466     qfalse                 //qboolean  reactorTest; 
     476    qfalse,                //qboolean  reactorTest; 
     477    qfalse                 //qboolean  replacable; 
    467478  }, 
    468479  { 
     
    503514    qtrue,                 //qboolean  dccTest; 
    504515    qtrue,                 //qboolean  transparentTest; 
    505     qfalse                 //qboolean  reactorTest; 
     516    qfalse,                //qboolean  reactorTest; 
     517    qfalse                 //qboolean  replacable; 
    506518  }, 
    507519  { 
     
    542554    qfalse,                //qboolean  dccTest; 
    543555    qfalse,                //qboolean  transparentTest; 
    544     qfalse                 //qboolean  reactorTest; 
     556    qfalse,                //qboolean  reactorTest; 
     557    qtrue                  //qboolean  replacable; 
    545558  }, 
    546559  { 
     
    581594    qfalse,                //qboolean  dccTest; 
    582595    qfalse,                //qboolean  transparentTest; 
    583     qfalse                 //qboolean  reactorTest; 
     596    qfalse,                //qboolean  reactorTest; 
     597    qtrue                  //qboolean  replacable; 
    584598  }, 
    585599  { 
     
    620634    qfalse,                //qboolean  dccTest; 
    621635    qfalse,                //qboolean  transparentTest; 
    622     qtrue                  //qboolean  reactorTest; 
     636    qtrue,                 //qboolean  reactorTest; 
     637    qtrue                  //qboolean  replacable; 
    623638  }, 
    624639  { 
     
    638653    0.0,                   //float     bounce; 
    639654    REPEATER_BP,           //int       buildPoints; 
    640     ( 1 << S2 )|( 1 << S3 ), //int  stages 
     655    ( 1 << S1)|( 1 << S2 )|( 1 << S3 ), //int  stages 
    641656    REPEATER_HEALTH,       //int       health; 
    642657    0,                     //int       regenRate; 
     
    659674    qfalse,                //qboolean  dccTest; 
    660675    qfalse,                //qboolean  transparentTest; 
    661     qfalse                 //qboolean  reactorTest; 
     676    qfalse,                //qboolean  reactorTest; 
     677    qtrue                  //qboolean  replacable; 
    662678  } 
    663679}; 
     
    13691385  } 
    13701386 
     1387  return qfalse; 
     1388} 
     1389 
     1390/* 
     1391============== 
     1392BG_FindReplaceableTestForBuildable 
     1393============== 
     1394*/ 
     1395qboolean 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  } 
    13711406  return qfalse; 
    13721407} 
     
    49905025  } 
    49915026 
    4992   // use misc field 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 ); 
    49945029 
    49955030  // have to get the surfNormal through somehow... 
     
    51015136  } 
    51025137 
    5103   // use misc field 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 ); 
    51055140 
    51065141  // have to get the surfNormal through somehow... 
     
    51205155/* 
    51215156======================== 
     5157BG_UnpackAmmoArray  
     5158 
     5159Extract the ammo quantity from the array 
     5160======================== 
     5161*/ 
     5162void 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========================  
     5182BG_PackAmmoArray 
     5183 
     5184Pack the ammo quantity into the array 
     5185======================== 
     5186*/ 
     5187void 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======================== 
    51225201BG_WeaponIsFull 
    51235202 
     
    51255204======================== 
    51265205*/ 
    5127 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips ) 
     5206qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] ) 
    51285207{ 
    51295208  int maxAmmo, maxClips; 
     5209  int ammo, clips; 
    51305210 
    51315211  BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); 
     5212  BG_UnpackAmmoArray( weapon, psAmmo, psAmmo2, &ammo, &clips ); 
    51325213 
    51335214  if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) ) 
  • src/game/bg_misc.c

    r122 r124  
    17341734    0.0f,                                           //float   fallDamage; 
    17351735    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; 
    17381737    WP_ALEVEL0,                                     //weapon_t  startWeapon 
    17391738    0.0f,                                           //float   buildDist; 
     
    17751774    0.0f,                                           //float   fallDamage; 
    17761775    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; 
    17791777    WP_ALEVEL1,                                     //weapon_t  startWeapon 
    17801778    0.0f,                                           //float   buildDist; 
     
    18171815    0.0f,                                           //float   fallDamage; 
    18181816    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; 
    18211818    WP_ALEVEL1_UPG,                                 //weapon_t  startWeapon 
    18221819    0.0f,                                           //float   buildDist; 
     
    18581855    0.0f,                                           //float   fallDamage; 
    18591856    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; 
    18621858    WP_ALEVEL2,                                     //weapon_t  startWeapon 
    18631859    0.0f,                                           //float   buildDist; 
     
    18991895    0.0f,                                           //float   fallDamage; 
    19001896    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; 
    19031898    WP_ALEVEL2_UPG,                                 //weapon_t  startWeapon 
    19041899    0.0f,                                           //float   buildDist; 
     
    19411936    0.0f,                                           //float   fallDamage; 
    19421937    LEVEL3_REGEN,                                   //int     regenRate; 
    1943     SCA_NOWEAPONDRIFT| 
    1944       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities; 
     1938    SCA_FOVWARPS|SCA_ALIENSENSE,                    //int     abilities; 
    19451939    WP_ALEVEL3,                                     //weapon_t  startWeapon 
    19461940    0.0f,                                           //float   buildDist; 
     
    19831977    0.0f,                                           //float   fallDamage; 
    19841978    LEVEL3_UPG_REGEN,                               //int     regenRate; 
    1985     SCA_NOWEAPONDRIFT| 
    1986       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities; 
     1979    SCA_FOVWARPS|SCA_ALIENSENSE,                    //int     abilities; 
    19871980    WP_ALEVEL3_UPG,                                 //weapon_t  startWeapon 
    19881981    0.0f,                                           //float   buildDist; 
     
    20252018    0.0f,                                           //float   fallDamage; 
    20262019    LEVEL4_REGEN,                                   //int     regenRate; 
    2027     SCA_NOWEAPONDRIFT| 
    2028       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities; 
     2020    SCA_FOVWARPS|SCA_ALIENSENSE,                    //int     abilities; 
    20292021    WP_ALEVEL4,                                     //weapon_t  startWeapon 
    20302022    0.0f,                                           //float   buildDist; 
     
    20652057    1.0f,                                           //float   fallDamage; 
    20662058    0,                                              //int     regenRate; 
    2067     SCA_TAKESFALLDAMAGE| 
    2068       SCA_CANUSELADDERS,                            //int     abilities; 
     2059    SCA_TAKESFALLDAMAGE|SCA_CANUSELADDERS,          //int     abilities; 
    20692060    WP_NONE, //special-cased in g_client.c          //weapon_t  startWeapon 
    20702061    110.0f,                                         //float   buildDist; 
     
    49854976  s->legsAnim = ps->legsAnim; 
    49864977  s->torsoAnim = ps->torsoAnim; 
     4978  s->weaponAnim = ps->weaponAnim; 
    49874979  s->clientNum = ps->clientNum;   // ET_PLAYER looks here instead of at number 
    49884980                    // so corpses can also reference the proper config 
     
    50935085  s->legsAnim = ps->legsAnim; 
    50945086  s->torsoAnim = ps->torsoAnim; 
     5087  s->weaponAnim = ps->weaponAnim; 
    50955088  s->clientNum = ps->clientNum;   // ET_PLAYER looks here instead of at number 
    50965089                    // so corpses can also reference the proper config 
  • src/game/bg_pmove.c

    r120 r124  
    538538    return qfalse; 
    539539 
     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 
    540549  if( pm->cmd.buttons & BUTTON_ATTACK2 ) 
    541   { 
    542     pm->ps->pm_flags &= ~PMF_CHARGE; 
    543550    return qfalse; 
    544   } 
    545  
     551 
     552  // already a pounce in progress 
    546553  if( pm->ps->pm_flags & PMF_CHARGE ) 
    547554    return qfalse; 
     
    26952702{ 
    26962703  int           addTime = 200; //default addTime - should never be used 
    2697   int           maxClips; 
     2704  int           ammo, clips, maxClips; 
    26982705  qboolean      attack1 = qfalse; 
    26992706  qboolean      attack2 = qfalse; 
     
    27212728  } 
    27222729 
    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 
    27242739  if( pm->ps->weaponTime > 0 ) 
    27252740    pm->ps->weaponTime -= pml.msec; 
     
    27952810  // start the animation even if out of ammo 
    27962811 
     2812  BG_UnpackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, &ammo, &clips); 
    27972813  BG_FindAmmoForWeapon( pm->ps->weapon, NULL, &maxClips ); 
    27982814 
    27992815  // 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 ) ) 
    28012817  { 
    28022818    PM_AddEvent( EV_NOAMMO ); 
     
    28142830    if( maxClips > 0 ) 
    28152831    { 
    2816       pm->ps->clips--; 
    2817       BG_FindAmmoForWeapon( pm->ps->weapon, &pm->ps->ammo, NULL ); 
     2832      clips--; 
     2833      BG_FindAmmoForWeapon( pm->ps->weapon, &ammo, NULL ); 
    28182834    } 
    28192835 
    28202836    if( BG_FindUsesEnergyForWeapon( pm->ps->weapon ) && 
    28212837        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 ); 
    28232841 
    28242842    //allow some time for the weapon to be raised 
     
    28292847 
    28302848  // 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 ) 
    28322850  { 
    28332851    pm->ps->pm_flags &= ~PMF_WEAPON_RELOAD; 
     
    29492967    { 
    29502968      //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 ) 
    29522970      { 
    29532971        PM_AddEvent( EV_NOAMMO ); 
     
    30923110    if( pm->ps->weapon == WP_LUCIFER_CANNON && attack1 && !attack2 ) 
    30933111    { 
    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 ) ); 
    30953113 
    30963114      //stay on the safe side 
    3097       if( pm->ps->ammo < 0 ) 
    3098         pm->ps->ammo = 0; 
     3115      if( ammo < 0 ) 
     3116        ammo = 0; 
    30993117    } 
    31003118    else 
    3101       pm->ps->ammo--; 
     3119      ammo--; 
     3120 
     3121    BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips ); 
    31023122  } 
    31033123  else if( pm->ps->weapon == WP_ALEVEL3_UPG && attack3 ) 
    31043124  { 
    31053125    //special case for slowblob 
    3106     pm->ps->ammo--; 
     3126    ammo--; 
     3127    BG_PackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, ammo, clips ); 
    31073128  } 
    31083129 
     
    33063327void PmoveSingle( pmove_t *pmove ) 
    33073328{ 
     3329  int ammo, clips; 
    33083330  pm = pmove; 
     3331 
     3332  BG_UnpackAmmoArray( pm->ps->weapon, pm->ps->ammo, pm->ps->powerups, &ammo, &clips ); 
    33093333 
    33103334  // this counter lets us debug movement problems with a journal 
     
    33343358  if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 
    33353359      ( 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 ) ) ) 
    33373361    pm->ps->eFlags |= EF_FIRING; 
    33383362  else 
     
    33423366  if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 
    33433367      ( 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 ) ) ) 
    33453369    pm->ps->eFlags |= EF_FIRING2; 
    33463370  else 
     
    33503374  if( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && 
    33513375      ( 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 ) ) ) 
    33533377    pm->ps->eFlags |= EF_FIRING3; 
    33543378  else 
  • src/game/bg_pmove.c

    r122 r124  
    104104/* 
    105105=================== 
     106PM_StartWeaponAnim 
     107=================== 
     108*/ 
     109static 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=================== 
    106120PM_StartLegsAnim 
    107121=================== 
     
    167181 
    168182  PM_StartTorsoAnim( anim ); 
     183} 
     184 
     185/* 
     186=================== 
     187PM_ContinueWeaponAnim 
     188=================== 
     189*/ 
     190static void PM_ContinueWeaponAnim( int anim ) 
     191{ 
     192  if( ( pm->ps->weaponAnim & ~ANIM_TOGGLEBIT ) == anim ) 
     193    return; 
     194 
     195  PM_StartWeaponAnim( anim ); 
    169196} 
    170197 
     
    25852612static void PM_BeginWeaponChange( int weapon ) 
    25862613{ 
    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 ) ) 
    25912618    return; 
    25922619 
     
    26072634 
    26082635  if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) ) 
     2636  { 
    26092637    PM_StartTorsoAnim( TORSO_DROP ); 
     2638    PM_StartWeaponAnim( WANIM_DROP ); 
     2639  } 
    26102640} 
    26112641 
     
    26322662 
    26332663  if( !( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) ) 
     2664  { 
    26342665    PM_StartTorsoAnim( TORSO_RAISE ); 
     2666    PM_StartWeaponAnim( WANIM_RAISE ); 
     2667  } 
    26352668} 
    26362669 
     
    26442677static void PM_TorsoAnimation( void ) 
    26452678{ 
    2646   if( pm->ps->persistant[ PERS_STATE ] & PS_NONSEGMODEL ) 
    2647     return; 
    2648  
    26492679  if( pm->ps->weaponstate == WEAPON_READY ) 
    26502680  { 
    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 ); 
    26552690  } 
    26562691} 
     
    27682803    } 
    27692804 
     2805    PM_ContinueWeaponAnim( WANIM_IDLE ); 
     2806 
    27702807    return; 
    27712808  } 
     
    28052842    //allow some time for the weapon to be raised 
    28062843    pm->ps->weaponstate = WEAPON_RAISING; 
    2807     PM_StartTorsoAnim( TORSO_RAISE ); 
    28082844    pm->ps->weaponTime += 250; 
    28092845    return; 
     
    28192855    //drop the weapon 
    28202856    PM_StartTorsoAnim( TORSO_DROP ); 
     2857    PM_StartWeaponAnim( WANIM_RELOAD ); 
    28212858 
    28222859    addTime = BG_FindReloadTimeForWeapon( pm->ps->weapon ); 
     
    30043041        { 
    30053042          PM_StartTorsoAnim( TORSO_ATTACK ); 
     3043          PM_StartWeaponAnim( WANIM_ATTACK1 ); 
    30063044        } 
    30073045        break; 
     
    30093047      case WP_BLASTER: 
    30103048        PM_StartTorsoAnim( TORSO_ATTACK2 ); 
     3049        PM_StartWeaponAnim( WANIM_ATTACK1 ); 
    30113050        break; 
    30123051 
    30133052      default: 
    30143053        PM_StartTorsoAnim( TORSO_ATTACK ); 
     3054        PM_StartWeaponAnim( WANIM_ATTACK1 ); 
    30153055        break; 
    30163056    } 
     
    30253065 
    30263066      if( num == 0 ) 
     3067      { 
    30273068        PM_ForceLegsAnim( NSPA_ATTACK1 ); 
     3069        PM_StartWeaponAnim( WANIM_ATTACK1 ); 
     3070      } 
    30283071      else if( num == 1 ) 
     3072      { 
    30293073        PM_ForceLegsAnim( NSPA_ATTACK2 ); 
     3074        PM_StartWeaponAnim( WANIM_ATTACK2 ); 
     3075      } 
    30303076      else if( num == 2 ) 
     3077      { 
    30313078        PM_ForceLegsAnim( NSPA_ATTACK3 ); 
     3079        PM_StartWeaponAnim( WANIM_ATTACK3 ); 
     3080      } 
    30323081    } 
    30333082    else 
    30343083    { 
    30353084      if( attack1 ) 
     3085      { 
    30363086        PM_ForceLegsAnim( NSPA_ATTACK1 ); 
     3087        PM_StartWeaponAnim( WANIM_ATTACK1 ); 
     3088      } 
    30373089      else if( attack2 ) 
     3090      { 
    30383091        PM_ForceLegsAnim( NSPA_ATTACK2 ); 
     3092        PM_StartWeaponAnim( WANIM_ATTACK2 ); 
     3093      } 
    30393094      else if( attack3 ) 
     3095      { 
    30403096        PM_ForceLegsAnim( NSPA_ATTACK3 ); 
     3097        PM_StartWeaponAnim( WANIM_ATTACK3 ); 
     3098      } 
    30413099    } 
    30423100 
  • src/game/bg_public.h

    r120 r124  
    3434 
    3535#define VOTE_TIME               30000 // 30 seconds before vote times out 
     36 
     37#define WARMUPMESSAGE_TIME      1000 // 1 second between two warmup messages 
    3638 
    3739#define MINS_Z                  -24 
     
    433435} buildableTeam_t; 
    434436 
    435 #define B_HEALTH_BITS       12 
     437#define B_HEALTH_BITS       5 
    436438#define B_HEALTH_MASK       ((1<<B_HEALTH_BITS)-1) 
    437439 
    438 #define B_MARKED_TOGGLEBIT  0x00001000 
    439 #define B_SPAWNED_TOGGLEBIT 0x00002000 
    440 #define B_POWERED_TOGGLEBIT 0x00004000 
    441 #define B_DCCED_TOGGLEBIT   0x00008000 
     440#define B_DCCED_TOGGLEBIT    0x00000000 
     441#define B_SPAWNED_TOGGLEBIT  0x00000020 
     442#define B_POWERED_TOGGLEBIT  0x00000040 
     443#define B_MARKED_TOGGLEBIT   0x00000080 
    442444 
    443445 
     
    564566  MN_A_TEAMFULL, 
    565567  MN_H_TEAMFULL, 
    566   MN_A_TEAMCHANGEBUILDTIMER, 
    567   MN_H_TEAMCHANGEBUILDTIMER, 
    568568 
    569569  //alien stuff 
     
    576576  MN_A_TOOCLOSE, 
    577577  MN_A_NOOVMND_EVOLVE, 
    578   MN_A_EVOLVEBUILDTIMER, 
    579578 
    580579  //alien build 
     
    596595  MN_H_NOFUNDS, 
    597596  MN_H_ITEMHELD, 
    598   MN_H_NOENERGYAMMOHERE, 
    599   MN_H_NOARMOURYHERE, 
    600   MN_H_NOROOMBSUITON, 
    601   MN_H_NOROOMBSUITOFF, 
    602   MN_H_ARMOURYBUILDTIMER, 
    603597 
    604598  //human build 
     
    612606  MN_H_TNODEWARN, 
    613607  MN_H_RPTWARN, 
    614   MN_H_RPTWARN2 
     608  MN_H_RPTWARN2, 
     609  // Balance mod 
     610  MN_H_RECHARGING, 
     611  MN_H_NOTELEPORT, 
    615612} dynMenu_t; 
    616613 
     
    883880  MOD_ASPAWN, 
    884881  MOD_ATUBE, 
    885   MOD_OVERMIND 
     882  MOD_OVERMIND, 
     883 
     884  MOD_SLAP 
    886885} meansOfDeath_t; 
    887886 
     
    10271026  qboolean  transparentTest; 
    10281027  qboolean  reactorTest; 
     1028  qboolean  replaceable; 
    10291029} buildableAttributes_t; 
    10301030 
     
    11001100} upgradeAttributes_t; 
    11011101 
    1102 qboolean  BG_WeaponIsFull( weapon_t weapon, int stats[ ], int ammo, int clips ); 
     1102void      BG_UnpackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int *ammo, int *clips ); 
     1103void      BG_PackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int ammo, int clips ); 
     1104qboolean  BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] ); 
    11031105void      BG_AddWeaponToInventory( int weapon, int stats[ ] ); 
    11041106void      BG_RemoveWeaponFromInventory( int weapon, int stats[ ] ); 
     
    11541156int       BG_FindDCCTestForBuildable( int bclass ); 
    11551157int       BG_FindUniqueTestForBuildable( int bclass ); 
     1158qboolean  BG_FindReplaceableTestForBuildable( int bclass ); 
    11561159qboolean  BG_FindTransparentTestForBuildable( int bclass ); 
    11571160void      BG_InitBuildableOverrides( void ); 
  • src/game/bg_public.h

    r122 r124  
    226226#define SCA_TAKESFALLDAMAGE     0x00000002 
    227227#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 
    233232 
    234233#define SS_WALLCLIMBING         0x00000001 
     
    743742  MAX_BUILDABLE_ANIMATIONS 
    744743} buildableAnimNumber_t; 
     744 
     745typedef 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; 
    745761 
    746762typedef struct animation_s 
  • src/game/g_active.c

    r120 r124  
    376376  pmove_t pm; 
    377377  gclient_t *client; 
     378  qboolean      doPmove = qtrue; 
    378379 
    379380  client = ent->client; 
     
    382383  client->buttons = ucmd->buttons; 
    383384 
    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  { 
    391403    client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); 
    392404 
     
    551563 
    552564    if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) && BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) ) 
     565    { 
     566      //don't run when jetpack on 
    553567      client->ps.stats[ STAT_STATE ] &= ~SS_SPEEDBOOST; 
     568    } 
    554569 
    555570    if( ( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST ) && !crouched ) 
     
    666681    if( client->ps.weapon == WP_LUCIFER_CANNON ) 
    667682    { 
     683      int ammo; 
     684 
     685      BG_UnpackAmmoArray( WP_LUCIFER_CANNON, client->ps.ammo, client->ps.powerups, &ammo, NULL ); 
     686 
    668687      if( client->ps.stats[ STAT_MISC ] < LCANNON_TOTAL_CHARGE && ucmd->buttons & BUTTON_ATTACK ) 
    669688        client->ps.stats[ STAT_MISC ] += ( 100.0f / LCANNON_CHARGE_TIME ) * LCANNON_TOTAL_CHARGE; 
     
    672691        client->ps.stats[ STAT_MISC ] = LCANNON_TOTAL_CHARGE; 
    673692 
    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; 
    676695    } 
    677696 
     
    695714 
    696715          // 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++ ) 
    698717          { 
    699718            if( i < level.numBuildablesForRemoval ) 
    700               client->ps.misc[ i ] = level.markedBuildables[ i ]->s.number; 
     719              client->ps.powerups[ i ] = level.markedBuildables[ i ]->s.number; 
    701720            else 
    702               client->ps.misc[ i ] = 0; 
     721              client->ps.powerups[ i ] = 0; 
    703722          } 
    704723        } 
    705724        else 
    706725        { 
    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; 
    709728        } 
    710729 
     730      case WP_BLASTER: 
    711731        //update build timer 
    712732        if( client->ps.stats[ STAT_MISC ] > 0 ) 
     
    732752        { 
    733753          ent->client->medKitHealthToRestore--; 
    734           ent->health++; 
     754          do_health( ent,1 ); 
    735755        } 
    736756        else 
     
    747767          { 
    748768            ent->client->medKitHealthToRestore--; 
    749             ent->health++; 
     769            do_health( ent,1 ); 
    750770 
    751771            client->medKitIncrementTime = level.time + 
     
    762782  { 
    763783    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    } 
    764812 
    765813    //client is poison clouded 
     
    825873      if( ent->health > 0 && ent->health < client->ps.stats[ STAT_MAX_HEALTH ] && 
    826874          ( 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 ); 
    828876 
    829877      if( ent->health > client->ps.stats[ STAT_MAX_HEALTH ] ) 
     
    852900    if( client->ps.weapon == WP_ALEVEL3_UPG ) 
    853901    { 
    854       int maxAmmo; 
     902      int ammo, maxAmmo; 
    855903 
    856904      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      } 
    860912    } 
    861913  } 
     
    13301382    msec = 200; 
    13311383 
    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; 
    13331388 
    13341389  if( pmove_msec.integer < 8 ) 
     
    13611416    SpectatorThink( ent, ucmd ); 
    13621417    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     } 
    13631431  } 
    13641432 
     
    14741542    } 
    14751543 
    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    { 
    14781547      BG_DeactivateUpgrade( UP_JETPACK, client->ps.stats ); 
     1548 
     1549      trap_SendServerCommand( ent - g_entities, 
     1550        "print \"Your jetpack is out of power\n\"" ); 
     1551    } 
    14791552  } 
    14801553 
     
    17661839      cl = &level.clients[ clientNum ]; 
    17671840 
    1768       if( cl->pers.connected == CON_CONNECTED && cl->sess.sessionTeam != TEAM_SPECTATOR ) 
     1841      if( cl->pers.connected == CON_CONNECTED ) 
    17691842      { 
    17701843        flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) | 
     
    17761849        ent->client->ps.ping = ping; 
    17771850        ent->client->ps.pm_flags |= PMF_FOLLOW; 
     1851        ent->client->ps.pm_flags &= ~PMF_QUEUED; 
    17781852        ent->client->ps.eFlags = flags; 
    17791853      } 
     
    17941868{ 
    17951869  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   } 
    17961877 
    17971878  if( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) 
     
    18391920} 
    18401921 
    1841  
     1922void 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  
    202202 
    203203  // 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 
    205205  if( ent->client->pers.teamSelection == PTE_ALIENS ) 
    206206  { 
     
    270270    // see G_UnlaggedDetectCollisions(), this is the inverse of that. 
    271271    // 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 
    273273    // blocking or server-side Pmove() from reaching it 
    274274    if( other->client && other->client->unlaggedCalc.used ) 
     
    10541054 G_UnlaggedStore 
    10551055 
    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[]. 
    10581058 This data is used by G_UnlaggedCalc() 
    10591059============== 
     
    10641064  gentity_t *ent; 
    10651065  unlagged_t *save; 
    1066    
     1066 
    10671067  if( !g_unlagged.integer ) 
    10681068    return; 
    1069   level.unlaggedIndex++;  
     1069  level.unlaggedIndex++; 
    10701070  if( level.unlaggedIndex >= MAX_UNLAGGED_MARKERS ) 
    10711071    level.unlaggedIndex = 0; 
    10721072 
    10731073  level.unlaggedTimes[ level.unlaggedIndex ] = level.time; 
    1074   
     1074 
    10751075  for( i = 0; i < level.maxclients; i++ ) 
    10761076  { 
    10771077    ent = &g_entities[ i ]; 
    10781078    save = &ent->client->unlaggedHist[ level.unlaggedIndex ]; 
    1079     save->used = qfalse;  
     1079    save->used = qfalse; 
    10801080    if( !ent->r.linked || !( ent->r.contents & CONTENTS_BODY ) ) 
    10811081      continue; 
    10821082    if( ent->client->pers.connected != CON_CONNECTED ) 
    1083       continue;  
     1083      continue; 
    10841084    VectorCopy( ent->r.mins, save->mins ); 
    10851085    VectorCopy( ent->r.maxs, save->maxs ); 
     
    10921092============== 
    10931093 G_UnlaggedClear 
    1094   
     1094 
    10951095 Mark all unlaggedHist[] markers for this client invalid.  Useful for 
    10961096 preventing teleporting and death. 
     
    11241124  if( !g_unlagged.integer ) 
    11251125    return; 
    1126   
     1126 
    11271127  // clear any calculated values from a previous run 
    11281128  for( i = 0; i < level.maxclients; i++ ) 
     
    11561156  if( frameMsec > 0 ) 
    11571157  { 
    1158     lerp = ( float )( time - level.unlaggedTimes[ startIndex ] ) 
    1159       / ( float )frameMsec;  
    1160   } 
    1161    
     1158    lerp = ( float )( time - level.unlaggedTimes[ startIndex ] ) / 
     1159      ( float )frameMsec; 
     1160  } 
     1161 
    11621162  for( i = 0; i < level.maxclients; i++ ) 
    11631163  { 
     
    12001200  int i = 0; 
    12011201  gentity_t *ent; 
    1202    
     1202 
    12031203  if( !g_unlagged.integer ) 
    12041204    return; 
    1205    
     1205 
    12061206  for( i = 0; i < level.maxclients; i++ ) 
    12071207  { 
     
    12361236  gentity_t *ent; 
    12371237  unlagged_t *calc; 
    1238    
     1238 
    12391239  if( !g_unlagged.integer ) 
    12401240    return; 
    1241    
     1241 
    12421242  for( i = 0; i < level.maxclients; i++ ) 
    12431243  { 
     
    12601260 
    12611261      if( Distance( muzzle, calc->origin ) > range + maxRadius ) 
    1262         continue;  
     1262        continue; 
    12631263    } 
    12641264 
     
    18281828  gclient_t *cl; 
    18291829  int       clientNum, flags; 
     1830  int       score, ping; 
    18301831 
    18311832  // if we are doing a chase cam or a remote view, grab the latest info 
     
    18421843        flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) | 
    18431844          ( ent->client->ps.eFlags & ( EF_VOTED | EF_TEAMVOTED ) ); 
     1845        score = ent->client->ps.persistant[ PERS_SCORE ]; 
     1846        ping = ent->client->ps.ping; 
    18441847        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; 
    18461850        ent->client->ps.pm_flags |= PMF_FOLLOW; 
    18471851        ent->client->ps.pm_flags &= ~PMF_QUEUED; 
     1852        ent->client->ps.eFlags = flags; 
    18481853      } 
    18491854    } 
  • src/game/g_admin.c

    r120 r124  
    7676    }, 
    7777 
     78    {"info", G_admin_info, "H", 
     79      "read the server's information files", 
     80      "(^5subject^7)" 
     81    }, 
     82 
    7883    {"kick", G_admin_kick, "k", 
    7984      "kick a player with an optional reason", 
     
    8388    {"listadmins", G_admin_listadmins, "D", 
    8489      "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)" 
    8691    }, 
    8792 
     
    135140      "" 
    136141    }, 
     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    }, 
    137147 
    138148    {"rename", G_admin_rename, "N", 
     
    142152 
    143153    {"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)" 
    146156    }, 
    147157 
     
    156166    }, 
    157167 
     168    {"slap", G_admin_slap, "x", 
     169      "assert your authoritay!", 
     170      "[^3name|slot^7] (damage)" 
     171    }, 
     172 
    158173    {"spec999", G_admin_spec999, "P", 
    159174      "move 999 pingers to the spectator team", 
     
    177192      "unmute a muted player", 
    178193      "[^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]" 
    179200    } 
    180201  }; 
     
    189210g_admin_namelog_t *g_admin_namelog[ MAX_ADMIN_NAMELOGS ]; 
    190211 
    191 qboolean G_admin_permission( gentity_t *ent, char flag ) 
     212 
     213qboolean G_admin_guid_permission( char *guid, char flag ) 
    192214{ 
    193215  int i; 
     
    195217  char *flags; 
    196218 
    197   // console always wins 
    198   if( !ent ) 
    199     return qtrue; 
    200  
    201219  for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ ) 
    202220  { 
    203     if( !Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) ) 
     221    if( !Q_stricmp( guid, g_admin_admins[ i ]->guid ) ) 
    204222    { 
    205223      flags = g_admin_admins[ i ]->flags; 
     
    263281} 
    264282 
     283qboolean 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 
    265292qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len ) 
    266293{ 
     
    269296  char testName[ MAX_NAME_LENGTH ] = {""}; 
    270297  char name2[ MAX_NAME_LENGTH ] = {""}; 
     298  int alphaCount = 0; 
    271299 
    272300  G_SanitiseName( name, name2 ); 
     
    274302  if( !Q_stricmp( name2, "UnnamedPlayer" ) ) 
    275303    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  } 
    276311 
    277312  for( i = 0; i < level.maxclients; i++ ) 
     
    292327      return qfalse; 
    293328    } 
     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; 
    294355  } 
    295356 
     
    305366      Q_stricmp( ent->client->pers.guid, g_admin_admins[ i ]->guid ) ) 
    306367    { 
    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 ); 
    309370      return qfalse; 
    310371    } 
     
    561622  Q_strncpyz( g_admin_levels[ 3 ]->name, "^2Junior Admin", 
    562623    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 ) ); 
    564625 
    565626  Q_strncpyz( g_admin_levels[ 4 ]->name, "^3Senior Admin", 
    566627    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 ) ); 
    568629 
    569630  Q_strncpyz( g_admin_levels[ 5 ]->name, "^1Server Operator", 
     
    724785} 
    725786 
    726 static int admin_listadmins( gentity_t *ent, int start, char *search ) 
     787static int admin_listadmins( gentity_t *ent, int start, char *search, int minlevel ) 
    727788{ 
    728789  int drawn = 0; 
     
    784845    drawn < MAX_ADMIN_LISTITEMS; i++ ) 
    785846  { 
    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 ) ) 
    799853          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++ ) 
    803859        { 
    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 ); 
    805890          break; 
    806891        } 
    807892      } 
    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    } 
    837901  } 
    838902  ADMBP_end(); 
     
    9551019    if( admin_command_permission( ent, cmd ) ) 
    9561020    { 
     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      } 
    9571035      trap_SendConsoleCommand( EXEC_APPEND, g_admin_commands[ i ]->exec ); 
    9581036      admin_log( ent, cmd, skip ); 
     
    14701548    ADMP( "^3!setlevel:^7 more than one match.  Use the admin number " 
    14711549      "instead:\n" ); 
    1472     admin_listadmins( ent, 0, name ); 
     1550    admin_listadmins( ent, 0, name, 0 ); 
    14731551    return qfalse; 
    14741552  } 
     
    15301608  char *ip, 
    15311609  int seconds, 
    1532   char *reason ) 
     1610  char *reason, 
     1611  int index ) 
    15331612{ 
    15341613  g_admin_ban_t *b = NULL; 
     
    15651644  else 
    15661645    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; 
    15751656  g_admin_bans[ i ] = b; 
    15761657  return qtrue; 
    15771658} 
    15781659 
     1660qboolean 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} 
    15791779 
    15801780qboolean G_admin_kick( gentity_t *ent, int skiparg ) 
     
    16151815      vic->client->pers.guid, 
    16161816      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 ); 
    16181819    if( g_admin.string[ 0 ] ) 
    16191820      admin_writeconfig(); 
     
    16411842  char duration[ 32 ]; 
    16421843  int modifier = 1; 
    1643   int logmatch = -1, logmatches = 0; 
     1844  int logmatch = -1, logmatches = 0, banmatches = 0, banmatch = -1; 
    16441845  int i, j; 
    16451846  qboolean exactmatch = qfalse; 
     
    16471848  char s2[ MAX_NAME_LENGTH ]; 
    16481849  char guid_stub[ 9 ]; 
     1850  qtime_t qt; 
     1851  int t; 
    16491852 
    16501853  if( G_admin_permission( ent, ADMF_CAN_PERM_BAN ) && 
     
    16701873  G_SanitiseName( search, s2 ); 
    16711874  G_SayArgv( 2 + skiparg, secs, sizeof( secs ) ); 
     1875 
     1876  t = trap_RealTime( &qt ); 
    16721877 
    16731878  // support "w" (weeks), "d" (days), "h" (hours), and "m" (minutes) modifiers 
     
    17321937  { 
    17331938    // 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; 
    17361941 
    17371942    if( !Q_stricmp( g_admin_namelog[ i ]->ip, search ) ) 
     
    17601965    return qfalse; 
    17611966  } 
    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 ) 
    17631993  { 
    17641994    ADMBP_begin(); 
     
    17862016      } 
    17872017    } 
     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    } 
    17882032    ADMBP_end(); 
    17892033    return qfalse; 
    17902034  } 
    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 
    18202050    AP( va( "print \"^3!ban:^7 %s^7 has been banned by %s^7 " 
    18212051      "duration: %s, reason: %s\n\"", 
    1822       g_admin_namelog[ logmatch ]->name[ 0 ], 
     2052      g_admin_bans[banmatch]->name, 
    18232053      ( ent ) ? ent->client->pers.netname : "console", 
    18242054      duration, 
    18252055      ( *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" ) ); 
    18262114    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  } 
    18422117} 
    18432118 
     
    21022377  qboolean numeric = qtrue; 
    21032378  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  } 
    21042391 
    21052392  for( i = 0; i < MAX_ADMIN_ADMINS && g_admin_admins[ i ]; i++ ) 
    21062393  { 
    2107     if( g_admin_admins[ i ]->level == 0 ) 
    2108       continue; 
    2109     found++; 
     2394    if( g_admin_admins[ i ]->level >= minlevel ) 
     2395      found++; 
    21102396  } 
    21112397  if( !found ) 
    21122398  { 
    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 ) 
    21182411  { 
    21192412    G_SayArgv( 1 + skiparg, s, sizeof( s ) ); 
     
    21392432    start = 0; 
    21402433 
    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 ); 
    21482435 
    21492436  if( search[ 0 ] ) 
    21502437  { 
    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    } 
    21532448  } 
    21542449  else 
    21552450  { 
    21562451    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, 
    21582454      ( found ) ? ( start + 1 ) : 0, 
    21592455      ( ( start + MAX_ADMIN_LISTITEMS ) > found ) ? 
     
    21622458    if( ( start + MAX_ADMIN_LISTITEMS ) < found ) 
    21632459    { 
    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      } 
    21662470    } 
    21672471    ADMBP( "\n" ); 
     
    25232827        if( !G_admin_permission( ent, g_admin_cmds[ i ].flag[ 0 ] ) ) 
    25242828        { 
    2525           ADMBP( va( "^3!help: ^7you have no permission to use '%s'\n", 
     2829          ADMBP( va( "^3!help: ^7you do not have permission to use '%s'\n", 
    25262830                   g_admin_cmds[ i ].keyword ) ); 
    25272831          ADMBP_end(); 
     
    25632867} 
    25642868 
     2869qboolean 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 
     2903void 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 
    25652956qboolean G_admin_admintest( gentity_t *ent, int skiparg ) 
    25662957{ 
     
    27013092} 
    27023093 
     3094 
     3095 
     3096qboolean 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 
     3128qboolean 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 
    27033161qboolean G_admin_rename( gentity_t *ent, int skiparg ) 
    27043162{ 
     
    27463204  trap_SetUserinfo( pids[ 0 ], userinfo ); 
    27473205  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" ) ); 
    27523211  return qtrue; 
    27533212} 
     
    27563215{ 
    27573216  char layout[ MAX_CVAR_VALUE_STRING ] = { "" }; 
     3217  char teampref[ MAX_CVAR_VALUE_STRING ] = { "" }; 
     3218  int i; 
     3219  gclient_t *cl; 
    27583220 
    27593221  if( G_SayArgc( ) > 1 + skiparg ) 
     
    27643226    G_SayArgv( skiparg + 1, layout, sizeof( layout ) ); 
    27653227 
    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\"", 
    27813293          ( ent ) ? ent->client->pers.netname : "console", 
    2782           ( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "" ) ); 
     3294          ( layout[ 0 ] ) ? va( "(forcing layout '%s')", layout ) : "", 
     3295          teampref ) ); 
    27833296  return qtrue; 
    27843297} 
     
    28353348    if( g_admin_namelog[ i ]->slot > -1 ) 
    28363349       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 ) ? 
    28393352        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" : " " ) ) ); 
    28413358    for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 
    28423359      g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 
     
    29413458} 
    29423459 
     3460//!Warn by Gate (Daniel Evans)  
     3461qboolean 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 
    29433507/* 
    29443508================ 
  • src/game/g_admin.c

    r122 r124  
    1212The functionality of this code mimics the behaviour of the currently 
    1313inactive project shrubet (http://www.etstats.com/shrubet/index.php?ver=2) 
    14 by Ryan Mannion.   However, shrubet was a closed-source project and  
     14by Ryan Mannion.   However, shrubet was a closed-source project and 
    1515none of it's code has been copied, only it's functionality. 
    1616 
     
    3737 
    3838// note: list ordered alphabetically 
    39 g_admin_cmd_t g_admin_cmds[ ] =  
     39g_admin_cmd_t g_admin_cmds[ ] = 
    4040  { 
    4141    {"admintest", G_admin_admintest, "a", 
     
    4848      "[^3name|slot#^7]" 
    4949    }, 
    50      
     50 
    5151    {"allready", G_admin_allready, "y", 
    5252      "makes everyone ready in intermission", 
     
    8585      "(^5reason^7)" 
    8686    }, 
    87      
     87 
    8888    {"listadmins", G_admin_listadmins, "D", 
    8989      "display a list of all server admins and their levels", 
    9090      "(^5name|start admin#^7) (^5minimum level to display^7)" 
    9191    }, 
    92      
     92 
    9393    {"listlayouts", G_admin_listlayouts, "L", 
    9494      "display a list of all available layouts for a map", 
     
    100100      "" 
    101101    }, 
    102      
     102 
    103103    {"lock", G_admin_lock, "K", 
    104104      "lock a team to prevent anyone from joining it", 
    105105      "[^3a|h^7]" 
    106106    }, 
    107      
     107 
    108108    {"map", G_admin_map, "M", 
    109109      "load a map (and optionally force layout)", 
     
    115115      "[^3name|slot#^7]" 
    116116    }, 
    117      
     117 
    118118    {"namelog", G_admin_namelog, "e", 
    119119      "display a list of names used by recently connected players", 
     
    183183      "[^3ban slot#^7]" 
    184184    }, 
    185      
     185 
    186186    {"unlock", G_admin_unlock, "K", 
    187187      "unlock a locked team", 
     
    232232            if( *flags == flag ) 
    233233              return qfalse; 
    234             else if( *flags == '+' ) 
     234            if( *flags == '+' ) 
    235235              break; 
    236236          } 
     
    244244          } 
    245245          // 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 
    247247          // 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 ); 
    256249        } 
    257250        flags++; 
     
    277270          } 
    278271          // 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 
    280273          // 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 ); 
    289275        } 
    290276        flags++; 
     
    314300  G_SanitiseName( name, name2 ); 
    315301 
    316   if( !Q_stricmp( name2, "UnnamedPlayer" ) )  
     302  if( !Q_stricmp( name2, "UnnamedPlayer" ) ) 
    317303    return qtrue; 
    318304 
     
    327313  { 
    328314    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 ) 
    332316      continue; 
    333     } 
    334317 
    335318    // can rename ones self to the same name using different colors 
     
    459442  fileHandle_t f; 
    460443  int len, i, j; 
    461   qtime_t qt; 
    462444  int t; 
    463445  char levels[ MAX_STRING_CHARS ] = {""}; 
     
    469451    return; 
    470452  } 
    471   t = trap_RealTime( &qt ); 
     453  t = trap_RealTime( NULL ); 
    472454  len = trap_FS_FOpenFile( g_admin.string, &f, FS_WRITE ); 
    473455  if( len < 0 ) 
     
    510492    // if expires is 0, then it's a perm ban 
    511493    if( g_admin_bans[ i ]->expires != 0 && 
    512          ( g_admin_bans[ i ]->expires - t ) < 1 ) 
     494      ( g_admin_bans[ i ]->expires - t ) < 1 ) 
    513495      continue; 
    514496 
     
    554536static void admin_readconfig_string( char **cnf, char *s, int size ) 
    555537{ 
    556   char * t; 
     538  char *t; 
    557539 
    558540  //COM_MatchToken(cnf, "="); 
     
    572554  while( t[ 0 ] ) 
    573555  { 
    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 ) ) 
    576558    { 
    577559 
     
    588570static void admin_readconfig_int( char **cnf, int *v ) 
    589571{ 
    590   char * t; 
     572  char *t; 
    591573 
    592574  //COM_MatchToken(cnf, "="); 
     
    610592static void admin_default_levels( void ) 
    611593{ 
    612   g_admin_level_t * l; 
     594  g_admin_level_t *l; 
    613595  int i; 
    614596 
     
    640622  Q_strncpyz( g_admin_levels[ 3 ]->name, "^2Junior Admin", 
    641623    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 
    644626  Q_strncpyz( g_admin_levels[ 4 ]->name, "^3Senior Admin", 
    645627    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 
    648630  Q_strncpyz( g_admin_levels[ 5 ]->name, "^1Server Operator", 
    649631    sizeof( l->name ) ); 
     
    687669  if( !ent ) 
    688670    return qtrue; 
    689   level  = ent->client->pers.adminLevel; 
     671  level = ent->client->pers.adminLevel; 
    690672  for( i = 0; i < MAX_ADMIN_COMMANDS && g_admin_commands[ i ]; i++ ) 
    691673  { 
     
    718700 
    719701  if( !g_adminLog.string[ 0 ] ) 
    720     return ; 
     702    return; 
    721703 
    722704 
     
    725707  { 
    726708    G_Printf( "admin_log: error could not open %s\n", g_adminLog.string ); 
    727     return ; 
     709    return; 
    728710  } 
    729711 
     
    815797  int l = 0; 
    816798  qboolean dup = qfalse; 
    817    
     799 
    818800  ADMBP_begin(); 
    819801 
     
    825807    if( vic->client && vic->client->pers.connected != CON_CONNECTED ) 
    826808      continue; 
    827      
     809 
    828810    l = vic->client->pers.adminLevel; 
    829811 
     
    835817      guid_stub[ j ] = vic->client->pers.guid[ j + 24 ]; 
    836818    guid_stub[ j ] = '\0'; 
    837    
    838     lname[ 0 ] = '\0';  
     819 
     820    lname[ 0 ] = '\0'; 
    839821    Q_strncpyz( lname_fmt, "%s", sizeof( lname_fmt ) ); 
    840822    for( j = 0; j < MAX_ADMIN_LEVELS && g_admin_levels[ j ]; j++ ) 
     
    860842  } 
    861843 
    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; 
    871854       
    872        // verify we don't have the same guid/name pair in connected players 
    873        // since we don't want to draw the same player twice 
    874        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'; 
    894877     
    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  } 
    918902  ADMBP_end(); 
    919903  return drawn; 
     
    948932  char *guid, *ip; 
    949933  int i; 
    950   qtime_t qt; 
    951934  int t; 
    952   
    953   *reason = '\0';  
    954   t  = trap_RealTime( &qt );  
     935 
     936  *reason = '\0'; 
     937  t = trap_RealTime( NULL ); 
    955938  if( !*userinfo ) 
    956939    return qfalse; 
     
    978961        duration 
    979962      ); 
    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 ); 
    981964      return qtrue; 
    982965    } 
     
    994977        duration 
    995978      ); 
    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 ); 
    997980      return qtrue; 
    998981    } 
     
    11121095    } 
    11131096 
    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++ ) 
    11191102      { 
    11201103        G_SanitiseName( g_admin_namelog[ i ]->name[ j ], n2 ); 
    1121         if( !Q_stricmp( n1, n2 ) )  
     1104        if( !Q_stricmp( n1, n2 ) ) 
    11221105          break; 
    11231106      } 
     
    11421125  namelog = G_Alloc( sizeof( g_admin_namelog_t ) ); 
    11431126  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++ ) 
    11451128    namelog->name[ j ][ 0 ] = '\0'; 
    11461129  Q_strncpyz( namelog->ip, client->pers.ip, sizeof( namelog->ip ) ); 
     
    11541137qboolean G_admin_readconfig( gentity_t *ent, int skiparg ) 
    11551138{ 
    1156   g_admin_level_t * l = NULL; 
     1139  g_admin_level_t *l = NULL; 
    11571140  g_admin_admin_t *a = NULL; 
    11581141  g_admin_ban_t *b = NULL; 
     
    11761159  } 
    11771160 
    1178   len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ) ; 
     1161  len = trap_FS_FOpenFile( g_admin.string, &f, FS_READ ); 
    11791162  if( len < 0 ) 
    11801163  { 
     
    13781361    else if( !Q_stricmp( t, "[command]" ) ) 
    13791362    { 
    1380       if( bc >= MAX_ADMIN_COMMANDS ) 
     1363      if( cc >= MAX_ADMIN_COMMANDS ) 
    13811364        return qfalse; 
    13821365      c = G_Alloc( sizeof( g_admin_command_t ) ); 
     
    13901373  } 
    13911374  if( level_open ) 
    1392   { 
    1393  
    13941375    g_admin_levels[ lc++ ] = l; 
    1395   } 
    13961376  if( admin_open ) 
    13971377    g_admin_admins[ ac++ ] = a; 
     
    14091389    char n[ MAX_NAME_LENGTH ] = {""}; 
    14101390    int i = 0; 
    1411   
    1412     // max printable name length for formatting  
     1391 
     1392    // max printable name length for formatting 
    14131393    for( i = 0; i < MAX_ADMIN_LEVELS && g_admin_levels[ i ]; i++ ) 
    14141394    { 
     
    14241404{ 
    14251405  qtime_t qt; 
    1426   int t; 
    1427  
    1428   t = trap_RealTime( &qt ); 
     1406 
     1407  trap_RealTime( &qt ); 
    14291408  ADMP( va( "^3!time: ^7local time is %02i:%02i:%02i\n", 
    14301409    qt.tm_hour, qt.tm_min, qt.tm_sec ) ); 
     
    14591438  l = atoi( lstr ); 
    14601439  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 ] ) ) 
    14641443    { 
    14651444      numeric = qfalse; 
     
    14961475  } 
    14971476 
    1498   if( numeric  && id >= 0 && id < level.maxclients ) 
     1477  if( numeric && id >= 0 && id < level.maxclients ) 
    14991478    vic = &g_entities[ id ]; 
    15001479 
    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  { 
    15041482    Q_strncpyz( adminname, vic->client->pers.netname, sizeof( adminname ) ); 
    15051483    Q_strncpyz( guid, vic->client->pers.guid, sizeof( guid ) ); 
     
    15441522            continue; 
    15451523          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 ) ) 
    15481526          { 
    15491527            dup = qtrue; 
     
    15661544    return qfalse; 
    15671545  } 
    1568   else if( matches > 1 ) 
     1546  if( matches > 1 ) 
    15691547  { 
    15701548    ADMP( "^3!setlevel:^7 more than one match.  Use the admin number " 
     
    16111589  } 
    16121590 
    1613   AP( va(  
     1591  AP( va( 
    16141592    "print \"^3!setlevel: ^7%s^7 was given level %d admin rights by %s\n\"", 
    16151593    adminname, l, ( ent ) ? ent->client->pers.netname : "console" ) ); 
    16161594  if( vic ) 
    16171595    vic->client->pers.adminLevel = l; 
    1618    
     1596 
    16191597  if( !g_admin.string[ 0 ] ) 
    16201598    ADMP( "^3!setlevel: ^7WARNING g_admin not set, not saving admin record " 
     
    18421820      admin_writeconfig(); 
    18431821  } 
    1844    
     1822 
    18451823  trap_SendServerCommand( pids[ 0 ], 
    18461824    va( "disconnect \"You have been kicked.\n%s^7\nreason:\n%s\"", 
     
    19101888    else if( secs[ lastchar ] == 'm' ) 
    19111889      modifier = 60; 
    1912     else if( secs[ lastchar ] < '0' || secs[ lastchar ] > '9' ) 
     1890    else if( !isdigit( secs[ lastchar ] ) ) 
    19131891      secs[ lastchar ] = '\0'; 
    19141892  } 
     
    19451923      continue; 
    19461924 
    1947     if( !Q_stricmp( va( "%d", g_admin_namelog[ i ]->slot ), s2 ) ) 
     1925    if( !Q_stricmp( va( "%d", g_admin_namelog[ i ]->slot ), search ) ) 
    19481926    { 
    19491927      logmatches = 1; 
     
    19621940        continue; 
    19631941 
    1964     if( !Q_stricmp( g_admin_namelog[ i ]->ip, s2 ) ) 
     1942    if( !Q_stricmp( g_admin_namelog[ i ]->ip, search ) ) 
    19651943    { 
    19661944      logmatches = 1; 
     
    19691947      break; 
    19701948    } 
    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 ); 
    19741953      if( strstr( n2, s2 ) ) 
    19751954      { 
    19761955        if( logmatch != i ) 
    19771956          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 
    19831968  // 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; 
    19861973      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      { 
    19881978        banmatches++; 
    19891979        banmatch = i; 
    19901980      } 
    1991       if (!Q_stricmp (va( "%db", i), s2)) { 
     1981      if (!Q_stricmp (va( "%db", i), s2 ) ) 
     1982      { 
    19921983        banmatches = 1; 
    19931984        banmatch = i; 
     
    20081999        guid_stub[ j ] = g_admin_namelog[ i ]->guid[ j + 24 ]; 
    20092000      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 ); 
    20142005        if( strstr( n2, s2 ) ) 
    20152006        { 
     
    20172008            ADMBP( "^3" ); 
    20182009          ADMBP( va( "%-2s (*%s) %15s ^7'%s^7'\n", 
    2019            (g_admin_namelog[ i ]->slot > -1) ? 
     2010           ( g_admin_namelog[ i ]->slot > -1 ) ? 
    20202011             va( "%d", g_admin_namelog[ i ]->slot ) : "-", 
    20212012           guid_stub, 
     
    20652056 
    20662057    return qtrue;  
    2067   } else if (!logmatches) { 
     2058  } 
     2059  else if (!logmatches) 
     2060  { 
    20682061 
    20692062    ADMP( "^3!ban: ^7no player found by that name, IP, or slot number\n" ); 
    20702063    return qfalse; 
    20712064     
    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  } 
    20932066  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, 
    21012078      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" ) ); 
    21052114    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; 
    21212115 
    21222116  } 
     
    21272121  int bnum; 
    21282122  char bs[ 4 ]; 
    2129   qtime_t qt; 
    2130   int t; 
    2131  
    2132   t = trap_RealTime( &qt ); 
     2123 
    21332124  if( G_SayArgc() < 2 + skiparg ) 
    21342125  { 
     
    21482139    return qfalse; 
    21492140  } 
    2150   g_admin_bans[ bnum -1 ]->expires = t; 
     2141  g_admin_bans[ bnum - 1 ]->expires = trap_RealTime( NULL ); 
    21512142  AP( va( "print \"^3!unban: ^7ban #%d for %s^7 has been removed by %s\n\"", 
    21522143          bnum, 
     
    22182209  char map[ MAX_QPATH ]; 
    22192210  char layout[ MAX_QPATH ] = { "" }; 
    2220    
     2211 
    22212212  if( G_SayArgc( ) < 2 + skiparg ) 
    22222213  { 
     
    23132304            ( ent ) ? ent->client->pers.netname : "console" ) ); 
    23142305  } 
    2315   ClientUserinfoChanged( pids[ 0 ] ); 
    23162306  return qtrue; 
    23172307} 
     
    23762366      ( ent ) ? ent->client->pers.netname : "console" ) ); 
    23772367  } 
    2378   ClientUserinfoChanged( pids[ 0 ] ); 
    23792368  return qtrue; 
    23802369} 
     
    23832372{ 
    23842373  int i, found = 0; 
    2385   qtime_t qt; 
    2386   int t; 
    23872374  char search[ MAX_NAME_LENGTH ] = {""}; 
    23882375  char s[ MAX_NAME_LENGTH ] = {""}; 
     
    23922379  int minlevel = 1; 
    23932380 
    2394   t = trap_RealTime( &qt ); 
    2395    
    23962381  if( G_SayArgc() == 3 + skiparg ) 
    23972382  { 
     
    24282413    for( i = 0; i < sizeof( s ) && s[ i ]; i++ ) 
    24292414    { 
    2430       if( s[ i ] >= '0' && s[ i ] <= '9' ) 
     2415      if( isdigit( s[ i ] ) ) 
    24312416        continue; 
    2432       numeric = qfalse;  
    2433     } 
    2434     if( numeric )  
     2417      numeric = qfalse; 
     2418    } 
     2419    if( numeric ) 
    24352420    { 
    24362421      start = atoi( s ); 
     
    24982483  char layout[ MAX_QPATH ] = { "" }; 
    24992484  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 ) ); 
    25032488  else 
    25042489    trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); 
    2505    
     2490 
    25062491  count = G_LayoutList( map, list, sizeof( list ) ); 
    25072492  ADMBP_begin( ); 
     
    25452530 
    25462531  ADMBP_begin(); 
    2547   ADMBP( va( "^3!listplayers^7: %d players connected:\n", 
     2532  ADMBP( va( "^3!listplayers: ^7%d players connected:\n", 
    25482533    level.numConnectedClients ) ); 
    25492534  for( i = 0; i < level.maxclients; i++ ) 
     
    25952580      if( !Q_stricmp( g_admin_admins[ j ]->guid, p->pers.guid ) ) 
    25962581      { 
    2597  
    25982582        // 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 ) ) 
    26002584        { 
    26012585          break; 
     
    26292613    } 
    26302614 
    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    } 
    26452641  } 
    26462642  ADMBP_end(); 
     
    26512647{ 
    26522648  int i, found = 0; 
    2653   qtime_t qt; 
    26542649  int t; 
    26552650  char duration[ 32 ]; 
     
    26662661  char n2[ MAX_NAME_LENGTH ] = {""}; 
    26672662 
    2668   t = trap_RealTime( &qt ); 
     2663  t = trap_RealTime( NULL ); 
    26692664 
    26702665  for( i = 0; i < MAX_ADMIN_BANS && g_admin_bans[ i ]; i++ ) 
    26712666  { 
    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 ) 
    26742669    { 
    26752670      continue; 
     
    26922687    start = 0; 
    26932688 
    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++ ) 
    26962691  { 
    26972692    G_DecolorString( g_admin_bans[ i ]->name, n1 ); 
     
    27112706  } 
    27122707  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 ) 
    27182713      continue; 
    27192714 
     
    27382733    Com_sprintf( name_fmt, sizeof( name_fmt ), "%%%is", 
    27392734      ( 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 ); 
    27412736 
    27422737    G_DecolorString( g_admin_bans[ i ]->banner, n2 ); 
    27432738    Com_sprintf( banner_fmt, sizeof( banner_fmt ), "%%%is", 
    27442739      ( 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 ); 
    27462741 
    27472742    ADMBP( va( "%4i %s^7 %-15s %-8s %s^7 %-10s\n     \\__ %s\n", 
     
    30253020  } 
    30263021  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" ) ); 
    30283023  return qtrue; 
    30293024} 
     
    30343029  if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] ) 
    30353030  { 
    3036     ADMP( "^3!cancelvote^7: no vote in progress\n" ); 
     3031    ADMP( "^3!cancelvote: ^7no vote in progress\n" ); 
    30373032    return qfalse; 
    30383033  } 
     
    30553050  if(!level.voteTime && !level.teamVoteTime[ 0 ] && !level.teamVoteTime[ 1 ] ) 
    30563051  { 
    3057     ADMP( "^3!passvote^7: no vote in progress\n" ); 
     3052    ADMP( "^3!passvote: ^7no vote in progress\n" ); 
    30583053    return qfalse; 
    30593054  } 
     
    30903085      G_ChangeTeam( vic, PTE_NONE ); 
    30913086      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", 
    30933088        vic->client->pers.netname ) ); 
    30943089    } 
     
    31893184    return qfalse; 
    31903185  } 
    3191   victim = &g_entities[ pids[ 0 ] ] ; 
     3186  victim = &g_entities[ pids[ 0 ] ]; 
    31923187  if( !admin_higher( ent, victim ) ) 
    31933188  { 
     
    33343329    { 
    33353330      found = qfalse; 
    3336       for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES &&  
     3331      for( j = 0; j < MAX_ADMIN_NAMELOG_NAMES && 
    33373332        g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 
    33383333      { 
     
    33613356      ( g_entities[ g_admin_namelog[ i ]->slot ].client && 
    33623357        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 && 
    33643359      g_admin_namelog[ i ]->name[ j ][ 0 ]; j++ ) 
    33653360    { 
    33663361      ADMBP( va( " '%s^7'", g_admin_namelog[ i ]->name[ j ] ) ); 
    33673362    } 
    3368     ADMBP( "\n" );  
    3369   }  
     3363    ADMBP( "\n" ); 
     3364  } 
    33703365  ADMBP( va( "^3!namelog:^7 %d recent clients found\n", printed ) ); 
    33713366  ADMBP_end(); 
     
    34013396      return qfalse; 
    34023397    } 
    3403     else 
    3404       level.alienTeamLocked = qtrue; 
     3398    level.alienTeamLocked = qtrue; 
    34053399  } 
    34063400  else if( team == PTE_HUMANS ) { 
     
    34103404      return qfalse; 
    34113405    } 
    3412     else 
    3413       level.humanTeamLocked = qtrue; 
     3406    level.humanTeamLocked = qtrue; 
    34143407  } 
    34153408 
     
    34183411    ( ent ) ? ent->client->pers.netname : "console" ) ); 
    34193412  return qtrue; 
    3420 }  
     3413} 
    34213414 
    34223415qboolean G_admin_unlock( gentity_t *ent, int skiparg ) 
     
    34403433    return qfalse; 
    34413434  } 
    3442    
     3435 
    34433436  if( team == PTE_ALIENS ) 
    34443437  { 
     
    34483441      return qfalse; 
    34493442    } 
    3450     else 
    3451       level.alienTeamLocked = qfalse; 
     3443    level.alienTeamLocked = qfalse; 
    34523444  } 
    34533445  else if( team == PTE_HUMANS ) { 
     
    34573449      return qfalse; 
    34583450    } 
    3459     else 
    3460       level.humanTeamLocked = qfalse; 
     3451    level.humanTeamLocked = qfalse; 
    34613452  } 
    34623453 
     
    34653456    ( ent ) ? ent->client->pers.netname : "console" ) ); 
    34663457  return qtrue; 
    3467 }  
     3458} 
    34683459 
    34693460//!Warn by Gate (Daniel Evans)  
     
    35243515void G_admin_print( gentity_t *ent, char *m ) 
    35253516{ 
    3526  
    35273517  if( ent ) 
    35283518    trap_SendServerCommand( ent - level.gentities, va( "print \"%s\"", m ) ); 
     
    35303520  { 
    35313521    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 ); 
    35343529  } 
    35353530} 
  • src/game/g_admin.h

    r120 r124  
    4242#define MAX_ADMIN_BAN_REASON 50 
    4343 
     44 
     45#define ADM_NEW_BAN -1 
     46 
    4447/* 
    4548 * 1 - cannot be vote kicked, vote muted 
     
    7174#define ADMF_IMMUTABLE '!' 
    7275#define ADMF_INCOGNITO '@' 
     76#define ADMF_ADMINCHAT '?' 
     77#define ADMF_PINGOVERRIDE '%' 
     78 
     79#define ADMF_VIP '#' 
    7380#define ADMF_SEESFULLLISTPLAYERS '$' 
    7481 
     
    136143g_admin_namelog_t; 
    137144 
     145qboolean G_admin_autoregister( gentity_t *ent ); 
    138146qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen ); 
    139147qboolean G_admin_cmd_check( gentity_t *ent, qboolean say ); 
    140148qboolean G_admin_readconfig( gentity_t *ent, int skiparg ); 
    141149qboolean G_admin_permission( gentity_t *ent, char flag ); 
     150qboolean G_admin_guid_permission( char *guid, char flag ); 
    142151qboolean G_admin_name_check( gentity_t *ent, char *name, char *err, int len ); 
    143152void G_admin_namelog_update( gclient_t *ent, qboolean disconnect ); 
     
    164173qboolean G_admin_passvote( gentity_t *ent, int skiparg ); 
    165174qboolean G_admin_spec999( gentity_t *ent, int skiparg ); 
     175qboolean G_admin_register( gentity_t *ent, int skiparg ); 
    166176qboolean G_admin_rename( gentity_t *ent, int skiparg ); 
    167177qboolean G_admin_restart( gentity_t *ent, int skiparg ); 
     
    170180qboolean G_admin_lock( gentity_t *ent, int skiparg ); 
    171181qboolean G_admin_unlock( gentity_t *ent, int skiparg ); 
     182qboolean G_admin_warn( gentity_t *ent, int skiparg ); 
     183qboolean G_admin_info( gentity_t *ent, int skiparg ); 
     184 
     185qboolean G_admin_slap( gentity_t *ent, int skiparg ); 
     186 
     187void G_admin_info_parse( char *unparsed, char *dest, int maxlength ); 
    172188 
    173189void G_admin_print( gentity_t *ent, char *m ); 
  • src/game/g_admin.h

    r50 r124  
    5959 * ! - admin commands cannot be used on them 
    6060 * @ - does not show up as an admin in !listplayers 
     61 * $ - sees all information in !listplayers  
    6162 */ 
    6263#define ADMF_IMMUNITY '1' 
     
    7778 
    7879#define ADMF_VIP '#' 
     80#define ADMF_SEESFULLLISTPLAYERS '$' 
    7981 
    8082#define MAX_ADMIN_LISTITEMS 20 
  • src/game/g_buildable.c

    r120 r124  
    152152 
    153153#define POWER_REFRESH_TIME  2000 
     154 
     155/* 
     156================ 
     157G_FindGenerator 
     158 
     159return the nearest generator, or NULL if isn't 
     160================ 
     161*/ 
     162gentity_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} 
    154216 
    155217/* 
     
    168230  int       minDistance = REPEATER_BASESIZE + 1; 
    169231  vec3_t    temp_v; 
     232  int       main_generator = 0; 
    170233 
    171234  if( self->biteam != BIT_HUMANS ) 
     
    184247 
    185248  //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++ ) 
    187250  { 
    188251    if( ent->s.eType != ET_BUILDABLE ) 
     
    199262      if( ent->s.modelindex == BA_H_REACTOR && distance <= REACTOR_BASESIZE ) 
    200263      { 
    201         self->parentNode = ent; 
    202         return qtrue; 
     264        main_generator = 1; 
     265        closestPower = ent; 
     266        minDistance = distance; 
    203267      } 
    204       if( distance < minDistance ) 
     268      else if( !main_generator && distance < minDistance && 
     269          ent->s.modelindex == BA_H_REPEATER && 
     270          distance <= REPEATER_BASESIZE ) 
    205271      { 
    206272        closestPower = ent; 
     
    403469  int       minDistance = 10000; 
    404470  vec3_t    temp_v; 
     471  int main_generator = 0; 
    405472 
    406473  //don't check for creep if flying through the air 
     
    421488        VectorSubtract( self->s.origin, ent->s.origin, temp_v ); 
    422489        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 ) 
    424498        { 
    425499          closestSpawn = ent; 
     
    664738          attacker->client->pers.netname ) ); 
    665739    } 
    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", 
    667741      attacker->client->ps.clientNum, self->s.modelindex, mod, 
    668742      attacker->client->pers.netname, 
     
    899973          attacker->client->pers.netname ) ); 
    900974    } 
    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", 
    902976      attacker->client->ps.clientNum, self->s.modelindex, mod, 
    903977      attacker->client->pers.netname, 
     
    9661040    } 
    9671041 
    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    } 
    9711054  } 
    9721055 
     
    13351418          attacker->client->pers.netname ) ); 
    13361419    } 
    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", 
    13381421      attacker->client->ps.clientNum, self->s.modelindex, mod, 
    13391422      attacker->client->pers.netname, 
     
    17111794} 
    17121795 
     1796 
     1797/* 
     1798================ 
     1799HSpawn_Activate 
     1800 
     1801Called when a human activates a spawn to teleport in Balance Mod 
     1802================ 
     1803*/ 
     1804void 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 
    17131856/* 
    17141857================ 
     
    18561999        self->enemy->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; 
    18572000 
    1858       self->enemy->health++; 
     2001      do_health( self->enemy,1 ); 
    18592002 
    18602003      //if they're completely healed, give them a medkit 
     
    18882031  float   accuracyTolerance, angularSpeed; 
    18892032 
    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 ) 
    18912040  { 
    18922041    //can't turn fast if grabbed 
     
    20902239    //find a dcc for self 
    20912240    self->dcced = G_FindDCC( self ); 
     2241    if (g_noBaseAttack.integer) 
     2242       self->dcced = qtrue;  
    20922243 
    20932244    //if the current target is not valid find a new one 
     
    23062457          attacker->client->pers.netname ) ); 
    23072458    } 
    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", 
    23092460      attacker->client->ps.clientNum, self->s.modelindex, mod, 
    23102461      attacker->client->pers.netname, 
     
    26952846    G_FreeEntity( ent ); 
    26962847  } 
     2848} 
     2849 
     2850/* 
     2851=============== 
     2852G_SufficientGeneratorBPAvailable 
     2853 
     2854Determine if nearest generator has enough build points can  
     2855be released for the buildable 
     2856=============== 
     2857*/ 
     2858static qboolean G_SufficientGeneratorBPAvailable( gentity_t*       generator, 
     2859                                         int             buildPoints ) 
     2860{ 
     2861  return generator->buildpoints >= buildPoints; 
    26972862} 
    26982863 
     
    30723237    reason = tempReason; 
    30733238 
     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 
    30743257  //this item does not fit here 
    30753258  if( reason == IBE_NONE && ( tr2.fraction < 1.0 || tr3.fraction < 1.0 ) ) 
     
    31523335  built->buildTime = built->s.time = level.time; 
    31533336 
    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) ) 
    31563339  { 
    31573340    built->health = BG_FindHealthForBuildable( buildable ); 
     
    31673350      built->think = ASpawn_Think; 
    31683351      built->pain = ASpawn_Pain; 
     3352      built->buildpoints = g_eggBuildPoints.integer; 
    31693353      break; 
    31703354 
     
    32043388      built->think = AOvermind_Think; 
    32053389      built->pain = ASpawn_Pain; 
     3390      built->buildpoints = g_overmindBuildPoints.integer; 
    32063391      break; 
    32073392 
     
    32163401      built->die = HSpawn_Die; 
    32173402      built->think = HSpawn_Think; 
     3403      built->use = HSpawn_Activate; 
    32183404      break; 
    32193405 
     
    32493435      built->use = HRepeater_Use; 
    32503436      built->powered = built->active = qtrue; 
     3437      built->buildpoints = g_reactorBuildPoints.integer; 
    32513438      break; 
    32523439 
     
    32563443      built->use = HRepeater_Use; 
    32573444      built->count = -1; 
     3445      built->buildpoints = g_repeaterBuildPoints.integer; 
    32583446      break; 
    32593447 
     
    33193507 
    33203508  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  } 
    33213521 
    33223522  return built; 
  • src/game/g_buildable.c

    r122 r124  
    9898      return NULL; 
    9999    } 
    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 ) 
    104103  { 
    105104    BG_FindBBoxForClass( PCL_HUMAN, cmins, cmaxs, NULL, NULL, NULL ); 
     
    122121      return NULL; 
    123122    } 
    124     else 
    125       return &g_entities[ tr.entityNum ]; 
     123    return &g_entities[ tr.entityNum ]; 
    126124  } 
    127125 
     
    141139  gentity_t *ent; 
    142140 
    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++ ) 
    144142  { 
    145143    if( ent->s.eType != ET_BUILDABLE ) 
     
    230228  gentity_t *closestPower = NULL; 
    231229  int       distance = 0; 
    232   int       minDistance = 10000; 
     230  int       minDistance = REPEATER_BASESIZE + 1; 
    233231  vec3_t    temp_v; 
    234232  int       main_generator = 0; 
     
    256254    //if entity is a power item calculate the distance to it 
    257255    if( ( ent->s.modelindex == BA_H_REACTOR || ent->s.modelindex == BA_H_REPEATER ) && 
    258         ent->spawned ) 
     256        ent->spawned && ent->powered ) 
    259257    { 
    260258      VectorSubtract( self->s.origin, ent->s.origin, temp_v ); 
     
    262260 
    263261      // 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 ) 
    267263      { 
    268264        main_generator = 1; 
     
    270266        minDistance = distance; 
    271267      } 
    272       else if( !main_generator && distance < minDistance && ent->powered && 
     268      else if( !main_generator && distance < minDistance && 
    273269          ent->s.modelindex == BA_H_REPEATER && 
    274270          distance <= REPEATER_BASESIZE ) 
     
    286282    return qtrue; 
    287283  } 
    288   else 
    289     return qfalse; 
     284  return qfalse; 
    290285} 
    291286 
     
    309304  if( G_FindPower( &dummy ) ) 
    310305    return dummy.parentNode; 
    311   else 
    312     return NULL; 
     306  return NULL; 
    313307} 
    314308 
     
    327321  if( ent ) 
    328322    return ent->s.modelindex; 
    329   else 
    330     return BA_NONE; 
     323  return BA_NONE; 
    331324} 
    332325 
     
    359352 
    360353  //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++ ) 
    362355  { 
    363356    if( ent->s.eType != ET_BUILDABLE ) 
     
    378371  } 
    379372 
    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; 
    387377} 
    388378 
     
    429419 
    430420  //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++ ) 
    432422  { 
    433423    if( ent->s.eType != ET_BUILDABLE ) 
     
    488478  if( ( self->parentNode == NULL ) || !self->parentNode->inuse ) 
    489479  { 
    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++ ) 
    491481    { 
    492482      if( ent->s.eType != ET_BUILDABLE ) 
     
    518508      return qtrue; 
    519509    } 
    520     else 
    521       return qfalse; 
     510    return qfalse; 
    522511  } 
    523512 
     
    829818void AOvermind_Think( gentity_t *self ) 
    830819{ 
    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; 
    836823 
    837824  VectorAdd( self->s.origin, range, maxs ); 
     
    841828  { 
    842829    //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 ); 
    855835    } 
    856836 
     
    12681248  } 
    12691249 
    1270   if( tr.fraction < 1.0f ) 
    1271     return qtrue; 
    1272   else 
    1273     return qfalse; 
     1250  return ( tr.fraction < 1.0f ); 
    12741251} 
    12751252 
     
    13291306      activator->client->ps.eFlags |= EF_NODRAW; 
    13301307      G_UnlaggedClear( activator ); 
     1308 
     1309      // Cancel pending suicides 
     1310      activator->suicideTime = 0; 
    13311311 
    13321312      activator->client->ps.stats[ STAT_STATE ] |= SS_HOVELING; 
     
    17501730  VectorSubtract( self->s.origin, range, mins ); 
    17511731 
    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 
    17551739    num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 
    17561740    for( i = 0; i < num; i++ ) 
     
    17601744      if( enemy->client && enemy->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 
    17611745      { 
    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  
    17661746        tent = G_TempEntity( enemy->s.pos.trBase, EV_TESLATRAIL ); 
    17671747 
     
    28042784  if( aMatches && !bMatches ) 
    28052785    return -1; 
    2806   else if( !aMatches && bMatches ) 
     2786  if( !aMatches && bMatches ) 
    28072787    return 1; 
    28082788 
     
    28122792  if( aMatches && !bMatches ) 
    28132793    return -1; 
    2814   else if( !aMatches && bMatches ) 
     2794  if( !aMatches && bMatches ) 
    28152795    return 1; 
    28162796 
     
    28252805    if( aMatches && !bMatches ) 
    28262806      return -1; 
    2827     else if( !aMatches && bMatches ) 
     2807    if( !aMatches && bMatches ) 
    28282808      return 1; 
    28292809 
     
    29382918 
    29392919    // 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++ ) 
    29412921    { 
    29422922      if( ent->s.eType != ET_BUILDABLE ) 
     
    29562936 
    29572937  // 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++ ) 
    29592939  { 
    29602940    if( ent->s.eType != ET_BUILDABLE ) 
     
    30713051 
    30723052  // Make sure we're not removing the last spawn 
    3073   if( ( remainingSpawns - spawnCount ) < 1 ) 
     3053  if( !g_cheats.integer && remainingSpawns > 0 && ( remainingSpawns - spawnCount ) < 1 ) 
    30743054    return bpError; 
    30753055 
     
    30773057  if( pointsYielded < buildPoints ) 
    30783058    return bpError; 
    3079   else 
    3080     return IBE_NONE; 
     3059  return IBE_NONE; 
    30813060} 
    30823061 
     
    33223301    // initial base layout created by server 
    33233302 
    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 ] ) 
    33273306    { 
    33283307      VectorCopy( builder->s.origin2, normal ); 
     
    37473726  } 
    37483727 
    3749   G_Printf("layoutsave: saving layout to %s\n", fileName ); 
     3728  G_Printf( "layoutsave: saving layout to %s\n", fileName ); 
    37503729 
    37513730  for( i = MAX_CLIENTS; i < level.num_entities; i++ ) 
     
    38573836  l = &layouts2[ 0 ]; 
    38583837  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 
    38623844    if( !Q_stricmp( s, "*BUILTIN*" ) ) 
    38633845    { 
     
    38653847      Q_strcat( layouts, sizeof( layouts ), " " ); 
    38663848      cnt++; 
    3867       s = COM_ParseExt( &l, qfalse ); 
    38683849      continue; 
    38693850    } 
     
    38783859    else 
    38793860      G_Printf( S_COLOR_YELLOW "WARNING: layout \"%s\" does not exist\n", s ); 
    3880     s = COM_ParseExt( &l, qfalse ); 
    38813861  } 
    38823862  if( !cnt ) 
     
    38913871  Q_strncpyz( layouts2, layouts, sizeof( layouts2 ) ); 
    38923872  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 ) ); 
    38963880    cnt++; 
    38973881    if( cnt >= layoutNum ) 
    38983882      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 ); 
    39033885} 
    39043886 
  • src/game/g_client.c

    r120 r124  
    8282/* 
    8383=============== 
     84G_CheckGUID 
     85=============== 
     86*/ 
     87qboolean 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=============== 
    84108G_AddCreditToClient 
    85109=============== 
     
    90114    return; 
    91115 
    92   //if we're already at the max and trying to add credit then stop 
     116  client->ps.persistant[ PERS_CREDIT ] += credit; 
     117 
    93118  if( cap ) 
    94119  { 
    95120    if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 
    96121    { 
    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      } 
    100128    } 
    101129    else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 
    102130    { 
    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     { 
    120131      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); 
    121135        client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS; 
     136      } 
    122137    } 
    123138  } 
     
    583598 
    584599    //sinking bodies can't be infested 
    585     ent->killedBy = ent->s.misc = MAX_CLIENTS; 
     600    ent->killedBy = ent->s.powerups = MAX_CLIENTS; 
    586601    ent->timestamp = level.time; 
    587602  } 
     
    657672    body->classname = "alienCorpse"; 
    658673 
    659   body->s.misc = MAX_CLIENTS; 
     674  body->s.powerups = MAX_CLIENTS; 
    660675 
    661676  body->think = BodySink; 
     
    867882 
    868883/* 
     884=================== 
     885G_NextNewbieName 
     886 
     887Generate a unique, known-good name for an UnnamedPlayer 
     888=================== 
     889*/ 
     890char *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/* 
    869915====================== 
    870916G_NonSegModel 
     
    944990  char      err[ MAX_STRING_CHARS ]; 
    945991  qboolean  revertName = qfalse; 
     992  qboolean  showRenameMsg = qtrue; 
    946993  gclient_t *client; 
    947994  char      c1[ MAX_INFO_STRING ]; 
     
    9721019  if( strcmp( oldname, newname ) ) 
    9731020  { 
    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 && 
    9791042      ( level.time - client->pers.nameChangeTime ) 
    9801043      <= ( g_minNameChangePeriod.value * 1000 ) ) 
     
    10101073      Q_strncpyz( client->pers.netname, newname, 
    10111074        sizeof( client->pers.netname ) ); 
     1075      Info_SetValueForKey( userinfo, "name", newname ); 
     1076      trap_SetUserinfo( clientNum, userinfo ); 
    10121077      if( client->pers.connected == CON_CONNECTED ) 
    10131078      { 
     
    10241089  } 
    10251090 
    1026   if( client->pers.connected == CON_CONNECTED ) 
     1091  if( client->pers.connected >= CON_CONNECTING && showRenameMsg ) 
    10271092  { 
    10281093    if( strcmp( oldname, client->pers.netname ) ) 
    10291094    { 
    10301095      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, 
    10331098         client->pers.ip, client->pers.guid, oldname, client->pers.netname ); 
    10341099      G_admin_namelog_update( client, qfalse ); 
     
    10481113 
    10491114  // 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 ) ) 
    10511116  { 
    10521117    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_FindModelNameForClass( PCL_HUMAN_BSUIT ), 
     
    11601225  char      reason[ MAX_STRING_CHARS ] = {""}; 
    11611226  int       i; 
     1227  int       used_privateSlots; 
     1228  int       privateClients; 
    11621229 
    11631230  ent = &g_entities[ clientNum ]; 
     
    11741241  } 
    11751242 
     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  } 
    11761263 
    11771264  // IP filtering 
     
    12061293 
    12071294  // add guid to session so we don't have to keep parsing userinfo everywhere 
    1208   if( !guid[0] ) 
     1295  if( !G_ValidGUID(guid) ) 
    12091296  { 
    12101297    Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 
     
    12281315  // get and distribute relevent paramters 
    12291316  ClientUserinfoChanged( clientNum ); 
    1230   G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s\"\n", clientNum, 
     1317  G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 
    12311318   client->pers.ip, client->pers.guid, client->pers.netname ); 
    12321319 
     
    12841371  // locate ent at a spawn point 
    12851372 
     1373  client->pers.classSelection = PCL_NONE; 
    12861374  ClientSpawn( ent, NULL, NULL, NULL ); 
    12871375 
     
    12911379  G_admin_namelog_update( client, qfalse ); 
    12921380 
     1381  // autoregister client if possible 
     1382  G_admin_autoregister( ent ); 
     1383 
    12931384  // request the clients PTR code 
    12941385  trap_SendServerCommand( ent - g_entities, "ptrcrequest" ); 
     
    12981389  // count current clients and rank for scoreboard 
    12991390  CalculateRanks( ); 
     1391} 
     1392 
     1393/* 
     1394================== 
     1395ClientPingOverride 
     1396 
     1397Called by server every time a client connects to check 
     1398whether it is immune to ping restrictions. 
     1399================== 
     1400*/ 
     1401int 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 ); 
    13001416} 
    13011417 
     
    13451461    client->sess.spectatorState = SPECTATOR_LOCKED; 
    13461462  } 
     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   
    13471472 
    13481473  if( origin != NULL ) 
     
    14691594  BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); 
    14701595  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 ); 
    14731597 
    14741598  ent->client->ps.stats[ STAT_PCLASS ] = ent->client->pers.classSelection; 
     
    14941618 
    14951619  client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA; 
     1620 
     1621  client->jetpack_beat = 0; 
     1622  client->jetpack_power = g_jetpackLimit.integer; 
    14961623 
    14971624  G_SetOrigin( ent, spawn_origin ); 
     
    16561783  } 
    16571784 
    1658   G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s\"\n", clientNum, 
     1785  G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 
    16591786   ent->client->pers.ip, ent->client->pers.guid, ent->client->pers.netname ); 
    16601787 
  • src/game/g_client.c

    r123 r124  
    818818{ 
    819819  int   len, colorlessLen; 
    820   char  ch; 
    821820  char  *p; 
    822821  int   spaces; 
     
    831830  spaces = 0; 
    832831 
    833   while( 1 ) 
    834   { 
    835     ch = *in++; 
    836     if( !ch ) 
    837       break; 
    838  
     832  for( ; *in; in++ ) 
     833  { 
    839834    // don't allow leading spaces 
    840     if( !*p && ch == ' ' ) 
     835    if( colorlessLen == 0 && *in == ' ' ) 
    841836      continue; 
    842837 
    843838    // 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 
    846847      // make sure room in dest for both chars 
    847848      if( len > outSize - 2 ) 
    848849        break; 
    849850 
    850       *out++ = ch; 
     851      *out++ = Q_COLOR_ESCAPE; 
     852      *out++ = *in; 
    851853      len += 2; 
    852  
    853       // solo trailing carat is not a color prefix 
    854       if( !*in ) { 
    855         *out++ = COLOR_WHITE; 
    856         break; 
    857       } 
    858  
    859       // don't allow black in a name, period 
    860       if( ColorIndex( *in ) == 0 ) 
    861         *out++ = COLOR_WHITE; 
    862       else 
    863         *out++ = *in; 
    864  
    865       in++; 
    866854      continue; 
    867855    } 
    868856 
    869857    // don't allow too many consecutive spaces 
    870     if( ch == ' ' ) 
     858    if( *in == ' ' ) 
    871859    { 
    872860      spaces++; 
     
    880868      break; 
    881869 
    882     *out++ = ch; 
     870    *out++ = *in; 
    883871    colorlessLen++; 
    884872    len++; 
     
    947935  } 
    948936 
    949   if( len <= 0 ) 
     937  if( len < 0 ) 
    950938    return qfalse; 
    951939 
  • src/game/g_cmds.c

    r120 r124  
    382382      maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 
    383383 
    384     client->ps.ammo = maxAmmo; 
    385     client->ps.clips = maxClips; 
     384    BG_PackAmmoArray( client->ps.weapon, client->ps.ammo, client->ps.powerups, maxAmmo, maxClips ); 
    386385  } 
    387386} 
     
    618617  ent->client->pers.joinedATeam = qtrue; 
    619618  ent->client->pers.teamChangeTime = level.time; 
    620  
    621619  //update ClientInfo 
    622620  ClientUserinfoChanged( ent->client->ps.clientNum ); 
     621  CalculateRanks( ); 
    623622} 
    624623 
     
    636635  int     aliens = level.numAlienClients; 
    637636  int     humans = level.numHumanClients; 
     637  int     warmup; 
    638638 
    639639  // stop team join spam 
    640640  if( level.time - ent->client->pers.teamChangeTime < 1000 ) 
    641641    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  } 
    642654 
    643655  if( oldteam == PTE_ALIENS ) 
     
    655667  } 
    656668 
    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 && 
    660671           level.numPlayingClients >= g_maxGameClients.integer ) 
    661672  { 
     
    665676    return; 
    666677  } 
     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; 
    667693  else if( !Q_stricmp( s, "aliens" ) ) 
    668694  { 
     
    673699      return; 
    674700    } 
    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\"" ) ); 
    685705      return; 
    686706    } 
     
    696716      return; 
    697717    } 
    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\"" ) ); 
    708721      return; 
    709722    } 
     
    715728    if( level.humanTeamLocked && level.alienTeamLocked ) 
    716729      team = PTE_NONE; 
    717     else if( humans > aliens ) 
     730    else if(humans > aliens ) 
    718731      team = PTE_ALIENS; 
    719732    else if( humans < aliens ) 
     
    734747 
    735748  // 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 ) ); 
    749758    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  } 
    759761  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  } 
    761775} 
    762776 
     
    767781================== 
    768782*/ 
    769 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message ) 
    770 { 
     783static 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 
    771787  qboolean ignore = qfalse; 
    772788 
     
    783799    return; 
    784800 
    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; 
    792816 
    793817    // specs with ADMF_SPEC_ALLCHAT flag can see team chat 
    794818  } 
     819 
     820  if( mode == SAY_ADMINS && !G_admin_permission( other, ADMF_ADMINCHAT) ) 
     821         return; 
     822 
     823  if( mode == SAY_ALL ) 
     824    usePrefix = qtrue; 
    795825 
    796826  if( BG_ClientListTest( &other->client->sess.ignoreList, ent-g_entities ) ) 
    797827    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  } 
    803837} 
    804838 
     
    840874    default: 
    841875    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": ", 
    844883                   ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 
    845884      color = COLOR_GREEN; 
    846885      break; 
    847886 
     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 
    848904    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 ); 
    850906      if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) 
    851907        Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC") (%s)"EC": ", 
     
    854910        Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC")"EC": ", 
    855911          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       
    857918      break; 
    858919 
     
    867928      color = COLOR_MAGENTA; 
    868929      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; 
    869947  } 
    870948 
    871949  Q_strncpyz( text, chatText, sizeof( text ) ); 
    872950 
     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 
    873959  if( target ) 
    874960  { 
    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  } 
    882964 
    883965  // send it to all the apropriate clients 
     
    885967  { 
    886968    other = &g_entities[ j ]; 
    887     G_SayTo( ent, other, mode, color, name, text ); 
     969    G_SayTo( ent, other, mode, color, name, text, prefix ); 
    888970  } 
    889971 
     
    904986  char    *p; 
    905987  char    *args; 
     988  int     offset = 0; 
    906989  int     mode = SAY_ALL; 
    907990 
     
    909992  if( Q_stricmpn( args, "say_team ", 9 ) == 0 ) 
    910993    mode = SAY_TEAM; 
     994  if( Q_stricmpn( args, "say_admins ", 11 ) == 0 || Q_stricmpn( args, "a ", 2 ) == 0) 
     995    mode = SAY_ADMINS; 
    911996 
    912997  // support parsing /m out of say text since some people have a hard 
     
    9201005    return; 
    9211006  } 
     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  } 
    9221041 
    9231042  if( trap_Argc( ) < 2 ) 
    9241043    return; 
    9251044 
     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 
    9261068  p = ConcatArgs( 1 ); 
     1069  p += offset; 
    9271070 
    9281071  G_Say( ent, NULL, mode, p ); 
     
    9561099  p = ConcatArgs( 2 ); 
    9571100 
    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 ); 
    9591102  G_Say( ent, target, SAY_TELL, p ); 
    9601103  // don't tell to the player self if it was already directed to this player 
     
    10521195 
    10531196    if( clientNum != -1 && 
    1054       level.clients[ clientNum ].pers.connected == CON_DISCONNECTED ) 
     1197      level.clients[ clientNum ].pers.connected != CON_CONNECTED ) 
    10551198    { 
    10561199      clientNum = -1; 
     
    11201263      "Un-Mute player \'%s\'", name ); 
    11211264  } 
    1122   else if( !Q_stricmp( arg1, "map_restart" ) ) 
     1265  else if( !Q_stricmp( arg1, "restartmap" ) ) 
    11231266  { 
    11241267    Com_sprintf( level.voteString, sizeof( level.voteString ), "%s", arg1 ); 
     
    11391282        sizeof( level.voteDisplayString ), "Change to map '%s'", arg2 ); 
    11401283  } 
    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" ); 
    11441287    Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), 
    1145         "End match in a draw" ); 
     1288        "Skip to next map in rotation" ); 
    11461289  } 
    11471290  else 
     
    11491292    trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" ); 
    11501293    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" ); 
    11521295    return; 
    11531296  } 
     
    11551298  trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE 
    11561299        " 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 ) ; 
    11571302 
    11581303  ent->client->pers.voteCount++; 
     
    14751620} 
    14761621 
     1622#define EVOLVE_TRACE_HEIGHT 128.0f 
    14771623#define AS_OVER_RT3         ((ALIENSENSE_RANGE*0.5f)/M_ROOT3) 
    14781624 
     
    15451691  int       clientNum; 
    15461692  int       i; 
     1693  trace_t   tr, tr2; 
    15471694  vec3_t    infestOrigin; 
    15481695  int       allowedClasses[ PCL_NUM_CLASSES ]; 
     
    15501697  pClass_t  currentClass = ent->client->ps.stats[ STAT_PCLASS ]; 
    15511698  pClass_t  newClass; 
     1699 
    15521700  int       numLevels; 
     1701  vec3_t    fromMins, fromMaxs, toMins, toMaxs; 
     1702  vec3_t    temp; 
     1703 
    15531704  int       entityList[ MAX_GENTITIES ]; 
    15541705  vec3_t    range = { AS_OVER_RT3, AS_OVER_RT3, AS_OVER_RT3 }; 
     
    15561707  int       num; 
    15571708  gentity_t *other; 
     1709  qboolean  humanNear = qfalse; 
    15581710 
    15591711  if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ) 
     
    15831735      return; 
    15841736    } 
     1737        else if( g_grangerMode.integer && newClass == PCL_ALIEN_BUILDER0_UPG && !level.overmindPresent) 
     1738        { 
     1739                newClass = PCL_ALIEN_BUILDER0; 
     1740        } 
    15851741 
    15861742    //if we are not currently spectating, we are attempting evolution 
     
    15901746          ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ) ) 
    15911747      { 
    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\"" ) ); 
    15931749        return; 
    15941750      } 
    1595  
     1751       
    15961752      //check there are no humans nearby 
    15971753      VectorAdd( ent->client->ps.origin, range, maxs ); 
    15981754      VectorSubtract( ent->client->ps.origin, range, mins ); 
    1599  
     1755       
    16001756      num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 
    16011757      for( i = 0; i < num; i++ ) 
     
    16061762            ( other->s.eType == ET_BUILDABLE && other->biteam == BIT_HUMANS ) ) 
    16071763        { 
    1608           G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); 
    1609           return; 
     1764          humanNear = qtrue; 
    16101765        } 
     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; 
    16111778      } 
    16121779 
     
    16221789          ent->client->ps.stats[ STAT_MISC ] > 0 ) 
    16231790      { 
    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\"" ) ); 
    16251793        return; 
    16261794      } 
     
    16301798                                           (short)ent->client->ps.persistant[ PERS_CREDIT ], 0 ); 
    16311799 
    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 ) 
    16331825      { 
    16341826        //...check we can evolve to that class 
    1635         if( numLevels >= 0 && 
     1827        if( (numLevels >= 0 || g_freeFunds.integer) && 
    16361828            BG_FindStagesForClass( newClass, g_alienStage.integer ) && 
    16371829            BG_ClassIsAllowed( newClass ) ) 
    16381830        { 
     1831          G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 
     1832 
    16391833          ent->client->pers.evolveHealthFraction = (float)ent->client->ps.stats[ STAT_HEALTH ] / 
    16401834            (float)BG_FindHealthForClass( currentClass ); 
     
    16451839            ent->client->pers.evolveHealthFraction = 1.0f; 
    16461840 
    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 ); 
    16491844          ent->client->pers.classSelection = newClass; 
    16501845          ClientUserinfoChanged( clientNum ); 
     
    16721867            BG_ClassIsAllowed( newClass ) ) 
    16731868        { 
     1869          G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 
     1870 
    16741871          ent->client->pers.classSelection = 
    16751872            ent->client->ps.stats[ STAT_PCLASS ] = newClass; 
     
    17071904      return; 
    17081905    } 
     1906 
     1907    G_LogOnlyPrintf("ClientTeamClass: %i human %s\n", clientNum, s); 
    17091908 
    17101909    G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ); 
     
    17831982 
    17841983      // 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\"" ); 
    17881994        return; 
    17891995      } 
     
    18112017              ent->client->pers.netname ) ); 
    18122018 
    1813           G_LogPrintf( "Decon: %i %i 0: %s deconstructed %s\n", 
     2019          G_LogPrintf( "Decon: %i %i 0: %s ^3deconstructed^7 %s\n", 
    18142020            ent->client->ps.clientNum, 
    18152021            traceEnt->s.modelindex, 
     
    18192025          G_FreeEntity( traceEnt ); 
    18202026 
    1821           if( !g_cheats.integer ) 
     2027          // cheat or fast build -> no build timer 
     2028          if( !g_cheats.integer && !g_fastBuild.integer ) 
    18222029            ent->client->ps.stats[ STAT_MISC ] += 
    18232030              BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 2; 
    18242031        } 
     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; 
    18252051      } 
    18262052    } 
     
    18942120    //special case to allow switching between 
    18952121    //the blaster and the primary weapon 
     2122    ent->client->ps.weaponTime = 0; 
    18962123 
    18972124    if( ent->client->ps.weapon != WP_BLASTER ) 
     
    19612188        !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 
    19622189    { 
    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\"" ) ); 
    19642192      return; 
    19652193    } 
     
    19702198    if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 
    19712199    { 
    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\"" ) ); 
    19732201      return; 
    19742202    } 
     
    19842212    } 
    19852213 
    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 ] ) 
    19882216    { 
    19892217      G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); 
     
    20272255      maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 
    20282256 
    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 ); 
    20312259 
    20322260    G_ForceWeaponChange( ent, weapon ); 
     
    20362264 
    20372265    //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 ); 
    20392268  } 
    20402269  else if( upgrade != UP_NONE ) 
     
    20482277 
    20492278    //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 ] ) 
    20512280    { 
    20522281      G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); 
     
    20922321        if( !G_RoomForClassChange( ent, PCL_HUMAN_BSUIT, newOrigin ) ) 
    20932322        { 
    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\"") ); 
    20952324          return; 
    20962325        } 
     
    21082337 
    21092338    //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 ); 
    21112341  } 
    21122342  else 
     
    21362366  if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 
    21372367  { 
    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\"" ) ); 
    21392369    return; 
    21402370  } 
     
    21592389          ent->client->ps.stats[ STAT_MISC ] > 0 ) 
    21602390      { 
    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\"" ) ); 
    21622392        return; 
    21632393      } 
     
    21662396 
    21672397      //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 ); 
    21692400    } 
    21702401 
     
    21912422        if( !G_RoomForClassChange( ent, PCL_HUMAN, newOrigin ) ) 
    21922423        { 
    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\"") ); 
    21942425          return; 
    21952426        } 
     
    22062437 
    22072438      //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 ); 
    22092441    } 
    22102442  } 
     
    22172449          ent->client->ps.stats[ STAT_MISC ] > 0 ) 
    22182450      { 
    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\"" ) ); 
    22202452        continue; 
    22212453      } 
     
    22272459 
    22282460        //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 ); 
    22302463      } 
    22312464 
     
    22432476          BG_FindPurchasableForUpgrade( i ) ) 
    22442477      { 
    2245  
    2246         // shouldn't really need to test for this, but just to be safe 
    2247         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  
    22602478        BG_RemoveUpgradeFromInventory( i, ent->client->ps.stats ); 
    22612479 
     
    22712489                !BG_FindInfinteAmmoForWeapon( j ) ) 
    22722490            { 
    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 ); 
    22752492            } 
    22762493          } 
     
    22782495 
    22792496        //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 ); 
    22812499      } 
    22822500    } 
     
    23132531 
    23142532  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 
    23152553  team = ent->client->ps.stats[ STAT_PTEAM ]; 
    23162554 
     
    23792617} 
    23802618 
     2619/* 
     2620================= 
     2621Cmd_Share_f 
     2622================= 
     2623*/ 
     2624void 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 
    23812822 
    23822823/* 
     
    24892930 
    24902931    // can't follow another spectator 
    2491     if( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) 
     2932    if( level.clients[ clientnum ].pers.teamSelection == PTE_NONE ) 
    24922933      continue; 
    24932934 
     
    25022943} 
    25032944 
     2945 /* 
     2946 ================= 
     2947Cmd_Donate_f 
     2948 
     2949Alms for the poor 
     2950================= 
     2951*/ 
     2952void 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 
    25042999/* 
    25053000================= 
     
    25173012/* 
    25183013================= 
    2519 Cmd_Follow_f 
     3014Cmd_Follow_f (with r1 changes in here) 
    25203015================= 
    25213016*/ 
     
    27603255  { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 
    27613256  { "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 }, 
    27623259  { "m", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 
    27633260  { "mt", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 
    2764  
     3261  { "me", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 
    27653262  { "score", CMD_INTERMISSION, ScoreboardMessage }, 
    27663263 
     
    27793276  { "ptrcverify", 0, Cmd_PTRCVerify_f }, 
    27803277  { "ptrcrestore", 0, Cmd_PTRCRestore_f }, 
     3278  { "share", CMD_TEAM, Cmd_Share_f }, 
     3279  { "donate", CMD_TEAM, Cmd_Donate_f }, 
    27813280 
    27823281  { "follow", CMD_NOTEAM, Cmd_Follow_f }, 
     
    30203519  gentity_t *tmpent; 
    30213520 
     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 
    30223527  if( !g_privateMessages.integer && ent ) 
    30233528  { 
     
    30743579 
    30753580  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  } 
    30763592 
    30773593  Q_strncpyz( str, 
     
    30893605    trap_SendServerCommand( pids[ i ], va( 
    30903606      "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", 
    30923608      color, 
    30933609      name, 
     
    30963612      msg, 
    30973613      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(  
    31053616      "cp \"^%cprivate message from ^7%s^7\"", color, 
    3106       ( ent ) ? ent->client->pers.netname : "console" ) ); 
     3617      ( ent ) ? ent->client->pers.netname : "Console" ) ); 
    31073618  } 
    31083619 
     
    31123623  else 
    31133624  { 
    3114     ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 
     3625    if( ent ) 
     3626      ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 
     3627 
    31153628    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 ); 
    31213629  } 
    31223630 
  • src/game/g_cmds.c

    r123 r124  
    5454    } 
    5555 
    56     if( *in == 27 || *in == '^' ) 
     56    if( *in == 27 || Q_IsColorString( in ) ) 
    5757    { 
    5858      in += 2;    // skip color code 
     
    194194    return 0; 
    195195  } 
    196    
     196 
    197197  // now look for name matches 
    198198  G_SanitiseName( s, s2 ); 
     
    536536      continue; 
    537537 
    538     // clean up projectiles 
    539     if( ent->s.eType == ET_MISSILE && ent->r.ownerNum == self->s.number ) 
    540       G_FreeEntity( ent ); 
    541538    if( ent->client && ent->client->pers.connected == CON_CONNECTED ) 
    542539    { 
     
    557554        ent->client->ps.stats[ STAT_STATE ] &= ~SS_POISONED; 
    558555    } 
     556    else if( ent->s.eType == ET_MISSILE && ent->r.ownerNum == self->s.number ) 
     557      G_FreeEntity( ent ); 
    559558  } 
    560559} 
     
    568567{ 
    569568  pTeam_t oldTeam = ent->client->pers.teamSelection; 
    570   
     569 
    571570  if( oldTeam == newTeam ) 
    572571    return; 
     
    578577  // when switching teams 
    579578  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 ) ) 
    582581  { 
    583582    if( oldTeam == PTE_NONE ) 
    584583    { 
    585584      // ps.persistant[] from a spectator cannot be trusted 
    586       ent->client->ps.persistant[ PERS_SCORE ] = ent->client->pers.savedScore; 
    587585      ent->client->ps.persistant[ PERS_CREDIT ] = ent->client->pers.savedCredit; 
    588586    } 
     
    598596      // save values before the client enters the spectator team and their 
    599597      // ps.persistant[] values become trashed 
    600       ent->client->pers.savedScore = ent->client->ps.persistant[ PERS_SCORE ]; 
    601598      ent->client->pers.savedCredit = ent->client->ps.persistant[ PERS_CREDIT ]; 
    602599    } 
     
    612609    ent->client->ps.persistant[ PERS_CREDIT ] = 0; 
    613610    ent->client->ps.persistant[ PERS_SCORE ] = 0; 
    614     ent->client->pers.savedScore = 0; 
    615611    ent->client->pers.savedCredit = 0; 
    616612  } 
     
    664660  trap_Argv( 1, s, sizeof( s ) ); 
    665661 
    666   if( !strlen( 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\"", 
    669665      oldteam ) ); 
    670666    return; 
     
    700696    { 
    701697      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; 
    704700    } 
    705701 
     
    717713    { 
    718714      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; 
    721717    } 
    722718    if( !force && !level.alienTeamLocked && g_teamForceBalance.integer && humans > aliens ) 
     
    854850  char        location[ 64 ]; 
    855851 
    856   if (g_chatTeamPrefix.integer) 
    857   { 
    858     switch( ent->client->pers.teamSelection) 
     852  if( g_chatTeamPrefix.integer ) 
     853  { 
     854    switch( ent->client->pers.teamSelection ) 
    859855    { 
    860856      default: 
     
    973969    G_SayTo( ent, other, mode, color, name, text, prefix ); 
    974970  } 
    975    
     971 
    976972  if( g_adminParseSay.integer ) 
    977973  { 
     
    1002998  // time figuring out what the console is. 
    1003999  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 ) || 
    10061002      !Q_stricmpn( args, "say_team /mt ", 13 ) ) 
    10071003  { 
     
    11461142  } 
    11471143 
    1148   if( g_voteLimit.integer > 0 
    1149     && ent->client->pers.voteCount >= g_voteLimit.integer  
    1150     && !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 ) ) 
    11511147  { 
    11521148    trap_SendServerCommand( ent-g_entities, va( 
     
    11901186    { 
    11911187      // there was only one partial name match 
    1192       clientNum = clientNums[ 0 ];  
     1188      clientNum = clientNums[ 0 ]; 
    11931189    } 
    11941190    else 
    11951191    { 
    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) 
    11971193      clientNum = G_ClientNumberFromString( ent, arg2 ); 
    11981194    } 
     
    12171213    } 
    12181214  } 
    1219   
     1215 
    12201216  if( !Q_stricmp( arg1, "kick" ) ) 
    12211217  { 
     
    13131309  ent->client->pers.vote = qtrue; 
    13141310 
    1315   for( i = 0 ; i < level.maxclients ; i++ ) 
     1311  for( i = 0; i < level.maxclients; i++ ) 
    13161312    level.clients[i].ps.eFlags &= ~EF_VOTED; 
    13171313 
     
    13671363  int   clientNum = -1; 
    13681364  char  name[ MAX_NETNAME ]; 
    1369    
     1365 
    13701366  team = ent->client->pers.teamSelection; 
    13711367 
     
    13851381  } 
    13861382 
    1387   if( g_voteLimit.integer > 0 
    1388     && ent->client->pers.voteCount >= g_voteLimit.integer  
    1389     && !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 ) ) 
    13901386  { 
    13911387    trap_SendServerCommand( ent-g_entities, va( 
     
    14041400    return; 
    14051401  } 
    1406    
     1402 
    14071403  // detect clientNum for partial name match votes 
    14081404  if( !Q_stricmp( arg1, "kick" ) || 
     
    14221418    { 
    14231419      // there was only one partial name match 
    1424       clientNum = clientNums[ 0 ];  
     1420      clientNum = clientNums[ 0 ]; 
    14251421    } 
    14261422    else 
    14271423    { 
    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) 
    14291425      clientNum = G_ClientNumberFromString( ent, arg2 ); 
    14301426    } 
     
    14361432      clientNum = -1; 
    14371433    } 
    1438        
     1434 
    14391435    if( clientNum != -1 && 
    14401436      level.clients[ clientNum ].pers.connected == CON_DISCONNECTED ) 
     
    15401536  ent->client->pers.teamVote = qtrue; 
    15411537 
    1542   for( i = 0 ; i < level.maxclients ; i++ ) 
     1538  for( i = 0; i < level.maxclients; i++ ) 
    15431539  { 
    15441540    if( level.clients[ i ].ps.stats[ STAT_PTEAM ] == team ) 
     
    16061602  if( trap_Argc( ) != 5 ) 
    16071603  { 
    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\"" ); 
    16091605    return; 
    16101606  } 
     
    16121608  VectorClear( angles ); 
    16131609 
    1614   for( i = 0 ; i < 3 ; i++ ) 
     1610  for( i = 0; i < 3; i++ ) 
    16151611  { 
    16161612    trap_Argv( i + 1, buffer, sizeof( buffer ) ); 
     
    16821678 
    16831679  //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 ); 
    16881681} 
    16891682 
     
    17391732    if( newClass == PCL_NONE ) 
    17401733    { 
    1741       trap_SendServerCommand( ent-g_entities, va( "print \"Unknown class\n\"" ) ); 
     1734      trap_SendServerCommand( ent-g_entities, "print \"Unknown class\n\"" ); 
    17421735      return; 
    17431736    } 
     
    17501743    if( ent->client->pers.classSelection != PCL_NONE ) 
    17511744    { 
    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\"" ) ); 
    17561749        return; 
    17571750      } 
     
    17841777        return; 
    17851778      } 
    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 ); 
    17911783        return; 
    17921784      } 
    1793  
    17941785 
    17951786      //guard against selling the HBUILD weapons exploit 
     
    18551846          VectorCopy( infestOrigin, ent->s.pos.trBase ); 
    18561847          ClientSpawn( ent, ent, ent->s.pos.trBase, ent->s.apos.trBase ); 
    1857           return; 
    18581848        } 
    18591849        else 
    18601850        { 
    18611851          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\"" ); 
    18641853        } 
    18651854      } 
     
    18671856      { 
    18681857        G_TriggerMenu( clientNum, MN_A_NOEROOM ); 
    1869         return; 
    18701858      } 
    18711859    } 
     
    18871875        } 
    18881876      } 
    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\"" ); 
    18911878    } 
    18921879  } 
     
    18961883    if( ent->client->pers.classSelection != PCL_NONE ) 
    18971884    { 
    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\"" ); 
    18991886      return; 
    19001887    } 
     
    19141901    { 
    19151902      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\"" ); 
    19171904      return; 
    19181905    } 
     
    20162003      if( traceEnt->health > 0 ) 
    20172004      { 
    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 ) 
    20192008        { 
    20202009          traceEnt->deconstruct     = qtrue; // Mark buildable for deconstruction 
     
    20342023            BG_FindNameForBuildable( traceEnt->s.modelindex ) ); 
    20352024 
    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 ); 
    20402026 
    20412027          // cheat or fast build -> no build timer 
     
    21242110{ 
    21252111  char  s[ MAX_TOKEN_CHARS ]; 
    2126   int   upgrade, weapon, i; 
     2112  int   upgrade, weapon; 
    21272113 
    21282114  trap_Argv( 1, s, sizeof( s ) ); 
     
    21392125      weapon = WP_BLASTER; 
    21402126    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; 
    21582128 
    21592129    G_ForceWeaponChange( ent, weapon ); 
     
    22592229    { 
    22602230      //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\"" ); 
    22622232      return; 
    22632233    } 
     
    22662236    if( !BG_FindPurchasableForWeapon( weapon ) ) 
    22672237    { 
    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\"" ); 
    22692239      return; 
    22702240    } 
     
    22732243    if( !BG_FindStagesForWeapon( weapon, g_humanStage.integer ) || !BG_WeaponIsAllowed( weapon ) ) 
    22742244    { 
    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\"" ); 
    22762246      return; 
    22772247    } 
     
    23232293    { 
    23242294      //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\"" ); 
    23262296      return; 
    23272297    } 
     
    23302300    if( !BG_FindPurchasableForUpgrade( upgrade ) ) 
    23312301    { 
    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\"" ); 
    23332303      return; 
    23342304    } 
     
    23372307    if( !BG_FindStagesForUpgrade( upgrade, g_humanStage.integer ) || !BG_UpgradeIsAllowed( upgrade ) ) 
    23382308    { 
    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\"" ); 
    23402310      return; 
    23412311    } 
     
    23722342  else 
    23732343  { 
    2374     trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ) ); 
     2344    trap_SendServerCommand( ent-g_entities, "print \"Unknown item\n\"" ); 
    23752345  } 
    23762346 
     
    24082378    if( !BG_FindPurchasableForWeapon( weapon ) ) 
    24092379    { 
    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\"" ); 
    24112381      return; 
    24122382    } 
     
    24392409    if( !BG_FindPurchasableForUpgrade( upgrade ) ) 
    24402410    { 
    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\"" ); 
    24422412      return; 
    24432413    } 
     
    25312501  } 
    25322502  else 
    2533     trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ) ); 
     2503    trap_SendServerCommand( ent-g_entities, "print \"Unknown item\n\"" ); 
    25342504 
    25352505  //update ClientInfo 
     
    26442614  } 
    26452615  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\"" ); 
    26472617} 
    26482618 
     
    31243094  trap_Argv( 1, s, sizeof( s ) ); 
    31253095 
    3126   if( !strlen( s ) ) 
     3096  if( !s[ 0 ] ) 
    31273097    return; 
    31283098 
     
    31683138  trap_Argv( 1, s, sizeof( s ) ); 
    31693139 
    3170   if( !strlen( s ) ) 
     3140  if( !s[ 0 ] ) 
    31713141    return; 
    31723142 
     
    32193189  { 
    32203190    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 ) ); 
    32223192    return; 
    32233193  } 
    32243194 
    32253195  Q_strncpyz( name, ConcatArgs( 1 ), sizeof( name ) ); 
    3226   matches = G_ClientNumbersFromString( name, pids, MAX_CLIENTS );  
     3196  matches = G_ClientNumbersFromString( name, pids, MAX_CLIENTS ); 
    32273197  if( matches < 1 ) 
    32283198  { 
     
    34313401    if( *s == ' ' ) 
    34323402    { 
    3433       s++;  
     3403      s++; 
    34343404      if( *s != ' ' ) 
    34353405      { 
     
    35213491 
    35223492void G_DecolorString( char *in, char *out ) 
    3523 {    
     3493{ 
    35243494  while( *in ) { 
    3525     if( *in == 27 || *in == '^' ) { 
     3495    if( *in == 27 || Q_IsColorString( in ) ) { 
    35263496      in++; 
    35273497      if( *in ) 
     
    35843554    int count = 0; 
    35853555 
    3586     for( i=0; i < pcount; i++ ) 
     3556    for( i = 0; i < pcount; i++ ) 
    35873557    { 
    35883558      tmpent = &g_entities[ pids[ i ] ]; 
  • src/game/g_combat.c

    r120 r124  
    4040{ 
    4141  if( !ent->client ) 
    42     return; 
    43  
    44   // no scoring during pre-match warmup 
    45   if( level.warmupTime ) 
    4642    return; 
    4743 
     
    122118  "MOD_ASPAWN", 
    123119  "MOD_ATUBE", 
    124   "MOD_OVERMIND" 
     120  "MOD_OVERMIND", 
     121 
     122  "MOD_SLAP" 
    125123}; 
    126124 
     
    139137  float     totalDamage = 0.0f; 
    140138  gentity_t *player; 
     139  qboolean  tk = qfalse; 
    141140 
    142141 
     
    148147 
    149148  // 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. 
    160150 
    161151  self->client->ps.pm_type = PM_DEAD; 
     
    167157 
    168158    if( attacker->client ) 
     159    { 
    169160      killerName = attacker->client->pers.netname; 
     161      tk = ( attacker != self && attacker->client->ps.stats[ STAT_PTEAM ]  
     162        == self->client->ps.stats[ STAT_PTEAM ] ); 
     163    } 
    170164    else 
    171165      killerName = "<non-client>"; 
     
    188182    obit = modNames[ meansOfDeath ]; 
    189183 
    190   G_LogPrintf("Kill: %i %i %i: %s killed %s by %s\n", 
     184  G_LogPrintf("Kill: %i %i %i: %s^7 killed %s^7 by %s\n", 
    191185    killer, self->s.number, meansOfDeath, killerName, 
    192186    self->client->pers.netname, obit ); 
     
    200194 
    201195  // 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  } 
    207214 
    208215  self->enemy = attacker; 
     
    396403 
    397404  // 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 ) ); 
    399406 
    400407  { 
     
    944951  } 
    945952 
     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   
    946959  client = targ->client; 
    947960 
     
    10171030    if( targ != attacker && OnSameTeam( targ, attacker ) ) 
    10181031    { 
    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 ) 
    10201049      { 
    10211050        if( !g_friendlyFireHumans.integer && 
     
    10371066    { 
    10381067      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 ) ) 
    10391072        return; 
    10401073    } 
  • src/game/g_combat.c

    r122 r124  
    10481048      else if( !g_friendlyFire.integer ) 
    10491049      { 
    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 ) 
    10521052        { 
    10531053          return; 
    10541054        } 
    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 ) 
    10571057        { 
    10581058          return; 
     
    10611061    } 
    10621062 
    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; 
     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; 
    10691069      // 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 ) ) 
    10711072        return; 
    1072                 } 
     1073    } 
    10731074 
    10741075    // check for godmode 
    1075     if ( targ->flags & FL_GODMODE ) 
     1076    if( targ->flags & FL_GODMODE ) 
    10761077      return; 
    10771078  } 
     
    12941295    points = damage * ( 1.0 - dist / radius ); 
    12951296 
    1296     if( CanDamage( ent, origin ) ) 
     1297    if( CanDamage( ent, origin ) && ent->client && 
     1298        ent->client->ps.stats[ STAT_PTEAM ] != team ) 
    12971299    { 
    12981300      VectorSubtract( ent->r.currentOrigin, origin, dir ); 
     
    13001302      // get knocked into the air more 
    13011303      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 ); 
    13041307    } 
    13051308  } 
     
    13711374      // get knocked into the air more 
    13721375      dir[ 2 ] += 24; 
     1376      hitClient = qtrue; 
    13731377      G_Damage( ent, NULL, attacker, dir, origin, 
    13741378          (int)points, DAMAGE_RADIUS|DAMAGE_NO_LOCDAMAGE, mod ); 
  • src/game/g_local.h

    r120 r124  
    199199  qboolean          active;             // for power repeater, but could be useful elsewhere 
    200200  qboolean          powered;            // for human buildables 
     201  int               buildpoints;        // buildpoints remains to this generator 
    201202  int               builtBy;            // clientNum of person that built this 
    202203  gentity_t         *dccNode;           // controlling dcc 
     
    295296{ 
    296297  team_t            sessionTeam; 
     298  pTeam_t           restartTeam; //for !restart keepteams and !restart switchteams 
    297299  int               spectatorTime;    // for determining next-in-line to play 
    298300  spectatorState_t  spectatorState; 
     
    356358  qboolean            denyBuild; 
    357359  int                 adminLevel; 
     360  int                 floodTimer; 
    358361} clientPersistant_t; 
    359362 
     
    460463  int                 unlaggedTime; 
    461464 
     465  int                 jetpack_beat;         // waiting time before turn on jetpack when power down 
     466  int                 jetpack_power; 
    462467}; 
    463468 
     
    532537  int               num_entities;   // current number, <= MAX_GENTITIES 
    533538 
    534   int               warmupTime;     // restart match at this time 
    535  
    536539  fileHandle_t      logFile; 
    537540 
     
    557560  int               numPlayingClients;            // connected, non-spectators 
    558561  int               sortedClients[MAX_CLIENTS];   // sorted by score 
     562  int               numNewbies;                   // number of UnnamedPlayers who have been renamed this round. 
    559563 
    560564  int               snd_fry;                      // sound index for standing in lava 
    561  
    562   int               warmupModificationCount;      // for detecting if g_warmup is changed 
    563565 
    564566  // voting state 
     
    634636  pTeam_t           lastWin; 
    635637 
     638  int               suddenDeathABuildPoints; 
     639  int               suddenDeathHBuildPoints; 
     640  qboolean          suddenDeath; 
    636641  timeWarning_t     suddenDeathWarning; 
    637642  timeWarning_t     timelimitWarning; 
     
    654659 
    655660  char              layout[ MAX_QPATH ]; 
     661 
     662  int               warmupMessageTime;            // last warmup message level.time 
    656663 
    657664  pTeam_t           surrenderTeam; 
     
    694701void      G_MatchOnePlayer( int *plist, int num, char *err, int len ); 
    695702int       G_ClientNumbersFromString( char *s, int *plist, int max ); 
     703void      G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ); 
    696704int       G_SayArgc( void ); 
    697705qboolean  G_SayArgv( int n, char *buffer, int bufferLength ); 
     
    702710void      G_SanitiseName( char *in, char *out ); 
    703711void      G_PrivateMessage( gentity_t *ent ); 
     712void      Cmd_Share_f( gentity_t *ent ); 
     713void      Cmd_Donate_f( gentity_t *ent ); 
    704714 
    705715// 
     
    745755                    buildable_t spawn, vec3_t spawnOrigin ); 
    746756 
     757gentity_t*        G_FindGenerator( buildableTeam_t team, vec3_t origin ); 
    747758buildable_t       G_IsPowered( vec3_t origin ); 
    748759qboolean          G_IsDCCBuilt( void ); 
     
    914925void      player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod ); 
    915926qboolean  SpotWouldTelefrag( gentity_t *spot ); 
     927char     *G_NextNewbieName( gentity_t *ent ); 
    916928 
    917929// 
     
    943955void G_RunThink( gentity_t *ent ); 
    944956void QDECL G_LogPrintf( const char *fmt, ... ); 
     957void QDECL G_LogOnlyPrintf( const char *fmt, ... ); 
    945958void SendScoreboardMessageToAllClients( void ); 
    946959void QDECL G_Printf( const char *fmt, ... ); 
     
    952965void LogExit( const char *string ); 
    953966int  G_TimeTilSuddenDeath( void ); 
     967void G_Donate( gclient_t *client, short value ); 
    954968 
    955969// 
     
    961975void ClientBegin( int clientNum ); 
    962976void ClientCommand( int clientNum ); 
     977int ClientPingOverride( void ); 
    963978 
    964979// 
     
    10991114extern  vmCvar_t  g_dedicated; 
    11001115extern  vmCvar_t  g_cheats; 
     1116extern  vmCvar_t  g_version; 
    11011117extern  vmCvar_t  g_maxclients;     // allow this many total, including spectators 
    11021118extern  vmCvar_t  g_maxGameClients;   // allow this many active 
     
    11051121extern  vmCvar_t  g_minNameChangePeriod; 
    11061122extern  vmCvar_t  g_maxNameChanges; 
     1123extern  vmCvar_t  g_newbieNumbering; 
     1124extern  vmCvar_t  g_newbieNamePrefix; 
    11071125 
    11081126extern  vmCvar_t  g_timelimit; 
    11091127extern  vmCvar_t  g_suddenDeathTime; 
     1128extern  vmCvar_t  g_suddenDeathMode; 
    11101129extern  vmCvar_t  g_friendlyFire; 
    11111130extern  vmCvar_t  g_friendlyFireHumans; 
    11121131extern  vmCvar_t  g_friendlyFireAliens; 
    11131132extern  vmCvar_t  g_friendlyBuildableFire; 
     1133extern  vmCvar_t  g_friendlyFireMovementAttacks; 
    11141134extern  vmCvar_t  g_password; 
    11151135extern  vmCvar_t  g_needpass; 
     
    11281148extern  vmCvar_t  g_warmup; 
    11291149extern  vmCvar_t  g_doWarmup; 
     1150extern  vmCvar_t  g_warmupMessage; 
    11301151extern  vmCvar_t  g_blood; 
    11311152extern  vmCvar_t  g_allowVote; 
     
    11391160extern  vmCvar_t  pmove_msec; 
    11401161extern  vmCvar_t  g_rankings; 
     1162extern  vmCvar_t  g_allowShare; 
     1163extern  vmCvar_t  g_allowDonate; 
     1164extern  vmCvar_t  g_grangerMode; 
     1165extern  vmCvar_t  g_repeaterOnReactor; 
     1166extern  vmCvar_t  g_jetpackLimit; 
     1167extern  vmCvar_t  g_autoDonate; 
    11411168extern  vmCvar_t  g_enableDust; 
    11421169extern  vmCvar_t  g_enableBreath; 
     
    11451172extern  vmCvar_t  g_humanBuildPoints; 
    11461173extern  vmCvar_t  g_alienBuildPoints; 
     1174extern  vmCvar_t  g_reactorBuildPoints; 
     1175extern  vmCvar_t  g_repeaterBuildPoints; 
     1176extern  vmCvar_t  g_overmindBuildPoints; 
     1177extern  vmCvar_t  g_eggBuildPoints; 
     1178extern  vmCvar_t  g_zoneBuildPoints; 
    11471179extern  vmCvar_t  g_humanStage; 
    11481180extern  vmCvar_t  g_humanKills; 
     
    11691201extern  vmCvar_t  g_initialMapRotation; 
    11701202extern  vmCvar_t  g_chatTeamPrefix; 
     1203extern  vmCvar_t  g_specsSeeTeamchat; 
    11711204 
    11721205extern  vmCvar_t  g_shove; 
     
    11821215extern  vmCvar_t  g_adminNameProtect; 
    11831216extern  vmCvar_t  g_adminTempBan; 
    1184  
     1217extern  vmCvar_t  g_minLevelToSpecMM1; 
     1218extern  vmCvar_t  g_adminWarnMessage; 
    11851219extern  vmCvar_t  g_privateMessages; 
     1220extern  vmCvar_t  g_publicSayadmins; 
     1221extern  vmCvar_t  g_allowActions; 
     1222extern  vmCvar_t  g_actionPrefix; 
     1223extern  vmCvar_t  g_floodProtection; 
     1224extern  vmCvar_t  g_autoRegister; 
     1225 
     1226extern  vmCvar_t  g_slapKnockback; 
     1227extern  vmCvar_t  g_slapDamage; 
     1228 
     1229extern  vmCvar_t  g_hiddenClients; 
     1230 
     1231extern  vmCvar_t  g_dretchPunt; 
     1232 
     1233extern vmCvar_t g_freeFunds; 
     1234extern vmCvar_t g_fastBuild; 
     1235extern vmCvar_t g_noBaseAttack; 
     1236extern vmCvar_t g_cheatAdminLevel; // an admin above or equal this level can use cheat, disable if 0 
     1237 
     1238extern vmCvar_t  g_playerVotePercent; 
     1239extern vmCvar_t  g_globalVotePercent; 
    11861240 
    11871241void      trap_Printf( const char *fmt ); 
     
    12331287void      trap_SnapVector( float *v ); 
    12341288void      trap_SendGameStat( const char *data ); 
     1289 
     1290void      do_health( gentity_t *ent, int quantity ); 
  • src/game/g_local.h

    r123 r124  
    346346 
    347347  // used to save persistant[] values while in SPECTATOR_FOLLOW mode 
    348   int                 savedScore; 
    349348  int                 savedCredit; 
    350349 
  • src/game/g_main.c

    r120 r124  
    2323 
    2424#include "g_local.h" 
     25 
     26#include "../qcommon/q_shared.h" 
    2527 
    2628level_locals_t  level; 
     
    4042gclient_t   g_clients[ MAX_CLIENTS ]; 
    4143 
     44vmCvar_t  g_version; 
    4245vmCvar_t  g_fraglimit; 
    4346vmCvar_t  g_timelimit; 
    4447vmCvar_t  g_suddenDeathTime; 
     48vmCvar_t  g_suddenDeathMode; 
    4549vmCvar_t  g_capturelimit; 
    4650vmCvar_t  g_friendlyFire; 
     
    4852vmCvar_t  g_friendlyFireHumans; 
    4953vmCvar_t  g_friendlyBuildableFire; 
     54vmCvar_t  g_friendlyFireMovementAttacks; 
    5055vmCvar_t  g_password; 
    5156vmCvar_t  g_needpass; 
     
    6873vmCvar_t  g_warmup; 
    6974vmCvar_t  g_doWarmup; 
     75vmCvar_t  g_warmupMessage; 
    7076vmCvar_t  g_restarted; 
    7177vmCvar_t  g_logFile; 
     
    8288vmCvar_t  g_smoothClients; 
    8389vmCvar_t  pmove_fixed; 
     90vmCvar_t  g_rankings; 
    8491vmCvar_t  pmove_msec; 
    85 vmCvar_t  g_rankings; 
    8692vmCvar_t  g_listEntity; 
    8793vmCvar_t  g_minCommandPeriod; 
    8894vmCvar_t  g_minNameChangePeriod; 
    8995vmCvar_t  g_maxNameChanges; 
    90  
     96vmCvar_t  g_newbieNumbering; 
     97vmCvar_t  g_newbieNamePrefix; 
     98 
     99vmCvar_t  g_reactorBuildPoints; 
     100vmCvar_t  g_repeaterBuildPoints; 
     101vmCvar_t  g_overmindBuildPoints; 
     102vmCvar_t  g_eggBuildPoints; 
     103vmCvar_t  g_zoneBuildPoints; 
    91104vmCvar_t  g_humanBuildPoints; 
    92105vmCvar_t  g_alienBuildPoints; 
     
    119132vmCvar_t  g_mapConfigs; 
    120133vmCvar_t  g_chatTeamPrefix; 
     134vmCvar_t  g_specsSeeTeamchat; 
    121135 
    122136vmCvar_t  g_layouts; 
     
    127141vmCvar_t  g_adminParseSay; 
    128142vmCvar_t  g_adminNameProtect; 
     143vmCvar_t  g_autoRegister; 
    129144vmCvar_t  g_adminTempBan; 
     145vmCvar_t  g_minLevelToSpecMM1; 
     146vmCvar_t  g_adminWarnMessage; 
    130147 
    131148vmCvar_t  g_privateMessages; 
     149vmCvar_t  g_publicSayadmins; 
     150vmCvar_t  g_floodProtection; 
     151 
     152vmCvar_t  g_slapKnockback; 
     153vmCvar_t  g_slapDamage; 
    132154 
    133155vmCvar_t  g_tag; 
     156 
     157vmCvar_t  g_allowActions; 
     158vmCvar_t  g_actionPrefix; 
     159 
     160vmCvar_t  g_hiddenClients; 
     161 
     162vmCvar_t  g_dretchPunt; 
     163 
     164vmCvar_t  g_allowShare; 
     165vmCvar_t  g_allowDonate; 
     166vmCvar_t  g_autoDonate; 
     167 
     168 
     169vmCvar_t g_freeFunds; 
     170vmCvar_t g_fastBuild; 
     171vmCvar_t g_noBaseAttack; 
     172vmCvar_t g_cheatAdminLevel; // an admin above or equal this level can use cheat, disable if 0 
     173 
     174vmCvar_t  g_grangerMode; 
     175vmCvar_t  g_repeaterOnReactor; 
     176vmCvar_t  g_jetpackLimit; 
     177 
     178vmCvar_t  g_playerVotePercent; 
     179vmCvar_t  g_globalVotePercent; 
    134180 
    135181static cvarTable_t   gameCvarTable[ ] = 
     
    148194  // latched vars 
    149195 
    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  }, 
    151200 
    152201  // change anytime vars 
     
    155204  { &g_timelimit, "timelimit", "0", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART, 0, qtrue }, 
    156205  { &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 }, 
    157209 
    158210  { &g_synchronousClients, "g_synchronousClients", "0", CVAR_SYSTEMINFO, 0, qfalse  }, 
    159211 
    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  }, 
    164217 
    165218  { &g_teamAutoJoin, "g_teamAutoJoin", "0", CVAR_ARCHIVE  }, 
    166   { &g_teamForceBalance, "g_teamForceBalance", "0", CVAR_ARCHIVE  }, 
     219  { &g_teamForceBalance, "g_teamForceBalance", "1", CVAR_ARCHIVE  }, 
    167220 
    168221  { &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  }, 
    170224  { &g_logFile, "g_logFile", "games.log", CVAR_ARCHIVE, 0, qfalse  }, 
    171225  { &g_logFileSync, "g_logFileSync", "0", CVAR_ARCHIVE, 0, qfalse  }, 
     
    197251 
    198252  { &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 }, 
    200254  { &g_listEntity, "g_listEntity", "0", 0, 0, qfalse }, 
    201255  { &g_minCommandPeriod, "g_minCommandPeriod", "500", 0, 0, qfalse}, 
    202256  { &g_minNameChangePeriod, "g_minNameChangePeriod", "5", 0, 0, qfalse}, 
    203257  { &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}, 
    204260 
    205261  { &g_smoothClients, "g_smoothClients", "1", 0, 0, qfalse}, 
     
    209265  { &g_humanBuildPoints, "g_humanBuildPoints", DEFAULT_HUMAN_BUILDPOINTS, 0, 0, qfalse  }, 
    210266  { &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  }, 
    211272  { &g_humanStage, "g_humanStage", "0", 0, 0, qfalse  }, 
    212273  { &g_humanKills, "g_humanKills", "0", 0, 0, qfalse  }, 
     
    219280  { &g_alienStage2Threshold, "g_alienStage2Threshold", DEFAULT_ALIEN_STAGE2_THRESH, 0, 0, qfalse  }, 
    220281  { &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  }, 
    223284 
    224285  { &g_disabledEquipment, "g_disabledEquipment", "", CVAR_ROM, 0, qfalse  }, 
     
    226287  { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse  }, 
    227288 
    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  }, 
    231293 
    232294  { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse  }, 
     
    235297  { &g_initialMapRotation, "g_initialMapRotation", "", CVAR_ARCHIVE, 0, qfalse  }, 
    236298  { &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  }, 
    238301  { NULL, "g_mapConfigsLoaded", "0", CVAR_ROM, 0, qfalse  }, 
    239302 
     
    246309  { &g_adminNameProtect, "g_adminNameProtect", "1", CVAR_ARCHIVE, 0, qfalse  }, 
    247310  { &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   
    249314  { &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}, 
    250321 
    251322  { &g_tag, "g_tag", "main", CVAR_INIT, 0, qfalse }, 
    252323 
    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 } 
    254343}; 
    255344 
     
    316405    case GAME_CONSOLE_COMMAND: 
    317406      return ConsoleCommand( ); 
     407 
     408    case GAME_PING_OVERRIDE: 
     409      return ClientPingOverride( ); 
    318410  } 
    319411 
     
    443535  if( remapped ) 
    444536    G_RemapTeamShaders( ); 
    445  
    446   // check some things 
    447   level.warmupModificationCount = g_warmup.modificationCount; 
    448537} 
    449538 
     
    553642    { 
    554643      char serverinfo[ MAX_INFO_STRING ]; 
     644      qtime_t qt; 
     645      int t; 
     646 
    555647 
    556648      trap_GetServerinfo( serverinfo, sizeof( serverinfo ) ); 
     
    558650      G_LogPrintf( "------------------------------------------------------------\n" ); 
    559651      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 
    560658    } 
    561659  } 
     
    629727  trap_Cvar_Set( "g_alienKills", 0 ); 
    630728  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); 
    631736 
    632737  G_Printf( "-----------------------------------\n" ); 
     
    10451150  int         localHTP = g_humanBuildPoints.integer, 
    10461151              localATP = g_alienBuildPoints.integer; 
    1047  
    1048   if( g_suddenDeathTime.integer && !level.warmupTime ) 
     1152  int buildPoints; 
     1153 
     1154  if( g_suddenDeathTime.integer ) 
    10491155  { 
    10501156    if( G_TimeTilSuddenDeath( ) <= 0 ) 
    10511157    { 
    1052       localHTP = 0; 
    1053       localATP = 0; 
    1054  
    1055       //warn about sudden death 
     1158      //begin sudden death 
    10561159      if( level.suddenDeathWarning < TW_PASSED ) 
    10571160      { 
    10581161        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 
    10591186        level.suddenDeathWarning = TW_PASSED; 
    10601187      } 
     
    10711198    } 
    10721199  } 
     1200 
     1201  if( level.suddenDeath ) 
     1202  { 
     1203    localHTP = level.suddenDeathHBuildPoints; 
     1204    localATP = level.suddenDeathABuildPoints; 
     1205  } 
    10731206  else 
    10741207  { 
     
    10831216  level.overmindPresent = qfalse; 
    10841217 
     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 
    10851232  for( i = 1, ent = g_entities + i ; i < level.num_entities ; i++, ent++ ) 
    10861233  { 
     
    11011248        level.overmindPresent = qtrue; 
    11021249 
    1103       if( BG_FindTeamForBuildable( buildable ) == BIT_HUMANS ) 
     1250      if( !level.suddenDeath || BG_FindReplaceableTestForBuildable( buildable ) ) 
    11041251      { 
    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        } 
    11131272      } 
    11141273    } 
     
    14161575 
    14171576  // 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 ) ); 
    14191578 
    14201579  ent->client->ps.eFlags = 0; 
     
    14821641  G_ClearVotes( ); 
    14831642 
     1643  // reset warmup messages 
     1644  level.warmupMessageTime = 0; 
     1645 
    14841646  FindIntermissionPoint( ); 
    14851647 
     
    15201682    G_AdvanceMapRotation( ); 
    15211683  else 
    1522     trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" ); 
     1684    trap_SendConsoleCommand( EXEC_APPEND, "restartmap\n" ); 
    15231685 
    15241686  level.restarted = qtrue; 
     
    15771739  if( g_dedicated.integer ) 
    15781740    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================= 
     1750G_LogOnlyPrintf 
     1751 
     1752Print to the logfile only (not console) with a time stamp if it is open 
     1753================= 
     1754*/ 
     1755void 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 ); 
    15791773 
    15801774  if( !level.logFile ) 
     
    18692063  } 
    18702064 
    1871   if( g_timelimit.integer && !level.warmupTime ) 
     2065  if( g_timelimit.integer ) 
    18722066  { 
    18732067    if( level.time - level.startTime >= g_timelimit.integer * 60000 ) 
     
    20272221void CheckVote( void ) 
    20282222{ 
     2223  double percent; 
     2224 
    20292225  if( level.voteExecuteTime && level.voteExecuteTime < level.time ) 
    20302226  { 
     
    20322228 
    20332229    trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) ); 
    2034     if( !Q_stricmp( level.voteString, "map_restart" ) || 
     2230    if( !Q_stricmp( level.voteString, "restartmap" ) || 
    20352231        !Q_stricmpn( level.voteString, "map", 3 ) ) 
    20362232    { 
     
    20382234    } 
    20392235  } 
     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; 
    20402241 
    20412242  if( !level.voteTime ) 
    20422243    return; 
    20432244 
     2245// warning: not sure about > or >= 
     2246 
    20442247  if( level.time - level.voteTime >= VOTE_TIME ) 
    20452248  { 
    2046     if( level.voteYes > level.voteNo ) 
     2249    if( level.voteYes >= rint ( (level.numVotingClients * percent) / 100 ) ) 
    20472250    { 
    20482251      // execute the command, then remove the vote 
     
    20582261  else 
    20592262  { 
    2060     if( level.voteYes > level.numVotingClients / 2 ) 
     2263    if( level.voteYes >= rint ( (level.numVotingClients * percent) / 100 ) ) 
    20612264    { 
    20622265      // execute the command, then remove the vote 
     
    20642267      level.voteExecuteTime = level.time + 3000; 
    20652268    } 
    2066     else if( level.voteNo >= ceil( (float)level.numVotingClients / 2 ) ) 
     2269    else if( level.voteNo > rint ( (level.numVotingClients * (100 - percent) ) / 100 ) ) 
    20672270    { 
    20682271      // same behavior as a timeout 
     
    20782281  level.voteTime = 0; 
    20792282  trap_SetConfigstring( CS_VOTE_TIME, "" ); 
     2283} 
     2284 
     2285 
     2286/* 
     2287================== 
     2288CheckWarmup 
     2289================== 
     2290*/ 
     2291void 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  } 
    20802318} 
    20812319 
     
    23642602  CheckVote( ); 
    23652603 
     2604  // cancel if there's a warmup message to print 
     2605  CheckWarmup( ); 
     2606 
    23662607  // check team votes 
    23672608  CheckTeamVote( PTE_HUMANS ); 
     
    23802621} 
    23812622 
     2623/* 
     2624 ================= 
     2625G_Donate 
     2626 
     2627Alms for the poor 
     2628================= 
     2629*/ 
     2630 
     2631int 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 
     2642void 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  
    287287  { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse  }, 
    288288 
    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  }, 
    291291 
    292292  { &g_markDeconstruct, "g_markDeconstruct", "0", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse  }, 
     
    592592  trap_SendConsoleCommand( EXEC_APPEND, 
    593593    va( "exec \"%s/default.cfg\"\n", g_mapConfigs.string ) ); 
    594    
     594 
    595595  trap_SendConsoleCommand( EXEC_APPEND, 
    596596    va( "exec \"%s/%s.cfg\"\n", g_mapConfigs.string, mapname ) ); 
     
    671671  trap_Cvar_Set( "g_mapConfigsLoaded", "0" ); 
    672672 
    673   if ( g_admin.string[ 0 ] ) { 
    674     G_admin_readconfig( NULL, 0 ); 
    675   } 
     673  G_admin_readconfig( NULL, 0 ); 
    676674 
    677675  // initialize all entities for this game 
     
    847845  if( ca->ps.persistant[ PERS_SCORE ] > cb->ps.persistant[ PERS_SCORE ] ) 
    848846    return -1; 
    849   else if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] ) 
     847  if( ca->ps.persistant[ PERS_SCORE ] < cb->ps.persistant[ PERS_SCORE ] ) 
    850848    return 1; 
    851   else 
    852     return 0; 
     849  return 0; 
    853850} 
    854851 
     
    911908    return clientNum; 
    912909  } 
    913   else 
    914     return -1; 
     910  return -1; 
    915911} 
    916912 
     
    14401436 
    14411437  level.numConnectedClients = 0; 
    1442   level.numNonSpectatorClients = 0; 
    14431438  level.numPlayingClients = 0; 
    14441439  level.numVotingClients = 0;   // don't count bots 
     
    14641459      { 
    14651460        level.numPlayingClients++; 
    1466         if( level.clients[ i ].sess.sessionTeam != TEAM_SPECTATOR ) 
    1467           level.numNonSpectatorClients++; 
    1468  
    14691461        if( level.clients[ i ].pers.teamSelection == PTE_ALIENS ) 
    14701462        { 
     
    14821474    } 
    14831475  } 
     1476  level.numNonSpectatorClients = level.numLiveAlienClients + 
     1477    level.numLiveHumanClients; 
    14841478  level.numteamVotingClients[ 0 ] = level.numHumanClients; 
    14851479  level.numteamVotingClients[ 1 ] = level.numAlienClients; 
     
    25862580  } 
    25872581 
    2588   // save position information for all active clients  
     2582  // save position information for all active clients 
    25892583  G_UnlaggedStore( ); 
    25902584 
  • src/game/g_svcmds.c

    r120 r124  
    541541  Q_strncpyz( layouts, s, sizeof( layouts ) ); 
    542542  trap_Cvar_Set( "g_layouts", layouts );  
    543   trap_SendConsoleCommand( EXEC_APPEND, "map_restart\n" ); 
     543  trap_SendConsoleCommand( EXEC_APPEND, "restartmap\n" ); 
    544544  level.restarted = qtrue; 
    545545} 
     
    732732      return qtrue; 
    733733    } 
    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    } 
    735739    G_Printf( "unknown command: %s\n", cmd ); 
    736740    return qtrue; 
  • src/game/g_svcmds.c

    r122 r124  
    345345  gentity_t *check; 
    346346 
    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++ ) 
    350350  { 
    351351    if( !check->inuse ) 
  • src/qcommon/common.c

    r120 r124  
    3434 
    3535int demo_protocols[] = 
    36 { PROTOCOL_VERSION, 0 }; 
     36{ 66, 67, 68, 69, 0 }; 
    3737 
    3838#define MAX_NUM_ARGVS   50 
     
    23742374*/ 
    23752375void Com_Init( char *commandLine ) { 
    2376         char    *s; 
    23772376 
    23782377        Com_Printf( "%s %s %s\n", Q3_VERSION, PLATFORM_STRING, __DATE__ ); 
     
    24812480        Cmd_AddCommand ("writeconfig", Com_WriteConfig_f ); 
    24822481 
    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 ); 
    24852483 
    24862484        Sys_Init(); 
     
    26982696        } while ( msec < minMsec ); 
    26992697        Cbuf_Execute (); 
     2698        Cdelay_Frame (); 
    27002699 
    27012700        if (com_altivec->modified) 
  • src/qcommon/common.c

    r123 r124  
    244244        static int      errorCount; 
    245245        int                     currentTime; 
     246 
     247        Cvar_Set( "com_errorCode", va( "%i", code ) ); 
    246248 
    247249        // when we are running automated scripts, make sure we 
     
    31543156        else 
    31553157        { 
     3158                int completionOffset; 
     3159 
    31563160                if( completionString[0] == '\\' || completionString[0] == '/' ) 
    31573161                        completionString++; 
     
    31723176                        return; // no matches 
    31733177 
    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 ); 
    31773182 
    31783183                completionField->cursor = strlen( completionField->buffer ); 
  • src/qcommon/cvar.c

    r120 r124  
    836836        for (var = cvar_vars ; var ; var = var->next) { 
    837837                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                        } 
    839845                } 
    840846        } 
  • src/qcommon/cvar.c

    r123 r124  
    286286 
    287287        var->flags = flags; 
     288        // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) 
     289        cvar_modifiedFlags |= var->flags; 
    288290 
    289291        hash = generateHashValue(var_name); 
  • src/qcommon/files.c

    r120 r124  
    9898e.g. the qpath "sound/newstuff/test.wav" would be searched for in the following places: 
    9999 
     100home path + current game's directory 
    100101home path + current game's zip files 
    101 home path + current game's directory 
     102base path + current game's directory 
    102103base path + current game's zip files 
    103 base path + current game's directory 
     104cd path + current game's directory 
    104105cd path + current game's zip files 
    105 cd path + current game's directory 
    106  
     106 
     107home path + base game's directory 
    107108home path + base game's zip file 
    108 home path + base game's directory 
     109base path + base game's directory 
    109110base path + base game's zip file 
    110 base path + base game's directory 
     111cd path + base game's directory 
    111112cd path + base game's zip file 
    112 cd path + base game's directory 
    113  
     113 
     114home path + BASEGAME's directory 
    114115home path + BASEGAME's zip file 
    115 home path + BASEGAME's directory 
     116base path + BASEGAME's directory 
    116117base path + BASEGAME's zip file 
    117 base path + BASEGAME's directory 
     118cd path + BASEGAME's directory 
    118119cd path + BASEGAME's zip file 
    119 cd path + BASEGAME's directory 
    120120 
    121121server download, to be written to home path + current game's directory 
     
    24112411        Q_strncpyz( fs_gamedir, dir, sizeof( fs_gamedir ) ); 
    24122412 
    2413         // 
    2414         // add the directory to the search path 
    2415         // 
    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  
    24242413        // find all pak files in this directory 
    24252414        pakfile = FS_BuildOSPath( path, dir, "" ); 
     
    24422431                fs_searchpaths = search; 
    24432432        } 
     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; 
    24442444 
    24452445        // done 
  • src/qcommon/files.c

    r123 r124  
    236236static  cvar_t          *fs_debug; 
    237237static  cvar_t          *fs_homepath; 
     238 
     239#ifdef MACOS_X 
     240// Also search the .app bundle for .pk3 files 
     241static  cvar_t          *fs_apppath; 
     242#endif 
     243 
    238244static  cvar_t          *fs_basepath; 
    239245static  cvar_t          *fs_basegame; 
     
    23872393================ 
    23882394*/ 
    2389 static void FS_AddGameDirectory( const char *path, const char *dir ) { 
     2395void FS_AddGameDirectory( const char *path, const char *dir ) { 
    23902396        searchpath_t    *sp; 
    23912397        int                             i; 
     
    27142720        } 
    27152721        // 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         
    27162730        // NOTE: same filtering below for mods and basegame 
    27172731        if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) { 
  • src/qcommon/msg.c

    r120 r124  
    809809{ NETF(eType), 8 }, 
    810810{ NETF(torsoAnim), 8 }, 
    811 { NETF(weaponAnim), 8 }, 
    812811{ NETF(eventParm), 8 }, 
    813812{ NETF(legsAnim), 8 }, 
     
    825824{ NETF(origin[2]), 0 }, 
    826825{ NETF(solid), 24 }, 
    827 { NETF(misc), MAX_MISC }, 
     826{ NETF(powerups), MAX_POWERUPS }, 
    828827{ NETF(modelindex), 8 }, 
    829828{ NETF(otherEntityNum2), GENTITYNUM_BITS }, 
    830829{ NETF(loopSound), 8 }, 
    831 { NETF(generic1), 16 }, 
     830{ NETF(generic1), 8 }, 
    832831{ NETF(origin2[2]), 0 }, 
    833832{ NETF(origin2[0]), 0 }, 
     
    11271126{ PSF(eventSequence), 16 }, 
    11281127{ PSF(torsoAnim), 8 }, 
    1129 { PSF(weaponAnim), 8 }, 
    11301128{ PSF(movementDir), 4 }, 
    11311129{ PSF(events[0]), 8 }, 
     
    11461144{ PSF(damagePitch), 8 }, 
    11471145{ PSF(damageCount), 8 }, 
    1148 { PSF(ammo), 12 }, 
    1149 { PSF(clips), 4 }, 
    1150 { PSF(generic1), 16 }, 
     1146{ PSF(generic1), 8 }, 
    11511147{ PSF(pm_type), 8 },                                     
    11521148{ PSF(delta_angles[0]), 16 }, 
     
    11761172        int                             statsbits; 
    11771173        int                             persistantbits; 
    1178         int                             miscbits; 
     1174        int                             ammobits; 
     1175        int                             powerupbits; 
    11791176        int                             numFields; 
    11801177        int                             c; 
     
    12561253                } 
    12571254        } 
    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) { 
    12661269                MSG_WriteBits( msg, 0, 1 );     // no change 
    12671270                oldsize += 4; 
     
    12921295 
    12931296 
    1294         if ( miscbits ) { 
     1297        if ( ammobits ) { 
    12951298                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] ); 
    13001314        } else { 
    13011315                MSG_WriteBits( msg, 0, 1 );     // no change 
     
    14111425                } 
    14121426 
    1413                 // parse misc data 
     1427                // parse ammo 
    14141428                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++) { 
    14181432                                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); 
    14201445                                } 
    14211446                        } 
  • src/qcommon/q_shared.h

    r120 r124  
    2929 
    3030#define PRODUCT_NAME            "tremulous" 
    31 #define PRODUCT_VERSION         "1.1.0" 
     31 
     32#ifndef PRODUCT_VERSION 
     33#define PRODUCT_VERSION         "DnC-Eggy" 
     34#endif 
    3235 
    3336#ifdef SVN_VERSION 
     
    3942#define CLIENT_WINDOW_TITLE       "Tremulous " PRODUCT_VERSION 
    4043#define CLIENT_WINDOW_MIN_TITLE   "Tremulous" 
     44 
     45#define FULL_VERSION Q3_VERSION " " PLATFORM_STRING " " __DATE__ 
    4146 
    4247#define MAX_TEAMNAME 32 
     
    9196 **********************************************************************/ 
    9297 
     98#ifdef Q3_VM 
     99 
    93100#include "../game/bg_lib.h" 
    94101 
    95 #ifndef Q3_VM 
     102#else 
    96103 
    97104#include <assert.h> 
     
    336343 
    337344#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 ) 
    339346 
    340347#define COLOR_BLACK             '0' 
     
    10131020#define MAX_STATS                               16 
    10141021#define MAX_PERSISTANT                  16 
    1015 #define MAX_MISC                        16 
     1022#define MAX_POWERUPS                    16 
    10161023#define MAX_WEAPONS                             16               
    10171024 
     
    10871094        int                     stats[MAX_STATS]; 
    10881095        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]; 
    10921098 
    10931099        int                     generic1; 
     
    11531159        TR_SINE,                                        // value = base + sin( time / duration ) * delta 
    11541160        TR_GRAVITY, 
    1155         TR_BUOYANCY 
     1161        TR_BUOYANCY //TA: what the hell is this doing in here anyway? 
    11561162} trType_t; 
    11571163 
     
    12071213 
    12081214        // for players 
    1209         int             misc;                   // bit flags 
     1215        int             powerups;               // bit flags 
    12101216        int             weapon;                 // determines weapon and flash model, etc 
    12111217        int             legsAnim;               // mask off ANIM_TOGGLEBIT 
     
    12781284 
    12791285// server browser sources 
    1280 // AS_MPLAYER is no longer used 
    1281 #define AS_GLOBAL                       0 
     1286// TTimo: AS_MPLAYER is no longer used 
     1287#define AS_GLOBAL                       2 
    12821288#define AS_MPLAYER              1 
    1283 #define AS_LOCAL                        2 
     1289#define AS_LOCAL                        0 
    12841290#define AS_FAVORITES    3 
    12851291 
     
    13191325#define MAX_SERVERSTATUSREQUESTS        16 
    13201326 
    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 
    13241333 
    13251334#endif  // __Q_SHARED_H 
  • src/qcommon/q_shared.h

    r123 r124  
    10601060        int                     torsoAnim;              // mask off ANIM_TOGGLEBIT 
    10611061 
     1062        int                     weaponAnim;             // mask off ANIM_TOGGLEBIT 
     1063 
    10621064        int                     movementDir;    // a number 0 to 7 that represents the reletive angle 
    10631065                                                                // of movement to the view angle (axial and diagonals) 
     
    12151217        int             legsAnim;               // mask off ANIM_TOGGLEBIT 
    12161218        int             torsoAnim;              // mask off ANIM_TOGGLEBIT 
     1219        int             weaponAnim;             // mask off ANIM_TOGGLEBIT 
    12171220 
    12181221        int             generic1; 
  • src/qcommon/qcommon.h

    r120 r124  
    222222*/ 
    223223 
    224 #define PROTOCOL_VERSION        70 
     224#define PROTOCOL_VERSION        69 
    225225 
    226226// maintain a list of compatible protocols for demo playing 
     
    365365// Do not call inside a command function, or current args will be destroyed. 
    366366 
     367void 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 
    367371//=========================================================================== 
    368372 
     
    404408void    Cmd_TokenizeString( const char *text ); 
    405409void    Cmd_TokenizeStringIgnoreQuotes( const char *text_in ); 
     410void    Cmd_TokenizeStringParseCvar( const char *text_in ); 
    406411// Takes a null terminated string.  Does not need to be /n terminated. 
    407412// breaks the string up into arg tokens. 
  • src/qcommon/qcommon.h

    r123 r124  
    544544void    FS_Restart( int checksumFeed ); 
    545545// shutdown and restart the filesystem so changes to fs_gamedir can take effect 
     546 
     547void FS_AddGameDirectory( const char *path, const char *dir ); 
    546548 
    547549char    **FS_ListFiles( const char *directory, const char *extension, int *numfiles ); 
     
    10221024void    Sys_SetDefaultInstallPath(const char *path); 
    10231025char    *Sys_DefaultInstallPath(void); 
     1026 
     1027#ifdef MACOS_X 
     1028char    *Sys_DefaultAppPath(void); 
     1029#endif 
     1030 
    10241031void  Sys_SetDefaultHomePath(const char *path); 
    10251032char    *Sys_DefaultHomePath(void); 
  • src/server/sv_init.c

    r120 r124  
    622622        sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO); 
    623623        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); 
    624628        sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 ); 
    625629        sv_master[1] = Cvar_Get ("sv_master2", "", CVAR_ARCHIVE ); 
  • src/server/sv_init.c

    r36 r124  
    281281        } 
    282282        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        } 
    283288 
    284289        Cvar_Set( "sv_running", "1" ); 
     
    657662                                if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { 
    658663                                        SV_SendServerCommand( cl, "print \"%s\n\"\n", message ); 
    659                                         SV_SendServerCommand( cl, "disconnect" ); 
     664                                        SV_SendServerCommand( cl, "disconnect \"%s\"", message ); 
    660665                                } 
    661666                                // force a snapshot to be sent 
  • src/ui/ui_main.c

    r120 r124  
    4242}; 
    4343 
    44 static const char *netSources[ ] = 
    45 { 
     44static const char *netSources[] = { 
     45  "LAN", 
     46  "Mplayer", 
    4647  "Internet", 
    47   "Mplayer", 
    48   "LAN", 
    4948  "Favorites" 
    5049}; 
  • src/ui/ui_main.c

    r123 r124  
    5151static const int numNetSources = sizeof( netSources ) / sizeof( const char* ); 
    5252 
    53 static const char* netnames[ ] = 
     53static const char *netnames[ ] = 
    5454{ 
    5555  "???", 
     
    389389static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) 
    390390{ 
    391   char * p, *score, *ping, *name; 
     391  char *p, *score, *ping, *name; 
    392392  int i, len; 
    393393 
     
    462462      { 
    463463        if( *p == '\\' ) 
    464           * p++ = '\0'; 
     464          *p++ = '\0'; 
    465465 
    466466        if( !p ) 
     
    16071607static const char *UI_OwnerDrawText( int ownerDraw ) 
    16081608{ 
    1609   const char * s = NULL; 
     1609  const char *s = NULL; 
    16101610 
    16111611  switch( ownerDraw ) 
     
    16611661static int UI_OwnerDrawWidth( int ownerDraw, float scale ) 
    16621662{ 
    1663   const char * s = NULL; 
     1663  const char *s = NULL; 
    16641664 
    16651665  switch( ownerDraw ) 
     
    21962196 
    21972197      while( iterator[ 0 ] != ' ' ) 
    2198         * bufPointer++ = *iterator++; 
     2198        *bufPointer++ = *iterator++; 
    21992199 
    22002200      *bufPointer++ = '\n'; 
     
    22092209 
    22102210      while( iterator[ 0 ] != ' ' ) 
    2211         * bufPointer++ = *iterator++; 
     2211        *bufPointer++ = *iterator++; 
    22122212 
    22132213      *bufPointer++ = '\n'; 
     
    27252725static void UI_RunMenuScript( char **args ) 
    27262726{ 
    2727   const char * name, *name2; 
     2727  const char *name, *name2; 
    27282728  char buff[1024]; 
    27292729  const char *cmd; 
     
    28802880        trap_FS_Read( text, len, f ); 
    28812881        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 ) 
    28822888        trap_FS_FCloseFile( f ); 
    2883  
    2884         Com_sprintf( command, 32, "ptrcrestore %s", text ); 
    2885  
    2886         trap_Cmd_ExecuteText( EXEC_APPEND, command ); 
    2887       } 
    28882889    } 
    28892890    else if( Q_stricmp( name, "Say" ) == 0 ) 
     
    32883289  else if( feederID == FEEDER_TREMHUMANBUILD ) 
    32893290    return uiInfo.humanBuildCount; 
     3291  else if( feederID == FEEDER_RESOLUTIONS ) 
     3292    return uiInfo.numResolutions; 
    32903293 
    32913294  return 0; 
     
    33173320  static char hostname[1024]; 
    33183321  static char clientBuff[32]; 
     3322  static char resolution[MAX_STRING_CHARS]; 
    33193323  static int lastColumn = -1; 
    33203324  static int lastTime = 0; 
    3321   *handle = -1; 
     3325 
     3326  if( handle ) 
     3327    *handle = -1; 
    33223328 
    33233329  if( feederID == FEEDER_MAPS ) 
     
    35013507      return uiInfo.humanBuildList[ index ].text; 
    35023508  } 
     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  } 
    35033527 
    35043528  return ""; 
     
    35513575  else if( feederID == FEEDER_SERVERS ) 
    35523576  { 
    3553     const char * mapName = NULL; 
     3577    const char *mapName = NULL; 
    35543578    uiInfo.serverStatus.currentServer = index; 
    35553579    trap_LAN_GetServerInfo( ui_netSource.integer, uiInfo.serverStatus.displayServers[index], 
     
    36253649  else if( feederID == FEEDER_TREMHUMANBUILD ) 
    36263650    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 
     3658static 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; 
    36273674} 
    36283675 
     
    36843731} 
    36853732 
     3733/* 
     3734================= 
     3735UI_ParseResolutions 
     3736================= 
     3737*/ 
     3738void 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} 
    36863765 
    36873766/* 
     
    37433822  uiInfo.uiDC.feederItemText = &UI_FeederItemText; 
    37443823  uiInfo.uiDC.feederSelection = &UI_FeederSelection; 
     3824  uiInfo.uiDC.feederInitialise = &UI_FeederInitialise; 
    37453825  uiInfo.uiDC.setBinding = &trap_Key_SetBinding; 
    37463826  uiInfo.uiDC.getBindingBuf = &trap_Key_GetBindingBuf; 
     
    37853865 
    37863866  trap_Cvar_Register( NULL, "debug_protocol", "", 0 ); 
     3867 
     3868  UI_ParseResolutions( ); 
    37873869} 
    37883870 
     
    37973879  if( Menu_Count() > 0 ) 
    37983880  { 
    3799     menuDef_t * menu = Menu_GetFocused(); 
     3881    menuDef_t *menu = Menu_GetFocused(); 
    38003882 
    38013883    if( menu ) 
     
    41054187void UI_DrawConnectScreen( qboolean overlay ) 
    41064188{ 
    4107   char      * s; 
     4189  char      *s; 
    41084190  uiClientState_t cstate; 
    41094191  char      info[MAX_INFO_VALUE];