Changeset 123:f8fbc6efbe8c
- Timestamp:
- 04/26/08 01:24:06 (2 years ago)
- Parents:
- 122:4a3bae9504ee (diff), 119:0fc9a5919e03 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Branch:
- mergetrem
- Files:
-
- 1 removed
- 51 modified
-
Makefile (modified) (10 diffs)
-
Makefile (modified) (8 diffs)
-
misc/server.cfg (deleted)
-
src/cgame/cg_draw.c (modified) (7 diffs)
-
src/cgame/cg_draw.c (modified) (59 diffs)
-
src/cgame/cg_local.h (modified) (1 diff)
-
src/cgame/cg_local.h (modified) (11 diffs)
-
src/cgame/cg_main.c (modified) (3 diffs)
-
src/cgame/cg_main.c (modified) (25 diffs)
-
src/cgame/cg_players.c (modified) (1 diff)
-
src/cgame/cg_players.c (modified) (8 diffs)
-
src/cgame/cg_predict.c (modified) (1 diff)
-
src/cgame/cg_predict.c (modified) (1 diff)
-
src/cgame/cg_public.h (modified) (2 diffs)
-
src/cgame/cg_public.h (modified) (2 diffs)
-
src/cgame/cg_scanner.c (modified) (1 diff)
-
src/cgame/cg_scanner.c (modified) (3 diffs)
-
src/cgame/cg_servercmds.c (modified) (4 diffs)
-
src/cgame/cg_servercmds.c (modified) (2 diffs)
-
src/cgame/cg_syscalls.asm (modified) (1 diff)
-
src/cgame/cg_tutorial.c (modified) (2 diffs)
-
src/cgame/cg_tutorial.c (modified) (1 diff)
-
src/cgame/cg_weapons.c (modified) (1 diff)
-
src/cgame/cg_weapons.c (modified) (6 diffs)
-
src/client/cl_cgame.c (modified) (1 diff)
-
src/client/cl_cgame.c (modified) (3 diffs)
-
src/client/cl_main.c (modified) (4 diffs)
-
src/client/cl_main.c (modified) (9 diffs)
-
src/client/client.h (modified) (1 diff)
-
src/client/client.h (modified) (2 diffs)
-
src/game/g_active.c (modified) (17 diffs)
-
src/game/g_active.c (modified) (3 diffs)
-
src/game/g_client.c (modified) (23 diffs)
-
src/game/g_client.c (modified) (4 diffs)
-
src/game/g_cmds.c (modified) (69 diffs)
-
src/game/g_cmds.c (modified) (7 diffs)
-
src/game/g_local.h (modified) (23 diffs)
-
src/game/g_local.h (modified) (2 diffs)
-
src/qcommon/common.c (modified) (4 diffs)
-
src/qcommon/common.c (modified) (8 diffs)
-
src/qcommon/cvar.c (modified) (1 diff)
-
src/qcommon/cvar.c (modified) (3 diffs)
-
src/qcommon/files.c (modified) (3 diffs)
-
src/qcommon/files.c (modified) (3 diffs)
-
src/qcommon/q_shared.h (modified) (10 diffs)
-
src/qcommon/q_shared.h (modified) (1 diff)
-
src/qcommon/qcommon.h (modified) (3 diffs)
-
src/qcommon/qcommon.h (modified) (2 diffs)
-
src/ui/ui_main.c (modified) (1 diff)
-
src/ui/ui_main.c (modified) (51 diffs)
-
src/ui/ui_public.h (modified) (2 diffs)
-
src/ui/ui_public.h (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r119 r123 199 199 endif 200 200 201 OPTIMIZE = -O 3 -ffast-math-funroll-loops -fomit-frame-pointer201 OPTIMIZE = -O2 -funroll-loops -fomit-frame-pointer 202 202 203 203 ifeq ($(ARCH),x86_64) 204 OPTIMIZE = -O 3 -fomit-frame-pointer -ffast-math-funroll-loops \204 OPTIMIZE = -O2 -fomit-frame-pointer -funroll-loops \ 205 205 -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 206 206 -fstrength-reduce … … 209 209 else 210 210 ifeq ($(ARCH),x86) 211 OPTIMIZE = -O 3 -march=i586 -fomit-frame-pointer -ffast-math\211 OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 212 212 -funroll-loops -falign-loops=2 -falign-jumps=2 \ 213 213 -falign-functions=2 -fstrength-reduce … … 325 325 326 326 ifeq ($(ARCH),ppc) 327 OPTIMIZE += -faltivec -O 3327 OPTIMIZE += -faltivec -O2 328 328 endif 329 329 ifeq ($(ARCH),x86) … … 375 375 $(LIBSDIR)/macosx/libSDL-1.2.0.dylib 376 376 377 OPTIMIZE += -f fast-math -falign-loops=16377 OPTIMIZE += -falign-loops=16 378 378 379 379 ifneq ($(HAVE_VM_COMPILED),true) … … 430 430 endif 431 431 432 OPTIMIZE = -O 3 -march=i586 -fno-omit-frame-pointer -ffast-math\432 OPTIMIZE = -O2 -march=i586 -fno-omit-frame-pointer \ 433 433 -falign-loops=2 -funroll-loops -falign-jumps=2 -falign-functions=2 \ 434 434 -fstrength-reduce … … 502 502 ifeq ($(ARCH),axp) 503 503 BASE_CFLAGS += -DNO_VM_COMPILED 504 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3 -ffast-math-funroll-loops \504 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -funroll-loops \ 505 505 -fomit-frame-pointer -fexpensive-optimizations 506 506 else 507 507 ifeq ($(ARCH),x86) 508 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3-mtune=pentiumpro \509 -march=pentium -fomit-frame-pointer -pipe -ffast-math\508 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 -mtune=pentiumpro \ 509 -march=pentium -fomit-frame-pointer -pipe \ 510 510 -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 511 511 -funroll-loops -fstrength-reduce … … 639 639 BASE_CFLAGS=-Dstricmp=strcasecmp -Xcpluscomm -woff 1185 -mips3 \ 640 640 -nostdinc -I. -I$(ROOT)/usr/include -DNO_VM_COMPILED 641 RELEASE_CFLAGS=$(BASE_CFLAGS) -O 3641 RELEASE_CFLAGS=$(BASE_CFLAGS) -O2 642 642 DEBUG_CFLAGS=$(BASE_CFLAGS) -g 643 643 … … 678 678 -pipe -DUSE_ICON $(shell sdl-config --cflags) 679 679 680 OPTIMIZE = -O 3 -ffast-math-funroll-loops680 OPTIMIZE = -O2 -funroll-loops 681 681 682 682 ifeq ($(ARCH),sparc) 683 OPTIMIZE = -O 3 -ffast-math-falign-loops=2 \683 OPTIMIZE = -O2 -falign-loops=2 \ 684 684 -falign-jumps=2 -falign-functions=2 -fstrength-reduce \ 685 685 -mtune=ultrasparc -mv8plus -mno-faster-structs \ … … 687 687 else 688 688 ifeq ($(ARCH),x86) 689 OPTIMIZE = -O 3 -march=i586 -fomit-frame-pointer -ffast-math\689 OPTIMIZE = -O2 -march=i586 -fomit-frame-pointer \ 690 690 -funroll-loops -falign-loops=2 -falign-jumps=2 \ 691 691 -falign-functions=2 -fstrength-reduce … … 723 723 BASE_CFLAGS=-DNO_VM_COMPILED 724 724 DEBUG_CFLAGS=$(BASE_CFLAGS) -g 725 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O 3725 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O2 726 726 727 727 SHLIBEXT=so -
Makefile
r122 r123 39 39 export PLATFORM 40 40 41 ifeq ($(COMPILE_ARCH),powerpc) 42 COMPILE_ARCH=ppc 43 endif 44 41 45 ifndef ARCH 42 46 ARCH=$(COMPILE_ARCH) 43 endif44 45 ifeq ($(ARCH),powerpc)46 ARCH=ppc47 47 endif 48 48 export ARCH … … 254 254 BASE_CFLAGS += -m32 255 255 LDFLAGS+=-m32 256 else 257 ifeq ($(ARCH),ppc64) 258 BASE_CFLAGS += -m64 259 LDFLAGS += -m64 260 endif 256 261 endif 257 262 … … 357 362 endif 358 363 359 BASE_CFLAGS += -D_THREAD_SAFE=1 -I$(SDLHDIR)/include 364 BASE_CFLAGS += -D_THREAD_SAFE=1 365 366 ifeq ($(USE_LOCAL_HEADERS),1) 367 BASE_CFLAGS += -I$(SDLHDIR)/include 368 endif 369 360 370 # We copy sdlmain before ranlib'ing it so that subversion doesn't think 361 371 # the file has been modified by each build. … … 399 409 400 410 BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ 401 -DUSE_ICON -I$(SDLHDIR)/include 411 -DUSE_ICON 412 413 ifeq ($(USE_LOCAL_HEADERS),1) 414 BASE_CFLAGS += -I$(SDLHDIR)/include 415 endif 402 416 403 417 ifeq ($(USE_OPENAL),1) … … 528 542 529 543 else # ifeq freebsd 544 545 ############################################################################# 546 # SETUP AND BUILD -- OPENBSD 547 ############################################################################# 548 549 ifeq ($(PLATFORM),openbsd) 550 551 #default to i386, no tests done on anything else 552 ARCH=i386 553 554 555 BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ 556 -DUSE_ICON $(shell sdl-config --cflags) 557 558 ifeq ($(USE_OPENAL),1) 559 BASE_CFLAGS += -DUSE_OPENAL 560 ifeq ($(USE_OPENAL_DLOPEN),1) 561 BASE_CFLAGS += -DUSE_OPENAL_DLOPEN 562 endif 563 endif 564 565 ifeq ($(USE_CODEC_VORBIS),1) 566 BASE_CFLAGS += -DUSE_CODEC_VORBIS 567 endif 568 569 BASE_CFLAGS += -DNO_VM_COMPILED -I/usr/X11R6/include -I/usr/local/include 570 RELEASE_CFLAGS=$(BASE_CFLAGS) -DNDEBUG -O3 \ 571 -march=pentium -fomit-frame-pointer -pipe -ffast-math \ 572 -falign-loops=2 -falign-jumps=2 -falign-functions=2 \ 573 -funroll-loops -fstrength-reduce 574 HAVE_VM_COMPILED=false 575 576 DEBUG_CFLAGS=$(BASE_CFLAGS) -g 577 578 SHLIBEXT=so 579 SHLIBCFLAGS=-fPIC 580 SHLIBLDFLAGS=-shared $(LDFLAGS) 581 582 THREAD_LDFLAGS=-lpthread 583 LDFLAGS=-lm 584 585 CLIENT_LDFLAGS = 586 587 CLIENT_LDFLAGS += $(shell sdl-config --libs) -lGL 588 589 ifeq ($(USE_OPENAL),1) 590 ifneq ($(USE_OPENAL_DLOPEN),1) 591 CLIENT_LDFLAGS += $(THREAD_LDFLAGS) -lopenal 592 endif 593 endif 594 595 ifeq ($(USE_CODEC_VORBIS),1) 596 CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg 597 endif 598 599 600 else # ifeq openbsd 530 601 531 602 ############################################################################# … … 662 733 endif #mingw32 663 734 endif #FreeBSD 735 endif #OpenBSD 664 736 endif #NetBSD 665 737 endif #IRIX … … 831 903 ############################################################################# 832 904 833 TOOLS_CFLAGS = -O2 -Wall -fno-strict-aliasing -MMD \ 905 TOOLS_OPTIMIZE = -g -O2 -Wall -fno-strict-aliasing 906 TOOLS_CFLAGS = $(TOOLS_OPTIMIZE) \ 834 907 -DTEMPDIR=\"$(TEMPDIR)\" -DSYSTEM=\"\" \ 835 908 -I$(Q3LCCSRCDIR) \ 836 909 -I$(LBURGDIR) 837 910 TOOLS_LDFLAGS = 911 912 ifeq ($(GENERATE_DEPENDENCIES),1) 913 TOOLS_CFLAGS += -MMD 914 endif 838 915 839 916 define DO_TOOLS_CC … … 1354 1431 $(B)/base/ui/ui_main.o \ 1355 1432 $(B)/base/ui/ui_atoms.o \ 1356 $(B)/base/ui/ui_players.o \1357 1433 $(B)/base/ui/ui_shared.o \ 1358 1434 $(B)/base/ui/ui_gameinfo.o \ -
src/cgame/cg_draw.c
r119 r123 628 628 int iconsize, numBarbs, i; 629 629 630 numBarbs = ps->ammo;630 BG_UnpackAmmoArray( ps->weapon, ps->ammo, ps->powerups, &numBarbs, NULL ); 631 631 632 632 if( height > width ) … … 703 703 704 704 default: 705 value = ps->ammo;705 BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, &value, NULL ); 706 706 break; 707 707 } … … 862 862 863 863 default: 864 value = ps->clips;864 BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, NULL, &value ); 865 865 866 866 if( value > -1 ) … … 1107 1107 case CG_PLAYER_AMMO_VALUE: 1108 1108 if( cent->currentState.weapon ) 1109 return ps->ammo; 1109 { 1110 int value; 1111 1112 BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, 1113 &value, NULL ); 1114 1115 return value; 1116 } 1110 1117 break; 1111 1118 case CG_PLAYER_CLIPS_VALUE: 1112 1119 if( cent->currentState.weapon ) 1113 return ps->clips; 1120 if( cent->currentState.weapon ) 1121 { 1122 int value; 1123 1124 BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, 1125 NULL, &value ); 1126 1127 return value; 1128 } 1114 1129 break; 1115 1130 case CG_PLAYER_HEALTH: … … 1902 1917 void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color ) 1903 1918 { 1904 int maxAmmo;1919 int ammo, clips, maxAmmo; 1905 1920 centity_t *cent; 1906 1921 playerState_t *ps; … … 1909 1924 ps = &cg.snap->ps; 1910 1925 1926 BG_UnpackAmmoArray( cent->currentState.weapon, ps->ammo, ps->powerups, &ammo, &clips ); 1911 1927 BG_FindAmmoForWeapon( cent->currentState.weapon, &maxAmmo, NULL ); 1912 1928 … … 1920 1936 CG_RegisterWeapon( cent->currentState.weapon ); 1921 1937 1922 if( ps->clips == 0 && !BG_FindInfinteAmmoForWeapon( cent->currentState.weapon ) )1923 { 1924 float ammoPercent = (float) ps->ammo / (float)maxAmmo;1938 if( clips == 0 && !BG_FindInfinteAmmoForWeapon( cent->currentState.weapon ) ) 1939 { 1940 float ammoPercent = (float)ammo / (float)maxAmmo; 1925 1941 1926 1942 if( ammoPercent < 0.33f ) -
src/cgame/cg_draw.c
r122 r123 29 29 #include "../ui/ui_shared.h" 30 30 31 // used for scoreboard32 extern displayContextDef_t cgDC;33 31 menuDef_t *menuScoreboard = NULL; 34 32 … … 38 36 int numSortedTeamPlayers; 39 37 40 //TA UI 41 int CG_Text_Width( const char *text, float scale, int limit ) 42 { 43 int count,len; 44 float out; 45 glyphInfo_t *glyph; 46 float useScale; 47 // FIXME: see ui_main.c, same problem 48 // const unsigned char *s = text; 49 const char *s = text; 50 fontInfo_t *font = &cgDC.Assets.textFont; 51 52 if( scale <= cg_smallFont.value ) 53 font = &cgDC.Assets.smallFont; 54 else if( scale > cg_bigFont.value ) 55 font = &cgDC.Assets.bigFont; 56 57 useScale = scale * font->glyphScale; 58 out = 0; 59 60 if( text ) 61 { 62 len = strlen( text ); 63 if( limit > 0 && len > limit ) 64 len = limit; 65 66 count = 0; 67 while( s && *s && count < len ) 68 { 69 if( Q_IsColorString( s ) ) 70 { 71 s += 2; 72 continue; 73 } 74 else 75 { 76 glyph = &font->glyphs[ (int)*s ]; 77 out += glyph->xSkip; 78 s++; 79 count++; 80 } 81 } 82 } 83 84 return out * useScale; 85 } 86 87 int CG_Text_Height( const char *text, float scale, int limit ) 88 { 89 int len, count; 90 float max; 91 glyphInfo_t *glyph; 92 float useScale; 93 const char *s = text; 94 fontInfo_t *font = &cgDC.Assets.textFont; 95 96 if( scale <= cg_smallFont.value ) 97 font = &cgDC.Assets.smallFont; 98 else if( scale > cg_bigFont.value ) 99 font = &cgDC.Assets.bigFont; 100 101 useScale = scale * font->glyphScale; 102 max = 0; 103 104 if( text ) 105 { 106 len = strlen( text ); 107 if( limit > 0 && len > limit ) 108 len = limit; 109 110 count = 0; 111 while( s && *s && count < len ) 112 { 113 if( Q_IsColorString( s ) ) 114 { 115 s += 2; 116 continue; 117 } 118 else 119 { 120 glyph = &font->glyphs[ (int)*s ]; 121 if( max < glyph->height ) 122 max = glyph->height; 123 124 s++; 125 count++; 126 } 127 } 128 } 129 130 return max * useScale; 131 } 132 133 void CG_Text_PaintChar( float x, float y, float width, float height, float scale, 134 float s, float t, float s2, float t2, qhandle_t hShader ) 135 { 136 float w, h; 137 w = width * scale; 138 h = height * scale; 139 CG_AdjustFrom640( &x, &y, &w, &h ); 140 trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader ); 141 } 142 143 void CG_Text_Paint( float x, float y, float scale, vec4_t color, const char *text, 144 float adjust, int limit, int style ) 145 { 146 int len, count; 147 vec4_t newColor; 148 glyphInfo_t *glyph; 149 float useScale; 150 fontInfo_t *font = &cgDC.Assets.textFont; 151 152 if( scale <= cg_smallFont.value ) 153 font = &cgDC.Assets.smallFont; 154 else if( scale > cg_bigFont.value ) 155 font = &cgDC.Assets.bigFont; 156 157 useScale = scale * font->glyphScale; 158 if( text ) 159 { 160 161 const char *s = text; 162 163 trap_R_SetColor( color ); 164 memcpy( &newColor[ 0 ], &color[ 0 ], sizeof( vec4_t ) ); 165 len = strlen( text ); 166 167 if( limit > 0 && len > limit ) 168 len = limit; 169 170 count = 0; 171 while( s && *s && count < len ) 172 { 173 glyph = &font->glyphs[ (int)*s ]; 174 175 if( Q_IsColorString( s ) ) 176 { 177 memcpy( newColor, g_color_table[ ColorIndex( *( s + 1 ) ) ], sizeof( newColor ) ); 178 newColor[ 3 ] = color[ 3 ]; 179 trap_R_SetColor( newColor ); 180 s += 2; 181 continue; 182 } 183 else 184 { 185 float yadj = useScale * glyph->top; 186 if( style == ITEM_TEXTSTYLE_SHADOWED || 187 style == ITEM_TEXTSTYLE_SHADOWEDMORE ) 188 { 189 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2; 190 colorBlack[ 3 ] = newColor[ 3 ]; 191 trap_R_SetColor( colorBlack ); 192 CG_Text_PaintChar( x + ofs, y - yadj + ofs, 193 glyph->imageWidth, 194 glyph->imageHeight, 195 useScale, 196 glyph->s, 197 glyph->t, 198 glyph->s2, 199 glyph->t2, 200 glyph->glyph ); 201 202 colorBlack[ 3 ] = 1.0; 203 trap_R_SetColor( newColor ); 204 } 205 else if( style == ITEM_TEXTSTYLE_NEON ) 206 { 207 vec4_t glow, outer, inner, white; 208 209 glow[ 0 ] = newColor[ 0 ] * 0.5; 210 glow[ 1 ] = newColor[ 1 ] * 0.5; 211 glow[ 2 ] = newColor[ 2 ] * 0.5; 212 glow[ 3 ] = newColor[ 3 ] * 0.2; 213 214 outer[ 0 ] = newColor[ 0 ]; 215 outer[ 1 ] = newColor[ 1 ]; 216 outer[ 2 ] = newColor[ 2 ]; 217 outer[ 3 ] = newColor[ 3 ]; 218 219 inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5; 220 inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5; 221 inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5; 222 inner[ 3 ] = newColor[ 3 ]; 223 224 white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f; 225 226 trap_R_SetColor( glow ); 227 CG_Text_PaintChar( x - 3, y - yadj - 3, 228 glyph->imageWidth + 6, 229 glyph->imageHeight + 6, 230 useScale, 231 glyph->s, 232 glyph->t, 233 glyph->s2, 234 glyph->t2, 235 glyph->glyph ); 236 237 trap_R_SetColor( outer ); 238 CG_Text_PaintChar( x - 1, y - yadj - 1, 239 glyph->imageWidth + 2, 240 glyph->imageHeight + 2, 241 useScale, 242 glyph->s, 243 glyph->t, 244 glyph->s2, 245 glyph->t2, 246 glyph->glyph ); 247 248 trap_R_SetColor( inner ); 249 CG_Text_PaintChar( x - 0.5, y - yadj - 0.5, 250 glyph->imageWidth + 1, 251 glyph->imageHeight + 1, 252 useScale, 253 glyph->s, 254 glyph->t, 255 glyph->s2, 256 glyph->t2, 257 glyph->glyph ); 258 259 trap_R_SetColor( white ); 260 } 261 262 263 CG_Text_PaintChar( x, y - yadj, 264 glyph->imageWidth, 265 glyph->imageHeight, 266 useScale, 267 glyph->s, 268 glyph->t, 269 glyph->s2, 270 glyph->t2, 271 glyph->glyph ); 272 273 x += ( glyph->xSkip * useScale ) + adjust; 274 s++; 275 count++; 276 } 277 } 278 279 trap_R_SetColor( NULL ); 280 } 38 static void CG_AlignText( rectDef_t *rect, const char *text, float scale, 39 float w, float h, 40 int align, int valign, 41 float *x, float *y ) 42 { 43 float tx, ty; 44 45 if( scale > 0.0f ) 46 { 47 w = UI_Text_Width( text, scale, 0 ); 48 h = UI_Text_Height( text, scale, 0 ); 49 } 50 51 switch( align ) 52 { 53 default: 54 case ALIGN_LEFT: 55 tx = 0.0f; 56 break; 57 58 case ALIGN_RIGHT: 59 tx = rect->w - w; 60 break; 61 62 case ALIGN_CENTER: 63 tx = ( rect->w - w ) / 2.0f; 64 break; 65 } 66 67 switch( valign ) 68 { 69 default: 70 case VALIGN_BOTTOM: 71 ty = rect->h; 72 break; 73 74 case VALIGN_TOP: 75 ty = h; 76 break; 77 78 case VALIGN_CENTER: 79 ty = h + ( ( rect->h - h ) / 2.0f ); 80 break; 81 } 82 83 if( x ) 84 *x = rect->x + tx; 85 86 if( y ) 87 *y = rect->y + ty; 281 88 } 282 89 … … 299 106 300 107 if( !( charHeight = ch ) ) 301 char Width= CHAR_HEIGHT;108 charHeight = CHAR_HEIGHT; 302 109 303 110 if( width < 1 ) … … 336 143 orgL = l; 337 144 338 x += 2;145 x += ( 2.0f * cgDC.aspectScale ); 339 146 340 147 ptr = num; … … 379 186 380 187 if( !( charHeight = ch ) ) 381 char Width= CHAR_HEIGHT;188 charHeight = CHAR_HEIGHT; 382 189 383 190 if( width < 1 ) … … 414 221 l = width; 415 222 416 x += 2+ charWidth * ( width - l );223 x += ( 2.0f * cgDC.aspectScale ) + charWidth * ( width - l ); 417 224 418 225 ptr = num; … … 432 239 433 240 static void CG_DrawProgressBar( rectDef_t *rect, vec4_t color, float scale, 434 int align, int textStyle, int special, float progress ) 241 int align, int textalign, int textStyle, 242 int special, float progress ) 435 243 { 436 244 float rimWidth = rect->h / 20.0f; 437 245 float doneWidth, leftWidth; 438 float tx, ty , tw, th;246 float tx, ty; 439 247 char textBuffer[ 8 ]; 440 248 … … 456 264 457 265 //draw rim and bar 458 if( align == ITEM_ALIGN_RIGHT )266 if( align == ALIGN_RIGHT ) 459 267 { 460 268 CG_DrawPic( rect->x, rect->y, rimWidth, rect->h, cgs.media.whiteShader ); … … 482 290 { 483 291 Com_sprintf( textBuffer, sizeof( textBuffer ), "%d%%", (int)( progress * 100 ) ); 484 tw = CG_Text_Width( textBuffer, scale, 0 ); 485 th = scale * 40.0f; 486 487 switch( align ) 488 { 489 case ITEM_ALIGN_LEFT: 490 tx = rect->x + ( rect->w / 10.0f ); 491 ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); 492 break; 493 494 case ITEM_ALIGN_RIGHT: 495 tx = rect->x + rect->w - ( rect->w / 10.0f ) - tw; 496 ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); 497 break; 498 499 case ITEM_ALIGN_CENTER: 500 tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f ); 501 ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f ); 502 break; 503 504 default: 505 tx = ty = 0.0f; 506 } 507 508 CG_Text_Paint( tx, ty, scale, color, textBuffer, 0, 0, textStyle ); 292 CG_AlignText( rect, textBuffer, scale, 0.0f, 0.0f, textalign, VALIGN_CENTER, &tx, &ty ); 293 294 UI_Text_Paint( tx, ty, scale, color, textBuffer, 0, 0, textStyle ); 509 295 } 510 296 } … … 891 677 } 892 678 893 static void CG_DrawPlayerStamina( rectDef_t *rect, vec4_t color, float scale,894 int align, int textStyle, int special )895 {896 playerState_t *ps = &cg.snap->ps;897 int stamina = ps->stats[ STAT_STAMINA ];898 float progress = ( (float)stamina + (float)MAX_STAMINA ) / ( (float)MAX_STAMINA * 2.0f );899 900 CG_DrawProgressBar( rect, color, scale, align, textStyle, special, progress );901 }902 903 679 static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) 904 680 { … … 1113 889 } 1114 890 1115 static void CG_DrawPlayerHealthBar( rectDef_t *rect, vec4_t color, float scale,1116 int align, int textStyle, int special )1117 {1118 playerState_t *ps;1119 float total;1120 1121 ps = &cg.snap->ps;1122 1123 total = ( (float)ps->stats[ STAT_HEALTH ] / (float)ps->stats[ STAT_MAX_HEALTH ] );1124 CG_DrawProgressBar( rect, color, scale, align, textStyle, special, total );1125 }1126 1127 891 /* 1128 892 ============== … … 1147 911 1148 912 static void CG_DrawProgressLabel( rectDef_t *rect, float text_x, float text_y, vec4_t color, 1149 float scale, int align, const char *s, float fraction ) 913 float scale, int textalign, int textvalign, 914 const char *s, float fraction ) 1150 915 { 1151 916 vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f }; 1152 float tx, tw = CG_Text_Width( s, scale, 0 ); 1153 1154 switch( align ) 1155 { 1156 case ITEM_ALIGN_LEFT: 1157 tx = 0.0f; 1158 break; 1159 1160 case ITEM_ALIGN_RIGHT: 1161 tx = rect->w - tw; 1162 break; 1163 1164 case ITEM_ALIGN_CENTER: 1165 tx = ( rect->w / 2.0f ) - ( tw / 2.0f ); 1166 break; 1167 1168 default: 1169 tx = 0.0f; 1170 } 917 float tx, ty; 918 919 CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty ); 1171 920 1172 921 if( fraction < 1.0f ) 1173 CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, white,922 UI_Text_Paint( text_x + tx, text_y + ty, scale, white, 1174 923 s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); 1175 924 else 1176 CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, color,925 UI_Text_Paint( text_x + tx, text_y + ty, scale, color, 1177 926 s, 0, 0, ITEM_TEXTSTYLE_NEON ); 1178 927 } 1179 928 1180 929 static void CG_DrawMediaProgress( rectDef_t *rect, vec4_t color, float scale, 1181 int align, int text Style, int special )1182 { 1183 CG_DrawProgressBar( rect, color, scale, align, text Style, special, cg.mediaFraction );930 int align, int textalign, int textStyle, int special ) 931 { 932 CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle, special, cg.mediaFraction ); 1184 933 } 1185 934 1186 935 static void CG_DrawMediaProgressLabel( rectDef_t *rect, float text_x, float text_y, 1187 vec4_t color, float scale, int align ) 1188 { 1189 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Map and Textures", cg.mediaFraction ); 936 vec4_t color, float scale, int textalign, int textvalign ) 937 { 938 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign, 939 "Map and Textures", cg.mediaFraction ); 1190 940 } 1191 941 1192 942 static void CG_DrawBuildablesProgress( rectDef_t *rect, vec4_t color, float scale, 1193 int align, int text Style, int special )1194 { 1195 CG_DrawProgressBar( rect, color, scale, align, text Style, special, cg.buildablesFraction );943 int align, int textalign, int textStyle, int special ) 944 { 945 CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle, special, cg.buildablesFraction ); 1196 946 } 1197 947 1198 948 static void CG_DrawBuildablesProgressLabel( rectDef_t *rect, float text_x, float text_y, 1199 vec4_t color, float scale, int align ) 1200 { 1201 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Buildable Models", cg.buildablesFraction ); 949 vec4_t color, float scale, int textalign, int textvalign ) 950 { 951 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign, 952 "Buildable Models", cg.buildablesFraction ); 1202 953 } 1203 954 1204 955 static void CG_DrawCharModelProgress( rectDef_t *rect, vec4_t color, float scale, 1205 int align, int text Style, int special )1206 { 1207 CG_DrawProgressBar( rect, color, scale, align, text Style, special, cg.charModelFraction );956 int align, int textalign, int textStyle, int special ) 957 { 958 CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle, special, cg.charModelFraction ); 1208 959 } 1209 960 1210 961 static void CG_DrawCharModelProgressLabel( rectDef_t *rect, float text_x, float text_y, 1211 vec4_t color, float scale, int align ) 1212 { 1213 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Character Models", cg.charModelFraction ); 962 vec4_t color, float scale, int textalign, int textvalign ) 963 { 964 CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign, 965 "Character Models", cg.charModelFraction ); 1214 966 } 1215 967 1216 968 static void CG_DrawOverallProgress( rectDef_t *rect, vec4_t color, float scale, 1217 int align, int text Style, int special )969 int align, int textalign, int textStyle, int special ) 1218 970 { 1219 971 float total; 1220 972 1221 973 total = ( cg.charModelFraction + cg.buildablesFraction + cg.mediaFraction ) / 3.0f; 1222 CG_DrawProgressBar( rect, color, scale, align, text Style, special, total );974 CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle, special, total ); 1223 975 } 1224 976 … … 1245 997 } 1246 998 1247 static void CG_DrawLoadingString( rectDef_t *rect, float text_x, float text_y, vec4_t color,1248 float scale, int align, int textStyle, const char *s )1249 {1250 float tw, th, tx;1251 int pos, i;1252 char buffer[ 1024 ];1253 char *end;1254 1255 if( !s[ 0 ] )1256 return;1257 1258 strcpy( buffer, s );1259 tw = CG_Text_Width( s, scale, 0 );1260 th = scale * 40.0f;1261 1262 pos = i = 0;1263 1264 while( pos < strlen( s ) )1265 {1266 strcpy( buffer, &s[ pos ] );1267 tw = CG_Text_Width( buffer, scale, 0 );1268 1269 while( tw > rect->w )1270 {1271 end = strrchr( buffer, ' ' );1272 1273 if( end == NULL )1274 break;1275 1276 *end = '\0';1277 tw = CG_Text_Width( buffer, scale, 0 );1278 }1279 1280 switch( align )1281 {1282 case ITEM_ALIGN_LEFT:1283 tx = rect->x;1284 break;1285 1286 case ITEM_ALIGN_RIGHT:1287 tx = rect->x + rect->w - tw;1288 break;1289 1290 case ITEM_ALIGN_CENTER:1291 tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f );1292 break;1293 1294 default:1295 tx = 0.0f;1296 }1297 1298 CG_Text_Paint( tx + text_x, rect->y + text_y + i * ( th + 3 ), scale, color,1299 buffer, 0, 0, textStyle );1300 1301 pos += strlen( buffer ) + 1;1302 i++;1303 }1304 }1305 1306 999 static void CG_DrawLevelName( rectDef_t *rect, float text_x, float text_y, 1307 vec4_t color, float scale, int align, int textStyle ) 1000 vec4_t color, float scale, 1001 int textalign, int textvalign, int textStyle ) 1308 1002 { 1309 1003 const char *s; … … 1311 1005 s = CG_ConfigString( CS_MESSAGE ); 1312 1006 1313 CG_DrawLoadingString( rect, text_x, text_y, color, scale,align, textStyle, s );1007 UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, s ); 1314 1008 } 1315 1009 1316 1010 static void CG_DrawMOTD( rectDef_t *rect, float text_x, float text_y, 1317 vec4_t color, float scale, int align, int textStyle ) 1011 vec4_t color, float scale, 1012 int textalign, int textvalign, int textStyle ) 1318 1013 { 1319 1014 const char *s; … … 1321 1016 s = CG_ConfigString( CS_MOTD ); 1322 1017 1323 CG_DrawLoadingString( rect, text_x, text_y, color, scale,align, textStyle, s );1018 UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, s ); 1324 1019 } 1325 1020 1326 1021 static void CG_DrawHostname( rectDef_t *rect, float text_x, float text_y, 1327 vec4_t color, float scale, int align, int textStyle ) 1022 vec4_t color, float scale, 1023 int textalign, int textvalign, int textStyle ) 1328 1024 { 1329 1025 char buffer[ 1024 ]; … … 1335 1031 Q_CleanStr( buffer ); 1336 1032 1337 CG_DrawLoadingString( rect, text_x, text_y, color, scale,align, textStyle, buffer );1033 UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, buffer ); 1338 1034 } 1339 1035 … … 1459 1155 { 1460 1156 int x = rect->x + rect->w / 2; 1461 CG_Text_Paint( x - CG_Text_Width( CG_GetKillerText( ), scale, 0 ) / 2,1157 UI_Text_Paint( x - UI_Text_Width( CG_GetKillerText( ), scale, 0 ) / 2, 1462 1158 rect->y + rect->h, scale, color, CG_GetKillerText( ), 0, 0, textStyle ); 1463 1159 } … … 1465 1161 1466 1162 1467 static void CG_Text_Paint_Limit( float *maxX, float x, float y, float scale, 1468 vec4_t color, const char* text, float adjust, int limit ) 1469 { 1470 int len, count; 1471 vec4_t newColor; 1472 glyphInfo_t *glyph; 1473 1474 if( text ) 1475 { 1476 const char *s = text; 1477 float max = *maxX; 1478 float useScale; 1479 fontInfo_t *font = &cgDC.Assets.textFont; 1480 1481 if( scale <= cg_smallFont.value ) 1482 font = &cgDC.Assets.smallFont; 1483 else if( scale > cg_bigFont.value ) 1484 font = &cgDC.Assets.bigFont; 1485 1486 useScale = scale * font->glyphScale; 1487 trap_R_SetColor( color ); 1488 len = strlen( text ); 1489 1490 if( limit > 0 && len > limit ) 1491 len = limit; 1492 1493 count = 0; 1494 1495 while( s && *s && count < len ) 1496 { 1497 glyph = &font->glyphs[ (int)*s ]; 1498 1499 if( Q_IsColorString( s ) ) 1500 { 1501 memcpy( newColor, g_color_table[ ColorIndex( *(s+1) ) ], sizeof( newColor ) ); 1502 newColor[ 3 ] = color[ 3 ]; 1503 trap_R_SetColor( newColor ); 1504 s += 2; 1505 continue; 1506 } 1507 else 1508 { 1509 float yadj = useScale * glyph->top; 1510 1511 if( CG_Text_Width( s, useScale, 1 ) + x > max ) 1512 { 1513 *maxX = 0; 1514 break; 1515 } 1516 1517 CG_Text_PaintChar( x, y - yadj, 1518 glyph->imageWidth, 1519 glyph->imageHeight, 1520 useScale, 1521 glyph->s, 1522 glyph->t, 1523 glyph->s2, 1524 glyph->t2, 1525 glyph->glyph ); 1526 x += ( glyph->xSkip * useScale ) + adjust; 1527 *maxX = x; 1528 count++; 1529 s++; 1530 } 1531 } 1532 1533 trap_R_SetColor( NULL ); 1534 } 1535 } 1536 1537 static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader ) 1538 { 1163 static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, int textvalign, vec4_t color, qhandle_t shader ) 1164 { 1165 float y; 1166 1539 1167 if( cg.spectatorLen ) 1540 1168 { … … 1568 1196 else 1569 1197 { 1570 cg.spectatorPaintX += CG_Text_Width( &cg.spectatorList[ cg.spectatorOffset ], scale, 1 ) - 1;1198 cg.spectatorPaintX += UI_Text_Width( &cg.spectatorList[ cg.spectatorOffset ], scale, 1 ) - 1; 1571 1199 cg.spectatorOffset++; 1572 1200 } … … 1594 1222 1595 1223 maxX = rect->x + rect->w - 2; 1596 1597 CG_Text_Paint_Limit( &maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, 1224 CG_AlignText( rect, NULL, 0.0f, 0.0f, UI_Text_EmHeight( scale ), 1225 ALIGN_LEFT, textvalign, NULL, &y ); 1226 1227 UI_Text_Paint_Limit( &maxX, cg.spectatorPaintX, y, scale, color, 1598 1228 &cg.spectatorList[ cg.spectatorOffset ], 0, 0 ); 1599 1229 … … 1601 1231 { 1602 1232 float maxX2 = rect->x + rect->w - 2; 1603 CG_Text_Paint_Limit( &maxX2, cg.spectatorPaintX2, rect->y + rect->h - 3, scale,1233 UI_Text_Paint_Limit( &maxX2, cg.spectatorPaintX2, y, scale, 1604 1234 color, cg.spectatorList, 0, cg.spectatorOffset ); 1605 1235 } … … 1618 1248 /* 1619 1249 ================== 1250 CG_DrawTeamLabel 1251 ================== 1252 */ 1253 static void CG_DrawTeamLabel( rectDef_t *rect, pTeam_t team, float text_x, float text_y, 1254 vec4_t color, float scale, int textalign, int textvalign, int textStyle ) 1255 { 1256 char *t; 1257 char stage[ MAX_TOKEN_CHARS ]; 1258 char *s; 1259 float tx, ty; 1260 1261 stage[ 0 ] = '\0'; 1262 1263 switch( team ) 1264 { 1265 case PTE_ALIENS: 1266 t = "Aliens"; 1267 if( cg.intermissionStarted ) 1268 Com_sprintf( stage, MAX_TOKEN_CHARS, "(Stage %d)", cgs.alienStage + 1 ); 1269 break; 1270 1271 case PTE_HUMANS: 1272 t = "Humans"; 1273 if( cg.intermissionStarted ) 1274 Com_sprintf( stage, MAX_TOKEN_CHARS, "(Stage %d)", cgs.humanStage + 1 ); 1275 break; 1276 1277 default: 1278 t = ""; 1279 break; 1280 } 1281 1282 switch( textalign ) 1283 { 1284 default: 1285 case ALIGN_LEFT: 1286 s = va( "%s %s", t, stage ); 1287 break; 1288 1289 case ALIGN_RIGHT: 1290 s = va( "%s %s", stage, t ); 1291 break; 1292 } 1293 1294 CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty ); 1295 UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle ); 1296 } 1297 1298 /* 1299 ================== 1620 1300 CG_DrawStageReport 1621 1301 ================== 1622 1302 */ 1623 1303 static void CG_DrawStageReport( rectDef_t *rect, float text_x, float text_y, 1624 vec4_t color, float scale, int align, int textStyle )1304 vec4_t color, float scale, int textalign, int textvalign, int textStyle ) 1625 1305 { 1626 1306 char s[ MAX_TOKEN_CHARS ]; 1627 int tx, w, kills; 1628 1629 if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_NONE && !cg.intermissionStarted ) 1630 return; 1307 float tx, ty; 1308 int kills; 1631 1309 1632 1310 if( cg.intermissionStarted ) 1633 { 1634 Com_sprintf( s, MAX_TOKEN_CHARS, 1635 "Stage %d" //PH34R MY MAD-LEET CODING SKILLZ 1636 " " 1637 "Stage %d", 1638 cgs.alienStage + 1, cgs.humanStage + 1 ); 1639 } 1640 else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 1311 return; 1312 1313 if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_NONE ) 1314 return; 1315 1316 if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 1641 1317 { 1642 1318 kills = cgs.alienNextStageThreshold - cgs.alienKills; … … 1665 1341 } 1666 1342 1667 w = CG_Text_Width( s, scale, 0 ); 1668 1669 switch( align ) 1670 { 1671 case ITEM_ALIGN_LEFT: 1672 tx = rect->x; 1673 break; 1674 1675 case ITEM_ALIGN_RIGHT: 1676 tx = rect->x + rect->w - w; 1677 break; 1678 1679 case ITEM_ALIGN_CENTER: 1680 tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f ); 1681 break; 1682 1683 default: 1684 tx = 0.0f; 1685 } 1686 1687 CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle ); 1343 CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty ); 1344 1345 UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle ); 1688 1346 } 1689 1347 … … 1696 1354 #define FPS_STRING "fps" 1697 1355 static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y, 1698 float scale, vec4_t color, int align, int textStyle, 1356 float scale, vec4_t color, 1357 int textalign, int textvalign, int textStyle, 1699 1358 qboolean scalableText ) 1700 1359 { 1701 1360 char *s; 1702 int tx, w, totalWidth, strLength; 1361 float tx, ty; 1362 float w, h, totalWidth; 1363 int strLength; 1703 1364 static int previousTimes[ FPS_FRAMES ]; 1704 1365 static int index; … … 1734 1395 1735 1396 s = va( "%d", fps ); 1736 w = CG_Text_Width( "0", scale, 0 ); 1397 w = UI_Text_Width( "0", scale, 0 ); 1398 h = UI_Text_Height( "0", scale, 0 ); 1737 1399 strLength = CG_DrawStrlen( s ); 1738 totalWidth = CG_Text_Width( FPS_STRING, scale, 0 ) + w * strLength; 1739 1740 switch( align ) 1741 { 1742 case ITEM_ALIGN_LEFT: 1743 tx = rect->x; 1744 break; 1745 1746 case ITEM_ALIGN_RIGHT: 1747 tx = rect->x + rect->w - totalWidth; 1748 break; 1749 1750 case ITEM_ALIGN_CENTER: 1751 tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); 1752 break; 1753 1754 default: 1755 tx = 0.0f; 1756 } 1400 totalWidth = UI_Text_Width( FPS_STRING, scale, 0 ) + w * strLength; 1401 1402 CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty ); 1757 1403 1758 1404 if( scalableText ) … … 1765 1411 c[ 1 ] = '\0'; 1766 1412 1767 CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );1413 UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle ); 1768 1414 } 1415 1416 UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, FPS_STRING, 0, 0, textStyle ); 1769 1417 } 1770 1418 else … … 1774 1422 trap_R_SetColor( NULL ); 1775 1423 } 1776 1777 if( scalableText )1778 CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, FPS_STRING, 0, 0, textStyle );1779 1424 } 1780 1425 } … … 1837 1482 */ 1838 1483 static void CG_DrawTimer( rectDef_t *rect, float text_x, float text_y, 1839 float scale, vec4_t color, int align, int textStyle ) 1484 float scale, vec4_t color, 1485 int textalign, int textvalign, int textStyle ) 1840 1486 { 1841 1487 char *s; 1842 int i, tx, w, totalWidth, strLength; 1488 float tx, ty; 1489 int i, strLength; 1490 float w, h, totalWidth; 1843 1491 int mins, seconds, tens; 1844 1492 int msec; … … 1856 1504 1857 1505 s = va( "%d:%d%d", mins, tens, seconds ); 1858 w = CG_Text_Width( "0", scale, 0 ); 1506 w = UI_Text_Width( "0", scale, 0 ); 1507 h = UI_Text_Height( "0", scale, 0 ); 1859 1508 strLength = CG_DrawStrlen( s ); 1860 1509 totalWidth = w * strLength; 1861 1510 1862 switch( align ) 1863 { 1864 case ITEM_ALIGN_LEFT: 1865 tx = rect->x; 1866 break; 1867 1868 case ITEM_ALIGN_RIGHT: 1869 tx = rect->x + rect->w - totalWidth; 1870 break; 1871 1872 case ITEM_ALIGN_CENTER: 1873 tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); 1874 break; 1875 1876 default: 1877 tx = 0.0f; 1878 } 1511 CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty ); 1879 1512 1880 1513 for( i = 0; i < strLength; i++ ) … … 1885 1518 c[ 1 ] = '\0'; 1886 1519 1887 CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );1520 UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle ); 1888 1521 } 1889 1522 } … … 1895 1528 */ 1896 1529 static void CG_DrawClock( rectDef_t *rect, float text_x, float text_y, 1897 float scale, vec4_t color, int align, int textStyle ) 1530 float scale, vec4_t color, 1531 int textalign, int textvalign, int textStyle ) 1898 1532 { 1899 1533 char *s; 1900 int i, tx, w, totalWidth, strLength; 1534 float tx, ty; 1535 int i, strLength; 1536 float w, h, totalWidth; 1901 1537 qtime_t qt; 1902 1538 int t; … … 1929 1565 s = va( "%d%s%02d%s", h, ( qt.tm_sec % 2 ) ? ":" : " ", qt.tm_min, pm ); 1930 1566 } 1931 w = CG_Text_Width( "0", scale, 0 ); 1567 w = UI_Text_Width( "0", scale, 0 ); 1568 h = UI_Text_Height( "0", scale, 0 ); 1932 1569 strLength = CG_DrawStrlen( s ); 1933 1570 totalWidth = w * strLength; 1934 1571 1935 switch( align ) 1936 { 1937 case ITEM_ALIGN_LEFT: 1938 tx = rect->x; 1939 break; 1940 1941 case ITEM_ALIGN_RIGHT: 1942 tx = rect->x + rect->w - totalWidth; 1943 break; 1944 1945 case ITEM_ALIGN_CENTER: 1946 tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); 1947 break; 1948 1949 default: 1950 tx = 0.0f; 1951 } 1572 CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty ); 1952 1573 1953 1574 for( i = 0; i < strLength; i++ ) … … 1958 1579 c[ 1 ] = '\0'; 1959 1580 1960 CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );1581 UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle ); 1961 1582 } 1962 1583 } … … 1968 1589 */ 1969 1590 static void CG_DrawSnapshot( rectDef_t *rect, float text_x, float text_y, 1970 float scale, vec4_t color, int align, int textStyle ) 1591 float scale, vec4_t color, 1592 int textalign, int textvalign, int textStyle ) 1971 1593 { 1972 1594 char *s; 1973 int w, tx;1595 float tx, ty; 1974 1596 1975 1597 if( !cg_drawSnapshot.integer ) … … 1978 1600 s = va( "time:%d snap:%d cmd:%d", cg.snap->serverTime, 1979 1601 cg.latestSnapshotNum, cgs.serverCommandSequence ); 1980 w = CG_Text_Width( s, scale, 0 ); 1981 1982 switch( align ) 1983 { 1984 case ITEM_ALIGN_LEFT: 1985 tx = rect->x; 1986 break; 1987 1988 case ITEM_ALIGN_RIGHT: 1989 tx = rect->x + rect->w - w; 1990 break; 1991 1992 case ITEM_ALIGN_CENTER: 1993 tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f ); 1994 break; 1995 1996 default: 1997 tx = 0.0f; 1998 } 1999 2000 CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle ); 1602 1603 CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty ); 1604 1605 UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle ); 2001 1606 } 2002 1607 … … 2109 1714 // also add text in center of screen 2110 1715 s = "Connection Interrupted"; 2111 w = CG_Text_Width( s, 0.7f, 0 );2112 CG_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED );1716 w = UI_Text_Width( s, 0.7f, 0 ); 1717 UI_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); 2113 1718 2114 1719 // blink the icon … … 2263 1868 2264 1869 if( cg_nopredict.integer || cg_synchronousClients.integer ) 2265 CG_Text_Paint( ax, ay, 0.5, white, "snc", 0, 0, ITEM_TEXTSTYLE_NORMAL );1870 UI_Text_Paint( ax, ay, 0.5, white, "snc", 0, 0, ITEM_TEXTSTYLE_NORMAL ); 2266 1871 else 2267 1872 { … … 2269 1874 2270 1875 s = va( "%d", cg.ping ); 2271 ax = rect->x + ( rect->w / 2.0f ) - ( CG_Text_Width( s, scale, 0 ) / 2.0f ) + text_x;2272 ay = rect->y + ( rect->h / 2.0f ) + ( CG_Text_Height( s, scale, 0 ) / 2.0f ) + text_y;1876 ax = rect->x + ( rect->w / 2.0f ) - ( UI_Text_Width( s, scale, 0 ) / 2.0f ) + text_x; 1877 ay = rect->y + ( rect->h / 2.0f ) + ( UI_Text_Height( s, scale, 0 ) / 2.0f ) + text_y; 2273 1878 2274 1879 Vector4Copy( textColor, adjustedColor ); 2275 1880 adjustedColor[ 3 ] = 0.5f; 2276 CG_Text_Paint( ax, ay, scale, adjustedColor, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );1881 UI_Text_Paint( ax, ay, scale, adjustedColor, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); 2277 1882 } 2278 1883 2279 1884 CG_DrawDisconnect( ); 2280 }2281 2282 /*2283 ==============2284 CG_DrawTextBlock2285 ==============2286 */2287 static void CG_DrawTextBlock( rectDef_t *rect, float text_x, float text_y, vec4_t color,2288 float scale, int align, int textStyle, const char *text,2289 menuDef_t *parent, itemDef_t *textItem )2290 {2291 float x, y, w, h;2292 2293 //offset the text2294 x = rect->x;2295 y = rect->y;2296 w = rect->w - ( 16 + ( 2 * text_x ) ); //16 to ensure text within frame2297 h = rect->h;2298 2299 textItem->text = text;2300 2301 textItem->parent = parent;2302 memcpy( textItem->window.foreColor, color, sizeof( vec4_t ) );2303 textItem->window.flags = 0;2304 2305 switch( align )2306 {2307 case ITEM_ALIGN_LEFT:2308 textItem->window.rect.x = x;2309 break;2310 2311 case ITEM_ALIGN_RIGHT:2312 textItem->window.rect.x = x + w;2313 break;2314 2315 case ITEM_ALIGN_CENTER:2316 textItem->window.rect.x = x + ( w / 2 );2317 break;2318 2319 default:2320 textItem->window.rect.x = x;2321 break;2322 }2323 2324 textItem->window.rect.y = y;2325 textItem->window.rect.w = w;2326 textItem->window.rect.h = h;2327 textItem->window.borderSize = 0;2328 textItem->textRect.x = 0;2329 textItem->textRect.y = 0;2330 textItem->textRect.w = 0;2331 textItem->textRect.h = 0;2332 textItem->textalignment = align;2333 textItem->textalignx = text_x;2334 textItem->textaligny = text_y;2335 textItem->textscale = scale;2336 textItem->textStyle = textStyle;2337 2338 //hack to utilise existing autowrap code2339 Item_Text_AutoWrapped_Paint( textItem );2340 1885 } 2341 1886 … … 2346 1891 */ 2347 1892 static void CG_DrawConsole( rectDef_t *rect, float text_x, float text_y, vec4_t color, 2348 float scale, int align, int textStyle ) 2349 { 2350 static menuDef_t dummyParent; 2351 static itemDef_t textItem; 2352 2353 CG_DrawTextBlock( rect, text_x, text_y, color, scale, align, textStyle, 2354 cg.consoleText, &dummyParent, &textItem ); 1893 float scale, int textalign, int textvalign, int textStyle ) 1894 { 1895 UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, cg.consoleText ); 2355 1896 } 2356 1897 … … 2361 1902 */ 2362 1903 static void CG_DrawTutorial( rectDef_t *rect, float text_x, float text_y, vec4_t color, 2363 float scale, int align, int textStyle ) 2364 { 2365 static menuDef_t dummyParent; 2366 static itemDef_t textItem; 2367 1904 float scale, int textalign, int textvalign, int textStyle ) 1905 { 2368 1906 if( !cg_tutorial.integer ) 2369 1907 return; 2370 1908 2371 CG_DrawTextBlock( rect, text_x, text_y, color, scale, align, textStyle, 2372 CG_TutorialText( ), &dummyParent, &textItem ); 1909 UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, CG_TutorialText( ) ); 2373 1910 } 2374 1911 … … 2468 2005 w = h = wi->crossHairSize; 2469 2006 2007 w *= cgDC.aspectScale; 2008 2470 2009 x = cg_crosshairX.integer; 2471 2010 y = cg_crosshairY.integer; … … 2554 2093 2555 2094 name = cgs.clientinfo[ cg.crosshairClientNum ].name; 2556 w = CG_Text_Width( name, scale, 0 );2095 w = UI_Text_Width( name, scale, 0 ); 2557 2096 x = rect->x + rect->w / 2; 2558 CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );2097 UI_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); 2559 2098 trap_R_SetColor( NULL ); 2560 2099 } … … 2570 2109 void CG_OwnerDraw( float x, float y, float w, float h, float text_x, 2571 2110 float text_y, int ownerDraw, int ownerDrawFlags, 2572 int align, float special, float scale, vec4_t color, 2111 int align, int textalign, int textvalign, float special, 2112 float scale, vec4_t color, 2573 2113 qhandle_t shader, int textStyle ) 2574 2114 { … … 2597 2137 CG_DrawPlayerBankValue( &rect, color, qfalse ); 2598 2138 break; 2599 case CG_PLAYER_STAMINA:2600 CG_DrawPlayerStamina( &rect, color, scale, align, textStyle, special );2601 break;2602 2139 case CG_PLAYER_STAMINA_1: 2603 2140 CG_DrawPlayerStamina1( &rect, color, shader ); … … 2627 2164 CG_DrawPlayerHealthValue( &rect, color ); 2628 2165 break; 2629 case CG_PLAYER_HEALTH_BAR:2630 CG_DrawPlayerHealthBar( &rect, color, scale, align, textStyle, special );2631 break;2632 2166 case CG_PLAYER_HEALTH_CROSS: 2633 2167 CG_DrawPlayerHealthCross( &rect, color, shader ); … … 2673 2207 break; 2674 2208 case CG_SPECTATORS: 2675 CG_DrawTeamSpectators( &rect, scale, color, shader );2209 CG_DrawTeamSpectators( &rect, scale, textvalign, color, shader ); 2676 2210 break; 2677 2211 case CG_PLAYER_CROSSHAIRNAMES: … … 2679 2213 break; 2680 2214 case CG_STAGE_REPORT_TEXT: 2681 CG_DrawStageReport( &rect, text_x, text_y, color, scale, align, textStyle ); 2215 CG_DrawStageReport( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2216 break; 2217 case CG_ALIENS_SCORE_LABEL: 2218 CG_DrawTeamLabel( &rect, PTE_ALIENS, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2219 break; 2220 case CG_HUMANS_SCORE_LABEL: 2221 CG_DrawTeamLabel( &rect, PTE_HUMANS, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2682 2222 break; 2683 2223 … … 2687 2227 break; 2688 2228 case CG_LOAD_MEDIA: 2689 CG_DrawMediaProgress( &rect, color, scale, align, text Style, special );2229 CG_DrawMediaProgress( &rect, color, scale, align, textalign, textStyle, special ); 2690 2230 break; 2691 2231 case CG_LOAD_MEDIA_LABEL: 2692 CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, align );2232 CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, textalign, textvalign ); 2693 2233 break; 2694 2234 case CG_LOAD_BUILDABLES: 2695 CG_DrawBuildablesProgress( &rect, color, scale, align, text Style, special );2235 CG_DrawBuildablesProgress( &rect, color, scale, align, textalign, textStyle, special ); 2696 2236 break; 2697 2237 case CG_LOAD_BUILDABLES_LABEL: 2698 CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, align );2238 CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, textalign, textvalign ); 2699 2239 break; 2700 2240 case CG_LOAD_CHARMODEL: 2701 CG_DrawCharModelProgress( &rect, color, scale, align, text Style, special );2241 CG_DrawCharModelProgress( &rect, color, scale, align, textalign, textStyle, special ); 2702 2242 break; 2703 2243 case CG_LOAD_CHARMODEL_LABEL: 2704 CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, align );2244 CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, textalign, textvalign ); 2705 2245 break; 2706 2246 case CG_LOAD_OVERALL: 2707 CG_DrawOverallProgress( &rect, color, scale, align, text Style, special );2247 CG_DrawOverallProgress( &rect, color, scale, align, textalign, textStyle, special ); 2708 2248 break; 2709 2249 case CG_LOAD_LEVELNAME: 2710 CG_DrawLevelName( &rect, text_x, text_y, color, scale, align, textStyle );2250 CG_DrawLevelName( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2711 2251 break; 2712 2252 case CG_LOAD_MOTD: 2713 CG_DrawMOTD( &rect, text_x, text_y, color, scale, align, textStyle );2253 CG_DrawMOTD( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2714 2254 break; 2715 2255 case CG_LOAD_HOSTNAME: 2716 CG_DrawHostname( &rect, text_x, text_y, color, scale, align, textStyle );2256 CG_DrawHostname( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2717 2257 break; 2718 2258 2719 2259 case CG_FPS: 2720 CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qtrue );2260 CG_DrawFPS( &rect, text_x, text_y, scale, color, textalign, textvalign, textStyle, qtrue ); 2721 2261 break; 2722 2262 case CG_FPS_FIXED: 2723 CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qfalse );2263 CG_DrawFPS( &rect, text_x, text_y, scale, color, textalign, textvalign, textStyle, qfalse ); 2724 2264 break; 2725 2265 case CG_TIMER: 2726 CG_DrawTimer( &rect, text_x, text_y, scale, color, align, textStyle );2266 CG_DrawTimer( &rect, text_x, text_y, scale, color, textalign, textvalign, textStyle ); 2727 2267 break; 2728 2268 case CG_CLOCK: 2729 CG_DrawClock( &rect, text_x, text_y, scale, color, align, textStyle );2269 CG_DrawClock( &rect, text_x, text_y, scale, color, textalign, textvalign, textStyle ); 2730 2270 break; 2731 2271 case CG_TIMER_MINS: … … 2736 2276 break; 2737 2277 case CG_SNAPSHOT: 2738 CG_DrawSnapshot( &rect, text_x, text_y, scale, color, align, textStyle );2278 CG_DrawSnapshot( &rect, text_x, text_y, scale, color, textalign, textvalign, textStyle ); 2739 2279 break; 2740 2280 case CG_LAGOMETER: … … 2750 2290 2751 2291 case CG_CONSOLE: 2752 CG_DrawConsole( &rect, text_x, text_y, color, scale, align, textStyle );2292 CG_DrawConsole( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2753 2293 break; 2754 2294 2755 2295 case CG_TUTORIAL: 2756 CG_DrawTutorial( &rect, text_x, text_y, color, scale, align, textStyle );2296 CG_DrawTutorial( &rect, text_x, text_y, color, scale, textalign, textvalign, textStyle ); 2757 2297 break; 2758 2298 … … 2819 2359 void CG_ShowTeamMenu( void ) 2820 2360 { 2821 Menus_ OpenByName( "teamMenu" );2361 Menus_ActivateByName( "teamMenu" ); 2822 2362 } 2823 2363 … … 2883 2423 { 2884 2424 } 2885 2886 2887 void CG_GetTeamColor( vec4_t *color )2888 {2889 (*color)[ 0 ] = (*color)[ 2 ] = 0.0f;2890 (*color)[ 1 ] = 0.17f;2891 (*color)[ 3 ] = 0.25f;2892 }2893 2425 //END TA UI 2894 2426 … … 2998 2530 linebuffer[ l ] = 0; 2999 2531 3000 w = CG_Text_Width( linebuffer, 0.5, 0 );3001 h = CG_Text_Height( linebuffer, 0.5, 0 );2532 w = UI_Text_Width( linebuffer, 0.5, 0 ); 2533 h = UI_Text_Height( linebuffer, 0.5, 0 ); 3002 2534 x = ( SCREEN_WIDTH - w ) / 2; 3003 CG_Text_Paint( x, y + h, 0.5, color, linebuffer, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE );2535 UI_Text_Paint( x, y + h, 0.5, color, linebuffer, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); 3004 2536 y += h + 6; 3005 2537 … … 3054 2586 s = va( "VOTE(%i): \"%s\" [%s]Yes:%i [%s]No:%i", sec, cgs.voteString, 3055 2587 yeskey, cgs.voteYes, nokey, cgs.voteNo ); 3056 CG_Text_Paint( 8, 340, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );2588 UI_Text_Paint( 8, 340, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); 3057 2589 } 3058 2590 … … 3098 2630 nokey, cgs.teamVoteNo[ cs_offset ] ); 3099 2631 3100 CG_Text_Paint( 8, 360, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );2632 UI_Text_Paint( 8, 360, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL ); 3101 2633 } 3102 2634 … … 3187 2719 strcat( buffer, cgs.clientinfo[ cg.snap->ps.clientNum ].name ); 3188 2720 3189 w = CG_Text_Width( buffer, 0.7f, 0 );3190 CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );2721 w = UI_Text_Width( buffer, 0.7f, 0 ); 2722 UI_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); 3191 2723 3192 2724 return qtrue; … … 3215 2747 cg.snap->ps.persistant[ PERS_QUEUEPOS ] + 1 ); 3216 2748 3217 w = CG_Text_Width( buffer, 0.7f, 0 );3218 CG_Text_Paint( 320 - w / 2, 360, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );2749 w = UI_Text_Width( buffer, 0.7f, 0 ); 2750 UI_Text_Paint( 320 - w / 2, 360, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); 3219 2751 3220 2752 if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) … … 3235 2767 } 3236 2768 3237 w = CG_Text_Width( buffer, 0.7f, 0 );3238 CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );2769 w = UI_Text_Width( buffer, 0.7f, 0 ); 2770 UI_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); 3239 2771 3240 2772 return qtrue; … … 3277 2809 if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) 3278 2810 { 3279 w = CG_Text_Width( SPECTATOR_STRING, 0.7f, 0 );3280 CG_Text_Paint( 320 - w / 2, 440, 0.7f, color, SPECTATOR_STRING, 0, 0, ITEM_TEXTSTYLE_SHADOWED );2811 w = UI_Text_Width( SPECTATOR_STRING, 0.7f, 0 ); 2812 UI_Text_Paint( 320 - w / 2, 440, 0.7f, color, SPECTATOR_STRING, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); 3281 2813 } 3282 2814 else -
src/cgame/cg_local.h
r119 r123 1385 1385 extern markPoly_t cg_markPolys[ MAX_MARK_POLYS ]; 1386 1386 1387 extern vmCvar_t cg_version; 1387 1388 extern vmCvar_t cg_centertime; 1388 1389 extern vmCvar_t cg_runpitch; -
src/cgame/cg_local.h
r122 r123 80 80 #define TEAM_OVERLAY_MAXLOCATION_WIDTH 16 81 81 82 #define DEFAULT_MODEL "sarge"83 #define DEFAULT_TEAM_MODEL "sarge"84 #define DEFAULT_TEAM_HEAD "sarge"85 86 82 typedef enum 87 83 { … … 709 705 pTeam_t team; 710 706 711 int botSkill; // 0 = not bot, 1-5 = bot712 713 707 vec3_t color1; 714 708 vec3_t color2; … … 721 715 722 716 int handicap; 723 int wins, losses; // in tourney mode724 725 int teamTask; // task in teamplay (offence/defence)726 qboolean teamLeader; // true when this is a team leader727 717 728 718 int medkitUsageTime; … … 737 727 char modelName[ MAX_QPATH ]; 738 728 char skinName[ MAX_QPATH ]; 739 char headModelName[ MAX_QPATH ];740 char headSkinName[ MAX_QPATH ];741 729 742 730 qboolean newAnims; // true if using the new mission pack animations … … 1388 1376 extern cg_t cg; 1389 1377 extern centity_t cg_entities[ MAX_GENTITIES ]; 1378 extern displayContextDef_t cgDC; 1390 1379 1391 1380 extern weaponInfo_t cg_weapons[ 32 ]; … … 1463 1452 extern vmCvar_t cg_paused; 1464 1453 extern vmCvar_t cg_blood; 1465 extern vmCvar_t cg_predictItems;1466 1454 extern vmCvar_t cg_deferPlayers; 1467 1455 extern vmCvar_t cg_drawFriend; … … 1473 1461 extern vmCvar_t pmove_fixed; 1474 1462 extern vmCvar_t pmove_msec; 1475 //extern vmCvar_t cg_pmove_fixed;1476 1463 extern vmCvar_t cg_cameraOrbit; 1477 1464 extern vmCvar_t cg_cameraOrbitDelay; … … 1488 1475 extern vmCvar_t cg_oldPlasma; 1489 1476 extern vmCvar_t cg_trueLightning; 1490 extern vmCvar_t cg_creepRes;1491 1477 extern vmCvar_t cg_drawSurfNormal; 1492 1478 extern vmCvar_t cg_drawBBOX; … … 1516 1502 extern vmCvar_t ui_stages; 1517 1503 extern vmCvar_t ui_dialog; 1518 extern vmCvar_t ui_loading;1519 1504 extern vmCvar_t ui_voteActive; 1520 1505 extern vmCvar_t ui_alienTeamVoteActive; … … 1602 1587 void CG_CenterPrint( const char *str, int y, int charWidth ); 1603 1588 void CG_DrawActive( stereoFrame_t stereoView ); 1604 void CG_OwnerDraw( float x, float y, float w, float h, float text_x, float text_y, 1605 int ownerDraw, int ownerDrawFlags, int align, float special, 1606 float scale, vec4_t color, qhandle_t shader, int textStyle); 1607 void CG_Text_Paint( float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style ); 1608 int CG_Text_Width( const char *text, float scale, int limit ); 1609 int CG_Text_Height( const char *text, float scale, int limit ); 1589 void CG_OwnerDraw( float x, float y, float w, float h, float text_x, 1590 float text_y, int ownerDraw, int ownerDrawFlags, 1591 int align, int textalign, int textvalign, float special, 1592 float scale, vec4_t color, 1593 qhandle_t shader, int textStyle ); 1610 1594 float CG_GetValue(int ownerDraw); 1611 1595 void CG_RunMenuScript(char **args); … … 2037 2021 void trap_Key_GetBindingBuf( int keynum, char *buf, int buflen ); 2038 2022 void trap_Key_SetBinding( int keynum, const char *binding ); 2023 void trap_Key_SetOverstrikeMode( qboolean state ); 2024 qboolean trap_Key_GetOverstrikeMode( void ); 2039 2025 2040 2026 int trap_CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits ); -
src/cgame/cg_main.c
r119 r123 24 24 // cg_main.c -- initialization and primary entry point for cgame 25 25 26 27 26 #include "cg_local.h" 27 28 #include "../qcommon/q_shared.h" 28 29 29 30 #include "../ui/ui_shared.h" … … 101 102 buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; 102 103 104 vmCvar_t cg_version; 103 105 vmCvar_t cg_teslaTrailTime; 104 106 vmCvar_t cg_railTrailTime; … … 239 241 static cvarTable_t cvarTable[ ] = 240 242 { 243 { &cg_version, "cg_version", FULL_VERSION, CVAR_ROM | CVAR_USERINFO }, 241 244 { &cg_ignore, "cg_ignore", "0", 0 }, // used for debugging 242 245 { &cg_autoswitch, "cg_autoswitch", "1", CVAR_ARCHIVE }, -
src/cgame/cg_main.c
r122 r123 69 69 CG_DrawActiveFrame( arg0, arg1, arg2 ); 70 70 return 0; 71 72 case CG_CROSSHAIR_PLAYER:73 return CG_CrosshairPlayer( );74 75 case CG_LAST_ATTACKER:76 return CG_LastAttacker( );77 71 78 72 case CG_KEY_EVENT: … … 173 167 vmCvar_t cg_paused; 174 168 vmCvar_t cg_blood; 175 vmCvar_t cg_predictItems;176 169 vmCvar_t cg_deferPlayers; 177 170 vmCvar_t cg_drawTeamOverlay; … … 185 178 vmCvar_t cg_smoothClients; 186 179 vmCvar_t pmove_fixed; 187 //vmCvar_t cg_pmove_fixed;188 180 vmCvar_t pmove_msec; 189 181 vmCvar_t cg_pmove_msec; … … 202 194 vmCvar_t cg_oldPlasma; 203 195 vmCvar_t cg_trueLightning; 204 vmCvar_t cg_creepRes;205 196 vmCvar_t cg_drawSurfNormal; 206 197 vmCvar_t cg_drawBBOX; … … 230 221 vmCvar_t ui_stages; 231 222 vmCvar_t ui_dialog; 232 vmCvar_t ui_loading;233 223 vmCvar_t ui_voteActive; 234 224 vmCvar_t ui_alienTeamVoteActive; … … 310 300 { &cg_thirdPerson, "cg_thirdPerson", "0", CVAR_CHEAT }, 311 301 { &cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE }, 312 { &cg_predictItems, "cg_predictItems", "1", CVAR_ARCHIVE },313 302 { &cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE }, 314 303 { &cg_drawTeamOverlay, "cg_drawTeamOverlay", "0", CVAR_ARCHIVE }, … … 319 308 { &cg_noVoiceChats, "cg_noVoiceChats", "0", CVAR_ARCHIVE }, 320 309 { &cg_noVoiceText, "cg_noVoiceText", "0", CVAR_ARCHIVE }, 321 { &cg_creepRes, "cg_creepRes", "16", CVAR_ARCHIVE },322 310 { &cg_drawSurfNormal, "cg_drawSurfNormal", "0", CVAR_CHEAT }, 323 311 { &cg_drawBBOX, "cg_drawBBOX", "0", CVAR_CHEAT }, … … 348 336 { &ui_stages, "ui_stages", "0 0", 0 }, 349 337 { &ui_dialog, "ui_dialog", "Text not set", 0 }, 350 { &ui_loading, "ui_loading", "0", 0 },351 338 { &ui_voteActive, "ui_voteActive", "0", 0 }, 352 339 { &ui_humanTeamVoteActive, "ui_humanTeamVoteActive", "0", 0 }, … … 370 357 { &cg_timescaleFadeSpeed, "cg_timescaleFadeSpeed", "0", 0}, 371 358 { &cg_timescale, "timescale", "1", 0}, 372 { &cg_scorePlum, "cg_scorePlums", "1", CVAR_USERINFO | CVAR_ARCHIVE},373 359 { &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE}, 374 360 { &cg_cameraMode, "com_cameraMode", "0", CVAR_CHEAT}, … … 384 370 { &cg_oldPlasma, "cg_oldPlasma", "1", CVAR_ARCHIVE}, 385 371 { &cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE} 386 // { &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE }387 372 }; 388 373 … … 413 398 cgs.localServer = atoi( var ); 414 399 forceModelModificationCount = cg_forceModel.modificationCount; 415 416 trap_Cvar_Register( NULL, "model", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );417 trap_Cvar_Register( NULL, "headmodel", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );418 trap_Cvar_Register( NULL, "team_model", DEFAULT_TEAM_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );419 trap_Cvar_Register( NULL, "team_headmodel", DEFAULT_TEAM_HEAD, CVAR_USERINFO | CVAR_ARCHIVE );420 400 } 421 401 … … 443 423 } 444 424 425 /* 426 =============== 427 CG_SetUIVars 428 429 Set some cvars used by the UI 430 =============== 431 */ 432 static void CG_SetUIVars( void ) 433 { 434 int i; 435 char carriageCvar[ MAX_TOKEN_CHARS ]; 436 437 if( !cg.snap ) 438 return; 439 440 *carriageCvar = 0; 441 442 //determine what the player is carrying 443 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 444 { 445 if( BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) && 446 BG_FindPurchasableForWeapon( i ) ) 447 strcat( carriageCvar, va( "W%d ", i ) ); 448 } 449 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 450 { 451 if( BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) && 452 BG_FindPurchasableForUpgrade( i ) ) 453 strcat( carriageCvar, va( "U%d ", i ) ); 454 } 455 strcat( carriageCvar, "$" ); 456 457 trap_Cvar_Set( "ui_carriage", carriageCvar ); 458 459 trap_Cvar_Set( "ui_stages", va( "%d %d", cgs.alienStage, cgs.humanStage ) ); 460 } 445 461 446 462 /* … … 465 481 CG_ForceModelChange( ); 466 482 } 483 484 CG_SetUIVars( ); 467 485 } 468 486 … … 484 502 return cg.snap->ps.persistant[ PERS_ATTACKER ]; 485 503 } 504 486 505 487 506 /* … … 1534 1553 case 6: 1535 1554 if( sp->ping == -1 ) 1536 return " connecting";1555 return ""; 1537 1556 1538 1557 return va( "%4d", sp->ping ); … … 1579 1598 int cursorPos, char cursor, int limit, int style ) 1580 1599 { 1581 CG_Text_Paint( x, y, scale, color, text, 0, limit, style );1600 UI_Text_Paint( x, y, scale, color, text, 0, limit, style ); 1582 1601 } 1583 1602 … … 1587 1606 { 1588 1607 case CG_KILLER: 1589 return CG_Text_Width( CG_GetKillerText( ), scale, 0 );1608 return UI_Text_Width( CG_GetKillerText( ), scale, 0 ); 1590 1609 break; 1591 1610 } … … 1630 1649 char buff[ 1024 ]; 1631 1650 const char *hudSet; 1651 1652 cgDC.aspectScale = ( ( 640.0f * cgs.glconfig.vidHeight ) / 1653 ( 480.0f * cgs.glconfig.vidWidth ) ); 1654 cgDC.xscale = cgs.glconfig.vidWidth / 640.0f; 1655 cgDC.yscale = cgs.glconfig.vidHeight / 480.0f; 1632 1656 1633 1657 cgDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip; … … 1635 1659 cgDC.drawHandlePic = &CG_DrawPic; 1636 1660 cgDC.drawStretchPic = &trap_R_DrawStretchPic; 1637 cgDC.drawText = &CG_Text_Paint;1638 cgDC.textWidth = &CG_Text_Width;1639 cgDC.textHeight = &CG_Text_Height;1640 1661 cgDC.registerModel = &trap_R_RegisterModel; 1641 1662 cgDC.modelBounds = &trap_R_ModelBounds; … … 1652 1673 cgDC.ownerDrawVisible = &CG_OwnerDrawVisible; 1653 1674 cgDC.runScript = &CG_RunMenuScript; 1654 cgDC.getTeamColor = &CG_GetTeamColor;1655 1675 cgDC.setCVar = trap_Cvar_Set; 1656 1676 cgDC.getCVarString = trap_Cvar_VariableStringBuffer; 1657 1677 cgDC.getCVarValue = CG_Cvar_Get; 1658 cgDC.drawTextWithCursor = &CG_Text_PaintWithCursor; 1659 //cgDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode; 1660 //cgDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode; 1678 cgDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode; 1679 cgDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode; 1661 1680 cgDC.startLocalSound = &trap_S_StartLocalSound; 1662 1681 cgDC.ownerDrawHandleKey = &CG_OwnerDrawHandleKey; … … 1672 1691 cgDC.Print = &Com_Printf; 1673 1692 cgDC.ownerDrawWidth = &CG_OwnerDrawWidth; 1693 //cgDC.ownerDrawText = &CG_OwnerDrawText; 1674 1694 //cgDC.Pause = &CG_Pause; 1675 1695 cgDC.registerSound = &trap_S_RegisterSound; … … 1730 1750 cgs.serverCommandSequence = serverCommandSequence; 1731 1751 1752 // get the rendering configuration from the client system 1753 trap_GetGlconfig( &cgs.glconfig ); 1754 cgs.screenXScale = cgs.glconfig.vidWidth / 640.0f; 1755 cgs.screenYScale = cgs.glconfig.vidHeight / 480.0f; 1756 1732 1757 // load a few needed things before we do any screen updates 1733 1758 cgs.media.whiteShader = trap_R_RegisterShader( "white" ); … … 1735 1760 cgs.media.outlineShader = trap_R_RegisterShader( "outline" ); 1736 1761 1737 //inform UI to repress cursor whilst loading1738 trap_Cvar_Set( "ui_loading", "1" );1739 1740 1762 // load overrides 1741 1763 BG_InitClassOverrides( ); … … 1760 1782 // old servers 1761 1783 1762 // get the rendering configuration from the client system1763 trap_GetGlconfig( &cgs.glconfig );1764 cgs.screenXScale = cgs.glconfig.vidWidth / 640.0;1765 cgs.screenYScale = cgs.glconfig.vidHeight / 480.0;1766 1767 1784 // get the gamestate from the client system 1768 1785 trap_GetGameState( &cgs.gameState ); … … 1821 1838 1822 1839 trap_S_ClearLoopingSounds( qtrue ); 1823 1824 trap_Cvar_Set( "ui_loading", "0" );1825 1840 } 1826 1841 -
src/cgame/cg_players.c
r119 r123 1945 1945 float shadowPlane; 1946 1946 entityState_t *es = ¢->currentState; 1947 pClass_t class = ( es-> misc>> 8 ) & 0xFF;1947 pClass_t class = ( es->powerups >> 8 ) & 0xFF; 1948 1948 float scale; 1949 1949 vec3_t tempAxis[ 3 ], tempAxis2[ 3 ]; -
src/cgame/cg_players.c
r122 r123 485 485 } 486 486 487 //FIXME: skins do not load without icon present. do we want icons anyway?488 /* Com_sprintf( filename, sizeof( filename ), "models/players/%s/icon_%s.tga", modelName, skinName );489 ci->modelIcon = trap_R_RegisterShaderNoMip( filename );490 if( !ci->modelIcon )491 {492 Com_Printf( "Failed to load icon file: %s\n", filename );493 return qfalse;494 }*/495 496 487 return qtrue; 497 488 } … … 536 527 static void CG_LoadClientInfo( clientInfo_t *ci ) 537 528 { 538 const char *dir , *fallback;529 const char *dir; 539 530 int i; 540 531 const char *s; … … 542 533 543 534 if( !CG_RegisterClientModelname( ci, ci->modelName, ci->skinName ) ) 544 { 545 if( cg_buildScript.integer ) 546 CG_Error( "CG_RegisterClientModelname( %s, %s ) failed", ci->modelName, ci->skinName ); 547 548 // fall back 549 if( !CG_RegisterClientModelname( ci, DEFAULT_MODEL, "default" ) ) 550 CG_Error( "DEFAULT_MODEL (%s) failed to register", DEFAULT_MODEL ); 551 } 535 CG_Error( "CG_RegisterClientModelname( %s, %s ) failed", ci->modelName, ci->skinName ); 552 536 553 537 // sounds 554 538 dir = ci->modelName; 555 fallback = DEFAULT_MODEL;556 539 557 540 for( i = 0; i < MAX_CUSTOM_SOUNDS; i++ ) … … 579 562 580 563 ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse ); 581 if( !ci->sounds[ i ] )582 ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse );583 564 } 584 565 } … … 586 567 { 587 568 ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", dir, s + 1 ), qfalse ); 588 if( !ci->sounds[ i ] )589 ci->sounds[ i ] = trap_S_RegisterSound( va( "sound/player/%s/%s", fallback, s + 1 ), qfalse );590 569 } 591 570 } … … 729 708 // model 730 709 Q_strncpyz( newInfo.modelName, model, sizeof( newInfo.modelName ) ); 731 Q_strncpyz( newInfo.headModelName, model, sizeof( newInfo.headModelName ) ); 732 733 // modelName didn not include a skin name 710 711 // modelName did not include a skin name 734 712 if( !skin ) 735 {736 713 Q_strncpyz( newInfo.skinName, "default", sizeof( newInfo.skinName ) ); 737 Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) ); 738 } 739 else 740 { 714 else 741 715 Q_strncpyz( newInfo.skinName, skin, sizeof( newInfo.skinName ) ); 742 Q_strncpyz( newInfo.headSkinName, skin, sizeof( newInfo.headSkinName ) );743 }744 716 745 717 newInfo.infoValid = qtrue; … … 787 759 CG_ColorFromString( v, newInfo.color2 ); 788 760 789 // bot skill790 v = Info_ValueForKey( configstring, "skill" );791 newInfo.botSkill = atoi( v );792 793 761 // handicap 794 762 v = Info_ValueForKey( configstring, "hc" ); 795 763 newInfo.handicap = atoi( v ); 796 764 797 // wins798 v = Info_ValueForKey( configstring, "w" );799 newInfo.wins = atoi( v );800 801 // losses802 v = Info_ValueForKey( configstring, "l" );803 newInfo.losses = atoi( v );804 805 765 // team 806 766 v = Info_ValueForKey( configstring, "t" ); 807 767 newInfo.team = atoi( v ); 808 768 809 // team task810 v = Info_ValueForKey( configstring, "tt" );811 newInfo.teamTask = atoi( v );812 813 // team leader814 v = Info_ValueForKey( configstring, "tl" );815 newInfo.teamLeader = atoi( v );816 817 769 // model 818 770 v = Info_ValueForKey( configstring, "model" ); … … 829 781 { 830 782 Q_strncpyz( newInfo.skinName, slash + 1, sizeof( newInfo.skinName ) ); 831 // truncate modelName832 *slash = 0;833 }834 835 //CG_Printf( "NCI: %s\n", v );836 837 // head model838 v = Info_ValueForKey( configstring, "hmodel" );839 Q_strncpyz( newInfo.headModelName, v, sizeof( newInfo.headModelName ) );840 841 slash = strchr( newInfo.headModelName, '/' );842 843 if( !slash )844 {845 // modelName didn not include a skin name846 Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) );847 }848 else849 {850 Q_strncpyz( newInfo.headSkinName, slash + 1, sizeof( newInfo.headSkinName ) );851 783 // truncate modelName 852 784 *slash = 0; -
src/cgame/cg_predict.c
r119 r123 139 139 140 140 if( i == cg_numSolidEntities ) 141 BG_FindBBoxForClass( ( ent-> misc>> 8 ) & 0xFF, bmins, bmaxs, NULL, NULL, NULL );141 BG_FindBBoxForClass( ( ent->powerups >> 8 ) & 0xFF, bmins, bmaxs, NULL, NULL, NULL ); 142 142 143 143 cmodel = trap_CM_TempBoxModel( bmins, bmaxs ); -
src/cgame/cg_predict.c
r122 r123 584 584 585 585 if( cg_pmove.ps->pm_type == PM_DEAD ) 586 cg_pmove.tracemask = MASK_ PLAYERSOLID & ~CONTENTS_BODY;586 cg_pmove.tracemask = MASK_DEADSOLID; 587 587 else 588 588 cg_pmove.tracemask = MASK_PLAYERSOLID; 589 589 590 590 if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) 591 cg_pmove.tracemask &= ~CONTENTS_BODY; // spectators can fly through bodies591 cg_pmove.tracemask = MASK_DEADSOLID; // spectators can fly through bodies 592 592 593 593 cg_pmove.noFootsteps = 0; -
src/cgame/cg_public.h
r119 r123 139 139 CG_KEY_SETCATCHER, 140 140 CG_KEY_GETKEY, 141 CG_PARSE_ADD_GLOBAL_DEFINE, 142 CG_PARSE_LOAD_SOURCE, 143 CG_PARSE_FREE_SOURCE, 144 CG_PARSE_READ_TOKEN, 145 CG_PARSE_SOURCE_FILE_AND_LINE, 141 146 CG_S_STOPBACKGROUNDTRACK, 142 147 CG_REAL_TIME, … … 173 178 CG_KEY_SETBINDING, 174 179 175 CG_PARSE_ADD_GLOBAL_DEFINE,176 CG_PARSE_LOAD_SOURCE,177 CG_PARSE_FREE_SOURCE,178 CG_PARSE_READ_TOKEN,179 CG_PARSE_SOURCE_FILE_AND_LINE,180 181 180 CG_KEY_SETOVERSTRIKEMODE, 182 181 CG_KEY_GETOVERSTRIKEMODE, -
src/cgame/cg_public.h
r1 r123 178 178 CG_KEY_SETBINDING, 179 179 180 CG_KEY_SETOVERSTRIKEMODE, 181 CG_KEY_GETOVERSTRIKEMODE, 182 180 183 CG_MEMSET = 200, 181 184 CG_MEMCPY, … … 229 232 // If demoPlayback is set, local movement prediction will not be enabled 230 233 231 CG_CROSSHAIR_PLAYER,232 // int (*CG_CrosshairPlayer)( void );233 234 CG_LAST_ATTACKER,235 // int (*CG_LastAttacker)( void );236 237 234 CG_KEY_EVENT, 238 235 // void (*CG_KeyEvent)( int key, qboolean down ); -
src/cgame/cg_scanner.c
r119 r123 83 83 else if( cent->currentState.eType == ET_PLAYER ) 84 84 { 85 int team = cent->currentState. misc& 0x00FF;85 int team = cent->currentState.powerups & 0x00FF; 86 86 87 87 if( team == PTE_ALIENS ) -
src/cgame/cg_scanner.c
r122 r123 24 24 #include "cg_local.h" 25 25 26 static entityPos_t entityPositions;26 static entityPos_t entityPositions; 27 27 28 28 #define HUMAN_SCANNER_UPDATE_PERIOD 700 … … 105 105 } 106 106 107 #define STALKWIDTH 2.0f108 #define BLIPX 16.0f107 #define STALKWIDTH (2.0f * cgDC.aspectScale) 108 #define BLIPX (16.0f * cgDC.aspectScale) 109 109 #define BLIPY 8.0f 110 110 #define FAR_ALPHA 0.8f … … 163 163 } 164 164 165 #define BLIPX2 24.0f165 #define BLIPX2 (24.0f * cgDC.aspectScale) 166 166 #define BLIPY2 24.0f 167 167 -
src/cgame/cg_servercmds.c
r119 r123 501 501 break; 502 502 503 case MN_A_TEAMCHANGEBUILDTIMER:504 longMsg = "You cannot leave the Alien team until your build timer "505 "has expired.";506 shortMsg = "You cannot change teams until your build timer expires.\n";507 cmd = "menu tremulous_alien_dialog\n";508 break;509 510 case MN_H_TEAMCHANGEBUILDTIMER:511 longMsg = "You cannot leave the Human team until your build timer "512 "has expired.";513 shortMsg = "You cannot change teams until your build timer expires.\n";514 cmd = "menu tremulous_human_dialog\n";515 break;516 503 517 504 //=============================== … … 608 595 break; 609 596 610 case MN_H_NOARMOURYHERE:611 longMsg = "You must be near a powered Armoury in order to purchase "612 "weapons, upgrades or non-energy ammunition.";613 shortMsg = "You must be near a powered Armoury\n";614 cmd = "menu tremulous_human_dialog\n";615 break;616 617 case MN_H_NOENERGYAMMOHERE:618 longMsg = "You must be near an Armoury, Reactor or Repeater in order "619 "to purchase energy ammunition.";620 shortMsg = "You must be near an Armoury, Reactor or Repeater\n";621 cmd = "menu tremulous_human_dialog\n";622 break;623 624 case MN_H_NOROOMBSUITON:625 longMsg = "There is not enough room here to put on a Battle Suit. "626 "Make sure you have enough head room to climb in.";627 shortMsg = "Not enough room here to put on a Battle Suit\n";628 cmd = "menu tremulous_human_dialog\n";629 break;630 631 case MN_H_NOROOMBSUITOFF:632 longMsg = "There is not enough room here to take off your Battle Suit. "633 "Make sure you have enough head room to climb out.";634 shortMsg = "Not enough room here to take off your Battle Suit\n";635 cmd = "menu tremulous_human_dialog\n";636 break;637 638 case MN_H_ARMOURYBUILDTIMER:639 longMsg = "You are not allowed to buy or sell weapons until your "640 "build timer has expired.";641 shortMsg = "You can not buy or sell weapos until your build timer "642 "expires\n";643 cmd = "menu tremulous_human_dialog\n";644 break;645 646 597 647 598 //=============================== … … 723 674 "you to upgrade."; 724 675 shortMsg = "There is no Overmind\n"; 725 cmd = "menu tremulous_alien_dialog\n";726 break;727 728 case MN_A_EVOLVEBUILDTIMER:729 longMsg = "You cannot Evolve until your build timer has expired.";730 shortMsg = "You cannot Evolve until your build timer expires\n";731 676 cmd = "menu tremulous_alien_dialog\n"; 732 677 break; … … 862 807 } 863 808 864 if( !strcmp( cmd, " map_restart" ) )809 if( !strcmp( cmd, "restartmap" ) ) 865 810 { 866 811 CG_MapRestart( ); -
src/cgame/cg_servercmds.c
r122 r123 451 451 452 452 /* 453 ===============454 CG_SetUIVars455 456 Set some cvars used by the UI457 ===============458 */459 static void CG_SetUIVars( void )460 {461 int i;462 char carriageCvar[ MAX_TOKEN_CHARS ];463 464 *carriageCvar = 0;465 466 //determine what the player is carrying467 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )468 {469 if( BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) &&470 BG_FindPurchasableForWeapon( i ) )471 strcat( carriageCvar, va( "W%d ", i ) );472 }473 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )474 {475 if( BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) &&476 BG_FindPurchasableForUpgrade( i ) )477 strcat( carriageCvar, va( "U%d ", i ) );478 }479 strcat( carriageCvar, "$" );480 481 trap_Cvar_Set( "ui_carriage", carriageCvar );482 483 trap_Cvar_Set( "ui_stages", va( "%d %d", cgs.alienStage, cgs.humanStage ) );484 }485 486 487 /*488 453 ============== 489 454 CG_Menu … … 495 460 const char *longMsg = NULL; // command parameter 496 461 const char *shortMsg = NULL; // non-modal version of message 497 CG_SetUIVars( ); 498 499 // string literals have static storage duration, this is safe, 500 // cleaner and much more readable. 462 501 463 switch( menu ) 502 464 { -
src/cgame/cg_syscalls.asm
r1 r123 65 65 equ trap_Key_SetCatcher -63 66 66 equ trap_Key_GetKey -64 67 equ trap_Parse_AddGlobalDefine -65 68 equ trap_Parse_LoadSource -66 69 equ trap_Parse_FreeSource -67 70 equ trap_Parse_ReadToken -68 71 equ trap_Parse_SourceFileAndLine -69 72 equ trap_S_StopBackgroundTrack -70 73 equ trap_RealTime -71 74 equ trap_SnapVector -72 75 equ trap_RemoveCommand -73 76 equ trap_R_LightForPoint -74 77 equ trap_CIN_PlayCinematic -75 78 equ trap_CIN_StopCinematic -76 79 equ trap_CIN_RunCinematic -77 80 equ trap_CIN_DrawCinematic -78 81 equ trap_CIN_SetExtents -79 82 equ trap_R_RemapShader -80 83 equ trap_S_AddRealLoopingSound -81 84 equ trap_S_StopLoopingSound -82 85 equ trap_CM_TempCapsuleModel -83 86 equ trap_CM_CapsuleTrace -84 87 equ trap_CM_TransformedCapsuleTrace -85 88 equ trap_R_AddAdditiveLightToScene -86 89 equ trap_GetEntityToken -87 90 equ trap_R_AddPolysToScene -88 91 equ trap_R_inPVS -89 92 equ trap_FS_Seek -90 93 equ trap_FS_GetFileList -91 94 equ trap_LiteralArgs -92 95 equ trap_CM_BiSphereTrace -93 96 equ trap_CM_TransformedBiSphereTrace -94 97 equ trap_GetDemoState -95 98 equ trap_GetDemoPos -96 99 equ trap_GetDemoName -97 100 equ trap_Key_KeynumToStringBuf -98 101 equ trap_Key_GetBindingBuf -99 102 equ trap_Key_SetBinding -100 67 equ trap_S_StopBackgroundTrack -65 68 equ trap_RealTime -66 69 equ trap_SnapVector -67 70 equ trap_RemoveCommand -68 71 equ trap_R_LightForPoint -69 72 equ trap_CIN_PlayCinematic -70 73 equ trap_CIN_StopCinematic -71 74 equ trap_CIN_RunCinematic -72 75 equ trap_CIN_DrawCinematic -73 76 equ trap_CIN_SetExtents -74 77 equ trap_R_RemapShader -75 78 equ trap_S_AddRealLoopingSound -76 79 equ trap_S_StopLoopingSound -77 80 equ trap_CM_TempCapsuleModel -78 81 equ trap_CM_CapsuleTrace -79 82 equ trap_CM_TransformedCapsuleTrace -80 83 equ trap_R_AddAdditiveLightToScene -81 84 equ trap_GetEntityToken -82 85 equ trap_R_AddPolysToScene -83 86 equ trap_R_inPVS -84 87 equ trap_FS_Seek -85 88 equ trap_FS_GetFileList -86 89 equ trap_LiteralArgs -87 90 equ trap_CM_BiSphereTrace -88 91 equ trap_CM_TransformedBiSphereTrace -89 92 equ trap_GetDemoState -90 93 equ trap_GetDemoPos -91 94 equ trap_GetDemoName -92 95 equ trap_Key_KeynumToStringBuf -93 96 equ trap_Key_GetBindingBuf -94 97 equ trap_Key_SetBinding -95 98 99 equ trap_Parse_AddGlobalDefine -96 100 equ trap_Parse_LoadSource -97 101 equ trap_Parse_FreeSource -98 102 equ trap_Parse_ReadToken -99 103 equ trap_Parse_SourceFileAndLine -100 104 equ trap_Key_SetOverstrikeMode -101 105 equ trap_Key_GetOverstrikeMode -102 103 106 104 107 equ memset -201 -
src/cgame/cg_tutorial.c
r119 r123 419 419 { 420 420 char *name; 421 int ammo, clips; 421 422 upgrade_t upgrade = UP_NONE; 422 423 … … 429 430 } 430 431 431 if( !ps->ammo && !ps->clips && !BG_FindInfinteAmmoForWeapon( ps->weapon ) ) 432 BG_UnpackAmmoArray( ps->weapon, ps->ammo, ps->powerups, &ammo, &clips ); 433 434 if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( ps->weapon ) ) 432 435 { 433 436 //no ammo -
src/cgame/cg_tutorial.c
r122 r123 650 650 651 651 case PCL_HUMAN: 652 case PCL_HUMAN_BSUIT: 652 653 CG_HumanText( text, ps ); 653 654 break; -
src/cgame/cg_weapons.c
r119 r123 1195 1195 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 1196 1196 { 1197 int ammo, clips; 1198 1197 1199 if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) ) 1198 1200 continue; 1199 1201 1200 if( !ps->ammo && !ps->clips && !BG_FindInfinteAmmoForWeapon( i ) ) 1202 BG_UnpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips ); 1203 1204 if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( i ) ) 1201 1205 colinfo[ numItems ] = 1; 1202 1206 else -
src/cgame/cg_weapons.c
r122 r123 1141 1141 { 1142 1142 int i; 1143 int x = rect->x; 1144 int y = rect->y; 1145 int width = rect->w; 1146 int height = rect->h; 1147 int iconsize; 1143 float x = rect->x; 1144 float y = rect->y; 1145 float width = rect->w; 1146 float height = rect->h; 1147 float iconWidth; 1148 float iconHeight; 1148 1149 int items[ 64 ]; 1149 1150 int numItems = 0, selectedItem = 0; … … 1178 1179 { 1179 1180 vertical = qtrue; 1180 iconsize = width; 1181 length = height / width; 1181 iconWidth = width * cgDC.aspectScale; 1182 iconHeight = width; 1183 length = height / ( width * cgDC.aspectScale ); 1182 1184 } 1183 1185 else if( height <= width ) 1184 1186 { 1185 1187 vertical = qfalse; 1186 iconsize = height; 1187 length = width / height; 1188 iconWidth = height * cgDC.aspectScale; 1189 iconHeight = height; 1190 length = width / ( height * cgDC.aspectScale ); 1188 1191 } 1189 1192 … … 1253 1256 1254 1257 if( items[ item ] <= 32 ) 1255 CG_DrawPic( x, y, icon size, iconsize, cg_weapons[ items[ item ] ].weaponIcon );1258 CG_DrawPic( x, y, iconWidth, iconHeight, cg_weapons[ items[ item ] ].weaponIcon ); 1256 1259 else if( items[ item ] > 32 ) 1257 CG_DrawPic( x, y, icon size, iconsize, cg_upgrades[ items[ item ] - 32 ].upgradeIcon );1260 CG_DrawPic( x, y, iconWidth, iconHeight, cg_upgrades[ items[ item ] - 32 ].upgradeIcon ); 1258 1261 1259 1262 trap_R_SetColor( NULL ); … … 1261 1264 1262 1265 if( vertical ) 1263 y += icon size;1266 y += iconHeight; 1264 1267 else 1265 x += icon size;1268 x += iconWidth; 1266 1269 } 1267 1270 } … … 1293 1296 if( ( name = cg_weapons[ cg.weaponSelect ].humanName ) ) 1294 1297 { 1295 w = CG_Text_Width( name, scale, 0 );1298 w = UI_Text_Width( name, scale, 0 ); 1296 1299 x = rect->x + rect->w / 2; 1297 CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );1300 UI_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); 1298 1301 } 1299 1302 } … … 1306 1309 if( ( name = cg_upgrades[ cg.weaponSelect - 32 ].humanName ) ) 1307 1310 { 1308 w = CG_Text_Width( name, scale, 0 );1311 w = UI_Text_Width( name, scale, 0 ); 1309 1312 x = rect->x + rect->w / 2; 1310 CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );1313 UI_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); 1311 1314 } 1312 1315 } -
src/client/cl_cgame.c
r119 r123 332 332 } 333 333 334 if ( !strcmp( cmd, " map_restart" ) ) {334 if ( !strcmp( cmd, "restartmap" ) ) { 335 335 // clear notify lines and outgoing commands before passing 336 336 // the restart to the cgame -
src/client/cl_cgame.c
r54 r123 386 386 */ 387 387 void CL_ShutdownCGame( void ) { 388 cls.keyCatchers &= ~KEYCATCH_CGAME;388 Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME ); 389 389 cls.cgameStarted = qfalse; 390 390 if ( !cgvm ) { … … 620 620 return Key_GetCatcher(); 621 621 case CG_KEY_SETCATCHER: 622 Key_SetCatcher( args[1] ); 622 // Don't allow the cgame module to close the console 623 Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ); 623 624 return 0; 624 625 case CG_KEY_GETKEY: … … 653 654 case CG_PARSE_SOURCE_FILE_AND_LINE: 654 655 return Parse_SourceFileAndLine( args[1], VMA(2), VMA(3) ); 656 657 case CG_KEY_SETOVERSTRIKEMODE: 658 Key_SetOverstrikeMode( args[1] ); 659 return 0; 660 case CG_KEY_GETOVERSTRIKEMODE: 661 return Key_GetOverstrikeMode( ); 655 662 656 663 case CG_MEMSET: -
src/client/cl_main.c
r119 r123 31 31 cvar_t *cl_noprint; 32 32 cvar_t *cl_motd; 33 33 cvar_t *cl_master; 34 34 cvar_t *rcon_client_password; 35 35 cvar_t *rconAddress; … … 983 983 return; 984 984 } 985 Com_Printf( "Resolving %s\n", MASTER_SERVER_NAME);986 if ( !NET_StringToAdr( MASTER_SERVER_NAME, &cls.updateServer ) ) {985 Com_Printf( "Resolving %s\n", cl_master->string ); 986 if ( !NET_StringToAdr( cl_master->string, &cls.updateServer ) ) { 987 987 Com_Printf( "Couldn't resolve address\n" ); 988 988 return; 989 989 } 990 990 cls.updateServer.port = BigShort( PORT_MASTER ); 991 Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", MASTER_SERVER_NAME,991 Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", cl_master->string, 992 992 cls.updateServer.ip[0], cls.updateServer.ip[1], 993 993 cls.updateServer.ip[2], cls.updateServer.ip[3], … … 2616 2616 cl_noprint = Cvar_Get( "cl_noprint", "0", 0 ); 2617 2617 cl_motd = Cvar_Get ("cl_motd", "1", 0); 2618 2618 cl_master = Cvar_Get("cl_master","master.tremulous.net",CVAR_ARCHIVE); 2619 2619 cl_timeout = Cvar_Get ("cl_timeout", "200", 0); 2620 2620 … … 3213 3213 3214 3214 if( cls.masterNum == 1 ) { 3215 NET_StringToAdr( MASTER_SERVER_NAME, &to );3215 NET_StringToAdr( cl_master->string, &to ); 3216 3216 cls.nummplayerservers = -1; 3217 3217 cls.pingUpdateSource = AS_MPLAYER; 3218 3218 } 3219 3219 else { 3220 NET_StringToAdr( MASTER_SERVER_NAME, &to );3220 NET_StringToAdr( cl_master->string, &to ); 3221 3221 cls.numglobalservers = -1; 3222 3222 cls.pingUpdateSource = AS_GLOBAL; -
src/client/cl_main.c
r122 r123 654 654 // start the demo loop again 655 655 Cbuf_AddText ("d1\n"); 656 cls.keyCatchers = 0;656 Key_SetCatcher( 0 ); 657 657 } 658 658 … … 799 799 if ( com_dedicated->integer ) { 800 800 cls.state = CA_DISCONNECTED; 801 cls.keyCatchers = KEYCATCH_CONSOLE;801 Key_SetCatcher( KEYCATCH_CONSOLE ); 802 802 return; 803 803 } … … 808 808 809 809 Con_Close(); 810 cls.keyCatchers = 0;810 Key_SetCatcher( 0 ); 811 811 812 812 // if we are already connected to the local host, stay connected … … 822 822 Q_strncpyz( cls.servername, "localhost", sizeof(cls.servername) ); 823 823 cls.state = CA_CHALLENGING; // so the connect screen is drawn 824 cls.keyCatchers = 0;824 Key_SetCatcher( 0 ); 825 825 SCR_UpdateScreen(); 826 826 clc.connectTime = -RETRANSMIT_TIMEOUT; … … 1170 1170 } 1171 1171 1172 cls.keyCatchers = 0;1172 Key_SetCatcher( 0 ); 1173 1173 clc.connectTime = -99999; // CL_CheckForResend() will fire immediately 1174 1174 clc.connectPacketCount = 0; … … 2182 2182 #endif 2183 2183 2184 if ( cls.state == CA_DISCONNECTED && !( cls.keyCatchers& KEYCATCH_UI )2184 if ( cls.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI ) 2185 2185 && !com_sv_running->integer ) { 2186 2186 // if disconnected, bring up the menu … … 2599 2599 */ 2600 2600 void CL_Init( void ) { 2601 const char *playerName;2602 2603 2601 Com_Printf( "----- Client Initialization -----\n" ); 2604 2602 … … 2692 2690 2693 2691 // userinfo 2694 playerName = getenv( "USER" ); // Unixy stuff 2695 if( playerName == NULL ) 2696 { 2697 playerName = getenv( "USERNAME" ); // Windows 2698 if( playerName == NULL ) 2699 { 2700 playerName = "Newbie"; // Default 2701 } 2702 } 2703 Cvar_Get ("name", playerName, CVAR_USERINFO | CVAR_ARCHIVE ); 2692 Cvar_Get ("name", Sys_GetCurrentUser( ), CVAR_USERINFO | CVAR_ARCHIVE ); 2704 2693 2705 2694 Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE ); 2706 2695 Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); 2707 Cvar_Get ("model", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );2708 Cvar_Get ("headmodel", "sarge", CVAR_USERINFO | CVAR_ARCHIVE );2709 Cvar_Get ("team_model", "james", CVAR_USERINFO | CVAR_ARCHIVE );2710 Cvar_Get ("team_headmodel", "*james", CVAR_USERINFO | CVAR_ARCHIVE );2711 2696 Cvar_Get ("color1", "4", CVAR_USERINFO | CVAR_ARCHIVE ); 2712 2697 Cvar_Get ("color2", "5", CVAR_USERINFO | CVAR_ARCHIVE ); 2713 2698 Cvar_Get ("handicap", "100", CVAR_USERINFO | CVAR_ARCHIVE ); 2714 Cvar_Get ("teamtask", "0", CVAR_USERINFO );2715 2699 Cvar_Get ("sex", "male", CVAR_USERINFO | CVAR_ARCHIVE ); 2716 Cvar_Get ("cl_anonymous", "0", CVAR_USERINFO | CVAR_ARCHIVE );2717 2700 2718 2701 Cvar_Get ("password", "", CVAR_USERINFO); 2719 Cvar_Get ("cg_predictItems", "1", CVAR_USERINFO | CVAR_ARCHIVE );2720 2702 2721 2703 … … 2821 2803 2822 2804 Com_Memset( &cls, 0, sizeof( cls ) ); 2805 Key_SetCatcher( 0 ); 2823 2806 2824 2807 Com_Printf( "-----------------------\n" ); -
src/client/client.h
r119 r123 345 345 extern cvar_t *cl_showTimeDelta; 346 346 extern cvar_t *cl_freezeDemo; 347 extern cvar_t *cl_master; 347 348 348 349 extern cvar_t *cl_yawspeed; -
src/client/client.h
r122 r123 271 271 typedef struct { 272 272 connstate_t state; // connection status 273 int keyCatchers; // bit flags274 273 275 274 qboolean cddialog; // bring up the cd needed dialog next frame … … 446 445 float CL_KeyState (kbutton_t *key); 447 446 char *Key_KeynumToString (int keynum); 447 int Key_GetCatcher( void ); 448 void Key_SetCatcher( int catcher ); 448 449 449 450 // -
src/game/g_active.c
r119 r123 376 376 pmove_t pm; 377 377 gclient_t *client; 378 qboolean doPmove = qtrue; 378 379 379 380 client = ent->client; … … 382 383 client->buttons = ucmd->buttons; 383 384 384 if( client->sess.spectatorState != SPECTATOR_FOLLOW ) 385 { 386 if( client->sess.spectatorState == SPECTATOR_LOCKED ) 387 client->ps.pm_type = PM_FREEZE; 388 else 389 client->ps.pm_type = PM_SPECTATOR; 390 385 if( client->sess.spectatorState == SPECTATOR_LOCKED || client->sess.spectatorState == SPECTATOR_FOLLOW ) 386 client->ps.pm_type = PM_FREEZE; 387 else 388 client->ps.pm_type = PM_SPECTATOR; 389 390 if ( client->sess.spectatorState == SPECTATOR_FOLLOW ) 391 { 392 gclient_t *cl; 393 if ( client->sess.spectatorClient >= 0 ) 394 { 395 cl = &level.clients[ client->sess.spectatorClient ]; 396 if ( cl->sess.sessionTeam != TEAM_SPECTATOR ) 397 doPmove = qfalse; 398 } 399 } 400 401 if (doPmove) 402 { 391 403 client->ps.speed = BG_FindSpeedForClass( client->ps.stats[ STAT_PCLASS ] ); 392 404 … … 551 563 552 564 if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) && BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) ) 565 { 566 //don't run when jetpack on 553 567 client->ps.stats[ STAT_STATE ] &= ~SS_SPEEDBOOST; 568 } 554 569 555 570 if( ( client->ps.stats[ STAT_STATE ] & SS_SPEEDBOOST ) && !crouched ) … … 666 681 if( client->ps.weapon == WP_LUCIFER_CANNON ) 667 682 { 683 int ammo; 684 685 BG_UnpackAmmoArray( WP_LUCIFER_CANNON, client->ps.ammo, client->ps.powerups, &ammo, NULL ); 686 668 687 if( client->ps.stats[ STAT_MISC ] < LCANNON_TOTAL_CHARGE && ucmd->buttons & BUTTON_ATTACK ) 669 688 client->ps.stats[ STAT_MISC ] += ( 100.0f / LCANNON_CHARGE_TIME ) * LCANNON_TOTAL_CHARGE; … … 672 691 client->ps.stats[ STAT_MISC ] = LCANNON_TOTAL_CHARGE; 673 692 674 if( client->ps.stats[ STAT_MISC ] > ( client->ps.ammo * LCANNON_TOTAL_CHARGE ) / 10 )675 client->ps.stats[ STAT_MISC ] = client->ps.ammo * LCANNON_TOTAL_CHARGE / 10;693 if( client->ps.stats[ STAT_MISC ] > ( ammo * LCANNON_TOTAL_CHARGE ) / 10 ) 694 client->ps.stats[ STAT_MISC ] = ammo * LCANNON_TOTAL_CHARGE / 10; 676 695 } 677 696 … … 695 714 696 715 // Let the client know which buildables will be removed by building 697 for( i = 0; i < MAX_ MISC; i++ )716 for( i = 0; i < MAX_POWERUPS; i++ ) 698 717 { 699 718 if( i < level.numBuildablesForRemoval ) 700 client->ps. misc[ i ] = level.markedBuildables[ i ]->s.number;719 client->ps.powerups[ i ] = level.markedBuildables[ i ]->s.number; 701 720 else 702 client->ps. misc[ i ] = 0;721 client->ps.powerups[ i ] = 0; 703 722 } 704 723 } 705 724 else 706 725 { 707 for( i = 0; i < MAX_ MISC; i++ )708 client->ps. misc[ i ] = 0;726 for( i = 0; i < MAX_POWERUPS; i++ ) 727 client->ps.powerups[ i ] = 0; 709 728 } 710 729 730 case WP_BLASTER: 711 731 //update build timer 712 732 if( client->ps.stats[ STAT_MISC ] > 0 ) … … 732 752 { 733 753 ent->client->medKitHealthToRestore--; 734 ent->health++;754 do_health( ent,1 ); 735 755 } 736 756 else … … 747 767 { 748 768 ent->client->medKitHealthToRestore--; 749 ent->health++;769 do_health( ent,1 ); 750 770 751 771 client->medKitIncrementTime = level.time + … … 762 782 { 763 783 client->time1000 -= 1000; 784 785 //jetpack power management 786 if( BG_InventoryContainsUpgrade( UP_JETPACK, client->ps.stats ) ) 787 { 788 if(BG_UpgradeIsActive( UP_JETPACK, client->ps.stats ) ) 789 { 790 if(g_jetpackLimit.integer > 0) 791 { 792 //decrease jetpack power 793 if(client->jetpack_power > 0) 794 { 795 client->jetpack_power--; 796 797 //if no power, can't reactive jetpack for a moment 798 if(client->jetpack_power == 0) 799 client->jetpack_beat = g_jetpackLimit.integer / 10; 800 } 801 } 802 } 803 else 804 { 805 //recover jetpack 806 if(client->jetpack_beat > 0) 807 client->jetpack_beat--; 808 else if( level.reactorPresent && client->jetpack_power < g_jetpackLimit.integer) 809 client->jetpack_power++; 810 } 811 } 764 812 765 813 //client is poison clouded … … 825 873 if( ent->health > 0 && ent->health < client->ps.stats[ STAT_MAX_HEALTH ] && 826 874 ( ent->lastDamageTime + ALIEN_REGEN_DAMAGE_TIME ) < level.time ) 827 ent->health += BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ) * modifier;875 do_health( ent,BG_FindRegenRateForClass( client->ps.stats[ STAT_PCLASS ] ) * modifier ); 828 876 829 877 if( ent->health > client->ps.stats[ STAT_MAX_HEALTH ] ) … … 852 900 if( client->ps.weapon == WP_ALEVEL3_UPG ) 853 901 { 854 int maxAmmo;902 int ammo, maxAmmo; 855 903 856 904 BG_FindAmmoForWeapon( WP_ALEVEL3_UPG, &maxAmmo, NULL ); 857 858 if( client->ps.ammo < maxAmmo ) 859 client->ps.ammo++; 905 BG_UnpackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, &ammo, NULL ); 906 907 if( ammo < maxAmmo ) 908 { 909 ammo++; 910 BG_PackAmmoArray( WP_ALEVEL3_UPG, client->ps.ammo, client->ps.powerups, ammo, 0 ); 911 } 860 912 } 861 913 } … … 1330 1382 msec = 200; 1331 1383 1332 client->unlaggedTime = ucmd->serverTime; 1384 if( ucmd->serverTime < level.time - g_unlagged.integer ) 1385 client->unlaggedTime = level.time - g_unlagged.integer; 1386 else 1387 client->unlaggedTime = ucmd->serverTime; 1333 1388 1334 1389 if( pmove_msec.integer < 8 ) … … 1361 1416 SpectatorThink( ent, ucmd ); 1362 1417 return; 1418 } 1419 1420 if (g_freeFunds.integer) 1421 { 1422 // give full evo/credits 1423 if (client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS) 1424 { 1425 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS; 1426 } 1427 else 1428 { 1429 client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS; 1430 } 1363 1431 } 1364 1432 … … 1474 1542 } 1475 1543 1476 //switch jetpack off if no reactor 1477 if( !level.reactorPresent ) 1544 //switch jetpack off if no power 1545 if( g_jetpackLimit.integer && (client->jetpack_beat || !client->jetpack_power)) 1546 { 1478 1547 BG_DeactivateUpgrade( UP_JETPACK, client->ps.stats ); 1548 1549 trap_SendServerCommand( ent - g_entities, 1550 "print \"Your jetpack is out of power\n\"" ); 1551 } 1479 1552 } 1480 1553 … … 1765 1838 cl = &level.clients[ clientNum ]; 1766 1839 1767 if( cl->pers.connected == CON_CONNECTED && cl->sess.sessionTeam != TEAM_SPECTATOR)1840 if( cl->pers.connected == CON_CONNECTED ) 1768 1841 { 1769 1842 flags = ( cl->ps.eFlags & ~( EF_VOTED | EF_TEAMVOTED ) ) | 1770 1843 ( ent->client->ps.eFlags & ( EF_VOTED | EF_TEAMVOTED ) ); 1771 1844 ent->client->ps = cl->ps; 1845 ent->client->ps.eFlags = flags; 1772 1846 ent->client->ps.pm_flags |= PMF_FOLLOW; 1773 ent->client->ps. eFlags = flags;1847 ent->client->ps.pm_flags &= ~PMF_QUEUED; 1774 1848 } 1775 1849 } … … 1789 1863 { 1790 1864 clientPersistant_t *pers; 1865 1866 if (ent->client->pers.floodTimer) 1867 { 1868 ent->client->pers.floodTimer -= 5; 1869 if (ent->client->pers.floodTimer < 0) 1870 ent->client->pers.floodTimer = 0; 1871 } 1791 1872 1792 1873 if( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) … … 1834 1915 } 1835 1916 1836 1917 void do_health( gentity_t *ent, int quantity ) 1918 { 1919 int i = 0; 1920 1921 if( ent->health == ent->client->ps.stats[ STAT_MAX_HEALTH ] ) 1922 return; 1923 1924 ent->health += quantity; 1925 if( ent->health >= ent->client->ps.stats[ STAT_MAX_HEALTH ] ) 1926 { 1927 ent->health = ent->client->ps.stats[ STAT_MAX_HEALTH ]; 1928 for( i = 0; i < MAX_CLIENTS; i++ ) 1929 ent->credits[ i ] = 0; 1930 } 1931 } 1932 -
src/game/g_active.c
r122 r123 413 413 pm.ps = &client->ps; 414 414 pm.cmd = *ucmd; 415 pm.tracemask = MASK_ PLAYERSOLID & ~CONTENTS_BODY; // spectators can fly through bodies415 pm.tracemask = MASK_DEADSOLID; // spectators can fly through bodies 416 416 pm.trace = trap_Trace; 417 417 pm.pointcontents = trap_PointContents; … … 1593 1593 1594 1594 if( pm.ps->pm_type == PM_DEAD ) 1595 pm.tracemask = MASK_ PLAYERSOLID; // & ~CONTENTS_BODY;1595 pm.tracemask = MASK_DEADSOLID; 1596 1596 1597 1597 if( pm.ps->stats[ STAT_STATE ] & SS_INFESTING || 1598 1598 pm.ps->stats[ STAT_STATE ] & SS_HOVELING ) 1599 pm.tracemask = MASK_ PLAYERSOLID & ~CONTENTS_BODY;1599 pm.tracemask = MASK_DEADSOLID; 1600 1600 else 1601 1601 pm.tracemask = MASK_PLAYERSOLID; … … 1757 1757 } 1758 1758 1759 if( level.framenum > client->retriggerArmouryMenu && client->retriggerArmouryMenu )1760 {1761 G_TriggerMenu( client->ps.clientNum, MN_H_ARMOURY );1762 1763 client->retriggerArmouryMenu = 0;1764 }1765 1766 1759 // Give clients some credit periodically 1767 1760 if( ent->client->lastKillTime + FREEKILL_PERIOD < level.time ) -
src/game/g_client.c
r119 r123 82 82 /* 83 83 =============== 84 G_CheckGUID 85 =============== 86 */ 87 qboolean G_ValidGUID(char *in) 88 { 89 int count = 0; 90 while( *in ) 91 { 92 count ++; 93 //check that the char is an alphanumeric one (with uppercased letter) 94 if( !((*in >= '0' && *in <= '9') || (*in >= 'A' && *in <= 'F')) ) 95 return qfalse; 96 97 in++; 98 } 99 100 if( count != 32 ) 101 return qfalse; 102 103 return qtrue; 104 } 105 106 /* 107 =============== 84 108 G_AddCreditToClient 85 109 =============== … … 90 114 return; 91 115 92 //if we're already at the max and trying to add credit then stop 116 client->ps.persistant[ PERS_CREDIT ] += credit; 117 93 118 if( cap ) 94 119 { 95 120 if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) 96 121 { 97 if( client->ps.persistant[ PERS_CREDIT ] >= ALIEN_MAX_KILLS && 98 credit > 0 ) 99 return; 122 if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS ) 123 { 124 if( g_autoDonate.integer ) 125 G_Donate(client, client->ps.persistant[ PERS_CREDIT ] - ALIEN_MAX_KILLS); 126 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS; 127 } 100 128 } 101 129 else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) 102 130 { 103 if( client->ps.persistant[ PERS_CREDIT ] >= HUMAN_MAX_CREDITS &&104 credit > 0 )105 return;106 }107 }108 109 client->ps.persistant[ PERS_CREDIT ] += credit;110 111 if( cap )112 {113 if( client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )114 {115 if( client->ps.persistant[ PERS_CREDIT ] > ALIEN_MAX_KILLS )116 client->ps.persistant[ PERS_CREDIT ] = ALIEN_MAX_KILLS;117 }118 else if( client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )119 {120 131 if( client->ps.persistant[ PERS_CREDIT ] > HUMAN_MAX_CREDITS ) 132 { 133 if( g_autoDonate.integer ) 134 G_Donate(client, client->ps.persistant[ PERS_CREDIT ] - HUMAN_MAX_CREDITS); 121 135 client->ps.persistant[ PERS_CREDIT ] = HUMAN_MAX_CREDITS; 136 } 122 137 } 123 138 } … … 583 598 584 599 //sinking bodies can't be infested 585 ent->killedBy = ent->s. misc= MAX_CLIENTS;600 ent->killedBy = ent->s.powerups = MAX_CLIENTS; 586 601 ent->timestamp = level.time; 587 602 } … … 657 672 body->classname = "alienCorpse"; 658 673 659 body->s. misc= MAX_CLIENTS;674 body->s.powerups = MAX_CLIENTS; 660 675 661 676 body->think = BodySink; … … 827 842 828 843 // check colors 829 if( ch == Q_COLOR_ESCAPE ) 830 { 831 // solo trailing carat is not a color prefix 832 if( !*in ) 833 break; 834 835 // don't allow black in a name, period 836 if( ColorIndex( *in ) == 0 ) 837 { 838 in++; 839 continue; 840 } 841 844 if( ch == Q_COLOR_ESCAPE && ( ( *in && *in != Q_COLOR_ESCAPE ) || !*in ) ) 845 { 842 846 // make sure room in dest for both chars 843 847 if( len > outSize - 2 ) … … 845 849 846 850 *out++ = ch; 847 *out++ = *in++;848 851 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++; 849 866 continue; 850 867 } … … 873 890 if( *p == 0 || colorlessLen == 0 ) 874 891 Q_strncpyz( p, "UnnamedPlayer", outSize ); 892 } 893 894 895 /* 896 =================== 897 G_NextNewbieName 898 899 Generate a unique, known-good name for an UnnamedPlayer 900 =================== 901 */ 902 char *G_NextNewbieName( gentity_t *ent ) 903 { 904 char newname[ MAX_NAME_LENGTH ]; 905 char namePrefix[ MAX_NAME_LENGTH - 4 ]; 906 char err[ MAX_STRING_CHARS ]; 907 908 if( g_newbieNamePrefix.string[ 0 ] ) 909 Q_strncpyz( namePrefix, g_newbieNamePrefix.string , sizeof( namePrefix ) ); 910 else 911 strcpy( namePrefix, "Newbie#" ); 912 913 while( level.numNewbies < 10000 ) 914 { 915 strcpy( newname, va( "%s%i", namePrefix, level.numNewbies ) ); 916 if ( G_admin_name_check( ent, newname, err, sizeof( err ) ) ) 917 { 918 return va( "%s", newname ); 919 } 920 level.numNewbies++; // Only increments if the last requested name was used. 921 } 922 return "UnnamedPlayer"; 875 923 } 876 924 … … 954 1002 char err[ MAX_STRING_CHARS ]; 955 1003 qboolean revertName = qfalse; 1004 qboolean showRenameMsg = qtrue; 956 1005 gclient_t *client; 957 1006 char c1[ MAX_INFO_STRING ]; … … 982 1031 if( strcmp( oldname, newname ) ) 983 1032 { 984 // in case we need to revert and there's no oldname 985 if( client->pers.connected != CON_CONNECTED ) 986 Q_strncpyz( oldname, "UnnamedPlayer", sizeof( oldname ) ); 987 988 if( client->pers.nameChangeTime && 1033 1034 if( !strlen( oldname ) && client->pers.connected != CON_CONNECTED ) 1035 showRenameMsg = qfalse; 1036 // in case we need to revert and there's no oldname 1037 ClientCleanName( va( "%s", client->pers.netname ), oldname, sizeof( oldname ) ); 1038 1039 if( g_newbieNumbering.integer ) 1040 { 1041 if( !strcmp( newname, "UnnamedPlayer" ) ) 1042 Q_strncpyz( newname, G_NextNewbieName( ent ), sizeof( newname ) ); 1043 if( !strcmp( oldname, "UnnamedPlayer" ) ) 1044 Q_strncpyz( oldname, G_NextNewbieName( ent ), sizeof( oldname ) ); 1045 } 1046 1047 if( client->pers.muted ) 1048 { 1049 trap_SendServerCommand( ent - g_entities, 1050 "print \"You cannot change your name while you are muted\n\"" ); 1051 revertName = qtrue; 1052 } 1053 else if( client->pers.nameChangeTime && 989 1054 ( level.time - client->pers.nameChangeTime ) 990 1055 <= ( g_minNameChangePeriod.value * 1000 ) ) … … 1020 1085 Q_strncpyz( client->pers.netname, newname, 1021 1086 sizeof( client->pers.netname ) ); 1087 Info_SetValueForKey( userinfo, "name", newname ); 1088 trap_SetUserinfo( clientNum, userinfo ); 1022 1089 if( client->pers.connected == CON_CONNECTED ) 1023 1090 { … … 1034 1101 } 1035 1102 1036 if( client->pers.connected == CON_CONNECTED)1103 if( client->pers.connected >= CON_CONNECTING && showRenameMsg ) 1037 1104 { 1038 1105 if( strcmp( oldname, client->pers.netname ) ) 1039 1106 { 1040 1107 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE 1041 " renamed to %s \n\"", oldname, client->pers.netname ) );1042 G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s \" -> \"%s\"\n", clientNum,1108 " renamed to %s" S_COLOR_WHITE "\n\"", oldname, client->pers.netname ) ); 1109 G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s^7\" -> \"%s^7\"\n", clientNum, 1043 1110 client->pers.ip, client->pers.guid, oldname, client->pers.netname ); 1044 1111 G_admin_namelog_update( client, qfalse ); … … 1058 1125 1059 1126 // set model 1060 if( client->ps.stats[ STAT_PCLASS ] == PCL_HUMAN _BSUIT)1127 if( client->ps.stats[ STAT_PCLASS ] == PCL_HUMAN && BG_InventoryContainsUpgrade( UP_BATTLESUIT, client->ps.stats ) ) 1061 1128 { 1062 1129 Com_sprintf( buffer, MAX_QPATH, "%s/%s", BG_FindModelNameForClass( PCL_HUMAN_BSUIT ), … … 1170 1237 char reason[ MAX_STRING_CHARS ] = {""}; 1171 1238 int i; 1239 int used_privateSlots; 1240 int privateClients; 1172 1241 1173 1242 ent = &g_entities[ clientNum ]; … … 1184 1253 } 1185 1254 1255 privateClients = trap_Cvar_VariableIntegerValue( "sv_privateClients" ); 1256 if( firstTime && clientNum >= privateClients && !G_admin_guid_permission( value, ADMF_VIP ) ) 1257 { 1258 // not flag ADMF_VIP, not already connected player after mapchange, and not privateClient... 1259 // may be refused, because too many players in game 1260 used_privateSlots = 0; 1261 for( i = 0 ; i < privateClients; i++ ) 1262 { 1263 if( level.clients[ i ].pers.connected != CON_DISCONNECTED ) 1264 { 1265 used_privateSlots++; 1266 } 1267 } 1268 1269 if( ( level.numConnectedClients - used_privateSlots ) >= ( level.maxclients - privateClients - g_hiddenClients.integer ) ) 1270 { 1271 // not flag ADMF_VIP and maxPlayers exceeded 1272 return "Server is full"; 1273 } 1274 } 1186 1275 1187 1276 // IP filtering … … 1216 1305 1217 1306 // add guid to session so we don't have to keep parsing userinfo everywhere 1218 if( ! guid[0])1307 if( !G_ValidGUID(guid) ) 1219 1308 { 1220 1309 Q_strncpyz( client->pers.guid, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", … … 1238 1327 // get and distribute relevent paramters 1239 1328 ClientUserinfoChanged( clientNum ); 1240 G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s \"\n", clientNum,1329 G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 1241 1330 client->pers.ip, client->pers.guid, client->pers.netname ); 1242 1331 … … 1294 1383 // locate ent at a spawn point 1295 1384 1385 client->pers.classSelection = PCL_NONE; 1296 1386 ClientSpawn( ent, NULL, NULL, NULL ); 1297 1387 … … 1301 1391 G_admin_namelog_update( client, qfalse ); 1302 1392 1393 // autoregister client if possible 1394 G_admin_autoregister( ent ); 1395 1303 1396 // request the clients PTR code 1304 1397 trap_SendServerCommand( ent - g_entities, "ptrcrequest" ); … … 1308 1401 // count current clients and rank for scoreboard 1309 1402 CalculateRanks( ); 1403 } 1404 1405 /* 1406 ================== 1407 ClientPingOverride 1408 1409 Called by server every time a client connects to check 1410 whether it is immune to ping restrictions. 1411 ================== 1412 */ 1413 int ClientPingOverride( void ) 1414 { 1415 char userinfo[ MAX_INFO_STRING ]; 1416 // create a temporary gentity 1417 gentity_t ent; 1418 gclient_t client; 1419 ent.client = &client; 1420 1421 // userinfo for the client is not yet availible so just use Argv(1) 1422 trap_Argv( 1, userinfo, sizeof( userinfo ) ); 1423 Q_strncpyz( client.pers.guid, Info_ValueForKey( userinfo, "cl_guid" ), sizeof( client.pers.guid ) ); 1424 if ( !client.pers.guid[0] ) 1425 return 0; 1426 1427 return G_admin_permission( &ent, ADMF_PINGOVERRIDE ); 1310 1428 } 1311 1429 … … 1355 1473 client->sess.spectatorState = SPECTATOR_LOCKED; 1356 1474 } 1475 1476 1477 // if this is after !restart keepteams or !restart switchteams, apply said selection 1478 if ( client->sess.restartTeam != PTE_NONE ) { 1479 G_ChangeTeam( ent, client->sess.restartTeam ); 1480 client->sess.restartTeam = PTE_NONE; 1481 } 1482 1483 1357 1484 1358 1485 if( origin != NULL ) … … 1479 1606 BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips ); 1480 1607 BG_AddWeaponToInventory( weapon, client->ps.stats ); 1481 client->ps.ammo = maxAmmo; 1482 client->ps.clips = maxClips; 1608 BG_PackAmmoArray( weapon, client->ps.ammo, client->ps.powerups, maxAmmo, maxClips ); 1483 1609 1484 1610 ent->client->ps.stats[ STAT_PCLASS ] = ent->client->pers.classSelection; … … 1504 1630 1505 1631 client->ps.stats[ STAT_STAMINA ] = MAX_STAMINA; 1632 1633 client->jetpack_beat = 0; 1634 client->jetpack_power = g_jetpackLimit.integer; 1506 1635 1507 1636 G_SetOrigin( ent, spawn_origin ); … … 1666 1795 } 1667 1796 1668 G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s \"\n", clientNum,1797 G_LogPrintf( "ClientDisconnect: %i [%s] (%s) \"%s^7\"\n", clientNum, 1669 1798 ent->client->pers.ip, ent->client->pers.guid, ent->client->pers.netname ); 1670 1799 -
src/game/g_client.c
r122 r123 993 993 { 994 994 gentity_t *ent; 995 int teamTask, teamLeader,health;995 int health; 996 996 char *s; 997 997 char model[ MAX_QPATH ]; … … 1024 1024 client->pers.localClient = qtrue; 1025 1025 1026 // check the item prediction1027 s = Info_ValueForKey( userinfo, "cg_predictItems" );1028 1029 if( !atoi( s ) )1030 client->pers.predictItemPickup = qfalse;1031 else1032 client->pers.predictItemPickup = qtrue;1033 1034 1026 // set name 1035 1027 Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) ); … … 1186 1178 s = Info_ValueForKey( userinfo, "teamoverlay" ); 1187 1179 1188 if( ! *s || atoi( s ) != 0 )1180 if( !*s || atoi( s ) != 0 ) 1189 1181 client->pers.teamInfo = qtrue; 1190 1182 else 1191 1183 client->pers.teamInfo = qfalse; 1192 1193 // team task (0 = none, 1 = offence, 2 = defence)1194 teamTask = atoi( Info_ValueForKey( userinfo, "teamtask" ) );1195 // team Leader (1 = leader, 0 is normal player)1196 teamLeader = client->sess.teamLeader;1197 1184 1198 1185 // colors … … 1209 1196 1210 1197 Com_sprintf( userinfo, sizeof( userinfo ), 1211 "n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\" 1212 "hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\" 1213 "tl\\%d\\ig\\%16s", 1214 client->pers.netname, team, model, model, c1, c2, 1215 client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, 1216 teamLeader, BG_ClientListString( &client->sess.ignoreList ) ); 1198 "n\\%s\\t\\%i\\model\\%s\\c1\\%s\\c2\\%s\\" 1199 "hc\\%i\\ig\\%16s", 1200 client->pers.netname, team, model, c1, c2, 1201 client->pers.maxHealth, BG_ClientListString( &client->sess.ignoreList ) ); 1217 1202 1218 1203 trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo ); -
src/game/g_cmds.c
r119 r123 382 382 maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 383 383 384 client->ps.ammo = maxAmmo; 385 client->ps.clips = maxClips; 384 BG_PackAmmoArray( client->ps.weapon, client->ps.ammo, client->ps.powerups, maxAmmo, maxClips ); 386 385 } 387 386 } … … 622 621 ent->client->pers.joinedATeam = qtrue; 623 622 ent->client->pers.teamChangeTime = level.time; 624 625 623 //update ClientInfo 626 624 ClientUserinfoChanged( ent->client->ps.clientNum ); 625 CalculateRanks( ); 627 626 } 628 627 … … 640 639 int aliens = level.numAlienClients; 641 640 int humans = level.numHumanClients; 641 int warmup; 642 642 643 643 // stop team join spam 644 644 if( level.time - ent->client->pers.teamChangeTime < 1000 ) 645 645 return; 646 647 // do warm up 648 if( g_doWarmup.integer ) 649 { 650 warmup = g_warmup.integer - ( ( level.time - level.startTime ) / 1000) - 1; 651 if( warmup > 0 ) 652 { 653 trap_SendServerCommand( ent - g_entities, va( "print \"team: you can't join" 654 " a team during warm up (%d seconds remaining)\n\"", warmup ) ); 655 return; 656 } 657 } 646 658 647 659 if( oldteam == PTE_ALIENS ) … … 659 671 } 660 672 661 if( !Q_stricmp( s, "spectate" ) ) 662 team = PTE_NONE; 663 else if( !force && oldteam == PTE_NONE && g_maxGameClients.integer && 673 // g_maxGameClients stuff 674 if( !force && oldteam == PTE_NONE && g_maxGameClients.integer && 664 675 level.numPlayingClients >= g_maxGameClients.integer ) 665 676 { … … 669 680 return; 670 681 } 682 683 //guard against build timer exploit 684 if( ent->client->pers.teamSelection != PTE_NONE && 685 ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 || 686 ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG || 687 BG_InventoryContainsWeapon( WP_HBUILD, ent->client->ps.stats ) || 688 BG_InventoryContainsWeapon( WP_HBUILD2, ent->client->ps.stats ) ) && 689 ent->client->ps.stats[ STAT_MISC ] > 0 ) 690 { 691 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot change teams until build timer expires\n\"" ) ); 692 return; 693 } 694 695 if( !Q_stricmp( s, "spectate" ) ) 696 team = PTE_NONE; 671 697 else if( !Q_stricmp( s, "aliens" ) ) 672 698 { … … 677 703 return; 678 704 } 679 else if( level.humanTeamLocked ) 680 { 681 // if only one team has been locked, let people join the other 682 // regardless of balance 683 force = qtrue; 684 } 685 686 if( !force && g_teamForceBalance.integer && aliens > humans ) 687 { 688 G_TriggerMenu( ent - g_entities, MN_A_TEAMFULL ); 705 706 if( !force && !level.humanTeamLocked && g_teamForceBalance.integer && aliens > humans ) 707 { 708 trap_SendServerCommand( ent-g_entities, va("print \"team: The alien team has too many players.\n\"" ) ); 689 709 return; 690 710 } … … 700 720 return; 701 721 } 702 else if( level.alienTeamLocked ) 703 { 704 // if only one team has been locked, let people join the other 705 // regardless of balance 706 force = qtrue; 707 } 708 709 if( !force && g_teamForceBalance.integer && humans > aliens ) 710 { 711 G_TriggerMenu( ent - g_entities, MN_H_TEAMFULL ); 722 if( !force && !level.alienTeamLocked && g_teamForceBalance.integer && humans > aliens ) 723 { 724 trap_SendServerCommand( ent-g_entities, va("print \"team: The human team has too many players.\n\"" ) ); 712 725 return; 713 726 } … … 719 732 if( level.humanTeamLocked && level.alienTeamLocked ) 720 733 team = PTE_NONE; 721 else if( humans > aliens )734 else if(humans > aliens ) 722 735 team = PTE_ALIENS; 723 736 else if( humans < aliens ) … … 738 751 739 752 // stop team join spam 740 if( oldteam == team ) 741 return; 742 743 //guard against build timer exploit 744 if( oldteam != PTE_NONE && 745 ( ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0 || 746 ent->client->ps.stats[ STAT_PCLASS ] == PCL_ALIEN_BUILDER0_UPG || 747 BG_InventoryContainsWeapon( WP_HBUILD, ent->client->ps.stats ) || 748 BG_InventoryContainsWeapon( WP_HBUILD2, ent->client->ps.stats ) ) && 749 ent->client->ps.stats[ STAT_MISC ] > 0 ) 750 { 751 if( ent->client->pers.teamSelection == PTE_ALIENS ) 752 G_TriggerMenu( ent->client->ps.clientNum, MN_A_TEAMCHANGEBUILDTIMER ); 753 if( ent->client->pers.teamSelection == team ) 754 return; 755 756 G_ChangeTeam( ent, team ); 757 758 if( team == PTE_ALIENS ) 759 { 760 if ( oldteam == PTE_HUMANS ) 761 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " abandoned humans and joined the aliens\n\"", ent->client->pers.netname ) ); 753 762 else 754 G_TriggerMenu( ent->client->ps.clientNum, MN_H_TEAMCHANGEBUILDTIMER ); 755 return; 756 } 757 758 759 G_ChangeTeam( ent, team ); 760 761 if( team == PTE_ALIENS ) 762 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the aliens\n\"", ent->client->pers.netname ) ); 763 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the aliens\n\"", ent->client->pers.netname ) ); 764 } 763 765 else if( team == PTE_HUMANS ) 764 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the humans\n\"", ent->client->pers.netname ) ); 766 { 767 if ( oldteam == PTE_ALIENS ) 768 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " abandoned aliens and joined the humans\n\"", ent->client->pers.netname ) ); 769 else 770 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " joined the humans\n\"", ent->client->pers.netname ) ); 771 } 772 else if( team == PTE_NONE ) 773 { 774 if ( oldteam == PTE_HUMANS ) 775 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " left the humans\n\"", ent->client->pers.netname ) ); 776 else 777 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " left the aliens\n\"", ent->client->pers.netname ) ); 778 } 765 779 } 766 780 … … 771 785 ================== 772 786 */ 773 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message ) 774 { 787 static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, const char *name, const char *message, const char *prefix ) 788 { 789 qboolean toSend = qtrue, usePrefix = qfalse; 790 775 791 qboolean ignore = qfalse; 776 792 … … 787 803 return; 788 804 789 if( mode == SAY_TEAM && !OnSameTeam( ent, other ) ) 790 { 791 if( other->client->pers.teamSelection != PTE_NONE ) 792 return; 793 794 if( !G_admin_permission( other, ADMF_SPEC_ALLCHAT ) ) 795 return; 805 if( ( mode == SAY_TEAM || mode == SAY_ACTION_T ) && !OnSameTeam( ent, other ) ) 806 { 807 toSend = qfalse; 808 809 if( other->client->ps.stats[ STAT_PTEAM ] == PTE_NONE && 810 G_admin_permission( other, ADMF_SPEC_ALLCHAT ) ) { 811 usePrefix = qtrue; 812 toSend = qtrue; 813 } 814 815 // spec following someone in talker's steam may see 816 // that teamchat if g_specsSeeTeamchat is enabled 817 if( other->client->ps.stats[ STAT_PTEAM ] == ent->client->ps.stats[ STAT_PTEAM ] && 818 ent->client->pers.teamSelection != PTE_NONE && g_specsSeeTeamchat.integer ) 819 toSend = qtrue; 796 820 797 821 // specs with ADMF_SPEC_ALLCHAT flag can see team chat 798 822 } 823 824 if( mode == SAY_ADMINS && !G_admin_permission( other, ADMF_ADMINCHAT) ) 825 return; 826 827 if( mode == SAY_ALL ) 828 usePrefix = qtrue; 799 829 800 830 if( BG_ClientListTest( &other->client->sess.ignoreList, ent-g_entities ) ) 801 831 ignore = qtrue; 802 832 803 trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%c%c%s\"", 804 mode == SAY_TEAM ? "tchat" : "chat", 805 ( ignore ) ? "[skipnotify]" : "", 806 name, Q_COLOR_ESCAPE, color, message ) ); 833 if( toSend ) 834 { 835 trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%s%c%c%s\"", 836 ( mode == SAY_TEAM || mode == SAY_ACTION_T ) ? "tchat" : "chat", 837 ( ignore ) ? "[skipnotify]" : "", 838 usePrefix ? prefix : "", 839 name, Q_COLOR_ESCAPE, color, message ) ); 840 } 807 841 } 808 842 … … 844 878 default: 845 879 case SAY_ALL: 846 G_LogPrintf( "say: %s: %s\n", ent->client->pers.netname, chatText ); 847 Com_sprintf( name, sizeof( name ), "%s%s%c%c"EC": ", prefix, 880 if(ent->client->pers.teamSelection == PTE_NONE && G_admin_level(ent)<g_minLevelToSpecMM1.integer) 881 { 882 trap_SendServerCommand( ent-g_entities,va( "print \"Sorry, but your admin level is not permitted to speak to all while spectating.\n\"") ); 883 return; 884 } 885 G_LogPrintf( "say: %s%s^7: ^2%s^7\n", prefix, ent->client->pers.netname, chatText ); 886 Com_sprintf( name, sizeof( name ), "%s%c%c"EC": ", 848 887 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 849 888 color = COLOR_GREEN; 850 889 break; 851 890 891 case SAY_ACTION: 892 G_LogPrintf( "action: %s: %s\n", ent->client->pers.netname, chatText ); 893 Com_sprintf( name, sizeof( name ), "^2%s^7%s%s%c%c"EC" ", g_actionPrefix.string, prefix, 894 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 895 color = COLOR_WHITE; 896 break; 897 case SAY_ACTION_T: 898 G_LogPrintf( "actionteam: %s: %s\n", ent->client->pers.netname, chatText ); 899 if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) 900 Com_sprintf( name, sizeof( name ), EC"^5%s^7%s%c%c"EC"(%s)"EC" ", g_actionPrefix.string, 901 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, location ); 902 else 903 Com_sprintf( name, sizeof( name ), EC"^5%s^7%s%c%c"EC""EC" ", g_actionPrefix.string, 904 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 905 color = COLOR_WHITE; 906 break; 907 852 908 case SAY_TEAM: 853 G_LogPrintf( "sayteam: %s : %s\n", ent->client->pers.netname, chatText );909 G_LogPrintf( "sayteam: %s%s^7: ^5%s^7\n", prefix, ent->client->pers.netname, chatText ); 854 910 if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) 855 911 Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC") (%s)"EC": ", … … 858 914 Com_sprintf( name, sizeof( name ), EC"(%s%c%c"EC")"EC": ", 859 915 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 860 color = COLOR_CYAN; 916 917 if( ent->client->pers.teamSelection == PTE_NONE ) 918 color = COLOR_YELLOW; 919 else 920 color = COLOR_CYAN; 921 861 922 break; 862 923 … … 871 932 color = COLOR_MAGENTA; 872 933 break; 934 935 case SAY_ADMINS: 936 if( G_admin_permission( ent, ADMF_ADMINCHAT ) ) //Differentiate between inter-admin chatter and user-admin alerts 937 { 938 G_LogPrintf( "say_admins: [ADMIN]%s: %s\n", ent->client->pers.netname, chatText ); 939 Com_sprintf( name, sizeof( name ), "%s[ADMIN]%s%c%c"EC": ", prefix, 940 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 941 color = COLOR_MAGENTA; 942 } 943 else 944 { 945 G_LogPrintf( "say_admins: [PLAYER]%s: %s\n", ent->client->pers.netname, chatText ); 946 Com_sprintf( name, sizeof( name ), "%s[PLAYER]%s%c%c"EC": ", prefix, 947 ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE ); 948 color = COLOR_MAGENTA; 949 } 950 break; 873 951 } 874 952 875 953 Q_strncpyz( text, chatText, sizeof( text ) ); 876 954 955 //R1's simple flood protection (lowered in g_client timer actions) 956 if ( g_floodProtection.integer && !G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) 957 { 958 if ( ent->client->pers.floodTimer >= 100 ) return; 959 ent->client->pers.floodTimer += g_floodProtection.integer; 960 } 961 962 877 963 if( target ) 878 964 { 879 G_SayTo( ent, target, mode, color, name, text ); 880 return; 881 } 882 883 // echo the text to the console 884 if( g_dedicated.integer ) 885 G_Printf( "%s%s\n", name, text); 965 G_SayTo( ent, target, mode, color, name, text, prefix ); 966 return; 967 } 886 968 887 969 // send it to all the apropriate clients … … 889 971 { 890 972 other = &g_entities[ j ]; 891 G_SayTo( ent, other, mode, color, name, text );973 G_SayTo( ent, other, mode, color, name, text, prefix ); 892 974 } 893 975 … … 908 990 char *p; 909 991 char *args; 992 int offset = 0; 910 993 int mode = SAY_ALL; 911 994 … … 913 996 if( Q_stricmpn( args, "say_team ", 9 ) == 0 ) 914 997 mode = SAY_TEAM; 998 if( Q_stricmpn( args, "say_admins ", 11 ) == 0 || Q_stricmpn( args, "a ", 2 ) == 0) 999 mode = SAY_ADMINS; 915 1000 916 1001 // support parsing /m out of say text since some people have a hard … … 924 1009 return; 925 1010 } 1011 1012 if( !Q_stricmpn( args, "say /a ", 7) || 1013 !Q_stricmpn( args, "say_team /a ", 12) || 1014 !Q_stricmpn( args, "say /say_admins ", 16) || 1015 !Q_stricmpn( args, "say_team /say_admins ", 21) ) 1016 { 1017 mode = SAY_ADMINS; 1018 offset =3; 1019 } 1020 1021 if( mode == SAY_ADMINS) 1022 if(!G_admin_permission( ent, ADMF_ADMINCHAT ) ) 1023 { 1024 if( !g_publicSayadmins.integer ) 1025 { 1026 ADMP( "Sorry, but public use of say_admins has been disabled.\n" ); 1027 return; 1028 } 1029 else 1030 { 1031 ADMP( "Your message has been sent to any available admins and to the server logs.\n" ); 1032 } 1033 } 1034 1035 if( g_allowDonate.integer ) 1036 { 1037 args = G_SayConcatArgs(0); 1038 if( !Q_stricmpn( args, "say /donate", 11 ) || 1039 !Q_stricmpn( args, "say_team /donate", 16 ) ) 1040 { 1041 Cmd_Donate_f( ent ); 1042 return; 1043 } 1044 } 926 1045 927 1046 if( trap_Argc( ) < 2 ) 928 1047 return; 929 1048 1049 if( g_allowShare.integer ) 1050 { 1051 args = G_SayConcatArgs(0); 1052 if( !Q_stricmpn( args, "say /share", 10 ) || 1053 !Q_stricmpn( args, "say_team /share", 15 ) ) 1054 { 1055 Cmd_Share_f( ent ); 1056 return; 1057 } 1058 } 1059 1060 if( g_allowActions.integer && !Q_stricmpn( args, "say /me ", 8 ) ) 1061 { 1062 mode = SAY_ACTION; 1063 offset = 4; 1064 } 1065 1066 if( g_allowActions.integer && !Q_stricmpn( args, "say_team /me ", 13 ) ) 1067 { 1068 mode = SAY_ACTION_T; 1069 offset = 4; 1070 } 1071 930 1072 p = ConcatArgs( 1 ); 1073 p += offset; 931 1074 932 1075 G_Say( ent, NULL, mode, p ); … … 960 1103 p = ConcatArgs( 2 ); 961 1104 962 G_LogPrintf( "tell: %s to %s: %s\n", ent->client->pers.netname, target->client->pers.netname, p );1105 G_LogPrintf( "tell: %s^7 to %s^7: ^6%s^7\n", ent->client->pers.netname, target->client->pers.netname, p ); 963 1106 G_Say( ent, target, SAY_TELL, p ); 964 1107 // don't tell to the player self if it was already directed to this player … … 1056 1199 1057 1200 if( clientNum != -1 && 1058 level.clients[ clientNum ].pers.connected == CON_DISCONNECTED )1201 level.clients[ clientNum ].pers.connected != CON_CONNECTED ) 1059 1202 { 1060 1203 clientNum = -1; … … 1124 1267 "Un-Mute player \'%s\'", name ); 1125 1268 } 1126 else if( !Q_stricmp( arg1, " map_restart" ) )1269 else if( !Q_stricmp( arg1, "restartmap" ) ) 1127 1270 { 1128 1271 Com_sprintf( level.voteString, sizeof( level.voteString ), "%s", arg1 ); … … 1143 1286 sizeof( level.voteDisplayString ), "Change to map '%s'", arg2 ); 1144 1287 } 1145 else if( !Q_stricmp( arg1, " draw" ) )1146 { 1147 Com_sprintf( level.voteString, sizeof( level.voteString ), " evacuation" );1288 else if( !Q_stricmp( arg1, "nextmap" ) ) 1289 { 1290 Com_sprintf( level.voteString, sizeof( level.voteString ), "advanceMapRotation" ); 1148 1291 Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), 1149 " End match in a draw" );1292 "Skip to next map in rotation" ); 1150 1293 } 1151 1294 else … … 1153 1296 trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" ); 1154 1297 trap_SendServerCommand( ent-g_entities, "print \"Valid vote commands are: " 1155 "map, map_restart, draw, kick, mute and unmute\n" );1298 "map, restartmap, nextmap, kick, mute and unmute\n" ); 1156 1299 return; 1157 1300 } … … 1159 1302 trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE 1160 1303 " called a vote\n\"", ent->client->pers.netname ) ); 1304 G_Printf( "'%s^7' called a vote for '%s'\n", ent->client->pers.netname, 1305 level.voteString ) ; 1161 1306 1162 1307 ent->client->pers.voteCount++; … … 1479 1624 } 1480 1625 1626 #define EVOLVE_TRACE_HEIGHT 128.0f 1481 1627 #define AS_OVER_RT3 ((ALIENSENSE_RANGE*0.5f)/M_ROOT3) 1482 1628 … … 1552 1698 int clientNum; 1553 1699 int i; 1700 trace_t tr, tr2; 1554 1701 vec3_t infestOrigin; 1555 1702 int allowedClasses[ PCL_NUM_CLASSES ]; … … 1557 1704 pClass_t currentClass = ent->client->ps.stats[ STAT_PCLASS ]; 1558 1705 pClass_t newClass; 1706 1559 1707 int numLevels; 1708 vec3_t fromMins, fromMaxs, toMins, toMaxs; 1709 vec3_t temp; 1710 1560 1711 int entityList[ MAX_GENTITIES ]; 1561 1712 vec3_t range = { AS_OVER_RT3, AS_OVER_RT3, AS_OVER_RT3 }; … … 1563 1714 int num; 1564 1715 gentity_t *other; 1716 qboolean humanNear = qfalse; 1565 1717 1566 1718 if( ent->client->ps.stats[ STAT_HEALTH ] <= 0 ) … … 1590 1742 return; 1591 1743 } 1744 else if( g_grangerMode.integer && newClass == PCL_ALIEN_BUILDER0_UPG && !level.overmindPresent) 1745 { 1746 newClass = PCL_ALIEN_BUILDER0; 1747 } 1592 1748 1593 1749 //if we are not currently spectating, we are attempting evolution 1594 1750 if( ent->client->pers.classSelection != PCL_NONE ) 1595 1751 { 1596 if( ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING ) || 1597 ( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING ))1598 { 1599 trap_SendServerCommand( ent-g_entities, va( "print \"You cannot evolve while wallwalking\n\"" ));1752 1753 if( !level.overmindPresent ) 1754 { 1755 G_TriggerMenu( clientNum, MN_A_NOOVMND_EVOLVE ); 1600 1756 return; 1601 1757 } 1602 1758 1603 1759 //check there are no humans nearby 1604 1760 VectorAdd( ent->client->ps.origin, range, maxs ); 1605 1761 VectorSubtract( ent->client->ps.origin, range, mins ); 1606 1762 1607 1763 num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); 1608 1764 for( i = 0; i < num; i++ ) … … 1613 1769 ( other->s.eType == ET_BUILDABLE && other->biteam == BIT_HUMANS ) ) 1614 1770 { 1615 G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); 1616 return; 1771 humanNear = qtrue; 1617 1772 } 1618 } 1619 1620 if( !level.overmindPresent ) 1621 { 1622 G_TriggerMenu( clientNum, MN_A_NOOVMND_EVOLVE ); 1773 //If its the OM, then ignore all humans. 1774 if(other->s.eType == ET_BUILDABLE && other->s.modelindex == BA_A_OVERMIND) 1775 { 1776 humanNear = qfalse; 1777 break; 1778 } 1779 } 1780 1781 if(humanNear == qtrue) 1782 { 1783 G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); 1623 1784 return; 1624 1785 } 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\"" ) ); 1791 return; 1792 } 1793 1625 1794 1626 1795 //guard against selling the HBUILD weapons exploit … … 1629 1798 ent->client->ps.stats[ STAT_MISC ] > 0 ) 1630 1799 { 1631 G_TriggerMenu( ent->client->ps.clientNum, MN_A_EVOLVEBUILDTIMER ); 1800 trap_SendServerCommand( ent-g_entities, 1801 va( "print \"You cannot evolve until build timer expires\n\"" ) ); 1632 1802 return; 1633 1803 } … … 1637 1807 (short)ent->client->ps.persistant[ PERS_CREDIT ], 0 ); 1638 1808 1639 if( G_RoomForClassChange( ent, newClass, infestOrigin ) ) 1809 BG_FindBBoxForClass( currentClass, 1810 fromMins, fromMaxs, NULL, NULL, NULL ); 1811 BG_FindBBoxForClass( newClass, 1812 toMins, toMaxs, NULL, NULL, NULL ); 1813 1814 VectorCopy( ent->s.pos.trBase, infestOrigin ); 1815 1816 infestOrigin[ 2 ] += ( fabs( toMins[ 2 ] ) - fabs( fromMins[ 2 ] ) ) + 1.0f; 1817 VectorCopy( infestOrigin, temp ); 1818 temp[ 2 ] += EVOLVE_TRACE_HEIGHT; 1819 1820 //compute a place up in the air to start the real trace 1821 trap_Trace( &tr, infestOrigin, toMins, toMaxs, temp, ent->s.number, MASK_SHOT ); 1822 VectorCopy( infestOrigin, temp ); 1823 temp[ 2 ] += ( EVOLVE_TRACE_HEIGHT * tr.fraction ) - 1.0f; 1824 1825 //trace down to the ground so that we can evolve on slopes 1826 trap_Trace( &tr, temp, toMins, toMaxs, infestOrigin, ent->s.number, MASK_SHOT ); 1827 VectorCopy( tr.endpos, infestOrigin ); 1828 1829 //make REALLY sure 1830 trap_Trace( &tr2, ent->s.pos.trBase, NULL, NULL, infestOrigin, ent->s.number, MASK_SHOT ); 1831 1832 //check there is room to evolve 1833 if( !tr.startsolid && tr2.fraction == 1.0f ) 1640 1834 { 1641 1835 //...check we can evolve to that class 1642 if( numLevels >= 0&&1836 if( (numLevels >= 0 || g_freeFunds.integer) && 1643 1837 BG_FindStagesForClass( newClass, g_alienStage.integer ) && 1644 1838 BG_ClassIsAllowed( newClass ) ) 1645 1839 { 1840 G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 1841 1646 1842 ent->client->pers.evolveHealthFraction = (float)ent->client->ps.stats[ STAT_HEALTH ] / 1647 1843 (float)BG_FindHealthForClass( currentClass ); … … 1652 1848 ent->client->pers.evolveHealthFraction = 1.0f; 1653 1849 1654 //remove credit 1655 G_AddCreditToClient( ent->client, -(short)numLevels, qtrue ); 1850 //remove credit if not freefunds 1851 if (!g_freeFunds.integer) 1852 G_AddCreditToClient( ent->client, -(short)numLevels, qtrue ); 1656 1853 ent->client->pers.classSelection = newClass; 1657 1854 ClientUserinfoChanged( clientNum ); … … 1682 1879 BG_ClassIsAllowed( newClass ) ) 1683 1880 { 1881 G_LogOnlyPrintf("ClientTeamClass: %i alien %s\n", clientNum, s); 1882 1684 1883 ent->client->pers.classSelection = 1685 1884 ent->client->ps.stats[ STAT_PCLASS ] = newClass; … … 1718 1917 return; 1719 1918 } 1919 1920 G_LogOnlyPrintf("ClientTeamClass: %i human %s\n", clientNum, s); 1720 1921 1721 1922 G_PushSpawnQueue( &level.humanSpawnQueue, clientNum ); … … 1794 1995 1795 1996 // Don't allow destruction of buildables that cannot be rebuilt 1796 if( G_TimeTilSuddenDeath( ) <= 0 && 1797 BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) 1798 { 1997 if( level.suddenDeath && traceEnt->health > 0 && 1998 ( ( g_suddenDeathMode.integer == SDMODE_SELECTIVE && 1999 !BG_FindReplaceableTestForBuildable( traceEnt->s.modelindex ) ) || 2000 ( g_suddenDeathMode.integer == SDMODE_BP && 2001 BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) || 2002 g_suddenDeathMode.integer == SDMODE_NO_BUILD ) ) 2003 { 2004 trap_SendServerCommand( ent-g_entities, 2005 "print \"During Sudden Death you can only decon buildings that " 2006 "can be rebuilt\n\"" ); 1799 2007 return; 1800 2008 } … … 1820 2028 ent->client->pers.netname ) ); 1821 2029 1822 G_LogPrintf( "Decon: %i %i 0: %s deconstructed%s\n",2030 G_LogPrintf( "Decon: %i %i 0: %s ^3deconstructed^7 %s\n", 1823 2031 ent->client->ps.clientNum, 1824 2032 traceEnt->s.modelindex, … … 1831 2039 G_FreeEntity( traceEnt ); 1832 2040 1833 if( !g_cheats.integer ) 2041 // cheat or fast build -> no build timer 2042 if( !g_cheats.integer && !g_fastBuild.integer ) 1834 2043 ent->client->ps.stats[ STAT_MISC ] += 1835 2044 BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 2; 1836 2045 } 2046 } 2047 else 2048 { 2049 // We *can* deconstrute building on fire :) 2050 G_LogPrintf( "Decon: %i %i 0: %s ^3deconstructed^7 %s\n", 2051 ent->client->ps.clientNum, 2052 traceEnt->s.modelindex, 2053 ent->client->pers.netname, 2054 BG_FindNameForBuildable( traceEnt->s.modelindex ) ); 2055 2056 if( !deconstruct ) 2057 G_Damage( traceEnt, ent, ent, forward, tr.endpos, 10000, 0, MOD_SUICIDE ); 2058 else 2059 G_FreeEntity( traceEnt ); 2060 2061 // cheat or fast build -> no build timer 2062 if( !g_cheats.integer && !g_fastBuild.integer ) 2063 ent->client->ps.stats[ STAT_MISC ] += 2064 BG_FindBuildDelayForWeapon( ent->s.weapon ) >> 2; 1837 2065 } 1838 2066 } … … 1906 2134 //special case to allow switching between 1907 2135 //the blaster and the primary weapon 2136 ent->client->ps.weaponTime = 0; 1908 2137 1909 2138 if( ent->client->ps.weapon != WP_BLASTER ) … … 1989 2218 !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 1990 2219 { 1991 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOENERGYAMMOHERE ); 2220 trap_SendServerCommand( ent-g_entities, va( 2221 "print \"You must be near a reactor, repeater or armoury\n\"" ) ); 1992 2222 return; 1993 2223 } … … 1998 2228 if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 1999 2229 { 2000 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOARMOURYHERE);2230 trap_SendServerCommand( ent-g_entities, va( "print \"You must be near a powered armoury\n\"" ) ); 2001 2231 return; 2002 2232 } … … 2012 2242 } 2013 2243 2014 //can afford this? 2015 if( BG_FindPriceForWeapon( weapon ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] )2244 //can afford this? (if free funds then go buy, it's free !) 2245 if( !g_freeFunds.integer && BG_FindPriceForWeapon( weapon ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] ) 2016 2246 { 2017 2247 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); … … 2055 2285 maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER ); 2056 2286 2057 ent->client->ps.ammo = maxAmmo;2058 ent->client->ps.clips = maxClips;2287 BG_PackAmmoArray( weapon, ent->client->ps.ammo, ent->client->ps.powerups, 2288 maxAmmo, maxClips ); 2059 2289 2060 2290 G_ForceWeaponChange( ent, weapon ); … … 2064 2294 2065 2295 //subtract from funds 2066 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ), qfalse ); 2296 if (!g_freeFunds.integer) // buy it for free 2297 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForWeapon( weapon ), qfalse ); 2067 2298 } 2068 2299 else if( upgrade != UP_NONE ) … … 2076 2307 2077 2308 //can afford this? 2078 if( BG_FindPriceForUpgrade( upgrade ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] )2309 if( !g_freeFunds.integer && BG_FindPriceForUpgrade( upgrade ) > (short)ent->client->ps.persistant[ PERS_CREDIT ] ) 2079 2310 { 2080 2311 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOFUNDS ); … … 2120 2351 if( !G_RoomForClassChange( ent, PCL_HUMAN_BSUIT, newOrigin ) ) 2121 2352 { 2122 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITON);2353 trap_SendServerCommand( ent-g_entities, va( "print \"Not enough room here to put on a Battle Suit\n\"") ); 2123 2354 return; 2124 2355 } … … 2136 2367 2137 2368 //subtract from funds 2138 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2369 if (!g_freeFunds.integer) 2370 G_AddCreditToClient( ent->client, -(short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2139 2371 } 2140 2372 else … … 2164 2396 if( !G_BuildableRange( ent->client->ps.origin, 100, BA_H_ARMOURY ) ) 2165 2397 { 2166 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOARMOURYHERE);2398 trap_SendServerCommand( ent-g_entities, va( "print \"You must be near a powered armoury\n\"" ) ); 2167 2399 return; 2168 2400 } … … 2187 2419 ent->client->ps.stats[ STAT_MISC ] > 0 ) 2188 2420 { 2189 G_TriggerMenu( ent->client->ps.clientNum, MN_H_ARMOURYBUILDTIMER);2421 trap_SendServerCommand( ent-g_entities, va( "print \"Cannot sell until build timer expires\n\"" ) ); 2190 2422 return; 2191 2423 } … … 2194 2426 2195 2427 //add to funds 2196 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ), qfalse ); 2428 if (!g_freeFunds.integer) // yes free funds but not get 9999 credits :) 2429 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( weapon ), qfalse ); 2197 2430 } 2198 2431 … … 2219 2452 if( !G_RoomForClassChange( ent, PCL_HUMAN, newOrigin ) ) 2220 2453 { 2221 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITOFF);2454 trap_SendServerCommand( ent-g_entities, va( "print \"Not enough room here to take off your Battle Suit\n\"") ); 2222 2455 return; 2223 2456 } … … 2234 2467 2235 2468 //add to funds 2236 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2469 if (!g_freeFunds.integer) 2470 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( upgrade ), qfalse ); 2237 2471 } 2238 2472 } … … 2245 2479 ent->client->ps.stats[ STAT_MISC ] > 0 ) 2246 2480 { 2247 G_TriggerMenu( ent->client->ps.clientNum, MN_H_ARMOURYBUILDTIMER);2481 trap_SendServerCommand( ent-g_entities, va( "print \"Cannot sell until build timer expires\n\"" ) ); 2248 2482 continue; 2249 2483 } … … 2255 2489 2256 2490 //add to funds 2257 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ), qfalse ); 2491 if (!g_freeFunds.integer) 2492 G_AddCreditToClient( ent->client, (short)BG_FindPriceForWeapon( i ), qfalse ); 2258 2493 } 2259 2494 … … 2271 2506 BG_FindPurchasableForUpgrade( i ) ) 2272 2507 { 2273 2274 // shouldn't really need to test for this, but just to be safe2275 if( i == UP_BATTLESUIT )2276 {2277 vec3_t newOrigin;2278 2279 if( !G_RoomForClassChange( ent, PCL_HUMAN, newOrigin ) )2280 {2281 G_TriggerMenu( ent->client->ps.clientNum, MN_H_NOROOMBSUITOFF );2282 continue;2283 }2284 VectorCopy( newOrigin, ent->s.pos.trBase );2285 ent->client->ps.stats[ STAT_PCLASS ] = PCL_HUMAN;2286 }2287 2288 2508 BG_RemoveUpgradeFromInventory( i, ent->client->ps.stats ); 2289 2509 … … 2299 2519 !BG_FindInfinteAmmoForWeapon( j ) ) 2300 2520 { 2301 ent->client->ps.ammo = 0; 2302 ent->client->ps.clips = 0; 2521 BG_PackAmmoArray( j, ent->client->ps.ammo, ent->client->ps.powerups, 0, 0 ); 2303 2522 } 2304 2523 } … … 2306 2525 2307 2526 //add to funds 2308 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ), qfalse ); 2527 if (!g_freeFunds.integer) 2528 G_AddCreditToClient( ent->client, (short)BG_FindPriceForUpgrade( i ), qfalse ); 2309 2529 } 2310 2530 } … … 2341 2561 2342 2562 buildable = BG_FindBuildNumForName( s ); 2563 2564 if( level.suddenDeath ) 2565 { 2566 if( g_suddenDeathMode.integer == SDMODE_SELECTIVE && 2567 !BG_FindReplaceableTestForBuildable( buildable ) ) 2568 { 2569 trap_SendServerCommand( ent-g_entities, 2570 "print \"Only essential buildings can be rebuilt in Sudden Death\n\"" ); 2571 return; 2572 } 2573 else if( g_suddenDeathMode.integer == SDMODE_NO_BUILD ) 2574 { 2575 trap_SendServerCommand( ent-g_entities, 2576 "print \"Building is not allowed during Sudden Death\n\"" ); 2577 } 2578 } 2579 2580 if(g_repeaterOnReactor.integer && buildable == BA_H_REACTOR && level.reactorPresent) 2581 buildable = BA_H_REPEATER; 2582 2343 2583 team = ent->client->ps.stats[ STAT_PTEAM ]; 2344 2584 … … 2407 2647 } 2408 2648 2649 /* 2650 ================= 2651 Cmd_Share_f 2652 ================= 2653 */ 2654 void Cmd_Share_f( gentity_t *ent ) 2655 { 2656 int i, clientNum = 0, creds = 0, skipargs = 0; 2657 int clientNums[ MAX_CLIENTS ] = { -1 }; 2658 char cmd[ 12 ]; 2659 char arg1[ MAX_STRING_TOKENS ]; 2660 char arg2[ MAX_STRING_TOKENS ]; 2661 pTeam_t team; 2662 2663 if( !ent || !ent->client || ( ent->client->pers.teamSelection == PTE_NONE ) ) 2664 { 2665 return; 2666 } 2667 2668 if( !g_allowShare.integer ) 2669 { 2670 return; 2671 } 2672 2673 team = ent->client->pers.teamSelection; 2674 2675 G_SayArgv( 0, cmd, sizeof( cmd ) ); 2676 if( !Q_stricmp( cmd, "say" ) || !Q_stricmp( cmd, "say_team" ) ) 2677 { 2678 skipargs = 1; 2679 G_SayArgv( 1, cmd, sizeof( cmd ) ); 2680 } 2681 2682 // target player name is in arg1 2683 G_SayArgv( 1+skipargs, arg1, sizeof( arg1 ) ); 2684 // amount to be shared is in arg2 2685 G_SayArgv( 2+skipargs, arg2, sizeof( arg2 ) ); 2686 2687 if( arg1[0] && !strchr( arg1, ';' ) && Q_stricmp( arg1, "target_in_aim" ) ) 2688 { 2689 //check arg1 is a number 2690 for( i = 0; arg1[ i ]; i++ ) 2691 { 2692 if( arg1[ i ] < '0' || arg1[ i ] > '9' ) 2693 { 2694 clientNum = -1; 2695 break; 2696 } 2697 } 2698 2699 if( clientNum >= 0 ) 2700 { 2701 clientNum = atoi( arg1 ); 2702 } 2703 else if( G_ClientNumbersFromString( arg1, clientNums, MAX_CLIENTS ) == 1 ) 2704 { 2705 // there was one partial name match 2706 clientNum = clientNums[ 0 ]; 2707 } 2708 else 2709 { 2710 // look for an exact name match before bailing out 2711 clientNum = G_ClientNumberFromString( ent, arg1 ); 2712 if( clientNum == -1 ) 2713 { 2714 trap_SendServerCommand( ent-g_entities, 2715 "print \"share: invalid player name specified.\n\"" ); 2716 return; 2717 } 2718 } 2719 } 2720 else // arg1 not set 2721 { 2722 vec3_t forward, end; 2723 trace_t tr; 2724 gentity_t *traceEnt; 2725 2726 2727 // trace a teammate 2728 AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL ); 2729 VectorMA( ent->client->ps.origin, 8192 * 16, forward, end ); 2730 2731 trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); 2732 traceEnt = &g_entities[ tr.entityNum ]; 2733 2734 if( tr.fraction < 1.0f && traceEnt->client && 2735 ( traceEnt->client->pers.teamSelection == team ) ) 2736 { 2737 clientNum = traceEnt - g_entities; 2738 } 2739 else 2740 { 2741 trap_SendServerCommand( ent-g_entities, 2742 va( "print \"share: aim at a teammate to share %s.\n\"", 2743 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) ); 2744 return; 2745 } 2746 } 2747 2748 // verify target player team 2749 if( ( clientNum < 0 ) || ( clientNum >= level.maxclients ) || 2750 ( level.clients[ clientNum ].pers.teamSelection != team ) ) 2751 { 2752 trap_SendServerCommand( ent-g_entities, 2753 "print \"share: not a valid player of your team.\n\"" ); 2754 return; 2755 } 2756 2757 if( !arg2[0] || strchr( arg2, ';' ) ) 2758 { 2759 // default credit count 2760 if( team == PTE_HUMANS ) 2761 { 2762 creds = FREEKILL_HUMAN; 2763 } 2764 else if( team == PTE_ALIENS ) 2765 { 2766 creds = FREEKILL_ALIEN; 2767 } 2768 } 2769 else 2770 { 2771 //check arg2 is a number 2772 for( i = 0; arg2[ i ]; i++ ) 2773 { 2774 if( arg2[ i ] < '0' || arg2[ i ] > '9' ) 2775 { 2776 trap_SendServerCommand( ent-g_entities, 2777 "print \"usage: share [name|slot#] [amount]\n\"" ); 2778 break; 2779 } 2780 } 2781 2782 // credit count from parameter 2783 creds = atoi( arg2 ); 2784 } 2785 2786 // player specified "0" to transfer 2787 if( creds <= 0 ) 2788 { 2789 trap_SendServerCommand( ent-g_entities, 2790 "print \"Ooh, you are a generous one, indeed!\n\"" ); 2791 return; 2792 } 2793 2794 // transfer only credits the player really has 2795 if( creds > ent->client->ps.persistant[ PERS_CREDIT ] ) 2796 { 2797 creds = ent->client->ps.persistant[ PERS_CREDIT ]; 2798 } 2799 2800 // player has no credits 2801 if( creds <= 0 ) 2802 { 2803 trap_SendServerCommand( ent-g_entities, 2804 "print \"Earn some first, lazy gal!\n\"" ); 2805 return; 2806 } 2807 2808 // allow transfers only up to the credit/evo limit 2809 if( ( team == PTE_HUMANS ) && 2810 ( creds > HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) ) 2811 { 2812 creds = HUMAN_MAX_CREDITS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ]; 2813 } 2814 else if( ( team == PTE_ALIENS ) && 2815 ( creds > ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] ) ) 2816 { 2817 creds = ALIEN_MAX_KILLS - level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ]; 2818 } 2819 2820 // target cannot take any more credits 2821 if( creds <= 0 ) 2822 { 2823 trap_SendServerCommand( ent-g_entities, 2824 va( "print \"share: player cannot receive any more %s.\n\"", 2825 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) ); 2826 return; 2827 } 2828 2829 // transfer credits 2830 ent->client->ps.persistant[ PERS_CREDIT ] -= creds; 2831 trap_SendServerCommand( ent-g_entities, 2832 va( "print \"share: transferred %d %s to %s^7.\n\"", creds, 2833 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints", 2834 level.clients[ clientNum ].pers.netname ) ); 2835 level.clients[ clientNum ].ps.persistant[ PERS_CREDIT ] += creds; 2836 trap_SendServerCommand( clientNum, 2837 va( "print \"You have received %d %s from %s^7.\n\"", creds, 2838 ( team == PTE_HUMANS ) ? "credits" : "evolvepoints", 2839 ent->client->pers.netname ) ); 2840 2841 G_LogPrintf( "Share: %i %i %i %d: %s^7 transferred %d%s to %s^7\n", 2842 ent->client->ps.clientNum, 2843 clientNum, 2844 team, 2845 creds, 2846 ent->client->pers.netname, 2847 creds, 2848 ( team == PTE_HUMANS ) ? "c" : "e", 2849 level.clients[ clientNum ].pers.netname ); 2850 } 2851 2409 2852 2410 2853 /* … … 2517 2960 2518 2961 // can't follow another spectator 2519 if( level.clients[ clientnum ]. sess.sessionTeam == TEAM_SPECTATOR)2962 if( level.clients[ clientnum ].pers.teamSelection == PTE_NONE ) 2520 2963 continue; 2521 2964 … … 2530 2973 } 2531 2974 2975 /* 2976 ================= 2977 Cmd_Donate_f 2978 2979 Alms for the poor 2980 ================= 2981 */ 2982 void Cmd_Donate_f( gentity_t *ent ) 2983 { 2984 int divisor; 2985 char s[20]; 2986 int skipargs = 0; 2987 int value; 2988 2989 if( !ent->client || !g_allowDonate.integer ) return; 2990 2991 if( ent->client->pers.teamSelection == PTE_ALIENS ) 2992 divisor = level.numAlienClients-1; 2993 else if( ent->client->pers.teamSelection == PTE_HUMANS ) 2994 divisor = level.numHumanClients-1; 2995 else 2996 return; 2997 2998 if(ent->client->pers.teamSelection == PTE_NONE ) 2999 { 3000 trap_SendServerCommand( ent-g_entities, 3001 va( "print \"donate: spectators cannot be so gracious\n\"" ) ); 3002 return; 3003 } 3004 3005 if( divisor < 1 ) { 3006 trap_SendServerCommand( ent-g_entities, 3007 "print \"donate: get yourself some teammates first\n\"" ); 3008 return; 3009 } 3010 3011 G_SayArgv ( 0, s, sizeof( s ) ); 3012 if ( !Q_stricmp( s, "say" ) || !Q_stricmp( s, "say_team" ) ) 3013 { 3014 skipargs = 1; 3015 G_SayArgv ( 1, s, sizeof( s )); //usefull ? 3016 } 3017 3018 G_SayArgv( 1 + skipargs, s, sizeof( s ) ); 3019 value = atoi(s); 3020 if( value <= 0 ) { 3021 trap_SendServerCommand( ent-g_entities, 3022 "print \"donate: very funny\n\"" ); 3023 return; 3024 } 3025 3026 G_Donate(ent->client, value); 3027 } 3028 2532 3029 /* 2533 3030 ================= … … 2545 3042 /* 2546 3043 ================= 2547 Cmd_Follow_f 3044 Cmd_Follow_f (with r1 changes in here) 2548 3045 ================= 2549 3046 */ … … 2788 3285 { "say", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2789 3286 { "say_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 3287 { "say_admins", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 3288 { "a", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2790 3289 { "m", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 2791 3290 { "mt", CMD_MESSAGE|CMD_INTERMISSION, G_PrivateMessage }, 2792 3291 { "me", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, 2793 3292 { "score", CMD_INTERMISSION, ScoreboardMessage }, 2794 3293 … … 2807 3306 { "ptrcverify", 0, Cmd_PTRCVerify_f }, 2808 3307 { "ptrcrestore", 0, Cmd_PTRCRestore_f }, 3308 { "share", CMD_TEAM, Cmd_Share_f }, 3309 { "donate", CMD_TEAM, Cmd_Donate_f }, 2809 3310 2810 3311 { "follow", CMD_NOTEAM, Cmd_Follow_f }, … … 3048 3549 gentity_t *tmpent; 3049 3550 3551 if ( g_floodProtection.integer && !G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) 3552 { 3553 if ( ent->client->pers.floodTimer >= 100 ) return; 3554 ent->client->pers.floodTimer += g_floodProtection.integer; 3555 } 3556 3050 3557 if( !g_privateMessages.integer && ent ) 3051 3558 { … … 3102 3609 3103 3610 color = teamonly ? COLOR_CYAN : COLOR_YELLOW; 3611 3612 if( !Q_stricmp( name, "console" ) ) 3613 { 3614 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3615 ADMP( va( "^%csent to Console.\n", color ) ); 3616 3617 G_LogPrintf( "privmsg: %s^7: Console: ^6%s^7\n", 3618 ( ent ) ? ent->client->pers.netname : "Console", msg ); 3619 3620 return; 3621 } 3104 3622 3105 3623 Q_strncpyz( str, … … 3117 3635 trap_SendServerCommand( pids[ i ], va( 3118 3636 "chat \"%s^%c -> ^7%s^7: (%d recipients): ^%c%s^7\" %i", 3119 ( ent ) ? ent->client->pers.netname : " console",3637 ( ent ) ? ent->client->pers.netname : "Console", 3120 3638 color, 3121 3639 name, … … 3124 3642 msg, 3125 3643 ent ? ent-g_entities : -1 ) ); 3126 if( ent ) 3127 { 3128 trap_SendServerCommand( pids[ i ], va( 3129 "print \">> to reply, say: /m %d [your message] <<\n\"", 3130 ( ent - g_entities ) ) ); 3131 } 3644 3132 3645 trap_SendServerCommand( pids[ i ], va( 3133 3646 "cp \"^%cprivate message from ^7%s^7\"", color, 3134 ( ent ) ? ent->client->pers.netname : " console" ) );3647 ( ent ) ? ent->client->pers.netname : "Console" ) ); 3135 3648 } 3136 3649 … … 3140 3653 else 3141 3654 { 3142 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3655 if( ent ) 3656 ADMP( va( "^%cPrivate message: ^7%s\n", color, msg ) ); 3657 3143 3658 ADMP( va( "%s\n", str ) ); 3144 3145 G_LogPrintf( "%s: %s: %s: %s\n",3146 ( teamonly ) ? "tprivmsg" : "privmsg",3147 ( ent ) ? ent->client->pers.netname : "console",3148 name, msg );3149 3659 } 3150 3660 -
src/game/g_cmds.c
r122 r123 83 83 { 84 84 gclient_t *cl; 85 int i dnum;85 int i; 86 86 char s2[ MAX_STRING_CHARS ]; 87 87 char n2[ MAX_STRING_CHARS ]; 88 88 89 89 // numeric values are just slot numbers 90 if( s[ 0 ] >= '0' && s[ 0 ] <= '9' ) 91 { 92 idnum = atoi( s ); 93 94 if( idnum < 0 || idnum >= level.maxclients ) 90 for( i = 0; s[ i ] && isdigit( s[ i ] ); i++ ); 91 if( !s[ i ] ) 92 { 93 i = atoi( s ); 94 95 if( i < 0 || i >= level.maxclients ) 95 96 return -1; 96 97 97 cl = &level.clients[ i dnum];98 cl = &level.clients[ i ]; 98 99 99 100 if( cl->pers.connected == CON_DISCONNECTED ) 100 101 return -1; 101 102 102 return i dnum;103 return i; 103 104 } 104 105 … … 106 107 G_SanitiseName( s, s2 ); 107 108 108 for( i dnum = 0, cl = level.clients; idnum < level.maxclients; idnum++, cl++ )109 for( i = 0, cl = level.clients; i < level.maxclients; i++, cl++ ) 109 110 { 110 111 if( cl->pers.connected == CON_DISCONNECTED ) … … 114 115 115 116 if( !strcmp( n2, s2 ) ) 116 return i dnum;117 return i; 117 118 } 118 119 … … 950 951 } 951 952 952 Com_sprintf( text, sizeof( text ), "%s^7", chatText);953 Q_strncpyz( text, chatText, sizeof( text ) ); 953 954 954 955 //R1's simple flood protection (lowered in g_client timer actions) … … 1668 1669 VectorCopy( newOrigin, temp ); 1669 1670 temp[ 2 ] += nudgeHeight; 1670 trap_Trace( &tr, newOrigin, toMins, toMaxs, temp, ent->s.number, MASK_ SHOT);1671 trap_Trace( &tr, newOrigin, toMins, toMaxs, temp, ent->s.number, MASK_PLAYERSOLID ); 1671 1672 1672 1673 //trace down to the ground so that we can evolve on slopes 1673 1674 VectorCopy( newOrigin, temp ); 1674 1675 temp[ 2 ] += ( nudgeHeight * tr.fraction ); 1675 trap_Trace( &tr, temp, toMins, toMaxs, newOrigin, ent->s.number, MASK_ SHOT);1676 trap_Trace( &tr, temp, toMins, toMaxs, newOrigin, ent->s.number, MASK_PLAYERSOLID ); 1676 1677 VectorCopy( tr.endpos, newOrigin ); 1677 1678 1678 1679 //make REALLY sure 1679 1680 trap_Trace( &tr, newOrigin, toMins, toMaxs, newOrigin, 1680 ent->s.number, MASK_ SHOT);1681 ent->s.number, MASK_PLAYERSOLID ); 1681 1682 1682 1683 //check there is room to evolve … … 2374 2375 } 2375 2376 2376 if( trap_Argc( ) >= 2 )2377 {2378 trap_Argv( 2, s, sizeof( s ) );2379 2380 //retrigger the armoury menu2381 if( !Q_stricmp( s, "retrigger" ) )2382 ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES;2383 }2384 2385 2377 //update ClientInfo 2386 2378 ClientUserinfoChanged( ent->client->ps.clientNum ); … … 2540 2532 else 2541 2533 trap_SendServerCommand( ent-g_entities, va( "print \"Unknown item\n\"" ) ); 2542 2543 if( trap_Argc( ) >= 2 )2544 {2545 trap_Argv( 2, s, sizeof( s ) );2546 2547 //retrigger the armoury menu2548 if( !Q_stricmp( s, "retrigger" ) )2549 ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES;2550 }2551 2534 2552 2535 //update ClientInfo -
src/game/g_local.h
r119 r123 199 199 qboolean active; // for power repeater, but could be useful elsewhere 200 200 qboolean powered; // for human buildables 201 int buildpoints; // buildpoints remains to this generator 201 202 int builtBy; // clientNum of person that built this 202 203 gentity_t *dccNode; // controlling dcc … … 295 296 { 296 297 team_t sessionTeam; 298 pTeam_t restartTeam; //for !restart keepteams and !restart switchteams 297 299 int spectatorTime; // for determining next-in-line to play 298 300 spectatorState_t spectatorState; … … 357 359 qboolean denyBuild; 358 360 int adminLevel; 361 int floodTimer; 359 362 } clientPersistant_t; 360 363 … … 461 464 int unlaggedTime; 462 465 466 int jetpack_beat; // waiting time before turn on jetpack when power down 467 int jetpack_power; 463 468 }; 464 469 … … 533 538 int num_entities; // current number, <= MAX_GENTITIES 534 539 535 int warmupTime; // restart match at this time536 537 540 fileHandle_t logFile; 538 541 … … 558 561 int numPlayingClients; // connected, non-spectators 559 562 int sortedClients[MAX_CLIENTS]; // sorted by score 563 int numNewbies; // number of UnnamedPlayers who have been renamed this round. 560 564 561 565 int snd_fry; // sound index for standing in lava 562 563 int warmupModificationCount; // for detecting if g_warmup is changed564 566 565 567 // voting state … … 635 637 pTeam_t lastWin; 636 638 639 int suddenDeathABuildPoints; 640 int suddenDeathHBuildPoints; 641 qboolean suddenDeath; 637 642 timeWarning_t suddenDeathWarning; 638 643 timeWarning_t timelimitWarning; … … 655 660 656 661 char layout[ MAX_QPATH ]; 662 663 int warmupMessageTime; // last warmup message level.time 657 664 658 665 pTeam_t surrenderTeam; … … 695 702 void G_MatchOnePlayer( int *plist, int num, char *err, int len ); 696 703 int G_ClientNumbersFromString( char *s, int *plist, int max ); 704 void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ); 697 705 int G_SayArgc( void ); 698 706 qboolean G_SayArgv( int n, char *buffer, int bufferLength ); … … 703 711 void G_SanitiseName( char *in, char *out ); 704 712 void G_PrivateMessage( gentity_t *ent ); 713 void Cmd_Share_f( gentity_t *ent ); 714 void Cmd_Donate_f( gentity_t *ent ); 705 715 706 716 // … … 746 756 buildable_t spawn, vec3_t spawnOrigin ); 747 757 758 gentity_t* G_FindGenerator( buildableTeam_t team, vec3_t origin ); 748 759 buildable_t G_IsPowered( vec3_t origin ); 749 760 qboolean G_IsDCCBuilt( void ); … … 915 926 void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod ); 916 927 qboolean SpotWouldTelefrag( gentity_t *spot ); 928 char *G_NextNewbieName( gentity_t *ent ); 917 929 918 930 // … … 944 956 void G_RunThink( gentity_t *ent ); 945 957 void QDECL G_LogPrintf( const char *fmt, ... ); 958 void QDECL G_LogOnlyPrintf( const char *fmt, ... ); 946 959 void SendScoreboardMessageToAllClients( void ); 947 960 void QDECL G_Printf( const char *fmt, ... ); … … 953 966 void LogExit( const char *string ); 954 967 int G_TimeTilSuddenDeath( void ); 968 void G_Donate( gclient_t *client, short value ); 955 969 956 970 // … … 962 976 void ClientBegin( int clientNum ); 963 977 void ClientCommand( int clientNum ); 978 int ClientPingOverride( void ); 964 979 965 980 // … … 1100 1115 extern vmCvar_t g_dedicated; 1101 1116 extern vmCvar_t g_cheats; 1117 extern vmCvar_t g_version; 1102 1118 extern vmCvar_t g_maxclients; // allow this many total, including spectators 1103 1119 extern vmCvar_t g_maxGameClients; // allow this many active … … 1106 1122 extern vmCvar_t g_minNameChangePeriod; 1107 1123 extern vmCvar_t g_maxNameChanges; 1124 extern vmCvar_t g_newbieNumbering; 1125 extern vmCvar_t g_newbieNamePrefix; 1108 1126 1109 1127 extern vmCvar_t g_timelimit; 1110 1128 extern vmCvar_t g_suddenDeathTime; 1129 extern vmCvar_t g_suddenDeathMode; 1111 1130 extern vmCvar_t g_friendlyFire; 1112 1131 extern vmCvar_t g_friendlyFireHumans; 1113 1132 extern vmCvar_t g_friendlyFireAliens; 1114 1133 extern vmCvar_t g_friendlyBuildableFire; 1134 extern vmCvar_t g_friendlyFireMovementAttacks; 1115 1135 extern vmCvar_t g_password; 1116 1136 extern vmCvar_t g_needpass; … … 1129 1149 extern vmCvar_t g_warmup; 1130 1150 extern vmCvar_t g_doWarmup; 1151 extern vmCvar_t g_warmupMessage; 1131 1152 extern vmCvar_t g_blood; 1132 1153 extern vmCvar_t g_allowVote; … … 1140 1161 extern vmCvar_t pmove_msec; 1141 1162 extern vmCvar_t g_rankings; 1163 extern vmCvar_t g_allowShare; 1164 extern vmCvar_t g_allowDonate; 1165 extern vmCvar_t g_grangerMode; 1166 extern vmCvar_t g_repeaterOnReactor; 1167 extern vmCvar_t g_jetpackLimit; 1168 extern vmCvar_t g_autoDonate; 1142 1169 extern vmCvar_t g_enableDust; 1143 1170 extern vmCvar_t g_enableBreath; … … 1146 1173 extern vmCvar_t g_humanBuildPoints; 1147 1174 extern vmCvar_t g_alienBuildPoints; 1175 extern vmCvar_t g_reactorBuildPoints; 1176 extern vmCvar_t g_repeaterBuildPoints; 1177 extern vmCvar_t g_overmindBuildPoints; 1178 extern vmCvar_t g_eggBuildPoints; 1179 extern vmCvar_t g_zoneBuildPoints; 1148 1180 extern vmCvar_t g_humanStage; 1149 1181 extern vmCvar_t g_humanKills; … … 1170 1202 extern vmCvar_t g_initialMapRotation; 1171 1203 extern vmCvar_t g_chatTeamPrefix; 1204 extern vmCvar_t g_specsSeeTeamchat; 1172 1205 1173 1206 extern vmCvar_t g_shove; … … 1183 1216 extern vmCvar_t g_adminNameProtect; 1184 1217 extern vmCvar_t g_adminTempBan; 1185 1218 extern vmCvar_t g_minLevelToSpecMM1; 1219 extern vmCvar_t g_adminWarnMessage; 1186 1220 extern vmCvar_t g_privateMessages; 1221 extern vmCvar_t g_publicSayadmins; 1222 extern vmCvar_t g_allowActions; 1223 extern vmCvar_t g_actionPrefix; 1224 extern vmCvar_t g_floodProtection; 1225 extern vmCvar_t g_autoRegister; 1226 1227 extern vmCvar_t g_slapKnockback; 1228 extern vmCvar_t g_slapDamage; 1229 1230 extern vmCvar_t g_hiddenClients; 1231 1232 extern vmCvar_t g_dretchPunt; 1233 1234 extern vmCvar_t g_freeFunds; 1235 extern vmCvar_t g_fastBuild; 1236 extern vmCvar_t g_noBaseAttack; 1237 extern vmCvar_t g_cheatAdminLevel; // an admin above or equal this level can use cheat, disable if 0 1238 1239 extern vmCvar_t g_playerVotePercent; 1240 extern vmCvar_t g_globalVotePercent; 1187 1241 1188 1242 void trap_Printf( const char *fmt ); … … 1234 1288 void trap_SnapVector( float *v ); 1235 1289 void trap_SendGameStat( const char *data ); 1290 1291 void do_health( gentity_t *ent, int quantity ); -
src/game/g_local.h
r122 r123 325 325 qboolean localClient; // true if "ip" info key is "localhost" 326 326 qboolean initialSpawn; // the first spawn should be at a cool location 327 qboolean predictItemPickup; // based on cg_predictItems userinfo328 327 qboolean pmoveFixed; // 329 328 char netname[ MAX_NETNAME ]; … … 459 458 460 459 int lastFlameBall; // s.number of the last flame ball fired 461 462 #define RAM_FRAMES 1 // number of frames to wait before retriggering463 int retriggerArmouryMenu; // frame number to retrigger the armoury menu464 460 465 461 unlagged_t unlaggedHist[ MAX_UNLAGGED_MARKERS ]; -
src/qcommon/common.c
r119 r123 34 34 35 35 int demo_protocols[] = 36 { PROTOCOL_VERSION, 0 };36 { 66, 67, 68, 69, 0 }; 37 37 38 38 #define MAX_NUM_ARGVS 50 … … 2372 2372 */ 2373 2373 void Com_Init( char *commandLine ) { 2374 char *s;2375 2374 2376 2375 Com_Printf( "%s %s %s\n", Q3_VERSION, PLATFORM_STRING, __DATE__ ); … … 2479 2478 Cmd_AddCommand ("writeconfig", Com_WriteConfig_f ); 2480 2479 2481 s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); 2482 com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); 2480 com_version = Cvar_Get ("version", FULL_VERSION, CVAR_ROM | CVAR_SERVERINFO ); 2483 2481 2484 2482 Sys_Init(); … … 2696 2694 } while ( msec < minMsec ); 2697 2695 Cbuf_Execute (); 2696 Cdelay_Frame (); 2698 2697 2699 2698 if (com_altivec->modified) -
src/qcommon/common.c
r62 r123 2947 2947 } 2948 2948 2949 #ifndef DEDICATED 2950 /* 2951 =============== 2952 Field_CompleteKeyname 2953 =============== 2954 */ 2955 static void Field_CompleteKeyname( void ) 2956 { 2957 matchCount = 0; 2958 shortestMatch[ 0 ] = 0; 2959 2960 Key_KeynameCompletion( FindMatches ); 2961 2962 if( matchCount == 0 ) 2963 return; 2964 2965 Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) - 2966 strlen( completionString ) ], shortestMatch, 2967 sizeof( completionField->buffer ) ); 2968 completionField->cursor = strlen( completionField->buffer ); 2969 2970 if( matchCount == 1 ) 2971 { 2972 Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " ); 2973 completionField->cursor++; 2974 return; 2975 } 2976 2977 Com_Printf( "]%s\n", completionField->buffer ); 2978 2979 Key_KeynameCompletion( PrintMatches ); 2980 } 2981 #endif 2982 2949 2983 /* 2950 2984 =============== … … 2963 2997 return; 2964 2998 2965 Q_strcat( completionField->buffer, sizeof( completionField->buffer ), 2966 shortestMatch + strlen( completionString ) ); 2999 Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) - 3000 strlen( completionString ) ], shortestMatch, 3001 sizeof( completionField->buffer ) ); 2967 3002 completionField->cursor = strlen( completionField->buffer ); 2968 3003 … … 3005 3040 completionString = Cmd_Argv( completionArgument - 1 ); 3006 3041 3042 #ifndef DEDICATED 3043 // Unconditionally add a '\' to the start of the buffer 3044 if( completionField->buffer[ 0 ] && 3045 completionField->buffer[ 0 ] != '\\' ) 3046 { 3047 if( completionField->buffer[ 0 ] != '/' ) 3048 { 3049 // Buffer is full, refuse to complete 3050 if( strlen( completionField->buffer ) + 1 >= 3051 sizeof( completionField->buffer ) ) 3052 return; 3053 3054 memmove( &completionField->buffer[ 1 ], 3055 &completionField->buffer[ 0 ], 3056 strlen( completionField->buffer ) + 1 ); 3057 completionField->cursor++; 3058 } 3059 3060 completionField->buffer[ 0 ] = '\\'; 3061 } 3062 #endif 3063 3007 3064 if( completionArgument > 1 ) 3008 3065 { … … 3010 3067 3011 3068 #ifndef DEDICATED 3012 // If the very first token does not have a leading \ or /, 3013 // refuse to autocomplete 3014 if( cmd == completionField->buffer ) 3015 { 3016 if( baseCmd[ 0 ] != '\\' && baseCmd[ 0 ] != '/' ) 3017 return; 3018 3069 // This should always be true 3070 if( baseCmd[ 0 ] == '\\' || baseCmd[ 0 ] == '/' ) 3019 3071 baseCmd++; 3020 }3021 3072 #endif 3022 3073 … … 3049 3100 Field_CompleteFilename( "", "txt", qfalse ); 3050 3101 } 3051 else if( !Q_stricmp( baseCmd, "demo" ) && completionArgument == 2 )3052 {3053 char demoExt[ 16 ];3054 3055 Com_sprintf( demoExt, sizeof( demoExt ), ".dm_%d", PROTOCOL_VERSION );3056 Field_CompleteFilename( "demos", demoExt, qtrue );3057 }3058 3102 else if( ( !Q_stricmp( baseCmd, "toggle" ) || 3059 3103 !Q_stricmp( baseCmd, "vstr" ) || … … 3070 3114 Field_CompleteCommand( p, qfalse, qtrue ); 3071 3115 } 3116 #ifndef DEDICATED 3117 else if( !Q_stricmp( baseCmd, "demo" ) && completionArgument == 2 ) 3118 { 3119 char demoExt[ 16 ]; 3120 3121 Com_sprintf( demoExt, sizeof( demoExt ), ".dm_%d", PROTOCOL_VERSION ); 3122 Field_CompleteFilename( "demos", demoExt, qtrue ); 3123 } 3072 3124 else if( !Q_stricmp( baseCmd, "rcon" ) && completionArgument == 2 ) 3073 3125 { … … 3078 3130 Field_CompleteCommand( p, qtrue, qtrue ); 3079 3131 } 3080 else if( !Q_stricmp( baseCmd, "bind" ) && completionArgument >= 3)3132 else if( !Q_stricmp( baseCmd, "bind" ) ) 3081 3133 { 3082 // Skip "bind <key> " 3083 p = Com_SkipTokens( cmd, 2, " " ); 3084 3085 if( p > cmd ) 3086 Field_CompleteCommand( p, qtrue, qtrue ); 3134 if( completionArgument == 2 ) 3135 { 3136 // Skip "bind " 3137 p = Com_SkipTokens( cmd, 1, " " ); 3138 3139 if( p > cmd ) 3140 Field_CompleteKeyname( ); 3141 } 3142 else if( completionArgument >= 3 ) 3143 { 3144 // Skip "bind <key> " 3145 p = Com_SkipTokens( cmd, 2, " " ); 3146 3147 if( p > cmd ) 3148 Field_CompleteCommand( p, qtrue, qtrue ); 3149 } 3087 3150 } 3151 #endif 3088 3152 } 3089 3153 } … … 3106 3170 3107 3171 if( matchCount == 0 ) 3108 return; // no matches 3109 3110 if( cmd == completionField->buffer ) 3111 { 3112 #ifndef DEDICATED 3113 Com_sprintf( completionField->buffer, 3114 sizeof( completionField->buffer ), "\\%s", shortestMatch ); 3115 #else 3116 Com_sprintf( completionField->buffer, 3117 sizeof( completionField->buffer ), "%s", shortestMatch ); 3118 #endif 3119 } 3120 else 3121 { 3122 Q_strcat( completionField->buffer, sizeof( completionField->buffer ), 3123 shortestMatch + strlen( completionString ) ); 3124 } 3172 return; // no matches 3173 3174 Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) - 3175 strlen( completionString ) ], shortestMatch, 3176 sizeof( completionField->buffer ) ); 3125 3177 3126 3178 completionField->cursor = strlen( completionField->buffer ); -
src/qcommon/cvar.c
r119 r123 834 834 for (var = cvar_vars ; var ; var = var->next) { 835 835 if (var->flags & bit) { 836 Info_SetValueForKey (info, var->name, var->string); 836 if (!strcmp (var->name, "sv_maxclients")) { 837 cvar_t *g_hiddenClients = Cvar_Get ("g_hiddenClients", "0", 0); 838 Info_SetValueForKey (info, var->name, 839 va ("%i", var->integer - g_hiddenClients->integer)); 840 } else { 841 Info_SetValueForKey (info, var->name, var->string); 842 } 837 843 } 838 844 } -
src/qcommon/cvar.c
r1 r123 499 499 qboolean Cvar_Command( void ) { 500 500 cvar_t *v; 501 char string[ TRUNCATE_LENGTH ];502 char resetString[ TRUNCATE_LENGTH ];503 char latchedString[ TRUNCATE_LENGTH ];504 501 505 502 // check variables … … 511 508 // perform a variable print or set 512 509 if ( Cmd_Argc() == 1 ) { 513 Com_TruncateLongString( string, v->string );514 Com_TruncateLongString( resetString, v->resetString );515 510 Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\"", 516 v->name, string );511 v->name, v->string ); 517 512 518 513 if ( !( v->flags & CVAR_ROM ) ) { 519 if ( !Q_stricmp( string,resetString ) ) {514 if ( !Q_stricmp( v->string, v->resetString ) ) { 520 515 Com_Printf (", the default" ); 521 516 } else { 522 517 Com_Printf (" default:\"%s" S_COLOR_WHITE "\"", 523 resetString );518 v->resetString ); 524 519 } 525 520 } … … 528 523 529 524 if ( v->latchedString ) { 530 Com_TruncateLongString( latchedString, v->latchedString ); 531 Com_Printf( "latched: \"%s\"\n", latchedString ); 525 Com_Printf( "latched: \"%s\"\n", v->latchedString ); 532 526 } 533 527 return qtrue; -
src/qcommon/files.c
r119 r123 98 98 e.g. the qpath "sound/newstuff/test.wav" would be searched for in the following places: 99 99 100 home path + current game's directory 100 101 home path + current game's zip files 101 home path + current game's directory102 base path + current game's directory 102 103 base path + current game's zip files 103 basepath + current game's directory104 cd path + current game's directory 104 105 cd path + current game's zip files 105 cd path + current game's directory 106 106 107 home path + base game's directory 107 108 home path + base game's zip file 108 home path + base game's directory109 base path + base game's directory 109 110 base path + base game's zip file 110 basepath + base game's directory111 cd path + base game's directory 111 112 cd path + base game's zip file 112 cd path + base game's directory 113 113 114 home path + BASEGAME's directory 114 115 home path + BASEGAME's zip file 115 home path + BASEGAME's directory116 base path + BASEGAME's directory 116 117 base path + BASEGAME's zip file 117 basepath + BASEGAME's directory118 cd path + BASEGAME's directory 118 119 cd path + BASEGAME's zip file 119 cd path + BASEGAME's directory120 120 121 121 server download, to be written to home path + current game's directory … … 2405 2405 Q_strncpyz( fs_gamedir, dir, sizeof( fs_gamedir ) ); 2406 2406 2407 //2408 // add the directory to the search path2409 //2410 search = Z_Malloc (sizeof(searchpath_t));2411 search->dir = Z_Malloc( sizeof( *search->dir ) );2412 2413 Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) );2414 Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) );2415 search->next = fs_searchpaths;2416 fs_searchpaths = search;2417 2418 2407 // find all pak files in this directory 2419 2408 pakfile = FS_BuildOSPath( path, dir, "" ); … … 2436 2425 fs_searchpaths = search; 2437 2426 } 2427 2428 // 2429 // add the directory to the search path 2430 // 2431 search = Z_Malloc (sizeof(searchpath_t)); 2432 search->dir = Z_Malloc( sizeof( *search->dir ) ); 2433 2434 Q_strncpyz( search->dir->path, path, sizeof( search->dir->path ) ); 2435 Q_strncpyz( search->dir->gamedir, dir, sizeof( search->dir->gamedir ) ); 2436 search->next = fs_searchpaths; 2437 fs_searchpaths = search; 2438 2438 2439 2439 // done -
src/qcommon/files.c
r40 r123 1055 1055 } 1056 1056 1057 if (!(pak->referenced & FS_QAGAME_REF) && strstr(filename, " qagame.qvm")) {1057 if (!(pak->referenced & FS_QAGAME_REF) && strstr(filename, "game.qvm")) { 1058 1058 pak->referenced |= FS_QAGAME_REF; 1059 1059 } … … 2096 2096 continue; 2097 2097 } 2098 // we drop "baseq3""." and ".."2098 // we drop BASEGAME "." and ".." 2099 2099 if (Q_stricmp(name, BASEGAME) && Q_stricmpn(name, ".", 1)) { 2100 2100 // now we need to find some .pk3 files to validate the mod … … 2768 2768 FS_GamePureChecksum 2769 2769 2770 Returns the checksum of the pk3 from which the server loaded the qagame.qvm2770 Returns the checksum of the pk3 from which the server loaded the game.qvm 2771 2771 ===================== 2772 2772 */ -
src/qcommon/q_shared.h
r119 r123 29 29 30 30 #define PRODUCT_NAME "tremulous" 31 #define PRODUCT_VERSION "1.1.0" 31 32 #ifndef PRODUCT_VERSION 33 #define PRODUCT_VERSION "DnC-Eggy" 34 #endif 32 35 33 36 #ifdef SVN_VERSION … … 39 42 #define CLIENT_WINDOW_TITLE "Tremulous " PRODUCT_VERSION 40 43 #define CLIENT_WINDOW_MIN_TITLE "Tremulous" 44 45 #define FULL_VERSION Q3_VERSION " " PLATFORM_STRING " " __DATE__ 41 46 42 47 #define MAX_TEAMNAME 32 … … 91 96 **********************************************************************/ 92 97 98 #ifdef Q3_VM 99 93 100 #include "../game/bg_lib.h" 94 101 95 # ifndef Q3_VM102 #else 96 103 97 104 #include <assert.h> … … 336 343 337 344 #define Q_COLOR_ESCAPE '^' 338 #define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1)) ) // ^[0-9a-zA-Z]345 #define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE ) 339 346 340 347 #define COLOR_BLACK '0' … … 1013 1020 #define MAX_STATS 16 1014 1021 #define MAX_PERSISTANT 16 1015 #define MAX_ MISC161022 #define MAX_POWERUPS 16 1016 1023 #define MAX_WEAPONS 16 1017 1024 … … 1085 1092 int stats[MAX_STATS]; 1086 1093 int persistant[MAX_PERSISTANT]; // stats that aren't cleared on death 1087 int misc[MAX_MISC]; // misc data 1088 int ammo; // ammo held 1089 int clips; // clips held 1094 int powerups[MAX_POWERUPS]; // level.time that the powerup runs out 1095 int ammo[MAX_WEAPONS]; 1090 1096 1091 1097 int generic1; … … 1151 1157 TR_SINE, // value = base + sin( time / duration ) * delta 1152 1158 TR_GRAVITY, 1153 TR_BUOYANCY 1159 TR_BUOYANCY //TA: what the hell is this doing in here anyway? 1154 1160 } trType_t; 1155 1161 … … 1205 1211 1206 1212 // for players 1207 int misc;// bit flags1213 int powerups; // bit flags 1208 1214 int weapon; // determines weapon and flash model, etc 1209 1215 int legsAnim; // mask off ANIM_TOGGLEBIT … … 1275 1281 1276 1282 // server browser sources 1277 // AS_MPLAYER is no longer used1278 #define AS_GLOBAL 01283 // TTimo: AS_MPLAYER is no longer used 1284 #define AS_GLOBAL 2 1279 1285 #define AS_MPLAYER 1 1280 #define AS_LOCAL 21286 #define AS_LOCAL 0 1281 1287 #define AS_FAVORITES 3 1282 1288 … … 1316 1322 #define MAX_SERVERSTATUSREQUESTS 16 1317 1323 1318 #define SAY_ALL 0 1319 #define SAY_TEAM 1 1320 #define SAY_TELL 2 1324 #define SAY_ALL 0 1325 #define SAY_TEAM 1 1326 #define SAY_TELL 2 1327 #define SAY_ACTION 3 1328 #define SAY_ACTION_T 4 1329 #define SAY_ADMINS 5 1321 1330 1322 1331 #endif // __Q_SHARED_H -
src/qcommon/q_shared.h
r122 r123 943 943 #define KEYCATCH_CONSOLE 0x0001 944 944 #define KEYCATCH_UI 0x0002 945 #define KEYCATCH_MESSAGE 0x0004946 945 #define KEYCATCH_CGAME 0x0008 947 946 -
src/qcommon/qcommon.h
r119 r123 222 222 */ 223 223 224 #define PROTOCOL_VERSION 70224 #define PROTOCOL_VERSION 69 225 225 226 226 // maintain a list of compatible protocols for demo playing … … 365 365 // Do not call inside a command function, or current args will be destroyed. 366 366 367 void Cdelay_Frame (void); 368 //Check if a delayed command have to be executed and decreases the remaining 369 //delay time for all of them 370 367 371 //=========================================================================== 368 372 … … 404 408 void Cmd_TokenizeString( const char *text ); 405 409 void Cmd_TokenizeStringIgnoreQuotes( const char *text_in ); 410 void Cmd_TokenizeStringParseCvar( const char *text_in ); 406 411 // Takes a null terminated string. Does not need to be /n terminated. 407 412 // breaks the string up into arg tokens. -
src/qcommon/qcommon.h
r62 r123 689 689 // vsnprintf is ISO/IEC 9899:1999 690 690 // abstracting this to make it portable 691 #ifdef WIN32691 #ifdef _WIN32 692 692 #define Q_vsnprintf _vsnprintf 693 #define Q_snprintf _snprintf 693 694 #else 694 695 #define Q_vsnprintf vsnprintf 696 #define Q_snprintf snprintf 695 697 #endif 696 698 … … 920 922 // start all the client stuff using the hunk 921 923 924 void Key_KeynameCompletion( void(*callback)(const char *s) ); 925 // for keyname autocompletion 926 922 927 void Key_WriteBindings( fileHandle_t f ); 923 928 // for writing the config files -
src/ui/ui_main.c
r119 r123 42 42 }; 43 43 44 static const char *netSources[ ] = 45 { 44 static const char *netSources[] = { 45 "LAN", 46 "Mplayer", 46 47 "Internet", 47 "Mplayer",48 "LAN",49 48 "Favorites" 50 49 }; -
src/ui/ui_main.c
r122 r123 3 3 Copyright (C) 1999-2005 Id Software, Inc. 4 4 Copyright (C) 2000-2006 Tim Angus 5 5 6 6 This file is part of Tremulous. 7 7 8 8 Tremulous is free software; you can redistribute it 9 9 and/or modify it under the terms of the GNU General Public License as 10 10 published by the Free Software Foundation; either version 2 of the License, 11 11 or (at your option) any later version. 12 12 13 13 Tremulous is distributed in the hope that it will be 14 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with Tremulous; if not, write to the Free Software … … 24 24 /* 25 25 ======================================================================= 26 26 27 27 USER INTERFACE MAIN 28 28 29 29 ======================================================================= 30 30 */ 31 31 32 // use this to get a demo build without an explicit demo build, i.e. to get the demo ui files to build33 //#define PRE_RELEASE_TADEMO34 35 32 #include "ui_local.h" 36 33 37 34 uiInfo_t uiInfo; 38 35 39 static const char *MonthAbbrev[] = { 40 "Jan","Feb","Mar", 41 "Apr","May","Jun", 42 "Jul","Aug","Sep", 43 "Oct","Nov","Dec" 36 static const char *MonthAbbrev[ ] = 37 { 38 "Jan", "Feb", "Mar", 39 "Apr", "May", "Jun", 40 "Jul", "Aug", "Sep", 41 "Oct", "Nov", "Dec" 44 42 }; 45 46 47 static const char *skillLevels[] = {48 "I Can Win",49 "Bring It On",50 "Hurt Me Plenty",51 "Hardcore",52 "Nightmare"53 };54 55 static const int numSkillLevels = sizeof(skillLevels) / sizeof(const char*);56 57 43 58 44 static const char *netSources[] = { … … 62 48 "Favorites" 63 49 }; 64 static const int numNetSources = sizeof(netSources) / sizeof(const char*); 65 66 static const serverFilter_t serverFilters[] = { 67 {"All", "" }, 68 {"Quake 3 Arena", "" }, 69 {"Team Arena", "missionpack" }, 70 {"Rocket Arena", "arena" }, 71 {"Alliance", "alliance20" }, 72 {"Weapons Factory Arena", "wfa" }, 73 {"OSP", "osp" }, 74 }; 75 76 static const char *teamArenaGameTypes[] = { 77 "FFA", 78 "TOURNAMENT", 79 "SP", 80 "TEAM DM", 81 "CTF", 82 "1FCTF", 83 "OVERLOAD", 84 "HARVESTER", 85 "TEAMTOURNAMENT" 86 }; 87 88 static int const numTeamArenaGameTypes = sizeof(teamArenaGameTypes) / sizeof(const char*); 89 90 91 static const char *teamArenaGameNames[] = { 92 "Free For All", 93 "Tournament", 94 "Single Player", 95 "Team Deathmatch", 96 "Capture the Flag", 97 "One Flag CTF", 98 "Overload", 99 "Harvester", 100 "Team Tournament", 101 }; 102 103 static int const numTeamArenaGameNames = sizeof(teamArenaGameNames) / sizeof(const char*); 104 105 106 static const int numServerFilters = sizeof(serverFilters) / sizeof(serverFilter_t); 107 108 static const char *sortKeys[] = { 109 "Server Name", 110 "Map Name", 111 "Open Player Spots", 112 "Game Type", 113 "Ping Time" 114 }; 115 static const int numSortKeys = sizeof(sortKeys) / sizeof(const char*); 116 117 static char* netnames[] = { 50 51 static const int numNetSources = sizeof( netSources ) / sizeof( const char* ); 52 53 static const char* netnames[ ] = 54 { 118 55 "???", 119 56 "UDP", … … 122 59 }; 123 60 124 static int gamecodetoui[] = {4,2,3,0,5,1,6}; 125 126 127 static void UI_StartServerRefresh(qboolean full); 128 static void UI_StopServerRefresh( void ); 129 static void UI_DoServerRefresh( void ); 130 static void UI_FeederSelection(float feederID, int index); 131 static void UI_BuildServerDisplayList(qboolean force); 132 static void UI_BuildServerStatus(qboolean force); 133 static void UI_BuildFindPlayerList(qboolean force); 134 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ); 135 static int UI_MapCountByGameType(qboolean singlePlayer); 136 static int UI_HeadCountByTeam( void ); 137 static const char *UI_SelectedMap(int index, int *actual); 138 static const char *UI_SelectedHead(int index, int *actual); 139 static int UI_GetIndexFromSelection(int actual); 140 141 int ProcessNewUI( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 ); 61 /* 62 ================ 63 cvars 64 ================ 65 */ 66 67 typedef struct 68 { 69 vmCvar_t *vmCvar; 70 char *cvarName; 71 char *defaultString; 72 int cvarFlags; 73 } 74 75 cvarTable_t; 76 77 vmCvar_t ui_browserShowFull; 78 vmCvar_t ui_browserShowEmpty; 79 80 vmCvar_t ui_dedicated; 81 vmCvar_t ui_netSource; 82 vmCvar_t ui_selectedMap; 83 vmCvar_t ui_lastServerRefresh_0; 84 vmCvar_t ui_lastServerRefresh_1; 85 vmCvar_t ui_lastServerRefresh_2; 86 vmCvar_t ui_lastServerRefresh_3; 87 vmCvar_t ui_lastServerRefresh_0_time; 88 vmCvar_t ui_lastServerRefresh_1_time; 89 vmCvar_t ui_lastServerRefresh_2_time; 90 vmCvar_t ui_lastServerRefresh_3_time; 91 vmCvar_t ui_smallFont; 92 vmCvar_t ui_bigFont; 93 vmCvar_t ui_findPlayer; 94 vmCvar_t ui_serverStatusTimeOut; 95 vmCvar_t ui_textWrapCache; 96 vmCvar_t ui_developer; 97 98 vmCvar_t ui_winner; 99 100 static cvarTable_t cvarTable[ ] = 101 { 102 { &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE }, 103 { &ui_browserShowEmpty, "ui_browserShowEmpty", "1", CVAR_ARCHIVE }, 104 105 { &ui_dedicated, "ui_dedicated", "0", CVAR_ARCHIVE }, 106 { &ui_netSource, "ui_netSource", "0", CVAR_ARCHIVE }, 107 { &ui_selectedMap, "ui_selectedMap", "0", CVAR_ARCHIVE }, 108 { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0", "", CVAR_ARCHIVE}, 109 { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1", "", CVAR_ARCHIVE}, 110 { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2", "", CVAR_ARCHIVE}, 111 { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3", "", CVAR_ARCHIVE}, 112 { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0_time", "", CVAR_ARCHIVE}, 113 { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1_time", "", CVAR_ARCHIVE}, 114 { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2_time", "", CVAR_ARCHIVE}, 115 { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3_time", "", CVAR_ARCHIVE}, 116 { &ui_smallFont, "ui_smallFont", "0.2", CVAR_ARCHIVE}, 117 { &ui_bigFont, "ui_bigFont", "0.5", CVAR_ARCHIVE}, 118 { &ui_findPlayer, "ui_findPlayer", "", CVAR_ARCHIVE}, 119 { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE}, 120 { &ui_textWrapCache, "ui_textWrapCache", "1", CVAR_ARCHIVE }, 121 { &ui_developer, "ui_developer", "0", CVAR_ARCHIVE | CVAR_CHEAT }, 122 }; 123 124 static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); 142 125 143 126 /* 144 127 ================ 145 128 vmMain 146 129 147 130 This is the only way control passes into the module. 148 131 This must be the very first function compiled into the .qvm file 149 132 ================ 150 133 */ 151 vmCvar_t ui_new; 152 vmCvar_t ui_debug; 153 vmCvar_t ui_initialized; 154 vmCvar_t ui_teamArenaFirstRun; 155 156 void _UI_Init( qboolean ); 157 void _UI_Shutdown( void ); 158 void _UI_KeyEvent( int key, qboolean down ); 159 void _UI_MouseEvent( int dx, int dy ); 160 void _UI_Refresh( int realtime ); 161 qboolean _UI_IsFullscreen( void ); 134 void UI_Init( qboolean ); 135 void UI_Shutdown( void ); 136 void UI_KeyEvent( int key, qboolean down ); 137 void UI_MouseEvent( int dx, int dy ); 138 void UI_Refresh( int realtime ); 139 qboolean UI_IsFullscreen( void ); 140 void UI_SetActiveMenu( uiMenuCommand_t menu ); 162 141 intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, 163 int arg4, int arg5, int arg6, int arg7, 164 int arg8, int arg9, int arg10, int arg11 ) { 165 switch ( command ) { 142 int arg4, int arg5, int arg6, int arg7, 143 int arg8, int arg9, int arg10, int arg11 ) 144 { 145 switch( command ) 146 { 166 147 case UI_GETAPIVERSION: 167 148 return UI_API_VERSION; 168 149 169 150 case UI_INIT: 170 _UI_Init(arg0);151 UI_Init( arg0 ); 171 152 return 0; 172 153 173 154 case UI_SHUTDOWN: 174 _UI_Shutdown();155 UI_Shutdown(); 175 156 return 0; 176 157 177 158 case UI_KEY_EVENT: 178 _UI_KeyEvent( arg0, arg1 );159 UI_KeyEvent( arg0, arg1 ); 179 160 return 0; 180 161 181 162 case UI_MOUSE_EVENT: 182 _UI_MouseEvent( arg0, arg1 );163 UI_MouseEvent( arg0, arg1 ); 183 164 return 0; 184 165 185 166 case UI_REFRESH: 186 _UI_Refresh( arg0 );167 UI_Refresh( arg0 ); 187 168 return 0; 188 169 189 170 case UI_IS_FULLSCREEN: 190 return _UI_IsFullscreen();171 return UI_IsFullscreen(); 191 172 192 173 case UI_SET_ACTIVE_MENU: 193 _UI_SetActiveMenu( arg0 );174 UI_SetActiveMenu( arg0 ); 194 175 return 0; 195 176 196 177 case UI_CONSOLE_COMMAND: 197 return UI_ConsoleCommand( arg0);178 return UI_ConsoleCommand( arg0 ); 198 179 199 180 case UI_DRAW_CONNECT_SCREEN: … … 207 188 208 189 209 void AssetCache( void ) { 190 void AssetCache( void ) 191 { 210 192 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR ); 211 193 uiInfo.uiDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR ); … … 219 201 } 220 202 221 void _UI_DrawSides(float x, float y, float w, float h, float size) { 203 void UI_DrawSides( float x, float y, float w, float h, float size ) 204 { 222 205 UI_AdjustFrom640( &x, &y, &w, &h ); 223 206 size *= uiInfo.uiDC.xscale; … … 226 209 } 227 210 228 void _UI_DrawTopBottom(float x, float y, float w, float h, float size) { 211 void UI_DrawTopBottom( float x, float y, float w, float h, float size ) 212 { 229 213 UI_AdjustFrom640( &x, &y, &w, &h ); 230 214 size *= uiInfo.uiDC.yscale; … … 232 216 trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader ); 233 217 } 218 234 219 /* 235 220 ================ 236 221 UI_DrawRect 237 222 238 223 Coordinates are 640*480 virtual values 239 224 ================= 240 225 */ 241 void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) { 226 void UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) 227 { 242 228 trap_R_SetColor( color ); 243 229 244 _UI_DrawTopBottom(x, y, width, height, size);245 _UI_DrawSides(x, y, width, height, size);230 UI_DrawTopBottom( x, y, width, height, size ); 231 UI_DrawSides( x, y, width, height, size ); 246 232 247 233 trap_R_SetColor( NULL ); 248 }249 250 251 252 253 int Text_Width(const char *text, float scale, int limit) {254 int count,len;255 float out;256 glyphInfo_t *glyph;257 float useScale;258 const char *s = text;259 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;260 if (scale <= ui_smallFont.value) {261 font = &uiInfo.uiDC.Assets.smallFont;262 } else if (scale >= ui_bigFont.value) {263 font = &uiInfo.uiDC.Assets.bigFont;264 }265 useScale = scale * font->glyphScale;266 out = 0;267 if (text) {268 len = strlen(text);269 if (limit > 0 && len > limit) {270 len = limit;271 }272 count = 0;273 while (s && *s && count < len) {274 if ( Q_IsColorString(s) ) {275 s += 2;276 continue;277 } else {278 glyph = &font->glyphs[(int)*s];279 out += glyph->xSkip;280 s++;281 count++;282 }283 }284 }285 return out * useScale;286 }287 288 int Text_Height(const char *text, float scale, int limit) {289 int len, count;290 float max;291 glyphInfo_t *glyph;292 float useScale;293 const char *s = text;294 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;295 if (scale <= ui_smallFont.value) {296 font = &uiInfo.uiDC.Assets.smallFont;297 } else if (scale >= ui_bigFont.value) {298 font = &uiInfo.uiDC.Assets.bigFont;299 }300 useScale = scale * font->glyphScale;301 max = 0;302 if (text) {303 len = strlen(text);304 if (limit > 0 && len > limit) {305 len = limit;306 }307 count = 0;308 while (s && *s && count < len) {309 if ( Q_IsColorString(s) ) {310 s += 2;311 continue;312 } else {313 glyph = &font->glyphs[(int)*s];314 if (max < glyph->height) {315 max = glyph->height;316 }317 s++;318 count++;319 }320 }321 }322 return max * useScale;323 }324 325 void Text_PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, qhandle_t hShader) {326 float w, h;327 w = width * scale;328 h = height * scale;329 UI_AdjustFrom640( &x, &y, &w, &h );330 trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader );331 }332 333 void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style) {334 int len, count;335 vec4_t newColor;336 glyphInfo_t *glyph;337 float useScale;338 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;339 if (scale <= ui_smallFont.value) {340 font = &uiInfo.uiDC.Assets.smallFont;341 } else if (scale >= ui_bigFont.value) {342 font = &uiInfo.uiDC.Assets.bigFont;343 }344 useScale = scale * font->glyphScale;345 if (text) {346 const char *s = text;347 trap_R_SetColor( color );348 memcpy(&newColor[0], &color[0], sizeof(vec4_t));349 len = strlen(text);350 if (limit > 0 && len > limit) {351 len = limit;352 }353 count = 0;354 while (s && *s && count < len) {355 glyph = &font->glyphs[(int)*s];356 //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top;357 //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height);358 if ( Q_IsColorString( s ) ) {359 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );360 newColor[3] = color[3];361 trap_R_SetColor( newColor );362 s += 2;363 continue;364 } else {365 float yadj = useScale * glyph->top;366 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {367 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;368 colorBlack[3] = newColor[3];369 trap_R_SetColor( colorBlack );370 Text_PaintChar(x + ofs, y - yadj + ofs,371 glyph->imageWidth,372 glyph->imageHeight,373 useScale,374 glyph->s,375 glyph->t,376 glyph->s2,377 glyph->t2,378 glyph->glyph);379 trap_R_SetColor( newColor );380 colorBlack[3] = 1.0;381 }382 else if( style == ITEM_TEXTSTYLE_NEON )383 {384 vec4_t glow, outer, inner, white;385 386 glow[ 0 ] = newColor[ 0 ] * 0.5;387 glow[ 1 ] = newColor[ 1 ] * 0.5;388 glow[ 2 ] = newColor[ 2 ] * 0.5;389 glow[ 3 ] = newColor[ 3 ] * 0.2;390 391 outer[ 0 ] = newColor[ 0 ];392 outer[ 1 ] = newColor[ 1 ];393 outer[ 2 ] = newColor[ 2 ];394 outer[ 3 ] = newColor[ 3 ];395 396 inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5;397 inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5;398 inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5;399 inner[ 3 ] = newColor[ 3 ];400 401 white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f;402 403 trap_R_SetColor( glow );404 Text_PaintChar( x - 1.5, y - yadj - 1.5,405 glyph->imageWidth + 3,406 glyph->imageHeight + 3,407 useScale,408 glyph->s,409 glyph->t,410 glyph->s2,411 glyph->t2,412 glyph->glyph );413 414 trap_R_SetColor( outer );415 Text_PaintChar( x - 1, y - yadj - 1,416 glyph->imageWidth + 2,417 glyph->imageHeight + 2,418 useScale,419 glyph->s,420 glyph->t,421 glyph->s2,422 glyph->t2,423 glyph->glyph );424 425 trap_R_SetColor( inner );426 Text_PaintChar( x - 0.5, y - yadj - 0.5,427 glyph->imageWidth + 1,428 glyph->imageHeight + 1,429 useScale,430 glyph->s,431 glyph->t,432 glyph->s2,433 glyph->t2,434 glyph->glyph );435 436 trap_R_SetColor( white );437 }438 439 Text_PaintChar(x, y - yadj,440 glyph->imageWidth,441 glyph->imageHeight,442 useScale,443 glyph->s,444 glyph->t,445 glyph->s2,446 glyph->t2,447 glyph->glyph);448 449 x += (glyph->xSkip * useScale) + adjust;450 s++;451 count++;452 }453 }454 trap_R_SetColor( NULL );455 }456 }457 458 void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style) {459 int len, count;460 vec4_t newColor;461 glyphInfo_t *glyph, *glyph2;462 float yadj;463 float useScale;464 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;465 if (scale <= ui_smallFont.value) {466 font = &uiInfo.uiDC.Assets.smallFont;467 } else if (scale >= ui_bigFont.value) {468 font = &uiInfo.uiDC.Assets.bigFont;469 }470 useScale = scale * font->glyphScale;471 if (text) {472 const char *s = text;473 trap_R_SetColor( color );474 memcpy(&newColor[0], &color[0], sizeof(vec4_t));475 len = strlen(text);476 if (limit > 0 && len > limit) {477 len = limit;478 }479 count = 0;480 glyph2 = &font->glyphs[ (int) cursor];481 while (s && *s && count < len) {482 glyph = &font->glyphs[(int)*s];483 if ( Q_IsColorString( s ) ) {484 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );485 newColor[3] = color[3];486 trap_R_SetColor( newColor );487 s += 2;488 continue;489 } else {490 yadj = useScale * glyph->top;491 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {492 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;493 colorBlack[3] = newColor[3];494 trap_R_SetColor( colorBlack );495 Text_PaintChar(x + ofs, y - yadj + ofs,496 glyph->imageWidth,497 glyph->imageHeight,498 useScale,499 glyph->s,500 glyph->t,501 glyph->s2,502 glyph->t2,503 glyph->glyph);504 colorBlack[3] = 1.0;505 trap_R_SetColor( newColor );506 }507 else if( style == ITEM_TEXTSTYLE_NEON )508 {509 vec4_t glow, outer, inner, white;510 511 glow[ 0 ] = newColor[ 0 ] * 0.5;512 glow[ 1 ] = newColor[ 1 ] * 0.5;513 glow[ 2 ] = newColor[ 2 ] * 0.5;514 glow[ 3 ] = newColor[ 3 ] * 0.2;515 516 outer[ 0 ] = newColor[ 0 ];517 outer[ 1 ] = newColor[ 1 ];518 outer[ 2 ] = newColor[ 2 ];519 outer[ 3 ] = newColor[ 3 ];520 521 inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5;522 inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5;523 inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5;524 inner[ 3 ] = newColor[ 3 ];525 526 white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f;527 528 trap_R_SetColor( glow );529 Text_PaintChar( x - 1.5, y - yadj - 1.5,530 glyph->imageWidth + 3,531 glyph->imageHeight + 3,532 useScale,533 glyph->s,534 glyph->t,535 glyph->s2,536 glyph->t2,537 glyph->glyph );538 539 trap_R_SetColor( outer );540 Text_PaintChar( x - 1, y - yadj - 1,541 glyph->imageWidth + 2,542 glyph->imageHeight + 2,543 useScale,544 glyph->s,545 glyph->t,546 glyph->s2,547 glyph->t2,548 glyph->glyph );549 550 trap_R_SetColor( inner );551 Text_PaintChar( x - 0.5, y - yadj - 0.5,552 glyph->imageWidth + 1,553 glyph->imageHeight + 1,554 useScale,555 glyph->s,556 glyph->t,557 glyph->s2,558 glyph->t2,559 glyph->glyph );560 561 trap_R_SetColor( white );562 }563 564 Text_PaintChar(x, y - yadj,565 glyph->imageWidth,566 glyph->imageHeight,567 useScale,568 glyph->s,569 glyph->t,570 glyph->s2,571 glyph->t2,572 glyph->glyph);573 574 // CG_DrawPic(x, y - yadj, scale * uiDC.Assets.textFont.glyphs[text[i]].imageWidth, scale * uiDC.Assets.textFont.glyphs[text[i]].imageHeight, uiDC.Assets.textFont.glyphs[text[i]].glyph);575 yadj = useScale * glyph2->top;576 if (count == cursorPos && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {577 Text_PaintChar(x, y - yadj,578 glyph2->imageWidth,579 glyph2->imageHeight,580 useScale,581 glyph2->s,582 glyph2->t,583 glyph2->s2,584 glyph2->t2,585 glyph2->glyph);586 }587 588 x += (glyph->xSkip * useScale);589 s++;590 count++;591 }592 }593 // need to paint cursor at end of text594 if (cursorPos == len && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {595 yadj = useScale * glyph2->top;596 Text_PaintChar(x, y - yadj,597 glyph2->imageWidth,598 glyph2->imageHeight,599 useScale,600 glyph2->s,601 glyph2->t,602 glyph2->s2,603 glyph2->t2,604 glyph2->glyph);605 606 }607 608 609 trap_R_SetColor( NULL );610 }611 }612 613 614 static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {615 int len, count;616 vec4_t newColor;617 glyphInfo_t *glyph;618 if (text) {619 const char *s = text;620 float max = *maxX;621 float useScale;622 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;623 if (scale <= ui_smallFont.value) {624 font = &uiInfo.uiDC.Assets.smallFont;625 } else if (scale > ui_bigFont.value) {626 font = &uiInfo.uiDC.Assets.bigFont;627 }628 useScale = scale * font->glyphScale;629 trap_R_SetColor( color );630 len = strlen(text);631 if (limit > 0 && len > limit) {632 len = limit;633 }634 count = 0;635 while (s && *s && count < len) {636 glyph = &font->glyphs[(int)*s];637 if ( Q_IsColorString( s ) ) {638 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );639 newColor[3] = color[3];640 trap_R_SetColor( newColor );641 s += 2;642 continue;643 } else {644 float yadj = useScale * glyph->top;645 if (Text_Width(s, useScale, 1) + x > max) {646 *maxX = 0;647 break;648 }649 Text_PaintChar(x, y - yadj,650 glyph->imageWidth,651 glyph->imageHeight,652 useScale,653 glyph->s,654 glyph->t,655 glyph->s2,656 glyph->t2,657 glyph->glyph);658 x += (glyph->xSkip * useScale) + adjust;659 *maxX = x;660 count++;661 s++;662 }663 }664 trap_R_SetColor( NULL );665 }666 667 }668 669 670 void UI_ShowPostGame(qboolean newHigh) {671 trap_Cvar_Set ("cg_cameraOrbit", "0");672 trap_Cvar_Set("cg_thirdPerson", "0");673 trap_Cvar_Set( "sv_killserver", "1" );674 uiInfo.soundHighScore = newHigh;675 _UI_SetActiveMenu(UIMENU_POSTGAME);676 }677 /*678 =================679 _UI_Refresh680 =================681 */682 683 void UI_DrawCenteredPic(qhandle_t image, int w, int h) {684 int x, y;685 x = (SCREEN_WIDTH - w) / 2;686 y = (SCREEN_HEIGHT - h) / 2;687 UI_DrawHandlePic(x, y, w, h, image);688 }689 690 int frameCount = 0;691 int startTime;692 693 #define UI_FPS_FRAMES 4694 void _UI_Refresh( int realtime )695 {696 static int index;697 static int previousTimes[UI_FPS_FRAMES];698 699 //if ( !( trap_Key_GetCatcher() & KEYCATCH_UI ) ) {700 // return;701 //}702 703 uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime;704 uiInfo.uiDC.realTime = realtime;705 706 previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime;707 index++;708 if ( index > UI_FPS_FRAMES ) {709 int i, total;710 // average multiple frames together to smooth changes out a bit711 total = 0;712 for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) {713 total += previousTimes[i];714 }715 if ( !total ) {716 total = 1;717 }718 uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total;719 }720 721 722 723 UI_UpdateCvars();724 725 if (Menu_Count() > 0) {726 // paint all the menus727 Menu_PaintAll();728 // refresh server browser list729 UI_DoServerRefresh();730 // refresh server status731 UI_BuildServerStatus(qfalse);732 // refresh find player list733 UI_BuildFindPlayerList(qfalse);734 }735 736 // draw cursor737 UI_SetColor( NULL );738 739 // don't draw the cursor whilst loading740 if( Menu_Count( ) > 0 && !trap_Cvar_VariableValue( "ui_loading" ) )741 UI_DrawHandlePic( uiInfo.uiDC.cursorx-16, uiInfo.uiDC.cursory-16, 32, 32, uiInfo.uiDC.Assets.cursor);742 743 #ifndef NDEBUG744 if (uiInfo.uiDC.debug)745 {746 // cursor coordinates747 //FIXME748 //UI_DrawString( 0, 0, va("(%d,%d)",uis.cursorx,uis.cursory), UI_LEFT|UI_SMALLFONT, colorRed );749 }750 #endif751 752 }753 754 /*755 =================756 _UI_Shutdown757 =================758 */759 void _UI_Shutdown( void ) {760 trap_LAN_SaveCachedServers();761 }762 763 char *defaultMenu = NULL;764 765 char *GetMenuBuffer(const char *filename) {766 int len;767 fileHandle_t f;768 static char buf[MAX_MENUFILE];769 770 len = trap_FS_FOpenFile( filename, &f, FS_READ );771 if ( !f ) {772 trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );773 return defaultMenu;774 }775 if ( len >= MAX_MENUFILE ) {776 trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );777 trap_FS_FCloseFile( f );778 return defaultMenu;779 }780 781 trap_FS_Read( buf, len, f );782 buf[len] = 0;783 trap_FS_FCloseFile( f );784 //COM_Compress(buf);785 return buf;786 787 }788 789 qboolean Asset_Parse(int handle) {790 pc_token_t token;791 const char *tempStr;792 793 if (!trap_Parse_ReadToken(handle, &token))794 return qfalse;795 if (Q_stricmp(token.string, "{") != 0) {796 return qfalse;797 }798 799 while ( 1 ) {800 801 memset(&token, 0, sizeof(pc_token_t));802 803 if (!trap_Parse_ReadToken(handle, &token))804 return qfalse;805 806 if (Q_stricmp(token.string, "}") == 0) {807 return qtrue;808 }809 810 // font811 if (Q_stricmp(token.string, "font") == 0) {812 int pointSize;813 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {814 return qfalse;815 }816 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.textFont);817 uiInfo.uiDC.Assets.fontRegistered = qtrue;818 continue;819 }820 821 if (Q_stricmp(token.string, "smallFont") == 0) {822 int pointSize;823 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {824 return qfalse;825 }826 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.smallFont);827 continue;828 }829 830 if (Q_stricmp(token.string, "bigFont") == 0) {831 int pointSize;832 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {833 return qfalse;834 }835 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.bigFont);836 continue;837 }838 839 840 // gradientbar841 if (Q_stricmp(token.string, "gradientbar") == 0) {842 if (!PC_String_Parse(handle, &tempStr)) {843 return qfalse;844 }845 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip(tempStr);846 continue;847 }848 849 // enterMenuSound850 if (Q_stricmp(token.string, "menuEnterSound") == 0) {851 if (!PC_String_Parse(handle, &tempStr)) {852 return qfalse;853 }854 uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse );855 continue;856 }857 858 // exitMenuSound859 if (Q_stricmp(token.string, "menuExitSound") == 0) {860 if (!PC_String_Parse(handle, &tempStr)) {861 return qfalse;862 }863 uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse );864 continue;865 }866 867 // itemFocusSound868 if (Q_stricmp(token.string, "itemFocusSound") == 0) {869 if (!PC_String_Parse(handle, &tempStr)) {870 return qfalse;871 }872 uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse );873 continue;874 }875 876 // menuBuzzSound877 if (Q_stricmp(token.string, "menuBuzzSound") == 0) {878 if (!PC_String_Parse(handle, &tempStr)) {879 return qfalse;880 }881 uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse );882 continue;883 }884 885 if (Q_stricmp(token.string, "cursor") == 0) {886 if (!PC_String_Parse(handle, &uiInfo.uiDC.Assets.cursorStr)) {887 return qfalse;888 }889 uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr);890 continue;891 }892 893 if (Q_stricmp(token.string, "fadeClamp") == 0) {894 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeClamp)) {895 return qfalse;896 }897 continue;898 }899 900 if (Q_stricmp(token.string, "fadeCycle") == 0) {901 if (!PC_Int_Parse(handle, &uiInfo.uiDC.Assets.fadeCycle)) {902 return qfalse;903 }904 continue;905 }906 907 if (Q_stricmp(token.string, "fadeAmount") == 0) {908 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeAmount)) {909 return qfalse;910 }911 continue;912 }913 914 if (Q_stricmp(token.string, "shadowX") == 0) {915 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowX)) {916 return qfalse;917 }918 continue;919 }920 921 if (Q_stricmp(token.string, "shadowY") == 0) {922 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowY)) {923 return qfalse;924 }925 continue;926 }927 928 if (Q_stricmp(token.string, "shadowColor") == 0) {929 if (!PC_Color_Parse(handle, &uiInfo.uiDC.Assets.shadowColor)) {930 return qfalse;931 }932 uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3];933 continue;934 }935 936 }937 return qfalse;938 }939 940 void Font_Report( void ) {941 int i;942 Com_Printf("Font Info\n");943 Com_Printf("=========\n");944 for ( i = 32; i < 96; i++) {945 Com_Printf("Glyph handle %i: %i\n", i, uiInfo.uiDC.Assets.textFont.glyphs[i].glyph);946 }947 }948 949 void UI_Report( void ) {950 String_Report();951 //Font_Report();952 953 }954 955 void UI_ParseMenu(const char *menuFile) {956 int handle;957 pc_token_t token;958 959 /*Com_Printf("Parsing menu file:%s\n", menuFile);*/960 961 handle = trap_Parse_LoadSource(menuFile);962 if (!handle) {963 return;964 }965 966 while ( 1 ) {967 memset(&token, 0, sizeof(pc_token_t));968 if (!trap_Parse_ReadToken( handle, &token )) {969 break;970 }971 972 //if ( Q_stricmp( token, "{" ) ) {973 // Com_Printf( "Missing { in menu file\n" );974 // break;975 //}976 977 //if ( menuCount == MAX_MENUS ) {978 // Com_Printf( "Too many menus!\n" );979 // break;980 //}981 982 if ( token.string[0] == '}' ) {983 break;984 }985 986 if (Q_stricmp(token.string, "assetGlobalDef") == 0) {987 if (Asset_Parse(handle)) {988 continue;989 } else {990 break;991 }992 }993 994 if (Q_stricmp(token.string, "menudef") == 0) {995 // start a new menu996 Menu_New(handle);997 }998 }999 trap_Parse_FreeSource(handle);1000 }1001 1002 qboolean Load_Menu(int handle) {1003 pc_token_t token;1004 1005 if (!trap_Parse_ReadToken(handle, &token))1006 return qfalse;1007 if (token.string[0] != '{') {1008 return qfalse;1009 }1010 1011 while ( 1 ) {1012 1013 if (!trap_Parse_ReadToken(handle, &token))1014 return qfalse;1015 1016 if ( token.string[0] == 0 ) {1017 return qfalse;1018 }1019 1020 if ( token.string[0] == '}' ) {1021 return qtrue;1022 }1023 1024 UI_ParseMenu(token.string);1025 }1026 return qfalse;1027 }1028 1029 void UI_LoadMenus(const char *menuFile, qboolean reset) {1030 pc_token_t token;1031 int handle;1032 int start;1033 1034 start = trap_Milliseconds();1035 1036 handle = trap_Parse_LoadSource( menuFile );1037 if (!handle) {1038 trap_Error( va( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!\n" ) );1039 }1040 1041 ui_new.integer = 1;1042 1043 if (reset) {1044 Menu_Reset();1045 }1046 1047 while ( 1 ) {1048 if (!trap_Parse_ReadToken(handle, &token))1049 break;1050 if( token.string[0] == 0 || token.string[0] == '}') {1051 break;1052 }1053 1054 if ( token.string[0] == '}' ) {1055 break;1056 }1057 1058 if (Q_stricmp(token.string, "loadmenu") == 0) {1059 if (Load_Menu(handle)) {1060 continue;1061 } else {1062 break;1063 }1064 }1065 }1066 1067 Com_Printf("UI menu load time = %d milli seconds\n", trap_Milliseconds() - start);1068 1069 trap_Parse_FreeSource( handle );1070 }1071 1072 void UI_Load( void ) {1073 char lastName[1024];1074 menuDef_t *menu = Menu_GetFocused();1075 if (menu && menu->window.name) {1076 strcpy(lastName, menu->window.name);1077 }1078 1079 String_Init();1080 1081 UI_LoadMenus("ui/menus.txt", qtrue);1082 Menus_CloseAll();1083 Menus_ActivateByName(lastName);1084 1085 }1086 1087 static const char *handicapValues[] = {"None","95","90","85","80","75","70","65","60","55","50","45","40","35","30","25","20","15","10","5",NULL};1088 1089 static void UI_DrawHandicap(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1090 int i, h;1091 1092 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );1093 i = 20 - h / 5;1094 1095 Text_Paint(rect->x, rect->y, scale, color, handicapValues[i], 0, 0, textStyle);1096 }1097 1098 static void UI_DrawClanName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1099 Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_teamName"), 0, 0, textStyle);1100 }1101 1102 1103 static void UI_SetCapFragLimits(qboolean uiVars) {1104 int cap = 5;1105 int frag = 10;1106 if (uiVars) {1107 trap_Cvar_Set("ui_captureLimit", va("%d", cap));1108 trap_Cvar_Set("ui_fragLimit", va("%d", frag));1109 } else {1110 trap_Cvar_Set("capturelimit", va("%d", cap));1111 trap_Cvar_Set("fraglimit", va("%d", frag));1112 }1113 }1114 // ui_gameType assumes gametype 0 is -1 ALL and will not show1115 static void UI_DrawGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1116 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[ui_gameType.integer].gameType, 0, 0, textStyle);1117 }1118 1119 static void UI_DrawNetGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1120 if (ui_netGameType.integer < 0 || ui_netGameType.integer > uiInfo.numGameTypes) {1121 trap_Cvar_Set("ui_netGameType", "0");1122 trap_Cvar_Set("ui_actualNetGameType", "0");1123 }1124 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[ui_netGameType.integer].gameType , 0, 0, textStyle);1125 }1126 1127 static void UI_DrawJoinGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1128 if (ui_joinGameType.integer < 0 || ui_joinGameType.integer > uiInfo.numJoinGameTypes) {1129 trap_Cvar_Set("ui_joinGameType", "0");1130 }1131 Text_Paint(rect->x, rect->y, scale, color, uiInfo.joinGameTypes[ui_joinGameType.integer].gameType , 0, 0, textStyle);1132 }1133 1134 1135 1136 static int UI_TeamIndexFromName(const char *name) {1137 int i;1138 1139 if (name && *name) {1140 for (i = 0; i < uiInfo.teamCount; i++) {1141 if (Q_stricmp(name, uiInfo.teamList[i].teamName) == 0) {1142 return i;1143 }1144 }1145 }1146 1147 return 0;1148 1149 }1150 1151 static void UI_DrawClanLogo(rectDef_t *rect, float scale, vec4_t color) {1152 int i;1153 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1154 if (i >= 0 && i < uiInfo.teamCount) {1155 trap_R_SetColor( color );1156 1157 if (uiInfo.teamList[i].teamIcon == -1) {1158 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1159 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1160 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1161 }1162 1163 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon);1164 trap_R_SetColor(NULL);1165 }1166 }1167 1168 static void UI_DrawClanCinematic(rectDef_t *rect, float scale, vec4_t color) {1169 int i;1170 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1171 if (i >= 0 && i < uiInfo.teamCount) {1172 1173 if (uiInfo.teamList[i].cinematic >= -2) {1174 if (uiInfo.teamList[i].cinematic == -1) {1175 uiInfo.teamList[i].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.teamList[i].imageName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );1176 }1177 if (uiInfo.teamList[i].cinematic >= 0) {1178 trap_CIN_RunCinematic(uiInfo.teamList[i].cinematic);1179 trap_CIN_SetExtents(uiInfo.teamList[i].cinematic, rect->x, rect->y, rect->w, rect->h);1180 trap_CIN_DrawCinematic(uiInfo.teamList[i].cinematic);1181 } else {1182 trap_R_SetColor( color );1183 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal);1184 trap_R_SetColor(NULL);1185 uiInfo.teamList[i].cinematic = -2;1186 }1187 } else {1188 trap_R_SetColor( color );1189 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon);1190 trap_R_SetColor(NULL);1191 }1192 }1193 1194 }1195 1196 static void UI_DrawPreviewCinematic(rectDef_t *rect, float scale, vec4_t color) {1197 if (uiInfo.previewMovie > -2) {1198 uiInfo.previewMovie = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.movieList[uiInfo.movieIndex]), 0, 0, 0, 0, (CIN_loop | CIN_silent) );1199 if (uiInfo.previewMovie >= 0) {1200 trap_CIN_RunCinematic(uiInfo.previewMovie);1201 trap_CIN_SetExtents(uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h);1202 trap_CIN_DrawCinematic(uiInfo.previewMovie);1203 } else {1204 uiInfo.previewMovie = -2;1205 }1206 }1207 1208 }1209 1210 1211 /*1212 ===============1213 UI_DrawInfoPane1214 ===============1215 */1216 static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, float text_y,1217 float scale, vec4_t color, int textStyle )1218 {1219 float maxLeft = 0, maxTop = 0;1220 float maxRight = 0, maxBottom = 0;1221 float x = rect->x - text_x, y = rect->y - text_y, w, h;1222 menuDef_t dummyParent;1223 itemDef_t textItem;1224 int value = 0;1225 char *string = "";1226 int class, credits;1227 char ui_currentClass[ MAX_STRING_CHARS ];1228 1229 trap_Cvar_VariableStringBuffer( "ui_currentClass", ui_currentClass, MAX_STRING_CHARS );1230 sscanf( ui_currentClass, "%d %d", &class, &credits );1231 1232 //offset the text1233 x = rect->x + maxLeft;1234 y = rect->y + maxTop;1235 w = rect->w - ( maxLeft + maxRight + 16 + ( 2 * text_x ) ); //16 to ensure text within frame1236 h = rect->h - ( maxTop + maxBottom );1237 1238 switch( item->type )1239 {1240 case INFOTYPE_TEXT:1241 textItem.text = item->v.text;1242 break;1243 1244 case INFOTYPE_CLASS:1245 value = BG_ClassCanEvolveFromTo( class, item->v.pclass, credits, 0 );1246 if( value < 1 )1247 {1248 textItem.text = va( "%s\n\n%s",1249 BG_FindHumanNameForClassNum( item->v.pclass ),1250 BG_FindInfoForClassNum( item->v.pclass ) );1251 }1252 else1253 {1254 textItem.text = va( "%s\n\n%s\n\nKills: %d",1255 BG_FindHumanNameForClassNum( item->v.pclass ),1256 BG_FindInfoForClassNum( item->v.pclass ),1257 value );1258 }1259 break;1260 1261 case INFOTYPE_WEAPON:1262 value = BG_FindPriceForWeapon( item->v.weapon );1263 if( value == 0 )1264 {1265 textItem.text = va( "%s\n\n%s\n\nCredits: Free",1266 BG_FindHumanNameForWeapon( item->v.weapon ),1267 BG_FindInfoForWeapon( item->v.weapon ) );1268 }1269 else1270 {1271 textItem.text = va( "%s\n\n%s\n\nCredits: %d",1272 BG_FindHumanNameForWeapon( item->v.weapon ),1273 BG_FindInfoForWeapon( item->v.weapon ),1274 value );1275 }1276 break;1277 1278 case INFOTYPE_UPGRADE:1279 value = BG_FindPriceForUpgrade( item->v.upgrade );1280 if( value == 0 )1281 {1282 textItem.text = va( "%s\n\n%s\n\nCredits: Free",1283 BG_FindHumanNameForUpgrade( item->v.upgrade ),1284 BG_FindInfoForUpgrade( item->v.upgrade ) );1285 }1286 else1287 {1288 textItem.text = va( "%s\n\n%s\n\nCredits: %d",1289 BG_FindHumanNameForUpgrade( item->v.upgrade ),1290 BG_FindInfoForUpgrade( item->v.upgrade ),1291 value );1292 }1293 break;1294 1295 case INFOTYPE_BUILDABLE:1296 value = BG_FindBuildPointsForBuildable( item->v.buildable );1297 switch( BG_FindTeamForBuildable( item->v.buildable ) )1298 {1299 case BIT_ALIENS: string = "Sentience"; break;1300 case BIT_HUMANS: string = "Power"; break;1301 default: break;1302 }1303 1304 if( value == 0 )1305 {1306 textItem.text = va( "%s\n\n%s",1307 BG_FindHumanNameForBuildable( item->v.buildable ),1308 BG_FindInfoForBuildable( item->v.buildable ) );1309 }1310 else1311 {1312 textItem.text = va( "%s\n\n%s\n\n%s: %d",1313 BG_FindHumanNameForBuildable( item->v.buildable ),1314 BG_FindInfoForBuildable( item->v.buildable ),1315 string, value );1316 }1317 break;1318 }1319 1320 textItem.parent = &dummyParent;1321 memcpy( textItem.window.foreColor, color, sizeof( vec4_t ) );1322 textItem.window.flags = 0;1323 1324 textItem.window.rect.x = x;1325 textItem.window.rect.y = y;1326 textItem.window.rect.w = w;1327 textItem.window.rect.h = h;1328 textItem.window.borderSize = 0;1329 textItem.textRect.x = 0;1330 textItem.textRect.y = 0;1331 textItem.textRect.w = 0;1332 textItem.textRect.h = 0;1333 textItem.textalignment = ITEM_ALIGN_LEFT;1334 textItem.textalignx = text_x;1335 textItem.textaligny = text_y;1336 textItem.textscale = scale;1337 textItem.textStyle = textStyle;1338 1339 textItem.enableCvar = NULL;1340 textItem.cvarTest = NULL;1341 1342 //hack to utilise existing autowrap code1343 Item_Text_AutoWrapped_Paint( &textItem );1344 }1345 1346 1347 static void UI_DrawSkill(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1348 int i;1349 i = trap_Cvar_VariableValue( "g_spSkill" );1350 if (i < 1 || i > numSkillLevels) {1351 i = 1;1352 }1353 Text_Paint(rect->x, rect->y, scale, color, skillLevels[i-1],0, 0, textStyle);1354 }1355 1356 1357 static void UI_DrawTeamName(rectDef_t *rect, float scale, vec4_t color, qboolean blue, int textStyle) {1358 int i;1359 i = UI_TeamIndexFromName(UI_Cvar_VariableString((blue) ? "ui_blueTeam" : "ui_redTeam"));1360 if (i >= 0 && i < uiInfo.teamCount) {1361 Text_Paint(rect->x, rect->y, scale, color, va("%s: %s", (blue) ? "Blue" : "Red", uiInfo.teamList[i].teamName),0, 0, textStyle);1362 }1363 }1364 1365 static void UI_DrawTeamMember(rectDef_t *rect, float scale, vec4_t color, qboolean blue, int num, int textStyle) {1366 // 0 - None1367 // 1 - Human1368 // 2..NumCharacters - Bot1369 int value = trap_Cvar_VariableValue(va(blue ? "ui_blueteam%i" : "ui_redteam%i", num));1370 const char *text;1371 if (value <= 0) {1372 text = "Closed";1373 } else if (value == 1) {1374 text = "Human";1375 } else {1376 value -= 2;1377 1378 if( value >= UI_GetNumBots( ) )1379 value = 0;1380 1381 text = UI_GetBotNameByNumber(value);1382 }1383 Text_Paint(rect->x, rect->y, scale, color, text, 0, 0, textStyle);1384 }1385 1386 static void UI_DrawMapPreview(rectDef_t *rect, float scale, vec4_t color, qboolean net) {1387 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;1388 if (map < 0 || map > uiInfo.mapCount) {1389 if (net) {1390 ui_currentNetMap.integer = 0;1391 trap_Cvar_Set("ui_currentNetMap", "0");1392 } else {1393 ui_currentMap.integer = 0;1394 trap_Cvar_Set("ui_currentMap", "0");1395 }1396 map = 0;1397 }1398 1399 if (uiInfo.mapList[map].levelShot == -1) {1400 uiInfo.mapList[map].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[map].imageName);1401 }1402 1403 if (uiInfo.mapList[map].levelShot > 0) {1404 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.mapList[map].levelShot);1405 } else {1406 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("gfx/2d/load_screen"));1407 }1408 }1409 1410 1411 static void UI_DrawMapTimeToBeat(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1412 int minutes, seconds, time;1413 if (ui_currentMap.integer < 0 || ui_currentMap.integer > uiInfo.mapCount) {1414 ui_currentMap.integer = 0;1415 trap_Cvar_Set("ui_currentMap", "0");1416 }1417 1418 time = uiInfo.mapList[ui_currentMap.integer].timeToBeat[uiInfo.gameTypes[ui_gameType.integer].gtEnum];1419 1420 minutes = time / 60;1421 seconds = time % 60;1422 1423 Text_Paint(rect->x, rect->y, scale, color, va("%02i:%02i", minutes, seconds), 0, 0, textStyle);1424 }1425 1426 1427 1428 static void UI_DrawMapCinematic(rectDef_t *rect, float scale, vec4_t color, qboolean net) {1429 1430 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;1431 if (map < 0 || map > uiInfo.mapCount) {1432 if (net) {1433 ui_currentNetMap.integer = 0;1434 trap_Cvar_Set("ui_currentNetMap", "0");1435 } else {1436 ui_currentMap.integer = 0;1437 trap_Cvar_Set("ui_currentMap", "0");1438 }1439 map = 0;1440 }1441 1442 if (uiInfo.mapList[map].cinematic >= -1) {1443 if (uiInfo.mapList[map].cinematic == -1) {1444 uiInfo.mapList[map].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[map].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );1445 }1446 if (uiInfo.mapList[map].cinematic >= 0) {1447 trap_CIN_RunCinematic(uiInfo.mapList[map].cinematic);1448 trap_CIN_SetExtents(uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h);1449 trap_CIN_DrawCinematic(uiInfo.mapList[map].cinematic);1450 } else {1451 uiInfo.mapList[map].cinematic = -2;1452 }1453 } else {1454 UI_DrawMapPreview(rect, scale, color, net);1455 }1456 }1457 1458 1459 1460 static qboolean updateModel = qtrue;1461 static qboolean q3Model = qfalse;1462 1463 static void UI_DrawPlayerModel(rectDef_t *rect) {1464 static playerInfo_t info;1465 char model[MAX_QPATH];1466 char team[256];1467 char head[256];1468 vec3_t viewangles;1469 vec3_t moveangles;1470 1471 if (trap_Cvar_VariableValue("ui_Q3Model")) {1472 strcpy(model, UI_Cvar_VariableString("model"));1473 strcpy(head, UI_Cvar_VariableString("headmodel"));1474 if (!q3Model) {1475 q3Model = qtrue;1476 updateModel = qtrue;1477 }1478 team[0] = '\0';1479 } else {1480 1481 strcpy(team, UI_Cvar_VariableString("ui_teamName"));1482 strcpy(model, UI_Cvar_VariableString("team_model"));1483 strcpy(head, UI_Cvar_VariableString("team_headmodel"));1484 if (q3Model) {1485 q3Model = qfalse;1486 updateModel = qtrue;1487 }1488 }1489 if (updateModel) {1490 memset( &info, 0, sizeof(playerInfo_t) );1491 viewangles[YAW] = 180 - 10;1492 viewangles[PITCH] = 0;1493 viewangles[ROLL] = 0;1494 VectorClear( moveangles );1495 UI_PlayerInfo_SetModel( &info, model, head, team);1496 UI_PlayerInfo_SetInfo( &info, LEGS_IDLE, TORSO_STAND, viewangles, vec3_origin, WP_MACHINEGUN, qfalse );1497 // UI_RegisterClientModelname( &info, model, head, team);1498 updateModel = qfalse;1499 }1500 1501 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info, uiInfo.uiDC.realTime / 2);1502 1503 }1504 1505 static void UI_DrawNetSource(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1506 if (ui_netSource.integer < 0 || ui_netSource.integer > numNetSources) {1507 ui_netSource.integer = 0;1508 }1509 Text_Paint(rect->x, rect->y, scale, color, va("Source: %s", netSources[ui_netSource.integer]), 0, 0, textStyle);1510 }1511 1512 static void UI_DrawNetMapPreview(rectDef_t *rect, float scale, vec4_t color) {1513 1514 if (uiInfo.serverStatus.currentServerPreview > 0) {1515 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.serverStatus.currentServerPreview);1516 } else {1517 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("gfx/2d/load_screen"));1518 }1519 }1520 1521 static void UI_DrawNetMapCinematic(rectDef_t *rect, float scale, vec4_t color) {1522 if (ui_currentNetMap.integer < 0 || ui_currentNetMap.integer > uiInfo.mapCount) {1523 ui_currentNetMap.integer = 0;1524 trap_Cvar_Set("ui_currentNetMap", "0");1525 }1526 1527 if (uiInfo.serverStatus.currentServerCinematic >= 0) {1528 trap_CIN_RunCinematic(uiInfo.serverStatus.currentServerCinematic);1529 trap_CIN_SetExtents(uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h);1530 trap_CIN_DrawCinematic(uiInfo.serverStatus.currentServerCinematic);1531 } else {1532 UI_DrawNetMapPreview(rect, scale, color);1533 }1534 }1535 1536 1537 1538 static void UI_DrawNetFilter(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1539 if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {1540 ui_serverFilterType.integer = 0;1541 }1542 Text_Paint(rect->x, rect->y, scale, color, va("Filter: %s", serverFilters[ui_serverFilterType.integer].description), 0, 0, textStyle);1543 }1544 1545 1546 static void UI_DrawTier(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1547 int i;1548 i = trap_Cvar_VariableValue( "ui_currentTier" );1549 if (i < 0 || i >= uiInfo.tierCount) {1550 i = 0;1551 }1552 Text_Paint(rect->x, rect->y, scale, color, va("Tier: %s", uiInfo.tierList[i].tierName),0, 0, textStyle);1553 }1554 1555 static void UI_DrawTierMap(rectDef_t *rect, int index) {1556 int i;1557 i = trap_Cvar_VariableValue( "ui_currentTier" );1558 if (i < 0 || i >= uiInfo.tierCount) {1559 i = 0;1560 }1561 1562 if (uiInfo.tierList[i].mapHandles[index] == -1) {1563 uiInfo.tierList[i].mapHandles[index] = trap_R_RegisterShaderNoMip(va("levelshots/%s", uiInfo.tierList[i].maps[index]));1564 }1565 1566 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.tierList[i].mapHandles[index]);1567 }1568 1569 static const char *UI_EnglishMapName(const char *map) {1570 int i;1571 for (i = 0; i < uiInfo.mapCount; i++) {1572 if (Q_stricmp(map, uiInfo.mapList[i].mapLoadName) == 0) {1573 return uiInfo.mapList[i].mapName;1574 }1575 }1576 return "";1577 }1578 1579 static void UI_DrawTierMapName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1580 int i, j;1581 i = trap_Cvar_VariableValue( "ui_currentTier" );1582 if (i < 0 || i >= uiInfo.tierCount) {1583 i = 0;1584 }1585 j = trap_Cvar_VariableValue("ui_currentMap");1586 if (j < 0 || j > MAPS_PER_TIER) {1587 j = 0;1588 }1589 1590 Text_Paint(rect->x, rect->y, scale, color, UI_EnglishMapName(uiInfo.tierList[i].maps[j]), 0, 0, textStyle);1591 }1592 1593 static void UI_DrawTierGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1594 int i, j;1595 i = trap_Cvar_VariableValue( "ui_currentTier" );1596 if (i < 0 || i >= uiInfo.tierCount) {1597 i = 0;1598 }1599 j = trap_Cvar_VariableValue("ui_currentMap");1600 if (j < 0 || j > MAPS_PER_TIER) {1601 j = 0;1602 }1603 1604 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[uiInfo.tierList[i].gameTypes[j]].gameType , 0, 0, textStyle);1605 }1606 1607 1608 static const char *UI_AIFromName(const char *name) {1609 int j;1610 for (j = 0; j < uiInfo.aliasCount; j++) {1611 if (Q_stricmp(uiInfo.aliasList[j].name, name) == 0) {1612 return uiInfo.aliasList[j].ai;1613 }1614 }1615 return "James";1616 }1617 1618 static qboolean updateOpponentModel = qtrue;1619 static void UI_DrawOpponent(rectDef_t *rect) {1620 static playerInfo_t info2;1621 char model[MAX_QPATH];1622 char headmodel[MAX_QPATH];1623 char team[256];1624 vec3_t viewangles;1625 vec3_t moveangles;1626 1627 if (updateOpponentModel) {1628 1629 strcpy(model, UI_Cvar_VariableString("ui_opponentModel"));1630 strcpy(headmodel, UI_Cvar_VariableString("ui_opponentModel"));1631 team[0] = '\0';1632 1633 memset( &info2, 0, sizeof(playerInfo_t) );1634 viewangles[YAW] = 180 - 10;1635 viewangles[PITCH] = 0;1636 viewangles[ROLL] = 0;1637 VectorClear( moveangles );1638 UI_PlayerInfo_SetModel( &info2, model, headmodel, "");1639 UI_PlayerInfo_SetInfo( &info2, LEGS_IDLE, TORSO_STAND, viewangles, vec3_origin, WP_MACHINEGUN, qfalse );1640 UI_RegisterClientModelname( &info2, model, headmodel, team);1641 updateOpponentModel = qfalse;1642 }1643 1644 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info2, uiInfo.uiDC.realTime / 2);1645 1646 }1647 1648 static void UI_NextOpponent( void ) {1649 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));1650 int j = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1651 i++;1652 if (i >= uiInfo.teamCount) {1653 i = 0;1654 }1655 if (i == j) {1656 i++;1657 if ( i >= uiInfo.teamCount) {1658 i = 0;1659 }1660 }1661 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );1662 }1663 1664 static void UI_PriorOpponent( void ) {1665 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));1666 int j = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1667 i--;1668 if (i < 0) {1669 i = uiInfo.teamCount - 1;1670 }1671 if (i == j) {1672 i--;1673 if ( i < 0) {1674 i = uiInfo.teamCount - 1;1675 }1676 }1677 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );1678 }1679 1680 static void UI_DrawPlayerLogo(rectDef_t *rect, vec3_t color) {1681 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1682 1683 if (uiInfo.teamList[i].teamIcon == -1) {1684 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1685 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1686 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1687 }1688 1689 trap_R_SetColor( color );1690 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );1691 trap_R_SetColor( NULL );1692 }1693 1694 static void UI_DrawPlayerLogoMetal(rectDef_t *rect, vec3_t color) {1695 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1696 if (uiInfo.teamList[i].teamIcon == -1) {1697 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1698 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1699 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1700 }1701 1702 trap_R_SetColor( color );1703 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );1704 trap_R_SetColor( NULL );1705 }1706 1707 static void UI_DrawPlayerLogoName(rectDef_t *rect, vec3_t color) {1708 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));1709 if (uiInfo.teamList[i].teamIcon == -1) {1710 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1711 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1712 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1713 }1714 1715 trap_R_SetColor( color );1716 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );1717 trap_R_SetColor( NULL );1718 }1719 1720 static void UI_DrawOpponentLogo(rectDef_t *rect, vec3_t color) {1721 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));1722 if (uiInfo.teamList[i].teamIcon == -1) {1723 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1724 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1725 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1726 }1727 1728 trap_R_SetColor( color );1729 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );1730 trap_R_SetColor( NULL );1731 }1732 1733 static void UI_DrawOpponentLogoMetal(rectDef_t *rect, vec3_t color) {1734 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));1735 if (uiInfo.teamList[i].teamIcon == -1) {1736 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1737 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1738 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1739 }1740 1741 trap_R_SetColor( color );1742 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );1743 trap_R_SetColor( NULL );1744 }1745 1746 static void UI_DrawOpponentLogoName(rectDef_t *rect, vec3_t color) {1747 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));1748 if (uiInfo.teamList[i].teamIcon == -1) {1749 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);1750 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));1751 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));1752 }1753 1754 trap_R_SetColor( color );1755 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );1756 trap_R_SetColor( NULL );1757 }1758 1759 static void UI_DrawAllMapsSelection(rectDef_t *rect, float scale, vec4_t color, int textStyle, qboolean net) {1760 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;1761 if (map >= 0 && map < uiInfo.mapCount) {1762 Text_Paint(rect->x, rect->y, scale, color, uiInfo.mapList[map].mapName, 0, 0, textStyle);1763 }1764 }1765 1766 static void UI_DrawPlayerListSelection( rectDef_t *rect, float scale,1767 vec4_t color, int textStyle )1768 {1769 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount )1770 {1771 Text_Paint(rect->x, rect->y, scale, color,1772 uiInfo.rawPlayerNames[ uiInfo.playerIndex ],1773 0, 0, textStyle);1774 }1775 }1776 1777 static void UI_DrawTeamListSelection( rectDef_t *rect, float scale,1778 vec4_t color, int textStyle )1779 {1780 if( uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount )1781 {1782 Text_Paint(rect->x, rect->y, scale, color,1783 uiInfo.rawTeamNames[ uiInfo.teamIndex ],1784 0, 0, textStyle);1785 }1786 }1787 1788 static void UI_DrawOpponentName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1789 Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_opponentName"), 0, 0, textStyle);1790 }1791 1792 1793 static int UI_OwnerDrawWidth(int ownerDraw, float scale) {1794 int i, h, value;1795 const char *text;1796 const char *s = NULL;1797 1798 switch( ownerDraw )1799 {1800 case UI_HANDICAP:1801 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );1802 i = 20 - h / 5;1803 s = handicapValues[i];1804 break;1805 case UI_CLANNAME:1806 s = UI_Cvar_VariableString("ui_teamName");1807 break;1808 case UI_GAMETYPE:1809 s = uiInfo.gameTypes[ui_gameType.integer].gameType;1810 break;1811 case UI_SKILL:1812 i = trap_Cvar_VariableValue( "g_spSkill" );1813 if (i < 1 || i > numSkillLevels) {1814 i = 1;1815 }1816 s = skillLevels[i-1];1817 break;1818 case UI_BLUETEAMNAME:1819 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_blueTeam"));1820 if (i >= 0 && i < uiInfo.teamCount) {1821 s = va("%s: %s", "Blue", uiInfo.teamList[i].teamName);1822 }1823 break;1824 case UI_REDTEAMNAME:1825 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_redTeam"));1826 if (i >= 0 && i < uiInfo.teamCount) {1827 s = va("%s: %s", "Red", uiInfo.teamList[i].teamName);1828 }1829 break;1830 case UI_BLUETEAM1:1831 case UI_BLUETEAM2:1832 case UI_BLUETEAM3:1833 case UI_BLUETEAM4:1834 case UI_BLUETEAM5:1835 value = trap_Cvar_VariableValue(va("ui_blueteam%i", ownerDraw-UI_BLUETEAM1 + 1));1836 if (value <= 0) {1837 text = "Closed";1838 } else if (value == 1) {1839 text = "Human";1840 } else {1841 value -= 2;1842 if (value >= uiInfo.aliasCount) {1843 value = 0;1844 }1845 text = uiInfo.aliasList[value].name;1846 }1847 s = va("%i. %s", ownerDraw-UI_BLUETEAM1 + 1, text);1848 break;1849 case UI_REDTEAM1:1850 case UI_REDTEAM2:1851 case UI_REDTEAM3:1852 case UI_REDTEAM4:1853 case UI_REDTEAM5:1854 value = trap_Cvar_VariableValue(va("ui_redteam%i", ownerDraw-UI_REDTEAM1 + 1));1855 if (value <= 0) {1856 text = "Closed";1857 } else if (value == 1) {1858 text = "Human";1859 } else {1860 value -= 2;1861 if (value >= uiInfo.aliasCount) {1862 value = 0;1863 }1864 text = uiInfo.aliasList[value].name;1865 }1866 s = va("%i. %s", ownerDraw-UI_REDTEAM1 + 1, text);1867 break;1868 case UI_NETSOURCE:1869 if (ui_netSource.integer < 0 || ui_netSource.integer > uiInfo.numJoinGameTypes) {1870 ui_netSource.integer = 0;1871 }1872 s = va("Source: %s", netSources[ui_netSource.integer]);1873 break;1874 case UI_NETFILTER:1875 if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {1876 ui_serverFilterType.integer = 0;1877 }1878 s = va("Filter: %s", serverFilters[ui_serverFilterType.integer].description );1879 break;1880 case UI_TIER:1881 break;1882 case UI_TIER_MAPNAME:1883 break;1884 case UI_TIER_GAMETYPE:1885 break;1886 case UI_ALLMAPS_SELECTION:1887 break;1888 case UI_PLAYERLIST_SELECTION:1889 break;1890 case UI_TEAMLIST_SELECTION:1891 break;1892 case UI_OPPONENT_NAME:1893 break;1894 case UI_KEYBINDSTATUS:1895 if (Display_KeyBindPending()) {1896 s = "Waiting for new key... Press ESCAPE to cancel";1897 } else {1898 s = "Press ENTER or CLICK to change, Press BACKSPACE to clear";1899 }1900 break;1901 case UI_SERVERREFRESHDATE:1902 s = UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer));1903 break;1904 default:1905 break;1906 }1907 1908 if (s) {1909 return Text_Width(s, scale, 0);1910 }1911 return 0;1912 }1913 1914 static void UI_DrawBotName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1915 int value = uiInfo.botIndex;1916 const char *text = "";1917 1918 if( value >= UI_GetNumBots( ) )1919 value = 0;1920 1921 text = UI_GetBotNameByNumber( value );1922 1923 Text_Paint(rect->x, rect->y, scale, color, text, 0, 0, textStyle);1924 }1925 1926 static void UI_DrawBotSkill(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1927 if (uiInfo.skillIndex >= 0 && uiInfo.skillIndex < numSkillLevels) {1928 Text_Paint(rect->x, rect->y, scale, color, skillLevels[uiInfo.skillIndex], 0, 0, textStyle);1929 }1930 }1931 1932 static void UI_DrawRedBlue(rectDef_t *rect, float scale, vec4_t color, int textStyle) {1933 Text_Paint(rect->x, rect->y, scale, color, (uiInfo.redBlue == 0) ? "Red" : "Blue", 0, 0, textStyle);1934 }1935 1936 /*1937 ===============1938 UI_BuildPlayerList1939 ===============1940 */1941 static void UI_BuildPlayerList( void ) {1942 uiClientState_t cs;1943 int n, count, team, team2, playerTeamNumber;1944 char info[MAX_INFO_STRING];1945 1946 trap_GetClientState( &cs );1947 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );1948 uiInfo.playerNumber = cs.clientNum;1949 uiInfo.teamLeader = atoi(Info_ValueForKey(info, "tl"));1950 team = atoi(Info_ValueForKey(info, "t"));1951 trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );1952 count = atoi( Info_ValueForKey( info, "sv_maxclients" ) );1953 uiInfo.playerCount = 0;1954 uiInfo.myTeamCount = 0;1955 uiInfo.myPlayerIndex = 0;1956 playerTeamNumber = 0;1957 for( n = 0; n < count; n++ ) {1958 trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );1959 1960 if (info[0]) {1961 BG_ClientListParse( &uiInfo.ignoreList[ uiInfo.playerCount ],1962 Info_ValueForKey( info, "ig" ) );1963 Q_strncpyz( uiInfo.rawPlayerNames[uiInfo.playerCount],1964 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );1965 Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount],1966 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );1967 Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] );1968 uiInfo.clientNums[uiInfo.playerCount] = n;1969 if( n == uiInfo.playerNumber )1970 uiInfo.myPlayerIndex = uiInfo.playerCount;1971 uiInfo.playerCount++;1972 team2 = atoi(Info_ValueForKey(info, "t"));1973 if (team2 == team) {1974 Q_strncpyz( uiInfo.rawTeamNames[uiInfo.myTeamCount],1975 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );1976 Q_strncpyz( uiInfo.teamNames[uiInfo.myTeamCount],1977 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );1978 Q_CleanStr( uiInfo.teamNames[uiInfo.myTeamCount] );1979 uiInfo.teamClientNums[uiInfo.myTeamCount] = n;1980 if (uiInfo.playerNumber == n) {1981 playerTeamNumber = uiInfo.myTeamCount;1982 }1983 uiInfo.myTeamCount++;1984 }1985 }1986 }1987 1988 if (!uiInfo.teamLeader) {1989 trap_Cvar_Set("cg_selectedPlayer", va("%d", playerTeamNumber));1990 }1991 1992 n = trap_Cvar_VariableValue("cg_selectedPlayer");1993 if (n < 0 || n > uiInfo.myTeamCount) {1994 n = 0;1995 }1996 if (n < uiInfo.myTeamCount) {1997 trap_Cvar_Set("cg_selectedPlayerName", uiInfo.teamNames[n]);1998 }1999 }2000 2001 2002 static void UI_DrawSelectedPlayer(rectDef_t *rect, float scale, vec4_t color, int textStyle) {2003 char name[ MAX_NAME_LENGTH ];2004 char *s;2005 2006 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) {2007 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;2008 UI_BuildPlayerList();2009 }2010 if( uiInfo.teamLeader )2011 s = UI_Cvar_VariableString("cg_selectedPlayerName");2012 else2013 s = UI_Cvar_VariableString("name");2014 Q_strncpyz( name, s, sizeof( name ) );2015 Text_Paint(rect->x, rect->y, scale, color, name, 0, 0, textStyle);2016 }2017 2018 static void UI_DrawServerRefreshDate(rectDef_t *rect, float scale, vec4_t color, int textStyle) {2019 if (uiInfo.serverStatus.refreshActive) {2020 vec4_t lowLight, newColor;2021 int numServers = trap_LAN_GetServerCount( ui_netSource.integer );2022 2023 lowLight[0] = 0.8 * color[0];2024 lowLight[1] = 0.8 * color[1];2025 lowLight[2] = 0.8 * color[2];2026 lowLight[3] = 0.8 * color[3];2027 LerpColor(color,lowLight,newColor,0.5+0.5*sin(uiInfo.uiDC.realTime / PULSE_DIVISOR));2028 Text_Paint(rect->x, rect->y, scale, newColor,2029 numServers < 0 ? "Waiting for response..." :2030 va("Getting info for %d servers (ESC to cancel)", numServers), 0, 0, textStyle);2031 } else {2032 char buff[64];2033 Q_strncpyz(buff, UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)), 64);2034 Text_Paint(rect->x, rect->y, scale, color, va("Refresh Time: %s", buff), 0, 0, textStyle);2035 }2036 }2037 2038 static void UI_DrawServerMOTD(rectDef_t *rect, float scale, vec4_t color) {2039 if (uiInfo.serverStatus.motdLen) {2040 float maxX;2041 2042 if (uiInfo.serverStatus.motdWidth == -1) {2043 uiInfo.serverStatus.motdWidth = 0;2044 uiInfo.serverStatus.motdPaintX = rect->x + 1;2045 uiInfo.serverStatus.motdPaintX2 = -1;2046 }2047 2048 if (uiInfo.serverStatus.motdOffset > uiInfo.serverStatus.motdLen) {2049 uiInfo.serverStatus.motdOffset = 0;2050 uiInfo.serverStatus.motdPaintX = rect->x + 1;2051 uiInfo.serverStatus.motdPaintX2 = -1;2052 }2053 2054 if (uiInfo.uiDC.realTime > uiInfo.serverStatus.motdTime) {2055 uiInfo.serverStatus.motdTime = uiInfo.uiDC.realTime + 10;2056 if (uiInfo.serverStatus.motdPaintX <= rect->x + 2) {2057 if (uiInfo.serverStatus.motdOffset < uiInfo.serverStatus.motdLen) {2058 uiInfo.serverStatus.motdPaintX += Text_Width(&uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], scale, 1) - 1;2059 uiInfo.serverStatus.motdOffset++;2060 } else {2061 uiInfo.serverStatus.motdOffset = 0;2062 if (uiInfo.serverStatus.motdPaintX2 >= 0) {2063 uiInfo.serverStatus.motdPaintX = uiInfo.serverStatus.motdPaintX2;2064 } else {2065 uiInfo.serverStatus.motdPaintX = rect->x + rect->w - 2;2066 }2067 uiInfo.serverStatus.motdPaintX2 = -1;2068 }2069 } else {2070 //serverStatus.motdPaintX--;2071 uiInfo.serverStatus.motdPaintX -= 2;2072 if (uiInfo.serverStatus.motdPaintX2 >= 0) {2073 //serverStatus.motdPaintX2--;2074 uiInfo.serverStatus.motdPaintX2 -= 2;2075 }2076 }2077 }2078 2079 maxX = rect->x + rect->w - 2;2080 Text_Paint_Limit(&maxX, uiInfo.serverStatus.motdPaintX, rect->y + rect->h - 3, scale, color, &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], 0, 0);2081 if (uiInfo.serverStatus.motdPaintX2 >= 0) {2082 float maxX2 = rect->x + rect->w - 2;2083 Text_Paint_Limit(&maxX2, uiInfo.serverStatus.motdPaintX2, rect->y + rect->h - 3, scale, color, uiInfo.serverStatus.motd, 0, uiInfo.serverStatus.motdOffset);2084 }2085 if (uiInfo.serverStatus.motdOffset && maxX > 0) {2086 // if we have an offset ( we are skipping the first part of the string ) and we fit the string2087 if (uiInfo.serverStatus.motdPaintX2 == -1) {2088 uiInfo.serverStatus.motdPaintX2 = rect->x + rect->w - 2;2089 }2090 } else {2091 uiInfo.serverStatus.motdPaintX2 = -1;2092 }2093 2094 }2095 }2096 2097 static void UI_DrawKeyBindStatus(rectDef_t *rect, float scale, vec4_t color, int textStyle) {2098 if (Display_KeyBindPending()) {2099 Text_Paint(rect->x, rect->y, scale, color, "Waiting for new key... Press ESCAPE to cancel", 0, 0, textStyle);2100 } else {2101 Text_Paint(rect->x, rect->y, scale, color, "Press ENTER or CLICK to change, Press BACKSPACE to clear", 0, 0, textStyle);2102 }2103 }2104 2105 static void UI_DrawGLInfo(rectDef_t *rect, float scale, vec4_t color, int textStyle) {2106 char * eptr;2107 char buff[1024];2108 const char *lines[64];2109 int y, numLines, i;2110 2111 Text_Paint(rect->x + 2, rect->y, scale, color, va("VENDOR: %s", uiInfo.uiDC.glconfig.vendor_string), 0, 30, textStyle);2112 Text_Paint(rect->x + 2, rect->y + 15, scale, color, va("VERSION: %s: %s", uiInfo.uiDC.glconfig.version_string,uiInfo.uiDC.glconfig.renderer_string), 0, 30, textStyle);2113 Text_Paint(rect->x + 2, rect->y + 30, scale, color, va ("PIXELFORMAT: color(%d-bits) Z(%d-bits) stencil(%d-bits)", uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits, uiInfo.uiDC.glconfig.stencilBits), 0, 30, textStyle);2114 2115 // build null terminated extension strings2116 // in TA this was not directly crashing, but displaying a nasty broken shader right in the middle2117 // brought down the string size to 1024, there's not much that can be shown on the screen anyway2118 Q_strncpyz(buff, uiInfo.uiDC.glconfig.extensions_string, 1024);2119 eptr = buff;2120 y = rect->y + 45;2121 numLines = 0;2122 while ( y < rect->y + rect->h && *eptr )2123 {2124 while ( *eptr && *eptr == ' ' )2125 *eptr++ = '\0';2126 2127 // track start of valid string2128 if (*eptr && *eptr != ' ') {2129 lines[numLines++] = eptr;2130 }2131 2132 while ( *eptr && *eptr != ' ' )2133 eptr++;2134 }2135 2136 i = 0;2137 while (i < numLines) {2138 Text_Paint(rect->x + 2, y, scale, color, lines[i++], 0, 20, textStyle);2139 if (i < numLines) {2140 Text_Paint(rect->x + rect->w / 2, y, scale, color, lines[i++], 0, 20, textStyle);2141 }2142 y += 10;2143 if (y > rect->y + rect->h - 11) {2144 break;2145 }2146 }2147 2148 2149 }2150 2151 // FIXME: table drive2152 //2153 static void UI_OwnerDraw( float x, float y, float w, float h,2154 float text_x, float text_y, int ownerDraw,2155 int ownerDrawFlags, int align, float special,2156 float scale, vec4_t color, qhandle_t shader, int textStyle )2157 {2158 rectDef_t rect;2159 2160 rect.x = x + text_x;2161 rect.y = y + text_y;2162 rect.w = w;2163 rect.h = h;2164 2165 switch( ownerDraw )2166 {2167 case UI_TEAMINFOPANE:2168 UI_DrawInfoPane( &uiInfo.tremTeamList[ uiInfo.tremTeamIndex ],2169 &rect, text_x, text_y, scale, color, textStyle );2170 break;2171 2172 case UI_ACLASSINFOPANE:2173 UI_DrawInfoPane( &uiInfo.alienClassList[ uiInfo.alienClassIndex ],2174 &rect, text_x, text_y, scale, color, textStyle );2175 break;2176 2177 case UI_AUPGRADEINFOPANE:2178 UI_DrawInfoPane( &uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ],2179 &rect, text_x, text_y, scale, color, textStyle );2180 break;2181 2182 case UI_HITEMINFOPANE:2183 UI_DrawInfoPane( &uiInfo.humanItemList[ uiInfo.humanItemIndex ],2184 &rect, text_x, text_y, scale, color, textStyle );2185 break;2186 2187 case UI_HBUYINFOPANE:2188 UI_DrawInfoPane( &uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ],2189 &rect, text_x, text_y, scale, color, textStyle );2190 break;2191 2192 case UI_HSELLINFOPANE:2193 UI_DrawInfoPane( &uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ],2194 &rect, text_x, text_y, scale, color, textStyle );2195 break;2196 2197 case UI_ABUILDINFOPANE:2198 UI_DrawInfoPane( &uiInfo.alienBuildList[ uiInfo.alienBuildIndex ],2199 &rect, text_x, text_y, scale, color, textStyle );2200 break;2201 2202 case UI_HBUILDINFOPANE:2203 UI_DrawInfoPane( &uiInfo.humanBuildList[ uiInfo.humanBuildIndex ],2204 &rect, text_x, text_y, scale, color, textStyle );2205 break;2206 2207 case UI_HANDICAP:2208 UI_DrawHandicap(&rect, scale, color, textStyle);2209 break;2210 case UI_PLAYERMODEL:2211 UI_DrawPlayerModel(&rect);2212 break;2213 case UI_CLANNAME:2214 UI_DrawClanName(&rect, scale, color, textStyle);2215 break;2216 case UI_CLANLOGO:2217 UI_DrawClanLogo(&rect, scale, color);2218 break;2219 case UI_CLANCINEMATIC:2220 UI_DrawClanCinematic(&rect, scale, color);2221 break;2222 case UI_PREVIEWCINEMATIC:2223 UI_DrawPreviewCinematic(&rect, scale, color);2224 break;2225 case UI_GAMETYPE:2226 UI_DrawGameType(&rect, scale, color, textStyle);2227 break;2228 case UI_NETGAMETYPE:2229 UI_DrawNetGameType(&rect, scale, color, textStyle);2230 break;2231 case UI_JOINGAMETYPE:2232 UI_DrawJoinGameType(&rect, scale, color, textStyle);2233 break;2234 case UI_MAPPREVIEW:2235 UI_DrawMapPreview(&rect, scale, color, qtrue);2236 break;2237 case UI_MAP_TIMETOBEAT:2238 UI_DrawMapTimeToBeat(&rect, scale, color, textStyle);2239 break;2240 case UI_MAPCINEMATIC:2241 UI_DrawMapCinematic(&rect, scale, color, qfalse);2242 break;2243 case UI_STARTMAPCINEMATIC:2244 UI_DrawMapCinematic(&rect, scale, color, qtrue);2245 break;2246 case UI_SKILL:2247 UI_DrawSkill(&rect, scale, color, textStyle);2248 break;2249 case UI_BLUETEAMNAME:2250 UI_DrawTeamName(&rect, scale, color, qtrue, textStyle);2251 break;2252 case UI_REDTEAMNAME:2253 UI_DrawTeamName(&rect, scale, color, qfalse, textStyle);2254 break;2255 case UI_BLUETEAM1:2256 case UI_BLUETEAM2:2257 case UI_BLUETEAM3:2258 case UI_BLUETEAM4:2259 case UI_BLUETEAM5:2260 UI_DrawTeamMember(&rect, scale, color, qtrue, ownerDraw - UI_BLUETEAM1 + 1, textStyle);2261 break;2262 case UI_REDTEAM1:2263 case UI_REDTEAM2:2264 case UI_REDTEAM3:2265 case UI_REDTEAM4:2266 case UI_REDTEAM5:2267 UI_DrawTeamMember(&rect, scale, color, qfalse, ownerDraw - UI_REDTEAM1 + 1, textStyle);2268 break;2269 case UI_NETSOURCE:2270 UI_DrawNetSource(&rect, scale, color, textStyle);2271 break;2272 case UI_NETMAPPREVIEW:2273 UI_DrawNetMapPreview(&rect, scale, color);2274 break;2275 case UI_NETMAPCINEMATIC:2276 UI_DrawNetMapCinematic(&rect, scale, color);2277 break;2278 case UI_NETFILTER:2279 UI_DrawNetFilter(&rect, scale, color, textStyle);2280 break;2281 case UI_TIER:2282 UI_DrawTier(&rect, scale, color, textStyle);2283 break;2284 case UI_OPPONENTMODEL:2285 UI_DrawOpponent(&rect);2286 break;2287 case UI_TIERMAP1:2288 UI_DrawTierMap(&rect, 0);2289 break;2290 case UI_TIERMAP2:2291 UI_DrawTierMap(&rect, 1);2292 break;2293 case UI_TIERMAP3:2294 UI_DrawTierMap(&rect, 2);2295 break;2296 case UI_PLAYERLOGO:2297 UI_DrawPlayerLogo(&rect, color);2298 break;2299 case UI_PLAYERLOGO_METAL:2300 UI_DrawPlayerLogoMetal(&rect, color);2301 break;2302 case UI_PLAYERLOGO_NAME:2303 UI_DrawPlayerLogoName(&rect, color);2304 break;2305 case UI_OPPONENTLOGO:2306 UI_DrawOpponentLogo(&rect, color);2307 break;2308 case UI_OPPONENTLOGO_METAL:2309 UI_DrawOpponentLogoMetal(&rect, color);2310 break;2311 case UI_OPPONENTLOGO_NAME:2312 UI_DrawOpponentLogoName(&rect, color);2313 break;2314 case UI_TIER_MAPNAME:2315 UI_DrawTierMapName(&rect, scale, color, textStyle);2316 break;2317 case UI_TIER_GAMETYPE:2318 UI_DrawTierGameType(&rect, scale, color, textStyle);2319 break;2320 case UI_ALLMAPS_SELECTION:2321 UI_DrawAllMapsSelection(&rect, scale, color, textStyle, qtrue);2322 break;2323 case UI_MAPS_SELECTION:2324 UI_DrawAllMapsSelection(&rect, scale, color, textStyle, qfalse);2325 break;2326 case UI_PLAYERLIST_SELECTION:2327 UI_DrawPlayerListSelection(&rect, scale, color, textStyle);2328 break;2329 case UI_TEAMLIST_SELECTION:2330 UI_DrawTeamListSelection(&rect, scale, color, textStyle);2331 break;2332 case UI_OPPONENT_NAME:2333 UI_DrawOpponentName(&rect, scale, color, textStyle);2334 break;2335 case UI_BOTNAME:2336 UI_DrawBotName(&rect, scale, color, textStyle);2337 break;2338 case UI_BOTSKILL:2339 UI_DrawBotSkill(&rect, scale, color, textStyle);2340 break;2341 case UI_REDBLUE:2342 UI_DrawRedBlue(&rect, scale, color, textStyle);2343 break;2344 case UI_SELECTEDPLAYER:2345 UI_DrawSelectedPlayer(&rect, scale, color, textStyle);2346 break;2347 case UI_SERVERREFRESHDATE:2348 UI_DrawServerRefreshDate(&rect, scale, color, textStyle);2349 break;2350 case UI_SERVERMOTD:2351 UI_DrawServerMOTD(&rect, scale, color);2352 break;2353 case UI_GLINFO:2354 UI_DrawGLInfo(&rect,scale, color, textStyle);2355 break;2356 case UI_KEYBINDSTATUS:2357 UI_DrawKeyBindStatus(&rect,scale, color, textStyle);2358 break;2359 default:2360 break;2361 }2362 2363 }2364 2365 static qboolean UI_OwnerDrawVisible(int flags) {2366 qboolean vis = qtrue;2367 uiClientState_t cs;2368 pTeam_t team;2369 char info[ MAX_INFO_STRING ];2370 2371 trap_GetClientState( &cs );2372 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );2373 team = atoi( Info_ValueForKey( info, "t" ) );2374 2375 2376 while (flags) {2377 2378 if( flags & UI_SHOW_NOTSPECTATING )2379 {2380 if( team == PTE_NONE )2381 vis = qfalse;2382 2383 flags &= ~UI_SHOW_NOTSPECTATING;2384 }2385 2386 if( flags & UI_SHOW_VOTEACTIVE )2387 {2388 if( !trap_Cvar_VariableValue( "ui_voteActive" ) )2389 vis = qfalse;2390 2391 flags &= ~UI_SHOW_VOTEACTIVE;2392 }2393 2394 if( flags & UI_SHOW_CANVOTE )2395 {2396 if( trap_Cvar_VariableValue( "ui_voteActive" ) )2397 vis = qfalse;2398 2399 flags &= ~UI_SHOW_CANVOTE;2400 }2401 2402 if( flags & UI_SHOW_TEAMVOTEACTIVE )2403 {2404 if( team == PTE_ALIENS )2405 {2406 if( !trap_Cvar_VariableValue( "ui_alienTeamVoteActive" ) )2407 vis = qfalse;2408 }2409 else if( team == PTE_HUMANS )2410 {2411 if( !trap_Cvar_VariableValue( "ui_humanTeamVoteActive" ) )2412 vis = qfalse;2413 }2414 2415 flags &= ~UI_SHOW_TEAMVOTEACTIVE;2416 }2417 2418 if( flags & UI_SHOW_CANTEAMVOTE )2419 {2420 if( team == PTE_ALIENS )2421 {2422 if( trap_Cvar_VariableValue( "ui_alienTeamVoteActive" ) )2423 vis = qfalse;2424 }2425 else if( team == PTE_HUMANS )2426 {2427 if( trap_Cvar_VariableValue( "ui_humanTeamVoteActive" ) )2428 vis = qfalse;2429 }2430 2431 flags &= ~UI_SHOW_CANTEAMVOTE;2432 }2433 2434 if (flags & UI_SHOW_LEADER) {2435 // these need to show when this client can give orders to a player or a group2436 if (!uiInfo.teamLeader) {2437 vis = qfalse;2438 } else {2439 // if showing yourself2440 if (ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber) {2441 vis = qfalse;2442 }2443 }2444 flags &= ~UI_SHOW_LEADER;2445 }2446 if (flags & UI_SHOW_NOTLEADER) {2447 // these need to show when this client is assigning their own status or they are NOT the leader2448 if (uiInfo.teamLeader) {2449 // if not showing yourself2450 if (!(ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber)) {2451 vis = qfalse;2452 }2453 // these need to show when this client can give orders to a player or a group2454 }2455 flags &= ~UI_SHOW_NOTLEADER;2456 }2457 if (flags & UI_SHOW_FAVORITESERVERS) {2458 // this assumes you only put this type of display flag on something showing in the proper context2459 if (ui_netSource.integer != AS_FAVORITES) {2460 vis = qfalse;2461 }2462 flags &= ~UI_SHOW_FAVORITESERVERS;2463 }2464 if (flags & UI_SHOW_NOTFAVORITESERVERS) {2465 // this assumes you only put this type of display flag on something showing in the proper context2466 if (ui_netSource.integer == AS_FAVORITES) {2467 vis = qfalse;2468 }2469 flags &= ~UI_SHOW_NOTFAVORITESERVERS;2470 }2471 if (flags & UI_SHOW_NEWHIGHSCORE) {2472 if (uiInfo.newHighScoreTime < uiInfo.uiDC.realTime) {2473 vis = qfalse;2474 } else {2475 if (uiInfo.soundHighScore) {2476 if (trap_Cvar_VariableValue("sv_killserver") == 0) {2477 // wait on server to go down before playing sound2478 trap_S_StartLocalSound(uiInfo.newHighScoreSound, CHAN_ANNOUNCER);2479 uiInfo.soundHighScore = qfalse;2480 }2481 }2482 }2483 flags &= ~UI_SHOW_NEWHIGHSCORE;2484 }2485 if (flags & UI_SHOW_NEWBESTTIME) {2486 if (uiInfo.newBestTime < uiInfo.uiDC.realTime) {2487 vis = qfalse;2488 }2489 flags &= ~UI_SHOW_NEWBESTTIME;2490 }2491 if (flags & UI_SHOW_DEMOAVAILABLE) {2492 if (!uiInfo.demoAvailable) {2493 vis = qfalse;2494 }2495 flags &= ~UI_SHOW_DEMOAVAILABLE;2496 } else {2497 flags = 0;2498 }2499 }2500 return vis;2501 }2502 2503 static qboolean UI_Handicap_HandleKey(int flags, float *special, int key) {2504 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2505 int h;2506 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );2507 if (key == K_MOUSE2) {2508 h -= 5;2509 } else {2510 h += 5;2511 }2512 if (h > 100) {2513 h = 5;2514 } else if (h < 0) {2515 h = 100;2516 }2517 trap_Cvar_Set( "handicap", va( "%i", h) );2518 return qtrue;2519 }2520 return qfalse;2521 }2522 2523 static qboolean UI_ClanName_HandleKey(int flags, float *special, int key) {2524 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2525 int i;2526 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));2527 if (uiInfo.teamList[i].cinematic >= 0) {2528 trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic);2529 uiInfo.teamList[i].cinematic = -1;2530 }2531 if (key == K_MOUSE2) {2532 i--;2533 } else {2534 i++;2535 }2536 if (i >= uiInfo.teamCount) {2537 i = 0;2538 } else if (i < 0) {2539 i = uiInfo.teamCount - 1;2540 }2541 trap_Cvar_Set( "ui_teamName", uiInfo.teamList[i].teamName);2542 UI_HeadCountByTeam();2543 UI_FeederSelection(FEEDER_HEADS, 0);2544 updateModel = qtrue;2545 return qtrue;2546 }2547 return qfalse;2548 }2549 2550 static qboolean UI_GameType_HandleKey(int flags, float *special, int key, qboolean resetMap) {2551 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2552 int oldCount = UI_MapCountByGameType(qtrue);2553 2554 // hard coded mess here2555 if (key == K_MOUSE2) {2556 ui_gameType.integer--;2557 if (ui_gameType.integer == 2) {2558 ui_gameType.integer = 1;2559 } else if (ui_gameType.integer < 2) {2560 ui_gameType.integer = uiInfo.numGameTypes - 1;2561 }2562 } else {2563 ui_gameType.integer++;2564 if (ui_gameType.integer >= uiInfo.numGameTypes) {2565 ui_gameType.integer = 1;2566 } else if (ui_gameType.integer == 2) {2567 ui_gameType.integer = 3;2568 }2569 }2570 2571 trap_Cvar_Set("ui_Q3Model", "0");2572 2573 trap_Cvar_Set("ui_gameType", va("%d", ui_gameType.integer));2574 UI_SetCapFragLimits(qtrue);2575 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);2576 if (resetMap && oldCount != UI_MapCountByGameType(qtrue)) {2577 trap_Cvar_Set( "ui_currentMap", "0");2578 Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, NULL);2579 }2580 return qtrue;2581 }2582 return qfalse;2583 }2584 2585 static qboolean UI_NetGameType_HandleKey(int flags, float *special, int key) {2586 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2587 2588 if (key == K_MOUSE2) {2589 ui_netGameType.integer--;2590 } else {2591 ui_netGameType.integer++;2592 }2593 2594 if (ui_netGameType.integer < 0) {2595 ui_netGameType.integer = uiInfo.numGameTypes - 1;2596 } else if (ui_netGameType.integer >= uiInfo.numGameTypes) {2597 ui_netGameType.integer = 0;2598 }2599 2600 trap_Cvar_Set( "ui_netGameType", va("%d", ui_netGameType.integer));2601 trap_Cvar_Set( "ui_actualnetGameType", va("%d", uiInfo.gameTypes[ui_netGameType.integer].gtEnum));2602 trap_Cvar_Set( "ui_currentNetMap", "0");2603 UI_MapCountByGameType(qfalse);2604 Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, NULL);2605 return qtrue;2606 }2607 return qfalse;2608 }2609 2610 static qboolean UI_JoinGameType_HandleKey(int flags, float *special, int key) {2611 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2612 2613 if (key == K_MOUSE2) {2614 ui_joinGameType.integer--;2615 } else {2616 ui_joinGameType.integer++;2617 }2618 2619 if (ui_joinGameType.integer < 0) {2620 ui_joinGameType.integer = uiInfo.numJoinGameTypes - 1;2621 } else if (ui_joinGameType.integer >= uiInfo.numJoinGameTypes) {2622 ui_joinGameType.integer = 0;2623 }2624 2625 trap_Cvar_Set( "ui_joinGameType", va("%d", ui_joinGameType.integer));2626 UI_BuildServerDisplayList(qtrue);2627 return qtrue;2628 }2629 return qfalse;2630 }2631 2632 2633 2634 static qboolean UI_Skill_HandleKey(int flags, float *special, int key) {2635 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2636 int i = trap_Cvar_VariableValue( "g_spSkill" );2637 2638 if (key == K_MOUSE2) {2639 i--;2640 } else {2641 i++;2642 }2643 2644 if (i < 1) {2645 i = numSkillLevels;2646 } else if (i > numSkillLevels) {2647 i = 1;2648 }2649 2650 trap_Cvar_Set("g_spSkill", va("%i", i));2651 return qtrue;2652 }2653 return qfalse;2654 }2655 2656 static qboolean UI_TeamName_HandleKey(int flags, float *special, int key, qboolean blue) {2657 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2658 int i;2659 i = UI_TeamIndexFromName(UI_Cvar_VariableString((blue) ? "ui_blueTeam" : "ui_redTeam"));2660 2661 if (key == K_MOUSE2) {2662 i--;2663 } else {2664 i++;2665 }2666 2667 if (i >= uiInfo.teamCount) {2668 i = 0;2669 } else if (i < 0) {2670 i = uiInfo.teamCount - 1;2671 }2672 2673 trap_Cvar_Set( (blue) ? "ui_blueTeam" : "ui_redTeam", uiInfo.teamList[i].teamName);2674 2675 return qtrue;2676 }2677 return qfalse;2678 }2679 2680 static qboolean UI_TeamMember_HandleKey(int flags, float *special, int key, qboolean blue, int num) {2681 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2682 // 0 - None2683 // 1 - Human2684 // 2..NumCharacters - Bot2685 char *cvar = va(blue ? "ui_blueteam%i" : "ui_redteam%i", num);2686 int value = trap_Cvar_VariableValue(cvar);2687 2688 if (key == K_MOUSE2) {2689 value--;2690 } else {2691 value++;2692 }2693 2694 if( value >= UI_GetNumBots( ) + 2 )2695 value = 0;2696 else if( value < 0 )2697 value = UI_GetNumBots( ) + 2 - 1;2698 2699 trap_Cvar_Set(cvar, va("%i", value));2700 return qtrue;2701 }2702 return qfalse;2703 }2704 2705 static qboolean UI_NetSource_HandleKey(int flags, float *special, int key) {2706 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2707 2708 if (key == K_MOUSE2) {2709 ui_netSource.integer--;2710 if (ui_netSource.integer == AS_MPLAYER)2711 ui_netSource.integer--;2712 } else {2713 ui_netSource.integer++;2714 if (ui_netSource.integer == AS_MPLAYER)2715 ui_netSource.integer++;2716 }2717 2718 if (ui_netSource.integer >= numNetSources) {2719 ui_netSource.integer = 0;2720 } else if (ui_netSource.integer < 0) {2721 ui_netSource.integer = numNetSources - 1;2722 }2723 2724 UI_BuildServerDisplayList(qtrue);2725 if (ui_netSource.integer != AS_GLOBAL) {2726 UI_StartServerRefresh(qtrue);2727 }2728 trap_Cvar_Set( "ui_netSource", va("%d", ui_netSource.integer));2729 return qtrue;2730 }2731 return qfalse;2732 }2733 2734 static qboolean UI_NetFilter_HandleKey(int flags, float *special, int key) {2735 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2736 2737 if (key == K_MOUSE2) {2738 ui_serverFilterType.integer--;2739 } else {2740 ui_serverFilterType.integer++;2741 }2742 2743 if (ui_serverFilterType.integer >= numServerFilters) {2744 ui_serverFilterType.integer = 0;2745 } else if (ui_serverFilterType.integer < 0) {2746 ui_serverFilterType.integer = numServerFilters - 1;2747 }2748 UI_BuildServerDisplayList(qtrue);2749 return qtrue;2750 }2751 return qfalse;2752 }2753 2754 static qboolean UI_OpponentName_HandleKey(int flags, float *special, int key) {2755 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2756 if (key == K_MOUSE2) {2757 UI_PriorOpponent();2758 } else {2759 UI_NextOpponent();2760 }2761 return qtrue;2762 }2763 return qfalse;2764 }2765 2766 static qboolean UI_BotName_HandleKey(int flags, float *special, int key) {2767 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2768 int value = uiInfo.botIndex;2769 2770 if (key == K_MOUSE2) {2771 value--;2772 } else {2773 value++;2774 }2775 2776 2777 if( value >= UI_GetNumBots( ) + 2 )2778 value = 0;2779 else if( value < 0 )2780 value = UI_GetNumBots( ) + 2 - 1;2781 2782 uiInfo.botIndex = value;2783 return qtrue;2784 }2785 return qfalse;2786 }2787 2788 static qboolean UI_BotSkill_HandleKey(int flags, float *special, int key) {2789 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2790 if (key == K_MOUSE2) {2791 uiInfo.skillIndex--;2792 } else {2793 uiInfo.skillIndex++;2794 }2795 if (uiInfo.skillIndex >= numSkillLevels) {2796 uiInfo.skillIndex = 0;2797 } else if (uiInfo.skillIndex < 0) {2798 uiInfo.skillIndex = numSkillLevels-1;2799 }2800 return qtrue;2801 }2802 return qfalse;2803 }2804 2805 static qboolean UI_RedBlue_HandleKey(int flags, float *special, int key) {2806 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2807 uiInfo.redBlue ^= 1;2808 return qtrue;2809 }2810 return qfalse;2811 }2812 2813 2814 2815 static qboolean UI_SelectedPlayer_HandleKey(int flags, float *special, int key) {2816 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {2817 int selected;2818 2819 UI_BuildPlayerList();2820 if (!uiInfo.teamLeader) {2821 return qfalse;2822 }2823 selected = trap_Cvar_VariableValue("cg_selectedPlayer");2824 2825 if (key == K_MOUSE2) {2826 selected--;2827 } else {2828 selected++;2829 }2830 2831 if (selected > uiInfo.myTeamCount) {2832 selected = 0;2833 } else if (selected < 0) {2834 selected = uiInfo.myTeamCount;2835 }2836 2837 if (selected == uiInfo.myTeamCount) {2838 trap_Cvar_Set( "cg_selectedPlayerName", "Everyone");2839 } else {2840 trap_Cvar_Set( "cg_selectedPlayerName", uiInfo.teamNames[selected]);2841 }2842 trap_Cvar_Set( "cg_selectedPlayer", va("%d", selected));2843 }2844 return qfalse;2845 }2846 2847 2848 static qboolean UI_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key) {2849 switch (ownerDraw) {2850 case UI_HANDICAP:2851 return UI_Handicap_HandleKey(flags, special, key);2852 break;2853 case UI_CLANNAME:2854 return UI_ClanName_HandleKey(flags, special, key);2855 break;2856 case UI_GAMETYPE:2857 return UI_GameType_HandleKey(flags, special, key, qtrue);2858 break;2859 case UI_NETGAMETYPE:2860 return UI_NetGameType_HandleKey(flags, special, key);2861 break;2862 case UI_JOINGAMETYPE:2863 return UI_JoinGameType_HandleKey(flags, special, key);2864 break;2865 case UI_SKILL:2866 return UI_Skill_HandleKey(flags, special, key);2867 break;2868 case UI_BLUETEAMNAME:2869 return UI_TeamName_HandleKey(flags, special, key, qtrue);2870 break;2871 case UI_REDTEAMNAME:2872 return UI_TeamName_HandleKey(flags, special, key, qfalse);2873 break;2874 case UI_BLUETEAM1:2875 case UI_BLUETEAM2:2876 case UI_BLUETEAM3:2877 case UI_BLUETEAM4:2878 case UI_BLUETEAM5:2879 UI_TeamMember_HandleKey(flags, special, key, qtrue, ownerDraw - UI_BLUETEAM1 + 1);2880 break;2881 case UI_REDTEAM1:2882 case UI_REDTEAM2:2883 case UI_REDTEAM3:2884 case UI_REDTEAM4:2885 case UI_REDTEAM5:2886 UI_TeamMember_HandleKey(flags, special, key, qfalse, ownerDraw - UI_REDTEAM1 + 1);2887 break;2888 case UI_NETSOURCE:2889 UI_NetSource_HandleKey(flags, special, key);2890 break;2891 case UI_NETFILTER:2892 UI_NetFilter_HandleKey(flags, special, key);2893 break;2894 case UI_OPPONENT_NAME:2895 UI_OpponentName_HandleKey(flags, special, key);2896 break;2897 case UI_BOTNAME:2898 return UI_BotName_HandleKey(flags, special, key);2899 break;2900 case UI_BOTSKILL:2901 return UI_BotSkill_HandleKey(flags, special, key);2902 break;2903 case UI_REDBLUE:2904 UI_RedBlue_HandleKey(flags, special, key);2905 break;2906 case UI_SELECTEDPLAYER:2907 UI_SelectedPlayer_HandleKey(flags, special, key);2908 break;2909 default:2910 break;2911 }2912 2913 return qfalse;2914 }2915 2916 2917 static float UI_GetValue(int ownerDraw) {2918 return 0;2919 }2920 2921 /*2922 =================2923 UI_ServersQsortCompare2924 =================2925 */2926 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ) {2927 return trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey, uiInfo.serverStatus.sortDir, *(int*)arg1, *(int*)arg2);2928 }2929 2930 2931 /*2932 =================2933 UI_ServersSort2934 =================2935 */2936 void UI_ServersSort(int column, qboolean force) {2937 2938 if ( !force ) {2939 if ( uiInfo.serverStatus.sortKey == column ) {2940 return;2941 }2942 }2943 2944 uiInfo.serverStatus.sortKey = column;2945 qsort( &uiInfo.serverStatus.displayServers[0], uiInfo.serverStatus.numDisplayServers, sizeof(int), UI_ServersQsortCompare);2946 }2947 2948 2949 /*2950 ===============2951 UI_GetCurrentAlienStage2952 ===============2953 */2954 static stage_t UI_GetCurrentAlienStage( void )2955 {2956 char buffer[ MAX_TOKEN_CHARS ];2957 stage_t stage, dummy;2958 2959 trap_Cvar_VariableStringBuffer( "ui_stages", buffer, sizeof( buffer ) );2960 sscanf( buffer, "%d %d", (int *)&stage , (int *)&dummy );2961 2962 return stage;2963 }2964 2965 /*2966 ===============2967 UI_GetCurrentHumanStage2968 ===============2969 */2970 static stage_t UI_GetCurrentHumanStage( void )2971 {2972 char buffer[ MAX_TOKEN_CHARS ];2973 stage_t stage, dummy;2974 2975 trap_Cvar_VariableStringBuffer( "ui_stages", buffer, sizeof( buffer ) );2976 sscanf( buffer, "%d %d", (int *)&dummy, (int *)&stage );2977 2978 return stage;2979 }2980 2981 /*2982 ===============2983 UI_LoadTeams2984 ===============2985 */2986 static void UI_LoadTeams( void )2987 {2988 uiInfo.tremTeamCount = 4;2989 2990 uiInfo.tremTeamList[ 0 ].text = String_Alloc( "Aliens" );2991 uiInfo.tremTeamList[ 0 ].cmd = String_Alloc( "cmd team aliens\n" );2992 uiInfo.tremTeamList[ 0 ].type = INFOTYPE_TEXT;2993 uiInfo.tremTeamList[ 0 ].v.text =2994 "The Alien Team\n\n"2995 "The Aliens' strengths are in movement and the ability to "2996 "quickly construct new bases quickly. They possess a range "2997 "of abilities including basic melee attacks, movement-"2998 "crippling poisons and more.";2999 3000 uiInfo.tremTeamList[ 1 ].text = String_Alloc( "Humans" );3001 uiInfo.tremTeamList[ 1 ].cmd = String_Alloc( "cmd team humans\n" );3002 uiInfo.tremTeamList[ 1 ].type = INFOTYPE_TEXT;3003 uiInfo.tremTeamList[ 1 ].v.text =3004 "The Human Team\n\n"3005 "The humans are the masters of technology. Although their "3006 "bases take long to construct, their automated defense "3007 "ensures they stay built. A wide range of upgrades and "3008 "weapons are available to the humans, each contributing "3009 "to eradicate the alien threat.";3010 3011 uiInfo.tremTeamList[ 2 ].text = String_Alloc( "Spectate" );3012 uiInfo.tremTeamList[ 2 ].cmd = String_Alloc( "cmd team spectate\n" );3013 uiInfo.tremTeamList[ 2 ].type = INFOTYPE_TEXT;3014 uiInfo.tremTeamList[ 2 ].v.text = "Watch the game without playing.";3015 3016 uiInfo.tremTeamList[ 3 ].text = String_Alloc( "Auto select" );3017 uiInfo.tremTeamList[ 3 ].cmd = String_Alloc( "cmd team auto\n" );3018 uiInfo.tremTeamList[ 3 ].type = INFOTYPE_TEXT;3019 uiInfo.tremTeamList[ 3 ].v.text = "Join the team with the least players.";3020 }3021 3022 /*3023 ===============3024 UI_AddClass3025 ===============3026 */3027 static void UI_AddClass( pClass_t class )3028 {3029 uiInfo.alienClassList[ uiInfo.alienClassCount ].text =3030 String_Alloc( BG_FindHumanNameForClassNum( class ) );3031 uiInfo.alienClassList[ uiInfo.alienClassCount ].cmd =3032 String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( class ) ) );3033 uiInfo.alienClassList[ uiInfo.alienClassCount ].type = INFOTYPE_CLASS;3034 uiInfo.alienClassList[ uiInfo.alienClassCount ].v.pclass = class;3035 3036 uiInfo.alienClassCount++;3037 }3038 3039 /*3040 ===============3041 UI_LoadAlienClasses3042 ===============3043 */3044 static void UI_LoadAlienClasses( void )3045 {3046 uiInfo.alienClassCount = 0;3047 3048 if( BG_ClassIsAllowed( PCL_ALIEN_LEVEL0 ) )3049 UI_AddClass( PCL_ALIEN_LEVEL0 );3050 3051 if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0_UPG ) &&3052 BG_FindStagesForClass( PCL_ALIEN_BUILDER0_UPG, UI_GetCurrentAlienStage( ) ) )3053 UI_AddClass( PCL_ALIEN_BUILDER0_UPG );3054 else if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0 ) )3055 UI_AddClass( PCL_ALIEN_BUILDER0 );3056 }3057 3058 /*3059 ===============3060 UI_AddItem3061 ===============3062 */3063 static void UI_AddItem( weapon_t weapon )3064 {3065 uiInfo.humanItemList[ uiInfo.humanItemCount ].text =3066 String_Alloc( BG_FindHumanNameForWeapon( weapon ) );3067 uiInfo.humanItemList[ uiInfo.humanItemCount ].cmd =3068 String_Alloc( va( "cmd class %s\n", BG_FindNameForWeapon( weapon ) ) );3069 uiInfo.humanItemList[ uiInfo.humanItemCount ].type = INFOTYPE_WEAPON;3070 uiInfo.humanItemList[ uiInfo.humanItemCount ].v.weapon = weapon;3071 3072 uiInfo.humanItemCount++;3073 }3074 3075 /*3076 ===============3077 UI_LoadHumanItems3078 ===============3079 */3080 static void UI_LoadHumanItems( void )3081 {3082 uiInfo.humanItemCount = 0;3083 3084 if( BG_WeaponIsAllowed( WP_MACHINEGUN ) )3085 UI_AddItem( WP_MACHINEGUN );3086 3087 if( BG_WeaponIsAllowed( WP_HBUILD2 ) &&3088 BG_FindStagesForWeapon( WP_HBUILD2, UI_GetCurrentHumanStage( ) ) )3089 UI_AddItem( WP_HBUILD2 );3090 else if( BG_WeaponIsAllowed( WP_HBUILD ) )3091 UI_AddItem( WP_HBUILD );3092 }3093 3094 /*3095 ===============3096 UI_ParseCarriageList3097 ===============3098 */3099 static void UI_ParseCarriageList( int *weapons, int *upgrades )3100 {3101 int i;3102 char carriageCvar[ MAX_TOKEN_CHARS ];3103 char *iterator;3104 char buffer[ MAX_TOKEN_CHARS ];3105 char *bufPointer;3106 3107 trap_Cvar_VariableStringBuffer( "ui_carriage", carriageCvar, sizeof( carriageCvar ) );3108 iterator = carriageCvar;3109 3110 if( weapons )3111 *weapons = 0;3112 3113 if( upgrades )3114 *upgrades = 0;3115 3116 //simple parser to give rise to weapon/upgrade list3117 while( iterator && iterator[ 0 ] != '$' )3118 {3119 bufPointer = buffer;3120 3121 if( iterator[ 0 ] == 'W' )3122 {3123 iterator++;3124 3125 while( iterator[ 0 ] != ' ' )3126 *bufPointer++ = *iterator++;3127 3128 *bufPointer++ = '\n';3129 3130 i = atoi( buffer );3131 3132 if( weapons )3133 *weapons |= ( 1 << i );3134 }3135 else if( iterator[ 0 ] == 'U' )3136 {3137 iterator++;3138 3139 while( iterator[ 0 ] != ' ' )3140 *bufPointer++ = *iterator++;3141 3142 *bufPointer++ = '\n';3143 3144 i = atoi( buffer );3145 3146 if( upgrades )3147 *upgrades |= ( 1 << i );3148 }3149 3150 iterator++;3151 }3152 }3153 3154 /*3155 ===============3156 UI_LoadHumanArmouryBuys3157 ===============3158 */3159 static void UI_LoadHumanArmouryBuys( void )3160 {3161 int i, j = 0;3162 stage_t stage = UI_GetCurrentHumanStage( );3163 int weapons, upgrades;3164 int slots = 0;3165 3166 UI_ParseCarriageList( &weapons, &upgrades );3167 3168 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )3169 {3170 if( weapons & ( 1 << i ) )3171 slots |= BG_FindSlotsForWeapon( i );3172 }3173 3174 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )3175 {3176 if( upgrades & ( 1 << i ) )3177 slots |= BG_FindSlotsForUpgrade( i );3178 }3179 3180 uiInfo.humanArmouryBuyCount = 0;3181 3182 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )3183 {3184 if( BG_FindTeamForWeapon( i ) == WUT_HUMANS &&3185 BG_FindPurchasableForWeapon( i ) &&3186 BG_FindStagesForWeapon( i, stage ) &&3187 BG_WeaponIsAllowed( i ) &&3188 !( BG_FindSlotsForWeapon( i ) & slots ) &&3189 !( weapons & ( 1 << i ) ) )3190 {3191 uiInfo.humanArmouryBuyList[ j ].text =3192 String_Alloc( BG_FindHumanNameForWeapon( i ) );3193 uiInfo.humanArmouryBuyList[ j ].cmd =3194 String_Alloc( va( "cmd buy %s retrigger\n", BG_FindNameForWeapon( i ) ) );3195 uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_WEAPON;3196 uiInfo.humanArmouryBuyList[ j ].v.weapon = i;3197 3198 j++;3199 3200 uiInfo.humanArmouryBuyCount++;3201 }3202 }3203 3204 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )3205 {3206 if( BG_FindTeamForUpgrade( i ) == WUT_HUMANS &&3207 BG_FindPurchasableForUpgrade( i ) &&3208 BG_FindStagesForUpgrade( i, stage ) &&3209 BG_UpgradeIsAllowed( i ) &&3210 !( BG_FindSlotsForUpgrade( i ) & slots ) &&3211 !( upgrades & ( 1 << i ) ) )3212 {3213 uiInfo.humanArmouryBuyList[ j ].text =3214 String_Alloc( BG_FindHumanNameForUpgrade( i ) );3215 uiInfo.humanArmouryBuyList[ j ].cmd =3216 String_Alloc( va( "cmd buy %s retrigger\n", BG_FindNameForUpgrade( i ) ) );3217 uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_UPGRADE;3218 uiInfo.humanArmouryBuyList[ j ].v.upgrade = i;3219 3220 j++;3221 3222 uiInfo.humanArmouryBuyCount++;3223 }3224 }3225 }3226 3227 /*3228 ===============3229 UI_LoadHumanArmourySells3230 ===============3231 */3232 static void UI_LoadHumanArmourySells( void )3233 {3234 int weapons, upgrades;3235 int i, j = 0;3236 3237 uiInfo.humanArmourySellCount = 0;3238 UI_ParseCarriageList( &weapons, &upgrades );3239 3240 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )3241 {3242 if( weapons & ( 1 << i ) )3243 {3244 uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForWeapon( i ) );3245 uiInfo.humanArmourySellList[ j ].cmd =3246 String_Alloc( va( "cmd sell %s retrigger\n", BG_FindNameForWeapon( i ) ) );3247 uiInfo.humanArmourySellList[ j ].type = INFOTYPE_WEAPON;3248 uiInfo.humanArmourySellList[ j ].v.weapon = i;3249 3250 j++;3251 3252 uiInfo.humanArmourySellCount++;3253 }3254 }3255 3256 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )3257 {3258 if( upgrades & ( 1 << i ) )3259 {3260 uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForUpgrade( i ) );3261 uiInfo.humanArmourySellList[ j ].cmd =3262 String_Alloc( va( "cmd sell %s retrigger\n", BG_FindNameForUpgrade( i ) ) );3263 uiInfo.humanArmourySellList[ j ].type = INFOTYPE_UPGRADE;3264 uiInfo.humanArmourySellList[ j ].v.upgrade = i;3265 3266 j++;3267 3268 uiInfo.humanArmourySellCount++;3269 }3270 }3271 }3272 3273 /*3274 ===============3275 UI_LoadAlienUpgrades3276 ===============3277 */3278 static void UI_LoadAlienUpgrades( void )3279 {3280 int i, j = 0;3281 int class, credits;3282 char ui_currentClass[ MAX_STRING_CHARS ];3283 stage_t stage = UI_GetCurrentAlienStage( );3284 3285 trap_Cvar_VariableStringBuffer( "ui_currentClass", ui_currentClass, MAX_STRING_CHARS );3286 sscanf( ui_currentClass, "%d %d", &class, &credits );3287 3288 uiInfo.alienUpgradeCount = 0;3289 3290 for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )3291 {3292 if( BG_ClassCanEvolveFromTo( class, i, credits, 0 ) >= 0 &&3293 BG_FindStagesForClass( i, stage ) &&3294 BG_ClassIsAllowed( i ) )3295 {3296 uiInfo.alienUpgradeList[ j ].text = String_Alloc( BG_FindHumanNameForClassNum( i ) );3297 uiInfo.alienUpgradeList[ j ].cmd =3298 String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( i ) ) );3299 uiInfo.alienUpgradeList[ j ].type = INFOTYPE_CLASS;3300 uiInfo.alienUpgradeList[ j ].v.pclass = i;3301 3302 j++;3303 3304 uiInfo.alienUpgradeCount++;3305 }3306 }3307 }3308 3309 /*3310 ===============3311 UI_LoadAlienBuilds3312 ===============3313 */3314 static void UI_LoadAlienBuilds( void )3315 {3316 int weapons;3317 int i, j = 0;3318 stage_t stage;3319 3320 UI_ParseCarriageList( &weapons, NULL );3321 stage = UI_GetCurrentAlienStage( );3322 3323 uiInfo.alienBuildCount = 0;3324 3325 for( i = BA_NONE +1; i < BA_NUM_BUILDABLES; i++ )3326 {3327 if( BG_FindTeamForBuildable( i ) == BIT_ALIENS &&3328 BG_FindBuildWeaponForBuildable( i ) & weapons &&3329 BG_FindStagesForBuildable( i, stage ) &&3330 BG_BuildableIsAllowed( i ) )3331 {3332 uiInfo.alienBuildList[ j ].text =3333 String_Alloc( BG_FindHumanNameForBuildable( i ) );3334 uiInfo.alienBuildList[ j ].cmd =3335 String_Alloc( va( "cmd build %s\n", BG_FindNameForBuildable( i ) ) );3336 uiInfo.alienBuildList[ j ].type = INFOTYPE_BUILDABLE;3337 uiInfo.alienBuildList[ j ].v.buildable = i;3338 3339 j++;3340 3341 uiInfo.alienBuildCount++;3342 }3343 }3344 }3345 3346 /*3347 ===============3348 UI_LoadHumanBuilds3349 ===============3350 */3351 static void UI_LoadHumanBuilds( void )3352 {3353 int weapons;3354 int i, j = 0;3355 stage_t stage;3356 3357 UI_ParseCarriageList( &weapons, NULL );3358 stage = UI_GetCurrentHumanStage( );3359 3360 uiInfo.humanBuildCount = 0;3361 3362 for( i = BA_NONE +1; i < BA_NUM_BUILDABLES; i++ )3363 {3364 if( BG_FindTeamForBuildable( i ) == BIT_HUMANS &&3365 BG_FindBuildWeaponForBuildable( i ) & weapons &&3366 BG_FindStagesForBuildable( i, stage ) &&3367 BG_BuildableIsAllowed( i ) )3368 {3369 uiInfo.humanBuildList[ j ].text =3370 String_Alloc( BG_FindHumanNameForBuildable( i ) );3371 uiInfo.humanBuildList[ j ].cmd =3372 String_Alloc( va( "cmd build %s\n", BG_FindNameForBuildable( i ) ) );3373 uiInfo.humanBuildList[ j ].type = INFOTYPE_BUILDABLE;3374 uiInfo.humanBuildList[ j ].v.buildable = i;3375 3376 j++;3377 3378 uiInfo.humanBuildCount++;3379 }3380 }3381 }3382 3383 /*3384 ===============3385 UI_LoadMods3386 ===============3387 */3388 static void UI_LoadMods( void ) {3389 int numdirs;3390 char dirlist[2048];3391 char *dirptr;3392 char *descptr;3393 int i;3394 int dirlen;3395 3396 uiInfo.modCount = 0;3397 numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof(dirlist) );3398 dirptr = dirlist;3399 for( i = 0; i < numdirs; i++ ) {3400 dirlen = strlen( dirptr ) + 1;3401 descptr = dirptr + dirlen;3402 uiInfo.modList[uiInfo.modCount].modName = String_Alloc(dirptr);3403 uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc(descptr);3404 dirptr += dirlen + strlen(descptr) + 1;3405 uiInfo.modCount++;3406 if (uiInfo.modCount >= MAX_MODS) {3407 break;3408 }3409 }3410 3411 }3412 3413 3414 /*3415 ===============3416 UI_LoadMovies3417 ===============3418 */3419 static void UI_LoadMovies( void ) {3420 char movielist[4096];3421 char *moviename;3422 int i, len;3423 3424 uiInfo.movieCount = trap_FS_GetFileList( "video", "roq", movielist, 4096 );3425 3426 if (uiInfo.movieCount) {3427 if (uiInfo.movieCount > MAX_MOVIES) {3428 uiInfo.movieCount = MAX_MOVIES;3429 }3430 moviename = movielist;3431 for ( i = 0; i < uiInfo.movieCount; i++ ) {3432 len = strlen( moviename );3433 if (!Q_stricmp(moviename + len - 4,".roq")) {3434 moviename[len-4] = '\0';3435 }3436 Q_strupr(moviename);3437 uiInfo.movieList[i] = String_Alloc(moviename);3438 moviename += len + 1;3439 }3440 }3441 3442 }3443 3444 3445 3446 /*3447 ===============3448 UI_LoadDemos3449 ===============3450 */3451 static void UI_LoadDemos( void ) {3452 char demolist[4096];3453 char demoExt[32];3454 char *demoname;3455 int i, len;3456 3457 Com_sprintf(demoExt, sizeof(demoExt), "dm_%d", (int)trap_Cvar_VariableValue("protocol"));3458 3459 uiInfo.demoCount = trap_FS_GetFileList( "demos", demoExt, demolist, 4096 );3460 3461 Com_sprintf(demoExt, sizeof(demoExt), ".dm_%d", (int)trap_Cvar_VariableValue("protocol"));3462 3463 if (uiInfo.demoCount) {3464 if (uiInfo.demoCount > MAX_DEMOS) {3465 uiInfo.demoCount = MAX_DEMOS;3466 }3467 demoname = demolist;3468 for ( i = 0; i < uiInfo.demoCount; i++ ) {3469 len = strlen( demoname );3470 if (!Q_stricmp(demoname + len - strlen(demoExt), demoExt)) {3471 demoname[len-strlen(demoExt)] = '\0';3472 }3473 Q_strupr(demoname);3474 uiInfo.demoList[i] = String_Alloc(demoname);3475 demoname += len + 1;3476 }3477 }3478 3479 }3480 3481 3482 static qboolean UI_SetNextMap(int actual, int index) {3483 int i;3484 for (i = actual + 1; i < uiInfo.mapCount; i++) {3485 if (uiInfo.mapList[i].active) {3486 Menu_SetFeederSelection(NULL, FEEDER_MAPS, index + 1, "skirmish");3487 return qtrue;3488 }3489 }3490 return qfalse;3491 }3492 3493 3494 static void UI_StartSkirmish(qboolean next) {3495 int i, k, g, delay, temp;3496 float skill;3497 char buff[MAX_STRING_CHARS];3498 3499 if (next) {3500 int actual;3501 int index = trap_Cvar_VariableValue("ui_mapIndex");3502 UI_MapCountByGameType(qtrue);3503 UI_SelectedMap(index, &actual);3504 if (UI_SetNextMap(actual, index)) {3505 } else {3506 UI_GameType_HandleKey(0, NULL, K_MOUSE1, qfalse);3507 UI_MapCountByGameType(qtrue);3508 Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, "skirmish");3509 }3510 }3511 3512 g = uiInfo.gameTypes[ui_gameType.integer].gtEnum;3513 trap_Cvar_SetValue( "g_gametype", g );3514 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName) );3515 skill = trap_Cvar_VariableValue( "g_spSkill" );3516 trap_Cvar_Set("ui_scoreMap", uiInfo.mapList[ui_currentMap.integer].mapName);3517 3518 k = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));3519 3520 trap_Cvar_Set("ui_singlePlayerActive", "1");3521 3522 // set up sp overrides, will be replaced on postgame3523 temp = trap_Cvar_VariableValue( "capturelimit" );3524 trap_Cvar_Set("ui_saveCaptureLimit", va("%i", temp));3525 temp = trap_Cvar_VariableValue( "fraglimit" );3526 trap_Cvar_Set("ui_saveFragLimit", va("%i", temp));3527 3528 UI_SetCapFragLimits(qfalse);3529 3530 temp = trap_Cvar_VariableValue( "cg_drawTimer" );3531 trap_Cvar_Set("ui_drawTimer", va("%i", temp));3532 temp = trap_Cvar_VariableValue( "g_doWarmup" );3533 trap_Cvar_Set("ui_doWarmup", va("%i", temp));3534 temp = trap_Cvar_VariableValue( "g_friendlyFire" );3535 trap_Cvar_Set("ui_friendlyFire", va("%i", temp));3536 temp = trap_Cvar_VariableValue( "sv_maxClients" );3537 trap_Cvar_Set("ui_maxClients", va("%i", temp));3538 temp = trap_Cvar_VariableValue( "g_warmup" );3539 trap_Cvar_Set("ui_Warmup", va("%i", temp));3540 temp = trap_Cvar_VariableValue( "sv_pure" );3541 trap_Cvar_Set("ui_pure", va("%i", temp));3542 3543 trap_Cvar_Set("cg_cameraOrbit", "0");3544 trap_Cvar_Set("cg_thirdPerson", "0");3545 trap_Cvar_Set("cg_drawTimer", "1");3546 trap_Cvar_Set("g_doWarmup", "1");3547 trap_Cvar_Set("g_warmup", "15");3548 trap_Cvar_Set("sv_pure", "0");3549 trap_Cvar_Set("g_friendlyFire", "0");3550 trap_Cvar_Set("g_redTeam", UI_Cvar_VariableString("ui_teamName"));3551 trap_Cvar_Set("g_blueTeam", UI_Cvar_VariableString("ui_opponentName"));3552 3553 if (trap_Cvar_VariableValue("ui_recordSPDemo")) {3554 Com_sprintf(buff, MAX_STRING_CHARS, "%s_%i", uiInfo.mapList[ui_currentMap.integer].mapLoadName, g);3555 trap_Cvar_Set("ui_recordSPDemoName", buff);3556 }3557 3558 delay = 500;3559 3560 {3561 temp = uiInfo.mapList[ui_currentMap.integer].teamMembers * 2;3562 trap_Cvar_Set("sv_maxClients", va("%d", temp));3563 for (i =0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers; i++) {3564 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s %i %s\n", UI_AIFromName(uiInfo.teamList[k].teamMembers[i]), skill, "", delay, uiInfo.teamList[k].teamMembers[i]);3565 trap_Cmd_ExecuteText( EXEC_APPEND, buff );3566 delay += 500;3567 }3568 k = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));3569 for (i =0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers-1; i++) {3570 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s %i %s\n", UI_AIFromName(uiInfo.teamList[k].teamMembers[i]), skill, "", delay, uiInfo.teamList[k].teamMembers[i]);3571 trap_Cmd_ExecuteText( EXEC_APPEND, buff );3572 delay += 500;3573 }3574 }3575 }3576 3577 static void UI_Update(const char *name) {3578 int val = trap_Cvar_VariableValue(name);3579 3580 if (Q_stricmp(name, "ui_SetName") == 0) {3581 trap_Cvar_Set( "name", UI_Cvar_VariableString("ui_Name"));3582 } else if (Q_stricmp(name, "ui_setRate") == 0) {3583 float rate = trap_Cvar_VariableValue("rate");3584 if (rate >= 5000) {3585 trap_Cvar_Set("cl_maxpackets", "30");3586 trap_Cvar_Set("cl_packetdup", "1");3587 } else if (rate >= 4000) {3588 trap_Cvar_Set("cl_maxpackets", "15");3589 trap_Cvar_Set("cl_packetdup", "2"); // favor less prediction errors when there's packet loss3590 } else {3591 trap_Cvar_Set("cl_maxpackets", "15");3592 trap_Cvar_Set("cl_packetdup", "1"); // favor lower bandwidth3593 }3594 } else if (Q_stricmp(name, "ui_GetName") == 0) {3595 trap_Cvar_Set( "ui_Name", UI_Cvar_VariableString("name"));3596 } else if (Q_stricmp(name, "r_colorbits") == 0) {3597 switch (val) {3598 case 0:3599 trap_Cvar_SetValue( "r_depthbits", 0 );3600 trap_Cvar_SetValue( "r_stencilbits", 0 );3601 break;3602 case 16:3603 trap_Cvar_SetValue( "r_depthbits", 16 );3604 trap_Cvar_SetValue( "r_stencilbits", 0 );3605 break;3606 case 32:3607 trap_Cvar_SetValue( "r_depthbits", 24 );3608 break;3609 }3610 } else if (Q_stricmp(name, "r_lodbias") == 0) {3611 switch (val) {3612 case 0:3613 trap_Cvar_SetValue( "r_subdivisions", 4 );3614 break;3615 case 1:3616 trap_Cvar_SetValue( "r_subdivisions", 12 );3617 break;3618 case 2:3619 trap_Cvar_SetValue( "r_subdivisions", 20 );3620 break;3621 }3622 } else if (Q_stricmp(name, "ui_glCustom") == 0) {3623 switch (val) {3624 case 0: // high quality3625 trap_Cvar_SetValue( "r_fullScreen", 1 );3626 trap_Cvar_SetValue( "r_subdivisions", 4 );3627 trap_Cvar_SetValue( "r_vertexlight", 0 );3628 trap_Cvar_SetValue( "r_lodbias", 0 );3629 trap_Cvar_SetValue( "r_colorbits", 32 );3630 trap_Cvar_SetValue( "r_depthbits", 24 );3631 trap_Cvar_SetValue( "r_picmip", 0 );3632 trap_Cvar_SetValue( "r_mode", 4 );3633 trap_Cvar_SetValue( "r_texturebits", 32 );3634 trap_Cvar_SetValue( "r_fastSky", 0 );3635 trap_Cvar_SetValue( "r_inGameVideo", 1 );3636 trap_Cvar_SetValue( "cg_shadows", 1 );3637 trap_Cvar_SetValue( "cg_brassTime", 2500 );3638 trap_Cvar_SetValue( "cg_bounceParticles", 1 );3639 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );3640 break;3641 case 1: // normal3642 trap_Cvar_SetValue( "r_fullScreen", 1 );3643 trap_Cvar_SetValue( "r_subdivisions", 12 );3644 trap_Cvar_SetValue( "r_vertexlight", 0 );3645 trap_Cvar_SetValue( "r_lodbias", 0 );3646 trap_Cvar_SetValue( "r_colorbits", 0 );3647 trap_Cvar_SetValue( "r_depthbits", 24 );3648 trap_Cvar_SetValue( "r_picmip", 1 );3649 trap_Cvar_SetValue( "r_mode", 3 );3650 trap_Cvar_SetValue( "r_texturebits", 0 );3651 trap_Cvar_SetValue( "r_fastSky", 0 );3652 trap_Cvar_SetValue( "r_inGameVideo", 1 );3653 trap_Cvar_SetValue( "cg_brassTime", 2500 );3654 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );3655 trap_Cvar_SetValue( "cg_shadows", 0 );3656 trap_Cvar_SetValue( "cg_bounceParticles", 0 );3657 break;3658 case 2: // fast3659 trap_Cvar_SetValue( "r_fullScreen", 1 );3660 trap_Cvar_SetValue( "r_subdivisions", 8 );3661 trap_Cvar_SetValue( "r_vertexlight", 0 );3662 trap_Cvar_SetValue( "r_lodbias", 1 );3663 trap_Cvar_SetValue( "r_colorbits", 0 );3664 trap_Cvar_SetValue( "r_depthbits", 0 );3665 trap_Cvar_SetValue( "r_picmip", 1 );3666 trap_Cvar_SetValue( "r_mode", 3 );3667 trap_Cvar_SetValue( "r_texturebits", 0 );3668 trap_Cvar_SetValue( "cg_shadows", 0 );3669 trap_Cvar_SetValue( "r_fastSky", 1 );3670 trap_Cvar_SetValue( "r_inGameVideo", 0 );3671 trap_Cvar_SetValue( "cg_brassTime", 0 );3672 trap_Cvar_SetValue( "cg_bounceParticles", 0 );3673 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );3674 break;3675 case 3: // fastest3676 trap_Cvar_SetValue( "r_fullScreen", 1 );3677 trap_Cvar_SetValue( "r_subdivisions", 20 );3678 trap_Cvar_SetValue( "r_vertexlight", 1 );3679 trap_Cvar_SetValue( "r_lodbias", 2 );3680 trap_Cvar_SetValue( "r_colorbits", 16 );3681 trap_Cvar_SetValue( "r_depthbits", 16 );3682 trap_Cvar_SetValue( "r_mode", 3 );3683 trap_Cvar_SetValue( "r_picmip", 2 );3684 trap_Cvar_SetValue( "r_texturebits", 16 );3685 trap_Cvar_SetValue( "cg_shadows", 0 );3686 trap_Cvar_SetValue( "cg_brassTime", 0 );3687 trap_Cvar_SetValue( "r_fastSky", 1 );3688 trap_Cvar_SetValue( "r_inGameVideo", 0 );3689 trap_Cvar_SetValue( "cg_bounceParticles", 0 );3690 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );3691 break;3692 }3693 } else if (Q_stricmp(name, "ui_mousePitch") == 0) {3694 if (val == 0) {3695 trap_Cvar_SetValue( "m_pitch", 0.022f );3696 } else {3697 trap_Cvar_SetValue( "m_pitch", -0.022f );3698 }3699 }3700 }3701 3702 static void UI_RunMenuScript(char **args) {3703 const char *name, *name2;3704 char buff[1024];3705 const char *cmd;3706 3707 if (String_Parse(args, &name)) {3708 if (Q_stricmp(name, "StartServer") == 0) {3709 int i, clients, oldclients;3710 float skill;3711 trap_Cvar_Set("cg_thirdPerson", "0");3712 trap_Cvar_Set("cg_cameraOrbit", "0");3713 trap_Cvar_Set("ui_singlePlayerActive", "0");3714 trap_Cvar_SetValue( "dedicated", Com_Clamp( 0, 2, ui_dedicated.integer ) );3715 trap_Cvar_SetValue( "g_gametype", Com_Clamp( 0, 8, uiInfo.gameTypes[ui_netGameType.integer].gtEnum ) );3716 trap_Cvar_Set("g_redTeam", UI_Cvar_VariableString("ui_teamName"));3717 trap_Cvar_Set("g_blueTeam", UI_Cvar_VariableString("ui_opponentName"));3718 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName ) );3719 skill = trap_Cvar_VariableValue( "g_spSkill" );3720 // set max clients based on spots3721 oldclients = trap_Cvar_VariableValue( "sv_maxClients" );3722 clients = 0;3723 for (i = 0; i < PLAYERS_PER_TEAM; i++) {3724 int bot = trap_Cvar_VariableValue( va("ui_blueteam%i", i+1));3725 if (bot >= 0) {3726 clients++;3727 }3728 bot = trap_Cvar_VariableValue( va("ui_redteam%i", i+1));3729 if (bot >= 0) {3730 clients++;3731 }3732 }3733 if (clients == 0) {3734 clients = 8;3735 }3736 3737 if (oldclients > clients) {3738 clients = oldclients;3739 }3740 3741 trap_Cvar_Set("sv_maxClients", va("%d",clients));3742 3743 for (i = 0; i < PLAYERS_PER_TEAM; i++) {3744 int bot = trap_Cvar_VariableValue( va("ui_blueteam%i", i+1));3745 if (bot > 1) {3746 Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);3747 trap_Cmd_ExecuteText( EXEC_APPEND, buff );3748 }3749 bot = trap_Cvar_VariableValue( va("ui_redteam%i", i+1));3750 if (bot > 1) {3751 Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);3752 trap_Cmd_ExecuteText( EXEC_APPEND, buff );3753 }3754 }3755 } else if (Q_stricmp(name, "updateSPMenu") == 0) {3756 UI_SetCapFragLimits(qtrue);3757 UI_MapCountByGameType(qtrue);3758 ui_mapIndex.integer = UI_GetIndexFromSelection(ui_currentMap.integer);3759 trap_Cvar_Set("ui_mapIndex", va("%d", ui_mapIndex.integer));3760 Menu_SetFeederSelection(NULL, FEEDER_MAPS, ui_mapIndex.integer, "skirmish");3761 UI_GameType_HandleKey(0, NULL, K_MOUSE1, qfalse);3762 UI_GameType_HandleKey(0, NULL, K_MOUSE2, qfalse);3763 } else if (Q_stricmp(name, "resetDefaults") == 0) {3764 trap_Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n");3765 trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");3766 Controls_SetDefaults();3767 trap_Cvar_Set("com_introPlayed", "1" );3768 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );3769 } else if (Q_stricmp(name, "loadArenas") == 0) {3770 UI_LoadArenas();3771 UI_MapCountByGameType(qfalse);3772 Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, "createserver");3773 } else if (Q_stricmp(name, "loadServerInfo") == 0) {3774 UI_ServerInfo();3775 } else if (Q_stricmp(name, "saveControls") == 0) {3776 Controls_SetConfig(qtrue);3777 } else if (Q_stricmp(name, "loadControls") == 0) {3778 Controls_GetConfig();3779 } else if (Q_stricmp(name, "clearError") == 0) {3780 trap_Cvar_Set("com_errorMessage", "");3781 } else if (Q_stricmp(name, "loadGameInfo") == 0) {3782 /* UI_ParseGameInfo("gameinfo.txt");3783 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);*/3784 } else if (Q_stricmp(name, "resetScores") == 0) {3785 UI_ClearScores();3786 } else if (Q_stricmp(name, "RefreshServers") == 0) {3787 UI_StartServerRefresh(qtrue);3788 UI_BuildServerDisplayList(qtrue);3789 } else if (Q_stricmp(name, "InitServerList") == 0) {3790 int time = trap_RealTime( NULL );3791 int last;3792 int sortColumn;3793 3794 // set up default sorting3795 if(!uiInfo.serverStatus.sorted && Int_Parse(args, &sortColumn))3796 {3797 uiInfo.serverStatus.sortKey = sortColumn;3798 uiInfo.serverStatus.sortDir = 0;3799 }3800 3801 // refresh if older than 3 days or if list is empty3802 last = atoi( UI_Cvar_VariableString( va( "ui_lastServerRefresh_%i_time",3803 ui_netSource.integer ) ) );3804 if( trap_LAN_GetServerCount( ui_netSource.integer ) < 1 ||3805 ( time - last ) > 3600 )3806 {3807 UI_StartServerRefresh(qtrue);3808 UI_BuildServerDisplayList(qtrue);3809 }3810 } else if (Q_stricmp(name, "RefreshFilter") == 0) {3811 UI_StartServerRefresh(qfalse);3812 UI_BuildServerDisplayList(qtrue);3813 } else if (Q_stricmp(name, "RunSPDemo") == 0) {3814 if (uiInfo.demoAvailable) {3815 trap_Cmd_ExecuteText( EXEC_APPEND, va("demo %s_%i\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum));3816 }3817 } else if (Q_stricmp(name, "LoadDemos") == 0) {3818 UI_LoadDemos();3819 } else if (Q_stricmp(name, "LoadMovies") == 0) {3820 UI_LoadMovies();3821 } else if (Q_stricmp(name, "LoadMods") == 0) {3822 UI_LoadMods();3823 }3824 else if( Q_stricmp( name, "LoadTeams" ) == 0 )3825 UI_LoadTeams( );3826 else if( Q_stricmp( name, "JoinTeam" ) == 0 )3827 {3828 if( ( cmd = uiInfo.tremTeamList[ uiInfo.tremTeamIndex ].cmd ) )3829 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3830 }3831 else if( Q_stricmp( name, "LoadHumanItems" ) == 0 )3832 UI_LoadHumanItems( );3833 else if( Q_stricmp( name, "SpawnWithHumanItem" ) == 0 )3834 {3835 if( ( cmd = uiInfo.humanItemList[ uiInfo.humanItemIndex ].cmd ) )3836 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3837 }3838 else if( Q_stricmp( name, "LoadAlienClasses" ) == 0 )3839 UI_LoadAlienClasses( );3840 else if( Q_stricmp( name, "SpawnAsAlienClass" ) == 0 )3841 {3842 if( ( cmd = uiInfo.alienClassList[ uiInfo.alienClassIndex ].cmd ) )3843 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3844 }3845 else if( Q_stricmp( name, "LoadHumanArmouryBuys" ) == 0 )3846 UI_LoadHumanArmouryBuys( );3847 else if( Q_stricmp( name, "BuyFromArmoury" ) == 0 )3848 {3849 if( ( cmd = uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ].cmd ) )3850 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3851 }3852 else if( Q_stricmp( name, "LoadHumanArmourySells" ) == 0 )3853 UI_LoadHumanArmourySells( );3854 else if( Q_stricmp( name, "SellToArmoury" ) == 0 )3855 {3856 if( ( cmd = uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ].cmd ) )3857 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3858 }3859 else if( Q_stricmp( name, "LoadAlienUpgrades" ) == 0 )3860 {3861 UI_LoadAlienUpgrades( );3862 3863 //disallow the menu if it would be empty3864 if( uiInfo.alienUpgradeCount <= 0 )3865 Menus_CloseAll( );3866 }3867 else if( Q_stricmp( name, "UpgradeToNewClass" ) == 0 )3868 {3869 if( ( cmd = uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ].cmd ) )3870 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3871 }3872 else if( Q_stricmp( name, "LoadAlienBuilds" ) == 0 )3873 UI_LoadAlienBuilds( );3874 else if( Q_stricmp( name, "BuildAlienBuildable" ) == 0 )3875 {3876 if( ( cmd = uiInfo.alienBuildList[ uiInfo.alienBuildIndex ].cmd ) )3877 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3878 }3879 else if( Q_stricmp( name, "LoadHumanBuilds" ) == 0 )3880 UI_LoadHumanBuilds( );3881 else if( Q_stricmp( name, "BuildHumanBuildable" ) == 0 )3882 {3883 if( ( cmd = uiInfo.humanBuildList[ uiInfo.humanBuildIndex ].cmd ) )3884 trap_Cmd_ExecuteText( EXEC_APPEND, cmd );3885 }3886 else if( Q_stricmp( name, "PTRCRestore" ) == 0 )3887 {3888 int len;3889 char text[ 16 ];3890 fileHandle_t f;3891 char command[ 32 ];3892 3893 // load the file3894 len = trap_FS_FOpenFile( "ptrc.cfg", &f, FS_READ );3895 3896 if( len > 0 && ( len < sizeof( text ) - 1 ) )3897 {3898 trap_FS_Read( text, len, f );3899 text[ len ] = 0;3900 trap_FS_FCloseFile( f );3901 3902 Com_sprintf( command, 32, "ptrcrestore %s", text );3903 3904 trap_Cmd_ExecuteText( EXEC_APPEND, command );3905 }3906 }3907 else if (Q_stricmp(name, "playMovie") == 0) {3908 if (uiInfo.previewMovie >= 0) {3909 trap_CIN_StopCinematic(uiInfo.previewMovie);3910 }3911 trap_Cmd_ExecuteText( EXEC_APPEND, va("cinematic %s.roq 2\n", uiInfo.movieList[uiInfo.movieIndex]));3912 } else if (Q_stricmp(name, "RunMod") == 0) {3913 trap_Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName);3914 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );3915 } else if (Q_stricmp(name, "RunDemo") == 0) {3916 trap_Cmd_ExecuteText( EXEC_APPEND, va("demo %s\n", uiInfo.demoList[uiInfo.demoIndex]));3917 } else if (Q_stricmp(name, "Tremulous") == 0) {3918 trap_Cvar_Set( "fs_game", "");3919 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );3920 } else if (Q_stricmp(name, "closeJoin") == 0) {3921 if (uiInfo.serverStatus.refreshActive) {3922 UI_StopServerRefresh();3923 uiInfo.serverStatus.nextDisplayRefresh = 0;3924 uiInfo.nextServerStatusRefresh = 0;3925 uiInfo.nextFindPlayerRefresh = 0;3926 UI_BuildServerDisplayList(qtrue);3927 } else {3928 Menus_CloseByName("joinserver");3929 Menus_OpenByName("main");3930 }3931 } else if (Q_stricmp(name, "StopRefresh") == 0) {3932 UI_StopServerRefresh();3933 uiInfo.serverStatus.nextDisplayRefresh = 0;3934 uiInfo.nextServerStatusRefresh = 0;3935 uiInfo.nextFindPlayerRefresh = 0;3936 } else if (Q_stricmp(name, "UpdateFilter") == 0) {3937 if (ui_netSource.integer == AS_LOCAL) {3938 UI_StartServerRefresh(qtrue);3939 }3940 UI_BuildServerDisplayList(qtrue);3941 UI_FeederSelection(FEEDER_SERVERS, 0);3942 } else if (Q_stricmp(name, "ServerStatus") == 0) {3943 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], uiInfo.serverStatusAddress, sizeof(uiInfo.serverStatusAddress));3944 UI_BuildServerStatus(qtrue);3945 } else if (Q_stricmp(name, "FoundPlayerServerStatus") == 0) {3946 Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress));3947 UI_BuildServerStatus(qtrue);3948 Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);3949 } else if (Q_stricmp(name, "FindPlayer") == 0) {3950 UI_BuildFindPlayerList(qtrue);3951 // clear the displayed server status info3952 uiInfo.serverStatusInfo.numLines = 0;3953 Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);3954 } else if (Q_stricmp(name, "JoinServer") == 0) {3955 trap_Cvar_Set("cg_thirdPerson", "0");3956 trap_Cvar_Set("cg_cameraOrbit", "0");3957 trap_Cvar_Set("ui_singlePlayerActive", "0");3958 if (uiInfo.serverStatus.currentServer >= 0 && uiInfo.serverStatus.currentServer < uiInfo.serverStatus.numDisplayServers) {3959 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, 1024);3960 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", buff ) );3961 }3962 } else if (Q_stricmp(name, "FoundPlayerJoinServer") == 0) {3963 trap_Cvar_Set("ui_singlePlayerActive", "0");3964 if (uiInfo.currentFoundPlayerServer >= 0 && uiInfo.currentFoundPlayerServer < uiInfo.numFoundPlayerServers) {3965 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer] ) );3966 }3967 } else if (Q_stricmp(name, "Quit") == 0) {3968 trap_Cvar_Set("ui_singlePlayerActive", "0");3969 trap_Cmd_ExecuteText( EXEC_NOW, "quit");3970 } else if (Q_stricmp(name, "Controls") == 0) {3971 trap_Cvar_Set( "cl_paused", "1" );3972 trap_Key_SetCatcher( KEYCATCH_UI );3973 Menus_CloseAll();3974 Menus_ActivateByName("setup_menu2");3975 } else if (Q_stricmp(name, "Leave") == 0) {3976 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect\n" );3977 trap_Key_SetCatcher( KEYCATCH_UI );3978 Menus_CloseAll();3979 Menus_ActivateByName("main");3980 } else if (Q_stricmp(name, "ServerSort") == 0) {3981 int sortColumn;3982 if (Int_Parse(args, &sortColumn)) {3983 // if same column we're already sorting on then flip the direction3984 if (sortColumn == uiInfo.serverStatus.sortKey) {3985 uiInfo.serverStatus.sortDir = !uiInfo.serverStatus.sortDir;3986 }3987 // make sure we sort again3988 UI_ServersSort(sortColumn, qtrue);3989 uiInfo.serverStatus.sorted = qtrue;3990 }3991 } else if (Q_stricmp(name, "nextSkirmish") == 0) {3992 UI_StartSkirmish(qtrue);3993 } else if (Q_stricmp(name, "SkirmishStart") == 0) {3994 UI_StartSkirmish(qfalse);3995 } else if (Q_stricmp(name, "closeingame") == 0) {3996 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );3997 trap_Key_ClearStates();3998 trap_Cvar_Set( "cl_paused", "0" );3999 Menus_CloseAll();4000 } else if (Q_stricmp(name, "voteMap") == 0) {4001 if (ui_currentNetMap.integer >=0 && ui_currentNetMap.integer < uiInfo.mapCount) {4002 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote map %s\n",uiInfo.mapList[ui_currentNetMap.integer].mapLoadName) );4003 }4004 }4005 else if( Q_stricmp( name, "voteKick" ) == 0 )4006 {4007 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount )4008 {4009 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote kick %d\n",4010 uiInfo.clientNums[ uiInfo.playerIndex ] ) );4011 }4012 }4013 else if( Q_stricmp( name, "voteMute" ) == 0 )4014 {4015 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount )4016 {4017 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote mute %d\n",4018 uiInfo.clientNums[ uiInfo.playerIndex ] ) );4019 }4020 }4021 else if( Q_stricmp( name, "voteUnMute" ) == 0 )4022 {4023 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount )4024 {4025 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote unmute %d\n",4026 uiInfo.clientNums[ uiInfo.playerIndex ] ) );4027 }4028 }4029 else if( Q_stricmp( name, "voteTeamKick" ) == 0 )4030 {4031 if( uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount )4032 {4033 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote kick %d\n",4034 uiInfo.teamClientNums[ uiInfo.teamIndex ] ) );4035 }4036 }4037 else if( Q_stricmp( name, "voteTeamDenyBuild" ) == 0 )4038 {4039 if( uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount )4040 {4041 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote denybuild %d\n",4042 uiInfo.teamClientNums[ uiInfo.teamIndex ] ) );4043 }4044 }4045 else if( Q_stricmp( name, "voteTeamAllowBuild" ) == 0 )4046 {4047 if( uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount )4048 {4049 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote allowbuild %d\n",4050 uiInfo.teamClientNums[ uiInfo.teamIndex ] ) );4051 }4052 }4053 else if (Q_stricmp(name, "addFavorite") == 0) {4054 if (ui_netSource.integer != AS_FAVORITES) {4055 char name[MAX_NAME_LENGTH];4056 char addr[MAX_NAME_LENGTH];4057 int res;4058 4059 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);4060 name[0] = addr[0] = '\0';4061 Q_strncpyz(name, Info_ValueForKey(buff, "hostname"), MAX_NAME_LENGTH);4062 Q_strncpyz(addr, Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);4063 if (strlen(name) > 0 && strlen(addr) > 0) {4064 res = trap_LAN_AddServer(AS_FAVORITES, name, addr);4065 if (res == 0) {4066 // server already in the list4067 Com_Printf("Favorite already in list\n");4068 }4069 else if (res == -1) {4070 // list full4071 Com_Printf("Favorite list full\n");4072 }4073 else {4074 // successfully added4075 Com_Printf("Added favorite server %s\n", addr);4076 }4077 }4078 }4079 } else if (Q_stricmp(name, "deleteFavorite") == 0) {4080 if (ui_netSource.integer == AS_FAVORITES) {4081 char addr[MAX_NAME_LENGTH];4082 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);4083 addr[0] = '\0';4084 Q_strncpyz(addr, Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);4085 if (strlen(addr) > 0) {4086 trap_LAN_RemoveServer(AS_FAVORITES, addr);4087 }4088 }4089 } else if (Q_stricmp(name, "createFavorite") == 0) {4090 if (ui_netSource.integer == AS_FAVORITES) {4091 char name[MAX_NAME_LENGTH];4092 char addr[MAX_NAME_LENGTH];4093 int res;4094 4095 name[0] = addr[0] = '\0';4096 Q_strncpyz(name, UI_Cvar_VariableString("ui_favoriteName"), MAX_NAME_LENGTH);4097 Q_strncpyz(addr, UI_Cvar_VariableString("ui_favoriteAddress"), MAX_NAME_LENGTH);4098 if (strlen(name) > 0 && strlen(addr) > 0) {4099 res = trap_LAN_AddServer(AS_FAVORITES, name, addr);4100 if (res == 0) {4101 // server already in the list4102 Com_Printf("Favorite already in list\n");4103 }4104 else if (res == -1) {4105 // list full4106 Com_Printf("Favorite list full\n");4107 }4108 else {4109 // successfully added4110 Com_Printf("Added favorite server %s\n", addr);4111 }4112 }4113 }4114 } else if (Q_stricmp(name, "orders") == 0) {4115 const char *orders;4116 if (String_Parse(args, &orders)) {4117 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");4118 if (selectedPlayer < uiInfo.myTeamCount) {4119 strcpy(buff, orders);4120 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );4121 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );4122 } else {4123 int i;4124 for (i = 0; i < uiInfo.myTeamCount; i++) {4125 if (Q_stricmp(UI_Cvar_VariableString("name"), uiInfo.teamNames[i]) == 0) {4126 continue;4127 }4128 strcpy(buff, orders);4129 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamNames[i]) );4130 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );4131 }4132 }4133 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );4134 trap_Key_ClearStates();4135 trap_Cvar_Set( "cl_paused", "0" );4136 Menus_CloseAll();4137 }4138 } else if (Q_stricmp(name, "voiceOrdersTeam") == 0) {4139 const char *orders;4140 if (String_Parse(args, &orders)) {4141 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");4142 if (selectedPlayer == uiInfo.myTeamCount) {4143 trap_Cmd_ExecuteText( EXEC_APPEND, orders );4144 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );4145 }4146 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );4147 trap_Key_ClearStates();4148 trap_Cvar_Set( "cl_paused", "0" );4149 Menus_CloseAll();4150 }4151 } else if (Q_stricmp(name, "voiceOrders") == 0) {4152 const char *orders;4153 if (String_Parse(args, &orders)) {4154 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");4155 if (selectedPlayer < uiInfo.myTeamCount) {4156 strcpy(buff, orders);4157 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );4158 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );4159 }4160 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );4161 trap_Key_ClearStates();4162 trap_Cvar_Set( "cl_paused", "0" );4163 Menus_CloseAll();4164 }4165 } else if (Q_stricmp(name, "glCustom") == 0) {4166 trap_Cvar_Set("ui_glCustom", "4");4167 } else if (Q_stricmp(name, "update") == 0) {4168 if (String_Parse(args, &name2))4169 UI_Update(name2);4170 } else if (Q_stricmp(name, "InitIgnoreList") == 0) {4171 UI_BuildPlayerList();4172 } else if (Q_stricmp(name, "ToggleIgnore") == 0) {4173 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount )4174 {4175 if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4176 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) )4177 {4178 BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4179 uiInfo.clientNums[ uiInfo.ignoreIndex ] );4180 trap_Cmd_ExecuteText( EXEC_NOW, va( "unignore %i\n",4181 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) );4182 }4183 else4184 {4185 BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4186 uiInfo.clientNums[ uiInfo.ignoreIndex ] );4187 trap_Cmd_ExecuteText( EXEC_NOW, va( "ignore %i\n",4188 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) );4189 }4190 }4191 } else if (Q_stricmp(name, "IgnorePlayer") == 0) {4192 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount )4193 {4194 if( !BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4195 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) )4196 {4197 BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4198 uiInfo.clientNums[ uiInfo.ignoreIndex ] );4199 trap_Cmd_ExecuteText( EXEC_NOW, va( "ignore %i\n",4200 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) );4201 }4202 }4203 } else if (Q_stricmp(name, "UnIgnorePlayer") == 0) {4204 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount )4205 {4206 if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4207 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) )4208 {4209 BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ],4210 uiInfo.clientNums[ uiInfo.ignoreIndex ] );4211 trap_Cmd_ExecuteText( EXEC_NOW, va( "unignore %i\n",4212 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) );4213 }4214 }4215 } else if (Q_stricmp(name, "setPbClStatus") == 0) {4216 int stat;4217 if ( Int_Parse( args, &stat ) )4218 trap_SetPbClStatus( stat );4219 }4220 else {4221 Com_Printf("unknown UI script %s\n", name);4222 }4223 }4224 }4225 4226 static void UI_GetTeamColor(vec4_t *color) {4227 }4228 4229 /*4230 ==================4231 UI_MapCountByGameType4232 ==================4233 */4234 static int UI_MapCountByGameType(qboolean singlePlayer) {4235 int i, c, game;4236 c = 0;4237 game = singlePlayer ? uiInfo.gameTypes[ui_gameType.integer].gtEnum : uiInfo.gameTypes[ui_netGameType.integer].gtEnum;4238 4239 for (i = 0; i < uiInfo.mapCount; i++) {4240 uiInfo.mapList[i].active = qfalse;4241 if ( uiInfo.mapList[i].typeBits & (1 << game)) {4242 if (singlePlayer) {4243 if (!(uiInfo.mapList[i].typeBits & (1 << 2))) {4244 continue;4245 }4246 }4247 c++;4248 uiInfo.mapList[i].active = qtrue;4249 }4250 }4251 return c;4252 }4253 4254 qboolean UI_hasSkinForBase(const char *base, const char *team) {4255 char test[1024];4256 4257 Com_sprintf( test, sizeof( test ), "models/players/%s/%s/lower_default.skin", base, team );4258 4259 if (trap_FS_FOpenFile(test, NULL, FS_READ)) {4260 return qtrue;4261 }4262 Com_sprintf( test, sizeof( test ), "models/players/characters/%s/%s/lower_default.skin", base, team );4263 4264 if (trap_FS_FOpenFile(test, NULL, FS_READ)) {4265 return qtrue;4266 }4267 return qfalse;4268 }4269 4270 /*4271 ==================4272 UI_MapCountByTeam4273 ==================4274 */4275 static int UI_HeadCountByTeam( void ) {4276 static int init = 0;4277 int i, j, k, c, tIndex;4278 4279 c = 0;4280 if (!init) {4281 for (i = 0; i < uiInfo.characterCount; i++) {4282 uiInfo.characterList[i].reference = 0;4283 for (j = 0; j < uiInfo.teamCount; j++) {4284 if (UI_hasSkinForBase(uiInfo.characterList[i].base, uiInfo.teamList[j].teamName)) {4285 uiInfo.characterList[i].reference |= (1<<j);4286 }4287 }4288 }4289 init = 1;4290 }4291 4292 tIndex = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));4293 4294 // do names4295 for (i = 0; i < uiInfo.characterCount; i++) {4296 uiInfo.characterList[i].active = qfalse;4297 for(j = 0; j < TEAM_MEMBERS; j++) {4298 if (uiInfo.teamList[tIndex].teamMembers[j] != NULL) {4299 if (uiInfo.characterList[i].reference&(1<<tIndex)) {// && Q_stricmp(uiInfo.teamList[tIndex].teamMembers[j], uiInfo.characterList[i].name)==0) {4300 uiInfo.characterList[i].active = qtrue;4301 c++;4302 break;4303 }4304 }4305 }4306 }4307 4308 // and then aliases4309 for(j = 0; j < TEAM_MEMBERS; j++) {4310 for(k = 0; k < uiInfo.aliasCount; k++) {4311 if (uiInfo.aliasList[k].name != NULL) {4312 if (Q_stricmp(uiInfo.teamList[tIndex].teamMembers[j], uiInfo.aliasList[k].name)==0) {4313 for (i = 0; i < uiInfo.characterCount; i++) {4314 if (uiInfo.characterList[i].headImage != -1 && uiInfo.characterList[i].reference&(1<<tIndex) && Q_stricmp(uiInfo.aliasList[k].ai, uiInfo.characterList[i].name)==0) {4315 if (uiInfo.characterList[i].active == qfalse) {4316 uiInfo.characterList[i].active = qtrue;4317 c++;4318 }4319 break;4320 }4321 }4322 }4323 }4324 }4325 }4326 return c;4327 234 } 4328 235 … … 4332 239 ================== 4333 240 */ 4334 static void UI_InsertServerIntoDisplayList(int num, int position) { 241 static void UI_InsertServerIntoDisplayList( int num, int position ) 242 { 4335 243 int i; 4336 244 4337 if (position < 0 || position > uiInfo.serverStatus.numDisplayServers ) {245 if( position < 0 || position > uiInfo.serverStatus.numDisplayServers ) 4338 246 return; 4339 } 247 4340 248 // 4341 249 uiInfo.serverStatus.numDisplayServers++; 4342 for (i = uiInfo.serverStatus.numDisplayServers; i > position; i--) { 250 251 for( i = uiInfo.serverStatus.numDisplayServers; i > position; i-- ) 4343 252 uiInfo.serverStatus.displayServers[i] = uiInfo.serverStatus.displayServers[i-1]; 4344 } 253 4345 254 uiInfo.serverStatus.displayServers[position] = num; 4346 255 } … … 4351 260 ================== 4352 261 */ 4353 static void UI_RemoveServerFromDisplayList(int num) { 262 static void UI_RemoveServerFromDisplayList( int num ) 263 { 4354 264 int i, j; 4355 265 4356 for (i = 0; i < uiInfo.serverStatus.numDisplayServers; i++) { 4357 if (uiInfo.serverStatus.displayServers[i] == num) { 266 for( i = 0; i < uiInfo.serverStatus.numDisplayServers; i++ ) 267 { 268 if( uiInfo.serverStatus.displayServers[i] == num ) 269 { 4358 270 uiInfo.serverStatus.numDisplayServers--; 4359 for (j = i; j < uiInfo.serverStatus.numDisplayServers; j++) { 271 272 for( j = i; j < uiInfo.serverStatus.numDisplayServers; j++ ) 4360 273 uiInfo.serverStatus.displayServers[j] = uiInfo.serverStatus.displayServers[j+1]; 4361 } 274 4362 275 return; 4363 276 } … … 4370 283 ================== 4371 284 */ 4372 static void UI_BinaryServerInsertion(int num) { 285 static void UI_BinaryServerInsertion( int num ) 286 { 4373 287 int mid, offset, res, len; 4374 288 … … 4378 292 offset = 0; 4379 293 res = 0; 4380 while(mid > 0) { 294 295 while( mid > 0 ) 296 { 4381 297 mid = len >> 1; 4382 298 // 4383 299 res = trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey, 4384 uiInfo.serverStatus.sortDir, num, uiInfo.serverStatus.displayServers[offset+mid]);300 uiInfo.serverStatus.sortDir, num, uiInfo.serverStatus.displayServers[offset+mid] ); 4385 301 // if equal 4386 if (res == 0) { 4387 UI_InsertServerIntoDisplayList(num, offset+mid); 302 303 if( res == 0 ) 304 { 305 UI_InsertServerIntoDisplayList( num, offset + mid ); 4388 306 return; 4389 307 } 308 4390 309 // if larger 4391 else if (res == 1) { 310 else if( res == 1 ) 311 { 4392 312 offset += mid; 4393 313 len -= mid; 4394 314 } 315 4395 316 // if smaller 4396 else {317 else 4397 318 len -= mid; 4398 }4399 } 4400 if (res == 1) {319 } 320 321 if( res == 1 ) 4401 322 offset++; 4402 } 4403 UI_InsertServerIntoDisplayList(num, offset); 4404 } 4405 4406 /* 4407 ================== 4408 UI_BuildServerDisplayList 4409 ================== 4410 */ 4411 static void UI_BuildServerDisplayList(qboolean force) { 4412 int i, count, clients, maxClients, ping, game, len, visible; 4413 char info[MAX_STRING_CHARS]; 4414 static int numinvisible; 4415 4416 if (!(force || uiInfo.uiDC.realTime > uiInfo.serverStatus.nextDisplayRefresh)) { 4417 return; 4418 } 4419 // if we shouldn't reset 4420 if ( force == 2 ) { 4421 force = 0; 4422 } 4423 4424 // do motd updates here too 4425 trap_Cvar_VariableStringBuffer( "cl_motdString", uiInfo.serverStatus.motd, sizeof(uiInfo.serverStatus.motd) ); 4426 len = strlen(uiInfo.serverStatus.motd); 4427 if (len != uiInfo.serverStatus.motdLen) { 4428 uiInfo.serverStatus.motdLen = len; 4429 uiInfo.serverStatus.motdWidth = -1; 4430 } 4431 4432 if (force) { 4433 numinvisible = 0; 4434 // clear number of displayed servers 4435 uiInfo.serverStatus.numDisplayServers = 0; 4436 uiInfo.serverStatus.numPlayersOnServers = 0; 4437 // set list box index to zero 4438 Menu_SetFeederSelection(NULL, FEEDER_SERVERS, 0, NULL); 4439 // mark all servers as visible so we store ping updates for them 4440 trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue); 4441 } 4442 4443 // get the server count (comes from the master) 4444 count = trap_LAN_GetServerCount(ui_netSource.integer); 4445 if (count == -1 || (ui_netSource.integer == AS_LOCAL && count == 0) ) { 4446 // still waiting on a response from the master 4447 uiInfo.serverStatus.numDisplayServers = 0; 4448 uiInfo.serverStatus.numPlayersOnServers = 0; 4449 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 500; 4450 return; 4451 } 4452 4453 visible = qfalse; 4454 for (i = 0; i < count; i++) { 4455 // if we already got info for this server 4456 if (!trap_LAN_ServerIsVisible(ui_netSource.integer, i)) { 4457 continue; 4458 } 4459 visible = qtrue; 4460 // get the ping for this server 4461 ping = trap_LAN_GetServerPing(ui_netSource.integer, i); 4462 if (ping > 0 || ui_netSource.integer == AS_FAVORITES) { 4463 4464 trap_LAN_GetServerInfo(ui_netSource.integer, i, info, MAX_STRING_CHARS); 4465 4466 clients = atoi(Info_ValueForKey(info, "clients")); 4467 uiInfo.serverStatus.numPlayersOnServers += clients; 4468 4469 if (ui_browserShowEmpty.integer == 0) { 4470 if (clients == 0) { 4471 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse); 4472 continue; 4473 } 4474 } 4475 4476 if (ui_browserShowFull.integer == 0) { 4477 maxClients = atoi(Info_ValueForKey(info, "sv_maxclients")); 4478 if (clients == maxClients) { 4479 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse); 4480 continue; 4481 } 4482 } 4483 4484 if (uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum != -1) { 4485 game = atoi(Info_ValueForKey(info, "gametype")); 4486 if (game != uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum) { 4487 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse); 4488 continue; 4489 } 4490 } 4491 4492 // make sure we never add a favorite server twice 4493 if (ui_netSource.integer == AS_FAVORITES) { 4494 UI_RemoveServerFromDisplayList(i); 4495 } 4496 // insert the server into the list 4497 UI_BinaryServerInsertion(i); 4498 // done with this server 4499 if (ping > 0) { 4500 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse); 4501 numinvisible++; 4502 } 4503 } 4504 } 4505 4506 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime; 4507 4508 // if there were no servers visible for ping updates 4509 if (!visible) { 4510 // UI_StopServerRefresh(); 4511 // uiInfo.serverStatus.nextDisplayRefresh = 0; 4512 } 323 324 UI_InsertServerIntoDisplayList( num, offset ); 4513 325 } 4514 326 … … 4516 328 { 4517 329 char *name, *altName; 4518 } serverStatusCvar_t; 330 } 331 332 serverStatusCvar_t; 4519 333 4520 334 serverStatusCvar_t serverStatusCvars[] = { 4521 {"sv_hostname", "Name"}, 4522 {"Address", ""}, 4523 {"gamename", "Game name"}, 4524 {"g_gametype", "Game type"}, 4525 {"mapname", "Map"}, 4526 {"version", ""}, 4527 {"protocol", ""}, 4528 {"timelimit", ""}, 4529 {"fraglimit", ""}, 4530 {NULL, NULL} 4531 }; 335 {"sv_hostname", "Name"}, 336 {"Address", ""}, 337 {"gamename", "Game name"}, 338 {"mapname", "Map"}, 339 {"version", ""}, 340 {"protocol", ""}, 341 {"timelimit", ""}, 342 {NULL, NULL} 343 }; 4532 344 4533 345 /* … … 4536 348 ================== 4537 349 */ 4538 static void UI_SortServerStatusInfo( serverStatusInfo_t *info ) { 350 static void UI_SortServerStatusInfo( serverStatusInfo_t *info ) 351 { 4539 352 int i, j, index; 4540 353 char *tmp1, *tmp2; 4541 354 4542 // FIXME: if "gamename" == "baseq3" or "missionpack" then4543 // replace the gametype number by FFA, CTF etc.4544 //4545 355 index = 0; 4546 for (i = 0; serverStatusCvars[i].name; i++) { 4547 for (j = 0; j < info->numLines; j++) { 4548 if ( !info->lines[j][1] || info->lines[j][1][0] ) { 356 357 for( i = 0; serverStatusCvars[i].name; i++ ) 358 { 359 for( j = 0; j < info->numLines; j++ ) 360 { 361 if( !info->lines[j][1] || info->lines[j][1][0] ) 4549 362 continue; 4550 } 4551 if ( !Q_stricmp(serverStatusCvars[i].name, info->lines[j][0]) ) { 363 364 if( !Q_stricmp( serverStatusCvars[i].name, info->lines[j][0] ) ) 365 { 4552 366 // swap lines 4553 367 tmp1 = info->lines[index][0]; … … 4558 372 info->lines[j][3] = tmp2; 4559 373 // 4560 if ( strlen(serverStatusCvars[i].altName) ) { 374 375 if( strlen( serverStatusCvars[i].altName ) ) 4561 376 info->lines[index][0] = serverStatusCvars[i].altName; 4562 } 377 4563 378 index++; 4564 379 } … … 4572 387 ================== 4573 388 */ 4574 static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) { 4575 char *p, *score, *ping, *name; 389 static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) 390 { 391 char * p, *score, *ping, *name; 4576 392 int i, len; 4577 393 4578 if (!info) { 4579 trap_LAN_ServerStatus( serverAddress, NULL, 0); 394 if( !info ) 395 { 396 trap_LAN_ServerStatus( serverAddress, NULL, 0 ); 4580 397 return qfalse; 4581 398 } 4582 memset(info, 0, sizeof(*info)); 4583 if ( trap_LAN_ServerStatus( serverAddress, info->text, sizeof(info->text)) ) { 4584 Q_strncpyz(info->address, serverAddress, sizeof(info->address)); 399 400 memset( info, 0, sizeof( *info ) ); 401 402 if( trap_LAN_ServerStatus( serverAddress, info->text, sizeof( info->text ) ) ) 403 { 404 Q_strncpyz( info->address, serverAddress, sizeof( info->address ) ); 4585 405 p = info->text; 4586 406 info->numLines = 0; … … 4591 411 info->numLines++; 4592 412 // get the cvars 4593 while (p && *p) { 4594 p = strchr(p, '\\'); 4595 if (!p) break; 413 414 while( p && *p ) 415 { 416 p = strchr( p, '\\' ); 417 418 if( !p ) break; 419 4596 420 *p++ = '\0'; 4597 if (*p == '\\') 421 422 if( *p == '\\' ) 4598 423 break; 424 4599 425 info->lines[info->numLines][0] = p; 4600 426 info->lines[info->numLines][1] = ""; 4601 427 info->lines[info->numLines][2] = ""; 4602 p = strchr(p, '\\'); 4603 if (!p) break; 428 429 p = strchr( p, '\\' ); 430 431 if( !p ) break; 432 4604 433 *p++ = '\0'; 434 4605 435 info->lines[info->numLines][3] = p; 4606 4607 436 info->numLines++; 4608 if (info->numLines >= MAX_SERVERSTATUS_LINES) 437 438 if( info->numLines >= MAX_SERVERSTATUS_LINES ) 4609 439 break; 4610 440 } 441 4611 442 // get the player list 4612 if (info->numLines < MAX_SERVERSTATUS_LINES-3) { 443 if( info->numLines < MAX_SERVERSTATUS_LINES - 3 ) 444 { 4613 445 // empty line 4614 446 info->lines[info->numLines][0] = ""; … … 4626 458 i = 0; 4627 459 len = 0; 4628 while (p && *p) { 4629 if (*p == '\\') 4630 *p++ = '\0'; 4631 if (!p) 460 461 while( p && *p ) 462 { 463 if( *p == '\\' ) 464 * p++ = '\0'; 465 466 if( !p ) 4632 467 break; 468 4633 469 score = p; 4634 p = strchr(p, ' '); 4635 if (!p) 470 471 p = strchr( p, ' ' ); 472 473 if( !p ) 4636 474 break; 475 4637 476 *p++ = '\0'; 477 4638 478 ping = p; 4639 p = strchr(p, ' '); 4640 if (!p) 479 480 p = strchr( p, ' ' ); 481 482 if( !p ) 4641 483 break; 484 4642 485 *p++ = '\0'; 486 4643 487 name = p; 4644 Com_sprintf(&info->pings[len], sizeof(info->pings)-len, "%d", i); 488 489 Com_sprintf( &info->pings[len], sizeof( info->pings ) - len, "%d", i ); 490 4645 491 info->lines[info->numLines][0] = &info->pings[len]; 4646 len += strlen(&info->pings[len]) + 1; 492 493 len += strlen( &info->pings[len] ) + 1; 494 4647 495 info->lines[info->numLines][1] = score; 4648 496 info->lines[info->numLines][2] = ping; 4649 497 info->lines[info->numLines][3] = name; 4650 498 info->numLines++; 4651 if (info->numLines >= MAX_SERVERSTATUS_LINES) 499 500 if( info->numLines >= MAX_SERVERSTATUS_LINES ) 4652 501 break; 4653 p = strchr(p, '\\'); 4654 if (!p) 502 503 p = strchr( p, '\\' ); 504 505 if( !p ) 4655 506 break; 507 4656 508 *p++ = '\0'; 509 4657 510 // 4658 511 i++; 4659 512 } 4660 513 } 514 4661 515 UI_SortServerStatusInfo( info ); 4662 516 return qtrue; 4663 517 } 518 4664 519 return qfalse; 4665 520 } … … 4670 525 ================== 4671 526 */ 4672 static char *stristr(char *str, char *charset) { 527 static char *stristr( char *str, char *charset ) 528 { 4673 529 int i; 4674 530 4675 while(*str) { 4676 for (i = 0; charset[i] && str[i]; i++) { 4677 if (toupper(charset[i]) != toupper(str[i])) break; 4678 } 4679 if (!charset[i]) return str; 531 while( *str ) 532 { 533 for( i = 0; charset[i] && str[i]; i++ ) 534 if( toupper( charset[i] ) != toupper( str[i] ) ) break; 535 536 if( !charset[i] ) return str; 537 4680 538 str++; 4681 539 } 540 4682 541 return NULL; 4683 542 } … … 4688 547 ================== 4689 548 */ 4690 static void UI_BuildFindPlayerList(qboolean force) { 549 static void UI_FeederSelection( float feederID, int index ); 550 551 static void UI_BuildFindPlayerList( qboolean force ) 552 { 4691 553 static int numFound, numTimeOuts; 4692 int i, j, resend;554 int i, j, k, resend; 4693 555 serverStatusInfo_t info; 4694 556 char name[MAX_NAME_LENGTH+2]; 4695 557 char infoString[MAX_STRING_CHARS]; 4696 4697 if (!force) { 4698 if (!uiInfo.nextFindPlayerRefresh || uiInfo.nextFindPlayerRefresh > uiInfo.uiDC.realTime) { 558 qboolean duplicate; 559 560 if( !force ) 561 { 562 if( !uiInfo.nextFindPlayerRefresh || uiInfo.nextFindPlayerRefresh > uiInfo.uiDC.realTime ) 4699 563 return; 4700 }4701 }4702 else{4703 memset( &uiInfo.pendingServerStatus, 0, sizeof(uiInfo.pendingServerStatus));564 } 565 else 566 { 567 memset( &uiInfo.pendingServerStatus, 0, sizeof( uiInfo.pendingServerStatus ) ); 4704 568 uiInfo.numFoundPlayerServers = 0; 4705 569 uiInfo.currentFoundPlayerServer = 0; 4706 trap_Cvar_VariableStringBuffer( "ui_findPlayer", uiInfo.findPlayerName, sizeof( uiInfo.findPlayerName));4707 Q_CleanStr( uiInfo.findPlayerName);570 trap_Cvar_VariableStringBuffer( "ui_findPlayer", uiInfo.findPlayerName, sizeof( uiInfo.findPlayerName ) ); 571 Q_CleanStr( uiInfo.findPlayerName ); 4708 572 // should have a string of some length 4709 if (!strlen(uiInfo.findPlayerName)) { 573 574 if( !strlen( uiInfo.findPlayerName ) ) 575 { 4710 576 uiInfo.nextFindPlayerRefresh = 0; 4711 577 return; 4712 578 } 579 4713 580 // set resend time 4714 581 resend = ui_serverStatusTimeOut.integer / 2 - 10; 4715 if (resend < 50) { 582 583 if( resend < 50 ) 4716 584 resend = 50; 4717 } 4718 trap_Cvar_Set( "cl_serverStatusResendTime", va("%d", resend));585 586 trap_Cvar_Set( "cl_serverStatusResendTime", va( "%d", resend ) ); 4719 587 // reset all server status requests 4720 trap_LAN_ServerStatus( NULL, NULL, 0 );588 trap_LAN_ServerStatus( NULL, NULL, 0 ); 4721 589 // 4722 590 uiInfo.numFoundPlayerServers = 1; 4723 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],4724 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),4725 "searching %d...", uiInfo.pendingServerStatus.num);591 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 592 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1] ), 593 "searching %d...", uiInfo.pendingServerStatus.num ); 4726 594 numFound = 0; 4727 595 numTimeOuts++; 4728 596 } 4729 for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) { 597 598 for( i = 0; i < MAX_SERVERSTATUSREQUESTS; i++ ) 599 { 4730 600 // if this pending server is valid 4731 if (uiInfo.pendingServerStatus.server[i].valid) { 601 602 if( uiInfo.pendingServerStatus.server[i].valid ) 603 { 4732 604 // try to get the server status for this server 4733 if (UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, &info ) ) { 605 606 if( UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, &info ) ) 607 { 4734 608 // 4735 609 numFound++; 4736 610 // parse through the server status lines 4737 for (j = 0; j < info.numLines; j++) { 611 612 for( j = 0; j < info.numLines; j++ ) 613 { 4738 614 // should have ping info 4739 if ( !info.lines[j][2] || !info.lines[j][2][0] ) { 615 616 if( !info.lines[j][2] || !info.lines[j][2][0] ) 4740 617 continue; 618 619 // clean string first 620 Q_strncpyz( name, info.lines[j][3], sizeof( name ) ); 621 622 Q_CleanStr( name ); 623 624 duplicate = qfalse; 625 626 for( k = 0; k < uiInfo.numFoundPlayerServers - 1; k++ ) 627 { 628 if( Q_strncmp( uiInfo.foundPlayerServerAddresses[ k ], 629 uiInfo.pendingServerStatus.server[ i ].adrstr, 630 MAX_ADDRESSLENGTH ) == 0 ) 631 duplicate = qtrue; 4741 632 } 4742 // clean string first 4743 Q_strncpyz(name, info.lines[j][3], sizeof(name)); 4744 Q_CleanStr(name); 633 4745 634 // if the player name is a substring 4746 if (stristr(name, uiInfo.findPlayerName)) { 635 if( stristr( name, uiInfo.findPlayerName ) && !duplicate ) 636 { 4747 637 // add to found server list if we have space (always leave space for a line with the number found) 4748 if (uiInfo.numFoundPlayerServers < MAX_FOUNDPLAYER_SERVERS-1) { 638 639 if( uiInfo.numFoundPlayerServers < MAX_FOUNDPLAYER_SERVERS - 1 ) 640 { 4749 641 // 4750 Q_strncpyz( uiInfo.foundPlayerServerAddresses[uiInfo.numFoundPlayerServers-1],4751 uiInfo.pendingServerStatus.server[i].adrstr,4752 sizeof(uiInfo.foundPlayerServerAddresses[0]));4753 Q_strncpyz( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],4754 uiInfo.pendingServerStatus.server[i].name,4755 sizeof(uiInfo.foundPlayerServerNames[0]));642 Q_strncpyz( uiInfo.foundPlayerServerAddresses[uiInfo.numFoundPlayerServers-1], 643 uiInfo.pendingServerStatus.server[i].adrstr, 644 sizeof( uiInfo.foundPlayerServerAddresses[0] ) ); 645 Q_strncpyz( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 646 uiInfo.pendingServerStatus.server[i].name, 647 sizeof( uiInfo.foundPlayerServerNames[0] ) ); 4756 648 uiInfo.numFoundPlayerServers++; 4757 649 } 4758 else { 650 else 651 { 4759 652 // can't add any more so we're done 4760 653 uiInfo.pendingServerStatus.num = uiInfo.serverStatus.numDisplayServers; … … 4762 655 } 4763 656 } 4764 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 4765 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]), 4766 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound); 657 658 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 659 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1] ), 660 "searching %d/%d...", numFound, uiInfo.pendingServerStatus.num ); 4767 661 // retrieved the server status so reuse this spot 4768 662 uiInfo.pendingServerStatus.server[i].valid = qfalse; 4769 663 } 4770 664 } 665 4771 666 // if empty pending slot or timed out 4772 if (!uiInfo.pendingServerStatus.server[i].valid || 4773 uiInfo.pendingServerStatus.server[i].startTime < uiInfo.uiDC.realTime - ui_serverStatusTimeOut.integer) { 4774 if (uiInfo.pendingServerStatus.server[i].valid) { 667 if( !uiInfo.pendingServerStatus.server[i].valid || 668 uiInfo.pendingServerStatus.server[i].startTime < uiInfo.uiDC.realTime - ui_serverStatusTimeOut.integer ) 669 { 670 if( uiInfo.pendingServerStatus.server[i].valid ) 4775 671 numTimeOuts++; 4776 } 672 4777 673 // reset server status request for this address 4778 674 UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, NULL ); 675 4779 676 // reuse pending slot 4780 677 uiInfo.pendingServerStatus.server[i].valid = qfalse; 678 4781 679 // if we didn't try to get the status of all servers in the main browser yet 4782 if (uiInfo.pendingServerStatus.num < uiInfo.serverStatus.numDisplayServers) { 680 if( uiInfo.pendingServerStatus.num < uiInfo.serverStatus.numDisplayServers ) 681 { 4783 682 uiInfo.pendingServerStatus.server[i].startTime = uiInfo.uiDC.realTime; 4784 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], 4785 uiInfo.pendingServerStatus.server[i].adrstr, sizeof(uiInfo.pendingServerStatus.server[i].adrstr)); 4786 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], infoString, sizeof(infoString)); 4787 Q_strncpyz(uiInfo.pendingServerStatus.server[i].name, Info_ValueForKey(infoString, "hostname"), sizeof(uiInfo.pendingServerStatus.server[0].name)); 683 trap_LAN_GetServerAddressString( ui_netSource.integer, 684 uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], 685 uiInfo.pendingServerStatus.server[i].adrstr, 686 sizeof( uiInfo.pendingServerStatus.server[i].adrstr ) ); 687 688 trap_LAN_GetServerInfo( ui_netSource.integer, 689 uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], 690 infoString, sizeof( infoString ) ); 691 692 Q_strncpyz( uiInfo.pendingServerStatus.server[i].name, 693 Info_ValueForKey( infoString, "hostname" ), 694 sizeof( uiInfo.pendingServerStatus.server[0].name ) ); 695 4788 696 uiInfo.pendingServerStatus.server[i].valid = qtrue; 4789 697 uiInfo.pendingServerStatus.num++; 4790 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 4791 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]), 4792 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound); 4793 } 4794 } 4795 } 4796 for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) { 4797 if (uiInfo.pendingServerStatus.server[i].valid) { 698 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 699 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1] ), 700 "searching %d/%d...", numFound, uiInfo.pendingServerStatus.num ); 701 } 702 } 703 } 704 705 for( i = 0; i < MAX_SERVERSTATUSREQUESTS; i++ ) 706 { 707 if( uiInfo.pendingServerStatus.server[i].valid ) 4798 708 break; 4799 }4800 } 709 } 710 4801 711 // if still trying to retrieve server status info 4802 if (i < MAX_SERVERSTATUSREQUESTS) {712 if( i < MAX_SERVERSTATUSREQUESTS ) 4803 713 uiInfo.nextFindPlayerRefresh = uiInfo.uiDC.realTime + 25; 4804 }4805 else{714 else 715 { 4806 716 // add a line that shows the number of servers found 4807 if (!uiInfo.numFoundPlayerServers) { 4808 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]), "no servers found"); 4809 } 4810 else { 4811 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]), 4812 "%d server%s found with player %s", uiInfo.numFoundPlayerServers-1, 4813 uiInfo.numFoundPlayerServers == 2 ? "":"s", uiInfo.findPlayerName); 4814 } 717 718 if( !uiInfo.numFoundPlayerServers ) 719 { 720 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 721 sizeof( uiInfo.foundPlayerServerAddresses[0] ), "no servers found" ); 722 } 723 else 724 { 725 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], 726 sizeof( uiInfo.foundPlayerServerAddresses[0] ), 727 "%d server%s found with player %s", uiInfo.numFoundPlayerServers - 1, 728 uiInfo.numFoundPlayerServers == 2 ? "" : "s", uiInfo.findPlayerName ); 729 } 730 4815 731 uiInfo.nextFindPlayerRefresh = 0; 4816 732 // show the server status info for the selected server 4817 UI_FeederSelection( FEEDER_FINDPLAYER, uiInfo.currentFoundPlayerServer);733 UI_FeederSelection( FEEDER_FINDPLAYER, uiInfo.currentFoundPlayerServer ); 4818 734 } 4819 735 } … … 4824 740 ================== 4825 741 */ 4826 static void UI_BuildServerStatus( qboolean force) {4827 4828 if (uiInfo.nextFindPlayerRefresh) {742 static void UI_BuildServerStatus( qboolean force ) 743 { 744 if( uiInfo.nextFindPlayerRefresh ) 4829 745 return; 4830 } 4831 if (!force) { 4832 if (!uiInfo.nextServerStatusRefresh || uiInfo.nextServerStatusRefresh > uiInfo.uiDC.realTime) { 746 747 if( !force ) 748 { 749 if( !uiInfo.nextServerStatusRefresh || uiInfo.nextServerStatusRefresh > uiInfo.uiDC.realTime ) 4833 750 return; 4834 }4835 }4836 else{4837 Menu_SetFeederSelection( NULL, FEEDER_SERVERSTATUS, 0, NULL);751 } 752 else 753 { 754 Menu_SetFeederSelection( NULL, FEEDER_SERVERSTATUS, 0, NULL ); 4838 755 uiInfo.serverStatusInfo.numLines = 0; 4839 756 // reset all server status requests 4840 trap_LAN_ServerStatus( NULL, NULL, 0); 4841 } 4842 if (uiInfo.serverStatus.currentServer < 0 || uiInfo.serverStatus.currentServer > uiInfo.serverStatus.numDisplayServers || uiInfo.serverStatus.numDisplayServers == 0) { 757 trap_LAN_ServerStatus( NULL, NULL, 0 ); 758 } 759 760 if( uiInfo.serverStatus.currentServer < 0 || 761 uiInfo.serverStatus.currentServer > uiInfo.serverStatus.numDisplayServers || 762 uiInfo.serverStatus.numDisplayServers == 0 ) 4843 763 return; 4844 } 4845 if (UI_GetServerStatusInfo( uiInfo.serverStatusAddress, &uiInfo.serverStatusInfo ) ) { 764 765 if( UI_GetServerStatusInfo( uiInfo.serverStatusAddress, &uiInfo.serverStatusInfo ) ) 766 { 4846 767 uiInfo.nextServerStatusRefresh = 0; 4847 768 UI_GetServerStatusInfo( uiInfo.serverStatusAddress, NULL ); 4848 769 } 4849 else {770 else 4850 771 uiInfo.nextServerStatusRefresh = uiInfo.uiDC.realTime + 500; 772 } 773 774 /* 775 ================== 776 UI_BuildServerDisplayList 777 ================== 778 */ 779 static void UI_BuildServerDisplayList( qboolean force ) 780 { 781 int i, count, clients, maxClients, ping, len, visible; 782 char info[MAX_STRING_CHARS]; 783 static int numinvisible; 784 785 if( !( force || uiInfo.uiDC.realTime > uiInfo.serverStatus.nextDisplayRefresh ) ) 786 return; 787 788 // if we shouldn't reset 789 if( force == 2 ) 790 force = 0; 791 792 // do motd updates here too 793 trap_Cvar_VariableStringBuffer( "cl_motdString", uiInfo.serverStatus.motd, sizeof( uiInfo.serverStatus.motd ) ); 794 795 len = strlen( uiInfo.serverStatus.motd ); 796 797 if( len != uiInfo.serverStatus.motdLen ) 798 { 799 uiInfo.serverStatus.motdLen = len; 800 uiInfo.serverStatus.motdWidth = -1; 801 } 802 803 if( force ) 804 { 805 numinvisible = 0; 806 // clear number of displayed servers 807 uiInfo.serverStatus.numDisplayServers = 0; 808 uiInfo.serverStatus.numPlayersOnServers = 0; 809 // set list box index to zero 810 Menu_SetFeederSelection( NULL, FEEDER_SERVERS, 0, NULL ); 811 // mark all servers as visible so we store ping updates for them 812 trap_LAN_MarkServerVisible( ui_netSource.integer, -1, qtrue ); 813 } 814 815 // get the server count (comes from the master) 816 count = trap_LAN_GetServerCount( ui_netSource.integer ); 817 818 if( count == -1 || ( ui_netSource.integer == AS_LOCAL && count == 0 ) ) 819 { 820 // still waiting on a response from the master 821 uiInfo.serverStatus.numDisplayServers = 0; 822 uiInfo.serverStatus.numPlayersOnServers = 0; 823 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 500; 824 return; 825 } 826 827 visible = qfalse; 828 829 for( i = 0; i < count; i++ ) 830 { 831 // if we already got info for this server 832 833 if( !trap_LAN_ServerIsVisible( ui_netSource.integer, i ) ) 834 continue; 835 836 visible = qtrue; 837 // get the ping for this server 838 ping = trap_LAN_GetServerPing( ui_netSource.integer, i ); 839 840 if( ping > 0 || ui_netSource.integer == AS_FAVORITES ) 841 { 842 trap_LAN_GetServerInfo( ui_netSource.integer, i, info, MAX_STRING_CHARS ); 843 844 clients = atoi( Info_ValueForKey( info, "clients" ) ); 845 uiInfo.serverStatus.numPlayersOnServers += clients; 846 847 if( ui_browserShowEmpty.integer == 0 ) 848 { 849 if( clients == 0 ) 850 { 851 trap_LAN_MarkServerVisible( ui_netSource.integer, i, qfalse ); 852 continue; 853 } 854 } 855 856 if( ui_browserShowFull.integer == 0 ) 857 { 858 maxClients = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); 859 860 if( clients == maxClients ) 861 { 862 trap_LAN_MarkServerVisible( ui_netSource.integer, i, qfalse ); 863 continue; 864 } 865 } 866 867 // make sure we never add a favorite server twice 868 if( ui_netSource.integer == AS_FAVORITES ) 869 UI_RemoveServerFromDisplayList( i ); 870 871 // insert the server into the list 872 UI_BinaryServerInsertion( i ); 873 874 // done with this server 875 if( ping > 0 ) 876 { 877 trap_LAN_MarkServerVisible( ui_netSource.integer, i, qfalse ); 878 numinvisible++; 879 } 880 } 881 } 882 883 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime; 884 885 // if there were no servers visible for ping updates 886 887 if( !visible ) 888 { 889 // UI_StopServerRefresh(); 890 // uiInfo.serverStatus.nextDisplayRefresh = 0; 891 } 892 } 893 894 895 /* 896 ================= 897 UI_StopServerRefresh 898 ================= 899 */ 900 static void UI_StopServerRefresh( void ) 901 { 902 int count; 903 904 if( !uiInfo.serverStatus.refreshActive ) 905 { 906 // not currently refreshing 907 return; 908 } 909 910 uiInfo.serverStatus.refreshActive = qfalse; 911 Com_Printf( "%d servers listed in browser with %d players.\n", 912 uiInfo.serverStatus.numDisplayServers, 913 uiInfo.serverStatus.numPlayersOnServers ); 914 count = trap_LAN_GetServerCount( ui_netSource.integer ); 915 916 if( count - uiInfo.serverStatus.numDisplayServers > 0 ) 917 { 918 Com_Printf( "%d servers not listed due to packet loss or pings higher than %d\n", 919 count - uiInfo.serverStatus.numDisplayServers, 920 ( int ) trap_Cvar_VariableValue( "cl_maxPing" ) ); 921 } 922 923 } 924 925 /* 926 ================= 927 UI_DoServerRefresh 928 ================= 929 */ 930 static void UI_DoServerRefresh( void ) 931 { 932 qboolean wait = qfalse; 933 934 if( !uiInfo.serverStatus.refreshActive ) 935 return; 936 937 if( ui_netSource.integer != AS_FAVORITES ) 938 { 939 if( ui_netSource.integer == AS_LOCAL ) 940 { 941 if( !trap_LAN_GetServerCount( ui_netSource.integer ) ) 942 wait = qtrue; 943 } 944 else 945 { 946 if( trap_LAN_GetServerCount( ui_netSource.integer ) < 0 ) 947 wait = qtrue; 948 } 949 } 950 951 if( uiInfo.uiDC.realTime < uiInfo.serverStatus.refreshtime ) 952 { 953 if( wait ) 954 return; 955 } 956 957 // if still trying to retrieve pings 958 if( trap_LAN_UpdateVisiblePings( ui_netSource.integer ) ) 959 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 960 else if( !wait ) 961 { 962 // get the last servers in the list 963 UI_BuildServerDisplayList( 2 ); 964 // stop the refresh 965 UI_StopServerRefresh(); 966 } 967 968 // 969 UI_BuildServerDisplayList( qfalse ); 970 } 971 972 /* 973 ================= 974 UI_UpdatePendingPings 975 ================= 976 */ 977 static void UI_UpdatePendingPings( void ) 978 { 979 trap_LAN_ResetPings( ui_netSource.integer ); 980 uiInfo.serverStatus.refreshActive = qtrue; 981 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 982 983 } 984 985 /* 986 ================= 987 UI_StartServerRefresh 988 ================= 989 */ 990 static void UI_StartServerRefresh( qboolean full ) 991 { 992 int i; 993 char *ptr; 994 int time; 995 qtime_t q; 996 997 time = trap_RealTime( &q ); 998 trap_Cvar_Set( va( "ui_lastServerRefresh_%i_time", ui_netSource.integer ), 999 va( "%i", time ) ); 1000 trap_Cvar_Set( va( "ui_lastServerRefresh_%i", ui_netSource.integer ), 1001 va( "%s-%i, %i at %i:%02i", MonthAbbrev[q.tm_mon], 1002 q.tm_mday, 1900 + q.tm_year, q.tm_hour, q.tm_min ) ); 1003 1004 if( !full ) 1005 { 1006 UI_UpdatePendingPings(); 1007 return; 1008 } 1009 1010 uiInfo.serverStatus.refreshActive = qtrue; 1011 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 1000; 1012 // clear number of displayed servers 1013 uiInfo.serverStatus.numDisplayServers = 0; 1014 uiInfo.serverStatus.numPlayersOnServers = 0; 1015 // mark all servers as visible so we store ping updates for them 1016 trap_LAN_MarkServerVisible( ui_netSource.integer, -1, qtrue ); 1017 // reset all the pings 1018 trap_LAN_ResetPings( ui_netSource.integer ); 1019 // 1020 1021 if( ui_netSource.integer == AS_LOCAL ) 1022 { 1023 trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" ); 1024 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 1025 return; 1026 } 1027 1028 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000; 1029 1030 if( ui_netSource.integer == AS_GLOBAL || ui_netSource.integer == AS_MPLAYER ) 1031 { 1032 if( ui_netSource.integer == AS_GLOBAL ) 1033 i = 0; 1034 else 1035 i = 1; 1036 1037 ptr = UI_Cvar_VariableString( "debug_protocol" ); 1038 1039 if( strlen( ptr ) ) 1040 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s full empty\n", i, ptr ) ); 1041 else 1042 { 1043 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d full empty\n", i, 1044 (int)trap_Cvar_VariableValue( "protocol" ) ) ); 1045 } 1046 } 1047 } 1048 1049 int frameCount = 0; 1050 int startTime; 1051 1052 #define UI_FPS_FRAMES 4 1053 void UI_Refresh( int realtime ) 1054 { 1055 static int index; 1056 static int previousTimes[UI_FPS_FRAMES]; 1057 1058 //if( !( trap_Key_GetCatcher() & KEYCATCH_UI ) ) { 1059 // return; 1060 //} 1061 1062 uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime; 1063 uiInfo.uiDC.realTime = realtime; 1064 1065 previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime; 1066 index++; 1067 1068 if( index > UI_FPS_FRAMES ) 1069 { 1070 int i, total; 1071 // average multiple frames together to smooth changes out a bit 1072 total = 0; 1073 1074 for( i = 0 ; i < UI_FPS_FRAMES ; i++ ) 1075 total += previousTimes[i]; 1076 1077 if( !total ) 1078 total = 1; 1079 1080 uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total; 1081 } 1082 1083 UI_UpdateCvars(); 1084 1085 if( Menu_Count() > 0 ) 1086 { 1087 // paint all the menus 1088 Menu_PaintAll(); 1089 // refresh server browser list 1090 UI_DoServerRefresh(); 1091 // refresh server status 1092 UI_BuildServerStatus( qfalse ); 1093 // refresh find player list 1094 UI_BuildFindPlayerList( qfalse ); 1095 } 1096 1097 // draw cursor 1098 UI_SetColor( NULL ); 1099 1100 if( Menu_Count( ) > 0 && !trap_Cvar_VariableValue( "ui_hideCursor" ) ) 1101 { 1102 UI_DrawHandlePic( uiInfo.uiDC.cursorx - ( 16.0f * uiInfo.uiDC.aspectScale ), uiInfo.uiDC.cursory - 16.0f, 1103 32.0f * uiInfo.uiDC.aspectScale, 32.0f, uiInfo.uiDC.Assets.cursor ); 1104 } 1105 } 1106 1107 /* 1108 ================= 1109 UI_Shutdown 1110 ================= 1111 */ 1112 void UI_Shutdown( void ) 1113 { 1114 trap_LAN_SaveCachedServers(); 1115 } 1116 1117 qboolean Asset_Parse( int handle ) 1118 { 1119 pc_token_t token; 1120 const char *tempStr; 1121 1122 if( !trap_Parse_ReadToken( handle, &token ) ) 1123 return qfalse; 1124 1125 if( Q_stricmp( token.string, "{" ) != 0 ) 1126 return qfalse; 1127 1128 while( 1 ) 1129 { 1130 memset( &token, 0, sizeof( pc_token_t ) ); 1131 1132 if( !trap_Parse_ReadToken( handle, &token ) ) 1133 return qfalse; 1134 1135 if( Q_stricmp( token.string, "}" ) == 0 ) 1136 return qtrue; 1137 1138 // font 1139 if( Q_stricmp( token.string, "font" ) == 0 ) 1140 { 1141 int pointSize; 1142 1143 if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) 1144 return qfalse; 1145 1146 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.textFont ); 1147 uiInfo.uiDC.Assets.fontRegistered = qtrue; 1148 continue; 1149 } 1150 1151 if( Q_stricmp( token.string, "smallFont" ) == 0 ) 1152 { 1153 int pointSize; 1154 1155 if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) 1156 return qfalse; 1157 1158 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.smallFont ); 1159 continue; 1160 } 1161 1162 if( Q_stricmp( token.string, "bigFont" ) == 0 ) 1163 { 1164 int pointSize; 1165 1166 if( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle, &pointSize ) ) 1167 return qfalse; 1168 1169 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.bigFont ); 1170 continue; 1171 } 1172 1173 1174 // gradientbar 1175 if( Q_stricmp( token.string, "gradientbar" ) == 0 ) 1176 { 1177 if( !PC_String_Parse( handle, &tempStr ) ) 1178 return qfalse; 1179 1180 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( tempStr ); 1181 continue; 1182 } 1183 1184 // enterMenuSound 1185 if( Q_stricmp( token.string, "menuEnterSound" ) == 0 ) 1186 { 1187 if( !PC_String_Parse( handle, &tempStr ) ) 1188 return qfalse; 1189 1190 uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse ); 1191 continue; 1192 } 1193 1194 // exitMenuSound 1195 if( Q_stricmp( token.string, "menuExitSound" ) == 0 ) 1196 { 1197 if( !PC_String_Parse( handle, &tempStr ) ) 1198 return qfalse; 1199 1200 uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse ); 1201 continue; 1202 } 1203 1204 // itemFocusSound 1205 if( Q_stricmp( token.string, "itemFocusSound" ) == 0 ) 1206 { 1207 if( !PC_String_Parse( handle, &tempStr ) ) 1208 return qfalse; 1209 1210 uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse ); 1211 continue; 1212 } 1213 1214 // menuBuzzSound 1215 if( Q_stricmp( token.string, "menuBuzzSound" ) == 0 ) 1216 { 1217 if( !PC_String_Parse( handle, &tempStr ) ) 1218 return qfalse; 1219 1220 uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse ); 1221 continue; 1222 } 1223 1224 if( Q_stricmp( token.string, "cursor" ) == 0 ) 1225 { 1226 if( !PC_String_Parse( handle, &uiInfo.uiDC.Assets.cursorStr ) ) 1227 return qfalse; 1228 1229 uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr ); 1230 continue; 1231 } 1232 1233 if( Q_stricmp( token.string, "fadeClamp" ) == 0 ) 1234 { 1235 if( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.fadeClamp ) ) 1236 return qfalse; 1237 1238 continue; 1239 } 1240 1241 if( Q_stricmp( token.string, "fadeCycle" ) == 0 ) 1242 { 1243 if( !PC_Int_Parse( handle, &uiInfo.uiDC.Assets.fadeCycle ) ) 1244 return qfalse; 1245 1246 continue; 1247 } 1248 1249 if( Q_stricmp( token.string, "fadeAmount" ) == 0 ) 1250 { 1251 if( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.fadeAmount ) ) 1252 return qfalse; 1253 1254 continue; 1255 } 1256 1257 if( Q_stricmp( token.string, "shadowX" ) == 0 ) 1258 { 1259 if( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.shadowX ) ) 1260 return qfalse; 1261 1262 continue; 1263 } 1264 1265 if( Q_stricmp( token.string, "shadowY" ) == 0 ) 1266 { 1267 if( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.shadowY ) ) 1268 return qfalse; 1269 1270 continue; 1271 } 1272 1273 if( Q_stricmp( token.string, "shadowColor" ) == 0 ) 1274 { 1275 if( !PC_Color_Parse( handle, &uiInfo.uiDC.Assets.shadowColor ) ) 1276 return qfalse; 1277 1278 uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3]; 1279 continue; 1280 } 1281 1282 } 1283 1284 return qfalse; 1285 } 1286 1287 void UI_Report( void ) 1288 { 1289 String_Report(); 1290 } 1291 1292 void UI_ParseMenu( const char *menuFile ) 1293 { 1294 int handle; 1295 pc_token_t token; 1296 1297 handle = trap_Parse_LoadSource( menuFile ); 1298 1299 if( !handle ) 1300 return; 1301 1302 while( 1 ) 1303 { 1304 memset( &token, 0, sizeof( pc_token_t ) ); 1305 1306 if( !trap_Parse_ReadToken( handle, &token ) ) 1307 break; 1308 1309 //if( Q_stricmp( token, "{" ) ) { 1310 // Com_Printf( "Missing { in menu file\n" ); 1311 // break; 1312 //} 1313 1314 //if( menuCount == MAX_MENUS ) { 1315 // Com_Printf( "Too many menus!\n" ); 1316 // break; 1317 //} 1318 1319 if( token.string[0] == '}' ) 1320 break; 1321 1322 if( Q_stricmp( token.string, "assetGlobalDef" ) == 0 ) 1323 { 1324 if( Asset_Parse( handle ) ) 1325 continue; 1326 else 1327 break; 1328 } 1329 1330 if( Q_stricmp( token.string, "menudef" ) == 0 ) 1331 { 1332 // start a new menu 1333 Menu_New( handle ); 1334 } 1335 } 1336 1337 trap_Parse_FreeSource( handle ); 1338 } 1339 1340 qboolean Load_Menu( int handle ) 1341 { 1342 pc_token_t token; 1343 1344 if( !trap_Parse_ReadToken( handle, &token ) ) 1345 return qfalse; 1346 1347 if( token.string[0] != '{' ) 1348 return qfalse; 1349 1350 while( 1 ) 1351 { 1352 if( !trap_Parse_ReadToken( handle, &token ) ) 1353 return qfalse; 1354 1355 if( token.string[0] == 0 ) 1356 return qfalse; 1357 1358 if( token.string[0] == '}' ) 1359 return qtrue; 1360 1361 UI_ParseMenu( token.string ); 1362 } 1363 1364 return qfalse; 1365 } 1366 1367 void UI_LoadMenus( const char *menuFile, qboolean reset ) 1368 { 1369 pc_token_t token; 1370 int handle; 1371 int start; 1372 1373 start = trap_Milliseconds(); 1374 1375 handle = trap_Parse_LoadSource( menuFile ); 1376 1377 if( !handle ) 1378 trap_Error( va( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!\n" ) ); 1379 1380 if( reset ) 1381 Menu_Reset(); 1382 1383 while( 1 ) 1384 { 1385 if( !trap_Parse_ReadToken( handle, &token ) ) 1386 break; 1387 1388 if( token.string[0] == 0 || token.string[0] == '}' ) 1389 break; 1390 1391 if( token.string[0] == '}' ) 1392 break; 1393 1394 if( Q_stricmp( token.string, "loadmenu" ) == 0 ) 1395 { 1396 if( Load_Menu( handle ) ) 1397 continue; 1398 else 1399 break; 1400 } 1401 } 1402 1403 Com_Printf( "UI menu load time = %d milli seconds\n", trap_Milliseconds() - start ); 1404 1405 trap_Parse_FreeSource( handle ); 1406 } 1407 1408 void UI_Load( void ) 1409 { 1410 char lastName[1024]; 1411 menuDef_t *menu = Menu_GetFocused(); 1412 1413 if( menu && menu->window.name ) 1414 strcpy( lastName, menu->window.name ); 1415 1416 String_Init(); 1417 1418 UI_LoadMenus( "ui/menus.txt", qtrue ); 1419 UI_LoadMenus( "ui/ingame.txt", qfalse ); 1420 UI_LoadMenus( "ui/tremulous.txt", qfalse ); 1421 Menus_CloseAll(); 1422 Menus_ActivateByName( lastName ); 1423 1424 } 1425 1426 /* 1427 =============== 1428 UI_DrawInfoPane 1429 =============== 1430 */ 1431 static void UI_DrawInfoPane( menuItem_t *item, rectDef_t *rect, float text_x, float text_y, 1432 float scale, int textalign, int textvalign, vec4_t color, int textStyle ) 1433 { 1434 int value = 0; 1435 const char *s = ""; 1436 char *string = ""; 1437 1438 int class, credits; 1439 char ui_currentClass[ MAX_STRING_CHARS ]; 1440 1441 trap_Cvar_VariableStringBuffer( "ui_currentClass", ui_currentClass, MAX_STRING_CHARS ); 1442 1443 sscanf( ui_currentClass, "%d %d", &class, &credits ); 1444 1445 switch( item->type ) 1446 { 1447 case INFOTYPE_TEXT: 1448 s = item->v.text; 1449 break; 1450 1451 case INFOTYPE_CLASS: 1452 value = BG_ClassCanEvolveFromTo( class, item->v.pclass, credits, 0 ); 1453 1454 if( value < 1 ) 1455 { 1456 s = va( "%s\n\n%s", 1457 BG_FindHumanNameForClassNum( item->v.pclass ), 1458 BG_FindInfoForClassNum( item->v.pclass ) ); 1459 } 1460 else 1461 { 1462 s = va( "%s\n\n%s\n\nKills: %d", 1463 BG_FindHumanNameForClassNum( item->v.pclass ), 1464 BG_FindInfoForClassNum( item->v.pclass ), 1465 value ); 1466 } 1467 1468 break; 1469 1470 case INFOTYPE_WEAPON: 1471 value = BG_FindPriceForWeapon( item->v.weapon ); 1472 1473 if( value == 0 ) 1474 { 1475 s = va( "%s\n\n%s\n\nCredits: Free", 1476 BG_FindHumanNameForWeapon( item->v.weapon ), 1477 BG_FindInfoForWeapon( item->v.weapon ) ); 1478 } 1479 else 1480 { 1481 s = va( "%s\n\n%s\n\nCredits: %d", 1482 BG_FindHumanNameForWeapon( item->v.weapon ), 1483 BG_FindInfoForWeapon( item->v.weapon ), 1484 value ); 1485 } 1486 1487 break; 1488 1489 case INFOTYPE_UPGRADE: 1490 value = BG_FindPriceForUpgrade( item->v.upgrade ); 1491 1492 if( value == 0 ) 1493 { 1494 s = va( "%s\n\n%s\n\nCredits: Free", 1495 BG_FindHumanNameForUpgrade( item->v.upgrade ), 1496 BG_FindInfoForUpgrade( item->v.upgrade ) ); 1497 } 1498 else 1499 { 1500 s = va( "%s\n\n%s\n\nCredits: %d", 1501 BG_FindHumanNameForUpgrade( item->v.upgrade ), 1502 BG_FindInfoForUpgrade( item->v.upgrade ), 1503 value ); 1504 } 1505 1506 break; 1507 1508 case INFOTYPE_BUILDABLE: 1509 value = BG_FindBuildPointsForBuildable( item->v.buildable ); 1510 1511 switch( BG_FindTeamForBuildable( item->v.buildable ) ) 1512 { 1513 case BIT_ALIENS: 1514 string = "Sentience"; 1515 break; 1516 1517 case BIT_HUMANS: 1518 string = "Power"; 1519 break; 1520 1521 default: 1522 break; 1523 } 1524 1525 if( value == 0 ) 1526 { 1527 s = va( "%s\n\n%s", 1528 BG_FindHumanNameForBuildable( item->v.buildable ), 1529 BG_FindInfoForBuildable( item->v.buildable ) ); 1530 } 1531 else 1532 { 1533 s = va( "%s\n\n%s\n\n%s: %d", 1534 BG_FindHumanNameForBuildable( item->v.buildable ), 1535 BG_FindInfoForBuildable( item->v.buildable ), 1536 string, value ); 1537 } 1538 1539 break; 1540 } 1541 1542 UI_DrawTextBlock( rect, text_x, text_y, color, scale, 1543 textalign, textvalign, textStyle, s ); 1544 } 1545 1546 1547 static void UI_DrawServerMapPreview( rectDef_t *rect, float scale, vec4_t color ) 1548 { 1549 if( uiInfo.serverStatus.currentServerCinematic >= 0 ) 1550 { 1551 trap_CIN_RunCinematic( uiInfo.serverStatus.currentServerCinematic ); 1552 trap_CIN_SetExtents( uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h ); 1553 trap_CIN_DrawCinematic( uiInfo.serverStatus.currentServerCinematic ); 1554 } 1555 else if( uiInfo.serverStatus.currentServerPreview > 0 ) 1556 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.serverStatus.currentServerPreview ); 1557 else 1558 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip( "gfx/2d/load_screen" ) ); 1559 } 1560 1561 static void UI_DrawSelectedMapPreview( rectDef_t *rect, float scale, vec4_t color ) 1562 { 1563 int map = ui_selectedMap.integer; 1564 1565 if( map < 0 || map > uiInfo.mapCount ) 1566 { 1567 ui_selectedMap.integer = 0; 1568 trap_Cvar_Set( "ui_selectedMap", "0" ); 1569 map = 0; 1570 } 1571 1572 if( uiInfo.mapList[map].cinematic >= -1 ) 1573 { 1574 if( uiInfo.mapList[map].cinematic == -1 ) 1575 uiInfo.mapList[map].cinematic = trap_CIN_PlayCinematic( va( "%s.roq", uiInfo.mapList[map].mapLoadName ), 1576 0, 0, 0, 0, ( CIN_loop | CIN_silent ) ); 1577 1578 if( uiInfo.mapList[map].cinematic >= 0 ) 1579 { 1580 trap_CIN_RunCinematic( uiInfo.mapList[map].cinematic ); 1581 trap_CIN_SetExtents( uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h ); 1582 trap_CIN_DrawCinematic( uiInfo.mapList[map].cinematic ); 1583 } 1584 else 1585 uiInfo.mapList[map].cinematic = -2; 1586 } 1587 else 1588 { 1589 if( uiInfo.mapList[map].levelShot == -1 ) 1590 uiInfo.mapList[map].levelShot = trap_R_RegisterShaderNoMip( uiInfo.mapList[map].imageName ); 1591 1592 if( uiInfo.mapList[map].levelShot > 0 ) 1593 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.mapList[map].levelShot ); 1594 else 1595 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip( "gfx/2d/load_screen" ) ); 1596 } 1597 } 1598 1599 static void UI_DrawSelectedMapName( rectDef_t *rect, float scale, vec4_t color, int textStyle ) 1600 { 1601 int map = ui_selectedMap.integer; 1602 1603 if( map >= 0 && map < uiInfo.mapCount ) 1604 UI_Text_Paint( rect->x, rect->y, scale, color, uiInfo.mapList[map].mapName, 0, 0, textStyle ); 1605 } 1606 1607 static const char *UI_OwnerDrawText( int ownerDraw ) 1608 { 1609 const char * s = NULL; 1610 1611 switch( ownerDraw ) 1612 { 1613 case UI_NETSOURCE: 1614 if( ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources ) 1615 ui_netSource.integer = 0; 1616 1617 s = netSources[ui_netSource.integer]; 1618 break; 1619 1620 case UI_KEYBINDSTATUS: 1621 if( Display_KeyBindPending() ) 1622 s = "Waiting for new key... Press ESCAPE to cancel"; 1623 else 1624 s = "Press ENTER or CLICK to change, Press BACKSPACE to clear"; 1625 1626 break; 1627 1628 case UI_SERVERREFRESHDATE: 1629 if( uiInfo.serverStatus.refreshActive ) 1630 { 1631 #define MAX_DOTS 5 1632 int numServers = trap_LAN_GetServerCount( ui_netSource.integer ); 1633 int numDots = ( uiInfo.uiDC.realTime / 500 ) % ( MAX_DOTS + 1 ); 1634 char dots[ MAX_DOTS + 1 ]; 1635 int i; 1636 1637 for( i = 0; i < numDots; i++ ) 1638 dots[ i ] = '.'; 1639 1640 dots[ i ] = '\0'; 1641 1642 s = numServers < 0 ? va( "Waiting for response%s", dots ) : 1643 va( "Getting info for %d servers (ESC to cancel)%s", numServers, dots ); 1644 } 1645 else 1646 s = va( "Refresh Time: %s", UI_Cvar_VariableString( va( "ui_lastServerRefresh_%i", ui_netSource.integer ) ) ); 1647 1648 break; 1649 1650 case UI_SERVERMOTD: 1651 s = uiInfo.serverStatus.motd; 1652 break; 1653 1654 default: 1655 break; 1656 } 1657 1658 return s; 1659 } 1660 1661 static int UI_OwnerDrawWidth( int ownerDraw, float scale ) 1662 { 1663 const char * s = NULL; 1664 1665 switch( ownerDraw ) 1666 { 1667 case UI_NETSOURCE: 1668 case UI_KEYBINDSTATUS: 1669 case UI_SERVERREFRESHDATE: 1670 case UI_SERVERMOTD: 1671 s = UI_OwnerDrawText( ownerDraw ); 1672 break; 1673 1674 default: 1675 break; 1676 } 1677 1678 if( s ) 1679 return UI_Text_Width( s, scale, 0 ); 1680 1681 return 0; 1682 } 1683 1684 /* 1685 =============== 1686 UI_BuildPlayerList 1687 =============== 1688 */ 1689 static void UI_BuildPlayerList( void ) 1690 { 1691 uiClientState_t cs; 1692 int n, count, team, team2, playerTeamNumber; 1693 char info[MAX_INFO_STRING]; 1694 1695 trap_GetClientState( &cs ); 1696 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING ); 1697 uiInfo.playerNumber = cs.clientNum; 1698 team = atoi( Info_ValueForKey( info, "t" ) ); 1699 trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ); 1700 count = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); 1701 uiInfo.playerCount = 0; 1702 uiInfo.myTeamCount = 0; 1703 uiInfo.myPlayerIndex = 0; 1704 playerTeamNumber = 0; 1705 1706 for( n = 0; n < count; n++ ) 1707 { 1708 trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING ); 1709 1710 if( info[0] ) 1711 { 1712 BG_ClientListParse( &uiInfo.ignoreList[ uiInfo.playerCount ], 1713 Info_ValueForKey( info, "ig" ) ); 1714 Q_strncpyz( uiInfo.rawPlayerNames[uiInfo.playerCount], 1715 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); 1716 Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], 1717 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); 1718 Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] ); 1719 uiInfo.clientNums[uiInfo.playerCount] = n; 1720 1721 if( n == uiInfo.playerNumber ) 1722 uiInfo.myPlayerIndex = uiInfo.playerCount; 1723 1724 uiInfo.playerCount++; 1725 1726 team2 = atoi( Info_ValueForKey( info, "t" ) ); 1727 1728 if( team2 == team ) 1729 { 1730 Q_strncpyz( uiInfo.rawTeamNames[uiInfo.myTeamCount], 1731 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); 1732 Q_strncpyz( uiInfo.teamNames[uiInfo.myTeamCount], 1733 Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH ); 1734 Q_CleanStr( uiInfo.teamNames[uiInfo.myTeamCount] ); 1735 uiInfo.teamClientNums[uiInfo.myTeamCount] = n; 1736 1737 if( uiInfo.playerNumber == n ) 1738 playerTeamNumber = uiInfo.myTeamCount; 1739 1740 uiInfo.myTeamCount++; 1741 } 1742 } 1743 } 1744 } 1745 1746 static void UI_DrawGLInfo( rectDef_t *rect, float scale, int textalign, int textvalign, 1747 vec4_t color, int textStyle, float text_x, float text_y ) 1748 { 1749 char buffer[ 4096 ]; 1750 1751 Com_sprintf( buffer, sizeof( buffer ), "VENDOR: %s\nVERSION: %s\n" 1752 "PIXELFORMAT: color(%d-bits) Z(%d-bits) stencil(%d-bits)\n%s", 1753 uiInfo.uiDC.glconfig.vendor_string, uiInfo.uiDC.glconfig.renderer_string, 1754 uiInfo.uiDC.glconfig.colorBits, uiInfo.uiDC.glconfig.depthBits, 1755 uiInfo.uiDC.glconfig.stencilBits, uiInfo.uiDC.glconfig.extensions_string ); 1756 1757 UI_DrawTextBlock( rect, text_x, text_y, color, scale, 1758 textalign, textvalign, textStyle, buffer ); 1759 } 1760 1761 // FIXME: table drive 1762 // 1763 static void UI_OwnerDraw( float x, float y, float w, float h, 1764 float text_x, float text_y, int ownerDraw, 1765 int ownerDrawFlags, int align, 1766 int textalign, int textvalign, float special, 1767 float scale, vec4_t color, qhandle_t shader, int textStyle ) 1768 { 1769 rectDef_t rect; 1770 1771 rect.x = x; 1772 rect.y = y; 1773 rect.w = w; 1774 rect.h = h; 1775 1776 switch( ownerDraw ) 1777 { 1778 case UI_TEAMINFOPANE: 1779 UI_DrawInfoPane( &uiInfo.teamList[ uiInfo.teamIndex ], 1780 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1781 break; 1782 1783 case UI_ACLASSINFOPANE: 1784 UI_DrawInfoPane( &uiInfo.alienClassList[ uiInfo.alienClassIndex ], 1785 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1786 break; 1787 1788 case UI_AUPGRADEINFOPANE: 1789 UI_DrawInfoPane( &uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ], 1790 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1791 break; 1792 1793 case UI_HITEMINFOPANE: 1794 UI_DrawInfoPane( &uiInfo.humanItemList[ uiInfo.humanItemIndex ], 1795 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1796 break; 1797 1798 case UI_HBUYINFOPANE: 1799 UI_DrawInfoPane( &uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ], 1800 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1801 break; 1802 1803 case UI_HSELLINFOPANE: 1804 UI_DrawInfoPane( &uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ], 1805 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1806 break; 1807 1808 case UI_ABUILDINFOPANE: 1809 UI_DrawInfoPane( &uiInfo.alienBuildList[ uiInfo.alienBuildIndex ], 1810 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1811 break; 1812 1813 case UI_HBUILDINFOPANE: 1814 UI_DrawInfoPane( &uiInfo.humanBuildList[ uiInfo.humanBuildIndex ], 1815 &rect, text_x, text_y, scale, textalign, textvalign, color, textStyle ); 1816 break; 1817 1818 case UI_NETMAPPREVIEW: 1819 UI_DrawServerMapPreview( &rect, scale, color ); 1820 break; 1821 1822 case UI_SELECTEDMAPPREVIEW: 1823 UI_DrawSelectedMapPreview( &rect, scale, color ); 1824 break; 1825 1826 case UI_SELECTEDMAPNAME: 1827 UI_DrawSelectedMapName( &rect, scale, color, textStyle ); 1828 break; 1829 1830 case UI_GLINFO: 1831 UI_DrawGLInfo( &rect, scale, textalign, textvalign, color, textStyle, text_x, text_y ); 1832 break; 1833 1834 default: 1835 break; 1836 } 1837 1838 } 1839 1840 static qboolean UI_OwnerDrawVisible( int flags ) 1841 { 1842 qboolean vis = qtrue; 1843 uiClientState_t cs; 1844 pTeam_t team; 1845 char info[ MAX_INFO_STRING ]; 1846 1847 trap_GetClientState( &cs ); 1848 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING ); 1849 team = atoi( Info_ValueForKey( info, "t" ) ); 1850 1851 1852 while( flags ) 1853 { 1854 if( flags & UI_SHOW_NOTSPECTATING ) 1855 { 1856 if( team == PTE_NONE ) 1857 vis = qfalse; 1858 1859 flags &= ~UI_SHOW_NOTSPECTATING; 1860 } 1861 1862 if( flags & UI_SHOW_VOTEACTIVE ) 1863 { 1864 if( !trap_Cvar_VariableValue( "ui_voteActive" ) ) 1865 vis = qfalse; 1866 1867 flags &= ~UI_SHOW_VOTEACTIVE; 1868 } 1869 1870 if( flags & UI_SHOW_CANVOTE ) 1871 { 1872 if( trap_Cvar_VariableValue( "ui_voteActive" ) ) 1873 vis = qfalse; 1874 1875 flags &= ~UI_SHOW_CANVOTE; 1876 } 1877 1878 if( flags & UI_SHOW_TEAMVOTEACTIVE ) 1879 { 1880 if( team == PTE_ALIENS ) 1881 { 1882 if( !trap_Cvar_VariableValue( "ui_alienTeamVoteActive" ) ) 1883 vis = qfalse; 1884 } 1885 else if( team == PTE_HUMANS ) 1886 { 1887 if( !trap_Cvar_VariableValue( "ui_humanTeamVoteActive" ) ) 1888 vis = qfalse; 1889 } 1890 1891 flags &= ~UI_SHOW_TEAMVOTEACTIVE; 1892 } 1893 1894 if( flags & UI_SHOW_CANTEAMVOTE ) 1895 { 1896 if( team == PTE_ALIENS ) 1897 { 1898 if( trap_Cvar_VariableValue( "ui_alienTeamVoteActive" ) ) 1899 vis = qfalse; 1900 } 1901 else if( team == PTE_HUMANS ) 1902 { 1903 if( trap_Cvar_VariableValue( "ui_humanTeamVoteActive" ) ) 1904 vis = qfalse; 1905 } 1906 1907 flags &= ~UI_SHOW_CANTEAMVOTE; 1908 } 1909 1910 if( flags & UI_SHOW_FAVORITESERVERS ) 1911 { 1912 // this assumes you only put this type of display flag on something showing in the proper context 1913 1914 if( ui_netSource.integer != AS_FAVORITES ) 1915 vis = qfalse; 1916 1917 flags &= ~UI_SHOW_FAVORITESERVERS; 1918 } 1919 1920 if( flags & UI_SHOW_NOTFAVORITESERVERS ) 1921 { 1922 // this assumes you only put this type of display flag on something showing in the proper context 1923 1924 if( ui_netSource.integer == AS_FAVORITES ) 1925 vis = qfalse; 1926 1927 flags &= ~UI_SHOW_NOTFAVORITESERVERS; 1928 } 1929 else 1930 flags = 0; 1931 } 1932 1933 return vis; 1934 } 1935 1936 static qboolean UI_NetSource_HandleKey( int flags, float *special, int key ) 1937 { 1938 if( key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER ) 1939 { 1940 if( key == K_MOUSE2 ) 1941 { 1942 ui_netSource.integer--; 1943 1944 if( ui_netSource.integer == AS_MPLAYER ) 1945 ui_netSource.integer--; 1946 } 1947 else 1948 { 1949 ui_netSource.integer++; 1950 1951 if( ui_netSource.integer == AS_MPLAYER ) 1952 ui_netSource.integer++; 1953 } 1954 1955 if( ui_netSource.integer >= numNetSources ) 1956 ui_netSource.integer = 0; 1957 else if( ui_netSource.integer < 0 ) 1958 ui_netSource.integer = numNetSources - 1; 1959 1960 UI_BuildServerDisplayList( qtrue ); 1961 1962 if( ui_netSource.integer != AS_GLOBAL ) 1963 UI_StartServerRefresh( qtrue ); 1964 1965 trap_Cvar_Set( "ui_netSource", va( "%d", ui_netSource.integer ) ); 1966 return qtrue; 1967 } 1968 1969 return qfalse; 1970 } 1971 1972 static qboolean UI_OwnerDrawHandleKey( int ownerDraw, int flags, float *special, int key ) 1973 { 1974 switch( ownerDraw ) 1975 { 1976 case UI_NETSOURCE: 1977 UI_NetSource_HandleKey( flags, special, key ); 1978 break; 1979 1980 default: 1981 break; 1982 } 1983 1984 return qfalse; 1985 } 1986 1987 1988 /* 1989 ================= 1990 UI_ServersQsortCompare 1991 ================= 1992 */ 1993 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ) 1994 { 1995 return trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey, 1996 uiInfo.serverStatus.sortDir, *( int* )arg1, *( int* )arg2 ); 1997 } 1998 1999 2000 /* 2001 ================= 2002 UI_ServersSort 2003 ================= 2004 */ 2005 void UI_ServersSort( int column, qboolean force ) 2006 { 2007 if( !force ) 2008 { 2009 if( uiInfo.serverStatus.sortKey == column ) 2010 return; 2011 } 2012 2013 uiInfo.serverStatus.sortKey = column; 2014 qsort( &uiInfo.serverStatus.displayServers[0], uiInfo.serverStatus.numDisplayServers, 2015 sizeof( int ), UI_ServersQsortCompare ); 2016 } 2017 2018 2019 /* 2020 =============== 2021 UI_GetCurrentAlienStage 2022 =============== 2023 */ 2024 static stage_t UI_GetCurrentAlienStage( void ) 2025 { 2026 char buffer[ MAX_TOKEN_CHARS ]; 2027 stage_t stage, dummy; 2028 2029 trap_Cvar_VariableStringBuffer( "ui_stages", buffer, sizeof( buffer ) ); 2030 sscanf( buffer, "%d %d", ( int * ) & stage , ( int * ) & dummy ); 2031 2032 return stage; 2033 } 2034 2035 /* 2036 =============== 2037 UI_GetCurrentHumanStage 2038 =============== 2039 */ 2040 static stage_t UI_GetCurrentHumanStage( void ) 2041 { 2042 char buffer[ MAX_TOKEN_CHARS ]; 2043 stage_t stage, dummy; 2044 2045 trap_Cvar_VariableStringBuffer( "ui_stages", buffer, sizeof( buffer ) ); 2046 sscanf( buffer, "%d %d", ( int * ) & dummy, ( int * ) & stage ); 2047 2048 return stage; 2049 } 2050 2051 /* 2052 =============== 2053 UI_LoadTeams 2054 =============== 2055 */ 2056 static void UI_LoadTeams( void ) 2057 { 2058 uiInfo.teamCount = 4; 2059 2060 uiInfo.teamList[ 0 ].text = String_Alloc( "Aliens" ); 2061 uiInfo.teamList[ 0 ].cmd = String_Alloc( "cmd team aliens\n" ); 2062 uiInfo.teamList[ 0 ].type = INFOTYPE_TEXT; 2063 uiInfo.teamList[ 0 ].v.text = 2064 "The Alien Team\n\n" 2065 "The Aliens' strengths are in movement and the ability to " 2066 "quickly construct new bases quickly. They possess a range " 2067 "of abilities including basic melee attacks, movement-" 2068 "crippling poisons and more."; 2069 2070 uiInfo.teamList[ 1 ].text = String_Alloc( "Humans" ); 2071 uiInfo.teamList[ 1 ].cmd = String_Alloc( "cmd team humans\n" ); 2072 uiInfo.teamList[ 1 ].type = INFOTYPE_TEXT; 2073 uiInfo.teamList[ 1 ].v.text = 2074 "The Human Team\n\n" 2075 "The humans are the masters of technology. Although their " 2076 "bases take long to construct, their automated defense " 2077 "ensures they stay built. A wide range of upgrades and " 2078 "weapons are available to the humans, each contributing " 2079 "to eradicate the alien threat."; 2080 2081 uiInfo.teamList[ 2 ].text = String_Alloc( "Spectate" ); 2082 uiInfo.teamList[ 2 ].cmd = String_Alloc( "cmd team spectate\n" ); 2083 uiInfo.teamList[ 2 ].type = INFOTYPE_TEXT; 2084 uiInfo.teamList[ 2 ].v.text = "Watch the game without playing."; 2085 2086 uiInfo.teamList[ 3 ].text = String_Alloc( "Auto select" ); 2087 uiInfo.teamList[ 3 ].cmd = String_Alloc( "cmd team auto\n" ); 2088 uiInfo.teamList[ 3 ].type = INFOTYPE_TEXT; 2089 uiInfo.teamList[ 3 ].v.text = "Join the team with the least players."; 2090 } 2091 2092 /* 2093 =============== 2094 UI_AddClass 2095 =============== 2096 */ 2097 2098 static void UI_AddClass( pClass_t class ) 2099 { 2100 uiInfo.alienClassList[ uiInfo.alienClassCount ].text = 2101 2102 String_Alloc( BG_FindHumanNameForClassNum( class ) ); 2103 uiInfo.alienClassList[ uiInfo.alienClassCount ].cmd = 2104 2105 String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( class ) ) ); 2106 uiInfo.alienClassList[ uiInfo.alienClassCount ].type = INFOTYPE_CLASS; 2107 2108 uiInfo.alienClassList[ uiInfo.alienClassCount ].v.pclass = class; 2109 2110 uiInfo.alienClassCount++; 2111 } 2112 2113 /* 2114 =============== 2115 UI_LoadAlienClasses 2116 =============== 2117 */ 2118 static void UI_LoadAlienClasses( void ) 2119 { 2120 uiInfo.alienClassCount = 0; 2121 2122 if( BG_ClassIsAllowed( PCL_ALIEN_LEVEL0 ) ) 2123 UI_AddClass( PCL_ALIEN_LEVEL0 ); 2124 2125 if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0_UPG ) && 2126 BG_FindStagesForClass( PCL_ALIEN_BUILDER0_UPG, UI_GetCurrentAlienStage( ) ) ) 2127 UI_AddClass( PCL_ALIEN_BUILDER0_UPG ); 2128 else if( BG_ClassIsAllowed( PCL_ALIEN_BUILDER0 ) ) 2129 UI_AddClass( PCL_ALIEN_BUILDER0 ); 2130 } 2131 2132 /* 2133 =============== 2134 UI_AddItem 2135 =============== 2136 */ 2137 static void UI_AddItem( weapon_t weapon ) 2138 { 2139 uiInfo.humanItemList[ uiInfo.humanItemCount ].text = 2140 String_Alloc( BG_FindHumanNameForWeapon( weapon ) ); 2141 uiInfo.humanItemList[ uiInfo.humanItemCount ].cmd = 2142 String_Alloc( va( "cmd class %s\n", BG_FindNameForWeapon( weapon ) ) ); 2143 uiInfo.humanItemList[ uiInfo.humanItemCount ].type = INFOTYPE_WEAPON; 2144 uiInfo.humanItemList[ uiInfo.humanItemCount ].v.weapon = weapon; 2145 2146 uiInfo.humanItemCount++; 2147 } 2148 2149 /* 2150 =============== 2151 UI_LoadHumanItems 2152 =============== 2153 */ 2154 static void UI_LoadHumanItems( void ) 2155 { 2156 uiInfo.humanItemCount = 0; 2157 2158 if( BG_WeaponIsAllowed( WP_MACHINEGUN ) ) 2159 UI_AddItem( WP_MACHINEGUN ); 2160 2161 if( BG_WeaponIsAllowed( WP_HBUILD2 ) && 2162 BG_FindStagesForWeapon( WP_HBUILD2, UI_GetCurrentHumanStage( ) ) ) 2163 UI_AddItem( WP_HBUILD2 ); 2164 else if( BG_WeaponIsAllowed( WP_HBUILD ) ) 2165 UI_AddItem( WP_HBUILD ); 2166 } 2167 2168 /* 2169 =============== 2170 UI_ParseCarriageList 2171 =============== 2172 */ 2173 static void UI_ParseCarriageList( void ) 2174 { 2175 int i; 2176 char carriageCvar[ MAX_TOKEN_CHARS ]; 2177 char *iterator; 2178 char buffer[ MAX_TOKEN_CHARS ]; 2179 char *bufPointer; 2180 2181 trap_Cvar_VariableStringBuffer( "ui_carriage", carriageCvar, sizeof( carriageCvar ) ); 2182 iterator = carriageCvar; 2183 2184 uiInfo.weapons = 0; 2185 uiInfo.upgrades = 0; 2186 2187 //simple parser to give rise to weapon/upgrade list 2188 2189 while( iterator && iterator[ 0 ] != '$' ) 2190 { 2191 bufPointer = buffer; 2192 2193 if( iterator[ 0 ] == 'W' ) 2194 { 2195 iterator++; 2196 2197 while( iterator[ 0 ] != ' ' ) 2198 * bufPointer++ = *iterator++; 2199 2200 *bufPointer++ = '\n'; 2201 2202 i = atoi( buffer ); 2203 2204 uiInfo.weapons |= ( 1 << i ); 2205 } 2206 else if( iterator[ 0 ] == 'U' ) 2207 { 2208 iterator++; 2209 2210 while( iterator[ 0 ] != ' ' ) 2211 * bufPointer++ = *iterator++; 2212 2213 *bufPointer++ = '\n'; 2214 2215 i = atoi( buffer ); 2216 2217 uiInfo.upgrades |= ( 1 << i ); 2218 } 2219 2220 iterator++; 2221 } 2222 } 2223 2224 /* 2225 =============== 2226 UI_LoadHumanArmouryBuys 2227 =============== 2228 */ 2229 static void UI_LoadHumanArmouryBuys( void ) 2230 { 2231 int i, j = 0; 2232 stage_t stage = UI_GetCurrentHumanStage( ); 2233 int slots = 0; 2234 2235 UI_ParseCarriageList( ); 2236 2237 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 2238 { 2239 if( uiInfo.weapons & ( 1 << i ) ) 2240 slots |= BG_FindSlotsForWeapon( i ); 2241 } 2242 2243 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 2244 { 2245 if( uiInfo.upgrades & ( 1 << i ) ) 2246 slots |= BG_FindSlotsForUpgrade( i ); 2247 } 2248 2249 uiInfo.humanArmouryBuyCount = 0; 2250 2251 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 2252 { 2253 if( BG_FindTeamForWeapon( i ) == WUT_HUMANS && 2254 BG_FindPurchasableForWeapon( i ) && 2255 BG_FindStagesForWeapon( i, stage ) && 2256 BG_WeaponIsAllowed( i ) && 2257 !( BG_FindSlotsForWeapon( i ) & slots ) && 2258 !( uiInfo.weapons & ( 1 << i ) ) ) 2259 { 2260 uiInfo.humanArmouryBuyList[ j ].text = 2261 String_Alloc( BG_FindHumanNameForWeapon( i ) ); 2262 uiInfo.humanArmouryBuyList[ j ].cmd = 2263 String_Alloc( va( "cmd buy %s\n", BG_FindNameForWeapon( i ) ) ); 2264 uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_WEAPON; 2265 uiInfo.humanArmouryBuyList[ j ].v.weapon = i; 2266 2267 j++; 2268 2269 uiInfo.humanArmouryBuyCount++; 2270 } 2271 } 2272 2273 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 2274 { 2275 if( BG_FindTeamForUpgrade( i ) == WUT_HUMANS && 2276 BG_FindPurchasableForUpgrade( i ) && 2277 BG_FindStagesForUpgrade( i, stage ) && 2278 BG_UpgradeIsAllowed( i ) && 2279 !( BG_FindSlotsForUpgrade( i ) & slots ) && 2280 !( uiInfo.upgrades & ( 1 << i ) ) ) 2281 { 2282 uiInfo.humanArmouryBuyList[ j ].text = 2283 String_Alloc( BG_FindHumanNameForUpgrade( i ) ); 2284 uiInfo.humanArmouryBuyList[ j ].cmd = 2285 String_Alloc( va( "cmd buy %s\n", BG_FindNameForUpgrade( i ) ) ); 2286 uiInfo.humanArmouryBuyList[ j ].type = INFOTYPE_UPGRADE; 2287 uiInfo.humanArmouryBuyList[ j ].v.upgrade = i; 2288 2289 j++; 2290 2291 uiInfo.humanArmouryBuyCount++; 2292 } 2293 } 2294 } 2295 2296 /* 2297 =============== 2298 UI_LoadHumanArmourySells 2299 =============== 2300 */ 2301 static void UI_LoadHumanArmourySells( void ) 2302 { 2303 int i, j = 0; 2304 2305 uiInfo.humanArmourySellCount = 0; 2306 UI_ParseCarriageList( ); 2307 2308 for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ ) 2309 { 2310 if( uiInfo.weapons & ( 1 << i ) ) 2311 { 2312 uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForWeapon( i ) ); 2313 uiInfo.humanArmourySellList[ j ].cmd = 2314 String_Alloc( va( "cmd sell %s\n", BG_FindNameForWeapon( i ) ) ); 2315 uiInfo.humanArmourySellList[ j ].type = INFOTYPE_WEAPON; 2316 uiInfo.humanArmourySellList[ j ].v.weapon = i; 2317 2318 j++; 2319 2320 uiInfo.humanArmourySellCount++; 2321 } 2322 } 2323 2324 for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ ) 2325 { 2326 if( uiInfo.upgrades & ( 1 << i ) ) 2327 { 2328 uiInfo.humanArmourySellList[ j ].text = String_Alloc( BG_FindHumanNameForUpgrade( i ) ); 2329 uiInfo.humanArmourySellList[ j ].cmd = 2330 String_Alloc( va( "cmd sell %s\n", BG_FindNameForUpgrade( i ) ) ); 2331 uiInfo.humanArmourySellList[ j ].type = INFOTYPE_UPGRADE; 2332 uiInfo.humanArmourySellList[ j ].v.upgrade = i; 2333 2334 j++; 2335 2336 uiInfo.humanArmourySellCount++; 2337 } 2338 } 2339 } 2340 2341 /* 2342 =============== 2343 UI_ArmouryRefreshCb 2344 =============== 2345 */ 2346 static void UI_ArmouryRefreshCb( void *data ) 2347 { 2348 int oldWeapons = uiInfo.weapons; 2349 int oldUpgrades = uiInfo.upgrades; 2350 2351 UI_ParseCarriageList( ); 2352 2353 if( uiInfo.weapons != oldWeapons || uiInfo.upgrades != oldUpgrades ) 2354 { 2355 UI_LoadHumanArmouryBuys( ); 2356 UI_LoadHumanArmourySells( ); 2357 UI_RemoveCaptureFunc( ); 2358 } 2359 } 2360 2361 /* 2362 =============== 2363 UI_LoadAlienUpgrades 2364 =============== 2365 */ 2366 static void UI_LoadAlienUpgrades( void ) 2367 { 2368 int i, j = 0; 2369 2370 int class, credits; 2371 char ui_currentClass[ MAX_STRING_CHARS ]; 2372 stage_t stage = UI_GetCurrentAlienStage( ); 2373 2374 trap_Cvar_VariableStringBuffer( "ui_currentClass", ui_currentClass, MAX_STRING_CHARS ); 2375 2376 sscanf( ui_currentClass, "%d %d", &class, &credits ); 2377 2378 uiInfo.alienUpgradeCount = 0; 2379 2380 for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ ) 2381 { 2382 if( BG_ClassCanEvolveFromTo( class, i, credits, 0 ) >= 0 && 2383 BG_FindStagesForClass( i, stage ) && 2384 BG_ClassIsAllowed( i ) ) 2385 { 2386 uiInfo.alienUpgradeList[ j ].text = String_Alloc( BG_FindHumanNameForClassNum( i ) ); 2387 uiInfo.alienUpgradeList[ j ].cmd = 2388 String_Alloc( va( "cmd class %s\n", BG_FindNameForClassNum( i ) ) ); 2389 uiInfo.alienUpgradeList[ j ].type = INFOTYPE_CLASS; 2390 uiInfo.alienUpgradeList[ j ].v.pclass = i; 2391 2392 j++; 2393 2394 uiInfo.alienUpgradeCount++; 2395 } 2396 } 2397 } 2398 2399 /* 2400 =============== 2401 UI_LoadAlienBuilds 2402 =============== 2403 */ 2404 static void UI_LoadAlienBuilds( void ) 2405 { 2406 int i, j = 0; 2407 stage_t stage; 2408 2409 UI_ParseCarriageList( ); 2410 stage = UI_GetCurrentAlienStage( ); 2411 2412 uiInfo.alienBuildCount = 0; 2413 2414 for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) 2415 { 2416 if( BG_FindTeamForBuildable( i ) == BIT_ALIENS && 2417 BG_FindBuildWeaponForBuildable( i ) & uiInfo.weapons && 2418 BG_FindStagesForBuildable( i, stage ) && 2419 BG_BuildableIsAllowed( i ) ) 2420 { 2421 uiInfo.alienBuildList[ j ].text = 2422 String_Alloc( BG_FindHumanNameForBuildable( i ) ); 2423 uiInfo.alienBuildList[ j ].cmd = 2424 String_Alloc( va( "cmd build %s\n", BG_FindNameForBuildable( i ) ) ); 2425 uiInfo.alienBuildList[ j ].type = INFOTYPE_BUILDABLE; 2426 uiInfo.alienBuildList[ j ].v.buildable = i; 2427 2428 j++; 2429 2430 uiInfo.alienBuildCount++; 2431 } 2432 } 2433 } 2434 2435 /* 2436 =============== 2437 UI_LoadHumanBuilds 2438 =============== 2439 */ 2440 static void UI_LoadHumanBuilds( void ) 2441 { 2442 int i, j = 0; 2443 stage_t stage; 2444 2445 UI_ParseCarriageList( ); 2446 stage = UI_GetCurrentHumanStage( ); 2447 2448 uiInfo.humanBuildCount = 0; 2449 2450 for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) 2451 { 2452 if( BG_FindTeamForBuildable( i ) == BIT_HUMANS && 2453 BG_FindBuildWeaponForBuildable( i ) & uiInfo.weapons && 2454 BG_FindStagesForBuildable( i, stage ) && 2455 BG_BuildableIsAllowed( i ) ) 2456 { 2457 uiInfo.humanBuildList[ j ].text = 2458 String_Alloc( BG_FindHumanNameForBuildable( i ) ); 2459 uiInfo.humanBuildList[ j ].cmd = 2460 String_Alloc( va( "cmd build %s\n", BG_FindNameForBuildable( i ) ) ); 2461 uiInfo.humanBuildList[ j ].type = INFOTYPE_BUILDABLE; 2462 uiInfo.humanBuildList[ j ].v.buildable = i; 2463 2464 j++; 2465 2466 uiInfo.humanBuildCount++; 2467 } 2468 } 2469 } 2470 2471 /* 2472 =============== 2473 UI_LoadMods 2474 =============== 2475 */ 2476 static void UI_LoadMods( void ) 2477 { 2478 int numdirs; 2479 char dirlist[2048]; 2480 char *dirptr; 2481 char *descptr; 2482 int i; 2483 int dirlen; 2484 2485 uiInfo.modCount = 0; 2486 numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof( dirlist ) ); 2487 dirptr = dirlist; 2488 2489 for( i = 0; i < numdirs; i++ ) 2490 { 2491 dirlen = strlen( dirptr ) + 1; 2492 descptr = dirptr + dirlen; 2493 uiInfo.modList[uiInfo.modCount].modName = String_Alloc( dirptr ); 2494 uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc( descptr ); 2495 dirptr += dirlen + strlen( descptr ) + 1; 2496 uiInfo.modCount++; 2497 2498 if( uiInfo.modCount >= MAX_MODS ) 2499 break; 2500 } 2501 2502 } 2503 2504 2505 /* 2506 =============== 2507 UI_LoadMovies 2508 =============== 2509 */ 2510 static void UI_LoadMovies( void ) 2511 { 2512 char movielist[4096]; 2513 char *moviename; 2514 int i, len; 2515 2516 uiInfo.movieCount = trap_FS_GetFileList( "video", "roq", movielist, 4096 ); 2517 2518 if( uiInfo.movieCount ) 2519 { 2520 if( uiInfo.movieCount > MAX_MOVIES ) 2521 uiInfo.movieCount = MAX_MOVIES; 2522 2523 moviename = movielist; 2524 2525 for( i = 0; i < uiInfo.movieCount; i++ ) 2526 { 2527 len = strlen( moviename ); 2528 2529 if( !Q_stricmp( moviename + len - 4, ".roq" ) ) 2530 moviename[len-4] = '\0'; 2531 2532 Q_strupr( moviename ); 2533 uiInfo.movieList[i] = String_Alloc( moviename ); 2534 moviename += len + 1; 2535 } 2536 } 2537 2538 } 2539 2540 2541 2542 /* 2543 =============== 2544 UI_LoadDemos 2545 =============== 2546 */ 2547 static void UI_LoadDemos( void ) 2548 { 2549 char demolist[4096]; 2550 char demoExt[32]; 2551 char *demoname; 2552 int i, len; 2553 2554 Com_sprintf( demoExt, sizeof( demoExt ), "dm_%d", ( int )trap_Cvar_VariableValue( "protocol" ) ); 2555 2556 uiInfo.demoCount = trap_FS_GetFileList( "demos", demoExt, demolist, 4096 ); 2557 2558 Com_sprintf( demoExt, sizeof( demoExt ), ".dm_%d", ( int )trap_Cvar_VariableValue( "protocol" ) ); 2559 2560 if( uiInfo.demoCount ) 2561 { 2562 if( uiInfo.demoCount > MAX_DEMOS ) 2563 uiInfo.demoCount = MAX_DEMOS; 2564 2565 demoname = demolist; 2566 2567 for( i = 0; i < uiInfo.demoCount; i++ ) 2568 { 2569 len = strlen( demoname ); 2570 2571 if( !Q_stricmp( demoname + len - strlen( demoExt ), demoExt ) ) 2572 demoname[len-strlen( demoExt )] = '\0'; 2573 2574 Q_strupr( demoname ); 2575 uiInfo.demoList[i] = String_Alloc( demoname ); 2576 demoname += len + 1; 2577 } 2578 } 2579 2580 } 2581 2582 static void UI_Update( const char *name ) 2583 { 2584 int val = trap_Cvar_VariableValue( name ); 2585 2586 if( Q_stricmp( name, "ui_SetName" ) == 0 ) 2587 trap_Cvar_Set( "name", UI_Cvar_VariableString( "ui_Name" ) ); 2588 else if( Q_stricmp( name, "ui_setRate" ) == 0 ) 2589 { 2590 float rate = trap_Cvar_VariableValue( "rate" ); 2591 2592 if( rate >= 5000 ) 2593 { 2594 trap_Cvar_Set( "cl_maxpackets", "30" ); 2595 trap_Cvar_Set( "cl_packetdup", "1" ); 2596 } 2597 else if( rate >= 4000 ) 2598 { 2599 trap_Cvar_Set( "cl_maxpackets", "15" ); 2600 trap_Cvar_Set( "cl_packetdup", "2" ); // favor less prediction errors when there's packet loss 2601 } 2602 else 2603 { 2604 trap_Cvar_Set( "cl_maxpackets", "15" ); 2605 trap_Cvar_Set( "cl_packetdup", "1" ); // favor lower bandwidth 2606 } 2607 } 2608 else if( Q_stricmp( name, "ui_GetName" ) == 0 ) 2609 trap_Cvar_Set( "ui_Name", UI_Cvar_VariableString( "name" ) ); 2610 else if( Q_stricmp( name, "r_colorbits" ) == 0 ) 2611 { 2612 switch( val ) 2613 { 2614 case 0: 2615 trap_Cvar_SetValue( "r_depthbits", 0 ); 2616 trap_Cvar_SetValue( "r_stencilbits", 0 ); 2617 break; 2618 2619 case 16: 2620 trap_Cvar_SetValue( "r_depthbits", 16 ); 2621 trap_Cvar_SetValue( "r_stencilbits", 0 ); 2622 break; 2623 2624 case 32: 2625 trap_Cvar_SetValue( "r_depthbits", 24 ); 2626 break; 2627 } 2628 } 2629 else if( Q_stricmp( name, "r_lodbias" ) == 0 ) 2630 { 2631 switch( val ) 2632 { 2633 case 0: 2634 trap_Cvar_SetValue( "r_subdivisions", 4 ); 2635 break; 2636 2637 case 1: 2638 trap_Cvar_SetValue( "r_subdivisions", 12 ); 2639 break; 2640 2641 case 2: 2642 trap_Cvar_SetValue( "r_subdivisions", 20 ); 2643 break; 2644 } 2645 } 2646 else if( Q_stricmp( name, "ui_glCustom" ) == 0 ) 2647 { 2648 switch( val ) 2649 { 2650 case 0: // high quality 2651 trap_Cvar_SetValue( "r_subdivisions", 4 ); 2652 trap_Cvar_SetValue( "r_vertexlight", 0 ); 2653 trap_Cvar_SetValue( "r_lodbias", 0 ); 2654 trap_Cvar_SetValue( "r_colorbits", 32 ); 2655 trap_Cvar_SetValue( "r_depthbits", 24 ); 2656 trap_Cvar_SetValue( "r_picmip", 0 ); 2657 trap_Cvar_SetValue( "r_texturebits", 32 ); 2658 trap_Cvar_SetValue( "r_fastSky", 0 ); 2659 trap_Cvar_SetValue( "r_inGameVideo", 1 ); 2660 trap_Cvar_SetValue( "cg_shadows", 1 ); 2661 trap_Cvar_SetValue( "cg_brassTime", 2500 ); 2662 trap_Cvar_SetValue( "cg_bounceParticles", 1 ); 2663 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); 2664 break; 2665 2666 case 1: // normal 2667 trap_Cvar_SetValue( "r_subdivisions", 12 ); 2668 trap_Cvar_SetValue( "r_vertexlight", 0 ); 2669 trap_Cvar_SetValue( "r_lodbias", 0 ); 2670 trap_Cvar_SetValue( "r_colorbits", 0 ); 2671 trap_Cvar_SetValue( "r_depthbits", 24 ); 2672 trap_Cvar_SetValue( "r_picmip", 1 ); 2673 trap_Cvar_SetValue( "r_texturebits", 0 ); 2674 trap_Cvar_SetValue( "r_fastSky", 0 ); 2675 trap_Cvar_SetValue( "r_inGameVideo", 1 ); 2676 trap_Cvar_SetValue( "cg_brassTime", 2500 ); 2677 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); 2678 trap_Cvar_SetValue( "cg_shadows", 0 ); 2679 trap_Cvar_SetValue( "cg_bounceParticles", 0 ); 2680 break; 2681 2682 case 2: // fast 2683 trap_Cvar_SetValue( "r_subdivisions", 8 ); 2684 trap_Cvar_SetValue( "r_vertexlight", 0 ); 2685 trap_Cvar_SetValue( "r_lodbias", 1 ); 2686 trap_Cvar_SetValue( "r_colorbits", 0 ); 2687 trap_Cvar_SetValue( "r_depthbits", 0 ); 2688 trap_Cvar_SetValue( "r_picmip", 1 ); 2689 trap_Cvar_SetValue( "r_texturebits", 0 ); 2690 trap_Cvar_SetValue( "cg_shadows", 0 ); 2691 trap_Cvar_SetValue( "r_fastSky", 1 ); 2692 trap_Cvar_SetValue( "r_inGameVideo", 0 ); 2693 trap_Cvar_SetValue( "cg_brassTime", 0 ); 2694 trap_Cvar_SetValue( "cg_bounceParticles", 0 ); 2695 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" ); 2696 break; 2697 2698 case 3: // fastest 2699 trap_Cvar_SetValue( "r_subdivisions", 20 ); 2700 trap_Cvar_SetValue( "r_vertexlight", 1 ); 2701 trap_Cvar_SetValue( "r_lodbias", 2 ); 2702 trap_Cvar_SetValue( "r_colorbits", 16 ); 2703 trap_Cvar_SetValue( "r_depthbits", 16 ); 2704 trap_Cvar_SetValue( "r_picmip", 2 ); 2705 trap_Cvar_SetValue( "r_texturebits", 16 ); 2706 trap_Cvar_SetValue( "cg_shadows", 0 ); 2707 trap_Cvar_SetValue( "cg_brassTime", 0 ); 2708 trap_Cvar_SetValue( "r_fastSky", 1 ); 2709 trap_Cvar_SetValue( "r_inGameVideo", 0 ); 2710 trap_Cvar_SetValue( "cg_bounceParticles", 0 ); 2711 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" ); 2712 break; 2713 } 2714 } 2715 else if( Q_stricmp( name, "ui_mousePitch" ) == 0 ) 2716 { 2717 if( val == 0 ) 2718 trap_Cvar_SetValue( "m_pitch", 0.022f ); 2719 else 2720 trap_Cvar_SetValue( "m_pitch", -0.022f ); 2721 } 2722 } 2723 2724 //FIXME: lookup table 2725 static void UI_RunMenuScript( char **args ) 2726 { 2727 const char * name, *name2; 2728 char buff[1024]; 2729 const char *cmd; 2730 2731 if( String_Parse( args, &name ) ) 2732 { 2733 if( Q_stricmp( name, "StartServer" ) == 0 ) 2734 { 2735 trap_Cvar_SetValue( "dedicated", Com_Clamp( 0, 2, ui_dedicated.integer ) ); 2736 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", 2737 uiInfo.mapList[ui_selectedMap.integer].mapLoadName ) ); 2738 } 2739 else if( Q_stricmp( name, "resetDefaults" ) == 0 ) 2740 { 2741 trap_Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n" ); 2742 trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n" ); 2743 Controls_SetDefaults(); 2744 trap_Cvar_Set( "com_introPlayed", "1" ); 2745 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" ); 2746 } 2747 else if( Q_stricmp( name, "loadArenas" ) == 0 ) 2748 { 2749 UI_LoadArenas(); 2750 Menu_SetFeederSelection( NULL, FEEDER_MAPS, 0, "createserver" ); 2751 } 2752 else if( Q_stricmp( name, "loadServerInfo" ) == 0 ) 2753 UI_ServerInfo(); 2754 else if( Q_stricmp( name, "saveControls" ) == 0 ) 2755 Controls_SetConfig( qtrue ); 2756 else if( Q_stricmp( name, "loadControls" ) == 0 ) 2757 Controls_GetConfig(); 2758 else if( Q_stricmp( name, "clearError" ) == 0 ) 2759 trap_Cvar_Set( "com_errorMessage", "" ); 2760 else if( Q_stricmp( name, "RefreshServers" ) == 0 ) 2761 { 2762 UI_StartServerRefresh( qtrue ); 2763 UI_BuildServerDisplayList( qtrue ); 2764 } 2765 else if( Q_stricmp( name, "InitServerList" ) == 0 ) 2766 { 2767 int time = trap_RealTime( NULL ); 2768 int last; 2769 int sortColumn; 2770 2771 // set up default sorting 2772 2773 if( !uiInfo.serverStatus.sorted && Int_Parse( args, &sortColumn ) ) 2774 { 2775 uiInfo.serverStatus.sortKey = sortColumn; 2776 uiInfo.serverStatus.sortDir = 0; 2777 } 2778 2779 // refresh if older than 3 days or if list is empty 2780 last = atoi( UI_Cvar_VariableString( va( "ui_lastServerRefresh_%i_time", 2781 ui_netSource.integer ) ) ); 2782 2783 if( trap_LAN_GetServerCount( ui_netSource.integer ) < 1 || 2784 ( time - last ) > 3600 ) 2785 { 2786 UI_StartServerRefresh( qtrue ); 2787 UI_BuildServerDisplayList( qtrue ); 2788 } 2789 } 2790 else if( Q_stricmp( name, "RefreshFilter" ) == 0 ) 2791 { 2792 UI_StartServerRefresh( qfalse ); 2793 UI_BuildServerDisplayList( qtrue ); 2794 } 2795 else if( Q_stricmp( name, "LoadDemos" ) == 0 ) 2796 UI_LoadDemos(); 2797 else if( Q_stricmp( name, "LoadMovies" ) == 0 ) 2798 UI_LoadMovies(); 2799 else if( Q_stricmp( name, "LoadMods" ) == 0 ) 2800 UI_LoadMods(); 2801 else if( Q_stricmp( name, "LoadTeams" ) == 0 ) 2802 UI_LoadTeams( ); 2803 else if( Q_stricmp( name, "JoinTeam" ) == 0 ) 2804 { 2805 if( ( cmd = uiInfo.teamList[ uiInfo.teamIndex ].cmd ) ) 2806 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2807 } 2808 else if( Q_stricmp( name, "LoadHumanItems" ) == 0 ) 2809 UI_LoadHumanItems( ); 2810 else if( Q_stricmp( name, "SpawnWithHumanItem" ) == 0 ) 2811 { 2812 if( ( cmd = uiInfo.humanItemList[ uiInfo.humanItemIndex ].cmd ) ) 2813 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2814 } 2815 else if( Q_stricmp( name, "LoadAlienClasses" ) == 0 ) 2816 UI_LoadAlienClasses( ); 2817 else if( Q_stricmp( name, "SpawnAsAlienClass" ) == 0 ) 2818 { 2819 if( ( cmd = uiInfo.alienClassList[ uiInfo.alienClassIndex ].cmd ) ) 2820 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2821 } 2822 else if( Q_stricmp( name, "LoadHumanArmouryBuys" ) == 0 ) 2823 UI_LoadHumanArmouryBuys( ); 2824 else if( Q_stricmp( name, "BuyFromArmoury" ) == 0 ) 2825 { 2826 if( ( cmd = uiInfo.humanArmouryBuyList[ uiInfo.humanArmouryBuyIndex ].cmd ) ) 2827 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2828 2829 UI_InstallCaptureFunc( UI_ArmouryRefreshCb, NULL, 1000 ); 2830 } 2831 else if( Q_stricmp( name, "LoadHumanArmourySells" ) == 0 ) 2832 UI_LoadHumanArmourySells( ); 2833 else if( Q_stricmp( name, "SellToArmoury" ) == 0 ) 2834 { 2835 if( ( cmd = uiInfo.humanArmourySellList[ uiInfo.humanArmourySellIndex ].cmd ) ) 2836 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2837 2838 UI_InstallCaptureFunc( UI_ArmouryRefreshCb, NULL, 1000 ); 2839 } 2840 else if( Q_stricmp( name, "LoadAlienUpgrades" ) == 0 ) 2841 { 2842 UI_LoadAlienUpgrades( ); 2843 2844 //disallow the menu if it would be empty 2845 2846 if( uiInfo.alienUpgradeCount <= 0 ) 2847 Menus_CloseAll( ); 2848 } 2849 else if( Q_stricmp( name, "UpgradeToNewClass" ) == 0 ) 2850 { 2851 if( ( cmd = uiInfo.alienUpgradeList[ uiInfo.alienUpgradeIndex ].cmd ) ) 2852 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2853 } 2854 else if( Q_stricmp( name, "LoadAlienBuilds" ) == 0 ) 2855 UI_LoadAlienBuilds( ); 2856 else if( Q_stricmp( name, "BuildAlienBuildable" ) == 0 ) 2857 { 2858 if( ( cmd = uiInfo.alienBuildList[ uiInfo.alienBuildIndex ].cmd ) ) 2859 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2860 } 2861 else if( Q_stricmp( name, "LoadHumanBuilds" ) == 0 ) 2862 UI_LoadHumanBuilds( ); 2863 else if( Q_stricmp( name, "BuildHumanBuildable" ) == 0 ) 2864 { 2865 if( ( cmd = uiInfo.humanBuildList[ uiInfo.humanBuildIndex ].cmd ) ) 2866 trap_Cmd_ExecuteText( EXEC_APPEND, cmd ); 2867 } 2868 else if( Q_stricmp( name, "PTRCRestore" ) == 0 ) 2869 { 2870 int len; 2871 char text[ 16 ]; 2872 fileHandle_t f; 2873 char command[ 32 ]; 2874 2875 // load the file 2876 len = trap_FS_FOpenFile( "ptrc.cfg", &f, FS_READ ); 2877 2878 if( len > 0 && ( len < sizeof( text ) - 1 ) ) 2879 { 2880 trap_FS_Read( text, len, f ); 2881 text[ len ] = 0; 2882 trap_FS_FCloseFile( f ); 2883 2884 Com_sprintf( command, 32, "ptrcrestore %s", text ); 2885 2886 trap_Cmd_ExecuteText( EXEC_APPEND, command ); 2887 } 2888 } 2889 else if( Q_stricmp( name, "Say" ) == 0 ) 2890 { 2891 char buffer[ MAX_CVAR_VALUE_STRING ]; 2892 trap_Cvar_VariableStringBuffer( "ui_sayBuffer", buffer, sizeof( buffer ) ); 2893 2894 if( uiInfo.chatTargetClientNum != -1 ) 2895 trap_Cmd_ExecuteText( EXEC_APPEND, va( "tell %i \"%s\"\n", uiInfo.chatTargetClientNum, buffer ) ); 2896 else if( uiInfo.chatTeam ) 2897 trap_Cmd_ExecuteText( EXEC_APPEND, va( "say_team \"%s\"\n", buffer ) ); 2898 else 2899 trap_Cmd_ExecuteText( EXEC_APPEND, va( "say \"%s\"\n", buffer ) ); 2900 } 2901 else if( Q_stricmp( name, "playMovie" ) == 0 ) 2902 { 2903 if( uiInfo.previewMovie >= 0 ) 2904 trap_CIN_StopCinematic( uiInfo.previewMovie ); 2905 2906 trap_Cmd_ExecuteText( EXEC_APPEND, va( "cinematic %s.roq 2\n", uiInfo.movieList[uiInfo.movieIndex] ) ); 2907 } 2908 else if( Q_stricmp( name, "RunMod" ) == 0 ) 2909 { 2910 trap_Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName ); 2911 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" ); 2912 } 2913 else if( Q_stricmp( name, "RunDemo" ) == 0 ) 2914 trap_Cmd_ExecuteText( EXEC_APPEND, va( "demo %s\n", uiInfo.demoList[uiInfo.demoIndex] ) ); 2915 else if( Q_stricmp( name, "Tremulous" ) == 0 ) 2916 { 2917 trap_Cvar_Set( "fs_game", "" ); 2918 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" ); 2919 } 2920 else if( Q_stricmp( name, "closeJoin" ) == 0 ) 2921 { 2922 if( uiInfo.serverStatus.refreshActive ) 2923 { 2924 UI_StopServerRefresh(); 2925 uiInfo.serverStatus.nextDisplayRefresh = 0; 2926 uiInfo.nextServerStatusRefresh = 0; 2927 uiInfo.nextFindPlayerRefresh = 0; 2928 UI_BuildServerDisplayList( qtrue ); 2929 } 2930 else 2931 { 2932 Menus_CloseByName( "joinserver" ); 2933 Menus_ActivateByName( "main" ); 2934 } 2935 } 2936 else if( Q_stricmp( name, "StopRefresh" ) == 0 ) 2937 { 2938 UI_StopServerRefresh(); 2939 uiInfo.serverStatus.nextDisplayRefresh = 0; 2940 uiInfo.nextServerStatusRefresh = 0; 2941 uiInfo.nextFindPlayerRefresh = 0; 2942 } 2943 else if( Q_stricmp( name, "UpdateFilter" ) == 0 ) 2944 { 2945 if( ui_netSource.integer == AS_LOCAL ) 2946 UI_StartServerRefresh( qtrue ); 2947 2948 UI_BuildServerDisplayList( qtrue ); 2949 UI_FeederSelection( FEEDER_SERVERS, 0 ); 2950 } 2951 else if( Q_stricmp( name, "ServerStatus" ) == 0 ) 2952 { 2953 trap_LAN_GetServerAddressString( ui_netSource.integer, 2954 uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], 2955 uiInfo.serverStatusAddress, sizeof( uiInfo.serverStatusAddress ) ); 2956 UI_BuildServerStatus( qtrue ); 2957 } 2958 else if( Q_stricmp( name, "FoundPlayerServerStatus" ) == 0 ) 2959 { 2960 Q_strncpyz( uiInfo.serverStatusAddress, 2961 uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], 2962 sizeof( uiInfo.serverStatusAddress ) ); 2963 UI_BuildServerStatus( qtrue ); 2964 Menu_SetFeederSelection( NULL, FEEDER_FINDPLAYER, 0, NULL ); 2965 } 2966 else if( Q_stricmp( name, "FindPlayer" ) == 0 ) 2967 { 2968 UI_BuildFindPlayerList( qtrue ); 2969 // clear the displayed server status info 2970 uiInfo.serverStatusInfo.numLines = 0; 2971 Menu_SetFeederSelection( NULL, FEEDER_FINDPLAYER, 0, NULL ); 2972 } 2973 else if( Q_stricmp( name, "JoinServer" ) == 0 ) 2974 { 2975 if( uiInfo.serverStatus.currentServer >= 0 && 2976 uiInfo.serverStatus.currentServer < uiInfo.serverStatus.numDisplayServers ) 2977 { 2978 trap_LAN_GetServerAddressString( ui_netSource.integer, 2979 uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], 2980 buff, 1024 ); 2981 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", buff ) ); 2982 } 2983 } 2984 else if( Q_stricmp( name, "FoundPlayerJoinServer" ) == 0 ) 2985 { 2986 if( uiInfo.currentFoundPlayerServer >= 0 && 2987 uiInfo.currentFoundPlayerServer < uiInfo.numFoundPlayerServers ) 2988 { 2989 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", 2990 uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer] ) ); 2991 } 2992 } 2993 else if( Q_stricmp( name, "Quit" ) == 0 ) 2994 trap_Cmd_ExecuteText( EXEC_NOW, "quit" ); 2995 else if( Q_stricmp( name, "Leave" ) == 0 ) 2996 { 2997 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect\n" ); 2998 trap_Key_SetCatcher( KEYCATCH_UI ); 2999 Menus_CloseAll(); 3000 Menus_ActivateByName( "main" ); 3001 } 3002 else if( Q_stricmp( name, "ServerSort" ) == 0 ) 3003 { 3004 int sortColumn; 3005 3006 if( Int_Parse( args, &sortColumn ) ) 3007 { 3008 // if same column we're already sorting on then flip the direction 3009 3010 if( sortColumn == uiInfo.serverStatus.sortKey ) 3011 uiInfo.serverStatus.sortDir = !uiInfo.serverStatus.sortDir; 3012 3013 // make sure we sort again 3014 UI_ServersSort( sortColumn, qtrue ); 3015 3016 uiInfo.serverStatus.sorted = qtrue; 3017 } 3018 } 3019 else if( Q_stricmp( name, "closeingame" ) == 0 ) 3020 { 3021 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); 3022 trap_Key_ClearStates(); 3023 trap_Cvar_Set( "cl_paused", "0" ); 3024 Menus_CloseAll(); 3025 } 3026 else if( Q_stricmp( name, "voteMap" ) == 0 ) 3027 { 3028 if( ui_selectedMap.integer >= 0 && ui_selectedMap.integer < uiInfo.mapCount ) 3029 { 3030 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote map %s\n", 3031 uiInfo.mapList[ui_selectedMap.integer].mapLoadName ) ); 3032 } 3033 } 3034 else if( Q_stricmp( name, "voteKick" ) == 0 ) 3035 { 3036 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount ) 3037 { 3038 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote kick %d\n", 3039 uiInfo.clientNums[ uiInfo.playerIndex ] ) ); 3040 } 3041 } 3042 else if( Q_stricmp( name, "voteMute" ) == 0 ) 3043 { 3044 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount ) 3045 { 3046 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote mute %d\n", 3047 uiInfo.clientNums[ uiInfo.playerIndex ] ) ); 3048 } 3049 } 3050 else if( Q_stricmp( name, "voteUnMute" ) == 0 ) 3051 { 3052 if( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount ) 3053 { 3054 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote unmute %d\n", 3055 uiInfo.clientNums[ uiInfo.playerIndex ] ) ); 3056 } 3057 } 3058 else if( Q_stricmp( name, "voteTeamKick" ) == 0 ) 3059 { 3060 if( uiInfo.teamPlayerIndex >= 0 && uiInfo.teamPlayerIndex < uiInfo.myTeamCount ) 3061 { 3062 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote kick %d\n", 3063 uiInfo.teamClientNums[ uiInfo.teamPlayerIndex ] ) ); 3064 } 3065 } 3066 else if( Q_stricmp( name, "voteTeamDenyBuild" ) == 0 ) 3067 { 3068 if( uiInfo.teamPlayerIndex >= 0 && uiInfo.teamPlayerIndex < uiInfo.myTeamCount ) 3069 { 3070 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote denybuild %d\n", 3071 uiInfo.teamClientNums[ uiInfo.teamPlayerIndex ] ) ); 3072 } 3073 } 3074 else if( Q_stricmp( name, "voteTeamAllowBuild" ) == 0 ) 3075 { 3076 if( uiInfo.teamPlayerIndex >= 0 && uiInfo.teamPlayerIndex < uiInfo.myTeamCount ) 3077 { 3078 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote allowbuild %d\n", 3079 uiInfo.teamClientNums[ uiInfo.teamPlayerIndex ] ) ); 3080 } 3081 } 3082 else if( Q_stricmp( name, "addFavorite" ) == 0 ) 3083 { 3084 if( ui_netSource.integer != AS_FAVORITES ) 3085 { 3086 char name[MAX_NAME_LENGTH]; 3087 char addr[MAX_NAME_LENGTH]; 3088 int res; 3089 3090 trap_LAN_GetServerInfo( ui_netSource.integer, 3091 uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], 3092 buff, MAX_STRING_CHARS ); 3093 name[0] = addr[0] = '\0'; 3094 Q_strncpyz( name, Info_ValueForKey( buff, "hostname" ), MAX_NAME_LENGTH ); 3095 Q_strncpyz( addr, Info_ValueForKey( buff, "addr" ), MAX_NAME_LENGTH ); 3096 3097 if( strlen( name ) > 0 && strlen( addr ) > 0 ) 3098 { 3099 res = trap_LAN_AddServer( AS_FAVORITES, name, addr ); 3100 3101 if( res == 0 ) 3102 { 3103 // server already in the list 3104 Com_Printf( "Favorite already in list\n" ); 3105 } 3106 else if( res == -1 ) 3107 { 3108 // list full 3109 Com_Printf( "Favorite list full\n" ); 3110 } 3111 else 3112 { 3113 // successfully added 3114 Com_Printf( "Added favorite server %s\n", addr ); 3115 } 3116 } 3117 } 3118 } 3119 else if( Q_stricmp( name, "deleteFavorite" ) == 0 ) 3120 { 3121 if( ui_netSource.integer == AS_FAVORITES ) 3122 { 3123 char addr[MAX_NAME_LENGTH]; 3124 trap_LAN_GetServerInfo( ui_netSource.integer, 3125 uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], 3126 buff, MAX_STRING_CHARS ); 3127 addr[0] = '\0'; 3128 Q_strncpyz( addr, Info_ValueForKey( buff, "addr" ), MAX_NAME_LENGTH ); 3129 3130 if( strlen( addr ) > 0 ) 3131 trap_LAN_RemoveServer( AS_FAVORITES, addr ); 3132 } 3133 } 3134 else if( Q_stricmp( name, "createFavorite" ) == 0 ) 3135 { 3136 if( ui_netSource.integer == AS_FAVORITES ) 3137 { 3138 char name[MAX_NAME_LENGTH]; 3139 char addr[MAX_NAME_LENGTH]; 3140 int res; 3141 3142 name[0] = addr[0] = '\0'; 3143 Q_strncpyz( name, UI_Cvar_VariableString( "ui_favoriteName" ), MAX_NAME_LENGTH ); 3144 Q_strncpyz( addr, UI_Cvar_VariableString( "ui_favoriteAddress" ), MAX_NAME_LENGTH ); 3145 3146 if( strlen( name ) > 0 && strlen( addr ) > 0 ) 3147 { 3148 res = trap_LAN_AddServer( AS_FAVORITES, name, addr ); 3149 3150 if( res == 0 ) 3151 { 3152 // server already in the list 3153 Com_Printf( "Favorite already in list\n" ); 3154 } 3155 else if( res == -1 ) 3156 { 3157 // list full 3158 Com_Printf( "Favorite list full\n" ); 3159 } 3160 else 3161 { 3162 // successfully added 3163 Com_Printf( "Added favorite server %s\n", addr ); 3164 } 3165 } 3166 } 3167 } 3168 else if( Q_stricmp( name, "glCustom" ) == 0 ) 3169 trap_Cvar_Set( "ui_glCustom", "4" ); 3170 else if( Q_stricmp( name, "update" ) == 0 ) 3171 { 3172 if( String_Parse( args, &name2 ) ) 3173 UI_Update( name2 ); 3174 } 3175 else if( Q_stricmp( name, "InitIgnoreList" ) == 0 ) 3176 UI_BuildPlayerList(); 3177 else if( Q_stricmp( name, "ToggleIgnore" ) == 0 ) 3178 { 3179 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) 3180 { 3181 if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3182 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) 3183 { 3184 BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3185 uiInfo.clientNums[ uiInfo.ignoreIndex ] ); 3186 trap_Cmd_ExecuteText( EXEC_NOW, va( "unignore %i\n", 3187 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); 3188 } 3189 else 3190 { 3191 BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3192 uiInfo.clientNums[ uiInfo.ignoreIndex ] ); 3193 trap_Cmd_ExecuteText( EXEC_NOW, va( "ignore %i\n", 3194 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); 3195 } 3196 } 3197 } 3198 else if( Q_stricmp( name, "IgnorePlayer" ) == 0 ) 3199 { 3200 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) 3201 { 3202 if( !BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3203 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) 3204 { 3205 BG_ClientListAdd( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3206 uiInfo.clientNums[ uiInfo.ignoreIndex ] ); 3207 trap_Cmd_ExecuteText( EXEC_NOW, va( "ignore %i\n", 3208 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); 3209 } 3210 } 3211 } 3212 else if( Q_stricmp( name, "UnIgnorePlayer" ) == 0 ) 3213 { 3214 if( uiInfo.ignoreIndex >= 0 && uiInfo.ignoreIndex < uiInfo.playerCount ) 3215 { 3216 if( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3217 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ) 3218 { 3219 BG_ClientListRemove( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3220 uiInfo.clientNums[ uiInfo.ignoreIndex ] ); 3221 trap_Cmd_ExecuteText( EXEC_NOW, va( "unignore %i\n", 3222 uiInfo.clientNums[ uiInfo.ignoreIndex ] ) ); 3223 } 3224 } 3225 } 3226 else 3227 Com_Printf( "unknown UI script %s\n", name ); 4851 3228 } 4852 3229 } … … 4857 3234 ================== 4858 3235 */ 4859 static int UI_FeederCount(float feederID) { 4860 4861 if (feederID == FEEDER_HEADS) { 4862 return UI_HeadCountByTeam(); 4863 } else if (feederID == FEEDER_Q3HEADS) { 4864 return uiInfo.q3HeadCount; 4865 } else if (feederID == FEEDER_CINEMATICS) { 3236 static int UI_FeederCount( float feederID ) 3237 { 3238 if( feederID == FEEDER_CINEMATICS ) 4866 3239 return uiInfo.movieCount; 4867 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) {4868 return UI_MapCountByGameType(feederID == FEEDER_MAPS ? qtrue : qfalse);4869 } else if (feederID == FEEDER_SERVERS) {3240 else if( feederID == FEEDER_MAPS ) 3241 return uiInfo.mapCount; 3242 else if( feederID == FEEDER_SERVERS ) 4870 3243 return uiInfo.serverStatus.numDisplayServers; 4871 } else if (feederID == FEEDER_SERVERSTATUS) {3244 else if( feederID == FEEDER_SERVERSTATUS ) 4872 3245 return uiInfo.serverStatusInfo.numLines; 4873 } else if (feederID == FEEDER_FINDPLAYER) {3246 else if( feederID == FEEDER_FINDPLAYER ) 4874 3247 return uiInfo.numFoundPlayerServers; 4875 } else if (feederID == FEEDER_PLAYER_LIST) { 4876 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) { 3248 else if( feederID == FEEDER_PLAYER_LIST ) 3249 { 3250 if( uiInfo.uiDC.realTime > uiInfo.playerRefresh ) 3251 { 4877 3252 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000; 4878 3253 UI_BuildPlayerList(); 4879 3254 } 3255 4880 3256 return uiInfo.playerCount; 4881 } else if (feederID == FEEDER_TEAM_LIST) { 4882 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) { 3257 } 3258 else if( feederID == FEEDER_TEAM_LIST ) 3259 { 3260 if( uiInfo.uiDC.realTime > uiInfo.playerRefresh ) 3261 { 4883 3262 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000; 4884 3263 UI_BuildPlayerList(); 4885 3264 } 3265 4886 3266 return uiInfo.myTeamCount; 4887 } else if (feederID == FEEDER_IGNORE_LIST) { 3267 } 3268 else if( feederID == FEEDER_IGNORE_LIST ) 4888 3269 return uiInfo.playerCount; 4889 } else if (feederID == FEEDER_MODS) {3270 else if( feederID == FEEDER_MODS ) 4890 3271 return uiInfo.modCount; 4891 } else if (feederID == FEEDER_DEMOS) {3272 else if( feederID == FEEDER_DEMOS ) 4892 3273 return uiInfo.demoCount; 4893 }4894 3274 else if( feederID == FEEDER_TREMTEAMS ) 4895 return uiInfo.t remTeamCount;3275 return uiInfo.teamCount; 4896 3276 else if( feederID == FEEDER_TREMHUMANITEMS ) 4897 3277 return uiInfo.humanItemCount; … … 4912 3292 } 4913 3293 4914 static const char *UI_SelectedMap(int index, int *actual) { 3294 static const char *UI_SelectedMap( int index, int *actual ) 3295 { 4915 3296 int i, c; 4916 3297 c = 0; 4917 3298 *actual = 0; 4918 for (i = 0; i < uiInfo.mapCount; i++) { 4919 if (uiInfo.mapList[i].active) { 4920 if (c == index) { 4921 *actual = i; 4922 return uiInfo.mapList[i].mapName; 4923 } else { 4924 c++; 4925 } 4926 } 4927 } 3299 3300 for( i = 0; i < uiInfo.mapCount; i++ ) 3301 { 3302 if( c == index ) 3303 { 3304 *actual = i; 3305 return uiInfo.mapList[i].mapName; 3306 } 3307 else 3308 c++; 3309 } 3310 4928 3311 return ""; 4929 3312 } 4930 3313 4931 static const char *UI_SelectedHead(int index, int *actual) { 4932 int i, c; 4933 c = 0; 4934 *actual = 0; 4935 for (i = 0; i < uiInfo.characterCount; i++) { 4936 if (uiInfo.characterList[i].active) { 4937 if (c == index) { 4938 *actual = i; 4939 return uiInfo.characterList[i].name; 4940 } else { 4941 c++; 4942 } 4943 } 4944 } 4945 return ""; 4946 } 4947 4948 static int UI_GetIndexFromSelection(int actual) { 4949 int i, c; 4950 c = 0; 4951 for (i = 0; i < uiInfo.mapCount; i++) { 4952 if (uiInfo.mapList[i].active) { 4953 if (i == actual) { 4954 return c; 4955 } 4956 c++; 4957 } 4958 } 4959 return 0; 4960 } 4961 4962 static void UI_UpdatePendingPings( void ) { 4963 trap_LAN_ResetPings(ui_netSource.integer); 4964 uiInfo.serverStatus.refreshActive = qtrue; 4965 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 4966 4967 } 4968 4969 static const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t *handle) { 3314 static const char *UI_FeederItemText( float feederID, int index, int column, qhandle_t *handle ) 3315 { 4970 3316 static char info[MAX_STRING_CHARS]; 4971 3317 static char hostname[1024]; … … 4974 3320 static int lastTime = 0; 4975 3321 *handle = -1; 4976 if (feederID == FEEDER_HEADS) { 3322 3323 if( feederID == FEEDER_MAPS ) 3324 { 4977 3325 int actual; 4978 return UI_SelectedHead(index, &actual); 4979 } else if (feederID == FEEDER_Q3HEADS) { 4980 if (index >= 0 && index < uiInfo.q3HeadCount) { 4981 return uiInfo.q3HeadNames[index]; 4982 } 4983 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) { 4984 int actual; 4985 return UI_SelectedMap(index, &actual); 4986 } else if (feederID == FEEDER_SERVERS) { 4987 if (index >= 0 && index < uiInfo.serverStatus.numDisplayServers) { 3326 return UI_SelectedMap( index, &actual ); 3327 } 3328 else if( feederID == FEEDER_SERVERS ) 3329 { 3330 if( index >= 0 && index < uiInfo.serverStatus.numDisplayServers ) 3331 { 4988 3332 int ping; 4989 if (lastColumn != column || lastTime > uiInfo.uiDC.realTime + 5000) { 4990 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS); 3333 3334 if( lastColumn != column || lastTime > uiInfo.uiDC.realTime + 5000 ) 3335 { 3336 trap_LAN_GetServerInfo( ui_netSource.integer, uiInfo.serverStatus.displayServers[index], 3337 info, MAX_STRING_CHARS ); 4991 3338 lastColumn = column; 4992 3339 lastTime = uiInfo.uiDC.realTime; 4993 3340 } 4994 3341 4995 ping = atoi(Info_ValueForKey(info, "ping")); 4996 if (ping == -1) { 3342 ping = atoi( Info_ValueForKey( info, "ping" ) ); 3343 3344 if( ping == -1 ) 3345 { 4997 3346 // if we ever see a ping that is out of date, do a server refresh 4998 3347 // UI_UpdatePendingPings(); 4999 3348 } 5000 switch (column) { 5001 case SORT_HOST : 5002 if (ping <= 0) { 5003 return Info_ValueForKey(info, "addr"); 5004 } else { 5005 if ( ui_netSource.integer == AS_LOCAL ) { 5006 Com_sprintf( hostname, sizeof(hostname), "%s [%s]", 5007 Info_ValueForKey(info, "hostname"), 5008 netnames[atoi(Info_ValueForKey(info, "nettype"))] ); 3349 3350 switch( column ) 3351 { 3352 case SORT_HOST: 3353 if( ping <= 0 ) 3354 return Info_ValueForKey( info, "addr" ); 3355 else 3356 { 3357 if( ui_netSource.integer == AS_LOCAL ) 3358 { 3359 Com_sprintf( hostname, sizeof( hostname ), "%s [%s]", 3360 Info_ValueForKey( info, "hostname" ), 3361 netnames[atoi( Info_ValueForKey( info, "nettype" ) )] ); 5009 3362 return hostname; 5010 3363 } … … 5013 3366 char *text; 5014 3367 5015 Com_sprintf( hostname, sizeof( hostname), "%s", Info_ValueForKey(info, "hostname"));3368 Com_sprintf( hostname, sizeof( hostname ), "%s", Info_ValueForKey( info, "hostname" ) ); 5016 3369 5017 3370 // Strip leading whitespace 5018 3371 text = hostname; 3372 5019 3373 while( *text != '\0' && *text == ' ' ) 5020 3374 text++; … … 5023 3377 } 5024 3378 } 5025 case SORT_MAP : 5026 return Info_ValueForKey(info, "mapname"); 5027 case SORT_CLIENTS : 5028 Com_sprintf( clientBuff, sizeof(clientBuff), "%s (%s)", Info_ValueForKey(info, "clients"), Info_ValueForKey(info, "sv_maxclients")); 3379 3380 case SORT_MAP: 3381 return Info_ValueForKey( info, "mapname" ); 3382 3383 case SORT_CLIENTS: 3384 Com_sprintf( clientBuff, sizeof( clientBuff ), "%s (%s)", 3385 Info_ValueForKey( info, "clients" ), Info_ValueForKey( info, "sv_maxclients" ) ); 5029 3386 return clientBuff; 5030 case SORT_PING : 5031 if (ping <= 0) { 3387 3388 case SORT_PING: 3389 if( ping <= 0 ) 5032 3390 return "..."; 5033 } else { 5034 return Info_ValueForKey(info, "ping"); 5035 } 5036 } 5037 } 5038 } else if (feederID == FEEDER_SERVERSTATUS) { 5039 if ( index >= 0 && index < uiInfo.serverStatusInfo.numLines ) { 5040 if ( column >= 0 && column < 4 ) { 3391 else 3392 return Info_ValueForKey( info, "ping" ); 3393 } 3394 } 3395 } 3396 else if( feederID == FEEDER_SERVERSTATUS ) 3397 { 3398 if( index >= 0 && index < uiInfo.serverStatusInfo.numLines ) 3399 { 3400 if( column >= 0 && column < 4 ) 5041 3401 return uiInfo.serverStatusInfo.lines[index][column]; 5042 } 5043 } 5044 } else if (feederID == FEEDER_FINDPLAYER) { 5045 if ( index >= 0 && index < uiInfo.numFoundPlayerServers ) { 3402 } 3403 } 3404 else if( feederID == FEEDER_FINDPLAYER ) 3405 { 3406 if( index >= 0 && index < uiInfo.numFoundPlayerServers ) 3407 { 5046 3408 //return uiInfo.foundPlayerServerAddresses[index]; 5047 3409 return uiInfo.foundPlayerServerNames[index]; 5048 3410 } 5049 } else if (feederID == FEEDER_PLAYER_LIST) { 5050 if (index >= 0 && index < uiInfo.playerCount) { 3411 } 3412 else if( feederID == FEEDER_PLAYER_LIST ) 3413 { 3414 if( index >= 0 && index < uiInfo.playerCount ) 5051 3415 return uiInfo.playerNames[index]; 5052 } 5053 } else if (feederID == FEEDER_TEAM_LIST) { 5054 if (index >= 0 && index < uiInfo.myTeamCount) { 3416 } 3417 else if( feederID == FEEDER_TEAM_LIST ) 3418 { 3419 if( index >= 0 && index < uiInfo.myTeamCount ) 5055 3420 return uiInfo.teamNames[index]; 5056 } 5057 } else if (feederID == FEEDER_IGNORE_LIST) { 5058 if (index >= 0 && index < uiInfo.playerCount) { 3421 } 3422 else if( feederID == FEEDER_IGNORE_LIST ) 3423 { 3424 if( index >= 0 && index < uiInfo.playerCount ) 3425 { 5059 3426 switch( column ) 5060 3427 { 5061 3428 case 1: 5062 3429 // am I ignoring him 5063 return ( BG_ClientListTest(&uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 5064 uiInfo.clientNums[ index ] ) ) ? "X" : ""; 3430 return ( BG_ClientListTest( &uiInfo.ignoreList[ uiInfo.myPlayerIndex ], 3431 uiInfo.clientNums[ index ] ) ) ? "X" : ""; 3432 5065 3433 case 2: 5066 3434 // is he ignoring me 5067 3435 return ( BG_ClientListTest( &uiInfo.ignoreList[ index ], 5068 uiInfo.playerNumber ) ) ? "X" : ""; 3436 uiInfo.playerNumber ) ) ? "X" : ""; 3437 5069 3438 default: 5070 3439 return uiInfo.playerNames[index]; 5071 3440 } 5072 3441 } 5073 } else if (feederID == FEEDER_MODS) { 5074 if (index >= 0 && index < uiInfo.modCount) { 5075 if (uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr) { 3442 } 3443 else if( feederID == FEEDER_MODS ) 3444 { 3445 if( index >= 0 && index < uiInfo.modCount ) 3446 { 3447 if( uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr ) 5076 3448 return uiInfo.modList[index].modDescr; 5077 } else {3449 else 5078 3450 return uiInfo.modList[index].modName; 5079 } 5080 } 5081 } else if (feederID == FEEDER_CINEMATICS) { 5082 if (index >= 0 && index < uiInfo.movieCount) { 3451 } 3452 } 3453 else if( feederID == FEEDER_CINEMATICS ) 3454 { 3455 if( index >= 0 && index < uiInfo.movieCount ) 5083 3456 return uiInfo.movieList[index]; 5084 } 5085 } else if (feederID == FEEDER_DEMOS) { 5086 if (index >= 0 && index < uiInfo.demoCount) { 3457 } 3458 else if( feederID == FEEDER_DEMOS ) 3459 { 3460 if( index >= 0 && index < uiInfo.demoCount ) 5087 3461 return uiInfo.demoList[index]; 5088 }5089 3462 } 5090 3463 else if( feederID == FEEDER_TREMTEAMS ) 5091 3464 { 5092 if( index >= 0 && index < uiInfo.t remTeamCount )5093 return uiInfo.t remTeamList[ index ].text;3465 if( index >= 0 && index < uiInfo.teamCount ) 3466 return uiInfo.teamList[ index ].text; 5094 3467 } 5095 3468 else if( feederID == FEEDER_TREMHUMANITEMS ) … … 5133 3506 5134 3507 5135 static qhandle_t UI_FeederItemImage(float feederID, int index) { 5136 if (feederID == FEEDER_HEADS) { 5137 int actual; 5138 UI_SelectedHead(index, &actual); 5139 index = actual; 5140 if (index >= 0 && index < uiInfo.characterCount) { 5141 if (uiInfo.characterList[index].headImage == -1) { 5142 uiInfo.characterList[index].headImage = trap_R_RegisterShaderNoMip(uiInfo.characterList[index].imageName); 5143 } 5144 return uiInfo.characterList[index].headImage; 5145 } 5146 } else if (feederID == FEEDER_Q3HEADS) { 5147 if (index >= 0 && index < uiInfo.q3HeadCount) { 5148 return uiInfo.q3HeadIcons[index]; 5149 } 5150 } else if (feederID == FEEDER_ALLMAPS || feederID == FEEDER_MAPS) { 3508 static qhandle_t UI_FeederItemImage( float feederID, int index ) 3509 { 3510 if( feederID == FEEDER_MAPS ) 3511 { 5151 3512 int actual; 5152 UI_SelectedMap( index, &actual);3513 UI_SelectedMap( index, &actual ); 5153 3514 index = actual; 5154 if (index >= 0 && index < uiInfo.mapCount) { 5155 if (uiInfo.mapList[index].levelShot == -1) { 5156 uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[index].imageName); 5157 } 3515 3516 if( index >= 0 && index < uiInfo.mapCount ) 3517 { 3518 if( uiInfo.mapList[index].levelShot == -1 ) 3519 uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip( uiInfo.mapList[index].imageName ); 3520 5158 3521 return uiInfo.mapList[index].levelShot; 5159 3522 } 5160 3523 } 3524 5161 3525 return 0; 5162 3526 } 5163 3527 5164 static void UI_FeederSelection(float feederID, int index) { 3528 static void UI_FeederSelection( float feederID, int index ) 3529 { 5165 3530 static char info[MAX_STRING_CHARS]; 5166 if (feederID == FEEDER_HEADS) { 5167 int actual; 5168 UI_SelectedHead(index, &actual); 5169 index = actual; 5170 if (index >= 0 && index < uiInfo.characterCount) { 5171 trap_Cvar_Set( "team_model", va("%s", uiInfo.characterList[index].base)); 5172 trap_Cvar_Set( "team_headmodel", va("*%s", uiInfo.characterList[index].name)); 5173 updateModel = qtrue; 5174 } 5175 } else if (feederID == FEEDER_Q3HEADS) { 5176 if (index >= 0 && index < uiInfo.q3HeadCount) { 5177 trap_Cvar_Set( "model", uiInfo.q3HeadNames[index]); 5178 trap_Cvar_Set( "headmodel", uiInfo.q3HeadNames[index]); 5179 updateModel = qtrue; 5180 } 5181 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) { 3531 3532 if( feederID == FEEDER_MAPS ) 3533 { 5182 3534 int actual, map; 5183 map = (feederID == FEEDER_ALLMAPS) ? ui_currentNetMap.integer : ui_currentMap.integer; 5184 if (uiInfo.mapList[map].cinematic >= 0) { 5185 trap_CIN_StopCinematic(uiInfo.mapList[map].cinematic); 3535 map = ui_selectedMap.integer; 3536 3537 if( uiInfo.mapList[map].cinematic >= 0 ) 3538 { 3539 trap_CIN_StopCinematic( uiInfo.mapList[map].cinematic ); 5186 3540 uiInfo.mapList[map].cinematic = -1; 5187 3541 } 5188 UI_SelectedMap(index, &actual); 5189 trap_Cvar_Set("ui_mapIndex", va("%d", index)); 5190 ui_mapIndex.integer = index; 5191 5192 if (feederID == FEEDER_MAPS) { 5193 ui_currentMap.integer = actual; 5194 trap_Cvar_Set("ui_currentMap", va("%d", actual)); 5195 uiInfo.mapList[ui_currentMap.integer].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[ui_currentMap.integer].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) ); 5196 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum); 5197 trap_Cvar_Set("ui_opponentModel", uiInfo.mapList[ui_currentMap.integer].opponentName); 5198 updateOpponentModel = qtrue; 5199 } else { 5200 ui_currentNetMap.integer = actual; 5201 trap_Cvar_Set("ui_currentNetMap", va("%d", actual)); 5202 uiInfo.mapList[ui_currentNetMap.integer].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) ); 5203 } 5204 5205 } else if (feederID == FEEDER_SERVERS) { 5206 const char *mapName = NULL; 3542 3543 UI_SelectedMap( index, &actual ); 3544 3545 ui_selectedMap.integer = actual; 3546 trap_Cvar_Set( "ui_selectedMap", va( "%d", actual ) ); 3547 uiInfo.mapList[ui_selectedMap.integer].cinematic = 3548 trap_CIN_PlayCinematic( va( "%s.roq", uiInfo.mapList[ui_selectedMap.integer].mapLoadName ), 3549 0, 0, 0, 0, ( CIN_loop | CIN_silent ) ); 3550 } 3551 else if( feederID == FEEDER_SERVERS ) 3552 { 3553 const char * mapName = NULL; 5207 3554 uiInfo.serverStatus.currentServer = index; 5208 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS); 5209 uiInfo.serverStatus.currentServerPreview = trap_R_RegisterShaderNoMip(va("levelshots/%s", Info_ValueForKey(info, "mapname"))); 5210 if (uiInfo.serverStatus.currentServerCinematic >= 0) { 5211 trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic); 3555 trap_LAN_GetServerInfo( ui_netSource.integer, uiInfo.serverStatus.displayServers[index], 3556 info, MAX_STRING_CHARS ); 3557 uiInfo.serverStatus.currentServerPreview = 3558 trap_R_RegisterShaderNoMip( va( "levelshots/%s", Info_ValueForKey( info, "mapname" ) ) ); 3559 3560 if( uiInfo.serverStatus.currentServerCinematic >= 0 ) 3561 { 3562 trap_CIN_StopCinematic( uiInfo.serverStatus.currentServerCinematic ); 5212 3563 uiInfo.serverStatus.currentServerCinematic = -1; 5213 3564 } 5214 mapName = Info_ValueForKey(info, "mapname"); 5215 if (mapName && *mapName) { 5216 uiInfo.serverStatus.currentServerCinematic = trap_CIN_PlayCinematic(va("%s.roq", mapName), 0, 0, 0, 0, (CIN_loop | CIN_silent) ); 5217 } 5218 } else if (feederID == FEEDER_SERVERSTATUS) { 5219 // 5220 } else if (feederID == FEEDER_FINDPLAYER) { 3565 3566 mapName = Info_ValueForKey( info, "mapname" ); 3567 3568 if( mapName && *mapName ) 3569 { 3570 uiInfo.serverStatus.currentServerCinematic = 3571 trap_CIN_PlayCinematic( va( "%s.roq", mapName ), 0, 0, 0, 0, ( CIN_loop | CIN_silent ) ); 3572 } 3573 } 3574 else if( feederID == FEEDER_SERVERSTATUS ) 3575 { 3576 } 3577 else if( feederID == FEEDER_FINDPLAYER ) 3578 { 5221 3579 uiInfo.currentFoundPlayerServer = index; 5222 3580 // 5223 if ( index < uiInfo.numFoundPlayerServers-1) { 3581 3582 if( index < uiInfo.numFoundPlayerServers - 1 ) 3583 { 5224 3584 // build a new server status for this server 5225 Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress)); 5226 Menu_SetFeederSelection(NULL, FEEDER_SERVERSTATUS, 0, NULL); 5227 UI_BuildServerStatus(qtrue); 5228 } 5229 } else if (feederID == FEEDER_PLAYER_LIST) { 3585 Q_strncpyz( uiInfo.serverStatusAddress, 3586 uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], 3587 sizeof( uiInfo.serverStatusAddress ) ); 3588 Menu_SetFeederSelection( NULL, FEEDER_SERVERSTATUS, 0, NULL ); 3589 UI_BuildServerStatus( qtrue ); 3590 } 3591 } 3592 else if( feederID == FEEDER_PLAYER_LIST ) 5230 3593 uiInfo.playerIndex = index; 5231 } else if (feederID == FEEDER_TEAM_LIST) { 3594 else if( feederID == FEEDER_TEAM_LIST ) 3595 uiInfo.teamPlayerIndex = index; 3596 else if( feederID == FEEDER_IGNORE_LIST ) 3597 uiInfo.ignoreIndex = index; 3598 else if( feederID == FEEDER_MODS ) 3599 uiInfo.modIndex = index; 3600 else if( feederID == FEEDER_CINEMATICS ) 3601 { 3602 uiInfo.movieIndex = index; 3603 3604 if( uiInfo.previewMovie >= 0 ) 3605 trap_CIN_StopCinematic( uiInfo.previewMovie ); 3606 3607 uiInfo.previewMovie = -1; 3608 } 3609 else if( feederID == FEEDER_DEMOS ) 3610 uiInfo.demoIndex = index; 3611 else if( feederID == FEEDER_TREMTEAMS ) 5232 3612 uiInfo.teamIndex = index; 5233 } else if (feederID == FEEDER_IGNORE_LIST) {5234 uiInfo.ignoreIndex = index;5235 } else if (feederID == FEEDER_MODS) {5236 uiInfo.modIndex = index;5237 } else if (feederID == FEEDER_CINEMATICS) {5238 uiInfo.movieIndex = index;5239 if (uiInfo.previewMovie >= 0) {5240 trap_CIN_StopCinematic(uiInfo.previewMovie);5241 }5242 uiInfo.previewMovie = -1;5243 } else if (feederID == FEEDER_DEMOS) {5244 uiInfo.demoIndex = index;5245 }5246 else if( feederID == FEEDER_TREMTEAMS )5247 uiInfo.tremTeamIndex = index;5248 3613 else if( feederID == FEEDER_TREMHUMANITEMS ) 5249 3614 uiInfo.humanItemIndex = index; … … 5262 3627 } 5263 3628 5264 static void UI_Pause(qboolean b) { 5265 if (b) { 3629 static void UI_Pause( qboolean b ) 3630 { 3631 if( b ) 3632 { 5266 3633 // pause the game and set the ui keycatcher 5267 3634 trap_Cvar_Set( "cl_paused", "1" ); 5268 3635 trap_Key_SetCatcher( KEYCATCH_UI ); 5269 } else { 3636 } 3637 else 3638 { 5270 3639 // unpause the game and clear the ui keycatcher 5271 3640 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); … … 5275 3644 } 5276 3645 5277 static int UI_PlayCinematic(const char *name, float x, float y, float w, float h) { 5278 return trap_CIN_PlayCinematic(name, x, y, w, h, (CIN_loop | CIN_silent)); 5279 } 5280 5281 static void UI_StopCinematic(int handle) { 5282 if (handle >= 0) { 5283 trap_CIN_StopCinematic(handle); 5284 } else { 5285 handle = abs(handle); 5286 if (handle == UI_MAPCINEMATIC) { 5287 if (uiInfo.mapList[ui_currentMap.integer].cinematic >= 0) { 5288 trap_CIN_StopCinematic(uiInfo.mapList[ui_currentMap.integer].cinematic); 5289 uiInfo.mapList[ui_currentMap.integer].cinematic = -1; 5290 } 5291 } else if (handle == UI_NETMAPCINEMATIC) { 5292 if (uiInfo.serverStatus.currentServerCinematic >= 0) { 5293 trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic); 3646 static int UI_PlayCinematic( const char *name, float x, float y, float w, float h ) 3647 { 3648 return trap_CIN_PlayCinematic( name, x, y, w, h, ( CIN_loop | CIN_silent ) ); 3649 } 3650 3651 static void UI_StopCinematic( int handle ) 3652 { 3653 if( handle >= 0 ) 3654 trap_CIN_StopCinematic( handle ); 3655 else 3656 { 3657 handle = abs( handle ); 3658 3659 if( handle == UI_NETMAPCINEMATIC ) 3660 { 3661 if( uiInfo.serverStatus.currentServerCinematic >= 0 ) 3662 { 3663 trap_CIN_StopCinematic( uiInfo.serverStatus.currentServerCinematic ); 5294 3664 uiInfo.serverStatus.currentServerCinematic = -1; 5295 3665 } 5296 } else if (handle == UI_CLANCINEMATIC) { 5297 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName")); 5298 if (i >= 0 && i < uiInfo.teamCount) { 5299 if (uiInfo.teamList[i].cinematic >= 0) { 5300 trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic); 5301 uiInfo.teamList[i].cinematic = -1; 5302 } 5303 } 5304 } 5305 } 5306 } 5307 5308 static void UI_DrawCinematic(int handle, float x, float y, float w, float h) { 5309 trap_CIN_SetExtents(handle, x, y, w, h); 5310 trap_CIN_DrawCinematic(handle); 5311 } 5312 5313 static void UI_RunCinematicFrame(int handle) { 5314 trap_CIN_RunCinematic(handle); 3666 } 3667 } 3668 } 3669 3670 static void UI_DrawCinematic( int handle, float x, float y, float w, float h ) 3671 { 3672 trap_CIN_SetExtents( handle, x, y, w, h ); 3673 trap_CIN_DrawCinematic( handle ); 3674 } 3675 3676 static void UI_RunCinematicFrame( int handle ) 3677 { 3678 trap_CIN_RunCinematic( handle ); 3679 } 3680 3681 static float UI_GetValue( int ownerDraw ) 3682 { 3683 return 0.0f; 5315 3684 } 5316 3685 … … 5321 3690 ================= 5322 3691 */ 5323 void _UI_Init( qboolean inGameLoad ) { 3692 void UI_Init( qboolean inGameLoad ) 3693 { 5324 3694 int start; 5325 3695 … … 5327 3697 BG_InitAllowedGameElements( ); 5328 3698 5329 //uiInfo.inGameLoad = inGameLoad;3699 uiInfo.inGameLoad = inGameLoad; 5330 3700 5331 3701 UI_RegisterCvars(); … … 5336 3706 5337 3707 // for 640x480 virtualized screen 5338 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0); 5339 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0); 5340 if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) { 5341 // wide screen 5342 uiInfo.uiDC.bias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * (640.0/480.0) ) ); 5343 } 5344 else { 5345 // no wide screen 5346 uiInfo.uiDC.bias = 0; 5347 } 5348 5349 5350 //UI_Load(); 3708 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * ( 1.0f / 480.0f ); 3709 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * ( 1.0f / 640.0f ); 3710 3711 // wide screen 3712 uiInfo.uiDC.aspectScale = ( ( 640.0f * uiInfo.uiDC.glconfig.vidHeight ) / 3713 ( 480.0f * uiInfo.uiDC.glconfig.vidWidth ) ); 3714 5351 3715 uiInfo.uiDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip; 5352 3716 uiInfo.uiDC.setColor = &UI_SetColor; 5353 3717 uiInfo.uiDC.drawHandlePic = &UI_DrawHandlePic; 5354 3718 uiInfo.uiDC.drawStretchPic = &trap_R_DrawStretchPic; 5355 uiInfo.uiDC.drawText = &Text_Paint;5356 uiInfo.uiDC.textWidth = &Text_Width;5357 uiInfo.uiDC.textHeight = &Text_Height;5358 3719 uiInfo.uiDC.registerModel = &trap_R_RegisterModel; 5359 3720 uiInfo.uiDC.modelBounds = &trap_R_ModelBounds; 5360 3721 uiInfo.uiDC.fillRect = &UI_FillRect; 5361 uiInfo.uiDC.drawRect = & _UI_DrawRect;5362 uiInfo.uiDC.drawSides = & _UI_DrawSides;5363 uiInfo.uiDC.drawTopBottom = & _UI_DrawTopBottom;3722 uiInfo.uiDC.drawRect = &UI_DrawRect; 3723 uiInfo.uiDC.drawSides = &UI_DrawSides; 3724 uiInfo.uiDC.drawTopBottom = &UI_DrawTopBottom; 5364 3725 uiInfo.uiDC.clearScene = &trap_R_ClearScene; 5365 uiInfo.uiDC.drawSides = & _UI_DrawSides;3726 uiInfo.uiDC.drawSides = &UI_DrawSides; 5366 3727 uiInfo.uiDC.addRefEntityToScene = &trap_R_AddRefEntityToScene; 5367 3728 uiInfo.uiDC.renderScene = &trap_R_RenderScene; … … 5371 3732 uiInfo.uiDC.ownerDrawVisible = &UI_OwnerDrawVisible; 5372 3733 uiInfo.uiDC.runScript = &UI_RunMenuScript; 5373 uiInfo.uiDC.getTeamColor = &UI_GetTeamColor;5374 3734 uiInfo.uiDC.setCVar = trap_Cvar_Set; 5375 3735 uiInfo.uiDC.getCVarString = trap_Cvar_VariableStringBuffer; 5376 3736 uiInfo.uiDC.getCVarValue = trap_Cvar_VariableValue; 5377 uiInfo.uiDC.drawTextWithCursor = &Text_PaintWithCursor;5378 3737 uiInfo.uiDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode; 5379 3738 uiInfo.uiDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode; … … 5392 3751 uiInfo.uiDC.Pause = &UI_Pause; 5393 3752 uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth; 3753 uiInfo.uiDC.ownerDrawText = &UI_OwnerDrawText; 5394 3754 uiInfo.uiDC.registerSound = &trap_S_RegisterSound; 5395 3755 uiInfo.uiDC.startBackgroundTrack = &trap_S_StartBackgroundTrack; … … 5400 3760 uiInfo.uiDC.runCinematicFrame = &UI_RunCinematicFrame; 5401 3761 5402 Init_Display( &uiInfo.uiDC);3762 Init_Display( &uiInfo.uiDC ); 5403 3763 5404 3764 String_Init(); … … 5410 3770 start = trap_Milliseconds(); 5411 3771 5412 uiInfo.teamCount = 0; 5413 uiInfo.characterCount = 0; 5414 uiInfo.aliasCount = 0; 5415 5416 UI_LoadMenus("ui/menus.txt", qtrue); 5417 UI_LoadMenus("ui/ingame.txt", qfalse); 5418 UI_LoadMenus("ui/tremulous.txt", qfalse); 3772 UI_LoadMenus( "ui/menus.txt", qtrue ); 3773 UI_LoadMenus( "ui/ingame.txt", qfalse ); 3774 UI_LoadMenus( "ui/tremulous.txt", qfalse ); 5419 3775 5420 3776 Menus_CloseAll(); 5421 3777 5422 3778 trap_LAN_LoadCachedServers(); 5423 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);5424 3779 5425 3780 // sets defaults for ui temp cvars 5426 uiInfo.effectsColor = gamecodetoui[(int)trap_Cvar_VariableValue("color1")-1]; 5427 uiInfo.currentCrosshair = (int)trap_Cvar_VariableValue("cg_drawCrosshair"); 5428 trap_Cvar_Set("ui_mousePitch", (trap_Cvar_VariableValue("m_pitch") >= 0) ? "0" : "1"); 3781 trap_Cvar_Set( "ui_mousePitch", ( trap_Cvar_VariableValue( "m_pitch" ) >= 0 ) ? "0" : "1" ); 5429 3782 5430 3783 uiInfo.serverStatus.currentServerCinematic = -1; 5431 3784 uiInfo.previewMovie = -1; 5432 3785 5433 if (trap_Cvar_VariableValue("ui_TeamArenaFirstRun") == 0) { 5434 trap_Cvar_Set("s_volume", "0.8"); 5435 trap_Cvar_Set("s_musicvolume", "0.5"); 5436 trap_Cvar_Set("ui_TeamArenaFirstRun", "1"); 5437 } 5438 5439 trap_Cvar_Register(NULL, "debug_protocol", "", 0 ); 5440 5441 trap_Cvar_Set("ui_actualNetGameType", va("%d", ui_netGameType.integer)); 3786 trap_Cvar_Register( NULL, "debug_protocol", "", 0 ); 5442 3787 } 5443 3788 … … 5448 3793 ================= 5449 3794 */ 5450 void _UI_KeyEvent( int key, qboolean down ) { 5451 5452 if (Menu_Count() > 0) { 5453 menuDef_t *menu = Menu_GetFocused(); 5454 if (menu) { 5455 if (key == K_ESCAPE && down && !Menus_AnyFullScreenVisible()) { 3795 void UI_KeyEvent( int key, qboolean down ) 3796 { 3797 if( Menu_Count() > 0 ) 3798 { 3799 menuDef_t * menu = Menu_GetFocused(); 3800 3801 if( menu ) 3802 { 3803 if( key == K_ESCAPE && down && !Menus_AnyFullScreenVisible() ) 5456 3804 Menus_CloseAll(); 5457 } else { 5458 Menu_HandleKey(menu, key, down ); 5459 } 5460 } else { 3805 else 3806 Menu_HandleKey( menu, key, down ); 3807 } 3808 else 3809 { 5461 3810 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); 5462 3811 trap_Key_ClearStates(); … … 5464 3813 } 5465 3814 } 5466 5467 //if ((s > 0) && (s != menu_null_sound)) {5468 // trap_S_StartLocalSound( s, CHAN_LOCAL_SOUND );5469 //}5470 3815 } 5471 3816 … … 5475 3820 ================= 5476 3821 */ 5477 void _UI_MouseEvent( int dx, int dy )3822 void UI_MouseEvent( int dx, int dy ) 5478 3823 { 5479 3824 // update mouse screen position 5480 uiInfo.uiDC.cursorx += dx; 5481 if (uiInfo.uiDC.cursorx < 0) 3825 uiInfo.uiDC.cursorx += ( dx * uiInfo.uiDC.aspectScale ); 3826 3827 if( uiInfo.uiDC.cursorx < 0 ) 5482 3828 uiInfo.uiDC.cursorx = 0; 5483 else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH)3829 else if( uiInfo.uiDC.cursorx > SCREEN_WIDTH ) 5484 3830 uiInfo.uiDC.cursorx = SCREEN_WIDTH; 5485 3831 5486 3832 uiInfo.uiDC.cursory += dy; 5487 if (uiInfo.uiDC.cursory < 0) 3833 3834 if( uiInfo.uiDC.cursory < 0 ) 5488 3835 uiInfo.uiDC.cursory = 0; 5489 else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT)3836 else if( uiInfo.uiDC.cursory > SCREEN_HEIGHT ) 5490 3837 uiInfo.uiDC.cursory = SCREEN_HEIGHT; 5491 3838 5492 if (Menu_Count() > 0) { 5493 //menuDef_t *menu = Menu_GetFocused(); 5494 //Menu_HandleMouseMove(menu, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); 5495 Display_MouseMove(NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory); 5496 } 5497 5498 } 5499 5500 void UI_LoadNonIngame( void ) { 5501 UI_LoadMenus("ui/menus.txt", qfalse); 5502 uiInfo.inGameLoad = qfalse; 5503 } 5504 5505 void _UI_SetActiveMenu( uiMenuCommand_t menu ) { 3839 if( Menu_Count() > 0 ) 3840 Display_MouseMove( NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory ); 3841 } 3842 3843 void UI_SetActiveMenu( uiMenuCommand_t menu ) 3844 { 5506 3845 char buf[256]; 5507 3846 5508 3847 // this should be the ONLY way the menu system is brought up 5509 3848 // enusure minumum menu data is cached 5510 if (Menu_Count() > 0) { 3849 3850 if( Menu_Count() > 0 ) 3851 { 5511 3852 vec3_t v; 5512 3853 v[0] = v[1] = v[2] = 0; 5513 switch ( menu ) { 5514 case UIMENU_NONE: 5515 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); 5516 trap_Key_ClearStates(); 5517 trap_Cvar_Set( "cl_paused", "0" ); 5518 Menus_CloseAll(); 5519 5520 return; 5521 case UIMENU_MAIN: 5522 trap_Cvar_Set( "sv_killserver", "1" ); 5523 trap_Key_SetCatcher( KEYCATCH_UI ); 5524 //trap_S_StartLocalSound( trap_S_RegisterSound("sound/misc/menu_background.wav", qfalse) , CHAN_LOCAL_SOUND ); 5525 //trap_S_StartBackgroundTrack("sound/misc/menu_background.wav", NULL); 5526 if (uiInfo.inGameLoad) { 5527 UI_LoadNonIngame(); 5528 } 5529 Menus_CloseAll(); 5530 Menus_ActivateByName("main"); 5531 trap_Cvar_Set( "ui_loading", "0" ); 5532 trap_Cvar_VariableStringBuffer("com_errorMessage", buf, sizeof(buf)); 5533 if (strlen(buf)) { 5534 if (!ui_singlePlayerActive.integer) { 3854 3855 switch( menu ) 3856 { 3857 case UIMENU_NONE: 3858 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI ); 3859 trap_Key_ClearStates(); 3860 trap_Cvar_Set( "cl_paused", "0" ); 3861 Menus_CloseAll(); 3862 3863 return; 3864 3865 case UIMENU_MAIN: 3866 trap_Cvar_Set( "sv_killserver", "1" ); 3867 trap_Key_SetCatcher( KEYCATCH_UI ); 3868 Menus_CloseAll(); 3869 Menus_ActivateByName( "main" ); 3870 trap_Cvar_VariableStringBuffer( "com_errorMessage", buf, sizeof( buf ) ); 3871 3872 if( strlen( buf ) ) 3873 { 5535 3874 if( trap_Cvar_VariableValue( "com_errorCode" ) == ERR_SERVERDISCONNECT ) 5536 Menus_ActivateByName( "drop_popmenu");3875 Menus_ActivateByName( "drop_popmenu" ); 5537 3876 else 5538 Menus_ActivateByName("error_popmenu"); 5539 } else { 5540 trap_Cvar_Set("com_errorMessage", ""); 3877 Menus_ActivateByName( "error_popmenu" ); 5541 3878 } 5542 } 5543 return; 5544 case UIMENU_TEAM: 5545 trap_Key_SetCatcher( KEYCATCH_UI ); 5546 Menus_ActivateByName("team"); 5547 return; 5548 case UIMENU_POSTGAME: 5549 trap_Cvar_Set( "sv_killserver", "1" ); 5550 trap_Key_SetCatcher( KEYCATCH_UI ); 5551 if (uiInfo.inGameLoad) { 5552 UI_LoadNonIngame(); 5553 } 5554 Menus_CloseAll(); 5555 Menus_ActivateByName("endofgame"); 5556 return; 5557 case UIMENU_INGAME: 5558 trap_Cvar_Set( "cl_paused", "1" ); 5559 trap_Key_SetCatcher( KEYCATCH_UI ); 5560 UI_BuildPlayerList(); 5561 Menus_CloseAll(); 5562 Menus_ActivateByName("ingame"); 5563 return; 5564 } 5565 } 5566 } 5567 5568 qboolean _UI_IsFullscreen( void ) { 3879 3880 return; 3881 3882 case UIMENU_INGAME: 3883 trap_Cvar_Set( "cl_paused", "1" ); 3884 trap_Key_SetCatcher( KEYCATCH_UI ); 3885 UI_BuildPlayerList(); 3886 Menus_CloseAll(); 3887 Menus_ActivateByName( "ingame" ); 3888 return; 3889 } 3890 } 3891 } 3892 3893 qboolean UI_IsFullscreen( void ) 3894 { 5569 3895 return Menus_AnyFullScreenVisible(); 5570 3896 } … … 5577 3903 static void UI_ReadableSize ( char *buf, int bufsize, int value ) 5578 3904 { 5579 if (value > 1024*1024*1024 ) { // gigs 5580 Com_sprintf( buf, bufsize, "%d", value / (1024*1024*1024) ); 5581 Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d GB", 5582 (value % (1024*1024*1024))*100 / (1024*1024*1024) ); 5583 } else if (value > 1024*1024 ) { // megs 5584 Com_sprintf( buf, bufsize, "%d", value / (1024*1024) ); 5585 Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d MB", 5586 (value % (1024*1024))*100 / (1024*1024) ); 5587 } else if (value > 1024 ) { // kilos 3905 if( value > 1024 * 1024 * 1024 ) 3906 { // gigs 3907 Com_sprintf( buf, bufsize, "%d", value / ( 1024 * 1024 * 1024 ) ); 3908 Com_sprintf( buf + strlen( buf ), bufsize - strlen( buf ), ".%02d GB", 3909 ( value % ( 1024 * 1024 * 1024 ) ) * 100 / ( 1024 * 1024 * 1024 ) ); 3910 } 3911 else if( value > 1024 * 1024 ) 3912 { // megs 3913 Com_sprintf( buf, bufsize, "%d", value / ( 1024 * 1024 ) ); 3914 Com_sprintf( buf + strlen( buf ), bufsize - strlen( buf ), ".%02d MB", 3915 ( value % ( 1024 * 1024 ) ) * 100 / ( 1024 * 1024 ) ); 3916 } 3917 else if( value > 1024 ) 3918 { // kilos 5588 3919 Com_sprintf( buf, bufsize, "%d KB", value / 1024 ); 5589 } else { // bytes 3920 } 3921 else 3922 { // bytes 5590 3923 Com_sprintf( buf, bufsize, "%d bytes", value ); 5591 3924 } … … 5593 3926 5594 3927 // Assumes time is in msec 5595 static void UI_PrintTime ( char *buf, int bufsize, int time ) { 3928 static void UI_PrintTime ( char *buf, int bufsize, int time ) 3929 { 5596 3930 time /= 1000; // change to seconds 5597 3931 5598 if (time > 3600) { // in the hours range 5599 Com_sprintf( buf, bufsize, "%d hr %d min", time / 3600, (time % 3600) / 60 ); 5600 } else if (time > 60) { // mins 3932 if( time > 3600 ) 3933 { // in the hours range 3934 Com_sprintf( buf, bufsize, "%d hr %d min", time / 3600, ( time % 3600 ) / 60 ); 3935 } 3936 else if( time > 60 ) 3937 { // mins 5601 3938 Com_sprintf( buf, bufsize, "%d min %d sec", time / 60, time % 60 ); 5602 } else { // secs 3939 } 3940 else 3941 { // secs 5603 3942 Com_sprintf( buf, bufsize, "%d sec", time ); 5604 3943 } 5605 3944 } 5606 3945 5607 void Text_PaintCenter(float x, float y, float scale, vec4_t color, const char *text, float adjust) { 5608 int len = Text_Width(text, scale, 0); 5609 Text_Paint(x - len / 2, y, scale, color, text, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE); 5610 } 5611 5612 void Text_PaintCenter_AutoWrapped(float x, float y, float xmax, float ystep, float scale, vec4_t color, const char *str, float adjust) { 3946 // FIXME: move to ui_shared.c? 3947 void Text_PaintCenter( float x, float y, float scale, vec4_t color, const char *text, float adjust ) 3948 { 3949 int len = UI_Text_Width( text, scale, 0 ); 3950 UI_Text_Paint( x - len / 2, y, scale, color, text, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); 3951 } 3952 3953 void Text_PaintCenter_AutoWrapped( float x, float y, float xmax, float ystep, float scale, vec4_t color, const char *str, float adjust ) 3954 { 5613 3955 int width; 5614 char *s1, *s2,*s3;3956 char *s1, *s2, *s3; 5615 3957 char c_bcp; 5616 3958 char buf[1024]; 5617 3959 5618 if (!str || str[0]=='\0')3960 if( !str || str[0] == '\0' ) 5619 3961 return; 5620 3962 5621 Q_strncpyz(buf, str, sizeof(buf)); 3963 Q_strncpyz( buf, str, sizeof( buf ) ); 3964 5622 3965 s1 = s2 = s3 = buf; 5623 3966 5624 while (1) { 5625 do { 3967 while( 1 ) 3968 { 3969 do 5626 3970 s3++; 5627 } while (*s3!=' ' && *s3!='\0'); 3971 while( *s3 != ' ' && *s3 != '\0' ); 3972 5628 3973 c_bcp = *s3; 3974 5629 3975 *s3 = '\0'; 5630 width = Text_Width(s1, scale, 0); 3976 3977 width = UI_Text_Width( s1, scale, 0 ); 3978 5631 3979 *s3 = c_bcp; 5632 if (width > xmax) { 5633 if (s1==s2) 3980 3981 if( width > xmax ) 3982 { 3983 if( s1 == s2 ) 5634 3984 { 5635 3985 // fuck, don't have a clean cut, we'll overflow 5636 3986 s2 = s3; 5637 3987 } 3988 5638 3989 *s2 = '\0'; 5639 Text_PaintCenter( x, y, scale, color, s1, adjust);3990 Text_PaintCenter( x, y, scale, color, s1, adjust ); 5640 3991 y += ystep; 5641 if (c_bcp == '\0') 3992 3993 if( c_bcp == '\0' ) 5642 3994 { 5643 3995 // that was the last word … … 5646 3998 // so just print it now if needed 5647 3999 s2++; 5648 if (*s2 != '\0') // if we are printing an overflowing line we have s2 == s3 5649 Text_PaintCenter(x, y, scale, color, s2, adjust); 4000 4001 if( *s2 != '\0' ) // if we are printing an overflowing line we have s2 == s3 4002 Text_PaintCenter( x, y, scale, color, s2, adjust ); 4003 5650 4004 break; 5651 4005 } 4006 5652 4007 s2++; 5653 4008 s1 = s2; … … 5657 4012 { 5658 4013 s2 = s3; 5659 if (c_bcp == '\0') // we reached the end 5660 { 5661 Text_PaintCenter(x, y, scale, color, s1, adjust); 4014 4015 if( c_bcp == '\0' ) // we reached the end 4016 { 4017 Text_PaintCenter( x, y, scale, color, s1, adjust ); 5662 4018 break; 5663 4019 } … … 5667 4023 5668 4024 5669 static void UI_DisplayDownloadInfo( const char *downloadName, float centerPoint, float yStart, float scale ) { 4025 static void UI_DisplayDownloadInfo( const char *downloadName, float centerPoint, float yStart, float scale ) 4026 { 5670 4027 static char dlText[] = "Downloading:"; 5671 4028 static char etaText[] = "Estimated time left:"; … … 5684 4041 leftWidth = 320; 5685 4042 5686 UI_SetColor( colorWhite);5687 Text_PaintCenter( centerPoint, yStart + 112, scale, colorWhite, dlText, 0);5688 Text_PaintCenter( centerPoint, yStart + 192, scale, colorWhite, etaText, 0);5689 Text_PaintCenter( centerPoint, yStart + 248, scale, colorWhite, xferText, 0);5690 5691 if (downloadSize > 0) {5692 s = va( "%s (%d%%)", downloadName, downloadCount * 100 / downloadSize);5693 } else {4043 UI_SetColor( colorWhite ); 4044 Text_PaintCenter( centerPoint, yStart + 112, scale, colorWhite, dlText, 0 ); 4045 Text_PaintCenter( centerPoint, yStart + 192, scale, colorWhite, etaText, 0 ); 4046 Text_PaintCenter( centerPoint, yStart + 248, scale, colorWhite, xferText, 0 ); 4047 4048 if( downloadSize > 0 ) 4049 s = va( "%s (%d%%)", downloadName, ( int )( ( float )downloadCount * 100.0f / downloadSize ) ); 4050 else 5694 4051 s = downloadName; 5695 } 5696 5697 Text_PaintCenter(centerPoint, yStart+136, scale, colorWhite, s, 0); 4052 4053 Text_PaintCenter( centerPoint, yStart + 136, scale, colorWhite, s, 0 ); 5698 4054 5699 4055 UI_ReadableSize( dlSizeBuf, sizeof dlSizeBuf, downloadCount ); 5700 4056 UI_ReadableSize( totalSizeBuf, sizeof totalSizeBuf, downloadSize ); 5701 4057 5702 if (downloadCount < 4096 || !downloadTime) { 5703 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, "estimating", 0); 5704 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0); 5705 } else { 5706 if ((uiInfo.uiDC.realTime - downloadTime) / 1000) { 5707 xferRate = downloadCount / ((uiInfo.uiDC.realTime - downloadTime) / 1000); 5708 } else { 4058 if( downloadCount < 4096 || !downloadTime ) 4059 { 4060 Text_PaintCenter( leftWidth, yStart + 216, scale, colorWhite, "estimating", 0 ); 4061 Text_PaintCenter( leftWidth, yStart + 160, scale, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 ); 4062 } 4063 else 4064 { 4065 if( ( uiInfo.uiDC.realTime - downloadTime ) / 1000 ) 4066 xferRate = downloadCount / ( ( uiInfo.uiDC.realTime - downloadTime ) / 1000 ); 4067 else 5709 4068 xferRate = 0; 5710 } 4069 5711 4070 UI_ReadableSize( xferRateBuf, sizeof xferRateBuf, xferRate ); 5712 4071 5713 4072 // Extrapolate estimated completion time 5714 if (downloadSize && xferRate) { 4073 4074 if( downloadSize && xferRate ) 4075 { 5715 4076 int n = downloadSize / xferRate; // estimated time for entire d/l in secs 5716 4077 5717 4078 // We do it in K (/1024) because we'd overflow around 4MB 5718 4079 UI_PrintTime ( dlTimeBuf, sizeof dlTimeBuf, 5719 (n - (((downloadCount/1024) * n) / (downloadSize/1024))) * 1000); 5720 5721 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, dlTimeBuf, 0); 5722 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0); 5723 } else { 5724 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, "estimating", 0); 5725 if (downloadSize) { 5726 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0); 5727 } else { 5728 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s copied)", dlSizeBuf), 0); 5729 } 5730 } 5731 5732 if (xferRate) { 5733 Text_PaintCenter(leftWidth, yStart+272, scale, colorWhite, va("%s/Sec", xferRateBuf), 0); 5734 } 4080 ( n - ( ( ( downloadCount / 1024 ) * n ) / ( downloadSize / 1024 ) ) ) * 1000 ); 4081 4082 Text_PaintCenter( leftWidth, yStart + 216, scale, colorWhite, dlTimeBuf, 0 ); 4083 Text_PaintCenter( leftWidth, yStart + 160, scale, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 ); 4084 } 4085 else 4086 { 4087 Text_PaintCenter( leftWidth, yStart + 216, scale, colorWhite, "estimating", 0 ); 4088 4089 if( downloadSize ) 4090 Text_PaintCenter( leftWidth, yStart + 160, scale, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 ); 4091 else 4092 Text_PaintCenter( leftWidth, yStart + 160, scale, colorWhite, va( "(%s copied)", dlSizeBuf ), 0 ); 4093 } 4094 4095 if( xferRate ) 4096 Text_PaintCenter( leftWidth, yStart + 272, scale, colorWhite, va( "%s/Sec", xferRateBuf ), 0 ); 5735 4097 } 5736 4098 } … … 5739 4101 ======================== 5740 4102 UI_DrawConnectScreen 5741 5742 This will also be overlaid on the cgame info screen during loading5743 to prevent it from blinking away too rapidly on local or lan games.5744 4103 ======================== 5745 4104 */ 5746 void UI_DrawConnectScreen( qboolean overlay ) { 5747 char *s; 4105 void UI_DrawConnectScreen( qboolean overlay ) 4106 { 4107 char * s; 5748 4108 uiClientState_t cstate; 5749 4109 char info[MAX_INFO_VALUE]; … … 5751 4111 float centerPoint, yStart, scale; 5752 4112 5753 menuDef_t *menu = Menus_FindByName( "Connect");5754 5755 5756 if ( !overlay && menu ) {5757 Menu_Paint( menu, qtrue);5758 } 5759 5760 if (!overlay){4113 menuDef_t *menu = Menus_FindByName( "Connect" ); 4114 4115 4116 if( !overlay && menu ) 4117 Menu_Paint( menu, qtrue ); 4118 4119 if( !overlay ) 4120 { 5761 4121 centerPoint = 320; 5762 4122 yStart = 130; 5763 4123 scale = 0.5f; 5764 } else { 4124 } 4125 else 4126 { 5765 4127 centerPoint = 320; 5766 4128 yStart = 32; … … 5773 4135 5774 4136 info[0] = '\0'; 5775 if( trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ) ) { 5776 Text_PaintCenter(centerPoint, yStart, scale, colorWhite, va( "Loading %s", Info_ValueForKey( info, "mapname" )), 0); 5777 } 5778 5779 if (!Q_stricmp(cstate.servername,"localhost")) { 5780 Text_PaintCenter(centerPoint, yStart + 48, scale, colorWhite, va("Starting up..."), ITEM_TEXTSTYLE_SHADOWEDMORE); 5781 } else { 5782 strcpy(text, va("Connecting to %s", cstate.servername)); 5783 Text_PaintCenter(centerPoint, yStart + 48, scale, colorWhite,text , ITEM_TEXTSTYLE_SHADOWEDMORE); 4137 4138 if( trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ) ) 4139 Text_PaintCenter( centerPoint, yStart, scale, colorWhite, va( "Loading %s", Info_ValueForKey( info, "mapname" ) ), 0 ); 4140 4141 if( !Q_stricmp( cstate.servername, "localhost" ) ) 4142 Text_PaintCenter( centerPoint, yStart + 48, scale, colorWhite, va( "Starting up..." ), ITEM_TEXTSTYLE_SHADOWEDMORE ); 4143 else 4144 { 4145 strcpy( text, va( "Connecting to %s", cstate.servername ) ); 4146 Text_PaintCenter( centerPoint, yStart + 48, scale, colorWhite, text , ITEM_TEXTSTYLE_SHADOWEDMORE ); 5784 4147 } 5785 4148 5786 4149 5787 4150 // display global MOTD at bottom 5788 Text_PaintCenter(centerPoint, 600, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0); 4151 Text_PaintCenter( centerPoint, 600, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0 ); 4152 5789 4153 // print any server info (server full, bad version, etc) 5790 if ( cstate.connState < CA_CONNECTED ) { 5791 Text_PaintCenter_AutoWrapped(centerPoint, yStart + 176, 630, 20, scale, colorWhite, cstate.messageString, 0); 5792 } 5793 5794 if ( lastConnState > cstate.connState ) { 4154 if( cstate.connState < CA_CONNECTED ) 4155 Text_PaintCenter_AutoWrapped( centerPoint, yStart + 176, 630, 20, scale, colorWhite, cstate.messageString, 0 ); 4156 4157 if( lastConnState > cstate.connState ) 5795 4158 lastLoadingText[0] = '\0'; 5796 } 4159 5797 4160 lastConnState = cstate.connState; 5798 4161 5799 switch ( cstate.connState ) { 5800 case CA_CONNECTING: 5801 s = va("Awaiting connection...%i", cstate.connectPacketCount); 5802 break; 5803 case CA_CHALLENGING: 5804 s = va("Awaiting challenge...%i", cstate.connectPacketCount); 5805 break; 5806 case CA_CONNECTED: { 5807 char downloadName[MAX_INFO_VALUE]; 5808 5809 trap_Cvar_VariableStringBuffer( "cl_downloadName", downloadName, sizeof(downloadName) ); 5810 if (*downloadName) { 5811 UI_DisplayDownloadInfo( downloadName, centerPoint, yStart, scale ); 5812 return; 5813 } 5814 } 5815 s = "Awaiting gamestate..."; 5816 break; 5817 case CA_LOADING: 5818 return; 5819 case CA_PRIMED: 5820 return; 5821 default: 5822 return; 5823 } 5824 5825 5826 if (Q_stricmp(cstate.servername,"localhost")) { 5827 Text_PaintCenter(centerPoint, yStart + 80, scale, colorWhite, s, 0); 5828 } 4162 switch( cstate.connState ) 4163 { 4164 case CA_CONNECTING: 4165 s = va( "Awaiting connection...%i", cstate.connectPacketCount ); 4166 break; 4167 4168 case CA_CHALLENGING: 4169 s = va( "Awaiting challenge...%i", cstate.connectPacketCount ); 4170 break; 4171 4172 case CA_CONNECTED: 4173 { 4174 char downloadName[MAX_INFO_VALUE]; 4175 4176 trap_Cvar_VariableStringBuffer( "cl_downloadName", downloadName, sizeof( downloadName ) ); 4177 4178 if( *downloadName ) 4179 { 4180 UI_DisplayDownloadInfo( downloadName, centerPoint, yStart, scale ); 4181 return; 4182 } 4183 } 4184 4185 s = "Awaiting gamestate..."; 4186 break; 4187 4188 case CA_LOADING: 4189 return; 4190 4191 case CA_PRIMED: 4192 return; 4193 4194 default: 4195 return; 4196 } 4197 4198 4199 if( Q_stricmp( cstate.servername, "localhost" ) ) 4200 Text_PaintCenter( centerPoint, yStart + 80, scale, colorWhite, s, 0 ); 5829 4201 5830 4202 // password required / connection rejected information goes here 5831 4203 } 5832 5833 5834 /*5835 ================5836 cvars5837 ================5838 */5839 5840 typedef struct {5841 vmCvar_t *vmCvar;5842 char *cvarName;5843 char *defaultString;5844 int cvarFlags;5845 } cvarTable_t;5846 5847 vmCvar_t ui_ffa_fraglimit;5848 vmCvar_t ui_ffa_timelimit;5849 5850 vmCvar_t ui_tourney_fraglimit;5851 vmCvar_t ui_tourney_timelimit;5852 5853 vmCvar_t ui_team_fraglimit;5854 vmCvar_t ui_team_timelimit;5855 vmCvar_t ui_team_friendly;5856 5857 vmCvar_t ui_ctf_capturelimit;5858 vmCvar_t ui_ctf_timelimit;5859 vmCvar_t ui_ctf_friendly;5860 5861 vmCvar_t ui_arenasFile;5862 vmCvar_t ui_botsFile;5863 vmCvar_t ui_spScores1;5864 vmCvar_t ui_spScores2;5865 vmCvar_t ui_spScores3;5866 vmCvar_t ui_spScores4;5867 vmCvar_t ui_spScores5;5868 vmCvar_t ui_spAwards;5869 vmCvar_t ui_spVideos;5870 vmCvar_t ui_spSkill;5871 5872 vmCvar_t ui_spSelection;5873 5874 vmCvar_t ui_browserMaster;5875 vmCvar_t ui_browserGameType;5876 vmCvar_t ui_browserSortKey;5877 vmCvar_t ui_browserShowFull;5878 vmCvar_t ui_browserShowEmpty;5879 5880 vmCvar_t ui_brassTime;5881 vmCvar_t ui_drawCrosshair;5882 vmCvar_t ui_drawCrosshairNames;5883 vmCvar_t ui_marks;5884 5885 vmCvar_t ui_server1;5886 vmCvar_t ui_server2;5887 vmCvar_t ui_server3;5888 vmCvar_t ui_server4;5889 vmCvar_t ui_server5;5890 vmCvar_t ui_server6;5891 vmCvar_t ui_server7;5892 vmCvar_t ui_server8;5893 vmCvar_t ui_server9;5894 vmCvar_t ui_server10;5895 vmCvar_t ui_server11;5896 vmCvar_t ui_server12;5897 vmCvar_t ui_server13;5898 vmCvar_t ui_server14;5899 vmCvar_t ui_server15;5900 vmCvar_t ui_server16;5901 5902 vmCvar_t ui_redteam;5903 vmCvar_t ui_redteam1;5904 vmCvar_t ui_redteam2;5905 vmCvar_t ui_redteam3;5906 vmCvar_t ui_redteam4;5907 vmCvar_t ui_redteam5;5908 vmCvar_t ui_blueteam;5909 vmCvar_t ui_blueteam1;5910 vmCvar_t ui_blueteam2;5911 vmCvar_t ui_blueteam3;5912 vmCvar_t ui_blueteam4;5913 vmCvar_t ui_blueteam5;5914 vmCvar_t ui_teamName;5915 vmCvar_t ui_dedicated;5916 vmCvar_t ui_gameType;5917 vmCvar_t ui_netGameType;5918 vmCvar_t ui_actualNetGameType;5919 vmCvar_t ui_joinGameType;5920 vmCvar_t ui_netSource;5921 vmCvar_t ui_serverFilterType;5922 vmCvar_t ui_opponentName;5923 vmCvar_t ui_menuFiles;5924 vmCvar_t ui_currentTier;5925 vmCvar_t ui_currentMap;5926 vmCvar_t ui_currentNetMap;5927 vmCvar_t ui_mapIndex;5928 vmCvar_t ui_currentOpponent;5929 vmCvar_t ui_selectedPlayer;5930 vmCvar_t ui_selectedPlayerName;5931 vmCvar_t ui_lastServerRefresh_0;5932 vmCvar_t ui_lastServerRefresh_1;5933 vmCvar_t ui_lastServerRefresh_2;5934 vmCvar_t ui_lastServerRefresh_3;5935 vmCvar_t ui_lastServerRefresh_0_time;5936 vmCvar_t ui_lastServerRefresh_1_time;5937 vmCvar_t ui_lastServerRefresh_2_time;5938 vmCvar_t ui_lastServerRefresh_3_time;5939 vmCvar_t ui_singlePlayerActive;5940 vmCvar_t ui_scoreAccuracy;5941 vmCvar_t ui_scoreImpressives;5942 vmCvar_t ui_scoreExcellents;5943 vmCvar_t ui_scoreCaptures;5944 vmCvar_t ui_scoreDefends;5945 vmCvar_t ui_scoreAssists;5946 vmCvar_t ui_scoreGauntlets;5947 vmCvar_t ui_scoreScore;5948 vmCvar_t ui_scorePerfect;5949 vmCvar_t ui_scoreTeam;5950 vmCvar_t ui_scoreBase;5951 vmCvar_t ui_scoreTimeBonus;5952 vmCvar_t ui_scoreSkillBonus;5953 vmCvar_t ui_scoreShutoutBonus;5954 vmCvar_t ui_scoreTime;5955 vmCvar_t ui_captureLimit;5956 vmCvar_t ui_fragLimit;5957 vmCvar_t ui_smallFont;5958 vmCvar_t ui_bigFont;5959 vmCvar_t ui_findPlayer;5960 vmCvar_t ui_Q3Model;5961 vmCvar_t ui_hudFiles;5962 vmCvar_t ui_recordSPDemo;5963 vmCvar_t ui_realCaptureLimit;5964 vmCvar_t ui_realWarmUp;5965 vmCvar_t ui_serverStatusTimeOut;5966 5967 vmCvar_t ui_winner;5968 5969 static cvarTable_t cvarTable[] = {5970 { &ui_ffa_fraglimit, "ui_ffa_fraglimit", "20", CVAR_ARCHIVE },5971 { &ui_ffa_timelimit, "ui_ffa_timelimit", "0", CVAR_ARCHIVE },5972 5973 { &ui_tourney_fraglimit, "ui_tourney_fraglimit", "0", CVAR_ARCHIVE },5974 { &ui_tourney_timelimit, "ui_tourney_timelimit", "15", CVAR_ARCHIVE },5975 5976 { &ui_team_fraglimit, "ui_team_fraglimit", "0", CVAR_ARCHIVE },5977 { &ui_team_timelimit, "ui_team_timelimit", "20", CVAR_ARCHIVE },5978 { &ui_team_friendly, "ui_team_friendly", "1", CVAR_ARCHIVE },5979 5980 { &ui_ctf_capturelimit, "ui_ctf_capturelimit", "8", CVAR_ARCHIVE },5981 { &ui_ctf_timelimit, "ui_ctf_timelimit", "30", CVAR_ARCHIVE },5982 { &ui_ctf_friendly, "ui_ctf_friendly", "0", CVAR_ARCHIVE },5983 5984 { &ui_arenasFile, "g_arenasFile", "", CVAR_INIT|CVAR_ROM },5985 { &ui_botsFile, "g_botsFile", "", CVAR_INIT|CVAR_ROM },5986 { &ui_spScores1, "g_spScores1", "", CVAR_ARCHIVE | CVAR_ROM },5987 { &ui_spScores2, "g_spScores2", "", CVAR_ARCHIVE | CVAR_ROM },5988 { &ui_spScores3, "g_spScores3", "", CVAR_ARCHIVE | CVAR_ROM },5989 { &ui_spScores4, "g_spScores4", "", CVAR_ARCHIVE | CVAR_ROM },5990 { &ui_spScores5, "g_spScores5", "", CVAR_ARCHIVE | CVAR_ROM },5991 { &ui_spAwards, "g_spAwards", "", CVAR_ARCHIVE | CVAR_ROM },5992 { &ui_spVideos, "g_spVideos", "", CVAR_ARCHIVE | CVAR_ROM },5993 { &ui_spSkill, "g_spSkill", "2", CVAR_ARCHIVE },5994 5995 { &ui_spSelection, "ui_spSelection", "", CVAR_ROM },5996 { &ui_winner, "ui_winner", "", CVAR_ROM },5997 5998 { &ui_browserMaster, "ui_browserMaster", "0", CVAR_ARCHIVE },5999 { &ui_browserGameType, "ui_browserGameType", "0", CVAR_ARCHIVE },6000 { &ui_browserSortKey, "ui_browserSortKey", "4", CVAR_ARCHIVE },6001 { &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE },6002 { &ui_browserShowEmpty, "ui_browserShowEmpty", "1", CVAR_ARCHIVE },6003 6004 { &ui_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE },6005 { &ui_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },6006 { &ui_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },6007 { &ui_marks, "cg_marks", "1", CVAR_ARCHIVE },6008 6009 { &ui_server1, "server1", "", CVAR_ARCHIVE },6010 { &ui_server2, "server2", "", CVAR_ARCHIVE },6011 { &ui_server3, "server3", "", CVAR_ARCHIVE },6012 { &ui_server4, "server4", "", CVAR_ARCHIVE },6013 { &ui_server5, "server5", "", CVAR_ARCHIVE },6014 { &ui_server6, "server6", "", CVAR_ARCHIVE },6015 { &ui_server7, "server7", "", CVAR_ARCHIVE },6016 { &ui_server8, "server8", "", CVAR_ARCHIVE },6017 { &ui_server9, "server9", "", CVAR_ARCHIVE },6018 { &ui_server10, "server10", "", CVAR_ARCHIVE },6019 { &ui_server11, "server11", "", CVAR_ARCHIVE },6020 { &ui_server12, "server12", "", CVAR_ARCHIVE },6021 { &ui_server13, "server13", "", CVAR_ARCHIVE },6022 { &ui_server14, "server14", "", CVAR_ARCHIVE },6023 { &ui_server15, "server15", "", CVAR_ARCHIVE },6024 { &ui_server16, "server16", "", CVAR_ARCHIVE },6025 { &ui_new, "ui_new", "0", CVAR_TEMP },6026 { &ui_debug, "ui_debug", "0", CVAR_TEMP },6027 { &ui_initialized, "ui_initialized", "0", CVAR_TEMP },6028 { &ui_teamName, "ui_teamName", "Pagans", CVAR_ARCHIVE },6029 { &ui_opponentName, "ui_opponentName", "Stroggs", CVAR_ARCHIVE },6030 { &ui_redteam, "ui_redteam", "Pagans", CVAR_ARCHIVE },6031 { &ui_blueteam, "ui_blueteam", "Stroggs", CVAR_ARCHIVE },6032 { &ui_dedicated, "ui_dedicated", "0", CVAR_ARCHIVE },6033 { &ui_gameType, "ui_gametype", "3", CVAR_ARCHIVE },6034 { &ui_joinGameType, "ui_joinGametype", "0", CVAR_ARCHIVE },6035 { &ui_netGameType, "ui_netGametype", "3", CVAR_ARCHIVE },6036 { &ui_actualNetGameType, "ui_actualNetGametype", "3", CVAR_ARCHIVE },6037 { &ui_redteam1, "ui_redteam1", "0", CVAR_ARCHIVE },6038 { &ui_redteam2, "ui_redteam2", "0", CVAR_ARCHIVE },6039 { &ui_redteam3, "ui_redteam3", "0", CVAR_ARCHIVE },6040 { &ui_redteam4, "ui_redteam4", "0", CVAR_ARCHIVE },6041 { &ui_redteam5, "ui_redteam5", "0", CVAR_ARCHIVE },6042 { &ui_blueteam1, "ui_blueteam1", "0", CVAR_ARCHIVE },6043 { &ui_blueteam2, "ui_blueteam2", "0", CVAR_ARCHIVE },6044 { &ui_blueteam3, "ui_blueteam3", "0", CVAR_ARCHIVE },6045 { &ui_blueteam4, "ui_blueteam4", "0", CVAR_ARCHIVE },6046 { &ui_blueteam5, "ui_blueteam5", "0", CVAR_ARCHIVE },6047 { &ui_netSource, "ui_netSource", "0", CVAR_ARCHIVE },6048 { &ui_menuFiles, "ui_menuFiles", "ui/menus.txt", CVAR_ARCHIVE },6049 { &ui_currentTier, "ui_currentTier", "0", CVAR_ARCHIVE },6050 { &ui_currentMap, "ui_currentMap", "0", CVAR_ARCHIVE },6051 { &ui_currentNetMap, "ui_currentNetMap", "0", CVAR_ARCHIVE },6052 { &ui_mapIndex, "ui_mapIndex", "0", CVAR_ARCHIVE },6053 { &ui_currentOpponent, "ui_currentOpponent", "0", CVAR_ARCHIVE },6054 { &ui_selectedPlayer, "cg_selectedPlayer", "0", CVAR_ARCHIVE},6055 { &ui_selectedPlayerName, "cg_selectedPlayerName", "", CVAR_ARCHIVE},6056 { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0", "", CVAR_ARCHIVE},6057 { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1", "", CVAR_ARCHIVE},6058 { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2", "", CVAR_ARCHIVE},6059 { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3", "", CVAR_ARCHIVE},6060 { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0_time", "", CVAR_ARCHIVE},6061 { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1_time", "", CVAR_ARCHIVE},6062 { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2_time", "", CVAR_ARCHIVE},6063 { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3_time", "", CVAR_ARCHIVE},6064 { &ui_singlePlayerActive, "ui_singlePlayerActive", "0", 0},6065 { &ui_scoreAccuracy, "ui_scoreAccuracy", "0", CVAR_ARCHIVE},6066 { &ui_scoreImpressives, "ui_scoreImpressives", "0", CVAR_ARCHIVE},6067 { &ui_scoreExcellents, "ui_scoreExcellents", "0", CVAR_ARCHIVE},6068 { &ui_scoreCaptures, "ui_scoreCaptures", "0", CVAR_ARCHIVE},6069 { &ui_scoreDefends, "ui_scoreDefends", "0", CVAR_ARCHIVE},6070 { &ui_scoreAssists, "ui_scoreAssists", "0", CVAR_ARCHIVE},6071 { &ui_scoreGauntlets, "ui_scoreGauntlets", "0",CVAR_ARCHIVE},6072 { &ui_scoreScore, "ui_scoreScore", "0", CVAR_ARCHIVE},6073 { &ui_scorePerfect, "ui_scorePerfect", "0", CVAR_ARCHIVE},6074 { &ui_scoreTeam, "ui_scoreTeam", "0 to 0", CVAR_ARCHIVE},6075 { &ui_scoreBase, "ui_scoreBase", "0", CVAR_ARCHIVE},6076 { &ui_scoreTime, "ui_scoreTime", "00:00", CVAR_ARCHIVE},6077 { &ui_scoreTimeBonus, "ui_scoreTimeBonus", "0", CVAR_ARCHIVE},6078 { &ui_scoreSkillBonus, "ui_scoreSkillBonus", "0", CVAR_ARCHIVE},6079 { &ui_scoreShutoutBonus, "ui_scoreShutoutBonus", "0", CVAR_ARCHIVE},6080 { &ui_fragLimit, "ui_fragLimit", "10", 0},6081 { &ui_captureLimit, "ui_captureLimit", "5", 0},6082 { &ui_smallFont, "ui_smallFont", "0.2", CVAR_ARCHIVE},6083 { &ui_bigFont, "ui_bigFont", "0.5", CVAR_ARCHIVE},6084 { &ui_findPlayer, "ui_findPlayer", "Sarge", CVAR_ARCHIVE},6085 { &ui_Q3Model, "ui_q3model", "0", CVAR_ARCHIVE},6086 { &ui_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},6087 { &ui_recordSPDemo, "ui_recordSPDemo", "0", CVAR_ARCHIVE},6088 { &ui_teamArenaFirstRun, "ui_teamArenaFirstRun", "0", CVAR_ARCHIVE},6089 { &ui_realWarmUp, "g_warmup", "20", CVAR_ARCHIVE},6090 { &ui_realCaptureLimit, "capturelimit", "8", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART},6091 { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},6092 };6093 6094 static int cvarTableSize = sizeof(cvarTable) / sizeof(cvarTable[0]);6095 6096 4204 6097 4205 /* … … 6100 4208 ================= 6101 4209 */ 6102 void UI_RegisterCvars( void ) { 4210 void UI_RegisterCvars( void ) 4211 { 6103 4212 int i; 6104 4213 cvarTable_t *cv; 6105 4214 6106 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {4215 for( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 6107 4216 trap_Cvar_Register( cv->vmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags ); 6108 }6109 4217 } 6110 4218 … … 6114 4222 ================= 6115 4223 */ 6116 void UI_UpdateCvars( void ) { 4224 void UI_UpdateCvars( void ) 4225 { 6117 4226 int i; 6118 4227 cvarTable_t *cv; 6119 4228 6120 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {4229 for( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) 6121 4230 trap_Cvar_Update( cv->vmCvar ); 6122 } 6123 } 6124 6125 6126 /* 6127 ================= 6128 ArenaServers_StopRefresh 6129 ================= 6130 */ 6131 static void UI_StopServerRefresh( void ) 6132 { 6133 int count; 6134 6135 if (!uiInfo.serverStatus.refreshActive) { 6136 // not currently refreshing 6137 return; 6138 } 6139 uiInfo.serverStatus.refreshActive = qfalse; 6140 Com_Printf("%d servers listed in browser with %d players.\n", 6141 uiInfo.serverStatus.numDisplayServers, 6142 uiInfo.serverStatus.numPlayersOnServers); 6143 count = trap_LAN_GetServerCount(ui_netSource.integer); 6144 if (count - uiInfo.serverStatus.numDisplayServers > 0) { 6145 Com_Printf("%d servers not listed due to packet loss or pings higher than %d\n", 6146 count - uiInfo.serverStatus.numDisplayServers, 6147 (int) trap_Cvar_VariableValue("cl_maxPing")); 6148 } 6149 6150 } 6151 6152 /* 6153 ================= 6154 UI_DoServerRefresh 6155 ================= 6156 */ 6157 static void UI_DoServerRefresh( void ) 6158 { 6159 qboolean wait = qfalse; 6160 6161 if (!uiInfo.serverStatus.refreshActive) { 6162 return; 6163 } 6164 if (ui_netSource.integer != AS_FAVORITES) { 6165 if (ui_netSource.integer == AS_LOCAL) { 6166 if (!trap_LAN_GetServerCount(ui_netSource.integer)) { 6167 wait = qtrue; 6168 } 6169 } else { 6170 if (trap_LAN_GetServerCount(ui_netSource.integer) < 0) { 6171 wait = qtrue; 6172 } 6173 } 6174 } 6175 6176 if (uiInfo.uiDC.realTime < uiInfo.serverStatus.refreshtime) { 6177 if (wait) { 6178 return; 6179 } 6180 } 6181 6182 // if still trying to retrieve pings 6183 if (trap_LAN_UpdateVisiblePings(ui_netSource.integer)) { 6184 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 6185 } else if (!wait) { 6186 // get the last servers in the list 6187 UI_BuildServerDisplayList(2); 6188 // stop the refresh 6189 UI_StopServerRefresh(); 6190 } 6191 // 6192 UI_BuildServerDisplayList(qfalse); 6193 } 6194 6195 /* 6196 ================= 6197 UI_StartServerRefresh 6198 ================= 6199 */ 6200 static void UI_StartServerRefresh(qboolean full) 6201 { 6202 int i; 6203 char *ptr; 6204 int time; 6205 qtime_t q; 6206 6207 time = trap_RealTime(&q); 6208 trap_Cvar_Set( va("ui_lastServerRefresh_%i_time", ui_netSource.integer ), 6209 va( "%i", time ) ); 6210 trap_Cvar_Set( va("ui_lastServerRefresh_%i", ui_netSource.integer), 6211 va("%s-%i, %i at %i:%02i", MonthAbbrev[q.tm_mon],q.tm_mday, 1900+q.tm_year,q.tm_hour,q.tm_min)); 6212 6213 if (!full) { 6214 UI_UpdatePendingPings(); 6215 return; 6216 } 6217 6218 uiInfo.serverStatus.refreshActive = qtrue; 6219 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 1000; 6220 // clear number of displayed servers 6221 uiInfo.serverStatus.numDisplayServers = 0; 6222 uiInfo.serverStatus.numPlayersOnServers = 0; 6223 // mark all servers as visible so we store ping updates for them 6224 trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue); 6225 // reset all the pings 6226 trap_LAN_ResetPings(ui_netSource.integer); 6227 // 6228 if( ui_netSource.integer == AS_LOCAL ) { 6229 trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" ); 6230 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000; 6231 return; 6232 } 6233 6234 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000; 6235 if( ui_netSource.integer == AS_GLOBAL || ui_netSource.integer == AS_MPLAYER ) { 6236 if( ui_netSource.integer == AS_GLOBAL ) { 6237 i = 0; 6238 } 6239 else { 6240 i = 1; 6241 } 6242 6243 ptr = UI_Cvar_VariableString("debug_protocol"); 6244 if (strlen(ptr)) { 6245 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s full empty\n", i, ptr)); 6246 } 6247 else { 6248 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d full empty\n", i, (int)trap_Cvar_VariableValue( "protocol" ) ) ); 6249 } 6250 } 6251 } 6252 4231 } -
src/ui/ui_public.h
r119 r123 95 95 UI_R_REGISTERFONT, 96 96 UI_R_MODELBOUNDS, 97 UI_PARSE_ADD_GLOBAL_DEFINE, 98 UI_PARSE_LOAD_SOURCE, 99 UI_PARSE_FREE_SOURCE, 100 UI_PARSE_READ_TOKEN, 101 UI_PARSE_SOURCE_FILE_AND_LINE, 97 102 UI_S_STOPBACKGROUNDTRACK, 98 103 UI_S_STARTBACKGROUNDTRACK, … … 121 126 UI_FS_SEEK, 122 127 UI_SET_PBCLSTATUS, 123 124 UI_PARSE_ADD_GLOBAL_DEFINE,125 UI_PARSE_LOAD_SOURCE,126 UI_PARSE_FREE_SOURCE,127 UI_PARSE_READ_TOKEN,128 UI_PARSE_SOURCE_FILE_AND_LINE,129 128 130 129 UI_MEMSET = 100, -
src/ui/ui_public.h
r1 r123 3 3 Copyright (C) 1999-2005 Id Software, Inc. 4 4 Copyright (C) 2000-2006 Tim Angus 5 5 6 6 This file is part of Tremulous. 7 7 8 8 Tremulous is free software; you can redistribute it 9 9 and/or modify it under the terms of the GNU General Public License as 10 10 published by the Free Software Foundation; either version 2 of the License, 11 11 or (at your option) any later version. 12 12 13 13 Tremulous is distributed in the hope that it will be 14 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 GNU General Public License for more details. 17 17 18 18 You should have received a copy of the GNU General Public License 19 19 along with Tremulous; if not, write to the Free Software … … 22 22 */ 23 23 24 #ifndef __UI_PUBLIC_H__25 #define __UI_PUBLIC_H__24 #ifndef UI_PUBLIC_H 25 #define UI_PUBLIC_H 26 26 27 27 #define UI_API_VERSION 6 28 28 29 typedef struct { 29 typedef struct 30 { 30 31 connstate_t connState; 31 32 int connectPacketCount; … … 34 35 char updateInfoString[MAX_STRING_CHARS]; 35 36 char messageString[MAX_STRING_CHARS]; 36 } uiClientState_t; 37 } 38 uiClientState_t; 37 39 38 typedef enum { 40 typedef enum 41 { 39 42 UI_ERROR, 40 43 UI_PRINT, … … 133 136 UI_FLOOR, 134 137 UI_CEIL 135 } uiImport_t; 138 } 139 uiImport_t; 136 140 137 typedef enum { 141 typedef enum 142 { 138 143 UIMENU_NONE, 139 144 UIMENU_MAIN, 140 UIMENU_INGAME, 141 UIMENU_TEAM, 142 UIMENU_POSTGAME 143 } uiMenuCommand_t; 145 UIMENU_INGAME 146 } 147 uiMenuCommand_t; 144 148 145 149 typedef enum … … 149 153 SORT_CLIENTS, 150 154 SORT_PING 151 } serverSortField_t; 155 } 156 serverSortField_t; 152 157 153 typedef enum { 158 typedef enum 159 { 154 160 UI_GETAPIVERSION = 0, // system reserved 155 161 156 162 UI_INIT, 157 // void UI_Init( void );163 // void UI_Init( void ); 158 164 159 165 UI_SHUTDOWN, 160 // void UI_Shutdown( void );166 // void UI_Shutdown( void ); 161 167 162 168 UI_KEY_EVENT, 163 // void UI_KeyEvent( int key );169 // void UI_KeyEvent( int key ); 164 170 165 171 UI_MOUSE_EVENT, 166 // void UI_MouseEvent( int dx, int dy );172 // void UI_MouseEvent( int dx, int dy ); 167 173 168 174 UI_REFRESH, 169 // void UI_Refresh( int time );175 // void UI_Refresh( int time ); 170 176 171 177 UI_IS_FULLSCREEN, 172 // qboolean UI_IsFullscreen( void );178 // qboolean UI_IsFullscreen( void ); 173 179 174 180 UI_SET_ACTIVE_MENU, 175 // void UI_SetActiveMenu( uiMenuCommand_t menu );181 // void UI_SetActiveMenu( uiMenuCommand_t menu ); 176 182 177 183 UI_CONSOLE_COMMAND, 178 // qboolean UI_ConsoleCommand( int realTime );184 // qboolean UI_ConsoleCommand( int realTime ); 179 185 180 186 UI_DRAW_CONNECT_SCREEN 181 // void UI_DrawConnectScreen( qboolean overlay );187 // void UI_DrawConnectScreen( qboolean overlay ); 182 188 183 // if !overlay, the background will be drawn, otherwise it will be 184 // overlayed over whatever the cgame has drawn. 185 // a GetClientState syscall will be made to get the current strings 186 } uiExport_t; 189 // if !overlay, the background will be drawn, otherwise it will be 190 // overlayed over whatever the cgame has drawn. 191 // a GetClientState syscall will be made to get the current strings 192 } 193 uiExport_t; 187 194 188 195 #endif
