00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "ui_local.h"
00035
00036 uiInfo_t uiInfo;
00037
00038 static const char *MonthAbbrev[] = {
00039 "Jan","Feb","Mar",
00040 "Apr","May","Jun",
00041 "Jul","Aug","Sep",
00042 "Oct","Nov","Dec"
00043 };
00044
00045
00046 static const char *skillLevels[] = {
00047 "I Can Win",
00048 "Bring It On",
00049 "Hurt Me Plenty",
00050 "Hardcore",
00051 "Nightmare"
00052 };
00053
00054 static const int numSkillLevels = sizeof(skillLevels) / sizeof(const char*);
00055
00056
00057 static const char *netSources[] = {
00058 "Local",
00059 "Mplayer",
00060 "Internet",
00061 "Favorites"
00062 };
00063 static const int numNetSources = sizeof(netSources) / sizeof(const char*);
00064
00065 static const serverFilter_t serverFilters[] = {
00066 {"All", "" },
00067 {"Quake 3 Arena", "" },
00068 {"Team Arena", "missionpack" },
00069 {"Rocket Arena", "arena" },
00070 {"Alliance", "alliance20" },
00071 {"Weapons Factory Arena", "wfa" },
00072 {"OSP", "osp" },
00073 };
00074
00075 static const char *teamArenaGameTypes[] = {
00076 "FFA",
00077 "TOURNAMENT",
00078 "SP",
00079 "TEAM DM",
00080 "CTF",
00081 "1FCTF",
00082 "OVERLOAD",
00083 "HARVESTER",
00084 "TEAMTOURNAMENT"
00085 };
00086
00087 static int const numTeamArenaGameTypes = sizeof(teamArenaGameTypes) / sizeof(const char*);
00088
00089
00090 static const char *teamArenaGameNames[] = {
00091 "Free For All",
00092 "Tournament",
00093 "Single Player",
00094 "Team Deathmatch",
00095 "Capture the Flag",
00096 "One Flag CTF",
00097 "Overload",
00098 "Harvester",
00099 "Team Tournament",
00100 };
00101
00102 static int const numTeamArenaGameNames = sizeof(teamArenaGameNames) / sizeof(const char*);
00103
00104
00105 static const int numServerFilters = sizeof(serverFilters) / sizeof(serverFilter_t);
00106
00107 static const char *sortKeys[] = {
00108 "Server Name",
00109 "Map Name",
00110 "Open Player Spots",
00111 "Game Type",
00112 "Ping Time"
00113 };
00114 static const int numSortKeys = sizeof(sortKeys) / sizeof(const char*);
00115
00116 static char* netnames[] = {
00117 "???",
00118 "UDP",
00119 "IPX",
00120 NULL
00121 };
00122
00123 #ifndef MISSIONPACK // bk001206
00124 static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
00125 #endif
00126
00127 static int gamecodetoui[] = {4,2,3,0,5,1,6};
00128 static int uitogamecode[] = {4,6,2,3,1,5,7};
00129
00130
00131 static void UI_StartServerRefresh(qboolean full);
00132 static void UI_StopServerRefresh( void );
00133 static void UI_DoServerRefresh( void );
00134 static void UI_FeederSelection(float feederID, int index);
00135 static void UI_BuildServerDisplayList(qboolean force);
00136 static void UI_BuildServerStatus(qboolean force);
00137 static void UI_BuildFindPlayerList(qboolean force);
00138 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 );
00139 static int UI_MapCountByGameType(qboolean singlePlayer);
00140 static int UI_HeadCountByTeam( void );
00141 static void UI_ParseGameInfo(const char *teamFile);
00142 static void UI_ParseTeamInfo(const char *teamFile);
00143 static const char *UI_SelectedMap(int index, int *actual);
00144 static const char *UI_SelectedHead(int index, int *actual);
00145 static int UI_GetIndexFromSelection(int actual);
00146
00147 int ProcessNewUI( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 );
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 vmCvar_t ui_new;
00158 vmCvar_t ui_debug;
00159 vmCvar_t ui_initialized;
00160 vmCvar_t ui_teamArenaFirstRun;
00161
00162 void _UI_Init( qboolean );
00163 void _UI_Shutdown( void );
00164 void _UI_KeyEvent( int key, qboolean down );
00165 void _UI_MouseEvent( int dx, int dy );
00166 void _UI_Refresh( int realtime );
00167 qboolean _UI_IsFullscreen( void );
00168 int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) {
00169 switch ( command ) {
00170 case UI_GETAPIVERSION:
00171 return UI_API_VERSION;
00172
00173 case UI_INIT:
00174 _UI_Init(arg0);
00175 return 0;
00176
00177 case UI_SHUTDOWN:
00178 _UI_Shutdown();
00179 return 0;
00180
00181 case UI_KEY_EVENT:
00182 _UI_KeyEvent( arg0, arg1 );
00183 return 0;
00184
00185 case UI_MOUSE_EVENT:
00186 _UI_MouseEvent( arg0, arg1 );
00187 return 0;
00188
00189 case UI_REFRESH:
00190 _UI_Refresh( arg0 );
00191 return 0;
00192
00193 case UI_IS_FULLSCREEN:
00194 return _UI_IsFullscreen();
00195
00196 case UI_SET_ACTIVE_MENU:
00197 _UI_SetActiveMenu( arg0 );
00198 return 0;
00199
00200 case UI_CONSOLE_COMMAND:
00201 return UI_ConsoleCommand(arg0);
00202
00203 case UI_DRAW_CONNECT_SCREEN:
00204 UI_DrawConnectScreen( arg0 );
00205 return 0;
00206 case UI_HASUNIQUECDKEY:
00207 return qtrue;
00208
00209 }
00210
00211 return -1;
00212 }
00213
00214
00215
00216 void AssetCache() {
00217 int n;
00218
00219
00220
00221
00222 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
00223 uiInfo.uiDC.Assets.fxBasePic = trap_R_RegisterShaderNoMip( ART_FX_BASE );
00224 uiInfo.uiDC.Assets.fxPic[0] = trap_R_RegisterShaderNoMip( ART_FX_RED );
00225 uiInfo.uiDC.Assets.fxPic[1] = trap_R_RegisterShaderNoMip( ART_FX_YELLOW );
00226 uiInfo.uiDC.Assets.fxPic[2] = trap_R_RegisterShaderNoMip( ART_FX_GREEN );
00227 uiInfo.uiDC.Assets.fxPic[3] = trap_R_RegisterShaderNoMip( ART_FX_TEAL );
00228 uiInfo.uiDC.Assets.fxPic[4] = trap_R_RegisterShaderNoMip( ART_FX_BLUE );
00229 uiInfo.uiDC.Assets.fxPic[5] = trap_R_RegisterShaderNoMip( ART_FX_CYAN );
00230 uiInfo.uiDC.Assets.fxPic[6] = trap_R_RegisterShaderNoMip( ART_FX_WHITE );
00231 uiInfo.uiDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
00232 uiInfo.uiDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
00233 uiInfo.uiDC.Assets.scrollBarArrowUp = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
00234 uiInfo.uiDC.Assets.scrollBarArrowLeft = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
00235 uiInfo.uiDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
00236 uiInfo.uiDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
00237 uiInfo.uiDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
00238 uiInfo.uiDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
00239
00240 for( n = 0; n < NUM_CROSSHAIRS; n++ ) {
00241 uiInfo.uiDC.Assets.crosshairShader[n] = trap_R_RegisterShaderNoMip( va("gfx/2d/crosshair%c", 'a' + n ) );
00242 }
00243
00244 uiInfo.newHighScoreSound = trap_S_RegisterSound("sound/feedback/voc_newhighscore.wav", qfalse);
00245 }
00246
00247 void _UI_DrawSides(float x, float y, float w, float h, float size) {
00248 UI_AdjustFrom640( &x, &y, &w, &h );
00249 size *= uiInfo.uiDC.xscale;
00250 trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00251 trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00252 }
00253
00254 void _UI_DrawTopBottom(float x, float y, float w, float h, float size) {
00255 UI_AdjustFrom640( &x, &y, &w, &h );
00256 size *= uiInfo.uiDC.yscale;
00257 trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00258 trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
00268 trap_R_SetColor( color );
00269
00270 _UI_DrawTopBottom(x, y, width, height, size);
00271 _UI_DrawSides(x, y, width, height, size);
00272
00273 trap_R_SetColor( NULL );
00274 }
00275
00276 int Text_Width(const char *text, float scale, int limit) {
00277 int count,len;
00278 float out;
00279 glyphInfo_t *glyph;
00280 float useScale;
00281 const char *s = text;
00282 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00283 if (scale <= ui_smallFont.value) {
00284 font = &uiInfo.uiDC.Assets.smallFont;
00285 } else if (scale >= ui_bigFont.value) {
00286 font = &uiInfo.uiDC.Assets.bigFont;
00287 }
00288 useScale = scale * font->glyphScale;
00289 out = 0;
00290 if (text) {
00291 len = strlen(text);
00292 if (limit > 0 && len > limit) {
00293 len = limit;
00294 }
00295 count = 0;
00296 while (s && *s && count < len) {
00297 if ( Q_IsColorString(s) ) {
00298 s += 2;
00299 continue;
00300 } else {
00301 glyph = &font->glyphs[(int)*s];
00302 out += glyph->xSkip;
00303 s++;
00304 count++;
00305 }
00306 }
00307 }
00308 return out * useScale;
00309 }
00310
00311 int Text_Height(const char *text, float scale, int limit) {
00312 int len, count;
00313 float max;
00314 glyphInfo_t *glyph;
00315 float useScale;
00316 const char *s = text;
00317 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00318 if (scale <= ui_smallFont.value) {
00319 font = &uiInfo.uiDC.Assets.smallFont;
00320 } else if (scale >= ui_bigFont.value) {
00321 font = &uiInfo.uiDC.Assets.bigFont;
00322 }
00323 useScale = scale * font->glyphScale;
00324 max = 0;
00325 if (text) {
00326 len = strlen(text);
00327 if (limit > 0 && len > limit) {
00328 len = limit;
00329 }
00330 count = 0;
00331 while (s && *s && count < len) {
00332 if ( Q_IsColorString(s) ) {
00333 s += 2;
00334 continue;
00335 } else {
00336 glyph = &font->glyphs[(int)*s];
00337 if (max < glyph->height) {
00338 max = glyph->height;
00339 }
00340 s++;
00341 count++;
00342 }
00343 }
00344 }
00345 return max * useScale;
00346 }
00347
00348 void Text_PaintChar(float x, float y, float width, float height, float scale, float s, float t, float s2, float t2, qhandle_t hShader) {
00349 float w, h;
00350 w = width * scale;
00351 h = height * scale;
00352 UI_AdjustFrom640( &x, &y, &w, &h );
00353 trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader );
00354 }
00355
00356 void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style) {
00357 int len, count;
00358 vec4_t newColor;
00359 glyphInfo_t *glyph;
00360 float useScale;
00361 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00362 if (scale <= ui_smallFont.value) {
00363 font = &uiInfo.uiDC.Assets.smallFont;
00364 } else if (scale >= ui_bigFont.value) {
00365 font = &uiInfo.uiDC.Assets.bigFont;
00366 }
00367 useScale = scale * font->glyphScale;
00368 if (text) {
00369 const char *s = text;
00370 trap_R_SetColor( color );
00371 memcpy(&newColor[0], &color[0], sizeof(vec4_t));
00372 len = strlen(text);
00373 if (limit > 0 && len > limit) {
00374 len = limit;
00375 }
00376 count = 0;
00377 while (s && *s && count < len) {
00378 glyph = &font->glyphs[(int)*s];
00379
00380
00381 if ( Q_IsColorString( s ) ) {
00382 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00383 newColor[3] = color[3];
00384 trap_R_SetColor( newColor );
00385 s += 2;
00386 continue;
00387 } else {
00388 float yadj = useScale * glyph->top;
00389 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
00390 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
00391 colorBlack[3] = newColor[3];
00392 trap_R_SetColor( colorBlack );
00393 Text_PaintChar(x + ofs, y - yadj + ofs,
00394 glyph->imageWidth,
00395 glyph->imageHeight,
00396 useScale,
00397 glyph->s,
00398 glyph->t,
00399 glyph->s2,
00400 glyph->t2,
00401 glyph->glyph);
00402 trap_R_SetColor( newColor );
00403 colorBlack[3] = 1.0;
00404 }
00405 Text_PaintChar(x, y - yadj,
00406 glyph->imageWidth,
00407 glyph->imageHeight,
00408 useScale,
00409 glyph->s,
00410 glyph->t,
00411 glyph->s2,
00412 glyph->t2,
00413 glyph->glyph);
00414
00415 x += (glyph->xSkip * useScale) + adjust;
00416 s++;
00417 count++;
00418 }
00419 }
00420 trap_R_SetColor( NULL );
00421 }
00422 }
00423
00424 void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style) {
00425 int len, count;
00426 vec4_t newColor;
00427 glyphInfo_t *glyph, *glyph2;
00428 float yadj;
00429 float useScale;
00430 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00431 if (scale <= ui_smallFont.value) {
00432 font = &uiInfo.uiDC.Assets.smallFont;
00433 } else if (scale >= ui_bigFont.value) {
00434 font = &uiInfo.uiDC.Assets.bigFont;
00435 }
00436 useScale = scale * font->glyphScale;
00437 if (text) {
00438 const char *s = text;
00439 trap_R_SetColor( color );
00440 memcpy(&newColor[0], &color[0], sizeof(vec4_t));
00441 len = strlen(text);
00442 if (limit > 0 && len > limit) {
00443 len = limit;
00444 }
00445 count = 0;
00446 glyph2 = &font->glyphs[ (int) cursor];
00447 while (s && *s && count < len) {
00448 glyph = &font->glyphs[(int)*s];
00449
00450
00451 if ( Q_IsColorString( s ) ) {
00452 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00453 newColor[3] = color[3];
00454 trap_R_SetColor( newColor );
00455 s += 2;
00456 continue;
00457 } else {
00458 yadj = useScale * glyph->top;
00459 if (style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE) {
00460 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
00461 colorBlack[3] = newColor[3];
00462 trap_R_SetColor( colorBlack );
00463 Text_PaintChar(x + ofs, y - yadj + ofs,
00464 glyph->imageWidth,
00465 glyph->imageHeight,
00466 useScale,
00467 glyph->s,
00468 glyph->t,
00469 glyph->s2,
00470 glyph->t2,
00471 glyph->glyph);
00472 colorBlack[3] = 1.0;
00473 trap_R_SetColor( newColor );
00474 }
00475 Text_PaintChar(x, y - yadj,
00476 glyph->imageWidth,
00477 glyph->imageHeight,
00478 useScale,
00479 glyph->s,
00480 glyph->t,
00481 glyph->s2,
00482 glyph->t2,
00483 glyph->glyph);
00484
00485 yadj = useScale * glyph2->top;
00486 if (count == cursorPos && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
00487 Text_PaintChar(x, y - yadj,
00488 glyph2->imageWidth,
00489 glyph2->imageHeight,
00490 useScale,
00491 glyph2->s,
00492 glyph2->t,
00493 glyph2->s2,
00494 glyph2->t2,
00495 glyph2->glyph);
00496 }
00497
00498 x += (glyph->xSkip * useScale);
00499 s++;
00500 count++;
00501 }
00502 }
00503
00504 if (cursorPos == len && !((uiInfo.uiDC.realTime/BLINK_DIVISOR) & 1)) {
00505 yadj = useScale * glyph2->top;
00506 Text_PaintChar(x, y - yadj,
00507 glyph2->imageWidth,
00508 glyph2->imageHeight,
00509 useScale,
00510 glyph2->s,
00511 glyph2->t,
00512 glyph2->s2,
00513 glyph2->t2,
00514 glyph2->glyph);
00515
00516 }
00517
00518 trap_R_SetColor( NULL );
00519 }
00520 }
00521
00522
00523 static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
00524 int len, count;
00525 vec4_t newColor;
00526 glyphInfo_t *glyph;
00527 if (text) {
00528 const char *s = text;
00529 float max = *maxX;
00530 float useScale;
00531 fontInfo_t *font = &uiInfo.uiDC.Assets.textFont;
00532 if (scale <= ui_smallFont.value) {
00533 font = &uiInfo.uiDC.Assets.smallFont;
00534 } else if (scale > ui_bigFont.value) {
00535 font = &uiInfo.uiDC.Assets.bigFont;
00536 }
00537 useScale = scale * font->glyphScale;
00538 trap_R_SetColor( color );
00539 len = strlen(text);
00540 if (limit > 0 && len > limit) {
00541 len = limit;
00542 }
00543 count = 0;
00544 while (s && *s && count < len) {
00545 glyph = &font->glyphs[(int)*s];
00546 if ( Q_IsColorString( s ) ) {
00547 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
00548 newColor[3] = color[3];
00549 trap_R_SetColor( newColor );
00550 s += 2;
00551 continue;
00552 } else {
00553 float yadj = useScale * glyph->top;
00554 if (Text_Width(s, useScale, 1) + x > max) {
00555 *maxX = 0;
00556 break;
00557 }
00558 Text_PaintChar(x, y - yadj,
00559 glyph->imageWidth,
00560 glyph->imageHeight,
00561 useScale,
00562 glyph->s,
00563 glyph->t,
00564 glyph->s2,
00565 glyph->t2,
00566 glyph->glyph);
00567 x += (glyph->xSkip * useScale) + adjust;
00568 *maxX = x;
00569 count++;
00570 s++;
00571 }
00572 }
00573 trap_R_SetColor( NULL );
00574 }
00575
00576 }
00577
00578
00579 void UI_ShowPostGame(qboolean newHigh) {
00580 trap_Cvar_Set ("cg_cameraOrbit", "0");
00581 trap_Cvar_Set("cg_thirdPerson", "0");
00582 trap_Cvar_Set( "sv_killserver", "1" );
00583 uiInfo.soundHighScore = newHigh;
00584 _UI_SetActiveMenu(UIMENU_POSTGAME);
00585 }
00586
00587
00588
00589
00590
00591
00592 void UI_DrawCenteredPic(qhandle_t image, int w, int h) {
00593 int x, y;
00594 x = (SCREEN_WIDTH - w) / 2;
00595 y = (SCREEN_HEIGHT - h) / 2;
00596 UI_DrawHandlePic(x, y, w, h, image);
00597 }
00598
00599 int frameCount = 0;
00600 int startTime;
00601
00602 #define UI_FPS_FRAMES 4
00603 void _UI_Refresh( int realtime )
00604 {
00605 static int index;
00606 static int previousTimes[UI_FPS_FRAMES];
00607
00608
00609
00610
00611
00612 uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime;
00613 uiInfo.uiDC.realTime = realtime;
00614
00615 previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime;
00616 index++;
00617 if ( index > UI_FPS_FRAMES ) {
00618 int i, total;
00619
00620 total = 0;
00621 for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) {
00622 total += previousTimes[i];
00623 }
00624 if ( !total ) {
00625 total = 1;
00626 }
00627 uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total;
00628 }
00629
00630
00631
00632 UI_UpdateCvars();
00633
00634 if (Menu_Count() > 0) {
00635
00636 Menu_PaintAll();
00637
00638 UI_DoServerRefresh();
00639
00640 UI_BuildServerStatus(qfalse);
00641
00642 UI_BuildFindPlayerList(qfalse);
00643 }
00644
00645
00646 UI_SetColor( NULL );
00647 if (Menu_Count() > 0) {
00648 UI_DrawHandlePic( uiInfo.uiDC.cursorx-16, uiInfo.uiDC.cursory-16, 32, 32, uiInfo.uiDC.Assets.cursor);
00649 }
00650
00651 #ifndef NDEBUG
00652 if (uiInfo.uiDC.debug)
00653 {
00654
00655
00656
00657 }
00658 #endif
00659
00660 }
00661
00662
00663
00664
00665
00666
00667 void _UI_Shutdown( void ) {
00668 trap_LAN_SaveCachedServers();
00669 }
00670
00671 char *defaultMenu = NULL;
00672
00673 char *GetMenuBuffer(const char *filename) {
00674 int len;
00675 fileHandle_t f;
00676 static char buf[MAX_MENUFILE];
00677
00678 len = trap_FS_FOpenFile( filename, &f, FS_READ );
00679 if ( !f ) {
00680 trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
00681 return defaultMenu;
00682 }
00683 if ( len >= MAX_MENUFILE ) {
00684 trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
00685 trap_FS_FCloseFile( f );
00686 return defaultMenu;
00687 }
00688
00689 trap_FS_Read( buf, len, f );
00690 buf[len] = 0;
00691 trap_FS_FCloseFile( f );
00692
00693 return buf;
00694
00695 }
00696
00697 qboolean Asset_Parse(int handle) {
00698 pc_token_t token;
00699 const char *tempStr;
00700
00701 if (!trap_PC_ReadToken(handle, &token))
00702 return qfalse;
00703 if (Q_stricmp(token.string, "{") != 0) {
00704 return qfalse;
00705 }
00706
00707 while ( 1 ) {
00708
00709 memset(&token, 0, sizeof(pc_token_t));
00710
00711 if (!trap_PC_ReadToken(handle, &token))
00712 return qfalse;
00713
00714 if (Q_stricmp(token.string, "}") == 0) {
00715 return qtrue;
00716 }
00717
00718
00719 if (Q_stricmp(token.string, "font") == 0) {
00720 int pointSize;
00721 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00722 return qfalse;
00723 }
00724 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.textFont);
00725 uiInfo.uiDC.Assets.fontRegistered = qtrue;
00726 continue;
00727 }
00728
00729 if (Q_stricmp(token.string, "smallFont") == 0) {
00730 int pointSize;
00731 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00732 return qfalse;
00733 }
00734 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.smallFont);
00735 continue;
00736 }
00737
00738 if (Q_stricmp(token.string, "bigFont") == 0) {
00739 int pointSize;
00740 if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle,&pointSize)) {
00741 return qfalse;
00742 }
00743 trap_R_RegisterFont(tempStr, pointSize, &uiInfo.uiDC.Assets.bigFont);
00744 continue;
00745 }
00746
00747
00748
00749 if (Q_stricmp(token.string, "gradientbar") == 0) {
00750 if (!PC_String_Parse(handle, &tempStr)) {
00751 return qfalse;
00752 }
00753 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip(tempStr);
00754 continue;
00755 }
00756
00757
00758 if (Q_stricmp(token.string, "menuEnterSound") == 0) {
00759 if (!PC_String_Parse(handle, &tempStr)) {
00760 return qfalse;
00761 }
00762 uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse );
00763 continue;
00764 }
00765
00766
00767 if (Q_stricmp(token.string, "menuExitSound") == 0) {
00768 if (!PC_String_Parse(handle, &tempStr)) {
00769 return qfalse;
00770 }
00771 uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse );
00772 continue;
00773 }
00774
00775
00776 if (Q_stricmp(token.string, "itemFocusSound") == 0) {
00777 if (!PC_String_Parse(handle, &tempStr)) {
00778 return qfalse;
00779 }
00780 uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse );
00781 continue;
00782 }
00783
00784
00785 if (Q_stricmp(token.string, "menuBuzzSound") == 0) {
00786 if (!PC_String_Parse(handle, &tempStr)) {
00787 return qfalse;
00788 }
00789 uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse );
00790 continue;
00791 }
00792
00793 if (Q_stricmp(token.string, "cursor") == 0) {
00794 if (!PC_String_Parse(handle, &uiInfo.uiDC.Assets.cursorStr)) {
00795 return qfalse;
00796 }
00797 uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr);
00798 continue;
00799 }
00800
00801 if (Q_stricmp(token.string, "fadeClamp") == 0) {
00802 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeClamp)) {
00803 return qfalse;
00804 }
00805 continue;
00806 }
00807
00808 if (Q_stricmp(token.string, "fadeCycle") == 0) {
00809 if (!PC_Int_Parse(handle, &uiInfo.uiDC.Assets.fadeCycle)) {
00810 return qfalse;
00811 }
00812 continue;
00813 }
00814
00815 if (Q_stricmp(token.string, "fadeAmount") == 0) {
00816 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.fadeAmount)) {
00817 return qfalse;
00818 }
00819 continue;
00820 }
00821
00822 if (Q_stricmp(token.string, "shadowX") == 0) {
00823 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowX)) {
00824 return qfalse;
00825 }
00826 continue;
00827 }
00828
00829 if (Q_stricmp(token.string, "shadowY") == 0) {
00830 if (!PC_Float_Parse(handle, &uiInfo.uiDC.Assets.shadowY)) {
00831 return qfalse;
00832 }
00833 continue;
00834 }
00835
00836 if (Q_stricmp(token.string, "shadowColor") == 0) {
00837 if (!PC_Color_Parse(handle, &uiInfo.uiDC.Assets.shadowColor)) {
00838 return qfalse;
00839 }
00840 uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3];
00841 continue;
00842 }
00843
00844 }
00845 return qfalse;
00846 }
00847
00848 void Font_Report() {
00849 int i;
00850 Com_Printf("Font Info\n");
00851 Com_Printf("=========\n");
00852 for ( i = 32; i < 96; i++) {
00853 Com_Printf("Glyph handle %i: %i\n", i, uiInfo.uiDC.Assets.textFont.glyphs[i].glyph);
00854 }
00855 }
00856
00857 void UI_Report() {
00858 String_Report();
00859
00860
00861 }
00862
00863 void UI_ParseMenu(const char *menuFile) {
00864 int handle;
00865 pc_token_t token;
00866
00867 Com_Printf("Parsing menu file:%s\n", menuFile);
00868
00869 handle = trap_PC_LoadSource(menuFile);
00870 if (!handle) {
00871 return;
00872 }
00873
00874 while ( 1 ) {
00875 memset(&token, 0, sizeof(pc_token_t));
00876 if (!trap_PC_ReadToken( handle, &token )) {
00877 break;
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 if ( token.string[0] == '}' ) {
00891 break;
00892 }
00893
00894 if (Q_stricmp(token.string, "assetGlobalDef") == 0) {
00895 if (Asset_Parse(handle)) {
00896 continue;
00897 } else {
00898 break;
00899 }
00900 }
00901
00902 if (Q_stricmp(token.string, "menudef") == 0) {
00903
00904 Menu_New(handle);
00905 }
00906 }
00907 trap_PC_FreeSource(handle);
00908 }
00909
00910 qboolean Load_Menu(int handle) {
00911 pc_token_t token;
00912
00913 if (!trap_PC_ReadToken(handle, &token))
00914 return qfalse;
00915 if (token.string[0] != '{') {
00916 return qfalse;
00917 }
00918
00919 while ( 1 ) {
00920
00921 if (!trap_PC_ReadToken(handle, &token))
00922 return qfalse;
00923
00924 if ( token.string[0] == 0 ) {
00925 return qfalse;
00926 }
00927
00928 if ( token.string[0] == '}' ) {
00929 return qtrue;
00930 }
00931
00932 UI_ParseMenu(token.string);
00933 }
00934 return qfalse;
00935 }
00936
00937 void UI_LoadMenus(const char *menuFile, qboolean reset) {
00938 pc_token_t token;
00939 int handle;
00940 int start;
00941
00942 start = trap_Milliseconds();
00943
00944 handle = trap_PC_LoadSource( menuFile );
00945 if (!handle) {
00946 trap_Error( va( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile ) );
00947 handle = trap_PC_LoadSource( "ui/menus.txt" );
00948 if (!handle) {
00949 trap_Error( va( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!\n", menuFile ) );
00950 }
00951 }
00952
00953 ui_new.integer = 1;
00954
00955 if (reset) {
00956 Menu_Reset();
00957 }
00958
00959 while ( 1 ) {
00960 if (!trap_PC_ReadToken(handle, &token))
00961 break;
00962 if( token.string[0] == 0 || token.string[0] == '}') {
00963 break;
00964 }
00965
00966 if ( token.string[0] == '}' ) {
00967 break;
00968 }
00969
00970 if (Q_stricmp(token.string, "loadmenu") == 0) {
00971 if (Load_Menu(handle)) {
00972 continue;
00973 } else {
00974 break;
00975 }
00976 }
00977 }
00978
00979 Com_Printf("UI menu load time = %d milli seconds\n", trap_Milliseconds() - start);
00980
00981 trap_PC_FreeSource( handle );
00982 }
00983
00984 void UI_Load() {
00985 char lastName[1024];
00986 menuDef_t *menu = Menu_GetFocused();
00987 char *menuSet = UI_Cvar_VariableString("ui_menuFiles");
00988 if (menu && menu->window.name) {
00989 strcpy(lastName, menu->window.name);
00990 }
00991 if (menuSet == NULL || menuSet[0] == '\0') {
00992 menuSet = "ui/menus.txt";
00993 }
00994
00995 String_Init();
00996
00997 #ifdef PRE_RELEASE_TADEMO
00998 UI_ParseGameInfo("demogameinfo.txt");
00999 #else
01000 UI_ParseGameInfo("gameinfo.txt");
01001 UI_LoadArenas();
01002 #endif
01003
01004 UI_LoadMenus(menuSet, qtrue);
01005 Menus_CloseAll();
01006 Menus_ActivateByName(lastName);
01007
01008 }
01009
01010 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};
01011 #ifndef MISSIONPACK // bk001206
01012 static int numHandicaps = sizeof(handicapValues) / sizeof(const char*);
01013 #endif
01014
01015 static void UI_DrawHandicap(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01016 int i, h;
01017
01018 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );
01019 i = 20 - h / 5;
01020
01021 Text_Paint(rect->x, rect->y, scale, color, handicapValues[i], 0, 0, textStyle);
01022 }
01023
01024 static void UI_DrawClanName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01025 Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_teamName"), 0, 0, textStyle);
01026 }
01027
01028
01029 static void UI_SetCapFragLimits(qboolean uiVars) {
01030 int cap = 5;
01031 int frag = 10;
01032 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_OBELISK) {
01033 cap = 4;
01034 } else if (uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_HARVESTER) {
01035 cap = 15;
01036 }
01037 if (uiVars) {
01038 trap_Cvar_Set("ui_captureLimit", va("%d", cap));
01039 trap_Cvar_Set("ui_fragLimit", va("%d", frag));
01040 } else {
01041 trap_Cvar_Set("capturelimit", va("%d", cap));
01042 trap_Cvar_Set("fraglimit", va("%d", frag));
01043 }
01044 }
01045
01046 static void UI_DrawGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01047 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[ui_gameType.integer].gameType, 0, 0, textStyle);
01048 }
01049
01050 static void UI_DrawNetGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01051 if (ui_netGameType.integer < 0 || ui_netGameType.integer > uiInfo.numGameTypes) {
01052 trap_Cvar_Set("ui_netGameType", "0");
01053 trap_Cvar_Set("ui_actualNetGameType", "0");
01054 }
01055 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[ui_netGameType.integer].gameType , 0, 0, textStyle);
01056 }
01057
01058 static void UI_DrawJoinGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01059 if (ui_joinGameType.integer < 0 || ui_joinGameType.integer > uiInfo.numJoinGameTypes) {
01060 trap_Cvar_Set("ui_joinGameType", "0");
01061 }
01062 Text_Paint(rect->x, rect->y, scale, color, uiInfo.joinGameTypes[ui_joinGameType.integer].gameType , 0, 0, textStyle);
01063 }
01064
01065
01066
01067 static int UI_TeamIndexFromName(const char *name) {
01068 int i;
01069
01070 if (name && *name) {
01071 for (i = 0; i < uiInfo.teamCount; i++) {
01072 if (Q_stricmp(name, uiInfo.teamList[i].teamName) == 0) {
01073 return i;
01074 }
01075 }
01076 }
01077
01078 return 0;
01079
01080 }
01081
01082 static void UI_DrawClanLogo(rectDef_t *rect, float scale, vec4_t color) {
01083 int i;
01084 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01085 if (i >= 0 && i < uiInfo.teamCount) {
01086 trap_R_SetColor( color );
01087
01088 if (uiInfo.teamList[i].teamIcon == -1) {
01089 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01090 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01091 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01092 }
01093
01094 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon);
01095 trap_R_SetColor(NULL);
01096 }
01097 }
01098
01099 static void UI_DrawClanCinematic(rectDef_t *rect, float scale, vec4_t color) {
01100 int i;
01101 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01102 if (i >= 0 && i < uiInfo.teamCount) {
01103
01104 if (uiInfo.teamList[i].cinematic >= -2) {
01105 if (uiInfo.teamList[i].cinematic == -1) {
01106 uiInfo.teamList[i].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.teamList[i].imageName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
01107 }
01108 if (uiInfo.teamList[i].cinematic >= 0) {
01109 trap_CIN_RunCinematic(uiInfo.teamList[i].cinematic);
01110 trap_CIN_SetExtents(uiInfo.teamList[i].cinematic, rect->x, rect->y, rect->w, rect->h);
01111 trap_CIN_DrawCinematic(uiInfo.teamList[i].cinematic);
01112 } else {
01113 trap_R_SetColor( color );
01114 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal);
01115 trap_R_SetColor(NULL);
01116 uiInfo.teamList[i].cinematic = -2;
01117 }
01118 } else {
01119 trap_R_SetColor( color );
01120 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon);
01121 trap_R_SetColor(NULL);
01122 }
01123 }
01124
01125 }
01126
01127 static void UI_DrawPreviewCinematic(rectDef_t *rect, float scale, vec4_t color) {
01128 if (uiInfo.previewMovie > -2) {
01129 uiInfo.previewMovie = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.movieList[uiInfo.movieIndex]), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
01130 if (uiInfo.previewMovie >= 0) {
01131 trap_CIN_RunCinematic(uiInfo.previewMovie);
01132 trap_CIN_SetExtents(uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h);
01133 trap_CIN_DrawCinematic(uiInfo.previewMovie);
01134 } else {
01135 uiInfo.previewMovie = -2;
01136 }
01137 }
01138
01139 }
01140
01141
01142
01143 static void UI_DrawSkill(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01144 int i;
01145 i = trap_Cvar_VariableValue( "g_spSkill" );
01146 if (i < 1 || i > numSkillLevels) {
01147 i = 1;
01148 }
01149 Text_Paint(rect->x, rect->y, scale, color, skillLevels[i-1],0, 0, textStyle);
01150 }
01151
01152
01153 static void UI_DrawTeamName(rectDef_t *rect, float scale, vec4_t color, qboolean blue, int textStyle) {
01154 int i;
01155 i = UI_TeamIndexFromName(UI_Cvar_VariableString((blue) ? "ui_blueTeam" : "ui_redTeam"));
01156 if (i >= 0 && i < uiInfo.teamCount) {
01157 Text_Paint(rect->x, rect->y, scale, color, va("%s: %s", (blue) ? "Blue" : "Red", uiInfo.teamList[i].teamName),0, 0, textStyle);
01158 }
01159 }
01160
01161 static void UI_DrawTeamMember(rectDef_t *rect, float scale, vec4_t color, qboolean blue, int num, int textStyle) {
01162
01163
01164
01165 int value = trap_Cvar_VariableValue(va(blue ? "ui_blueteam%i" : "ui_redteam%i", num));
01166 const char *text;
01167 if (value <= 0) {
01168 text = "Closed";
01169 } else if (value == 1) {
01170 text = "Human";
01171 } else {
01172 value -= 2;
01173
01174 if (ui_actualNetGameType.integer >= GT_TEAM) {
01175 if (value >= uiInfo.characterCount) {
01176 value = 0;
01177 }
01178 text = uiInfo.characterList[value].name;
01179 } else {
01180 if (value >= UI_GetNumBots()) {
01181 value = 0;
01182 }
01183 text = UI_GetBotNameByNumber(value);
01184 }
01185 }
01186 Text_Paint(rect->x, rect->y, scale, color, text, 0, 0, textStyle);
01187 }
01188
01189 static void UI_DrawEffects(rectDef_t *rect, float scale, vec4_t color) {
01190 UI_DrawHandlePic( rect->x, rect->y - 14, 128, 8, uiInfo.uiDC.Assets.fxBasePic );
01191 UI_DrawHandlePic( rect->x + uiInfo.effectsColor * 16 + 8, rect->y - 16, 16, 12, uiInfo.uiDC.Assets.fxPic[uiInfo.effectsColor] );
01192 }
01193
01194 static void UI_DrawMapPreview(rectDef_t *rect, float scale, vec4_t color, qboolean net) {
01195 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;
01196 if (map < 0 || map > uiInfo.mapCount) {
01197 if (net) {
01198 ui_currentNetMap.integer = 0;
01199 trap_Cvar_Set("ui_currentNetMap", "0");
01200 } else {
01201 ui_currentMap.integer = 0;
01202 trap_Cvar_Set("ui_currentMap", "0");
01203 }
01204 map = 0;
01205 }
01206
01207 if (uiInfo.mapList[map].levelShot == -1) {
01208 uiInfo.mapList[map].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[map].imageName);
01209 }
01210
01211 if (uiInfo.mapList[map].levelShot > 0) {
01212 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.mapList[map].levelShot);
01213 } else {
01214 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("menu/art/unknownmap"));
01215 }
01216 }
01217
01218
01219 static void UI_DrawMapTimeToBeat(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01220 int minutes, seconds, time;
01221 if (ui_currentMap.integer < 0 || ui_currentMap.integer > uiInfo.mapCount) {
01222 ui_currentMap.integer = 0;
01223 trap_Cvar_Set("ui_currentMap", "0");
01224 }
01225
01226 time = uiInfo.mapList[ui_currentMap.integer].timeToBeat[uiInfo.gameTypes[ui_gameType.integer].gtEnum];
01227
01228 minutes = time / 60;
01229 seconds = time % 60;
01230
01231 Text_Paint(rect->x, rect->y, scale, color, va("%02i:%02i", minutes, seconds), 0, 0, textStyle);
01232 }
01233
01234
01235
01236 static void UI_DrawMapCinematic(rectDef_t *rect, float scale, vec4_t color, qboolean net) {
01237
01238 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;
01239 if (map < 0 || map > uiInfo.mapCount) {
01240 if (net) {
01241 ui_currentNetMap.integer = 0;
01242 trap_Cvar_Set("ui_currentNetMap", "0");
01243 } else {
01244 ui_currentMap.integer = 0;
01245 trap_Cvar_Set("ui_currentMap", "0");
01246 }
01247 map = 0;
01248 }
01249
01250 if (uiInfo.mapList[map].cinematic >= -1) {
01251 if (uiInfo.mapList[map].cinematic == -1) {
01252 uiInfo.mapList[map].cinematic = trap_CIN_PlayCinematic(va("%s.roq", uiInfo.mapList[map].mapLoadName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
01253 }
01254 if (uiInfo.mapList[map].cinematic >= 0) {
01255 trap_CIN_RunCinematic(uiInfo.mapList[map].cinematic);
01256 trap_CIN_SetExtents(uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h);
01257 trap_CIN_DrawCinematic(uiInfo.mapList[map].cinematic);
01258 } else {
01259 uiInfo.mapList[map].cinematic = -2;
01260 }
01261 } else {
01262 UI_DrawMapPreview(rect, scale, color, net);
01263 }
01264 }
01265
01266
01267
01268 static qboolean updateModel = qtrue;
01269 static qboolean q3Model = qfalse;
01270
01271 static void UI_DrawPlayerModel(rectDef_t *rect) {
01272 static playerInfo_t info;
01273 char model[MAX_QPATH];
01274 char team[256];
01275 char head[256];
01276 vec3_t viewangles;
01277 vec3_t moveangles;
01278
01279 if (trap_Cvar_VariableValue("ui_Q3Model")) {
01280 strcpy(model, UI_Cvar_VariableString("model"));
01281 strcpy(head, UI_Cvar_VariableString("headmodel"));
01282 if (!q3Model) {
01283 q3Model = qtrue;
01284 updateModel = qtrue;
01285 }
01286 team[0] = '\0';
01287 } else {
01288
01289 strcpy(team, UI_Cvar_VariableString("ui_teamName"));
01290 strcpy(model, UI_Cvar_VariableString("team_model"));
01291 strcpy(head, UI_Cvar_VariableString("team_headmodel"));
01292 if (q3Model) {
01293 q3Model = qfalse;
01294 updateModel = qtrue;
01295 }
01296 }
01297 if (updateModel) {
01298 memset( &info, 0, sizeof(playerInfo_t) );
01299 viewangles[YAW] = 180 - 10;
01300 viewangles[PITCH] = 0;
01301 viewangles[ROLL] = 0;
01302 VectorClear( moveangles );
01303 UI_PlayerInfo_SetModel( &info, model, head, team);
01304 UI_PlayerInfo_SetInfo( &info, LEGS_IDLE, TORSO_STAND, viewangles, vec3_origin, WP_MACHINEGUN, qfalse );
01305
01306 updateModel = qfalse;
01307 }
01308
01309 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info, uiInfo.uiDC.realTime / 2);
01310
01311 }
01312
01313 static void UI_DrawNetSource(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01314 if (ui_netSource.integer < 0 || ui_netSource.integer > numNetSources) {
01315 ui_netSource.integer = 0;
01316 }
01317 Text_Paint(rect->x, rect->y, scale, color, va("Source: %s", netSources[ui_netSource.integer]), 0, 0, textStyle);
01318 }
01319
01320 static void UI_DrawNetMapPreview(rectDef_t *rect, float scale, vec4_t color) {
01321
01322 if (uiInfo.serverStatus.currentServerPreview > 0) {
01323 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.serverStatus.currentServerPreview);
01324 } else {
01325 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip("menu/art/unknownmap"));
01326 }
01327 }
01328
01329 static void UI_DrawNetMapCinematic(rectDef_t *rect, float scale, vec4_t color) {
01330 if (ui_currentNetMap.integer < 0 || ui_currentNetMap.integer > uiInfo.mapCount) {
01331 ui_currentNetMap.integer = 0;
01332 trap_Cvar_Set("ui_currentNetMap", "0");
01333 }
01334
01335 if (uiInfo.serverStatus.currentServerCinematic >= 0) {
01336 trap_CIN_RunCinematic(uiInfo.serverStatus.currentServerCinematic);
01337 trap_CIN_SetExtents(uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h);
01338 trap_CIN_DrawCinematic(uiInfo.serverStatus.currentServerCinematic);
01339 } else {
01340 UI_DrawNetMapPreview(rect, scale, color);
01341 }
01342 }
01343
01344
01345
01346 static void UI_DrawNetFilter(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01347 if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
01348 ui_serverFilterType.integer = 0;
01349 }
01350 Text_Paint(rect->x, rect->y, scale, color, va("Filter: %s", serverFilters[ui_serverFilterType.integer].description), 0, 0, textStyle);
01351 }
01352
01353
01354 static void UI_DrawTier(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01355 int i;
01356 i = trap_Cvar_VariableValue( "ui_currentTier" );
01357 if (i < 0 || i >= uiInfo.tierCount) {
01358 i = 0;
01359 }
01360 Text_Paint(rect->x, rect->y, scale, color, va("Tier: %s", uiInfo.tierList[i].tierName),0, 0, textStyle);
01361 }
01362
01363 static void UI_DrawTierMap(rectDef_t *rect, int index) {
01364 int i;
01365 i = trap_Cvar_VariableValue( "ui_currentTier" );
01366 if (i < 0 || i >= uiInfo.tierCount) {
01367 i = 0;
01368 }
01369
01370 if (uiInfo.tierList[i].mapHandles[index] == -1) {
01371 uiInfo.tierList[i].mapHandles[index] = trap_R_RegisterShaderNoMip(va("levelshots/%s", uiInfo.tierList[i].maps[index]));
01372 }
01373
01374 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.tierList[i].mapHandles[index]);
01375 }
01376
01377 static const char *UI_EnglishMapName(const char *map) {
01378 int i;
01379 for (i = 0; i < uiInfo.mapCount; i++) {
01380 if (Q_stricmp(map, uiInfo.mapList[i].mapLoadName) == 0) {
01381 return uiInfo.mapList[i].mapName;
01382 }
01383 }
01384 return "";
01385 }
01386
01387 static void UI_DrawTierMapName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01388 int i, j;
01389 i = trap_Cvar_VariableValue( "ui_currentTier" );
01390 if (i < 0 || i >= uiInfo.tierCount) {
01391 i = 0;
01392 }
01393 j = trap_Cvar_VariableValue("ui_currentMap");
01394 if (j < 0 || j > MAPS_PER_TIER) {
01395 j = 0;
01396 }
01397
01398 Text_Paint(rect->x, rect->y, scale, color, UI_EnglishMapName(uiInfo.tierList[i].maps[j]), 0, 0, textStyle);
01399 }
01400
01401 static void UI_DrawTierGameType(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01402 int i, j;
01403 i = trap_Cvar_VariableValue( "ui_currentTier" );
01404 if (i < 0 || i >= uiInfo.tierCount) {
01405 i = 0;
01406 }
01407 j = trap_Cvar_VariableValue("ui_currentMap");
01408 if (j < 0 || j > MAPS_PER_TIER) {
01409 j = 0;
01410 }
01411
01412 Text_Paint(rect->x, rect->y, scale, color, uiInfo.gameTypes[uiInfo.tierList[i].gameTypes[j]].gameType , 0, 0, textStyle);
01413 }
01414
01415
01416 #ifndef MISSIONPACK // bk001206
01417 static const char *UI_OpponentLeaderName() {
01418 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01419 return uiInfo.teamList[i].teamMembers[0];
01420 }
01421 #endif
01422
01423 static const char *UI_AIFromName(const char *name) {
01424 int j;
01425 for (j = 0; j < uiInfo.aliasCount; j++) {
01426 if (Q_stricmp(uiInfo.aliasList[j].name, name) == 0) {
01427 return uiInfo.aliasList[j].ai;
01428 }
01429 }
01430 return "James";
01431 }
01432
01433 #ifndef MISSIONPACK // bk001206
01434 static const int UI_AIIndex(const char *name) {
01435 int j;
01436 for (j = 0; j < uiInfo.characterCount; j++) {
01437 if (Q_stricmp(name, uiInfo.characterList[j].name) == 0) {
01438 return j;
01439 }
01440 }
01441 return 0;
01442 }
01443 #endif
01444
01445 #ifndef MISSIONPACK // bk001206
01446 static const int UI_AIIndexFromName(const char *name) {
01447 int j;
01448 for (j = 0; j < uiInfo.aliasCount; j++) {
01449 if (Q_stricmp(uiInfo.aliasList[j].name, name) == 0) {
01450 return UI_AIIndex(uiInfo.aliasList[j].ai);
01451 }
01452 }
01453 return 0;
01454 }
01455 #endif
01456
01457
01458 #ifndef MISSIONPACK // bk001206
01459 static const char *UI_OpponentLeaderHead() {
01460 const char *leader = UI_OpponentLeaderName();
01461 return UI_AIFromName(leader);
01462 }
01463 #endif
01464
01465 #ifndef MISSIONPACK // bk001206
01466 static const char *UI_OpponentLeaderModel() {
01467 int i;
01468 const char *head = UI_OpponentLeaderHead();
01469 for (i = 0; i < uiInfo.characterCount; i++) {
01470 if (Q_stricmp(head, uiInfo.characterList[i].name) == 0) {
01471 return uiInfo.characterList[i].base;
01472 }
01473 }
01474 return "James";
01475 }
01476 #endif
01477
01478
01479 static qboolean updateOpponentModel = qtrue;
01480 static void UI_DrawOpponent(rectDef_t *rect) {
01481 static playerInfo_t info2;
01482 char model[MAX_QPATH];
01483 char headmodel[MAX_QPATH];
01484 char team[256];
01485 vec3_t viewangles;
01486 vec3_t moveangles;
01487
01488 if (updateOpponentModel) {
01489
01490 strcpy(model, UI_Cvar_VariableString("ui_opponentModel"));
01491 strcpy(headmodel, UI_Cvar_VariableString("ui_opponentModel"));
01492 team[0] = '\0';
01493
01494 memset( &info2, 0, sizeof(playerInfo_t) );
01495 viewangles[YAW] = 180 - 10;
01496 viewangles[PITCH] = 0;
01497 viewangles[ROLL] = 0;
01498 VectorClear( moveangles );
01499 UI_PlayerInfo_SetModel( &info2, model, headmodel, "");
01500 UI_PlayerInfo_SetInfo( &info2, LEGS_IDLE, TORSO_STAND, viewangles, vec3_origin, WP_MACHINEGUN, qfalse );
01501 UI_RegisterClientModelname( &info2, model, headmodel, team);
01502 updateOpponentModel = qfalse;
01503 }
01504
01505 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info2, uiInfo.uiDC.realTime / 2);
01506
01507 }
01508
01509 static void UI_NextOpponent() {
01510 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01511 int j = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01512 i++;
01513 if (i >= uiInfo.teamCount) {
01514 i = 0;
01515 }
01516 if (i == j) {
01517 i++;
01518 if ( i >= uiInfo.teamCount) {
01519 i = 0;
01520 }
01521 }
01522 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );
01523 }
01524
01525 static void UI_PriorOpponent() {
01526 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01527 int j = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01528 i--;
01529 if (i < 0) {
01530 i = uiInfo.teamCount - 1;
01531 }
01532 if (i == j) {
01533 i--;
01534 if ( i < 0) {
01535 i = uiInfo.teamCount - 1;
01536 }
01537 }
01538 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );
01539 }
01540
01541 static void UI_DrawPlayerLogo(rectDef_t *rect, vec3_t color) {
01542 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01543
01544 if (uiInfo.teamList[i].teamIcon == -1) {
01545 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01546 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01547 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01548 }
01549
01550 trap_R_SetColor( color );
01551 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
01552 trap_R_SetColor( NULL );
01553 }
01554
01555 static void UI_DrawPlayerLogoMetal(rectDef_t *rect, vec3_t color) {
01556 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01557 if (uiInfo.teamList[i].teamIcon == -1) {
01558 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01559 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01560 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01561 }
01562
01563 trap_R_SetColor( color );
01564 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );
01565 trap_R_SetColor( NULL );
01566 }
01567
01568 static void UI_DrawPlayerLogoName(rectDef_t *rect, vec3_t color) {
01569 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
01570 if (uiInfo.teamList[i].teamIcon == -1) {
01571 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01572 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01573 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01574 }
01575
01576 trap_R_SetColor( color );
01577 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );
01578 trap_R_SetColor( NULL );
01579 }
01580
01581 static void UI_DrawOpponentLogo(rectDef_t *rect, vec3_t color) {
01582 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01583 if (uiInfo.teamList[i].teamIcon == -1) {
01584 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01585 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01586 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01587 }
01588
01589 trap_R_SetColor( color );
01590 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
01591 trap_R_SetColor( NULL );
01592 }
01593
01594 static void UI_DrawOpponentLogoMetal(rectDef_t *rect, vec3_t color) {
01595 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01596 if (uiInfo.teamList[i].teamIcon == -1) {
01597 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01598 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01599 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01600 }
01601
01602 trap_R_SetColor( color );
01603 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );
01604 trap_R_SetColor( NULL );
01605 }
01606
01607 static void UI_DrawOpponentLogoName(rectDef_t *rect, vec3_t color) {
01608 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
01609 if (uiInfo.teamList[i].teamIcon == -1) {
01610 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[i].imageName);
01611 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[i].imageName));
01612 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[i].imageName));
01613 }
01614
01615 trap_R_SetColor( color );
01616 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );
01617 trap_R_SetColor( NULL );
01618 }
01619
01620 static void UI_DrawAllMapsSelection(rectDef_t *rect, float scale, vec4_t color, int textStyle, qboolean net) {
01621 int map = (net) ? ui_currentNetMap.integer : ui_currentMap.integer;
01622 if (map >= 0 && map < uiInfo.mapCount) {
01623 Text_Paint(rect->x, rect->y, scale, color, uiInfo.mapList[map].mapName, 0, 0, textStyle);
01624 }
01625 }
01626
01627 static void UI_DrawOpponentName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01628 Text_Paint(rect->x, rect->y, scale, color, UI_Cvar_VariableString("ui_opponentName"), 0, 0, textStyle);
01629 }
01630
01631
01632 static int UI_OwnerDrawWidth(int ownerDraw, float scale) {
01633 int i, h, value;
01634 const char *text;
01635 const char *s = NULL;
01636
01637 switch (ownerDraw) {
01638 case UI_HANDICAP:
01639 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );
01640 i = 20 - h / 5;
01641 s = handicapValues[i];
01642 break;
01643 case UI_CLANNAME:
01644 s = UI_Cvar_VariableString("ui_teamName");
01645 break;
01646 case UI_GAMETYPE:
01647 s = uiInfo.gameTypes[ui_gameType.integer].gameType;
01648 break;
01649 case UI_SKILL:
01650 i = trap_Cvar_VariableValue( "g_spSkill" );
01651 if (i < 1 || i > numSkillLevels) {
01652 i = 1;
01653 }
01654 s = skillLevels[i-1];
01655 break;
01656 case UI_BLUETEAMNAME:
01657 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_blueTeam"));
01658 if (i >= 0 && i < uiInfo.teamCount) {
01659 s = va("%s: %s", "Blue", uiInfo.teamList[i].teamName);
01660 }
01661 break;
01662 case UI_REDTEAMNAME:
01663 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_redTeam"));
01664 if (i >= 0 && i < uiInfo.teamCount) {
01665 s = va("%s: %s", "Red", uiInfo.teamList[i].teamName);
01666 }
01667 break;
01668 case UI_BLUETEAM1:
01669 case UI_BLUETEAM2:
01670 case UI_BLUETEAM3:
01671 case UI_BLUETEAM4:
01672 case UI_BLUETEAM5:
01673 value = trap_Cvar_VariableValue(va("ui_blueteam%i", ownerDraw-UI_BLUETEAM1 + 1));
01674 if (value <= 0) {
01675 text = "Closed";
01676 } else if (value == 1) {
01677 text = "Human";
01678 } else {
01679 value -= 2;
01680 if (value >= uiInfo.aliasCount) {
01681 value = 0;
01682 }
01683 text = uiInfo.aliasList[value].name;
01684 }
01685 s = va("%i. %s", ownerDraw-UI_BLUETEAM1 + 1, text);
01686 break;
01687 case UI_REDTEAM1:
01688 case UI_REDTEAM2:
01689 case UI_REDTEAM3:
01690 case UI_REDTEAM4:
01691 case UI_REDTEAM5:
01692 value = trap_Cvar_VariableValue(va("ui_redteam%i", ownerDraw-UI_REDTEAM1 + 1));
01693 if (value <= 0) {
01694 text = "Closed";
01695 } else if (value == 1) {
01696 text = "Human";
01697 } else {
01698 value -= 2;
01699 if (value >= uiInfo.aliasCount) {
01700 value = 0;
01701 }
01702 text = uiInfo.aliasList[value].name;
01703 }
01704 s = va("%i. %s", ownerDraw-UI_REDTEAM1 + 1, text);
01705 break;
01706 case UI_NETSOURCE:
01707 if (ui_netSource.integer < 0 || ui_netSource.integer > uiInfo.numJoinGameTypes) {
01708 ui_netSource.integer = 0;
01709 }
01710 s = va("Source: %s", netSources[ui_netSource.integer]);
01711 break;
01712 case UI_NETFILTER:
01713 if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) {
01714 ui_serverFilterType.integer = 0;
01715 }
01716 s = va("Filter: %s", serverFilters[ui_serverFilterType.integer].description );
01717 break;
01718 case UI_TIER:
01719 break;
01720 case UI_TIER_MAPNAME:
01721 break;
01722 case UI_TIER_GAMETYPE:
01723 break;
01724 case UI_ALLMAPS_SELECTION:
01725 break;
01726 case UI_OPPONENT_NAME:
01727 break;
01728 case UI_KEYBINDSTATUS:
01729 if (Display_KeyBindPending()) {
01730 s = "Waiting for new key... Press ESCAPE to cancel";
01731 } else {
01732 s = "Press ENTER or CLICK to change, Press BACKSPACE to clear";
01733 }
01734 break;
01735 case UI_SERVERREFRESHDATE:
01736 s = UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer));
01737 break;
01738 default:
01739 break;
01740 }
01741
01742 if (s) {
01743 return Text_Width(s, scale, 0);
01744 }
01745 return 0;
01746 }
01747
01748 static void UI_DrawBotName(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01749 int value = uiInfo.botIndex;
01750 int game = trap_Cvar_VariableValue("g_gametype");
01751 const char *text = "";
01752 if (game >= GT_TEAM) {
01753 if (value >= uiInfo.characterCount) {
01754 value = 0;
01755 }
01756 text = uiInfo.characterList[value].name;
01757 } else {
01758 if (value >= UI_GetNumBots()) {
01759 value = 0;
01760 }
01761 text = UI_GetBotNameByNumber(value);
01762 }
01763 Text_Paint(rect->x, rect->y, scale, color, text, 0, 0, textStyle);
01764 }
01765
01766 static void UI_DrawBotSkill(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01767 if (uiInfo.skillIndex >= 0 && uiInfo.skillIndex < numSkillLevels) {
01768 Text_Paint(rect->x, rect->y, scale, color, skillLevels[uiInfo.skillIndex], 0, 0, textStyle);
01769 }
01770 }
01771
01772 static void UI_DrawRedBlue(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01773 Text_Paint(rect->x, rect->y, scale, color, (uiInfo.redBlue == 0) ? "Red" : "Blue", 0, 0, textStyle);
01774 }
01775
01776 static void UI_DrawCrosshair(rectDef_t *rect, float scale, vec4_t color) {
01777 trap_R_SetColor( color );
01778 if (uiInfo.currentCrosshair < 0 || uiInfo.currentCrosshair >= NUM_CROSSHAIRS) {
01779 uiInfo.currentCrosshair = 0;
01780 }
01781 UI_DrawHandlePic( rect->x, rect->y - rect->h, rect->w, rect->h, uiInfo.uiDC.Assets.crosshairShader[uiInfo.currentCrosshair]);
01782 trap_R_SetColor( NULL );
01783 }
01784
01785
01786
01787
01788
01789
01790 static void UI_BuildPlayerList() {
01791 uiClientState_t cs;
01792 int n, count, team, team2, playerTeamNumber;
01793 char info[MAX_INFO_STRING];
01794
01795 trap_GetClientState( &cs );
01796 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
01797 uiInfo.playerNumber = cs.clientNum;
01798 uiInfo.teamLeader = atoi(Info_ValueForKey(info, "tl"));
01799 team = atoi(Info_ValueForKey(info, "t"));
01800 trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
01801 count = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
01802 uiInfo.playerCount = 0;
01803 uiInfo.myTeamCount = 0;
01804 playerTeamNumber = 0;
01805 for( n = 0; n < count; n++ ) {
01806 trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );
01807
01808 if (info[0]) {
01809 Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
01810 Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] );
01811 uiInfo.playerCount++;
01812 team2 = atoi(Info_ValueForKey(info, "t"));
01813 if (team2 == team) {
01814 Q_strncpyz( uiInfo.teamNames[uiInfo.myTeamCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
01815 Q_CleanStr( uiInfo.teamNames[uiInfo.myTeamCount] );
01816 uiInfo.teamClientNums[uiInfo.myTeamCount] = n;
01817 if (uiInfo.playerNumber == n) {
01818 playerTeamNumber = uiInfo.myTeamCount;
01819 }
01820 uiInfo.myTeamCount++;
01821 }
01822 }
01823 }
01824
01825 if (!uiInfo.teamLeader) {
01826 trap_Cvar_Set("cg_selectedPlayer", va("%d", playerTeamNumber));
01827 }
01828
01829 n = trap_Cvar_VariableValue("cg_selectedPlayer");
01830 if (n < 0 || n > uiInfo.myTeamCount) {
01831 n = 0;
01832 }
01833 if (n < uiInfo.myTeamCount) {
01834 trap_Cvar_Set("cg_selectedPlayerName", uiInfo.teamNames[n]);
01835 }
01836 }
01837
01838
01839 static void UI_DrawSelectedPlayer(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01840 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) {
01841 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
01842 UI_BuildPlayerList();
01843 }
01844 Text_Paint(rect->x, rect->y, scale, color, (uiInfo.teamLeader) ? UI_Cvar_VariableString("cg_selectedPlayerName") : UI_Cvar_VariableString("name") , 0, 0, textStyle);
01845 }
01846
01847 static void UI_DrawServerRefreshDate(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01848 if (uiInfo.serverStatus.refreshActive) {
01849 vec4_t lowLight, newColor;
01850 lowLight[0] = 0.8 * color[0];
01851 lowLight[1] = 0.8 * color[1];
01852 lowLight[2] = 0.8 * color[2];
01853 lowLight[3] = 0.8 * color[3];
01854 LerpColor(color,lowLight,newColor,0.5+0.5*sin(uiInfo.uiDC.realTime / PULSE_DIVISOR));
01855 Text_Paint(rect->x, rect->y, scale, newColor, va("Getting info for %d servers (ESC to cancel)", trap_LAN_GetServerCount(ui_netSource.integer)), 0, 0, textStyle);
01856 } else {
01857 char buff[64];
01858 Q_strncpyz(buff, UI_Cvar_VariableString(va("ui_lastServerRefresh_%i", ui_netSource.integer)), 64);
01859 Text_Paint(rect->x, rect->y, scale, color, va("Refresh Time: %s", buff), 0, 0, textStyle);
01860 }
01861 }
01862
01863 static void UI_DrawServerMOTD(rectDef_t *rect, float scale, vec4_t color) {
01864 if (uiInfo.serverStatus.motdLen) {
01865 float maxX;
01866
01867 if (uiInfo.serverStatus.motdWidth == -1) {
01868 uiInfo.serverStatus.motdWidth = 0;
01869 uiInfo.serverStatus.motdPaintX = rect->x + 1;
01870 uiInfo.serverStatus.motdPaintX2 = -1;
01871 }
01872
01873 if (uiInfo.serverStatus.motdOffset > uiInfo.serverStatus.motdLen) {
01874 uiInfo.serverStatus.motdOffset = 0;
01875 uiInfo.serverStatus.motdPaintX = rect->x + 1;
01876 uiInfo.serverStatus.motdPaintX2 = -1;
01877 }
01878
01879 if (uiInfo.uiDC.realTime > uiInfo.serverStatus.motdTime) {
01880 uiInfo.serverStatus.motdTime = uiInfo.uiDC.realTime + 10;
01881 if (uiInfo.serverStatus.motdPaintX <= rect->x + 2) {
01882 if (uiInfo.serverStatus.motdOffset < uiInfo.serverStatus.motdLen) {
01883 uiInfo.serverStatus.motdPaintX += Text_Width(&uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], scale, 1) - 1;
01884 uiInfo.serverStatus.motdOffset++;
01885 } else {
01886 uiInfo.serverStatus.motdOffset = 0;
01887 if (uiInfo.serverStatus.motdPaintX2 >= 0) {
01888 uiInfo.serverStatus.motdPaintX = uiInfo.serverStatus.motdPaintX2;
01889 } else {
01890 uiInfo.serverStatus.motdPaintX = rect->x + rect->w - 2;
01891 }
01892 uiInfo.serverStatus.motdPaintX2 = -1;
01893 }
01894 } else {
01895
01896 uiInfo.serverStatus.motdPaintX -= 2;
01897 if (uiInfo.serverStatus.motdPaintX2 >= 0) {
01898
01899 uiInfo.serverStatus.motdPaintX2 -= 2;
01900 }
01901 }
01902 }
01903
01904 maxX = rect->x + rect->w - 2;
01905 Text_Paint_Limit(&maxX, uiInfo.serverStatus.motdPaintX, rect->y + rect->h - 3, scale, color, &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], 0, 0);
01906 if (uiInfo.serverStatus.motdPaintX2 >= 0) {
01907 float maxX2 = rect->x + rect->w - 2;
01908 Text_Paint_Limit(&maxX2, uiInfo.serverStatus.motdPaintX2, rect->y + rect->h - 3, scale, color, uiInfo.serverStatus.motd, 0, uiInfo.serverStatus.motdOffset);
01909 }
01910 if (uiInfo.serverStatus.motdOffset && maxX > 0) {
01911
01912 if (uiInfo.serverStatus.motdPaintX2 == -1) {
01913 uiInfo.serverStatus.motdPaintX2 = rect->x + rect->w - 2;
01914 }
01915 } else {
01916 uiInfo.serverStatus.motdPaintX2 = -1;
01917 }
01918
01919 }
01920 }
01921
01922 static void UI_DrawKeyBindStatus(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01923
01924 if (Display_KeyBindPending()) {
01925 Text_Paint(rect->x, rect->y, scale, color, "Waiting for new key... Press ESCAPE to cancel", 0, 0, textStyle);
01926 } else {
01927 Text_Paint(rect->x, rect->y, scale, color, "Press ENTER or CLICK to change, Press BACKSPACE to clear", 0, 0, textStyle);
01928 }
01929 }
01930
01931 static void UI_DrawGLInfo(rectDef_t *rect, float scale, vec4_t color, int textStyle) {
01932 char * eptr;
01933 char buff[1024];
01934 const char *lines[64];
01935 int y, numLines, i;
01936
01937 Text_Paint(rect->x + 2, rect->y, scale, color, va("VENDOR: %s", uiInfo.uiDC.glconfig.vendor_string), 0, 30, textStyle);
01938 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);
01939 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);
01940
01941
01942
01943
01944
01945 Q_strncpyz(buff, uiInfo.uiDC.glconfig.extensions_string, 1024);
01946 eptr = buff;
01947 y = rect->y + 45;
01948 numLines = 0;
01949 while ( y < rect->y + rect->h && *eptr )
01950 {
01951 while ( *eptr && *eptr == ' ' )
01952 *eptr++ = '\0';
01953
01954
01955 if (*eptr && *eptr != ' ') {
01956 lines[numLines++] = eptr;
01957 }
01958
01959 while ( *eptr && *eptr != ' ' )
01960 eptr++;
01961 }
01962
01963 i = 0;
01964 while (i < numLines) {
01965 Text_Paint(rect->x + 2, y, scale, color, lines[i++], 0, 20, textStyle);
01966 if (i < numLines) {
01967 Text_Paint(rect->x + rect->w / 2, y, scale, color, lines[i++], 0, 20, textStyle);
01968 }
01969 y += 10;
01970 if (y > rect->y + rect->h - 11) {
01971 break;
01972 }
01973 }
01974
01975
01976 }
01977
01978
01979
01980 static void UI_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle) {
01981 rectDef_t rect;
01982
01983 rect.x = x + text_x;
01984 rect.y = y + text_y;
01985 rect.w = w;
01986 rect.h = h;
01987
01988 switch (ownerDraw) {
01989 case UI_HANDICAP:
01990 UI_DrawHandicap(&rect, scale, color, textStyle);
01991 break;
01992 case UI_EFFECTS:
01993 UI_DrawEffects(&rect, scale, color);
01994 break;
01995 case UI_PLAYERMODEL:
01996 UI_DrawPlayerModel(&rect);
01997 break;
01998 case UI_CLANNAME:
01999 UI_DrawClanName(&rect, scale, color, textStyle);
02000 break;
02001 case UI_CLANLOGO:
02002 UI_DrawClanLogo(&rect, scale, color);
02003 break;
02004 case UI_CLANCINEMATIC:
02005 UI_DrawClanCinematic(&rect, scale, color);
02006 break;
02007 case UI_PREVIEWCINEMATIC:
02008 UI_DrawPreviewCinematic(&rect, scale, color);
02009 break;
02010 case UI_GAMETYPE:
02011 UI_DrawGameType(&rect, scale, color, textStyle);
02012 break;
02013 case UI_NETGAMETYPE:
02014 UI_DrawNetGameType(&rect, scale, color, textStyle);
02015 break;
02016 case UI_JOINGAMETYPE:
02017 UI_DrawJoinGameType(&rect, scale, color, textStyle);
02018 break;
02019 case UI_MAPPREVIEW:
02020 UI_DrawMapPreview(&rect, scale, color, qtrue);
02021 break;
02022 case UI_MAP_TIMETOBEAT:
02023 UI_DrawMapTimeToBeat(&rect, scale, color, textStyle);
02024 break;
02025 case UI_MAPCINEMATIC:
02026 UI_DrawMapCinematic(&rect, scale, color, qfalse);
02027 break;
02028 case UI_STARTMAPCINEMATIC:
02029 UI_DrawMapCinematic(&rect, scale, color, qtrue);
02030 break;
02031 case UI_SKILL:
02032 UI_DrawSkill(&rect, scale, color, textStyle);
02033 break;
02034 case UI_BLUETEAMNAME:
02035 UI_DrawTeamName(&rect, scale, color, qtrue, textStyle);
02036 break;
02037 case UI_REDTEAMNAME:
02038 UI_DrawTeamName(&rect, scale, color, qfalse, textStyle);
02039 break;
02040 case UI_BLUETEAM1:
02041 case UI_BLUETEAM2:
02042 case UI_BLUETEAM3:
02043 case UI_BLUETEAM4:
02044 case UI_BLUETEAM5:
02045 UI_DrawTeamMember(&rect, scale, color, qtrue, ownerDraw - UI_BLUETEAM1 + 1, textStyle);
02046 break;
02047 case UI_REDTEAM1:
02048 case UI_REDTEAM2:
02049 case UI_REDTEAM3:
02050 case UI_REDTEAM4:
02051 case UI_REDTEAM5:
02052 UI_DrawTeamMember(&rect, scale, color, qfalse, ownerDraw - UI_REDTEAM1 + 1, textStyle);
02053 break;
02054 case UI_NETSOURCE:
02055 UI_DrawNetSource(&rect, scale, color, textStyle);
02056 break;
02057 case UI_NETMAPPREVIEW:
02058 UI_DrawNetMapPreview(&rect, scale, color);
02059 break;
02060 case UI_NETMAPCINEMATIC:
02061 UI_DrawNetMapCinematic(&rect, scale, color);
02062 break;
02063 case UI_NETFILTER:
02064 UI_DrawNetFilter(&rect, scale, color, textStyle);
02065 break;
02066 case UI_TIER:
02067 UI_DrawTier(&rect, scale, color, textStyle);
02068 break;
02069 case UI_OPPONENTMODEL:
02070 UI_DrawOpponent(&rect);
02071 break;
02072 case UI_TIERMAP1:
02073 UI_DrawTierMap(&rect, 0);
02074 break;
02075 case UI_TIERMAP2:
02076 UI_DrawTierMap(&rect, 1);
02077 break;
02078 case UI_TIERMAP3:
02079 UI_DrawTierMap(&rect, 2);
02080 break;
02081 case UI_PLAYERLOGO:
02082 UI_DrawPlayerLogo(&rect, color);
02083 break;
02084 case UI_PLAYERLOGO_METAL:
02085 UI_DrawPlayerLogoMetal(&rect, color);
02086 break;
02087 case UI_PLAYERLOGO_NAME:
02088 UI_DrawPlayerLogoName(&rect, color);
02089 break;
02090 case UI_OPPONENTLOGO:
02091 UI_DrawOpponentLogo(&rect, color);
02092 break;
02093 case UI_OPPONENTLOGO_METAL:
02094 UI_DrawOpponentLogoMetal(&rect, color);
02095 break;
02096 case UI_OPPONENTLOGO_NAME:
02097 UI_DrawOpponentLogoName(&rect, color);
02098 break;
02099 case UI_TIER_MAPNAME:
02100 UI_DrawTierMapName(&rect, scale, color, textStyle);
02101 break;
02102 case UI_TIER_GAMETYPE:
02103 UI_DrawTierGameType(&rect, scale, color, textStyle);
02104 break;
02105 case UI_ALLMAPS_SELECTION:
02106 UI_DrawAllMapsSelection(&rect, scale, color, textStyle, qtrue);
02107 break;
02108 case UI_MAPS_SELECTION:
02109 UI_DrawAllMapsSelection(&rect, scale, color, textStyle, qfalse);
02110 break;
02111 case UI_OPPONENT_NAME:
02112 UI_DrawOpponentName(&rect, scale, color, textStyle);
02113 break;
02114 case UI_BOTNAME:
02115 UI_DrawBotName(&rect, scale, color, textStyle);
02116 break;
02117 case UI_BOTSKILL:
02118 UI_DrawBotSkill(&rect, scale, color, textStyle);
02119 break;
02120 case UI_REDBLUE:
02121 UI_DrawRedBlue(&rect, scale, color, textStyle);
02122 break;
02123 case UI_CROSSHAIR:
02124 UI_DrawCrosshair(&rect, scale, color);
02125 break;
02126 case UI_SELECTEDPLAYER:
02127 UI_DrawSelectedPlayer(&rect, scale, color, textStyle);
02128 break;
02129 case UI_SERVERREFRESHDATE:
02130 UI_DrawServerRefreshDate(&rect, scale, color, textStyle);
02131 break;
02132 case UI_SERVERMOTD:
02133 UI_DrawServerMOTD(&rect, scale, color);
02134 break;
02135 case UI_GLINFO:
02136 UI_DrawGLInfo(&rect,scale, color, textStyle);
02137 break;
02138 case UI_KEYBINDSTATUS:
02139 UI_DrawKeyBindStatus(&rect,scale, color, textStyle);
02140 break;
02141 default:
02142 break;
02143 }
02144
02145 }
02146
02147 static qboolean UI_OwnerDrawVisible(int flags) {
02148 qboolean vis = qtrue;
02149
02150 while (flags) {
02151
02152 if (flags & UI_SHOW_FFA) {
02153 if (trap_Cvar_VariableValue("g_gametype") != GT_FFA) {
02154 vis = qfalse;
02155 }
02156 flags &= ~UI_SHOW_FFA;
02157 }
02158
02159 if (flags & UI_SHOW_NOTFFA) {
02160 if (trap_Cvar_VariableValue("g_gametype") == GT_FFA) {
02161 vis = qfalse;
02162 }
02163 flags &= ~UI_SHOW_NOTFFA;
02164 }
02165
02166 if (flags & UI_SHOW_LEADER) {
02167
02168 if (!uiInfo.teamLeader) {
02169 vis = qfalse;
02170 } else {
02171
02172 if (ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber) {
02173 vis = qfalse;
02174 }
02175 }
02176 flags &= ~UI_SHOW_LEADER;
02177 }
02178 if (flags & UI_SHOW_NOTLEADER) {
02179
02180 if (uiInfo.teamLeader) {
02181
02182 if (!(ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber)) {
02183 vis = qfalse;
02184 }
02185
02186 }
02187 flags &= ~UI_SHOW_NOTLEADER;
02188 }
02189 if (flags & UI_SHOW_FAVORITESERVERS) {
02190
02191 if (ui_netSource.integer != AS_FAVORITES) {
02192 vis = qfalse;
02193 }
02194 flags &= ~UI_SHOW_FAVORITESERVERS;
02195 }
02196 if (flags & UI_SHOW_NOTFAVORITESERVERS) {
02197
02198 if (ui_netSource.integer == AS_FAVORITES) {
02199 vis = qfalse;
02200 }
02201 flags &= ~UI_SHOW_NOTFAVORITESERVERS;
02202 }
02203 if (flags & UI_SHOW_ANYTEAMGAME) {
02204 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum <= GT_TEAM ) {
02205 vis = qfalse;
02206 }
02207 flags &= ~UI_SHOW_ANYTEAMGAME;
02208 }
02209 if (flags & UI_SHOW_ANYNONTEAMGAME) {
02210 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum > GT_TEAM ) {
02211 vis = qfalse;
02212 }
02213 flags &= ~UI_SHOW_ANYNONTEAMGAME;
02214 }
02215 if (flags & UI_SHOW_NETANYTEAMGAME) {
02216 if (uiInfo.gameTypes[ui_netGameType.integer].gtEnum <= GT_TEAM ) {
02217 vis = qfalse;
02218 }
02219 flags &= ~UI_SHOW_NETANYTEAMGAME;
02220 }
02221 if (flags & UI_SHOW_NETANYNONTEAMGAME) {
02222 if (uiInfo.gameTypes[ui_netGameType.integer].gtEnum > GT_TEAM ) {
02223 vis = qfalse;
02224 }
02225 flags &= ~UI_SHOW_NETANYNONTEAMGAME;
02226 }
02227 if (flags & UI_SHOW_NEWHIGHSCORE) {
02228 if (uiInfo.newHighScoreTime < uiInfo.uiDC.realTime) {
02229 vis = qfalse;
02230 } else {
02231 if (uiInfo.soundHighScore) {
02232 if (trap_Cvar_VariableValue("sv_killserver") == 0) {
02233
02234 trap_S_StartLocalSound(uiInfo.newHighScoreSound, CHAN_ANNOUNCER);
02235 uiInfo.soundHighScore = qfalse;
02236 }
02237 }
02238 }
02239 flags &= ~UI_SHOW_NEWHIGHSCORE;
02240 }
02241 if (flags & UI_SHOW_NEWBESTTIME) {
02242 if (uiInfo.newBestTime < uiInfo.uiDC.realTime) {
02243 vis = qfalse;
02244 }
02245 flags &= ~UI_SHOW_NEWBESTTIME;
02246 }
02247 if (flags & UI_SHOW_DEMOAVAILABLE) {
02248 if (!uiInfo.demoAvailable) {
02249 vis = qfalse;
02250 }
02251 flags &= ~UI_SHOW_DEMOAVAILABLE;
02252 } else {
02253 flags = 0;
02254 }
02255 }
02256 return vis;
02257 }
02258
02259 static qboolean UI_Handicap_HandleKey(int flags, float *special, int key) {
02260 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02261 int h;
02262 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );
02263 if (key == K_MOUSE2) {
02264 h -= 5;
02265 } else {
02266 h += 5;
02267 }
02268 if (h > 100) {
02269 h = 5;
02270 } else if (h < 0) {
02271 h = 100;
02272 }
02273 trap_Cvar_Set( "handicap", va( "%i", h) );
02274 return qtrue;
02275 }
02276 return qfalse;
02277 }
02278
02279 static qboolean UI_Effects_HandleKey(int flags, float *special, int key) {
02280 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02281
02282 if (key == K_MOUSE2) {
02283 uiInfo.effectsColor--;
02284 } else {
02285 uiInfo.effectsColor++;
02286 }
02287
02288 if( uiInfo.effectsColor > 6 ) {
02289 uiInfo.effectsColor = 0;
02290 } else if (uiInfo.effectsColor < 0) {
02291 uiInfo.effectsColor = 6;
02292 }
02293
02294 trap_Cvar_SetValue( "color1", uitogamecode[uiInfo.effectsColor] );
02295 return qtrue;
02296 }
02297 return qfalse;
02298 }
02299
02300 static qboolean UI_ClanName_HandleKey(int flags, float *special, int key) {
02301 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02302 int i;
02303 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
02304 if (uiInfo.teamList[i].cinematic >= 0) {
02305 trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic);
02306 uiInfo.teamList[i].cinematic = -1;
02307 }
02308 if (key == K_MOUSE2) {
02309 i--;
02310 } else {
02311 i++;
02312 }
02313 if (i >= uiInfo.teamCount) {
02314 i = 0;
02315 } else if (i < 0) {
02316 i = uiInfo.teamCount - 1;
02317 }
02318 trap_Cvar_Set( "ui_teamName", uiInfo.teamList[i].teamName);
02319 UI_HeadCountByTeam();
02320 UI_FeederSelection(FEEDER_HEADS, 0);
02321 updateModel = qtrue;
02322 return qtrue;
02323 }
02324 return qfalse;
02325 }
02326
02327 static qboolean UI_GameType_HandleKey(int flags, float *special, int key, qboolean resetMap) {
02328 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02329 int oldCount = UI_MapCountByGameType(qtrue);
02330
02331
02332 if (key == K_MOUSE2) {
02333 ui_gameType.integer--;
02334 if (ui_gameType.integer == 2) {
02335 ui_gameType.integer = 1;
02336 } else if (ui_gameType.integer < 2) {
02337 ui_gameType.integer = uiInfo.numGameTypes - 1;
02338 }
02339 } else {
02340 ui_gameType.integer++;
02341 if (ui_gameType.integer >= uiInfo.numGameTypes) {
02342 ui_gameType.integer = 1;
02343 } else if (ui_gameType.integer == 2) {
02344 ui_gameType.integer = 3;
02345 }
02346 }
02347
02348 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_TOURNAMENT) {
02349 trap_Cvar_Set("ui_Q3Model", "1");
02350 } else {
02351 trap_Cvar_Set("ui_Q3Model", "0");
02352 }
02353
02354 trap_Cvar_Set("ui_gameType", va("%d", ui_gameType.integer));
02355 UI_SetCapFragLimits(qtrue);
02356 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);
02357 if (resetMap && oldCount != UI_MapCountByGameType(qtrue)) {
02358 trap_Cvar_Set( "ui_currentMap", "0");
02359 Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, NULL);
02360 }
02361 return qtrue;
02362 }
02363 return qfalse;
02364 }
02365
02366 static qboolean UI_NetGameType_HandleKey(int flags, float *special, int key) {
02367 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02368
02369 if (key == K_MOUSE2) {
02370 ui_netGameType.integer--;
02371 } else {
02372 ui_netGameType.integer++;
02373 }
02374
02375 if (ui_netGameType.integer < 0) {
02376 ui_netGameType.integer = uiInfo.numGameTypes - 1;
02377 } else if (ui_netGameType.integer >= uiInfo.numGameTypes) {
02378 ui_netGameType.integer = 0;
02379 }
02380
02381 trap_Cvar_Set( "ui_netGameType", va("%d", ui_netGameType.integer));
02382 trap_Cvar_Set( "ui_actualnetGameType", va("%d", uiInfo.gameTypes[ui_netGameType.integer].gtEnum));
02383 trap_Cvar_Set( "ui_currentNetMap", "0");
02384 UI_MapCountByGameType(qfalse);
02385 Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, NULL);
02386 return qtrue;
02387 }
02388 return qfalse;
02389 }
02390
02391 static qboolean UI_JoinGameType_HandleKey(int flags, float *special, int key) {
02392 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02393
02394 if (key == K_MOUSE2) {
02395 ui_joinGameType.integer--;
02396 } else {
02397 ui_joinGameType.integer++;
02398 }
02399
02400 if (ui_joinGameType.integer < 0) {
02401 ui_joinGameType.integer = uiInfo.numJoinGameTypes - 1;
02402 } else if (ui_joinGameType.integer >= uiInfo.numJoinGameTypes) {
02403 ui_joinGameType.integer = 0;
02404 }
02405
02406 trap_Cvar_Set( "ui_joinGameType", va("%d", ui_joinGameType.integer));
02407 UI_BuildServerDisplayList(qtrue);
02408 return qtrue;
02409 }
02410 return qfalse;
02411 }
02412
02413
02414
02415 static qboolean UI_Skill_HandleKey(int flags, float *special, int key) {
02416 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02417 int i = trap_Cvar_VariableValue( "g_spSkill" );
02418
02419 if (key == K_MOUSE2) {
02420 i--;
02421 } else {
02422 i++;
02423 }
02424
02425 if (i < 1) {
02426 i = numSkillLevels;
02427 } else if (i > numSkillLevels) {
02428 i = 1;
02429 }
02430
02431 trap_Cvar_Set("g_spSkill", va("%i", i));
02432 return qtrue;
02433 }
02434 return qfalse;
02435 }
02436
02437 static qboolean UI_TeamName_HandleKey(int flags, float *special, int key, qboolean blue) {
02438 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02439 int i;
02440 i = UI_TeamIndexFromName(UI_Cvar_VariableString((blue) ? "ui_blueTeam" : "ui_redTeam"));
02441
02442 if (key == K_MOUSE2) {
02443 i--;
02444 } else {
02445 i++;
02446 }
02447
02448 if (i >= uiInfo.teamCount) {
02449 i = 0;
02450 } else if (i < 0) {
02451 i = uiInfo.teamCount - 1;
02452 }
02453
02454 trap_Cvar_Set( (blue) ? "ui_blueTeam" : "ui_redTeam", uiInfo.teamList[i].teamName);
02455
02456 return qtrue;
02457 }
02458 return qfalse;
02459 }
02460
02461 static qboolean UI_TeamMember_HandleKey(int flags, float *special, int key, qboolean blue, int num) {
02462 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02463
02464
02465
02466 char *cvar = va(blue ? "ui_blueteam%i" : "ui_redteam%i", num);
02467 int value = trap_Cvar_VariableValue(cvar);
02468
02469 if (key == K_MOUSE2) {
02470 value--;
02471 } else {
02472 value++;
02473 }
02474
02475 if (ui_actualNetGameType.integer >= GT_TEAM) {
02476 if (value >= uiInfo.characterCount + 2) {
02477 value = 0;
02478 } else if (value < 0) {
02479 value = uiInfo.characterCount + 2 - 1;
02480 }
02481 } else {
02482 if (value >= UI_GetNumBots() + 2) {
02483 value = 0;
02484 } else if (value < 0) {
02485 value = UI_GetNumBots() + 2 - 1;
02486 }
02487 }
02488
02489 trap_Cvar_Set(cvar, va("%i", value));
02490 return qtrue;
02491 }
02492 return qfalse;
02493 }
02494
02495 static qboolean UI_NetSource_HandleKey(int flags, float *special, int key) {
02496 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02497
02498 if (key == K_MOUSE2) {
02499 ui_netSource.integer--;
02500 if (ui_netSource.integer == AS_MPLAYER)
02501 ui_netSource.integer--;
02502 } else {
02503 ui_netSource.integer++;
02504 if (ui_netSource.integer == AS_MPLAYER)
02505 ui_netSource.integer++;
02506 }
02507
02508 if (ui_netSource.integer >= numNetSources) {
02509 ui_netSource.integer = 0;
02510 } else if (ui_netSource.integer < 0) {
02511 ui_netSource.integer = numNetSources - 1;
02512 }
02513
02514 UI_BuildServerDisplayList(qtrue);
02515 if (ui_netSource.integer != AS_GLOBAL) {
02516 UI_StartServerRefresh(qtrue);
02517 }
02518 trap_Cvar_Set( "ui_netSource", va("%d", ui_netSource.integer));
02519 return qtrue;
02520 }
02521 return qfalse;
02522 }
02523
02524 static qboolean UI_NetFilter_HandleKey(int flags, float *special, int key) {
02525 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02526
02527 if (key == K_MOUSE2) {
02528 ui_serverFilterType.integer--;
02529 } else {
02530 ui_serverFilterType.integer++;
02531 }
02532
02533 if (ui_serverFilterType.integer >= numServerFilters) {
02534 ui_serverFilterType.integer = 0;
02535 } else if (ui_serverFilterType.integer < 0) {
02536 ui_serverFilterType.integer = numServerFilters - 1;
02537 }
02538 UI_BuildServerDisplayList(qtrue);
02539 return qtrue;
02540 }
02541 return qfalse;
02542 }
02543
02544 static qboolean UI_OpponentName_HandleKey(int flags, float *special, int key) {
02545 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02546 if (key == K_MOUSE2) {
02547 UI_PriorOpponent();
02548 } else {
02549 UI_NextOpponent();
02550 }
02551 return qtrue;
02552 }
02553 return qfalse;
02554 }
02555
02556 static qboolean UI_BotName_HandleKey(int flags, float *special, int key) {
02557 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02558 int game = trap_Cvar_VariableValue("g_gametype");
02559 int value = uiInfo.botIndex;
02560
02561 if (key == K_MOUSE2) {
02562 value--;
02563 } else {
02564 value++;
02565 }
02566
02567 if (game >= GT_TEAM) {
02568 if (value >= uiInfo.characterCount + 2) {
02569 value = 0;
02570 } else if (value < 0) {
02571 value = uiInfo.characterCount + 2 - 1;
02572 }
02573 } else {
02574 if (value >= UI_GetNumBots() + 2) {
02575 value = 0;
02576 } else if (value < 0) {
02577 value = UI_GetNumBots() + 2 - 1;
02578 }
02579 }
02580 uiInfo.botIndex = value;
02581 return qtrue;
02582 }
02583 return qfalse;
02584 }
02585
02586 static qboolean UI_BotSkill_HandleKey(int flags, float *special, int key) {
02587 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02588 if (key == K_MOUSE2) {
02589 uiInfo.skillIndex--;
02590 } else {
02591 uiInfo.skillIndex++;
02592 }
02593 if (uiInfo.skillIndex >= numSkillLevels) {
02594 uiInfo.skillIndex = 0;
02595 } else if (uiInfo.skillIndex < 0) {
02596 uiInfo.skillIndex = numSkillLevels-1;
02597 }
02598 return qtrue;
02599 }
02600 return qfalse;
02601 }
02602
02603 static qboolean UI_RedBlue_HandleKey(int flags, float *special, int key) {
02604 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02605 uiInfo.redBlue ^= 1;
02606 return qtrue;
02607 }
02608 return qfalse;
02609 }
02610
02611 static qboolean UI_Crosshair_HandleKey(int flags, float *special, int key) {
02612 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02613 if (key == K_MOUSE2) {
02614 uiInfo.currentCrosshair--;
02615 } else {
02616 uiInfo.currentCrosshair++;
02617 }
02618
02619 if (uiInfo.currentCrosshair >= NUM_CROSSHAIRS) {
02620 uiInfo.currentCrosshair = 0;
02621 } else if (uiInfo.currentCrosshair < 0) {
02622 uiInfo.currentCrosshair = NUM_CROSSHAIRS - 1;
02623 }
02624 trap_Cvar_Set("cg_drawCrosshair", va("%d", uiInfo.currentCrosshair));
02625 return qtrue;
02626 }
02627 return qfalse;
02628 }
02629
02630
02631
02632 static qboolean UI_SelectedPlayer_HandleKey(int flags, float *special, int key) {
02633 if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_ENTER || key == K_KP_ENTER) {
02634 int selected;
02635
02636 UI_BuildPlayerList();
02637 if (!uiInfo.teamLeader) {
02638 return qfalse;
02639 }
02640 selected = trap_Cvar_VariableValue("cg_selectedPlayer");
02641
02642 if (key == K_MOUSE2) {
02643 selected--;
02644 } else {
02645 selected++;
02646 }
02647
02648 if (selected > uiInfo.myTeamCount) {
02649 selected = 0;
02650 } else if (selected < 0) {
02651 selected = uiInfo.myTeamCount;
02652 }
02653
02654 if (selected == uiInfo.myTeamCount) {
02655 trap_Cvar_Set( "cg_selectedPlayerName", "Everyone");
02656 } else {
02657 trap_Cvar_Set( "cg_selectedPlayerName", uiInfo.teamNames[selected]);
02658 }
02659 trap_Cvar_Set( "cg_selectedPlayer", va("%d", selected));
02660 }
02661 return qfalse;
02662 }
02663
02664
02665 static qboolean UI_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key) {
02666 switch (ownerDraw) {
02667 case UI_HANDICAP:
02668 return UI_Handicap_HandleKey(flags, special, key);
02669 break;
02670 case UI_EFFECTS:
02671 return UI_Effects_HandleKey(flags, special, key);
02672 break;
02673 case UI_CLANNAME:
02674 return UI_ClanName_HandleKey(flags, special, key);
02675 break;
02676 case UI_GAMETYPE:
02677 return UI_GameType_HandleKey(flags, special, key, qtrue);
02678 break;
02679 case UI_NETGAMETYPE:
02680 return UI_NetGameType_HandleKey(flags, special, key);
02681 break;
02682 case UI_JOINGAMETYPE:
02683 return UI_JoinGameType_HandleKey(flags, special, key);
02684 break;
02685 case UI_SKILL:
02686 return UI_Skill_HandleKey(flags, special, key);
02687 break;
02688 case UI_BLUETEAMNAME:
02689 return UI_TeamName_HandleKey(flags, special, key, qtrue);
02690 break;
02691 case UI_REDTEAMNAME:
02692 return UI_TeamName_HandleKey(flags, special, key, qfalse);
02693 break;
02694 case UI_BLUETEAM1:
02695 case UI_BLUETEAM2:
02696 case UI_BLUETEAM3:
02697 case UI_BLUETEAM4:
02698 case UI_BLUETEAM5:
02699 UI_TeamMember_HandleKey(flags, special, key, qtrue, ownerDraw - UI_BLUETEAM1 + 1);
02700 break;
02701 case UI_REDTEAM1:
02702 case UI_REDTEAM2:
02703 case UI_REDTEAM3:
02704 case UI_REDTEAM4:
02705 case UI_REDTEAM5:
02706 UI_TeamMember_HandleKey(flags, special, key, qfalse, ownerDraw - UI_REDTEAM1 + 1);
02707 break;
02708 case UI_NETSOURCE:
02709 UI_NetSource_HandleKey(flags, special, key);
02710 break;
02711 case UI_NETFILTER:
02712 UI_NetFilter_HandleKey(flags, special, key);
02713 break;
02714 case UI_OPPONENT_NAME:
02715 UI_OpponentName_HandleKey(flags, special, key);
02716 break;
02717 case UI_BOTNAME:
02718 return UI_BotName_HandleKey(flags, special, key);
02719 break;
02720 case UI_BOTSKILL:
02721 return UI_BotSkill_HandleKey(flags, special, key);
02722 break;
02723 case UI_REDBLUE:
02724 UI_RedBlue_HandleKey(flags, special, key);
02725 break;
02726 case UI_CROSSHAIR:
02727 UI_Crosshair_HandleKey(flags, special, key);
02728 break;
02729 case UI_SELECTEDPLAYER:
02730 UI_SelectedPlayer_HandleKey(flags, special, key);
02731 break;
02732 default:
02733 break;
02734 }
02735
02736 return qfalse;
02737 }
02738
02739
02740 static float UI_GetValue(int ownerDraw) {
02741 return 0;
02742 }
02743
02744
02745
02746
02747
02748
02749 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ) {
02750 return trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey, uiInfo.serverStatus.sortDir, *(int*)arg1, *(int*)arg2);
02751 }
02752
02753
02754
02755
02756
02757
02758
02759 void UI_ServersSort(int column, qboolean force) {
02760
02761 if ( !force ) {
02762 if ( uiInfo.serverStatus.sortKey == column ) {
02763 return;
02764 }
02765 }
02766
02767 uiInfo.serverStatus.sortKey = column;
02768 qsort( &uiInfo.serverStatus.displayServers[0], uiInfo.serverStatus.numDisplayServers, sizeof(int), UI_ServersQsortCompare);
02769 }
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816 static void UI_LoadMods() {
02817 int numdirs;
02818 char dirlist[2048];
02819 char *dirptr;
02820 char *descptr;
02821 int i;
02822 int dirlen;
02823
02824 uiInfo.modCount = 0;
02825 numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof(dirlist) );
02826 dirptr = dirlist;
02827 for( i = 0; i < numdirs; i++ ) {
02828 dirlen = strlen( dirptr ) + 1;
02829 descptr = dirptr + dirlen;
02830 uiInfo.modList[uiInfo.modCount].modName = String_Alloc(dirptr);
02831 uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc(descptr);
02832 dirptr += dirlen + strlen(descptr) + 1;
02833 uiInfo.modCount++;
02834 if (uiInfo.modCount >= MAX_MODS) {
02835 break;
02836 }
02837 }
02838
02839 }
02840
02841
02842
02843
02844
02845
02846
02847 static void UI_LoadTeams() {
02848 char teamList[4096];
02849 char *teamName;
02850 int i, len, count;
02851
02852 count = trap_FS_GetFileList( "", "team", teamList, 4096 );
02853
02854 if (count) {
02855 teamName = teamList;
02856 for ( i = 0; i < count; i++ ) {
02857 len = strlen( teamName );
02858 UI_ParseTeamInfo(teamName);
02859 teamName += len + 1;
02860 }
02861 }
02862
02863 }
02864
02865
02866
02867
02868
02869
02870
02871 static void UI_LoadMovies() {
02872 char movielist[4096];
02873 char *moviename;
02874 int i, len;
02875
02876 uiInfo.movieCount = trap_FS_GetFileList( "video", "roq", movielist, 4096 );
02877
02878 if (uiInfo.movieCount) {
02879 if (uiInfo.movieCount > MAX_MOVIES) {
02880 uiInfo.movieCount = MAX_MOVIES;
02881 }
02882 moviename = movielist;
02883 for ( i = 0; i < uiInfo.movieCount; i++ ) {
02884 len = strlen( moviename );
02885 if (!Q_stricmp(moviename + len - 4,".roq")) {
02886 moviename[len-4] = '\0';
02887 }
02888 Q_strupr(moviename);
02889 uiInfo.movieList[i] = String_Alloc(moviename);
02890 moviename += len + 1;
02891 }
02892 }
02893
02894 }
02895
02896
02897
02898
02899
02900
02901
02902
02903 static void UI_LoadDemos() {
02904 char demolist[4096];
02905 char demoExt[32];
02906 char *demoname;
02907 int i, len;
02908
02909 Com_sprintf(demoExt, sizeof(demoExt), "dm_%d", (int)trap_Cvar_VariableValue("protocol"));
02910
02911 uiInfo.demoCount = trap_FS_GetFileList( "demos", demoExt, demolist, 4096 );
02912
02913 Com_sprintf(demoExt, sizeof(demoExt), ".dm_%d", (int)trap_Cvar_VariableValue("protocol"));
02914
02915 if (uiInfo.demoCount) {
02916 if (uiInfo.demoCount > MAX_DEMOS) {
02917 uiInfo.demoCount = MAX_DEMOS;
02918 }
02919 demoname = demolist;
02920 for ( i = 0; i < uiInfo.demoCount; i++ ) {
02921 len = strlen( demoname );
02922 if (!Q_stricmp(demoname + len - strlen(demoExt), demoExt)) {
02923 demoname[len-strlen(demoExt)] = '\0';
02924 }
02925 Q_strupr(demoname);
02926 uiInfo.demoList[i] = String_Alloc(demoname);
02927 demoname += len + 1;
02928 }
02929 }
02930
02931 }
02932
02933
02934 static qboolean UI_SetNextMap(int actual, int index) {
02935 int i;
02936 for (i = actual + 1; i < uiInfo.mapCount; i++) {
02937 if (uiInfo.mapList[i].active) {
02938 Menu_SetFeederSelection(NULL, FEEDER_MAPS, index + 1, "skirmish");
02939 return qtrue;
02940 }
02941 }
02942 return qfalse;
02943 }
02944
02945
02946 static void UI_StartSkirmish(qboolean next) {
02947 int i, k, g, delay, temp;
02948 float skill;
02949 char buff[MAX_STRING_CHARS];
02950
02951 if (next) {
02952 int actual;
02953 int index = trap_Cvar_VariableValue("ui_mapIndex");
02954 UI_MapCountByGameType(qtrue);
02955 UI_SelectedMap(index, &actual);
02956 if (UI_SetNextMap(actual, index)) {
02957 } else {
02958 UI_GameType_HandleKey(0, 0, K_MOUSE1, qfalse);
02959 UI_MapCountByGameType(qtrue);
02960 Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, "skirmish");
02961 }
02962 }
02963
02964 g = uiInfo.gameTypes[ui_gameType.integer].gtEnum;
02965 trap_Cvar_SetValue( "g_gametype", g );
02966 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName) );
02967 skill = trap_Cvar_VariableValue( "g_spSkill" );
02968 trap_Cvar_Set("ui_scoreMap", uiInfo.mapList[ui_currentMap.integer].mapName);
02969
02970 k = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
02971
02972 trap_Cvar_Set("ui_singlePlayerActive", "1");
02973
02974
02975 temp = trap_Cvar_VariableValue( "capturelimit" );
02976 trap_Cvar_Set("ui_saveCaptureLimit", va("%i", temp));
02977 temp = trap_Cvar_VariableValue( "fraglimit" );
02978 trap_Cvar_Set("ui_saveFragLimit", va("%i", temp));
02979
02980 UI_SetCapFragLimits(qfalse);
02981
02982 temp = trap_Cvar_VariableValue( "cg_drawTimer" );
02983 trap_Cvar_Set("ui_drawTimer", va("%i", temp));
02984 temp = trap_Cvar_VariableValue( "g_doWarmup" );
02985 trap_Cvar_Set("ui_doWarmup", va("%i", temp));
02986 temp = trap_Cvar_VariableValue( "g_friendlyFire" );
02987 trap_Cvar_Set("ui_friendlyFire", va("%i", temp));
02988 temp = trap_Cvar_VariableValue( "sv_maxClients" );
02989 trap_Cvar_Set("ui_maxClients", va("%i", temp));
02990 temp = trap_Cvar_VariableValue( "g_warmup" );
02991 trap_Cvar_Set("ui_Warmup", va("%i", temp));
02992 temp = trap_Cvar_VariableValue( "sv_pure" );
02993 trap_Cvar_Set("ui_pure", va("%i", temp));
02994
02995 trap_Cvar_Set("cg_cameraOrbit", "0");
02996 trap_Cvar_Set("cg_thirdPerson", "0");
02997 trap_Cvar_Set("cg_drawTimer", "1");
02998 trap_Cvar_Set("g_doWarmup", "1");
02999 trap_Cvar_Set("g_warmup", "15");
03000 trap_Cvar_Set("sv_pure", "0");
03001 trap_Cvar_Set("g_friendlyFire", "0");
03002 trap_Cvar_Set("g_redTeam", UI_Cvar_VariableString("ui_teamName"));
03003 trap_Cvar_Set("g_blueTeam", UI_Cvar_VariableString("ui_opponentName"));
03004
03005 if (trap_Cvar_VariableValue("ui_recordSPDemo")) {
03006 Com_sprintf(buff, MAX_STRING_CHARS, "%s_%i", uiInfo.mapList[ui_currentMap.integer].mapLoadName, g);
03007 trap_Cvar_Set("ui_recordSPDemoName", buff);
03008 }
03009
03010 delay = 500;
03011
03012 if (g == GT_TOURNAMENT) {
03013 trap_Cvar_Set("sv_maxClients", "2");
03014 Com_sprintf( buff, sizeof(buff), "wait ; addbot %s %f "", %i \n", uiInfo.mapList[ui_currentMap.integer].opponentName, skill, delay);
03015 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
03016 } else {
03017 temp = uiInfo.mapList[ui_currentMap.integer].teamMembers * 2;
03018 trap_Cvar_Set("sv_maxClients", va("%d", temp));
03019 for (i =0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers; i++) {
03020 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s %i %s\n", UI_AIFromName(uiInfo.teamList[k].teamMembers[i]), skill, (g == GT_FFA) ? "" : "Blue", delay, uiInfo.teamList[k].teamMembers[i]);
03021 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
03022 delay += 500;
03023 }
03024 k = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
03025 for (i =0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers-1; i++) {
03026 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s %i %s\n", UI_AIFromName(uiInfo.teamList[k].teamMembers[i]), skill, (g == GT_FFA) ? "" : "Red", delay, uiInfo.teamList[k].teamMembers[i]);
03027 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
03028 delay += 500;
03029 }
03030 }
03031 if (g >= GT_TEAM ) {
03032 trap_Cmd_ExecuteText( EXEC_APPEND, "wait 5; team Red\n" );
03033 }
03034 }
03035
03036 static void UI_Update(const char *name) {
03037 int val = trap_Cvar_VariableValue(name);
03038
03039 if (Q_stricmp(name, "ui_SetName") == 0) {
03040 trap_Cvar_Set( "name", UI_Cvar_VariableString("ui_Name"));
03041 } else if (Q_stricmp(name, "ui_setRate") == 0) {
03042 float rate = trap_Cvar_VariableValue("rate");
03043 if (rate >= 5000) {
03044 trap_Cvar_Set("cl_maxpackets", "30");
03045 trap_Cvar_Set("cl_packetdup", "1");
03046 } else if (rate >= 4000) {
03047 trap_Cvar_Set("cl_maxpackets", "15");
03048 trap_Cvar_Set("cl_packetdup", "2");
03049 } else {
03050 trap_Cvar_Set("cl_maxpackets", "15");
03051 trap_Cvar_Set("cl_packetdup", "1");
03052 }
03053 } else if (Q_stricmp(name, "ui_GetName") == 0) {
03054 trap_Cvar_Set( "ui_Name", UI_Cvar_VariableString("name"));
03055 } else if (Q_stricmp(name, "r_colorbits") == 0) {
03056 switch (val) {
03057 case 0:
03058 trap_Cvar_SetValue( "r_depthbits", 0 );
03059 trap_Cvar_SetValue( "r_stencilbits", 0 );
03060 break;
03061 case 16:
03062 trap_Cvar_SetValue( "r_depthbits", 16 );
03063 trap_Cvar_SetValue( "r_stencilbits", 0 );
03064 break;
03065 case 32:
03066 trap_Cvar_SetValue( "r_depthbits", 24 );
03067 break;
03068 }
03069 } else if (Q_stricmp(name, "r_lodbias") == 0) {
03070 switch (val) {
03071 case 0:
03072 trap_Cvar_SetValue( "r_subdivisions", 4 );
03073 break;
03074 case 1:
03075 trap_Cvar_SetValue( "r_subdivisions", 12 );
03076 break;
03077 case 2:
03078 trap_Cvar_SetValue( "r_subdivisions", 20 );
03079 break;
03080 }
03081 } else if (Q_stricmp(name, "ui_glCustom") == 0) {
03082 switch (val) {
03083 case 0:
03084 trap_Cvar_SetValue( "r_fullScreen", 1 );
03085 trap_Cvar_SetValue( "r_subdivisions", 4 );
03086 trap_Cvar_SetValue( "r_vertexlight", 0 );
03087 trap_Cvar_SetValue( "r_lodbias", 0 );
03088 trap_Cvar_SetValue( "r_colorbits", 32 );
03089 trap_Cvar_SetValue( "r_depthbits", 24 );
03090 trap_Cvar_SetValue( "r_picmip", 0 );
03091 trap_Cvar_SetValue( "r_mode", 4 );
03092 trap_Cvar_SetValue( "r_texturebits", 32 );
03093 trap_Cvar_SetValue( "r_fastSky", 0 );
03094 trap_Cvar_SetValue( "r_inGameVideo", 1 );
03095 trap_Cvar_SetValue( "cg_shadows", 1 );
03096 trap_Cvar_SetValue( "cg_brassTime", 2500 );
03097 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
03098 break;
03099 case 1:
03100 trap_Cvar_SetValue( "r_fullScreen", 1 );
03101 trap_Cvar_SetValue( "r_subdivisions", 12 );
03102 trap_Cvar_SetValue( "r_vertexlight", 0 );
03103 trap_Cvar_SetValue( "r_lodbias", 0 );
03104 trap_Cvar_SetValue( "r_colorbits", 0 );
03105 trap_Cvar_SetValue( "r_depthbits", 24 );
03106 trap_Cvar_SetValue( "r_picmip", 1 );
03107 trap_Cvar_SetValue( "r_mode", 3 );
03108 trap_Cvar_SetValue( "r_texturebits", 0 );
03109 trap_Cvar_SetValue( "r_fastSky", 0 );
03110 trap_Cvar_SetValue( "r_inGameVideo", 1 );
03111 trap_Cvar_SetValue( "cg_brassTime", 2500 );
03112 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
03113 trap_Cvar_SetValue( "cg_shadows", 0 );
03114 break;
03115 case 2:
03116 trap_Cvar_SetValue( "r_fullScreen", 1 );
03117 trap_Cvar_SetValue( "r_subdivisions", 8 );
03118 trap_Cvar_SetValue( "r_vertexlight", 0 );
03119 trap_Cvar_SetValue( "r_lodbias", 1 );
03120 trap_Cvar_SetValue( "r_colorbits", 0 );
03121 trap_Cvar_SetValue( "r_depthbits", 0 );
03122 trap_Cvar_SetValue( "r_picmip", 1 );
03123 trap_Cvar_SetValue( "r_mode", 3 );
03124 trap_Cvar_SetValue( "r_texturebits", 0 );
03125 trap_Cvar_SetValue( "cg_shadows", 0 );
03126 trap_Cvar_SetValue( "r_fastSky", 1 );
03127 trap_Cvar_SetValue( "r_inGameVideo", 0 );
03128 trap_Cvar_SetValue( "cg_brassTime", 0 );
03129 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
03130 break;
03131 case 3:
03132 trap_Cvar_SetValue( "r_fullScreen", 1 );
03133 trap_Cvar_SetValue( "r_subdivisions", 20 );
03134 trap_Cvar_SetValue( "r_vertexlight", 1 );
03135 trap_Cvar_SetValue( "r_lodbias", 2 );
03136 trap_Cvar_SetValue( "r_colorbits", 16 );
03137 trap_Cvar_SetValue( "r_depthbits", 16 );
03138 trap_Cvar_SetValue( "r_mode", 3 );
03139 trap_Cvar_SetValue( "r_picmip", 2 );
03140 trap_Cvar_SetValue( "r_texturebits", 16 );
03141 trap_Cvar_SetValue( "cg_shadows", 0 );
03142 trap_Cvar_SetValue( "cg_brassTime", 0 );
03143 trap_Cvar_SetValue( "r_fastSky", 1 );
03144 trap_Cvar_SetValue( "r_inGameVideo", 0 );
03145 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
03146 break;
03147 }
03148 } else if (Q_stricmp(name, "ui_mousePitch") == 0) {
03149 if (val == 0) {
03150 trap_Cvar_SetValue( "m_pitch", 0.022f );
03151 } else {
03152 trap_Cvar_SetValue( "m_pitch", -0.022f );
03153 }
03154 }
03155 }
03156
03157 static void UI_RunMenuScript(char **args) {
03158 const char *name, *name2;
03159 char buff[1024];
03160
03161 if (String_Parse(args, &name)) {
03162 if (Q_stricmp(name, "StartServer") == 0) {
03163 int i, clients, oldclients;
03164 float skill;
03165 trap_Cvar_Set("cg_thirdPerson", "0");
03166 trap_Cvar_Set("cg_cameraOrbit", "0");
03167 trap_Cvar_Set("ui_singlePlayerActive", "0");
03168 trap_Cvar_SetValue( "dedicated", Com_Clamp( 0, 2, ui_dedicated.integer ) );
03169 trap_Cvar_SetValue( "g_gametype", Com_Clamp( 0, 8, uiInfo.gameTypes[ui_netGameType.integer].gtEnum ) );
03170 trap_Cvar_Set("g_redTeam", UI_Cvar_VariableString("ui_teamName"));
03171 trap_Cvar_Set("g_blueTeam", UI_Cvar_VariableString("ui_opponentName"));
03172 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName ) );
03173 skill = trap_Cvar_VariableValue( "g_spSkill" );
03174
03175 oldclients = trap_Cvar_VariableValue( "sv_maxClients" );
03176 clients = 0;
03177 for (i = 0; i < PLAYERS_PER_TEAM; i++) {
03178 int bot = trap_Cvar_VariableValue( va("ui_blueteam%i", i+1));
03179 if (bot >= 0) {
03180 clients++;
03181 }
03182 bot = trap_Cvar_VariableValue( va("ui_redteam%i", i+1));
03183 if (bot >= 0) {
03184 clients++;
03185 }
03186 }
03187 if (clients == 0) {
03188 clients = 8;
03189 }
03190
03191 if (oldclients > clients) {
03192 clients = oldclients;
03193 }
03194
03195 trap_Cvar_Set("sv_maxClients", va("%d",clients));
03196
03197 for (i = 0; i < PLAYERS_PER_TEAM; i++) {
03198 int bot = trap_Cvar_VariableValue( va("ui_blueteam%i", i+1));
03199 if (bot > 1) {
03200 if (ui_actualNetGameType.integer >= GT_TEAM) {
03201 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s\n", uiInfo.characterList[bot-2].name, skill, "Blue");
03202 } else {
03203 Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);
03204 }
03205 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
03206 }
03207 bot = trap_Cvar_VariableValue( va("ui_redteam%i", i+1));
03208 if (bot > 1) {
03209 if (ui_actualNetGameType.integer >= GT_TEAM) {
03210 Com_sprintf( buff, sizeof(buff), "addbot %s %f %s\n", uiInfo.characterList[bot-2].name, skill, "Red");
03211 } else {
03212 Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);
03213 }
03214 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
03215 }
03216 }
03217 } else if (Q_stricmp(name, "updateSPMenu") == 0) {
03218 UI_SetCapFragLimits(qtrue);
03219 UI_MapCountByGameType(qtrue);
03220 ui_mapIndex.integer = UI_GetIndexFromSelection(ui_currentMap.integer);
03221 trap_Cvar_Set("ui_mapIndex", va("%d", ui_mapIndex.integer));
03222 Menu_SetFeederSelection(NULL, FEEDER_MAPS, ui_mapIndex.integer, "skirmish");
03223 UI_GameType_HandleKey(0, 0, K_MOUSE1, qfalse);
03224 UI_GameType_HandleKey(0, 0, K_MOUSE2, qfalse);
03225 } else if (Q_stricmp(name, "resetDefaults") == 0) {
03226 trap_Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n");
03227 trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
03228 Controls_SetDefaults();
03229 trap_Cvar_Set("com_introPlayed", "1" );
03230 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
03231 } else if (Q_stricmp(name, "getCDKey") == 0) {
03232 char out[17];
03233 trap_GetCDKey(buff, 17);
03234 trap_Cvar_Set("cdkey1", "");
03235 trap_Cvar_Set("cdkey2", "");
03236 trap_Cvar_Set("cdkey3", "");
03237 trap_Cvar_Set("cdkey4", "");
03238 if (strlen(buff) == CDKEY_LEN) {
03239 Q_strncpyz(out, buff, 5);
03240 trap_Cvar_Set("cdkey1", out);
03241 Q_strncpyz(out, buff + 4, 5);
03242 trap_Cvar_Set("cdkey2", out);
03243 Q_strncpyz(out, buff + 8, 5);
03244 trap_Cvar_Set("cdkey3", out);
03245 Q_strncpyz(out, buff + 12, 5);
03246 trap_Cvar_Set("cdkey4", out);
03247 }
03248
03249 } else if (Q_stricmp(name, "verifyCDKey") == 0) {
03250 buff[0] = '\0';
03251 Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey1"));
03252 Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey2"));
03253 Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey3"));
03254 Q_strcat(buff, 1024, UI_Cvar_VariableString("cdkey4"));
03255 trap_Cvar_Set("cdkey", buff);
03256 if (trap_VerifyCDKey(buff, UI_Cvar_VariableString("cdkeychecksum"))) {
03257 trap_Cvar_Set("ui_cdkeyvalid", "CD Key Appears to be valid.");
03258 trap_SetCDKey(buff);
03259 } else {
03260 trap_Cvar_Set("ui_cdkeyvalid", "CD Key does not appear to be valid.");
03261 }
03262 } else if (Q_stricmp(name, "loadArenas") == 0) {
03263 UI_LoadArenas();
03264 UI_MapCountByGameType(qfalse);
03265 Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, "createserver");
03266 } else if (Q_stricmp(name, "saveControls") == 0) {
03267 Controls_SetConfig(qtrue);
03268 } else if (Q_stricmp(name, "loadControls") == 0) {
03269 Controls_GetConfig();
03270 } else if (Q_stricmp(name, "clearError") == 0) {
03271 trap_Cvar_Set("com_errorMessage", "");
03272 } else if (Q_stricmp(name, "loadGameInfo") == 0) {
03273 #ifdef PRE_RELEASE_TADEMO
03274 UI_ParseGameInfo("demogameinfo.txt");
03275 #else
03276 UI_ParseGameInfo("gameinfo.txt");
03277 #endif
03278 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);
03279 } else if (Q_stricmp(name, "resetScores") == 0) {
03280 UI_ClearScores();
03281 } else if (Q_stricmp(name, "RefreshServers") == 0) {
03282 UI_StartServerRefresh(qtrue);
03283 UI_BuildServerDisplayList(qtrue);
03284 } else if (Q_stricmp(name, "RefreshFilter") == 0) {
03285 UI_StartServerRefresh(qfalse);
03286 UI_BuildServerDisplayList(qtrue);
03287 } else if (Q_stricmp(name, "RunSPDemo") == 0) {
03288 if (uiInfo.demoAvailable) {
03289 trap_Cmd_ExecuteText( EXEC_APPEND, va("demo %s_%i\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum));
03290 }
03291 } else if (Q_stricmp(name, "LoadDemos") == 0) {
03292 UI_LoadDemos();
03293 } else if (Q_stricmp(name, "LoadMovies") == 0) {
03294 UI_LoadMovies();
03295 } else if (Q_stricmp(name, "LoadMods") == 0) {
03296 UI_LoadMods();
03297 } else if (Q_stricmp(name, "playMovie") == 0) {
03298 if (uiInfo.previewMovie >= 0) {
03299 trap_CIN_StopCinematic(uiInfo.previewMovie);
03300 }
03301 trap_Cmd_ExecuteText( EXEC_APPEND, va("cinematic %s.roq 2\n", uiInfo.movieList[uiInfo.movieIndex]));
03302 } else if (Q_stricmp(name, "RunMod") == 0) {
03303 trap_Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName);
03304 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
03305 } else if (Q_stricmp(name, "RunDemo") == 0) {
03306 trap_Cmd_ExecuteText( EXEC_APPEND, va("demo %s\n", uiInfo.demoList[uiInfo.demoIndex]));
03307 } else if (Q_stricmp(name, "Quake3") == 0) {
03308 trap_Cvar_Set( "fs_game", "");
03309 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
03310 } else if (Q_stricmp(name, "closeJoin") == 0) {
03311 if (uiInfo.serverStatus.refreshActive) {
03312 UI_StopServerRefresh();
03313 uiInfo.serverStatus.nextDisplayRefresh = 0;
03314 uiInfo.nextServerStatusRefresh = 0;
03315 uiInfo.nextFindPlayerRefresh = 0;
03316 UI_BuildServerDisplayList(qtrue);
03317 } else {
03318 Menus_CloseByName("joinserver");
03319 Menus_OpenByName("main");
03320 }
03321 } else if (Q_stricmp(name, "StopRefresh") == 0) {
03322 UI_StopServerRefresh();
03323 uiInfo.serverStatus.nextDisplayRefresh = 0;
03324 uiInfo.nextServerStatusRefresh = 0;
03325 uiInfo.nextFindPlayerRefresh = 0;
03326 } else if (Q_stricmp(name, "UpdateFilter") == 0) {
03327 if (ui_netSource.integer == AS_LOCAL) {
03328 UI_StartServerRefresh(qtrue);
03329 }
03330 UI_BuildServerDisplayList(qtrue);
03331 UI_FeederSelection(FEEDER_SERVERS, 0);
03332 } else if (Q_stricmp(name, "ServerStatus") == 0) {
03333 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], uiInfo.serverStatusAddress, sizeof(uiInfo.serverStatusAddress));
03334 UI_BuildServerStatus(qtrue);
03335 } else if (Q_stricmp(name, "FoundPlayerServerStatus") == 0) {
03336 Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress));
03337 UI_BuildServerStatus(qtrue);
03338 Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);
03339 } else if (Q_stricmp(name, "FindPlayer") == 0) {
03340 UI_BuildFindPlayerList(qtrue);
03341
03342 uiInfo.serverStatusInfo.numLines = 0;
03343 Menu_SetFeederSelection(NULL, FEEDER_FINDPLAYER, 0, NULL);
03344 } else if (Q_stricmp(name, "JoinServer") == 0) {
03345 trap_Cvar_Set("cg_thirdPerson", "0");
03346 trap_Cvar_Set("cg_cameraOrbit", "0");
03347 trap_Cvar_Set("ui_singlePlayerActive", "0");
03348 if (uiInfo.serverStatus.currentServer >= 0 && uiInfo.serverStatus.currentServer < uiInfo.serverStatus.numDisplayServers) {
03349 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, 1024);
03350 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", buff ) );
03351 }
03352 } else if (Q_stricmp(name, "FoundPlayerJoinServer") == 0) {
03353 trap_Cvar_Set("ui_singlePlayerActive", "0");
03354 if (uiInfo.currentFoundPlayerServer >= 0 && uiInfo.currentFoundPlayerServer < uiInfo.numFoundPlayerServers) {
03355 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer] ) );
03356 }
03357 } else if (Q_stricmp(name, "Quit") == 0) {
03358 trap_Cvar_Set("ui_singlePlayerActive", "0");
03359 trap_Cmd_ExecuteText( EXEC_NOW, "quit");
03360 } else if (Q_stricmp(name, "Controls") == 0) {
03361 trap_Cvar_Set( "cl_paused", "1" );
03362 trap_Key_SetCatcher( KEYCATCH_UI );
03363 Menus_CloseAll();
03364 Menus_ActivateByName("setup_menu2");
03365 } else if (Q_stricmp(name, "Leave") == 0) {
03366 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect\n" );
03367 trap_Key_SetCatcher( KEYCATCH_UI );
03368 Menus_CloseAll();
03369 Menus_ActivateByName("main");
03370 } else if (Q_stricmp(name, "ServerSort") == 0) {
03371 int sortColumn;
03372 if (Int_Parse(args, &sortColumn)) {
03373
03374 if (sortColumn == uiInfo.serverStatus.sortKey) {
03375 uiInfo.serverStatus.sortDir = !uiInfo.serverStatus.sortDir;
03376 }
03377
03378 UI_ServersSort(sortColumn, qtrue);
03379 }
03380 } else if (Q_stricmp(name, "nextSkirmish") == 0) {
03381 UI_StartSkirmish(qtrue);
03382 } else if (Q_stricmp(name, "SkirmishStart") == 0) {
03383 UI_StartSkirmish(qfalse);
03384 } else if (Q_stricmp(name, "closeingame") == 0) {
03385 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
03386 trap_Key_ClearStates();
03387 trap_Cvar_Set( "cl_paused", "0" );
03388 Menus_CloseAll();
03389 } else if (Q_stricmp(name, "voteMap") == 0) {
03390 if (ui_currentNetMap.integer >=0 && ui_currentNetMap.integer < uiInfo.mapCount) {
03391 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote map %s\n",uiInfo.mapList[ui_currentNetMap.integer].mapLoadName) );
03392 }
03393 } else if (Q_stricmp(name, "voteKick") == 0) {
03394 if (uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount) {
03395 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote kick %s\n",uiInfo.playerNames[uiInfo.playerIndex]) );
03396 }
03397 } else if (Q_stricmp(name, "voteGame") == 0) {
03398 if (ui_netGameType.integer >= 0 && ui_netGameType.integer < uiInfo.numGameTypes) {
03399 trap_Cmd_ExecuteText( EXEC_APPEND, va("callvote g_gametype %i\n",uiInfo.gameTypes[ui_netGameType.integer].gtEnum) );
03400 }
03401 } else if (Q_stricmp(name, "voteLeader") == 0) {
03402 if (uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount) {
03403 trap_Cmd_ExecuteText( EXEC_APPEND, va("callteamvote leader %s\n",uiInfo.teamNames[uiInfo.teamIndex]) );
03404 }
03405 } else if (Q_stricmp(name, "addBot") == 0) {
03406 if (trap_Cvar_VariableValue("g_gametype") >= GT_TEAM) {
03407 trap_Cmd_ExecuteText( EXEC_APPEND, va("addbot %s %i %s\n", uiInfo.characterList[uiInfo.botIndex].name, uiInfo.skillIndex+1, (uiInfo.redBlue == 0) ? "Red" : "Blue") );
03408 } else {
03409 trap_Cmd_ExecuteText( EXEC_APPEND, va("addbot %s %i %s\n", UI_GetBotNameByNumber(uiInfo.botIndex), uiInfo.skillIndex+1, (uiInfo.redBlue == 0) ? "Red" : "Blue") );
03410 }
03411 } else if (Q_stricmp(name, "addFavorite") == 0) {
03412 if (ui_netSource.integer != AS_FAVORITES) {
03413 char name[MAX_NAME_LENGTH];
03414 char addr[MAX_NAME_LENGTH];
03415 int res;
03416
03417 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);
03418 name[0] = addr[0] = '\0';
03419 Q_strncpyz(name, Info_ValueForKey(buff, "hostname"), MAX_NAME_LENGTH);
03420 Q_strncpyz(addr, Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);
03421 if (strlen(name) > 0 && strlen(addr) > 0) {
03422 res = trap_LAN_AddServer(AS_FAVORITES, name, addr);
03423 if (res == 0) {
03424
03425 Com_Printf("Favorite already in list\n");
03426 }
03427 else if (res == -1) {
03428
03429 Com_Printf("Favorite list full\n");
03430 }
03431 else {
03432
03433 Com_Printf("Added favorite server %s\n", addr);
03434 }
03435 }
03436 }
03437 } else if (Q_stricmp(name, "deleteFavorite") == 0) {
03438 if (ui_netSource.integer == AS_FAVORITES) {
03439 char addr[MAX_NAME_LENGTH];
03440 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);
03441 addr[0] = '\0';
03442 Q_strncpyz(addr, Info_ValueForKey(buff, "addr"), MAX_NAME_LENGTH);
03443 if (strlen(addr) > 0) {
03444 trap_LAN_RemoveServer(AS_FAVORITES, addr);
03445 }
03446 }
03447 } else if (Q_stricmp(name, "createFavorite") == 0) {
03448 if (ui_netSource.integer == AS_FAVORITES) {
03449 char name[MAX_NAME_LENGTH];
03450 char addr[MAX_NAME_LENGTH];
03451 int res;
03452
03453 name[0] = addr[0] = '\0';
03454 Q_strncpyz(name, UI_Cvar_VariableString("ui_favoriteName"), MAX_NAME_LENGTH);
03455 Q_strncpyz(addr, UI_Cvar_VariableString("ui_favoriteAddress"), MAX_NAME_LENGTH);
03456 if (strlen(name) > 0 && strlen(addr) > 0) {
03457 res = trap_LAN_AddServer(AS_FAVORITES, name, addr);
03458 if (res == 0) {
03459
03460 Com_Printf("Favorite already in list\n");
03461 }
03462 else if (res == -1) {
03463
03464 Com_Printf("Favorite list full\n");
03465 }
03466 else {
03467
03468 Com_Printf("Added favorite server %s\n", addr);
03469 }
03470 }
03471 }
03472 } else if (Q_stricmp(name, "orders") == 0) {
03473 const char *orders;
03474 if (String_Parse(args, &orders)) {
03475 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
03476 if (selectedPlayer < uiInfo.myTeamCount) {
03477 strcpy(buff, orders);
03478 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );
03479 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
03480 } else {
03481 int i;
03482 for (i = 0; i < uiInfo.myTeamCount; i++) {
03483 if (Q_stricmp(UI_Cvar_VariableString("name"), uiInfo.teamNames[i]) == 0) {
03484 continue;
03485 }
03486 strcpy(buff, orders);
03487 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamNames[i]) );
03488 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
03489 }
03490 }
03491 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
03492 trap_Key_ClearStates();
03493 trap_Cvar_Set( "cl_paused", "0" );
03494 Menus_CloseAll();
03495 }
03496 } else if (Q_stricmp(name, "voiceOrdersTeam") == 0) {
03497 const char *orders;
03498 if (String_Parse(args, &orders)) {
03499 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
03500 if (selectedPlayer == uiInfo.myTeamCount) {
03501 trap_Cmd_ExecuteText( EXEC_APPEND, orders );
03502 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
03503 }
03504 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
03505 trap_Key_ClearStates();
03506 trap_Cvar_Set( "cl_paused", "0" );
03507 Menus_CloseAll();
03508 }
03509 } else if (Q_stricmp(name, "voiceOrders") == 0) {
03510 const char *orders;
03511 if (String_Parse(args, &orders)) {
03512 int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer");
03513 if (selectedPlayer < uiInfo.myTeamCount) {
03514 strcpy(buff, orders);
03515 trap_Cmd_ExecuteText( EXEC_APPEND, va(buff, uiInfo.teamClientNums[selectedPlayer]) );
03516 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
03517 }
03518 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
03519 trap_Key_ClearStates();
03520 trap_Cvar_Set( "cl_paused", "0" );
03521 Menus_CloseAll();
03522 }
03523 } else if (Q_stricmp(name, "glCustom") == 0) {
03524 trap_Cvar_Set("ui_glCustom", "4");
03525 } else if (Q_stricmp(name, "update") == 0) {
03526 if (String_Parse(args, &name2)) {
03527 UI_Update(name2);
03528 }
03529 } else if (Q_stricmp(name, "setPbClStatus") == 0) {
03530 int stat;
03531 if ( Int_Parse( args, &stat ) )
03532 trap_SetPbClStatus( stat );
03533 }
03534 else {
03535 Com_Printf("unknown UI script %s\n", name);
03536 }
03537 }
03538 }
03539
03540 static void UI_GetTeamColor(vec4_t *color) {
03541 }
03542
03543
03544
03545
03546
03547
03548 static int UI_MapCountByGameType(qboolean singlePlayer) {
03549 int i, c, game;
03550 c = 0;
03551 game = singlePlayer ? uiInfo.gameTypes[ui_gameType.integer].gtEnum : uiInfo.gameTypes[ui_netGameType.integer].gtEnum;
03552 if (game == GT_SINGLE_PLAYER) {
03553 game++;
03554 }
03555 if (game == GT_TEAM) {
03556 game = GT_FFA;
03557 }
03558
03559 for (i = 0; i < uiInfo.mapCount; i++) {
03560 uiInfo.mapList[i].active = qfalse;
03561 if ( uiInfo.mapList[i].typeBits & (1 << game)) {
03562 if (singlePlayer) {
03563 if (!(uiInfo.mapList[i].typeBits & (1 << GT_SINGLE_PLAYER))) {
03564 continue;
03565 }
03566 }
03567 c++;
03568 uiInfo.mapList[i].active = qtrue;
03569 }
03570 }
03571 return c;
03572 }
03573
03574 qboolean UI_hasSkinForBase(const char *base, const char *team) {
03575 char test[1024];
03576
03577 Com_sprintf( test, sizeof( test ), "models/players/%s/%s/lower_default.skin", base, team );
03578
03579 if (trap_FS_FOpenFile(test, 0, FS_READ)) {
03580 return qtrue;
03581 }
03582 Com_sprintf( test, sizeof( test ), "models/players/characters/%s/%s/lower_default.skin", base, team );
03583
03584 if (trap_FS_FOpenFile(test, 0, FS_READ)) {
03585 return qtrue;
03586 }
03587 return qfalse;
03588 }
03589
03590
03591
03592
03593
03594
03595 static int UI_HeadCountByTeam() {
03596 static int init = 0;
03597 int i, j, k, c, tIndex;
03598
03599 c = 0;
03600 if (!init) {
03601 for (i = 0; i < uiInfo.characterCount; i++) {
03602 uiInfo.characterList[i].reference = 0;
03603 for (j = 0; j < uiInfo.teamCount; j++) {
03604 if (UI_hasSkinForBase(uiInfo.characterList[i].base, uiInfo.teamList[j].teamName)) {
03605 uiInfo.characterList[i].reference |= (1<<j);
03606 }
03607 }
03608 }
03609 init = 1;
03610 }
03611
03612 tIndex = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
03613
03614
03615 for (i = 0; i < uiInfo.characterCount; i++) {
03616 uiInfo.characterList[i].active = qfalse;
03617 for(j = 0; j < TEAM_MEMBERS; j++) {
03618 if (uiInfo.teamList[tIndex].teamMembers[j] != NULL) {
03619 if (uiInfo.characterList[i].reference&(1<<tIndex)) {
03620 uiInfo.characterList[i].active = qtrue;
03621 c++;
03622 break;
03623 }
03624 }
03625 }
03626 }
03627
03628
03629 for(j = 0; j < TEAM_MEMBERS; j++) {
03630 for(k = 0; k < uiInfo.aliasCount; k++) {
03631 if (uiInfo.aliasList[k].name != NULL) {
03632 if (Q_stricmp(uiInfo.teamList[tIndex].teamMembers[j], uiInfo.aliasList[k].name)==0) {
03633 for (i = 0; i < uiInfo.characterCount; i++) {
03634 if (uiInfo.characterList[i].headImage != -1 && uiInfo.characterList[i].reference&(1<<tIndex) && Q_stricmp(uiInfo.aliasList[k].ai, uiInfo.characterList[i].name)==0) {
03635 if (uiInfo.characterList[i].active == qfalse) {
03636 uiInfo.characterList[i].active = qtrue;
03637 c++;
03638 }
03639 break;
03640 }
03641 }
03642 }
03643 }
03644 }
03645 }
03646 return c;
03647 }
03648
03649
03650
03651
03652
03653
03654 static void UI_InsertServerIntoDisplayList(int num, int position) {
03655 int i;
03656
03657 if (position < 0 || position > uiInfo.serverStatus.numDisplayServers ) {
03658 return;
03659 }
03660
03661 uiInfo.serverStatus.numDisplayServers++;
03662 for (i = uiInfo.serverStatus.numDisplayServers; i > position; i--) {
03663 uiInfo.serverStatus.displayServers[i] = uiInfo.serverStatus.displayServers[i-1];
03664 }
03665 uiInfo.serverStatus.displayServers[position] = num;
03666 }
03667
03668
03669
03670
03671
03672
03673 static void UI_RemoveServerFromDisplayList(int num) {
03674 int i, j;
03675
03676 for (i = 0; i < uiInfo.serverStatus.numDisplayServers; i++) {
03677 if (uiInfo.serverStatus.displayServers[i] == num) {
03678 uiInfo.serverStatus.numDisplayServers--;
03679 for (j = i; j < uiInfo.serverStatus.numDisplayServers; j++) {
03680 uiInfo.serverStatus.displayServers[j] = uiInfo.serverStatus.displayServers[j+1];
03681 }
03682 return;
03683 }
03684 }
03685 }
03686
03687
03688
03689
03690
03691
03692 static void UI_BinaryServerInsertion(int num) {
03693 int mid, offset, res, len;
03694
03695
03696 len = uiInfo.serverStatus.numDisplayServers;
03697 mid = len;
03698 offset = 0;
03699 res = 0;
03700 while(mid > 0) {
03701 mid = len >> 1;
03702
03703 res = trap_LAN_CompareServers( ui_netSource.integer, uiInfo.serverStatus.sortKey,
03704 uiInfo.serverStatus.sortDir, num, uiInfo.serverStatus.displayServers[offset+mid]);
03705
03706 if (res == 0) {
03707 UI_InsertServerIntoDisplayList(num, offset+mid);
03708 return;
03709 }
03710
03711 else if (res == 1) {
03712 offset += mid;
03713 len -= mid;
03714 }
03715
03716 else {
03717 len -= mid;
03718 }
03719 }
03720 if (res == 1) {
03721 offset++;
03722 }
03723 UI_InsertServerIntoDisplayList(num, offset);
03724 }
03725
03726
03727
03728
03729
03730
03731 static void UI_BuildServerDisplayList(qboolean force) {
03732 int i, count, clients, maxClients, ping, game, len, visible;
03733 char info[MAX_STRING_CHARS];
03734
03735 static int numinvisible;
03736
03737 if (!(force || uiInfo.uiDC.realTime > uiInfo.serverStatus.nextDisplayRefresh)) {
03738 return;
03739 }
03740
03741 if ( force == 2 ) {
03742 force = 0;
03743 }
03744
03745
03746 trap_Cvar_VariableStringBuffer( "cl_motdString", uiInfo.serverStatus.motd, sizeof(uiInfo.serverStatus.motd) );
03747 len = strlen(uiInfo.serverStatus.motd);
03748 if (len == 0) {
03749 strcpy(uiInfo.serverStatus.motd, "Welcome to Team Arena!");
03750 len = strlen(uiInfo.serverStatus.motd);
03751 }
03752 if (len != uiInfo.serverStatus.motdLen) {
03753 uiInfo.serverStatus.motdLen = len;
03754 uiInfo.serverStatus.motdWidth = -1;
03755 }
03756
03757 if (force) {
03758 numinvisible = 0;
03759
03760 uiInfo.serverStatus.numDisplayServers = 0;
03761 uiInfo.serverStatus.numPlayersOnServers = 0;
03762
03763 Menu_SetFeederSelection(NULL, FEEDER_SERVERS, 0, NULL);
03764
03765 trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue);
03766 }
03767
03768
03769 count = trap_LAN_GetServerCount(ui_netSource.integer);
03770 if (count == -1 || (ui_netSource.integer == AS_LOCAL && count == 0) ) {
03771
03772 uiInfo.serverStatus.numDisplayServers = 0;
03773 uiInfo.serverStatus.numPlayersOnServers = 0;
03774 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 500;
03775 return;
03776 }
03777
03778 visible = qfalse;
03779 for (i = 0; i < count; i++) {
03780
03781 if (!trap_LAN_ServerIsVisible(ui_netSource.integer, i)) {
03782 continue;
03783 }
03784 visible = qtrue;
03785
03786 ping = trap_LAN_GetServerPing(ui_netSource.integer, i);
03787 if (ping > 0 || ui_netSource.integer == AS_FAVORITES) {
03788
03789 trap_LAN_GetServerInfo(ui_netSource.integer, i, info, MAX_STRING_CHARS);
03790
03791 clients = atoi(Info_ValueForKey(info, "clients"));
03792 uiInfo.serverStatus.numPlayersOnServers += clients;
03793
03794 if (ui_browserShowEmpty.integer == 0) {
03795 if (clients == 0) {
03796 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
03797 continue;
03798 }
03799 }
03800
03801 if (ui_browserShowFull.integer == 0) {
03802 maxClients = atoi(Info_ValueForKey(info, "sv_maxclients"));
03803 if (clients == maxClients) {
03804 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
03805 continue;
03806 }
03807 }
03808
03809 if (uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum != -1) {
03810 game = atoi(Info_ValueForKey(info, "gametype"));
03811 if (game != uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum) {
03812 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
03813 continue;
03814 }
03815 }
03816
03817 if (ui_serverFilterType.integer > 0) {
03818 if (Q_stricmp(Info_ValueForKey(info, "game"), serverFilters[ui_serverFilterType.integer].basedir) != 0) {
03819 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
03820 continue;
03821 }
03822 }
03823
03824 if (ui_netSource.integer == AS_FAVORITES) {
03825 UI_RemoveServerFromDisplayList(i);
03826 }
03827
03828 UI_BinaryServerInsertion(i);
03829
03830 if (ping > 0) {
03831 trap_LAN_MarkServerVisible(ui_netSource.integer, i, qfalse);
03832 numinvisible++;
03833 }
03834 }
03835 }
03836
03837 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime;
03838
03839
03840 if (!visible) {
03841
03842
03843 }
03844 }
03845
03846 typedef struct
03847 {
03848 char *name, *altName;
03849 } serverStatusCvar_t;
03850
03851 serverStatusCvar_t serverStatusCvars[] = {
03852 {"sv_hostname", "Name"},
03853 {"Address", ""},
03854 {"gamename", "Game name"},
03855 {"g_gametype", "Game type"},
03856 {"mapname", "Map"},
03857 {"version", ""},
03858 {"protocol", ""},
03859 {"timelimit", ""},
03860 {"fraglimit", ""},
03861 {NULL, NULL}
03862 };
03863
03864
03865
03866
03867
03868
03869 static void UI_SortServerStatusInfo( serverStatusInfo_t *info ) {
03870 int i, j, index;
03871 char *tmp1, *tmp2;
03872
03873
03874
03875
03876 index = 0;
03877 for (i = 0; serverStatusCvars[i].name; i++) {
03878 for (j = 0; j < info->numLines; j++) {
03879 if ( !info->lines[j][1] || info->lines[j][1][0] ) {
03880 continue;
03881 }
03882 if ( !Q_stricmp(serverStatusCvars[i].name, info->lines[j][0]) ) {
03883
03884 tmp1 = info->lines[index][0];
03885 tmp2 = info->lines[index][3];
03886 info->lines[index][0] = info->lines[j][0];
03887 info->lines[index][3] = info->lines[j][3];
03888 info->lines[j][0] = tmp1;
03889 info->lines[j][3] = tmp2;
03890
03891 if ( strlen(serverStatusCvars[i].altName) ) {
03892 info->lines[index][0] = serverStatusCvars[i].altName;
03893 }
03894 index++;
03895 }
03896 }
03897 }
03898 }
03899
03900
03901
03902
03903
03904
03905 static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) {
03906 char *p, *score, *ping, *name;
03907 int i, len;
03908
03909 if (!info) {
03910 trap_LAN_ServerStatus( serverAddress, NULL, 0);
03911 return qfalse;
03912 }
03913 memset(info, 0, sizeof(*info));
03914 if ( trap_LAN_ServerStatus( serverAddress, info->text, sizeof(info->text)) ) {
03915 Q_strncpyz(info->address, serverAddress, sizeof(info->address));
03916 p = info->text;
03917 info->numLines = 0;
03918 info->lines[info->numLines][0] = "Address";
03919 info->lines[info->numLines][1] = "";
03920 info->lines[info->numLines][2] = "";
03921 info->lines[info->numLines][3] = info->address;
03922 info->numLines++;
03923
03924 while (p && *p) {
03925 p = strchr(p, '\\');
03926 if (!p) break;
03927 *p++ = '\0';
03928 if (*p == '\\')
03929 break;
03930 info->lines[info->numLines][0] = p;
03931 info->lines[info->numLines][1] = "";
03932 info->lines[info->numLines][2] = "";
03933 p = strchr(p, '\\');
03934 if (!p) break;
03935 *p++ = '\0';
03936 info->lines[info->numLines][3] = p;
03937
03938 info->numLines++;
03939 if (info->numLines >= MAX_SERVERSTATUS_LINES)
03940 break;
03941 }
03942
03943 if (info->numLines < MAX_SERVERSTATUS_LINES-3) {
03944
03945 info->lines[info->numLines][0] = "";
03946 info->lines[info->numLines][1] = "";
03947 info->lines[info->numLines][2] = "";
03948 info->lines[info->numLines][3] = "";
03949 info->numLines++;
03950
03951 info->lines[info->numLines][0] = "num";
03952 info->lines[info->numLines][1] = "score";
03953 info->lines[info->numLines][2] = "ping";
03954 info->lines[info->numLines][3] = "name";
03955 info->numLines++;
03956
03957 i = 0;
03958 len = 0;
03959 while (p && *p) {
03960 if (*p == '\\')
03961 *p++ = '\0';
03962 if (!p)
03963 break;
03964 score = p;
03965 p = strchr(p, ' ');
03966 if (!p)
03967 break;
03968 *p++ = '\0';
03969 ping = p;
03970 p = strchr(p, ' ');
03971 if (!p)
03972 break;
03973 *p++ = '\0';
03974 name = p;
03975 Com_sprintf(&info->pings[len], sizeof(info->pings)-len, "%d", i);
03976 info->lines[info->numLines][0] = &info->pings[len];
03977 len += strlen(&info->pings[len]) + 1;
03978 info->lines[info->numLines][1] = score;
03979 info->lines[info->numLines][2] = ping;
03980 info->lines[info->numLines][3] = name;
03981 info->numLines++;
03982 if (info->numLines >= MAX_SERVERSTATUS_LINES)
03983 break;
03984 p = strchr(p, '\\');
03985 if (!p)
03986 break;
03987 *p++ = '\0';
03988
03989 i++;
03990 }
03991 }
03992 UI_SortServerStatusInfo( info );
03993 return qtrue;
03994 }
03995 return qfalse;
03996 }
03997
03998
03999
04000
04001
04002
04003 static char *stristr(char *str, char *charset) {
04004 int i;
04005
04006 while(*str) {
04007 for (i = 0; charset[i] && str[i]; i++) {
04008 if (toupper(charset[i]) != toupper(str[i])) break;
04009 }
04010 if (!charset[i]) return str;
04011 str++;
04012 }
04013 return NULL;
04014 }
04015
04016
04017
04018
04019
04020
04021 static void UI_BuildFindPlayerList(qboolean force) {
04022 static int numFound, numTimeOuts;
04023 int i, j, resend;
04024 serverStatusInfo_t info;
04025 char name[MAX_NAME_LENGTH+2];
04026 char infoString[MAX_STRING_CHARS];
04027
04028 if (!force) {
04029 if (!uiInfo.nextFindPlayerRefresh || uiInfo.nextFindPlayerRefresh > uiInfo.uiDC.realTime) {
04030 return;
04031 }
04032 }
04033 else {
04034 memset(&uiInfo.pendingServerStatus, 0, sizeof(uiInfo.pendingServerStatus));
04035 uiInfo.numFoundPlayerServers = 0;
04036 uiInfo.currentFoundPlayerServer = 0;
04037 trap_Cvar_VariableStringBuffer( "ui_findPlayer", uiInfo.findPlayerName, sizeof(uiInfo.findPlayerName));
04038 Q_CleanStr(uiInfo.findPlayerName);
04039
04040 if (!strlen(uiInfo.findPlayerName)) {
04041 uiInfo.nextFindPlayerRefresh = 0;
04042 return;
04043 }
04044
04045 resend = ui_serverStatusTimeOut.integer / 2 - 10;
04046 if (resend < 50) {
04047 resend = 50;
04048 }
04049 trap_Cvar_Set("cl_serverStatusResendTime", va("%d", resend));
04050
04051 trap_LAN_ServerStatus( NULL, NULL, 0);
04052
04053 uiInfo.numFoundPlayerServers = 1;
04054 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
04055 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
04056 "searching %d...", uiInfo.pendingServerStatus.num);
04057 numFound = 0;
04058 numTimeOuts++;
04059 }
04060 for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) {
04061
04062 if (uiInfo.pendingServerStatus.server[i].valid) {
04063
04064 if (UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, &info ) ) {
04065
04066 numFound++;
04067
04068 for (j = 0; j < info.numLines; j++) {
04069
04070 if ( !info.lines[j][2] || !info.lines[j][2][0] ) {
04071 continue;
04072 }
04073
04074 Q_strncpyz(name, info.lines[j][3], sizeof(name));
04075 Q_CleanStr(name);
04076
04077 if (stristr(name, uiInfo.findPlayerName)) {
04078
04079 if (uiInfo.numFoundPlayerServers < MAX_FOUNDPLAYER_SERVERS-1) {
04080
04081 Q_strncpyz(uiInfo.foundPlayerServerAddresses[uiInfo.numFoundPlayerServers-1],
04082 uiInfo.pendingServerStatus.server[i].adrstr,
04083 sizeof(uiInfo.foundPlayerServerAddresses[0]));
04084 Q_strncpyz(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
04085 uiInfo.pendingServerStatus.server[i].name,
04086 sizeof(uiInfo.foundPlayerServerNames[0]));
04087 uiInfo.numFoundPlayerServers++;
04088 }
04089 else {
04090
04091 uiInfo.pendingServerStatus.num = uiInfo.serverStatus.numDisplayServers;
04092 }
04093 }
04094 }
04095 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
04096 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
04097 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound);
04098
04099 uiInfo.pendingServerStatus.server[i].valid = qfalse;
04100 }
04101 }
04102
04103 if (!uiInfo.pendingServerStatus.server[i].valid ||
04104 uiInfo.pendingServerStatus.server[i].startTime < uiInfo.uiDC.realTime - ui_serverStatusTimeOut.integer) {
04105 if (uiInfo.pendingServerStatus.server[i].valid) {
04106 numTimeOuts++;
04107 }
04108
04109 UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, NULL );
04110
04111 uiInfo.pendingServerStatus.server[i].valid = qfalse;
04112
04113 if (uiInfo.pendingServerStatus.num < uiInfo.serverStatus.numDisplayServers) {
04114 uiInfo.pendingServerStatus.server[i].startTime = uiInfo.uiDC.realTime;
04115 trap_LAN_GetServerAddressString(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num],
04116 uiInfo.pendingServerStatus.server[i].adrstr, sizeof(uiInfo.pendingServerStatus.server[i].adrstr));
04117 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], infoString, sizeof(infoString));
04118 Q_strncpyz(uiInfo.pendingServerStatus.server[i].name, Info_ValueForKey(infoString, "hostname"), sizeof(uiInfo.pendingServerStatus.server[0].name));
04119 uiInfo.pendingServerStatus.server[i].valid = qtrue;
04120 uiInfo.pendingServerStatus.num++;
04121 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1],
04122 sizeof(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1]),
04123 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound);
04124 }
04125 }
04126 }
04127 for (i = 0; i < MAX_SERVERSTATUSREQUESTS; i++) {
04128 if (uiInfo.pendingServerStatus.server[i].valid) {
04129 break;
04130 }
04131 }
04132
04133 if (i < MAX_SERVERSTATUSREQUESTS) {
04134 uiInfo.nextFindPlayerRefresh = uiInfo.uiDC.realTime + 25;
04135 }
04136 else {
04137
04138 if (!uiInfo.numFoundPlayerServers) {
04139 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]), "no servers found");
04140 }
04141 else {
04142 Com_sprintf(uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof(uiInfo.foundPlayerServerAddresses[0]),
04143 "%d server%s found with player %s", uiInfo.numFoundPlayerServers-1,
04144 uiInfo.numFoundPlayerServers == 2 ? "":"s", uiInfo.findPlayerName);
04145 }
04146 uiInfo.nextFindPlayerRefresh = 0;
04147
04148 UI_FeederSelection(FEEDER_FINDPLAYER, uiInfo.currentFoundPlayerServer);
04149 }
04150 }
04151
04152
04153
04154
04155
04156
04157 static void UI_BuildServerStatus(qboolean force) {
04158
04159 if (uiInfo.nextFindPlayerRefresh) {
04160 return;
04161 }
04162 if (!force) {
04163 if (!uiInfo.nextServerStatusRefresh || uiInfo.nextServerStatusRefresh > uiInfo.uiDC.realTime) {
04164 return;
04165 }
04166 }
04167 else {
04168 Menu_SetFeederSelection(NULL, FEEDER_SERVERSTATUS, 0, NULL);
04169 uiInfo.serverStatusInfo.numLines = 0;
04170
04171 trap_LAN_ServerStatus( NULL, NULL, 0);
04172 }
04173 if (uiInfo.serverStatus.currentServer < 0 || uiInfo.serverStatus.currentServer > uiInfo.serverStatus.numDisplayServers || uiInfo.serverStatus.numDisplayServers == 0) {
04174 return;
04175 }
04176 if (UI_GetServerStatusInfo( uiInfo.serverStatusAddress, &uiInfo.serverStatusInfo ) ) {
04177 uiInfo.nextServerStatusRefresh = 0;
04178 UI_GetServerStatusInfo( uiInfo.serverStatusAddress, NULL );
04179 }
04180 else {
04181 uiInfo.nextServerStatusRefresh = uiInfo.uiDC.realTime + 500;
04182 }
04183 }
04184
04185
04186
04187
04188
04189
04190 static int UI_FeederCount(float feederID) {
04191 if (feederID == FEEDER_HEADS) {
04192 return UI_HeadCountByTeam();
04193 } else if (feederID == FEEDER_Q3HEADS) {
04194 return uiInfo.q3HeadCount;
04195 } else if (feederID == FEEDER_CINEMATICS) {
04196 return uiInfo.movieCount;
04197 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) {
04198 return UI_MapCountByGameType(feederID == FEEDER_MAPS ? qtrue : qfalse);
04199 } else if (feederID == FEEDER_SERVERS) {
04200 return uiInfo.serverStatus.numDisplayServers;
04201 } else if (feederID == FEEDER_SERVERSTATUS) {
04202 return uiInfo.serverStatusInfo.numLines;
04203 } else if (feederID == FEEDER_FINDPLAYER) {
04204 return uiInfo.numFoundPlayerServers;
04205 } else if (feederID == FEEDER_PLAYER_LIST) {
04206 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) {
04207 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
04208 UI_BuildPlayerList();
04209 }
04210 return uiInfo.playerCount;
04211 } else if (feederID == FEEDER_TEAM_LIST) {
04212 if (uiInfo.uiDC.realTime > uiInfo.playerRefresh) {
04213 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
04214 UI_BuildPlayerList();
04215 }
04216 return uiInfo.myTeamCount;
04217 } else if (feederID == FEEDER_MODS) {
04218 return uiInfo.modCount;
04219 } else if (feederID == FEEDER_DEMOS) {
04220 return uiInfo.demoCount;
04221 }
04222 return 0;
04223 }
04224
04225 static const char *UI_SelectedMap(int index, int *actual) {
04226 int i, c;
04227 c = 0;
04228 *actual = 0;
04229 for (i = 0; i < uiInfo.mapCount; i++) {
04230 if (uiInfo.mapList[i].active) {
04231 if (c == index) {
04232 *actual = i;
04233 return uiInfo.mapList[i].mapName;
04234 } else {
04235 c++;
04236 }
04237 }
04238 }
04239 return "";
04240 }
04241
04242 static const char *UI_SelectedHead(int index, int *actual) {
04243 int i, c;
04244 c = 0;
04245 *actual = 0;
04246 for (i = 0; i < uiInfo.characterCount; i++) {
04247 if (uiInfo.characterList[i].active) {
04248 if (c == index) {
04249 *actual = i;
04250 return uiInfo.characterList[i].name;
04251 } else {
04252 c++;
04253 }
04254 }
04255 }
04256 return "";
04257 }
04258
04259 static int UI_GetIndexFromSelection(int actual) {
04260 int i, c;
04261 c = 0;
04262 for (i = 0; i < uiInfo.mapCount; i++) {
04263 if (uiInfo.mapList[i].active) {
04264 if (i == actual) {
04265 return c;
04266 }
04267 c++;
04268 }
04269 }
04270 return 0;
04271 }
04272
04273 static void UI_UpdatePendingPings() {
04274 trap_LAN_ResetPings(ui_netSource.integer);
04275 uiInfo.serverStatus.refreshActive = qtrue;
04276 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
04277
04278 }
04279
04280 static const char *UI_FeederItemText(float feederID, int index, int column, qhandle_t *handle) {
04281 static char info[MAX_STRING_CHARS];
04282 static char hostname[1024];
04283 static char clientBuff[32];
04284 static int lastColumn = -1;
04285 static int lastTime = 0;
04286 *handle = -1;
04287 if (feederID == FEEDER_HEADS) {
04288 int actual;
04289 return UI_SelectedHead(index, &actual);
04290 } else if (feederID == FEEDER_Q3HEADS) {
04291 if (index >= 0 && index < uiInfo.q3HeadCount) {
04292 return uiInfo.q3HeadNames[index];
04293 }
04294 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) {
04295 int actual;
04296 return UI_SelectedMap(index, &actual);
04297 } else if (feederID == FEEDER_SERVERS) {
04298 if (index >= 0 && index < uiInfo.serverStatus.numDisplayServers) {
04299 int ping, game, punkbuster;
04300 if (lastColumn != column || lastTime > uiInfo.uiDC.realTime + 5000) {
04301 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
04302 lastColumn = column;
04303 lastTime = uiInfo.uiDC.realTime;
04304 }
04305 ping = atoi(Info_ValueForKey(info, "ping"));
04306 if (ping == -1) {
04307
04308
04309 }
04310 switch (column) {
04311 case SORT_HOST :
04312 if (ping <= 0) {
04313 return Info_ValueForKey(info, "addr");
04314 } else {
04315 if ( ui_netSource.integer == AS_LOCAL ) {
04316 Com_sprintf( hostname, sizeof(hostname), "%s [%s]",
04317 Info_ValueForKey(info, "hostname"),
04318 netnames[atoi(Info_ValueForKey(info, "nettype"))] );
04319 return hostname;
04320 }
04321 else {
04322 Com_sprintf( hostname, sizeof(hostname), "%s", Info_ValueForKey(info, "hostname"));
04323 return hostname;
04324 }
04325 }
04326 case SORT_MAP : return Info_ValueForKey(info, "mapname");
04327 case SORT_CLIENTS :
04328 Com_sprintf( clientBuff, sizeof(clientBuff), "%s (%s)", Info_ValueForKey(info, "clients"), Info_ValueForKey(info, "sv_maxclients"));
04329 return clientBuff;
04330 case SORT_GAME :
04331 game = atoi(Info_ValueForKey(info, "gametype"));
04332 if (game >= 0 && game < numTeamArenaGameTypes) {
04333 return teamArenaGameTypes[game];
04334 } else {
04335 return "Unknown";
04336 }
04337 case SORT_PING :
04338 if (ping <= 0) {
04339 return "...";
04340 } else {
04341 return Info_ValueForKey(info, "ping");
04342 }
04343 case SORT_PUNKBUSTER:
04344 punkbuster = atoi(Info_ValueForKey(info, "punkbuster"));
04345 if ( punkbuster ) {
04346 return "Yes";
04347 } else {
04348 return "No";
04349 }
04350 }
04351 }
04352 } else if (feederID == FEEDER_SERVERSTATUS) {
04353 if ( index >= 0 && index < uiInfo.serverStatusInfo.numLines ) {
04354 if ( column >= 0 && column < 4 ) {
04355 return uiInfo.serverStatusInfo.lines[index][column];
04356 }
04357 }
04358 } else if (feederID == FEEDER_FINDPLAYER) {
04359 if ( index >= 0 && index < uiInfo.numFoundPlayerServers ) {
04360
04361 return uiInfo.foundPlayerServerNames[index];
04362 }
04363 } else if (feederID == FEEDER_PLAYER_LIST) {
04364 if (index >= 0 && index < uiInfo.playerCount) {
04365 return uiInfo.playerNames[index];
04366 }
04367 } else if (feederID == FEEDER_TEAM_LIST) {
04368 if (index >= 0 && index < uiInfo.myTeamCount) {
04369 return uiInfo.teamNames[index];
04370 }
04371 } else if (feederID == FEEDER_MODS) {
04372 if (index >= 0 && index < uiInfo.modCount) {
04373 if (uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr) {
04374 return uiInfo.modList[index].modDescr;
04375 } else {
04376 return uiInfo.modList[index].modName;
04377 }
04378 }
04379 } else if (feederID == FEEDER_CINEMATICS) {
04380 if (index >= 0 && index < uiInfo.movieCount) {
04381 return uiInfo.movieList[index];
04382 }
04383 } else if (feederID == FEEDER_DEMOS) {
04384 if (index >= 0 && index < uiInfo.demoCount) {
04385 return uiInfo.demoList[index];
04386 }
04387 }
04388 return "";
04389 }
04390
04391
04392 static qhandle_t UI_FeederItemImage(float feederID, int index) {
04393 if (feederID == FEEDER_HEADS) {
04394 int actual;
04395 UI_SelectedHead(index, &actual);
04396 index = actual;
04397 if (index >= 0 && index < uiInfo.characterCount) {
04398 if (uiInfo.characterList[index].headImage == -1) {
04399 uiInfo.characterList[index].headImage = trap_R_RegisterShaderNoMip(uiInfo.characterList[index].imageName);
04400 }
04401 return uiInfo.characterList[index].headImage;
04402 }
04403 } else if (feederID == FEEDER_Q3HEADS) {
04404 if (index >= 0 && index < uiInfo.q3HeadCount) {
04405 return uiInfo.q3HeadIcons[index];
04406 }
04407 } else if (feederID == FEEDER_ALLMAPS || feederID == FEEDER_MAPS) {
04408 int actual;
04409 UI_SelectedMap(index, &actual);
04410 index = actual;
04411 if (index >= 0 && index < uiInfo.mapCount) {
04412 if (uiInfo.mapList[index].levelShot == -1) {
04413 uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip(uiInfo.mapList[index].imageName);
04414 }
04415 return uiInfo.mapList[index].levelShot;
04416 }
04417 }
04418 return 0;
04419 }
04420
04421 static void UI_FeederSelection(float feederID, int index) {
04422 static char info[MAX_STRING_CHARS];
04423 if (feederID == FEEDER_HEADS) {
04424 int actual;
04425 UI_SelectedHead(index, &actual);
04426 index = actual;
04427 if (index >= 0 && index < uiInfo.characterCount) {
04428 trap_Cvar_Set( "team_model", va("%s", uiInfo.characterList[index].base));
04429 trap_Cvar_Set( "team_headmodel", va("*%s", uiInfo.characterList[index].name));
04430 updateModel = qtrue;
04431 }
04432 } else if (feederID == FEEDER_Q3HEADS) {
04433 if (index >= 0 && index < uiInfo.q3HeadCount) {
04434 trap_Cvar_Set( "model", uiInfo.q3HeadNames[index]);
04435 trap_Cvar_Set( "headmodel", uiInfo.q3HeadNames[index]);
04436 updateModel = qtrue;
04437 }
04438 } else if (feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS) {
04439 int actual, map;
04440 map = (feederID == FEEDER_ALLMAPS) ? ui_currentNetMap.integer : ui_currentMap.integer;
04441 if (uiInfo.mapList[map].cinematic >= 0) {
04442 trap_CIN_StopCinematic(uiInfo.mapList[map].cinematic);
04443 uiInfo.mapList[map].cinematic = -1;
04444 }
04445 UI_SelectedMap(index, &actual);
04446 trap_Cvar_Set("ui_mapIndex", va("%d", index));
04447 ui_mapIndex.integer = index;
04448
04449 if (feederID == FEEDER_MAPS) {
04450 ui_currentMap.integer = actual;
04451 trap_Cvar_Set("ui_currentMap", va("%d", actual));
04452 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) );
04453 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);
04454 trap_Cvar_Set("ui_opponentModel", uiInfo.mapList[ui_currentMap.integer].opponentName);
04455 updateOpponentModel = qtrue;
04456 } else {
04457 ui_currentNetMap.integer = actual;
04458 trap_Cvar_Set("ui_currentNetMap", va("%d", actual));
04459 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) );
04460 }
04461
04462 } else if (feederID == FEEDER_SERVERS) {
04463 const char *mapName = NULL;
04464 uiInfo.serverStatus.currentServer = index;
04465 trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
04466 uiInfo.serverStatus.currentServerPreview = trap_R_RegisterShaderNoMip(va("levelshots/%s", Info_ValueForKey(info, "mapname")));
04467 if (uiInfo.serverStatus.currentServerCinematic >= 0) {
04468 trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic);
04469 uiInfo.serverStatus.currentServerCinematic = -1;
04470 }
04471 mapName = Info_ValueForKey(info, "mapname");
04472 if (mapName && *mapName) {
04473 uiInfo.serverStatus.currentServerCinematic = trap_CIN_PlayCinematic(va("%s.roq", mapName), 0, 0, 0, 0, (CIN_loop | CIN_silent) );
04474 }
04475 } else if (feederID == FEEDER_SERVERSTATUS) {
04476
04477 } else if (feederID == FEEDER_FINDPLAYER) {
04478 uiInfo.currentFoundPlayerServer = index;
04479
04480 if ( index < uiInfo.numFoundPlayerServers-1) {
04481
04482 Q_strncpyz(uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof(uiInfo.serverStatusAddress));
04483 Menu_SetFeederSelection(NULL, FEEDER_SERVERSTATUS, 0, NULL);
04484 UI_BuildServerStatus(qtrue);
04485 }
04486 } else if (feederID == FEEDER_PLAYER_LIST) {
04487 uiInfo.playerIndex = index;
04488 } else if (feederID == FEEDER_TEAM_LIST) {
04489 uiInfo.teamIndex = index;
04490 } else if (feederID == FEEDER_MODS) {
04491 uiInfo.modIndex = index;
04492 } else if (feederID == FEEDER_CINEMATICS) {
04493 uiInfo.movieIndex = index;
04494 if (uiInfo.previewMovie >= 0) {
04495 trap_CIN_StopCinematic(uiInfo.previewMovie);
04496 }
04497 uiInfo.previewMovie = -1;
04498 } else if (feederID == FEEDER_DEMOS) {
04499 uiInfo.demoIndex = index;
04500 }
04501 }
04502
04503 static qboolean Team_Parse(char **p) {
04504 char *token;
04505 const char *tempStr;
04506 int i;
04507
04508 token = COM_ParseExt(p, qtrue);
04509
04510 if (token[0] != '{') {
04511 return qfalse;
04512 }
04513
04514 while ( 1 ) {
04515
04516 token = COM_ParseExt(p, qtrue);
04517
04518 if (Q_stricmp(token, "}") == 0) {
04519 return qtrue;
04520 }
04521
04522 if ( !token || token[0] == 0 ) {
04523 return qfalse;
04524 }
04525
04526 if (token[0] == '{') {
04527
04528 if (!String_Parse(p, &uiInfo.teamList[uiInfo.teamCount].teamName) || !String_Parse(p, &tempStr)) {
04529 return qfalse;
04530 }
04531
04532
04533 uiInfo.teamList[uiInfo.teamCount].imageName = tempStr;
04534 uiInfo.teamList[uiInfo.teamCount].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[uiInfo.teamCount].imageName);
04535 uiInfo.teamList[uiInfo.teamCount].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[uiInfo.teamCount].imageName));
04536 uiInfo.teamList[uiInfo.teamCount].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[uiInfo.teamCount].imageName));
04537
04538 uiInfo.teamList[uiInfo.teamCount].cinematic = -1;
04539
04540 for (i = 0; i < TEAM_MEMBERS; i++) {
04541 uiInfo.teamList[uiInfo.teamCount].teamMembers[i] = NULL;
04542 if (!String_Parse(p, &uiInfo.teamList[uiInfo.teamCount].teamMembers[i])) {
04543 return qfalse;
04544 }
04545 }
04546
04547 Com_Printf("Loaded team %s with team icon %s.\n", uiInfo.teamList[uiInfo.teamCount].teamName, tempStr);
04548 if (uiInfo.teamCount < MAX_TEAMS) {
04549 uiInfo.teamCount++;
04550 } else {
04551 Com_Printf("Too many teams, last team replaced!\n");
04552 }
04553 token = COM_ParseExt(p, qtrue);
04554 if (token[0] != '}') {
04555 return qfalse;
04556 }
04557 }
04558 }
04559
04560 return qfalse;
04561 }
04562
04563 static qboolean Character_Parse(char **p) {
04564 char *token;
04565 const char *tempStr;
04566
04567 token = COM_ParseExt(p, qtrue);
04568
04569 if (token[0] != '{') {
04570 return qfalse;
04571 }
04572
04573
04574 while ( 1 ) {
04575 token = COM_ParseExt(p, qtrue);
04576
04577 if (Q_stricmp(token, "}") == 0) {
04578 return qtrue;
04579 }
04580
04581 if ( !token || token[0] == 0 ) {
04582 return qfalse;
04583 }
04584
04585 if (token[0] == '{') {
04586
04587 if (!String_Parse(p, &uiInfo.characterList[uiInfo.characterCount].name) || !String_Parse(p, &tempStr)) {
04588 return qfalse;
04589 }
04590
04591 uiInfo.characterList[uiInfo.characterCount].headImage = -1;
04592 uiInfo.characterList[uiInfo.characterCount].imageName = String_Alloc(va("models/players/heads/%s/icon_default.tga", uiInfo.characterList[uiInfo.characterCount].name));
04593
04594 if (tempStr && (!Q_stricmp(tempStr, "female"))) {
04595 uiInfo.characterList[uiInfo.characterCount].base = String_Alloc(va("Janet"));
04596 } else if (tempStr && (!Q_stricmp(tempStr, "male"))) {
04597 uiInfo.characterList[uiInfo.characterCount].base = String_Alloc(va("James"));
04598 } else {
04599 uiInfo.characterList[uiInfo.characterCount].base = String_Alloc(va("%s",tempStr));
04600 }
04601
04602 Com_Printf("Loaded %s character %s.\n", uiInfo.characterList[uiInfo.characterCount].base, uiInfo.characterList[uiInfo.characterCount].name);
04603 if (uiInfo.characterCount < MAX_HEADS) {
04604 uiInfo.characterCount++;
04605 } else {
04606 Com_Printf("Too many characters, last character replaced!\n");
04607 }
04608
04609 token = COM_ParseExt(p, qtrue);
04610 if (token[0] != '}') {
04611 return qfalse;
04612 }
04613 }
04614 }
04615
04616 return qfalse;
04617 }
04618
04619
04620 static qboolean Alias_Parse(char **p) {
04621 char *token;
04622
04623 token = COM_ParseExt(p, qtrue);
04624
04625 if (token[0] != '{') {
04626 return qfalse;
04627 }
04628
04629 while ( 1 ) {
04630 token = COM_ParseExt(p, qtrue);
04631
04632 if (Q_stricmp(token, "}") == 0) {
04633 return qtrue;
04634 }
04635
04636 if ( !token || token[0] == 0 ) {
04637 return qfalse;
04638 }
04639
04640 if (token[0] == '{') {
04641
04642 if (!String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].name) || !String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].ai) || !String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].action)) {
04643 return qfalse;
04644 }
04645
04646 Com_Printf("Loaded character alias %s using character ai %s.\n", uiInfo.aliasList[uiInfo.aliasCount].name, uiInfo.aliasList[uiInfo.aliasCount].ai);
04647 if (uiInfo.aliasCount < MAX_ALIASES) {
04648 uiInfo.aliasCount++;
04649 } else {
04650 Com_Printf("Too many aliases, last alias replaced!\n");
04651 }
04652
04653 token = COM_ParseExt(p, qtrue);
04654 if (token[0] != '}') {
04655 return qfalse;
04656 }
04657 }
04658 }
04659
04660 return qfalse;
04661 }
04662
04663
04664
04665
04666
04667
04668
04669 static void UI_ParseTeamInfo(const char *teamFile) {
04670 char *token;
04671 char *p;
04672 char *buff = NULL;
04673
04674
04675 buff = GetMenuBuffer(teamFile);
04676 if (!buff) {
04677 return;
04678 }
04679
04680 p = buff;
04681
04682 while ( 1 ) {
04683 token = COM_ParseExt( &p, qtrue );
04684 if( !token || token[0] == 0 || token[0] == '}') {
04685 break;
04686 }
04687
04688 if ( Q_stricmp( token, "}" ) == 0 ) {
04689 break;
04690 }
04691
04692 if (Q_stricmp(token, "teams") == 0) {
04693
04694 if (Team_Parse(&p)) {
04695 continue;
04696 } else {
04697 break;
04698 }
04699 }
04700
04701 if (Q_stricmp(token, "characters") == 0) {
04702 Character_Parse(&p);
04703 }
04704
04705 if (Q_stricmp(token, "aliases") == 0) {
04706 Alias_Parse(&p);
04707 }
04708
04709 }
04710
04711 }
04712
04713
04714 static qboolean GameType_Parse(char **p, qboolean join) {
04715 char *token;
04716
04717 token = COM_ParseExt(p, qtrue);
04718
04719 if (token[0] != '{') {
04720 return qfalse;
04721 }
04722
04723 if (join) {
04724 uiInfo.numJoinGameTypes = 0;
04725 } else {
04726 uiInfo.numGameTypes = 0;
04727 }
04728
04729 while ( 1 ) {
04730 token = COM_ParseExt(p, qtrue);
04731
04732 if (Q_stricmp(token, "}") == 0) {
04733 return qtrue;
04734 }
04735
04736 if ( !token || token[0] == 0 ) {
04737 return qfalse;
04738 }
04739
04740 if (token[0] == '{') {
04741
04742 if (join) {
04743 if (!String_Parse(p, &uiInfo.joinGameTypes[uiInfo.numJoinGameTypes].gameType) || !Int_Parse(p, &uiInfo.joinGameTypes[uiInfo.numJoinGameTypes].gtEnum)) {
04744 return qfalse;
04745 }
04746 } else {
04747 if (!String_Parse(p, &uiInfo.gameTypes[uiInfo.numGameTypes].gameType) || !Int_Parse(p, &uiInfo.gameTypes[uiInfo.numGameTypes].gtEnum)) {
04748 return qfalse;
04749 }
04750 }
04751
04752 if (join) {
04753 if (uiInfo.numJoinGameTypes < MAX_GAMETYPES) {
04754 uiInfo.numJoinGameTypes++;
04755 } else {
04756 Com_Printf("Too many net game types, last one replace!\n");
04757 }
04758 } else {
04759 if (uiInfo.numGameTypes < MAX_GAMETYPES) {
04760 uiInfo.numGameTypes++;
04761 } else {
04762 Com_Printf("Too many game types, last one replace!\n");
04763 }
04764 }
04765
04766 token = COM_ParseExt(p, qtrue);
04767 if (token[0] != '}') {
04768 return qfalse;
04769 }
04770 }
04771 }
04772 return qfalse;
04773 }
04774
04775 static qboolean MapList_Parse(char **p) {
04776 char *token;
04777
04778 token = COM_ParseExt(p, qtrue);
04779
04780 if (token[0] != '{') {
04781 return qfalse;
04782 }
04783
04784 uiInfo.mapCount = 0;
04785
04786 while ( 1 ) {
04787 token = COM_ParseExt(p, qtrue);
04788
04789 if (Q_stricmp(token, "}") == 0) {
04790 return qtrue;
04791 }
04792
04793 if ( !token || token[0] == 0 ) {
04794 return qfalse;
04795 }
04796
04797 if (token[0] == '{') {
04798 if (!String_Parse(p, &uiInfo.mapList[uiInfo.mapCount].mapName) || !String_Parse(p, &uiInfo.mapList[uiInfo.mapCount].mapLoadName)
04799 ||!Int_Parse(p, &uiInfo.mapList[uiInfo.mapCount].teamMembers) ) {
04800 return qfalse;
04801 }
04802
04803 if (!String_Parse(p, &uiInfo.mapList[uiInfo.mapCount].opponentName)) {
04804 return qfalse;
04805 }
04806
04807 uiInfo.mapList[uiInfo.mapCount].typeBits = 0;
04808
04809 while (1) {
04810 token = COM_ParseExt(p, qtrue);
04811 if (token[0] >= '0' && token[0] <= '9') {
04812 uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << (token[0] - 0x030));
04813 if (!Int_Parse(p, &uiInfo.mapList[uiInfo.mapCount].timeToBeat[token[0] - 0x30])) {
04814 return qfalse;
04815 }
04816 } else {
04817 break;
04818 }
04819 }
04820
04821
04822
04823
04824
04825
04826 uiInfo.mapList[uiInfo.mapCount].cinematic = -1;
04827 uiInfo.mapList[uiInfo.mapCount].levelShot = trap_R_RegisterShaderNoMip(va("levelshots/%s_small", uiInfo.mapList[uiInfo.mapCount].mapLoadName));
04828
04829 if (uiInfo.mapCount < MAX_MAPS) {
04830 uiInfo.mapCount++;
04831 } else {
04832 Com_Printf("Too many maps, last one replaced!\n");
04833 }
04834 }
04835 }
04836 return qfalse;
04837 }
04838
04839 static void UI_ParseGameInfo(const char *teamFile) {
04840 char *token;
04841 char *p;
04842 char *buff = NULL;
04843
04844
04845 buff = GetMenuBuffer(teamFile);
04846 if (!buff) {
04847 return;
04848 }
04849
04850 p = buff;
04851
04852 while ( 1 ) {
04853 token = COM_ParseExt( &p, qtrue );
04854 if( !token || token[0] == 0 || token[0] == '}') {
04855 break;
04856 }
04857
04858 if ( Q_stricmp( token, "}" ) == 0 ) {
04859 break;
04860 }
04861
04862 if (Q_stricmp(token, "gametypes") == 0) {
04863
04864 if (GameType_Parse(&p, qfalse)) {
04865 continue;
04866 } else {
04867 break;
04868 }
04869 }
04870
04871 if (Q_stricmp(token, "joingametypes") == 0) {
04872
04873 if (GameType_Parse(&p, qtrue)) {
04874 continue;
04875 } else {
04876 break;
04877 }
04878 }
04879
04880 if (Q_stricmp(token, "maps") == 0) {
04881
04882 MapList_Parse(&p);
04883 }
04884
04885 }
04886 }
04887
04888 static void UI_Pause(qboolean b) {
04889 if (b) {
04890
04891 trap_Cvar_Set( "cl_paused", "1" );
04892 trap_Key_SetCatcher( KEYCATCH_UI );
04893 } else {
04894
04895 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
04896 trap_Key_ClearStates();
04897 trap_Cvar_Set( "cl_paused", "0" );
04898 }
04899 }
04900
04901 #ifndef MISSIONPACK // bk001206
04902 static int UI_OwnerDraw_Width(int ownerDraw) {
04903
04904 return 0;
04905 }
04906 #endif
04907
04908 static int UI_PlayCinematic(const char *name, float x, float y, float w, float h) {
04909 return trap_CIN_PlayCinematic(name, x, y, w, h, (CIN_loop | CIN_silent));
04910 }
04911
04912 static void UI_StopCinematic(int handle) {
04913 if (handle >= 0) {
04914 trap_CIN_StopCinematic(handle);
04915 } else {
04916 handle = abs(handle);
04917 if (handle == UI_MAPCINEMATIC) {
04918 if (uiInfo.mapList[ui_currentMap.integer].cinematic >= 0) {
04919 trap_CIN_StopCinematic(uiInfo.mapList[ui_currentMap.integer].cinematic);
04920 uiInfo.mapList[ui_currentMap.integer].cinematic = -1;
04921 }
04922 } else if (handle == UI_NETMAPCINEMATIC) {
04923 if (uiInfo.serverStatus.currentServerCinematic >= 0) {
04924 trap_CIN_StopCinematic(uiInfo.serverStatus.currentServerCinematic);
04925 uiInfo.serverStatus.currentServerCinematic = -1;
04926 }
04927 } else if (handle == UI_CLANCINEMATIC) {
04928 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
04929 if (i >= 0 && i < uiInfo.teamCount) {
04930 if (uiInfo.teamList[i].cinematic >= 0) {
04931 trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic);
04932 uiInfo.teamList[i].cinematic = -1;
04933 }
04934 }
04935 }
04936 }
04937 }
04938
04939 static void UI_DrawCinematic(int handle, float x, float y, float w, float h) {
04940 trap_CIN_SetExtents(handle, x, y, w, h);
04941 trap_CIN_DrawCinematic(handle);
04942 }
04943
04944 static void UI_RunCinematicFrame(int handle) {
04945 trap_CIN_RunCinematic(handle);
04946 }
04947
04948
04949
04950
04951
04952
04953
04954
04955 static void UI_BuildQ3Model_List( void )
04956 {
04957 int numdirs;
04958 int numfiles;
04959 char dirlist[2048];
04960 char filelist[2048];
04961 char skinname[64];
04962 char scratch[256];
04963 char* dirptr;
04964 char* fileptr;
04965 int i;
04966 int j, k, dirty;
04967 int dirlen;
04968 int filelen;
04969
04970 uiInfo.q3HeadCount = 0;
04971
04972
04973 numdirs = trap_FS_GetFileList("models/players", "/", dirlist, 2048 );
04974 dirptr = dirlist;
04975 for (i=0; i<numdirs && uiInfo.q3HeadCount < MAX_PLAYERMODELS; i++,dirptr+=dirlen+1)
04976 {
04977 dirlen = strlen(dirptr);
04978
04979 if (dirlen && dirptr[dirlen-1]=='/') dirptr[dirlen-1]='\0';
04980
04981 if (!strcmp(dirptr,".") || !strcmp(dirptr,".."))
04982 continue;
04983
04984
04985 numfiles = trap_FS_GetFileList( va("models/players/%s",dirptr), "tga", filelist, 2048 );
04986 fileptr = filelist;
04987 for (j=0; j<numfiles && uiInfo.q3HeadCount < MAX_PLAYERMODELS;j++,fileptr+=filelen+1)
04988 {
04989 filelen = strlen(fileptr);
04990
04991 COM_StripExtension(fileptr,skinname);
04992
04993
04994 if (Q_stricmpn(skinname, "icon_", 5) == 0 && !(Q_stricmp(skinname,"icon_blue") == 0 || Q_stricmp(skinname,"icon_red") == 0))
04995 {
04996 if (Q_stricmp(skinname, "icon_default") == 0) {
04997 Com_sprintf( scratch, sizeof(scratch), dirptr);
04998 } else {
04999 Com_sprintf( scratch, sizeof(scratch), "%s/%s",dirptr, skinname + 5);
05000 }
05001 dirty = 0;
05002 for(k=0;k<uiInfo.q3HeadCount;k++) {
05003 if (!Q_stricmp(scratch, uiInfo.q3HeadNames[uiInfo.q3HeadCount])) {
05004 dirty = 1;
05005 break;
05006 }
05007 }
05008 if (!dirty) {
05009 Com_sprintf( uiInfo.q3HeadNames[uiInfo.q3HeadCount], sizeof(uiInfo.q3HeadNames[uiInfo.q3HeadCount]), scratch);
05010 uiInfo.q3HeadIcons[uiInfo.q3HeadCount++] = trap_R_RegisterShaderNoMip(va("models/players/%s/%s",dirptr,skinname));
05011 }
05012 }
05013
05014 }
05015 }
05016
05017 }
05018
05019
05020
05021
05022
05023
05024
05025
05026 void _UI_Init( qboolean inGameLoad ) {
05027 const char *menuSet;
05028 int start;
05029
05030
05031
05032 UI_RegisterCvars();
05033 UI_InitMemory();
05034
05035
05036 trap_GetGlconfig( &uiInfo.uiDC.glconfig );
05037
05038
05039 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
05040 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
05041 if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) {
05042
05043 uiInfo.uiDC.bias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * (640.0/480.0) ) );
05044 }
05045 else {
05046
05047 uiInfo.uiDC.bias = 0;
05048 }
05049
05050
05051
05052 uiInfo.uiDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip;
05053 uiInfo.uiDC.setColor = &UI_SetColor;
05054 uiInfo.uiDC.drawHandlePic = &UI_DrawHandlePic;
05055 uiInfo.uiDC.drawStretchPic = &trap_R_DrawStretchPic;
05056 uiInfo.uiDC.drawText = &Text_Paint;
05057 uiInfo.uiDC.textWidth = &Text_Width;
05058 uiInfo.uiDC.textHeight = &Text_Height;
05059 uiInfo.uiDC.registerModel = &trap_R_RegisterModel;
05060 uiInfo.uiDC.modelBounds = &trap_R_ModelBounds;
05061 uiInfo.uiDC.fillRect = &UI_FillRect;
05062 uiInfo.uiDC.drawRect = &_UI_DrawRect;
05063 uiInfo.uiDC.drawSides = &_UI_DrawSides;
05064 uiInfo.uiDC.drawTopBottom = &_UI_DrawTopBottom;
05065 uiInfo.uiDC.clearScene = &trap_R_ClearScene;
05066 uiInfo.uiDC.drawSides = &_UI_DrawSides;
05067 uiInfo.uiDC.addRefEntityToScene = &trap_R_AddRefEntityToScene;
05068 uiInfo.uiDC.renderScene = &trap_R_RenderScene;
05069 uiInfo.uiDC.registerFont = &trap_R_RegisterFont;
05070 uiInfo.uiDC.ownerDrawItem = &UI_OwnerDraw;
05071 uiInfo.uiDC.getValue = &UI_GetValue;
05072 uiInfo.uiDC.ownerDrawVisible = &UI_OwnerDrawVisible;
05073 uiInfo.uiDC.runScript = &UI_RunMenuScript;
05074 uiInfo.uiDC.getTeamColor = &UI_GetTeamColor;
05075 uiInfo.uiDC.setCVar = trap_Cvar_Set;
05076 uiInfo.uiDC.getCVarString = trap_Cvar_VariableStringBuffer;
05077 uiInfo.uiDC.getCVarValue = trap_Cvar_VariableValue;
05078 uiInfo.uiDC.drawTextWithCursor = &Text_PaintWithCursor;
05079 uiInfo.uiDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode;
05080 uiInfo.uiDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode;
05081 uiInfo.uiDC.startLocalSound = &trap_S_StartLocalSound;
05082 uiInfo.uiDC.ownerDrawHandleKey = &UI_OwnerDrawHandleKey;
05083 uiInfo.uiDC.feederCount = &UI_FeederCount;
05084 uiInfo.uiDC.feederItemImage = &UI_FeederItemImage;
05085 uiInfo.uiDC.feederItemText = &UI_FeederItemText;
05086 uiInfo.uiDC.feederSelection = &UI_FeederSelection;
05087 uiInfo.uiDC.setBinding = &trap_Key_SetBinding;
05088 uiInfo.uiDC.getBindingBuf = &trap_Key_GetBindingBuf;
05089 uiInfo.uiDC.keynumToStringBuf = &trap_Key_KeynumToStringBuf;
05090 uiInfo.uiDC.executeText = &trap_Cmd_ExecuteText;
05091 uiInfo.uiDC.Error = &Com_Error;
05092 uiInfo.uiDC.Print = &Com_Printf;
05093 uiInfo.uiDC.Pause = &UI_Pause;
05094 uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth;
05095 uiInfo.uiDC.registerSound = &trap_S_RegisterSound;
05096 uiInfo.uiDC.startBackgroundTrack = &trap_S_StartBackgroundTrack;
05097 uiInfo.uiDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack;
05098 uiInfo.uiDC.playCinematic = &UI_PlayCinematic;
05099 uiInfo.uiDC.stopCinematic = &UI_StopCinematic;
05100 uiInfo.uiDC.drawCinematic = &UI_DrawCinematic;
05101 uiInfo.uiDC.runCinematicFrame = &UI_RunCinematicFrame;
05102
05103 Init_Display(&uiInfo.uiDC);
05104
05105 String_Init();
05106
05107 uiInfo.uiDC.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" );
05108 uiInfo.uiDC.whiteShader = trap_R_RegisterShaderNoMip( "white" );
05109
05110 AssetCache();
05111
05112 start = trap_Milliseconds();
05113
05114 uiInfo.teamCount = 0;
05115 uiInfo.characterCount = 0;
05116 uiInfo.aliasCount = 0;
05117
05118 #ifdef PRE_RELEASE_TADEMO
05119 UI_ParseTeamInfo("demoteaminfo.txt");
05120 UI_ParseGameInfo("demogameinfo.txt");
05121 #else
05122 UI_ParseTeamInfo("teaminfo.txt");
05123 UI_LoadTeams();
05124 UI_ParseGameInfo("gameinfo.txt");
05125 #endif
05126
05127 menuSet = UI_Cvar_VariableString("ui_menuFiles");
05128 if (menuSet == NULL || menuSet[0] == '\0') {
05129 menuSet = "ui/menus.txt";
05130 }
05131
05132 #if 0
05133 if (uiInfo.inGameLoad) {
05134 UI_LoadMenus("ui/ingame.txt", qtrue);
05135 } else {
05136 }
05137 #else
05138 UI_LoadMenus(menuSet, qtrue);
05139 UI_LoadMenus("ui/ingame.txt", qfalse);
05140 #endif
05141
05142 Menus_CloseAll();
05143
05144 trap_LAN_LoadCachedServers();
05145 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);
05146
05147 UI_BuildQ3Model_List();
05148 UI_LoadBots();
05149
05150
05151 uiInfo.effectsColor = gamecodetoui[(int)trap_Cvar_VariableValue("color1")-1];
05152 uiInfo.currentCrosshair = (int)trap_Cvar_VariableValue("cg_drawCrosshair");
05153 trap_Cvar_Set("ui_mousePitch", (trap_Cvar_VariableValue("m_pitch") >= 0) ? "0" : "1");
05154
05155 uiInfo.serverStatus.currentServerCinematic = -1;
05156 uiInfo.previewMovie = -1;
05157
05158 if (trap_Cvar_VariableValue("ui_TeamArenaFirstRun") == 0) {
05159 trap_Cvar_Set("s_volume", "0.8");
05160 trap_Cvar_Set("s_musicvolume", "0.5");
05161 trap_Cvar_Set("ui_TeamArenaFirstRun", "1");
05162 }
05163
05164 trap_Cvar_Register(NULL, "debug_protocol", "", 0 );
05165
05166 trap_Cvar_Set("ui_actualNetGameType", va("%d", ui_netGameType.integer));
05167 }
05168
05169
05170
05171
05172
05173
05174
05175 void _UI_KeyEvent( int key, qboolean down ) {
05176
05177 if (Menu_Count() > 0) {
05178 menuDef_t *menu = Menu_GetFocused();
05179 if (menu) {
05180 if (key == K_ESCAPE && down && !Menus_AnyFullScreenVisible()) {
05181 Menus_CloseAll();
05182 } else {
05183 Menu_HandleKey(menu, key, down );
05184 }
05185 } else {
05186 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
05187 trap_Key_ClearStates();
05188 trap_Cvar_Set( "cl_paused", "0" );
05189 }
05190 }
05191
05192
05193
05194
05195 }
05196
05197
05198
05199
05200
05201
05202 void _UI_MouseEvent( int dx, int dy )
05203 {
05204
05205 uiInfo.uiDC.cursorx += dx;
05206 if (uiInfo.uiDC.cursorx < 0)
05207 uiInfo.uiDC.cursorx = 0;
05208 else if (uiInfo.uiDC.cursorx > SCREEN_WIDTH)
05209 uiInfo.uiDC.cursorx = SCREEN_WIDTH;
05210
05211 uiInfo.uiDC.cursory += dy;
05212 if (uiInfo.uiDC.cursory < 0)
05213 uiInfo.uiDC.cursory = 0;
05214 else if (uiInfo.uiDC.cursory > SCREEN_HEIGHT)
05215 uiInfo.uiDC.cursory = SCREEN_HEIGHT;
05216
05217 if (Menu_Count() > 0) {
05218
05219
05220 Display_MouseMove(NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory);
05221 }
05222
05223 }
05224
05225 void UI_LoadNonIngame() {
05226 const char *menuSet = UI_Cvar_VariableString("ui_menuFiles");
05227 if (menuSet == NULL || menuSet[0] == '\0') {
05228 menuSet = "ui/menus.txt";
05229 }
05230 UI_LoadMenus(menuSet, qfalse);
05231 uiInfo.inGameLoad = qfalse;
05232 }
05233
05234 void _UI_SetActiveMenu( uiMenuCommand_t menu ) {
05235 char buf[256];
05236
05237
05238
05239 if (Menu_Count() > 0) {
05240 vec3_t v;
05241 v[0] = v[1] = v[2] = 0;
05242 switch ( menu ) {
05243 case UIMENU_NONE:
05244 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
05245 trap_Key_ClearStates();
05246 trap_Cvar_Set( "cl_paused", "0" );
05247 Menus_CloseAll();
05248
05249 return;
05250 case UIMENU_MAIN:
05251
05252 trap_Key_SetCatcher( KEYCATCH_UI );
05253
05254
05255 if (uiInfo.inGameLoad) {
05256 UI_LoadNonIngame();
05257 }
05258 Menus_CloseAll();
05259 Menus_ActivateByName("main");
05260 trap_Cvar_VariableStringBuffer("com_errorMessage", buf, sizeof(buf));
05261 if (strlen(buf)) {
05262 if (!ui_singlePlayerActive.integer) {
05263 Menus_ActivateByName("error_popmenu");
05264 } else {
05265 trap_Cvar_Set("com_errorMessage", "");
05266 }
05267 }
05268 return;
05269 case UIMENU_TEAM:
05270 trap_Key_SetCatcher( KEYCATCH_UI );
05271 Menus_ActivateByName("team");
05272 return;
05273 case UIMENU_NEED_CD:
05274
05275
05276
05277
05278 return;
05279 case UIMENU_BAD_CD_KEY:
05280
05281
05282
05283
05284 return;
05285 case UIMENU_POSTGAME:
05286
05287 trap_Key_SetCatcher( KEYCATCH_UI );
05288 if (uiInfo.inGameLoad) {
05289 UI_LoadNonIngame();
05290 }
05291 Menus_CloseAll();
05292 Menus_ActivateByName("endofgame");
05293
05294 return;
05295 case UIMENU_INGAME:
05296 trap_Cvar_Set( "cl_paused", "1" );
05297 trap_Key_SetCatcher( KEYCATCH_UI );
05298 UI_BuildPlayerList();
05299 Menus_CloseAll();
05300 Menus_ActivateByName("ingame");
05301 return;
05302 }
05303 }
05304 }
05305
05306 qboolean _UI_IsFullscreen( void ) {
05307 return Menus_AnyFullScreenVisible();
05308 }
05309
05310
05311
05312 static connstate_t lastConnState;
05313 static char lastLoadingText[MAX_INFO_VALUE];
05314
05315 static void UI_ReadableSize ( char *buf, int bufsize, int value )
05316 {
05317 if (value > 1024*1024*1024 ) {
05318 Com_sprintf( buf, bufsize, "%d", value / (1024*1024*1024) );
05319 Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d GB",
05320 (value % (1024*1024*1024))*100 / (1024*1024*1024) );
05321 } else if (value > 1024*1024 ) {
05322 Com_sprintf( buf, bufsize, "%d", value / (1024*1024) );
05323 Com_sprintf( buf+strlen(buf), bufsize-strlen(buf), ".%02d MB",
05324 (value % (1024*1024))*100 / (1024*1024) );
05325 } else if (value > 1024 ) {
05326 Com_sprintf( buf, bufsize, "%d KB", value / 1024 );
05327 } else {
05328 Com_sprintf( buf, bufsize, "%d bytes", value );
05329 }
05330 }
05331
05332
05333 static void UI_PrintTime ( char *buf, int bufsize, int time ) {
05334 time /= 1000;
05335
05336 if (time > 3600) {
05337 Com_sprintf( buf, bufsize, "%d hr %d min", time / 3600, (time % 3600) / 60 );
05338 } else if (time > 60) {
05339 Com_sprintf( buf, bufsize, "%d min %d sec", time / 60, time % 60 );
05340 } else {
05341 Com_sprintf( buf, bufsize, "%d sec", time );
05342 }
05343 }
05344
05345 void Text_PaintCenter(float x, float y, float scale, vec4_t color, const char *text, float adjust) {
05346 int len = Text_Width(text, scale, 0);
05347 Text_Paint(x - len / 2, y, scale, color, text, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE);
05348 }
05349
05350 void Text_PaintCenter_AutoWrapped(float x, float y, float xmax, float ystep, float scale, vec4_t color, const char *str, float adjust) {
05351 int width;
05352 char *s1,*s2,*s3;
05353 char c_bcp;
05354 char buf[1024];
05355
05356 if (!str || str[0]=='\0')
05357 return;
05358
05359 Q_strncpyz(buf, str, sizeof(buf));
05360 s1 = s2 = s3 = buf;
05361
05362 while (1) {
05363 do {
05364 s3++;
05365 } while (*s3!=' ' && *s3!='\0');
05366 c_bcp = *s3;
05367 *s3 = '\0';
05368 width = Text_Width(s1, scale, 0);
05369 *s3 = c_bcp;
05370 if (width > xmax) {
05371 if (s1==s2)
05372 {
05373
05374 s2 = s3;
05375 }
05376 *s2 = '\0';
05377 Text_PaintCenter(x, y, scale, color, s1, adjust);
05378 y += ystep;
05379 if (c_bcp == '\0')
05380 {
05381
05382
05383
05384
05385 s2++;
05386 if (*s2 != '\0')
05387 Text_PaintCenter(x, y, scale, color, s2, adjust);
05388 break;
05389 }
05390 s2++;
05391 s1 = s2;
05392 s3 = s2;
05393 }
05394 else
05395 {
05396 s2 = s3;
05397 if (c_bcp == '\0')
05398 {
05399 Text_PaintCenter(x, y, scale, color, s1, adjust);
05400 break;
05401 }
05402 }
05403 }
05404 }
05405
05406 static void UI_DisplayDownloadInfo( const char *downloadName, float centerPoint, float yStart, float scale ) {
05407 static char dlText[] = "Downloading:";
05408 static char etaText[] = "Estimated time left:";
05409 static char xferText[] = "Transfer rate:";
05410
05411 int downloadSize, downloadCount, downloadTime;
05412 char dlSizeBuf[64], totalSizeBuf[64], xferRateBuf[64], dlTimeBuf[64];
05413 int xferRate;
05414 int leftWidth;
05415 const char *s;
05416
05417 downloadSize = trap_Cvar_VariableValue( "cl_downloadSize" );
05418 downloadCount = trap_Cvar_VariableValue( "cl_downloadCount" );
05419 downloadTime = trap_Cvar_VariableValue( "cl_downloadTime" );
05420
05421 leftWidth = 320;
05422
05423 UI_SetColor(colorWhite);
05424 Text_PaintCenter(centerPoint, yStart + 112, scale, colorWhite, dlText, 0);
05425 Text_PaintCenter(centerPoint, yStart + 192, scale, colorWhite, etaText, 0);
05426 Text_PaintCenter(centerPoint, yStart + 248, scale, colorWhite, xferText, 0);
05427
05428 if (downloadSize > 0) {
05429 s = va( "%s (%d%%)", downloadName, downloadCount * 100 / downloadSize );
05430 } else {
05431 s = downloadName;
05432 }
05433
05434 Text_PaintCenter(centerPoint, yStart+136, scale, colorWhite, s, 0);
05435
05436 UI_ReadableSize( dlSizeBuf, sizeof dlSizeBuf, downloadCount );
05437 UI_ReadableSize( totalSizeBuf, sizeof totalSizeBuf, downloadSize );
05438
05439 if (downloadCount < 4096 || !downloadTime) {
05440 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, "estimating", 0);
05441 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0);
05442 } else {
05443 if ((uiInfo.uiDC.realTime - downloadTime) / 1000) {
05444 xferRate = downloadCount / ((uiInfo.uiDC.realTime - downloadTime) / 1000);
05445 } else {
05446 xferRate = 0;
05447 }
05448 UI_ReadableSize( xferRateBuf, sizeof xferRateBuf, xferRate );
05449
05450
05451 if (downloadSize && xferRate) {
05452 int n = downloadSize / xferRate;
05453
05454
05455 UI_PrintTime ( dlTimeBuf, sizeof dlTimeBuf,
05456 (n - (((downloadCount/1024) * n) / (downloadSize/1024))) * 1000);
05457
05458 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, dlTimeBuf, 0);
05459 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0);
05460 } else {
05461 Text_PaintCenter(leftWidth, yStart+216, scale, colorWhite, "estimating", 0);
05462 if (downloadSize) {
05463 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s of %s copied)", dlSizeBuf, totalSizeBuf), 0);
05464 } else {
05465 Text_PaintCenter(leftWidth, yStart+160, scale, colorWhite, va("(%s copied)", dlSizeBuf), 0);
05466 }
05467 }
05468
05469 if (xferRate) {
05470 Text_PaintCenter(leftWidth, yStart+272, scale, colorWhite, va("%s/Sec", xferRateBuf), 0);
05471 }
05472 }
05473 }
05474
05475
05476
05477
05478
05479
05480
05481
05482
05483 void UI_DrawConnectScreen( qboolean overlay ) {
05484 char *s;
05485 uiClientState_t cstate;
05486 char info[MAX_INFO_VALUE];
05487 char text[256];
05488 float centerPoint, yStart, scale;
05489
05490 menuDef_t *menu = Menus_FindByName("Connect");
05491
05492
05493 if ( !overlay && menu ) {
05494 Menu_Paint(menu, qtrue);
05495 }
05496
05497 if (!overlay) {
05498 centerPoint = 320;
05499 yStart = 130;
05500 scale = 0.5f;
05501 } else {
05502 centerPoint = 320;
05503 yStart = 32;
05504 scale = 0.6f;
05505 return;
05506 }
05507
05508
05509 trap_GetClientState( &cstate );
05510
05511 info[0] = '\0';
05512 if( trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) ) ) {
05513 Text_PaintCenter(centerPoint, yStart, scale, colorWhite, va( "Loading %s", Info_ValueForKey( info, "mapname" )), 0);
05514 }
05515
05516 if (!Q_stricmp(cstate.servername,"localhost")) {
05517 Text_PaintCenter(centerPoint, yStart + 48, scale, colorWhite, va("Starting up..."), ITEM_TEXTSTYLE_SHADOWEDMORE);
05518 } else {
05519 strcpy(text, va("Connecting to %s", cstate.servername));
05520 Text_PaintCenter(centerPoint, yStart + 48, scale, colorWhite,text , ITEM_TEXTSTYLE_SHADOWEDMORE);
05521 }
05522
05523
05524 Text_PaintCenter(centerPoint, 600, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0);
05525
05526 if ( cstate.connState < CA_CONNECTED ) {
05527 Text_PaintCenter_AutoWrapped(centerPoint, yStart + 176, 630, 20, scale, colorWhite, cstate.messageString, 0);
05528 }
05529
05530 if ( lastConnState > cstate.connState ) {
05531 lastLoadingText[0] = '\0';
05532 }
05533 lastConnState = cstate.connState;
05534
05535 switch ( cstate.connState ) {
05536 case CA_CONNECTING:
05537 s = va("Awaiting connection...%i", cstate.connectPacketCount);
05538 break;
05539 case CA_CHALLENGING:
05540 s = va("Awaiting challenge...%i", cstate.connectPacketCount);
05541 break;
05542 case CA_CONNECTED: {
05543 char downloadName[MAX_INFO_VALUE];
05544
05545 trap_Cvar_VariableStringBuffer( "cl_downloadName", downloadName, sizeof(downloadName) );
05546 if (*downloadName) {
05547 UI_DisplayDownloadInfo( downloadName, centerPoint, yStart, scale );
05548 return;
05549 }
05550 }
05551 s = "Awaiting gamestate...";
05552 break;
05553 case CA_LOADING:
05554 return;
05555 case CA_PRIMED:
05556 return;
05557 default:
05558 return;
05559 }
05560
05561
05562 if (Q_stricmp(cstate.servername,"localhost")) {
05563 Text_PaintCenter(centerPoint, yStart + 80, scale, colorWhite, s, 0);
05564 }
05565
05566
05567 }
05568
05569
05570
05571
05572
05573
05574
05575
05576 typedef struct {
05577 vmCvar_t *vmCvar;
05578 char *cvarName;
05579 char *defaultString;
05580 int cvarFlags;
05581 } cvarTable_t;
05582
05583 vmCvar_t ui_ffa_fraglimit;
05584 vmCvar_t ui_ffa_timelimit;
05585
05586 vmCvar_t ui_tourney_fraglimit;
05587 vmCvar_t ui_tourney_timelimit;
05588
05589 vmCvar_t ui_team_fraglimit;
05590 vmCvar_t ui_team_timelimit;
05591 vmCvar_t ui_team_friendly;
05592
05593 vmCvar_t ui_ctf_capturelimit;
05594 vmCvar_t ui_ctf_timelimit;
05595 vmCvar_t ui_ctf_friendly;
05596
05597 vmCvar_t ui_arenasFile;
05598 vmCvar_t ui_botsFile;
05599 vmCvar_t ui_spScores1;
05600 vmCvar_t ui_spScores2;
05601 vmCvar_t ui_spScores3;
05602 vmCvar_t ui_spScores4;
05603 vmCvar_t ui_spScores5;
05604 vmCvar_t ui_spAwards;
05605 vmCvar_t ui_spVideos;
05606 vmCvar_t ui_spSkill;
05607
05608 vmCvar_t ui_spSelection;
05609
05610 vmCvar_t ui_browserMaster;
05611 vmCvar_t ui_browserGameType;
05612 vmCvar_t ui_browserSortKey;
05613 vmCvar_t ui_browserShowFull;
05614 vmCvar_t ui_browserShowEmpty;
05615
05616 vmCvar_t ui_brassTime;
05617 vmCvar_t ui_drawCrosshair;
05618 vmCvar_t ui_drawCrosshairNames;
05619 vmCvar_t ui_marks;
05620
05621 vmCvar_t ui_server1;
05622 vmCvar_t ui_server2;
05623 vmCvar_t ui_server3;
05624 vmCvar_t ui_server4;
05625 vmCvar_t ui_server5;
05626 vmCvar_t ui_server6;
05627 vmCvar_t ui_server7;
05628 vmCvar_t ui_server8;
05629 vmCvar_t ui_server9;
05630 vmCvar_t ui_server10;
05631 vmCvar_t ui_server11;
05632 vmCvar_t ui_server12;
05633 vmCvar_t ui_server13;
05634 vmCvar_t ui_server14;
05635 vmCvar_t ui_server15;
05636 vmCvar_t ui_server16;
05637
05638 vmCvar_t ui_cdkeychecked;
05639
05640 vmCvar_t ui_redteam;
05641 vmCvar_t ui_redteam1;
05642 vmCvar_t ui_redteam2;
05643 vmCvar_t ui_redteam3;
05644 vmCvar_t ui_redteam4;
05645 vmCvar_t ui_redteam5;
05646 vmCvar_t ui_blueteam;
05647 vmCvar_t ui_blueteam1;
05648 vmCvar_t ui_blueteam2;
05649 vmCvar_t ui_blueteam3;
05650 vmCvar_t ui_blueteam4;
05651 vmCvar_t ui_blueteam5;
05652 vmCvar_t ui_teamName;
05653 vmCvar_t ui_dedicated;
05654 vmCvar_t ui_gameType;
05655 vmCvar_t ui_netGameType;
05656 vmCvar_t ui_actualNetGameType;
05657 vmCvar_t ui_joinGameType;
05658 vmCvar_t ui_netSource;
05659 vmCvar_t ui_serverFilterType;
05660 vmCvar_t ui_opponentName;
05661 vmCvar_t ui_menuFiles;
05662 vmCvar_t ui_currentTier;
05663 vmCvar_t ui_currentMap;
05664 vmCvar_t ui_currentNetMap;
05665 vmCvar_t ui_mapIndex;
05666 vmCvar_t ui_currentOpponent;
05667 vmCvar_t ui_selectedPlayer;
05668 vmCvar_t ui_selectedPlayerName;
05669 vmCvar_t ui_lastServerRefresh_0;
05670 vmCvar_t ui_lastServerRefresh_1;
05671 vmCvar_t ui_lastServerRefresh_2;
05672 vmCvar_t ui_lastServerRefresh_3;
05673 vmCvar_t ui_singlePlayerActive;
05674 vmCvar_t ui_scoreAccuracy;
05675 vmCvar_t ui_scoreImpressives;
05676 vmCvar_t ui_scoreExcellents;
05677 vmCvar_t ui_scoreCaptures;
05678 vmCvar_t ui_scoreDefends;
05679 vmCvar_t ui_scoreAssists;
05680 vmCvar_t ui_scoreGauntlets;
05681 vmCvar_t ui_scoreScore;
05682 vmCvar_t ui_scorePerfect;
05683 vmCvar_t ui_scoreTeam;
05684 vmCvar_t ui_scoreBase;
05685 vmCvar_t ui_scoreTimeBonus;
05686 vmCvar_t ui_scoreSkillBonus;
05687 vmCvar_t ui_scoreShutoutBonus;
05688 vmCvar_t ui_scoreTime;
05689 vmCvar_t ui_captureLimit;
05690 vmCvar_t ui_fragLimit;
05691 vmCvar_t ui_smallFont;
05692 vmCvar_t ui_bigFont;
05693 vmCvar_t ui_findPlayer;
05694 vmCvar_t ui_Q3Model;
05695 vmCvar_t ui_hudFiles;
05696 vmCvar_t ui_recordSPDemo;
05697 vmCvar_t ui_realCaptureLimit;
05698 vmCvar_t ui_realWarmUp;
05699 vmCvar_t ui_serverStatusTimeOut;
05700
05701
05702
05703 static cvarTable_t cvarTable[] = {
05704 { &ui_ffa_fraglimit, "ui_ffa_fraglimit", "20", CVAR_ARCHIVE },
05705 { &ui_ffa_timelimit, "ui_ffa_timelimit", "0", CVAR_ARCHIVE },
05706
05707 { &ui_tourney_fraglimit, "ui_tourney_fraglimit", "0", CVAR_ARCHIVE },
05708 { &ui_tourney_timelimit, "ui_tourney_timelimit", "15", CVAR_ARCHIVE },
05709
05710 { &ui_team_fraglimit, "ui_team_fraglimit", "0", CVAR_ARCHIVE },
05711 { &ui_team_timelimit, "ui_team_timelimit", "20", CVAR_ARCHIVE },
05712 { &ui_team_friendly, "ui_team_friendly", "1", CVAR_ARCHIVE },
05713
05714 { &ui_ctf_capturelimit, "ui_ctf_capturelimit", "8", CVAR_ARCHIVE },
05715 { &ui_ctf_timelimit, "ui_ctf_timelimit", "30", CVAR_ARCHIVE },
05716 { &ui_ctf_friendly, "ui_ctf_friendly", "0", CVAR_ARCHIVE },
05717
05718 { &ui_arenasFile, "g_arenasFile", "", CVAR_INIT|CVAR_ROM },
05719 { &ui_botsFile, "g_botsFile", "", CVAR_INIT|CVAR_ROM },
05720 { &ui_spScores1, "g_spScores1", "", CVAR_ARCHIVE | CVAR_ROM },
05721 { &ui_spScores2, "g_spScores2", "", CVAR_ARCHIVE | CVAR_ROM },
05722 { &ui_spScores3, "g_spScores3", "", CVAR_ARCHIVE | CVAR_ROM },
05723 { &ui_spScores4, "g_spScores4", "", CVAR_ARCHIVE | CVAR_ROM },
05724 { &ui_spScores5, "g_spScores5", "", CVAR_ARCHIVE | CVAR_ROM },
05725 { &ui_spAwards, "g_spAwards", "", CVAR_ARCHIVE | CVAR_ROM },
05726 { &ui_spVideos, "g_spVideos", "", CVAR_ARCHIVE | CVAR_ROM },
05727 { &ui_spSkill, "g_spSkill", "2", CVAR_ARCHIVE },
05728
05729 { &ui_spSelection, "ui_spSelection", "", CVAR_ROM },
05730
05731 { &ui_browserMaster, "ui_browserMaster", "0", CVAR_ARCHIVE },
05732 { &ui_browserGameType, "ui_browserGameType", "0", CVAR_ARCHIVE },
05733 { &ui_browserSortKey, "ui_browserSortKey", "4", CVAR_ARCHIVE },
05734 { &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE },
05735 { &ui_browserShowEmpty, "ui_browserShowEmpty", "1", CVAR_ARCHIVE },
05736
05737 { &ui_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE },
05738 { &ui_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },
05739 { &ui_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
05740 { &ui_marks, "cg_marks", "1", CVAR_ARCHIVE },
05741
05742 { &ui_server1, "server1", "", CVAR_ARCHIVE },
05743 { &ui_server2, "server2", "", CVAR_ARCHIVE },
05744 { &ui_server3, "server3", "", CVAR_ARCHIVE },
05745 { &ui_server4, "server4", "", CVAR_ARCHIVE },
05746 { &ui_server5, "server5", "", CVAR_ARCHIVE },
05747 { &ui_server6, "server6", "", CVAR_ARCHIVE },
05748 { &ui_server7, "server7", "", CVAR_ARCHIVE },
05749 { &ui_server8, "server8", "", CVAR_ARCHIVE },
05750 { &ui_server9, "server9", "", CVAR_ARCHIVE },
05751 { &ui_server10, "server10", "", CVAR_ARCHIVE },
05752 { &ui_server11, "server11", "", CVAR_ARCHIVE },
05753 { &ui_server12, "server12", "", CVAR_ARCHIVE },
05754 { &ui_server13, "server13", "", CVAR_ARCHIVE },
05755 { &ui_server14, "server14", "", CVAR_ARCHIVE },
05756 { &ui_server15, "server15", "", CVAR_ARCHIVE },
05757 { &ui_server16, "server16", "", CVAR_ARCHIVE },
05758 { &ui_cdkeychecked, "ui_cdkeychecked", "0", CVAR_ROM },
05759 { &ui_new, "ui_new", "0", CVAR_TEMP },
05760 { &ui_debug, "ui_debug", "0", CVAR_TEMP },
05761 { &ui_initialized, "ui_initialized", "0", CVAR_TEMP },
05762 { &ui_teamName, "ui_teamName", "Pagans", CVAR_ARCHIVE },
05763 { &ui_opponentName, "ui_opponentName", "Stroggs", CVAR_ARCHIVE },
05764 { &ui_redteam, "ui_redteam", "Pagans", CVAR_ARCHIVE },
05765 { &ui_blueteam, "ui_blueteam", "Stroggs", CVAR_ARCHIVE },
05766 { &ui_dedicated, "ui_dedicated", "0", CVAR_ARCHIVE },
05767 { &ui_gameType, "ui_gametype", "3", CVAR_ARCHIVE },
05768 { &ui_joinGameType, "ui_joinGametype", "0", CVAR_ARCHIVE },
05769 { &ui_netGameType, "ui_netGametype", "3", CVAR_ARCHIVE },
05770 { &ui_actualNetGameType, "ui_actualNetGametype", "3", CVAR_ARCHIVE },
05771 { &ui_redteam1, "ui_redteam1", "0", CVAR_ARCHIVE },
05772 { &ui_redteam2, "ui_redteam2", "0", CVAR_ARCHIVE },
05773 { &ui_redteam3, "ui_redteam3", "0", CVAR_ARCHIVE },
05774 { &ui_redteam4, "ui_redteam4", "0", CVAR_ARCHIVE },
05775 { &ui_redteam5, "ui_redteam5", "0", CVAR_ARCHIVE },
05776 { &ui_blueteam1, "ui_blueteam1", "0", CVAR_ARCHIVE },
05777 { &ui_blueteam2, "ui_blueteam2", "0", CVAR_ARCHIVE },
05778 { &ui_blueteam3, "ui_blueteam3", "0", CVAR_ARCHIVE },
05779 { &ui_blueteam4, "ui_blueteam4", "0", CVAR_ARCHIVE },
05780 { &ui_blueteam5, "ui_blueteam5", "0", CVAR_ARCHIVE },
05781 { &ui_netSource, "ui_netSource", "0", CVAR_ARCHIVE },
05782 { &ui_menuFiles, "ui_menuFiles", "ui/menus.txt", CVAR_ARCHIVE },
05783 { &ui_currentTier, "ui_currentTier", "0", CVAR_ARCHIVE },
05784 { &ui_currentMap, "ui_currentMap", "0", CVAR_ARCHIVE },
05785 { &ui_currentNetMap, "ui_currentNetMap", "0", CVAR_ARCHIVE },
05786 { &ui_mapIndex, "ui_mapIndex", "0", CVAR_ARCHIVE },
05787 { &ui_currentOpponent, "ui_currentOpponent", "0", CVAR_ARCHIVE },
05788 { &ui_selectedPlayer, "cg_selectedPlayer", "0", CVAR_ARCHIVE},
05789 { &ui_selectedPlayerName, "cg_selectedPlayerName", "", CVAR_ARCHIVE},
05790 { &ui_lastServerRefresh_0, "ui_lastServerRefresh_0", "", CVAR_ARCHIVE},
05791 { &ui_lastServerRefresh_1, "ui_lastServerRefresh_1", "", CVAR_ARCHIVE},
05792 { &ui_lastServerRefresh_2, "ui_lastServerRefresh_2", "", CVAR_ARCHIVE},
05793 { &ui_lastServerRefresh_3, "ui_lastServerRefresh_3", "", CVAR_ARCHIVE},
05794 { &ui_singlePlayerActive, "ui_singlePlayerActive", "0", 0},
05795 { &ui_scoreAccuracy, "ui_scoreAccuracy", "0", CVAR_ARCHIVE},
05796 { &ui_scoreImpressives, "ui_scoreImpressives", "0", CVAR_ARCHIVE},
05797 { &ui_scoreExcellents, "ui_scoreExcellents", "0", CVAR_ARCHIVE},
05798 { &ui_scoreCaptures, "ui_scoreCaptures", "0", CVAR_ARCHIVE},
05799 { &ui_scoreDefends, "ui_scoreDefends", "0", CVAR_ARCHIVE},
05800 { &ui_scoreAssists, "ui_scoreAssists", "0", CVAR_ARCHIVE},
05801 { &ui_scoreGauntlets, "ui_scoreGauntlets", "0",CVAR_ARCHIVE},
05802 { &ui_scoreScore, "ui_scoreScore", "0", CVAR_ARCHIVE},
05803 { &ui_scorePerfect, "ui_scorePerfect", "0", CVAR_ARCHIVE},
05804 { &ui_scoreTeam, "ui_scoreTeam", "0 to 0", CVAR_ARCHIVE},
05805 { &ui_scoreBase, "ui_scoreBase", "0", CVAR_ARCHIVE},
05806 { &ui_scoreTime, "ui_scoreTime", "00:00", CVAR_ARCHIVE},
05807 { &ui_scoreTimeBonus, "ui_scoreTimeBonus", "0", CVAR_ARCHIVE},
05808 { &ui_scoreSkillBonus, "ui_scoreSkillBonus", "0", CVAR_ARCHIVE},
05809 { &ui_scoreShutoutBonus, "ui_scoreShutoutBonus", "0", CVAR_ARCHIVE},
05810 { &ui_fragLimit, "ui_fragLimit", "10", 0},
05811 { &ui_captureLimit, "ui_captureLimit", "5", 0},
05812 { &ui_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE},
05813 { &ui_bigFont, "ui_bigFont", "0.4", CVAR_ARCHIVE},
05814 { &ui_findPlayer, "ui_findPlayer", "Sarge", CVAR_ARCHIVE},
05815 { &ui_Q3Model, "ui_q3model", "0", CVAR_ARCHIVE},
05816 { &ui_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},
05817 { &ui_recordSPDemo, "ui_recordSPDemo", "0", CVAR_ARCHIVE},
05818 { &ui_teamArenaFirstRun, "ui_teamArenaFirstRun", "0", CVAR_ARCHIVE},
05819 { &ui_realWarmUp, "g_warmup", "20", CVAR_ARCHIVE},
05820 { &ui_realCaptureLimit, "capturelimit", "8", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART},
05821 { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
05822
05823 };
05824
05825
05826 static int cvarTableSize = sizeof(cvarTable) / sizeof(cvarTable[0]);
05827
05828
05829
05830
05831
05832
05833
05834 void UI_RegisterCvars( void ) {
05835 int i;
05836 cvarTable_t *cv;
05837
05838 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
05839 trap_Cvar_Register( cv->vmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags );
05840 }
05841 }
05842
05843
05844
05845
05846
05847
05848 void UI_UpdateCvars( void ) {
05849 int i;
05850 cvarTable_t *cv;
05851
05852 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
05853 trap_Cvar_Update( cv->vmCvar );
05854 }
05855 }
05856
05857
05858
05859
05860
05861
05862
05863 static void UI_StopServerRefresh( void )
05864 {
05865 int count;
05866
05867 if (!uiInfo.serverStatus.refreshActive) {
05868
05869 return;
05870 }
05871 uiInfo.serverStatus.refreshActive = qfalse;
05872 Com_Printf("%d servers listed in browser with %d players.\n",
05873 uiInfo.serverStatus.numDisplayServers,
05874 uiInfo.serverStatus.numPlayersOnServers);
05875 count = trap_LAN_GetServerCount(ui_netSource.integer);
05876 if (count - uiInfo.serverStatus.numDisplayServers > 0) {
05877 Com_Printf("%d servers not listed due to packet loss or pings higher than %d\n",
05878 count - uiInfo.serverStatus.numDisplayServers,
05879 (int) trap_Cvar_VariableValue("cl_maxPing"));
05880 }
05881
05882 }
05883
05884
05885
05886
05887
05888
05889 #ifndef MISSIONPACK // bk001206
05890 static int ArenaServers_MaxPing( void ) {
05891 int maxPing;
05892
05893 maxPing = (int)trap_Cvar_VariableValue( "cl_maxPing" );
05894 if( maxPing < 100 ) {
05895 maxPing = 100;
05896 }
05897 return maxPing;
05898 }
05899 #endif
05900
05901
05902
05903
05904
05905
05906 static void UI_DoServerRefresh( void )
05907 {
05908 qboolean wait = qfalse;
05909
05910 if (!uiInfo.serverStatus.refreshActive) {
05911 return;
05912 }
05913 if (ui_netSource.integer != AS_FAVORITES) {
05914 if (ui_netSource.integer == AS_LOCAL) {
05915 if (!trap_LAN_GetServerCount(ui_netSource.integer)) {
05916 wait = qtrue;
05917 }
05918 } else {
05919 if (trap_LAN_GetServerCount(ui_netSource.integer) < 0) {
05920 wait = qtrue;
05921 }
05922 }
05923 }
05924
05925 if (uiInfo.uiDC.realTime < uiInfo.serverStatus.refreshtime) {
05926 if (wait) {
05927 return;
05928 }
05929 }
05930
05931
05932 if (trap_LAN_UpdateVisiblePings(ui_netSource.integer)) {
05933 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
05934 } else if (!wait) {
05935
05936 UI_BuildServerDisplayList(2);
05937
05938 UI_StopServerRefresh();
05939 }
05940
05941 UI_BuildServerDisplayList(qfalse);
05942 }
05943
05944
05945
05946
05947
05948
05949 static void UI_StartServerRefresh(qboolean full)
05950 {
05951 int i;
05952 char *ptr;
05953
05954 qtime_t q;
05955 trap_RealTime(&q);
05956 trap_Cvar_Set( va("ui_lastServerRefresh_%i", ui_netSource.integer), va("%s-%i, %i at %i:%i", MonthAbbrev[q.tm_mon],q.tm_mday, 1900+q.tm_year,q.tm_hour,q.tm_min));
05957
05958 if (!full) {
05959 UI_UpdatePendingPings();
05960 return;
05961 }
05962
05963 uiInfo.serverStatus.refreshActive = qtrue;
05964 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 1000;
05965
05966 uiInfo.serverStatus.numDisplayServers = 0;
05967 uiInfo.serverStatus.numPlayersOnServers = 0;
05968
05969 trap_LAN_MarkServerVisible(ui_netSource.integer, -1, qtrue);
05970
05971 trap_LAN_ResetPings(ui_netSource.integer);
05972
05973 if( ui_netSource.integer == AS_LOCAL ) {
05974 trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" );
05975 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
05976 return;
05977 }
05978
05979 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000;
05980 if( ui_netSource.integer == AS_GLOBAL || ui_netSource.integer == AS_MPLAYER ) {
05981 if( ui_netSource.integer == AS_GLOBAL ) {
05982 i = 0;
05983 }
05984 else {
05985 i = 1;
05986 }
05987
05988 ptr = UI_Cvar_VariableString("debug_protocol");
05989 if (strlen(ptr)) {
05990 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s full empty\n", i, ptr));
05991 }
05992 else {
05993 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d full empty\n", i, (int)trap_Cvar_VariableValue( "protocol" ) ) );
05994 }
05995 }
05996 }
05997