1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
8
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29
30
31
32
33 /*
34 =======================================================================
35
36 USER INTERFACE MAIN
37
38 =======================================================================
39 */
40
41 #include "ui_local.h"
42
43 uiInfo_t uiInfo;
44
45 static const char *MonthAbbrev[] = {
46 "Jan","Feb","Mar",
47 "Apr","May","Jun",
48 "Jul","Aug","Sep",
49 "Oct","Nov","Dec"
50 };
51
52
53 static const char *skillLevels[] = {
54 "I Can Win",
55 "Bring It On",
56 "Hurt Me Plenty",
57 "Hardcore",
58 "Nightmare"
59 };
60
61 static const int numSkillLevels = ARRAY_LEN( skillLevels );
62
63
64 #define UIAS_LOCAL 0
65 #define UIAS_GLOBAL0 1
66 #define UIAS_GLOBAL1 2
67 #define UIAS_GLOBAL2 3
68 #define UIAS_GLOBAL3 4
69 #define UIAS_GLOBAL4 5
70 #define UIAS_GLOBAL5 6
71 #define UIAS_FAVORITES 7
72
73 static const char *netSources[] = {
74 "Local",
75 "Internet",
76 "Master1",
77 "Master2",
78 "Master3",
79 "Master4",
80 "Master5",
81 "Favorites"
82 };
83 static const int numNetSources = ARRAY_LEN( netSources );
84
85 static const serverFilter_t serverFilters[] = {
86 {"All", "" },
87 {"Quake 3 Arena", "" },
88 {"Team Arena", "missionpack" },
89 {"Rocket Arena", "arena" },
90 {"Alliance", "alliance" },
91 };
92
93 static const int numServerFilters = ARRAY_LEN( serverFilters );
94
95 static const char *teamArenaGameTypes[] = {
96 "FFA",
97 "TOURNAMENT",
98 "SP",
99 "TEAM DM",
100 "CTF",
101 "1FCTF",
102 "OVERLOAD",
103 "HARVESTER",
104 };
105
106 static int const numTeamArenaGameTypes = ARRAY_LEN( teamArenaGameTypes );
107
108 static char* netnames[] = {
109 "???",
110 "IP4",
111 "IP6"
112 };
113
114 // TTimo: unused
115 //static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
116
117 static int gamecodetoui[] = {4,2,3,0,5,1,6};
118 static int uitogamecode[] = {4,6,2,3,1,5,7};
119
120
121 // NERVE - SMF - enabled for multiplayer
122 static void UI_StartServerRefresh( qboolean full, qboolean force );
123 static void UI_StopServerRefresh( void );
124 static void UI_DoServerRefresh( void );
125 static void UI_FeederSelection( float feederID, int index );
126 static void UI_BuildServerDisplayList( int force );
127 static void UI_BuildServerStatus( qboolean force );
128 static void UI_BuildFindPlayerList( qboolean force );
129 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 );
130 static int UI_MapCountByGameType( qboolean singlePlayer );
131 static const char *UI_SelectedMap( int index, int *actual );
132 static int UI_GetIndexFromSelection( int actual );
133 // -NERVE - SMF - enabled for multiplayer
134
135 static void UI_ParseGameInfo( const char *teamFile );
136 //static void UI_ParseTeamInfo(const char *teamFile);
137
138 //int ProcessNewUI( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6 );
139
140 static uiMenuCommand_t menutype = UIMENU_NONE;
141
142 // externs
143 extern displayContextDef_t *DC;
144
145
146 //----(SA) added for savegame sorting
147 static int QDECL UI_SavegamesQsortCompare( const void *arg1, const void *arg2 );
148 //----(SA) end
149
150 void Text_PaintCenter( float x, float y, int font, float scale, vec4_t color, const char *text, float adjust );
151
152
153 /*
154 ================
155 vmMain
156
157 This is the only way control passes into the module.
158 This must be the very first function compiled into the .qvm file
159 ================
160 */
161 vmCvar_t ui_new;
162 vmCvar_t ui_debug;
163 vmCvar_t ui_initialized;
164 vmCvar_t ui_WolfFirstRun;
165
166 void _UI_Init( qboolean );
167 void _UI_Shutdown( void );
168 void _UI_KeyEvent( int key, qboolean down );
169 void _UI_MouseEvent( int dx, int dy );
170 void _UI_Refresh( int realtime );
171 qboolean _UI_IsFullscreen( void );
172
vmMain(intptr_t command,intptr_t arg0,intptr_t arg1,intptr_t arg2,intptr_t arg3,intptr_t arg4,intptr_t arg5,intptr_t arg6,intptr_t arg7,intptr_t arg8,intptr_t arg9,intptr_t arg10,intptr_t arg11)173 Q_EXPORT intptr_t vmMain( intptr_t command, intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4, intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9, intptr_t arg10, intptr_t arg11 ) {
174 switch ( command ) {
175 case UI_GETAPIVERSION:
176 return UI_API_VERSION;
177
178 case UI_INIT:
179 _UI_Init( arg0 );
180 return 0;
181
182 case UI_SHUTDOWN:
183 _UI_Shutdown();
184 return 0;
185
186 case UI_KEY_EVENT:
187 _UI_KeyEvent( arg0, arg1 );
188 return 0;
189
190 case UI_MOUSE_EVENT:
191 _UI_MouseEvent( arg0, arg1 );
192 return 0;
193
194 case UI_REFRESH:
195 _UI_Refresh( arg0 );
196 return 0;
197
198 case UI_IS_FULLSCREEN:
199 return _UI_IsFullscreen();
200
201 case UI_SET_ACTIVE_MENU:
202 _UI_SetActiveMenu( arg0 );
203 return 0;
204
205 case UI_GET_ACTIVE_MENU:
206 return _UI_GetActiveMenu();
207
208 case UI_CONSOLE_COMMAND:
209 return UI_ConsoleCommand( arg0 );
210
211 case UI_DRAW_CONNECT_SCREEN:
212 UI_DrawConnectScreen( arg0 );
213 return 0;
214 case UI_HASUNIQUECDKEY: // mod authors need to observe this
215 return qtrue;
216
217 }
218
219 return -1;
220 }
221
222
223
AssetCache(void)224 void AssetCache( void ) {
225 int n;
226 //if (Assets.textFont == NULL) {
227 //}
228 //Assets.background = trap_R_RegisterShaderNoMip( ASSET_BACKGROUND );
229 //Com_Printf("Menu Size: %i bytes\n", sizeof(Menus));
230 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
231 uiInfo.uiDC.Assets.fxBasePic = trap_R_RegisterShaderNoMip( ART_FX_BASE );
232 uiInfo.uiDC.Assets.fxPic[0] = trap_R_RegisterShaderNoMip( ART_FX_RED );
233 uiInfo.uiDC.Assets.fxPic[1] = trap_R_RegisterShaderNoMip( ART_FX_YELLOW );
234 uiInfo.uiDC.Assets.fxPic[2] = trap_R_RegisterShaderNoMip( ART_FX_GREEN );
235 uiInfo.uiDC.Assets.fxPic[3] = trap_R_RegisterShaderNoMip( ART_FX_TEAL );
236 uiInfo.uiDC.Assets.fxPic[4] = trap_R_RegisterShaderNoMip( ART_FX_BLUE );
237 uiInfo.uiDC.Assets.fxPic[5] = trap_R_RegisterShaderNoMip( ART_FX_CYAN );
238 uiInfo.uiDC.Assets.fxPic[6] = trap_R_RegisterShaderNoMip( ART_FX_WHITE );
239 uiInfo.uiDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
240 uiInfo.uiDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
241 uiInfo.uiDC.Assets.scrollBarArrowUp = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
242 uiInfo.uiDC.Assets.scrollBarArrowLeft = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
243 uiInfo.uiDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
244 uiInfo.uiDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
245 uiInfo.uiDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
246 uiInfo.uiDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
247
248 for ( n = 0; n < NUM_CROSSHAIRS; n++ ) {
249 uiInfo.uiDC.Assets.crosshairShader[n] = trap_R_RegisterShaderNoMip( va( "gfx/2d/crosshair%c", 'a' + n ) );
250 }
251
252 // uiInfo.newHighScoreSound = trap_S_RegisterSound("sound/feedback/voc_newhighscore.wav");
253 }
254
_UI_DrawSides(float x,float y,float w,float h,float size)255 void _UI_DrawSides( float x, float y, float w, float h, float size ) {
256 UI_AdjustFrom640( &x, &y, &w, &h );
257 size *= uiInfo.uiDC.xscale;
258 trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
259 trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
260 }
261
_UI_DrawTopBottom(float x,float y,float w,float h,float size)262 void _UI_DrawTopBottom( float x, float y, float w, float h, float size ) {
263 UI_AdjustFrom640( &x, &y, &w, &h );
264 size *= uiInfo.uiDC.yscale;
265 trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
266 trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
267 }
268 /*
269 ================
270 UI_DrawRect
271
272 Coordinates are 640*480 virtual values
273 =================
274 */
_UI_DrawRect(float x,float y,float width,float height,float size,const float * color)275 void _UI_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
276 trap_R_SetColor( color );
277
278 _UI_DrawTopBottom( x, y, width, height, size );
279 _UI_DrawSides( x, y, width, height, size );
280
281 trap_R_SetColor( NULL );
282 }
283
284
285
286
Text_Width(const char * text,int font,float scale,int limit)287 int Text_Width( const char *text, int font, float scale, int limit ) {
288 int count,len;
289 float out;
290 glyphInfo_t *glyph;
291 float useScale;
292 const char *s = text;
293
294 fontInfo_t *fnt = &uiInfo.uiDC.Assets.textFont;
295 if ( font == UI_FONT_DEFAULT ) {
296 if ( scale <= ui_smallFont.value ) {
297 fnt = &uiInfo.uiDC.Assets.smallFont;
298 } else if ( scale > ui_bigFont.value ) {
299 fnt = &uiInfo.uiDC.Assets.bigFont;
300 }
301 } else if ( font == UI_FONT_BIG ) {
302 fnt = &uiInfo.uiDC.Assets.bigFont;
303 } else if ( font == UI_FONT_SMALL ) {
304 fnt = &uiInfo.uiDC.Assets.smallFont;
305 } else if ( font == UI_FONT_HANDWRITING ) {
306 fnt = &uiInfo.uiDC.Assets.handwritingFont;
307 }
308
309 useScale = scale * fnt->glyphScale;
310 out = 0;
311 if ( text ) {
312 len = strlen( text );
313 if ( limit > 0 && len > limit ) {
314 len = limit;
315 }
316 count = 0;
317 while ( s && *s && count < len ) {
318 if ( Q_IsColorString( s ) ) {
319 s += 2;
320 continue;
321 } else {
322 glyph = &fnt->glyphs[*s & 255];
323 out += glyph->xSkip;
324 s++;
325 count++;
326 }
327 }
328 }
329 return out * useScale;
330 }
331
Text_Height(const char * text,int font,float scale,int limit)332 int Text_Height( const char *text, int font, float scale, int limit ) {
333 int len, count;
334 float max;
335 glyphInfo_t *glyph;
336 float useScale;
337 const char *s = text;
338
339 fontInfo_t *fnt = &uiInfo.uiDC.Assets.textFont;
340 if ( font == UI_FONT_DEFAULT ) {
341 if ( scale <= ui_smallFont.value ) {
342 fnt = &uiInfo.uiDC.Assets.smallFont;
343 } else if ( scale > ui_bigFont.value ) {
344 fnt = &uiInfo.uiDC.Assets.bigFont;
345 }
346 } else if ( font == UI_FONT_BIG ) {
347 fnt = &uiInfo.uiDC.Assets.bigFont;
348 } else if ( font == UI_FONT_SMALL ) {
349 fnt = &uiInfo.uiDC.Assets.smallFont;
350 } else if ( font == UI_FONT_HANDWRITING ) {
351 fnt = &uiInfo.uiDC.Assets.handwritingFont;
352 }
353
354 useScale = scale * fnt->glyphScale;
355 max = 0;
356 if ( text ) {
357 len = strlen( text );
358 if ( limit > 0 && len > limit ) {
359 len = limit;
360 }
361 count = 0;
362 while ( s && *s && count < len ) {
363 if ( Q_IsColorString( s ) ) {
364 s += 2;
365 continue;
366 } else {
367 glyph = &fnt->glyphs[*s & 255];
368 if ( max < glyph->height ) {
369 max = glyph->height;
370 }
371 s++;
372 count++;
373 }
374 }
375 }
376 return max * useScale;
377 }
378
Text_PaintChar(float x,float y,float width,float height,int font,float scale,float s,float t,float s2,float t2,qhandle_t hShader)379 void Text_PaintChar( float x, float y, float width, float height, int font, float scale, float s, float t, float s2, float t2, qhandle_t hShader ) {
380 float w, h;
381 w = width * scale;
382 h = height * scale;
383 UI_AdjustFrom640( &x, &y, &w, &h );
384 trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader );
385 }
386
Text_Paint(float x,float y,int font,float scale,vec4_t color,const char * text,float adjust,int limit,int style)387 void Text_Paint( float x, float y, int font, float scale, vec4_t color, const char *text, float adjust, int limit, int style ) {
388 int len, count;
389 vec4_t newColor;
390 glyphInfo_t *glyph;
391 float useScale;
392
393 fontInfo_t *fnt = &uiInfo.uiDC.Assets.textFont;
394 if ( font == UI_FONT_DEFAULT ) {
395 if ( scale <= ui_smallFont.value ) {
396 fnt = &uiInfo.uiDC.Assets.smallFont;
397 } else if ( scale > ui_bigFont.value ) {
398 fnt = &uiInfo.uiDC.Assets.bigFont;
399 }
400 } else if ( font == UI_FONT_BIG ) {
401 fnt = &uiInfo.uiDC.Assets.bigFont;
402 } else if ( font == UI_FONT_SMALL ) {
403 fnt = &uiInfo.uiDC.Assets.smallFont;
404 } else if ( font == UI_FONT_HANDWRITING ) {
405 fnt = &uiInfo.uiDC.Assets.handwritingFont;
406 }
407
408 useScale = scale * fnt->glyphScale;
409 if ( text ) {
410 const char *s = text;
411 trap_R_SetColor( color );
412 memcpy( &newColor[0], &color[0], sizeof( vec4_t ) );
413 len = strlen( text );
414 if ( limit > 0 && len > limit ) {
415 len = limit;
416 }
417 count = 0;
418 while ( s && *s && count < len ) {
419 glyph = &fnt->glyphs[*s & 255];
420 //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top;
421 //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height);
422 if ( Q_IsColorString( s ) ) {
423 memcpy( newColor, g_color_table[ColorIndex( *( s + 1 ) )], sizeof( newColor ) );
424 newColor[3] = color[3];
425 trap_R_SetColor( newColor );
426 s += 2;
427 continue;
428 } else {
429 float yadj = useScale * glyph->top;
430 if ( style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE ) {
431 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
432 colorBlack[3] = newColor[3];
433 trap_R_SetColor( colorBlack );
434 Text_PaintChar( x + ofs, y - yadj + ofs,
435 glyph->imageWidth,
436 glyph->imageHeight,
437 font,
438 useScale,
439 glyph->s,
440 glyph->t,
441 glyph->s2,
442 glyph->t2,
443 glyph->glyph );
444 trap_R_SetColor( newColor );
445 colorBlack[3] = 1.0;
446 }
447 Text_PaintChar( x, y - yadj,
448 glyph->imageWidth,
449 glyph->imageHeight,
450 font,
451 useScale,
452 glyph->s,
453 glyph->t,
454 glyph->s2,
455 glyph->t2,
456 glyph->glyph );
457
458 x += ( glyph->xSkip * useScale ) + adjust;
459 s++;
460 count++;
461 }
462 }
463 trap_R_SetColor( NULL );
464 }
465 }
466
Text_PaintWithCursor(float x,float y,int font,float scale,vec4_t color,const char * text,int cursorPos,char cursor,int limit,int style)467 void Text_PaintWithCursor( float x, float y, int font, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style ) {
468 int len, count;
469 vec4_t newColor;
470 glyphInfo_t *glyph, *glyph2;
471 float yadj;
472 float useScale;
473
474 fontInfo_t *fnt = &uiInfo.uiDC.Assets.textFont;
475 if ( font == UI_FONT_DEFAULT ) {
476 if ( scale <= ui_smallFont.value ) {
477 fnt = &uiInfo.uiDC.Assets.smallFont;
478 } else if ( scale > ui_bigFont.value ) {
479 fnt = &uiInfo.uiDC.Assets.bigFont;
480 }
481 } else if ( font == UI_FONT_BIG ) {
482 fnt = &uiInfo.uiDC.Assets.bigFont;
483 } else if ( font == UI_FONT_SMALL ) {
484 fnt = &uiInfo.uiDC.Assets.smallFont;
485 } else if ( font == UI_FONT_HANDWRITING ) {
486 fnt = &uiInfo.uiDC.Assets.handwritingFont;
487 }
488
489 useScale = scale * fnt->glyphScale;
490 if ( text ) {
491 const char *s = text;
492 trap_R_SetColor( color );
493 memcpy( &newColor[0], &color[0], sizeof( vec4_t ) );
494 len = strlen( text );
495 if ( limit > 0 && len > limit ) {
496 len = limit;
497 }
498 count = 0;
499 glyph2 = &fnt->glyphs[cursor & 255];
500 while ( s && *s && count < len ) {
501 glyph = &fnt->glyphs[*s & 255];
502 //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top;
503 //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height);
504 if ( Q_IsColorString( s ) ) {
505 memcpy( newColor, g_color_table[ColorIndex( *( s + 1 ) )], sizeof( newColor ) );
506 newColor[3] = color[3];
507 trap_R_SetColor( newColor );
508 s += 2;
509 continue;
510 } else {
511 yadj = useScale * glyph->top;
512 if ( style == ITEM_TEXTSTYLE_SHADOWED || style == ITEM_TEXTSTYLE_SHADOWEDMORE ) {
513 int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
514 colorBlack[3] = newColor[3];
515 trap_R_SetColor( colorBlack );
516 Text_PaintChar( x + ofs, y - yadj + ofs,
517 glyph->imageWidth,
518 glyph->imageHeight,
519 font,
520 useScale,
521 glyph->s,
522 glyph->t,
523 glyph->s2,
524 glyph->t2,
525 glyph->glyph );
526 colorBlack[3] = 1.0;
527 trap_R_SetColor( newColor );
528 }
529 Text_PaintChar( x, y - yadj,
530 glyph->imageWidth,
531 glyph->imageHeight,
532 font,
533 useScale,
534 glyph->s,
535 glyph->t,
536 glyph->s2,
537 glyph->t2,
538 glyph->glyph );
539
540 // CG_DrawPic(x, y - yadj, scale * uiDC.Assets.textFont.glyphs[text[i]].imageWidth, scale * uiDC.Assets.textFont.glyphs[text[i]].imageHeight, uiDC.Assets.textFont.glyphs[text[i]].glyph);
541 yadj = useScale * glyph2->top;
542 if ( count == cursorPos && !( ( uiInfo.uiDC.realTime / BLINK_DIVISOR ) & 1 ) ) {
543 Text_PaintChar( x, y - yadj,
544 glyph2->imageWidth,
545 glyph2->imageHeight,
546 font,
547 useScale,
548 glyph2->s,
549 glyph2->t,
550 glyph2->s2,
551 glyph2->t2,
552 glyph2->glyph );
553 }
554
555 x += ( glyph->xSkip * useScale );
556 s++;
557 count++;
558 }
559 }
560 // need to paint cursor at end of text
561 if ( cursorPos == len && !( ( uiInfo.uiDC.realTime / BLINK_DIVISOR ) & 1 ) ) {
562 yadj = useScale * glyph2->top;
563 Text_PaintChar( x, y - yadj,
564 glyph2->imageWidth,
565 glyph2->imageHeight,
566 font,
567 useScale,
568 glyph2->s,
569 glyph2->t,
570 glyph2->s2,
571 glyph2->t2,
572 glyph2->glyph );
573
574 }
575
576
577 trap_R_SetColor( NULL );
578 }
579 }
580
581 // TTimo: unused
582 /*
583 static void Text_Paint_Limit(float *maxX, float x, float y, int font, float scale, vec4_t color, const char* text, float adjust, int limit) {
584 int len, count;
585 vec4_t newColor;
586 glyphInfo_t *glyph;
587 if (text) {
588 const char *s = text;
589 float max = *maxX;
590 float useScale;
591
592 fontInfo_t *fnt = &uiInfo.uiDC.Assets.textFont;
593 if(font == UI_FONT_DEFAULT) {
594 if (scale <= ui_smallFont.value) {
595 fnt = &uiInfo.uiDC.Assets.smallFont;
596 } else if (scale > ui_bigFont.value) {
597 fnt = &uiInfo.uiDC.Assets.bigFont;
598 }
599 } else if(font == UI_FONT_BIG) {
600 fnt = &uiInfo.uiDC.Assets.bigFont;
601 } else if(font == UI_FONT_SMALL) {
602 fnt = &uiInfo.uiDC.Assets.smallFont;
603 } else if(font == UI_FONT_HANDWRITING) {
604 fnt = &uiInfo.uiDC.Assets.handwritingFont;
605 }
606
607 useScale = scale * fnt->glyphScale;
608 trap_R_SetColor( color );
609 len = strlen(text);
610 if (limit > 0 && len > limit) {
611 len = limit;
612 }
613 count = 0;
614 while (s && *s && count < len) {
615 glyph = &fnt->glyphs[*s & 255];
616 if ( Q_IsColorString( s ) ) {
617 memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
618 newColor[3] = color[3];
619 trap_R_SetColor( newColor );
620 s += 2;
621 continue;
622 } else {
623 float yadj = useScale * glyph->top;
624 if (Text_Width(s, font, scale, 1) + x > max) {
625 *maxX = 0;
626 break;
627 }
628 Text_PaintChar(x, y - yadj,
629 glyph->imageWidth,
630 glyph->imageHeight,
631 font,
632 useScale,
633 glyph->s,
634 glyph->t,
635 glyph->s2,
636 glyph->t2,
637 glyph->glyph);
638 x += (glyph->xSkip * useScale) + adjust;
639 *maxX = x;
640 count++;
641 s++;
642 }
643 }
644 trap_R_SetColor( NULL );
645 }
646
647 }
648 */
649
UI_ShowPostGame(qboolean newHigh)650 void UI_ShowPostGame( qboolean newHigh ) {
651 trap_Cvar_Set( "cg_cameraOrbit", "0" );
652 trap_Cvar_Set( "cg_thirdPerson", "0" );
653 uiInfo.soundHighScore = newHigh;
654 _UI_SetActiveMenu( UIMENU_POSTGAME );
655 }
656 /*
657 =================
658 _UI_Refresh
659 =================
660 */
661
UI_DrawCenteredPic(qhandle_t image,int w,int h)662 void UI_DrawCenteredPic( qhandle_t image, int w, int h ) {
663 int x, y;
664 x = ( SCREEN_WIDTH - w ) / 2;
665 y = ( SCREEN_HEIGHT - h ) / 2;
666 UI_DrawHandlePic( x, y, w, h, image );
667 }
668
669 int frameCount = 0;
670 int startTime;
671
672 #define UI_FPS_FRAMES 4
_UI_Refresh(int realtime)673 void _UI_Refresh( int realtime ) {
674 static int index;
675 static int previousTimes[UI_FPS_FRAMES];
676
677 //if ( !( trap_Key_GetCatcher() & KEYCATCH_UI ) ) {
678 // return;
679 //}
680
681 uiInfo.uiDC.frameTime = realtime - uiInfo.uiDC.realTime;
682 uiInfo.uiDC.realTime = realtime;
683
684 previousTimes[index % UI_FPS_FRAMES] = uiInfo.uiDC.frameTime;
685 index++;
686 if ( index > UI_FPS_FRAMES ) {
687 int i, total;
688 // average multiple frames together to smooth changes out a bit
689 total = 0;
690 for ( i = 0 ; i < UI_FPS_FRAMES ; i++ ) {
691 total += previousTimes[i];
692 }
693 if ( !total ) {
694 total = 1;
695 }
696 uiInfo.uiDC.FPS = 1000 * UI_FPS_FRAMES / total;
697 }
698
699
700
701 UI_UpdateCvars();
702
703 if ( Menu_Count() > 0 ) {
704 // paint all the menus
705 Menu_PaintAll();
706 // refresh server browser list
707 UI_DoServerRefresh();
708 // refresh server status
709 UI_BuildServerStatus( qfalse );
710 // refresh find player list
711 UI_BuildFindPlayerList( qfalse );
712 }
713
714 // draw cursor
715 UI_SetColor( NULL );
716 if (Menu_Count() > 0 && (trap_Key_GetCatcher() & KEYCATCH_UI)) {
717 uiMenuCommand_t mymenu = _UI_GetActiveMenu();
718 if ( mymenu != UIMENU_BRIEFING ) {
719 UI_DrawHandlePic( uiInfo.uiDC.cursorx - 16, uiInfo.uiDC.cursory - 16, 32, 32, uiInfo.uiDC.Assets.cursor );
720 }
721 }
722
723 #ifndef NDEBUG
724 if ( uiInfo.uiDC.debug ) {
725 // cursor coordinates
726 //FIXME
727 //UI_DrawString( 0, 0, va("(%d,%d)",uis.cursorx,uis.cursory), UI_LEFT|UI_SMALLFONT, colorRed );
728 }
729 #endif
730
731 }
732
733 /*
734 =================
735 _UI_Shutdown
736 =================
737 */
_UI_Shutdown(void)738 void _UI_Shutdown( void ) {
739 trap_LAN_SaveCachedServers();
740 }
741
742 char *defaultMenu = NULL;
743
GetMenuBuffer(const char * filename)744 char *GetMenuBuffer( const char *filename ) {
745 int len;
746 fileHandle_t f;
747 static char buf[MAX_MENUFILE];
748
749 len = trap_FS_FOpenFile( filename, &f, FS_READ );
750 if ( !f ) {
751 trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
752 return defaultMenu;
753 }
754 if ( len >= MAX_MENUFILE ) {
755 trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
756 trap_FS_FCloseFile( f );
757 return defaultMenu;
758 }
759
760 trap_FS_Read( buf, len, f );
761 buf[len] = 0;
762 trap_FS_FCloseFile( f );
763 //COM_Compress(buf);
764 return buf;
765
766 }
767
Asset_Parse(int handle)768 qboolean Asset_Parse( int handle ) {
769 pc_token_t token;
770 const char *tempStr;
771
772 if ( !trap_PC_ReadToken( handle, &token ) ) {
773 return qfalse;
774 }
775 if ( Q_stricmp( token.string, "{" ) != 0 ) {
776 return qfalse;
777 }
778
779 while ( 1 ) {
780
781 memset( &token, 0, sizeof( pc_token_t ) );
782
783 if ( !trap_PC_ReadToken( handle, &token ) ) {
784 return qfalse;
785 }
786
787 if ( Q_stricmp( token.string, "}" ) == 0 ) {
788 return qtrue;
789 }
790
791 // font
792 if ( Q_stricmp( token.string, "font" ) == 0 ) {
793 int pointSize;
794 if ( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle,&pointSize ) ) {
795 return qfalse;
796 }
797 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.textFont );
798 uiInfo.uiDC.Assets.fontRegistered = qtrue;
799 continue;
800 }
801
802 if ( Q_stricmp( token.string, "smallFont" ) == 0 ) {
803 int pointSize;
804 if ( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle,&pointSize ) ) {
805 return qfalse;
806 }
807 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.smallFont );
808 continue;
809 }
810
811 if ( Q_stricmp( token.string, "bigFont" ) == 0 ) {
812 int pointSize;
813 if ( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle,&pointSize ) ) {
814 return qfalse;
815 }
816 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.bigFont );
817 continue;
818 }
819
820 // handwriting
821 if ( Q_stricmp( token.string, "handwritingFont" ) == 0 ) {
822 int pointSize;
823 if ( !PC_String_Parse( handle, &tempStr ) || !PC_Int_Parse( handle,&pointSize ) ) {
824 return qfalse;
825 }
826 trap_R_RegisterFont( tempStr, pointSize, &uiInfo.uiDC.Assets.handwritingFont );
827 continue;
828 }
829
830
831 // gradientbar
832 if ( Q_stricmp( token.string, "gradientbar" ) == 0 ) {
833 if ( !PC_String_Parse( handle, &tempStr ) ) {
834 return qfalse;
835 }
836 uiInfo.uiDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( tempStr );
837 continue;
838 }
839
840 // enterMenuSound
841 if ( Q_stricmp( token.string, "menuEnterSound" ) == 0 ) {
842 if ( !PC_String_Parse( handle, &tempStr ) ) {
843 return qfalse;
844 }
845 uiInfo.uiDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr );
846 continue;
847 }
848
849 // exitMenuSound
850 if ( Q_stricmp( token.string, "menuExitSound" ) == 0 ) {
851 if ( !PC_String_Parse( handle, &tempStr ) ) {
852 return qfalse;
853 }
854 uiInfo.uiDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr );
855 continue;
856 }
857
858 // itemFocusSound
859 if ( Q_stricmp( token.string, "itemFocusSound" ) == 0 ) {
860 if ( !PC_String_Parse( handle, &tempStr ) ) {
861 return qfalse;
862 }
863 uiInfo.uiDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr );
864 continue;
865 }
866
867 // menuBuzzSound
868 if ( Q_stricmp( token.string, "menuBuzzSound" ) == 0 ) {
869 if ( !PC_String_Parse( handle, &tempStr ) ) {
870 return qfalse;
871 }
872 uiInfo.uiDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr );
873 continue;
874 }
875
876 if ( Q_stricmp( token.string, "cursor" ) == 0 ) {
877 if ( !PC_String_Parse( handle, &uiInfo.uiDC.Assets.cursorStr ) ) {
878 return qfalse;
879 }
880 uiInfo.uiDC.Assets.cursor = trap_R_RegisterShaderNoMip( uiInfo.uiDC.Assets.cursorStr );
881 continue;
882 }
883
884 if ( Q_stricmp( token.string, "fadeClamp" ) == 0 ) {
885 if ( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.fadeClamp ) ) {
886 return qfalse;
887 }
888 continue;
889 }
890
891 if ( Q_stricmp( token.string, "fadeCycle" ) == 0 ) {
892 if ( !PC_Int_Parse( handle, &uiInfo.uiDC.Assets.fadeCycle ) ) {
893 return qfalse;
894 }
895 continue;
896 }
897
898 if ( Q_stricmp( token.string, "fadeAmount" ) == 0 ) {
899 if ( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.fadeAmount ) ) {
900 return qfalse;
901 }
902 continue;
903 }
904
905 if ( Q_stricmp( token.string, "shadowX" ) == 0 ) {
906 if ( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.shadowX ) ) {
907 return qfalse;
908 }
909 continue;
910 }
911
912 if ( Q_stricmp( token.string, "shadowY" ) == 0 ) {
913 if ( !PC_Float_Parse( handle, &uiInfo.uiDC.Assets.shadowY ) ) {
914 return qfalse;
915 }
916 continue;
917 }
918
919 if ( Q_stricmp( token.string, "shadowColor" ) == 0 ) {
920 if ( !PC_Color_Parse( handle, &uiInfo.uiDC.Assets.shadowColor ) ) {
921 return qfalse;
922 }
923 uiInfo.uiDC.Assets.shadowFadeClamp = uiInfo.uiDC.Assets.shadowColor[3];
924 continue;
925 }
926
927 }
928 return qfalse;
929 }
930
Font_Report(void)931 void Font_Report( void ) {
932 int i;
933 Com_Printf( "Font Info\n" );
934 Com_Printf( "=========\n" );
935 for ( i = 32; i < 96; i++ ) {
936 Com_Printf( "Glyph handle %i: %i\n", i, uiInfo.uiDC.Assets.textFont.glyphs[i].glyph );
937 }
938 }
939
UI_Report(void)940 void UI_Report( void ) {
941 String_Report();
942 //Font_Report();
943
944 }
945
946 void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ( ( format ( printf, 1, 2 ) ) );
UI_ParseMenu(const char * menuFile)947 void UI_ParseMenu( const char *menuFile ) {
948 int handle;
949 pc_token_t token;
950
951 Com_DPrintf( "Parsing menu file: %s\n", menuFile );
952
953 handle = trap_PC_LoadSource( menuFile );
954 if ( !handle ) {
955 return;
956 }
957
958 while ( 1 ) {
959 memset( &token, 0, sizeof( pc_token_t ) );
960 if ( !trap_PC_ReadToken( handle, &token ) ) {
961 break;
962 }
963
964 //if ( Q_stricmp( token, "{" ) ) {
965 // Com_Printf( "Missing { in menu file\n" );
966 // break;
967 //}
968
969 //if ( menuCount == MAX_MENUS ) {
970 // Com_Printf( "Too many menus!\n" );
971 // break;
972 //}
973
974 if ( token.string[0] == '}' ) {
975 break;
976 }
977
978 if ( Q_stricmp( token.string, "assetGlobalDef" ) == 0 ) {
979 if ( Asset_Parse( handle ) ) {
980 continue;
981 } else {
982 break;
983 }
984 }
985
986 if ( Q_stricmp( token.string, "menudef" ) == 0 ) {
987 // start a new menu
988 Menu_New( handle );
989 }
990 }
991 trap_PC_FreeSource( handle );
992 }
993
Load_Menu(int handle)994 qboolean Load_Menu( int handle ) {
995 pc_token_t token;
996
997 if ( !trap_PC_ReadToken( handle, &token ) ) {
998 return qfalse;
999 }
1000 if ( token.string[0] != '{' ) {
1001 return qfalse;
1002 }
1003
1004 while ( 1 ) {
1005
1006 if ( !trap_PC_ReadToken( handle, &token ) ) {
1007 return qfalse;
1008 }
1009
1010 if ( token.string[0] == 0 ) {
1011 return qfalse;
1012 }
1013
1014 if ( token.string[0] == '}' ) {
1015 return qtrue;
1016 }
1017
1018 UI_ParseMenu( token.string );
1019 }
1020 return qfalse;
1021 }
1022
UI_LoadMenus(const char * menuFile,qboolean reset)1023 void UI_LoadMenus( const char *menuFile, qboolean reset ) {
1024 pc_token_t token;
1025 int handle;
1026 int start;
1027
1028 start = trap_Milliseconds();
1029
1030 handle = trap_PC_LoadSource( menuFile );
1031 if ( !handle ) {
1032 Com_Printf( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile );
1033 #ifdef WOLF_SP_DEMO
1034 handle = trap_PC_LoadSource( "ui/menus.txt" );
1035 #else
1036 handle = trap_PC_LoadSource( "ui/demomenus.txt" );
1037 #endif
1038 if ( !handle ) {
1039 trap_Error( S_COLOR_RED "default menu file not found: ui/menus.txt, unable to continue!" );
1040 }
1041 }
1042
1043 ui_new.integer = 1;
1044
1045 if ( reset ) {
1046 Menu_Reset();
1047 }
1048
1049 while ( 1 ) {
1050 if ( !trap_PC_ReadToken( handle, &token ) ) {
1051 break;
1052 }
1053 if ( token.string[0] == 0 || token.string[0] == '}' ) {
1054 break;
1055 }
1056
1057 if ( token.string[0] == '}' ) {
1058 break;
1059 }
1060
1061 if ( Q_stricmp( token.string, "loadmenu" ) == 0 ) {
1062 if ( Load_Menu( handle ) ) {
1063 continue;
1064 } else {
1065 break;
1066 }
1067 }
1068 }
1069
1070 Com_DPrintf( "UI menu load time = %d milli seconds\n", trap_Milliseconds() - start );
1071
1072 trap_PC_FreeSource( handle );
1073 }
1074
1075
1076
1077 /*
1078 ==============
1079 UI_LoadTranslationStrings
1080 ==============
1081 */
1082 #define MAX_BUFFER 20000
UI_LoadTranslationStrings(void)1083 static void UI_LoadTranslationStrings( void ) {
1084 char buffer[MAX_BUFFER];
1085 char *text;
1086 char filename[MAX_QPATH];
1087 fileHandle_t f;
1088 int len, i, numStrings;
1089 char *token;
1090
1091 Com_sprintf( filename, MAX_QPATH, "text/strings.txt" );
1092 len = trap_FS_FOpenFile( filename, &f, FS_READ );
1093 if ( len <= 0 ) {
1094 // CG_Printf( S_COLOR_RED "WARNING: string translation file (strings.txt not found in main/text)\n" );
1095 return;
1096 }
1097 if ( len > MAX_BUFFER ) {
1098 // CG_Error( "%s is too big, make it smaller (max = %i bytes)\n", filename, MAX_BUFFER );
1099 }
1100
1101 // load the file into memory
1102 trap_FS_Read( buffer, len, f );
1103 buffer[len] = 0;
1104 trap_FS_FCloseFile( f );
1105 // parse the list
1106 text = buffer;
1107
1108 numStrings = sizeof( translateStrings ) / sizeof( translateStrings[0] ) - 1;
1109
1110 for ( i = 0; i < numStrings; i++ ) {
1111 token = COM_ParseExt( &text, qtrue );
1112 if ( !token[0] ) {
1113 break;
1114 }
1115 #ifdef Q3_VM // new IORTCW syscall (works for qvms and dlls), but have dlls use vanilla rtcw compatible code
1116 translateStrings[i].localname = (char *)trap_Alloc( strlen( token ) + 1 );
1117 #else
1118 translateStrings[i].localname = (char *)malloc( strlen( token ) + 1 );
1119 #endif
1120 strcpy( translateStrings[i].localname, token );
1121 }
1122 }
1123
1124
UI_Load(void)1125 void UI_Load( void ) {
1126 char lastName[1024];
1127 menuDef_t *menu = Menu_GetFocused();
1128 char *menuSet = UI_Cvar_VariableString( "ui_menuFiles" );
1129 if ( menu && menu->window.name ) {
1130 Q_strncpyz(lastName, menu->window.name, sizeof(lastName));
1131 }
1132 if ( menuSet == NULL || menuSet[0] == '\0' ) {
1133 #ifdef WOLF_SP_DEMO
1134 menuSet = "ui/demomenus.txt";
1135 #else
1136 menuSet = "ui/menus.txt";
1137 #endif
1138 }
1139
1140 String_Init();
1141
1142 // load translation text
1143 UI_LoadTranslationStrings();
1144
1145 // UI_ParseGameInfo("gameinfo.txt");
1146 // UI_LoadArenas();
1147
1148 UI_LoadMenus( menuSet, qtrue );
1149 Menus_CloseAll();
1150 Menus_ActivateByName( lastName );
1151
1152 }
1153
1154 // Convert ui's net source to AS_* used by trap calls.
UI_SourceForLAN(void)1155 int UI_SourceForLAN(void) {
1156 switch (ui_netSource.integer) {
1157 default:
1158 case UIAS_LOCAL:
1159 return AS_LOCAL;
1160 case UIAS_GLOBAL0:
1161 case UIAS_GLOBAL1:
1162 case UIAS_GLOBAL2:
1163 case UIAS_GLOBAL3:
1164 case UIAS_GLOBAL4:
1165 case UIAS_GLOBAL5:
1166 return AS_GLOBAL;
1167 case UIAS_FAVORITES:
1168 return AS_FAVORITES;
1169 }
1170 }
1171
1172 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};
1173 // TTimo: unused
1174 //static int numHandicaps = ARRAY_LEN(handicapValues);
1175
UI_DrawHandicap(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1176 static void UI_DrawHandicap( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1177 int i, h;
1178
1179 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue( "handicap" ) );
1180 i = 20 - h / 5;
1181
1182 Text_Paint( rect->x, rect->y, font, scale, color, handicapValues[i], 0, 0, textStyle );
1183 }
1184
1185 //----(SA) added
1186 /*
1187 ==============
1188 UI_DrawSavegameName
1189 ==============
1190 */
UI_DrawSavegameName(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1191 static void UI_DrawSavegameName( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1192 Text_PaintCenter( rect->x, rect->y, font, scale, color, ui_savegameName.string, textStyle );
1193 }
1194
1195
1196
1197 /*
1198 ==============
1199 UI_DrawClanName
1200 ==============
1201 */
UI_DrawClanName(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1202 static void UI_DrawClanName( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1203 Text_Paint( rect->x, rect->y, font, scale, color, UI_Cvar_VariableString( "ui_teamName" ), 0, 0, textStyle );
1204 }
1205
1206
UI_SetCapFragLimits(qboolean uiVars)1207 static void UI_SetCapFragLimits( qboolean uiVars ) {
1208 int cap = 5;
1209 int frag = 10;
1210 #ifdef MISSIONPACK
1211 if ( uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_OBELISK ) {
1212 cap = 4;
1213 } else if ( uiInfo.gameTypes[ui_gameType.integer].gtEnum == GT_HARVESTER ) {
1214 cap = 15;
1215 }
1216 #endif // #ifdef MISSIONPACK
1217 if ( uiVars ) {
1218 trap_Cvar_Set( "ui_captureLimit", va( "%d", cap ) );
1219 trap_Cvar_Set( "ui_fragLimit", va( "%d", frag ) );
1220 } else {
1221 trap_Cvar_Set( "capturelimit", va( "%d", cap ) );
1222 trap_Cvar_Set( "fraglimit", va( "%d", frag ) );
1223 }
1224 }
1225 // ui_gameType assumes gametype 0 is -1 ALL and will not show
UI_DrawGameType(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1226 static void UI_DrawGameType( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1227 Text_Paint( rect->x, rect->y, font, scale, color, uiInfo.gameTypes[ui_gameType.integer].gameType, 0, 0, textStyle );
1228 }
1229
UI_DrawNetGameType(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1230 static void UI_DrawNetGameType( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1231 if ( ui_netGameType.integer < 0 || ui_netGameType.integer > uiInfo.numGameTypes ) {
1232 trap_Cvar_Set( "ui_netGameType", "0" );
1233 trap_Cvar_Set( "ui_actualNetGameType", "0" );
1234 }
1235 Text_Paint( rect->x, rect->y, font, scale, color, uiInfo.gameTypes[ui_netGameType.integer].gameType, 0, 0, textStyle );
1236 }
1237
UI_DrawJoinGameType(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1238 static void UI_DrawJoinGameType( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1239 if ( ui_joinGameType.integer < 0 || ui_joinGameType.integer > uiInfo.numJoinGameTypes ) {
1240 trap_Cvar_Set( "ui_joinGameType", "0" );
1241 }
1242 Text_Paint( rect->x, rect->y, font, scale, color, uiInfo.joinGameTypes[ui_joinGameType.integer].gameType, 0, 0, textStyle );
1243 }
1244
1245
1246 /*
1247 ==============
1248 UI_SavegameIndexFromName
1249 sorted index in feeder
1250 ==============
1251 */
UI_SavegameIndexFromName(const char * name)1252 static int UI_SavegameIndexFromName( const char *name ) {
1253 int i;
1254 if ( name && *name ) {
1255 for ( i = 0; i < uiInfo.savegameCount; i++ ) {
1256 // if (Q_stricmp(name, uiInfo.savegameList[i].savegameName) == 0) {
1257 if ( Q_stricmp( name, uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[i]].savegameName ) == 0 ) {
1258 return i;
1259 }
1260 }
1261 }
1262 return 0;
1263 }
1264
1265 /*
1266 ==============
1267 UI_SavegameIndexFromName2
1268 return the index in t
1269 ==============
1270 */
UI_SavegameIndexFromName2(const char * name)1271 static int UI_SavegameIndexFromName2( const char *name ) {
1272 int index;
1273 index = UI_SavegameIndexFromName( name );
1274
1275 return uiInfo.savegameStatus.displaySavegames[index];
1276 }
1277
1278 /*
1279 ==============
1280 UI_DrawSaveGameShot
1281 ==============
1282 */
UI_DrawSaveGameShot(rectDef_t * rect,float scale,vec4_t color)1283 static void UI_DrawSaveGameShot( rectDef_t *rect, float scale, vec4_t color ) {
1284 int i;
1285 qhandle_t image;
1286
1287 trap_R_SetColor( color );
1288
1289 if ( !strlen( ui_savegameName.string ) || ui_savegameName.string[0] == '0' ) {
1290 image = trap_R_RegisterShaderNoMip( "menu/art/unknownmap" );
1291 } else {
1292 i = UI_SavegameIndexFromName2( ui_savegameName.string );
1293 // mapName
1294 if ( uiInfo.savegameList[i].sshotImage == -1 ) {
1295 uiInfo.savegameList[i].sshotImage = trap_R_RegisterShaderNoMip( uiInfo.savegameList[i].imageName );
1296 }
1297
1298 image = uiInfo.savegameList[i].sshotImage;
1299 }
1300
1301 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, image );
1302 trap_R_SetColor( NULL );
1303
1304 }
1305
1306
1307 /*
1308 ==============
1309 UI_DrawMessageIcon
1310 ==============
1311 */
1312 // TTimo: unused
1313 /*
1314 //----(SA) added
1315 static void UI_DrawMessageIcon(rectDef_t *rect, float scale, vec4_t color) {
1316 trap_R_SetColor( color );
1317 // UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.savegameList[uiInfo.savegameIndex].sshotImage);
1318 trap_R_SetColor(NULL);
1319 }
1320 */
1321
UI_TeamIndexFromName(const char * name)1322 static int UI_TeamIndexFromName( const char *name ) {
1323 int i;
1324
1325 if ( name && *name ) {
1326 for ( i = 0; i < uiInfo.teamCount; i++ ) {
1327 if ( Q_stricmp( name, uiInfo.teamList[i].teamName ) == 0 ) {
1328 return i;
1329 }
1330 }
1331 }
1332
1333 return 0;
1334
1335 }
1336
1337
1338 /*
1339 ==============
1340 UI_DrawClanLogo
1341 ==============
1342 */
UI_DrawClanLogo(rectDef_t * rect,float scale,vec4_t color)1343 static void UI_DrawClanLogo( rectDef_t *rect, float scale, vec4_t color ) {
1344 int i;
1345 i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
1346 if ( i >= 0 && i < uiInfo.teamCount ) {
1347 trap_R_SetColor( color );
1348
1349 if ( uiInfo.teamList[i].teamIcon == -1 ) {
1350 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
1351 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
1352 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
1353 }
1354
1355 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
1356 trap_R_SetColor( NULL );
1357 }
1358 }
1359
1360 /*
1361 ==============
1362 UI_DrawClanCinematic
1363 ==============
1364 */
UI_DrawClanCinematic(rectDef_t * rect,float scale,vec4_t color)1365 static void UI_DrawClanCinematic( rectDef_t *rect, float scale, vec4_t color ) {
1366 int i;
1367 i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
1368 if ( i >= 0 && i < uiInfo.teamCount ) {
1369
1370 if ( uiInfo.teamList[i].cinematic >= -2 ) {
1371 if ( uiInfo.teamList[i].cinematic == -1 ) {
1372 uiInfo.teamList[i].cinematic = trap_CIN_PlayCinematic( va( "%s.roq", uiInfo.teamList[i].imageName ), 0, 0, 0, 0, ( CIN_loop | CIN_silent ) );
1373 }
1374 if ( uiInfo.teamList[i].cinematic >= 0 ) {
1375 trap_CIN_RunCinematic( uiInfo.teamList[i].cinematic );
1376
1377 if ( ui_fixedAspect.integer ) {
1378 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1379 float scaledx = rect->x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
1380 float scaledw = rect->w * ( 480.0 / 640.0 );
1381
1382 trap_CIN_SetExtents( uiInfo.teamList[i].cinematic, scaledx, rect->y, scaledw, rect->h );
1383 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
1384 float scaledy = rect->y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
1385 float scaledh = rect->h * ( 480.0 / 640.0 );
1386
1387 trap_CIN_SetExtents( uiInfo.teamList[i].cinematic, rect->x, scaledy, rect->w, scaledh );
1388 } else {
1389 trap_CIN_SetExtents( uiInfo.teamList[i].cinematic, rect->x, rect->y, rect->w, rect->h );
1390 }
1391 } else {
1392 trap_CIN_SetExtents( uiInfo.teamList[i].cinematic, rect->x, rect->y, rect->w, rect->h );
1393 }
1394
1395 trap_CIN_DrawCinematic( uiInfo.teamList[i].cinematic );
1396 } else {
1397 uiInfo.teamList[i].cinematic = -2;
1398 }
1399 } else {
1400 trap_R_SetColor( color );
1401 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
1402 trap_R_SetColor( NULL );
1403 }
1404 }
1405
1406 }
1407
1408
UI_DrawPregameCinematic(rectDef_t * rect,float scale,vec4_t color)1409 static void UI_DrawPregameCinematic( rectDef_t *rect, float scale, vec4_t color ) {
1410 if ( uiInfo.previewMovie > -2 ) {
1411 uiInfo.previewMovie = trap_CIN_PlayCinematic( va( "%s.roq", "assault" ), 0, 0, 0, 0, ( CIN_loop | CIN_silent | CIN_system ) );
1412 if ( uiInfo.previewMovie >= 0 ) {
1413 trap_CIN_RunCinematic( uiInfo.previewMovie );
1414
1415 if ( ui_fixedAspect.integer ) {
1416 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1417 float scaledx = rect->x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
1418 float scaledw = rect->w * ( 480.0 / 640.0 );
1419
1420 trap_CIN_SetExtents( uiInfo.previewMovie, scaledx, rect->y, scaledw, rect->h );
1421 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
1422 float scaledy = rect->y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
1423 float scaledh = rect->h * ( 480.0 / 640.0 );
1424
1425 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, scaledy, rect->w, scaledh );
1426 } else {
1427 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h );
1428 }
1429 } else {
1430 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h );
1431 }
1432
1433 trap_CIN_DrawCinematic( uiInfo.previewMovie );
1434 } else {
1435 uiInfo.previewMovie = -2;
1436 }
1437 }
1438
1439 }
1440
UI_DrawPreviewCinematic(rectDef_t * rect,float scale,vec4_t color)1441 static void UI_DrawPreviewCinematic( rectDef_t *rect, float scale, vec4_t color ) {
1442 if ( uiInfo.previewMovie > -2 ) {
1443 uiInfo.previewMovie = trap_CIN_PlayCinematic( va( "%s.roq", uiInfo.movieList[uiInfo.movieIndex] ), 0, 0, 0, 0, ( CIN_loop | CIN_silent ) );
1444 if ( uiInfo.previewMovie >= 0 ) {
1445 trap_CIN_RunCinematic( uiInfo.previewMovie );
1446
1447 if ( ui_fixedAspect.integer ) {
1448 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1449 float scaledx = rect->x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
1450 float scaledw = rect->w * ( 480.0 / 640.0 );
1451
1452 trap_CIN_SetExtents( uiInfo.previewMovie, scaledx, rect->y, scaledw, rect->h );
1453 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
1454 float scaledy = rect->y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
1455 float scaledh = rect->h * ( 480.0 / 640.0 );
1456
1457 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, scaledy, rect->w, scaledh );
1458 } else {
1459 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h );
1460 }
1461 } else {
1462 trap_CIN_SetExtents( uiInfo.previewMovie, rect->x, rect->y, rect->w, rect->h );
1463 }
1464
1465 trap_CIN_DrawCinematic( uiInfo.previewMovie );
1466 } else {
1467 uiInfo.previewMovie = -2;
1468 }
1469 }
1470
1471 }
1472
1473
UI_DrawSkill(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1474 static void UI_DrawSkill( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1475 int i;
1476 i = trap_Cvar_VariableValue( "g_spSkill" );
1477 if ( i < 1 || i > numSkillLevels ) {
1478 i = 1;
1479 }
1480 Text_Paint( rect->x, rect->y, font, scale, color, skillLevels[i - 1],0, 0, textStyle );
1481 }
1482
1483
UI_DrawTeamName(rectDef_t * rect,int font,float scale,vec4_t color,qboolean blue,int textStyle)1484 static void UI_DrawTeamName( rectDef_t *rect, int font, float scale, vec4_t color, qboolean blue, int textStyle ) {
1485 int i;
1486 i = UI_TeamIndexFromName( UI_Cvar_VariableString( ( blue ) ? "ui_blueTeam" : "ui_redTeam" ) );
1487 if ( i >= 0 && i < uiInfo.teamCount ) {
1488 Text_Paint( rect->x, rect->y, font, scale, color, va( "%s: %s", ( blue ) ? "Blue" : "Red", uiInfo.teamList[i].teamName ),0, 0, textStyle );
1489 }
1490 }
1491
UI_DrawTeamMember(rectDef_t * rect,int font,float scale,vec4_t color,qboolean blue,int num,int textStyle)1492 static void UI_DrawTeamMember( rectDef_t *rect, int font, float scale, vec4_t color, qboolean blue, int num, int textStyle ) {
1493 #ifdef MISSIONPACK
1494 // 0 - None
1495 // 1 - Human
1496 // 2..NumCharacters - Bot
1497 int value = trap_Cvar_VariableValue( va( blue ? "ui_blueteam%i" : "ui_redteam%i", num ) );
1498 const char *text;
1499 if ( value <= 0 ) {
1500 text = "Closed";
1501 } else if ( value == 1 ) {
1502 text = "Human";
1503 } else {
1504 value -= 2;
1505
1506 if ( ui_actualNetGameType.integer >= GT_TEAM ) {
1507 if ( value >= uiInfo.characterCount ) {
1508 value = 0;
1509 }
1510 text = uiInfo.characterList[value].name;
1511 } else {
1512 if ( value >= UI_GetNumBots() ) {
1513 value = 0;
1514 }
1515 text = UI_GetBotNameByNumber( value );
1516 }
1517 }
1518 Text_Paint( rect->x, rect->y, font, scale, color, text, 0, 0, textStyle );
1519 #endif // #ifdef MISSIONPACK
1520 }
1521
UI_DrawEffects(rectDef_t * rect,float scale,vec4_t color)1522 static void UI_DrawEffects( rectDef_t *rect, float scale, vec4_t color ) {
1523 UI_DrawHandlePic( rect->x, rect->y - 14, 128, 8, uiInfo.uiDC.Assets.fxBasePic );
1524 UI_DrawHandlePic( rect->x + uiInfo.effectsColor * 16 + 8, rect->y - 16, 16, 12, uiInfo.uiDC.Assets.fxPic[uiInfo.effectsColor] );
1525 }
1526
1527 //----(SA) added
1528 /*
1529 ==============
1530 UI_DrawMapLevelshot
1531 Draws the levelshot for the current map.
1532 ==============
1533 */
UI_DrawMapLevelshot(rectDef_t * rect)1534 static void UI_DrawMapLevelshot( rectDef_t *rect ) {
1535 char levelname[64];
1536 qhandle_t levelshot = 0;
1537
1538 DC->getCVarString( "mapname", levelname, sizeof( levelname ) );
1539
1540 if ( levelname[0] != 0 ) {
1541 levelshot = trap_R_RegisterShaderNoMip( va( "levelshots/%s.tga", levelname ) );
1542 }
1543
1544 if ( !levelshot ) {
1545 levelshot = trap_R_RegisterShaderNoMip( "levelshots/unknownmap.jpg" );
1546 }
1547
1548 // HACK Pillarboxing...Copied from ui_shared.c
1549 if ( ui_fixedAspect.integer ) {
1550 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1551 vec4_t col = {0, 0, 0, 1};
1552 float pillar = 0.5 * ( ( DC->glconfig.vidWidth - ( DC->xscale * 640.0 ) ) / DC->xscale );
1553
1554 UI_SetScreenPlacement(PLACE_LEFT, PLACE_CENTER);
1555 DC->fillRect( 0, 0, pillar + 1, 480, col );
1556 UI_SetScreenPlacement(PLACE_RIGHT, PLACE_CENTER);
1557 DC->fillRect( 640 - pillar, 0, pillar + 1, 480, col );
1558 UI_SetScreenPlacement(PLACE_CENTER, PLACE_CENTER);
1559 }
1560 }
1561
1562 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, levelshot );
1563 }
1564
1565 /*
1566 ==============
1567 CG_HorizontalPercentBar
1568 Generic routine for pretty much all status indicators that show a fractional
1569 value to the palyer by virtue of how full a drawn box is.
1570
1571 flags:
1572 left - 1
1573 center - 2 // direction is 'right' by default and orientation is 'horizontal'
1574 vert - 4
1575 nohudalpha - 8 // don't adjust bar's alpha value by the cg_hudalpha value
1576 bg - 16 // background contrast box (bg set with bgColor of 'NULL' means use default bg color (1,1,1,0.25)
1577 spacing - 32 // some bars use different sorts of spacing when drawing both an inner and outer box
1578
1579 lerp color - 256 // use an average of the start and end colors to set the fill color
1580 ==============
1581 */
1582
1583
1584 // TODO: these flags will be shared, but it was easier to work on stuff if I wasn't changing header files a lot
1585 #define BAR_LEFT 0x0001
1586 #define BAR_CENTER 0x0002
1587 #define BAR_VERT 0x0004
1588 #define BAR_NOHUDALPHA 0x0008
1589 #define BAR_BG 0x0010
1590 // different spacing modes for use w/ BAR_BG
1591 #define BAR_BGSPACING_X0Y5 0x0020
1592 #define BAR_BGSPACING_X0Y0 0x0040
1593
1594 #define BAR_LERP_COLOR 0x0100
1595
1596 #define BAR_BORDERSIZE 2
1597
UI_FilledBar(float x,float y,float w,float h,float * startColor,float * endColor,const float * bgColor,float frac,int flags)1598 void UI_FilledBar( float x, float y, float w, float h, float *startColor, float *endColor, const float *bgColor, float frac, int flags ) {
1599 vec4_t backgroundcolor = {1, 1, 1, 0.25f}, colorAtPos; // colorAtPos is the lerped color if necessary
1600 int indent = BAR_BORDERSIZE;
1601
1602 if ( ( flags & BAR_BG ) && bgColor ) { // BAR_BG set, and color specified, use specified bg color
1603 Vector4Copy( bgColor, backgroundcolor );
1604 }
1605
1606 // hud alpha
1607 if ( !( flags & BAR_NOHUDALPHA ) ) {
1608 startColor[3] *= ui_hudAlpha.value;
1609 if ( endColor ) {
1610 endColor[3] *= ui_hudAlpha.value;
1611 }
1612 backgroundcolor[3] *= ui_hudAlpha.value;
1613 }
1614
1615 if ( flags & BAR_LERP_COLOR ) {
1616 Vector4Average( startColor, endColor, frac, colorAtPos );
1617 }
1618
1619 // background
1620 if ( ( flags & BAR_BG ) ) {
1621 // draw background at full size and shrink the remaining box to fit inside with a border. (alternate border may be specified by a BAR_BGSPACING_xx)
1622 UI_FillRect( x,
1623 y,
1624 w,
1625 h,
1626 backgroundcolor );
1627
1628 if ( flags & BAR_BGSPACING_X0Y0 ) { // fill the whole box (no border)
1629
1630 } else if ( flags & BAR_BGSPACING_X0Y5 ) { // spacing created for weapon heat
1631 indent *= 3;
1632 y += indent;
1633 h -= ( 2 * indent );
1634
1635 } else { // default spacing of 2 units on each side
1636 x += indent;
1637 y += indent;
1638 w -= ( 2 * indent );
1639 h -= ( 2 * indent );
1640 }
1641 }
1642
1643
1644 // adjust for horiz/vertical and draw the fractional box
1645 if ( flags & BAR_VERT ) {
1646 if ( flags & BAR_LEFT ) { // TODO: remember to swap colors on the ends here
1647 y += ( h * ( 1 - frac ) );
1648 } else if ( flags & BAR_CENTER ) {
1649 y += ( h * ( 1 - frac ) / 2 );
1650 }
1651
1652 if ( flags & BAR_LERP_COLOR ) {
1653 UI_FillRect( x, y, w, h * frac, colorAtPos );
1654 } else {
1655 UI_FillRect( x, y, w, h * frac, startColor );
1656 }
1657
1658 } else {
1659
1660 if ( flags & BAR_LEFT ) { // TODO: remember to swap colors on the ends here
1661 x += ( w * ( 1 - frac ) );
1662 } else if ( flags & BAR_CENTER ) {
1663 x += ( w * ( 1 - frac ) / 2 );
1664 }
1665
1666 if ( flags & BAR_LERP_COLOR ) {
1667 UI_FillRect( x, y, w * frac, h, colorAtPos );
1668 } else {
1669 UI_FillRect( x, y, w * frac, h, startColor );
1670 }
1671 }
1672
1673 }
1674
1675
1676
1677 /*
1678 ==============
1679 UI_DrawLoadStatus
1680 ==============
1681 */
UI_DrawLoadStatus(rectDef_t * rect,vec4_t color,int align)1682 static void UI_DrawLoadStatus( rectDef_t *rect, vec4_t color, int align ) {
1683 int expectedHunk;
1684 float percentDone = 0.0f;
1685 char hunkBuf[MAX_QPATH];
1686 int flags = 0;
1687
1688 if ( align != HUD_HORIZONTAL ) {
1689 flags |= 4; // BAR_VERT
1690 // flags|=1; // BAR_LEFT (left, when vertical means grow 'up')
1691 }
1692
1693 flags |= 16; // BAR_BG - draw the filled contrast box
1694
1695 trap_Cvar_VariableStringBuffer( "com_expectedhunkusage", hunkBuf, MAX_QPATH );
1696 expectedHunk = atoi( hunkBuf );
1697
1698 if ( expectedHunk > 0 ) {
1699 percentDone = (float)( ui_hunkUsed.integer ) / (float)( expectedHunk );
1700 if ( percentDone > 0.97 ) { // never actually show 100%, since we are not in the game yet
1701 percentDone = 0.97;
1702 }
1703
1704 UI_FilledBar( rect->x, rect->y, rect->w, rect->h, color, NULL, NULL, percentDone, flags ); // flags (BAR_CENTER|BAR_VERT|BAR_LERP_COLOR)
1705 } else {
1706 // Text_Paint( rect->x, rect->y, UI_FONT_DEFAULT, 0.2f, color, "Please Wait...", 0, 0, 0);
1707 Text_Paint( rect->x, rect->y, UI_FONT_DEFAULT, 0.2f, color, DC->getTranslatedString( "pleasewait" ), 0, 0, 0 );
1708 }
1709
1710 }
1711 //----(SA) end
1712
1713
UI_DrawMapPreview(rectDef_t * rect,float scale,vec4_t color,qboolean net)1714 static void UI_DrawMapPreview( rectDef_t *rect, float scale, vec4_t color, qboolean net ) {
1715 int map = ( net ) ? ui_currentNetMap.integer : ui_currentMap.integer;
1716 if ( map < 0 || map > uiInfo.mapCount ) {
1717 if ( net ) {
1718 ui_currentNetMap.integer = 0;
1719 trap_Cvar_Set( "ui_currentNetMap", "0" );
1720 } else {
1721 ui_currentMap.integer = 0;
1722 trap_Cvar_Set( "ui_currentMap", "0" );
1723 }
1724 map = 0;
1725 }
1726
1727 if ( uiInfo.mapList[map].levelShot == -1 ) {
1728 uiInfo.mapList[map].levelShot = trap_R_RegisterShaderNoMip( uiInfo.mapList[map].imageName );
1729 }
1730
1731 if ( uiInfo.mapList[map].levelShot > 0 ) {
1732 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.mapList[map].levelShot );
1733 } else {
1734 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip( "menu/art/unknownmap" ) );
1735 }
1736 }
1737
1738
UI_DrawMapTimeToBeat(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1739 static void UI_DrawMapTimeToBeat( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1740 int minutes, seconds, time;
1741 if ( ui_currentMap.integer < 0 || ui_currentMap.integer > uiInfo.mapCount ) {
1742 ui_currentMap.integer = 0;
1743 trap_Cvar_Set( "ui_currentMap", "0" );
1744 }
1745
1746 time = uiInfo.mapList[ui_currentMap.integer].timeToBeat[uiInfo.gameTypes[ui_gameType.integer].gtEnum];
1747
1748 minutes = time / 60;
1749 seconds = time % 60;
1750
1751 Text_Paint( rect->x, rect->y, font, scale, color, va( "%02i:%02i", minutes, seconds ), 0, 0, textStyle );
1752 }
1753
1754
1755
UI_DrawMapCinematic(rectDef_t * rect,float scale,vec4_t color,qboolean net)1756 static void UI_DrawMapCinematic( rectDef_t *rect, float scale, vec4_t color, qboolean net ) {
1757
1758 int map = ( net ) ? ui_currentNetMap.integer : ui_currentMap.integer;
1759 if ( map < 0 || map > uiInfo.mapCount ) {
1760 if ( net ) {
1761 ui_currentNetMap.integer = 0;
1762 trap_Cvar_Set( "ui_currentNetMap", "0" );
1763 } else {
1764 ui_currentMap.integer = 0;
1765 trap_Cvar_Set( "ui_currentMap", "0" );
1766 }
1767 map = 0;
1768 }
1769
1770 if ( uiInfo.mapList[map].cinematic >= -1 ) {
1771 if ( uiInfo.mapList[map].cinematic == -1 ) {
1772 uiInfo.mapList[map].cinematic = trap_CIN_PlayCinematic( va( "%s.roq", uiInfo.mapList[map].mapLoadName ), 0, 0, 0, 0, ( CIN_loop | CIN_silent ) );
1773 }
1774 if ( uiInfo.mapList[map].cinematic >= 0 ) {
1775 trap_CIN_RunCinematic( uiInfo.mapList[map].cinematic );
1776
1777 if ( ui_fixedAspect.integer ) {
1778 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1779 float scaledx = rect->x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
1780 float scaledw = rect->w * ( 480.0 / 640.0 );
1781
1782 trap_CIN_SetExtents( uiInfo.mapList[map].cinematic, scaledx, rect->y, scaledw, rect->h );
1783 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
1784 float scaledy = rect->y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
1785 float scaledh = rect->h * ( 480.0 / 640.0 );
1786
1787 trap_CIN_SetExtents( uiInfo.mapList[map].cinematic, rect->x, scaledy, rect->w, scaledh );
1788 } else {
1789 trap_CIN_SetExtents( uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h );
1790 }
1791 } else {
1792 trap_CIN_SetExtents( uiInfo.mapList[map].cinematic, rect->x, rect->y, rect->w, rect->h );
1793 }
1794
1795 trap_CIN_DrawCinematic( uiInfo.mapList[map].cinematic );
1796 } else {
1797 uiInfo.mapList[map].cinematic = -2;
1798 }
1799 } else {
1800 UI_DrawMapPreview( rect, scale, color, net );
1801 }
1802 }
1803
1804
1805
1806 static qboolean updateModel = qtrue;
1807 static qboolean q3Model = qfalse;
1808
UI_DrawPlayerModel(rectDef_t * rect)1809 static void UI_DrawPlayerModel( rectDef_t *rect ) {
1810 static playerInfo_t info;
1811 char model[MAX_QPATH];
1812 char team[256];
1813 char head[256];
1814 vec3_t viewangles;
1815 static vec3_t moveangles = { 0, 0, 0 };
1816
1817 if ( trap_Cvar_VariableValue( "ui_Q3Model" ) ) {
1818 // Q_strncpyz(model, UI_Cvar_VariableString("model"), sizeof(model));
1819 strcpy( model, "multi" );
1820 Q_strncpyz(head, UI_Cvar_VariableString("headmodel"), sizeof(head));
1821 if ( !q3Model ) {
1822 q3Model = qtrue;
1823 updateModel = qtrue;
1824 }
1825 team[0] = '\0';
1826 } else {
1827 Q_strncpyz(model, UI_Cvar_VariableString("team_model"), sizeof(model));
1828 Q_strncpyz(head, UI_Cvar_VariableString("team_headmodel"), sizeof(head));
1829 Q_strncpyz(team, UI_Cvar_VariableString("ui_teamName"), sizeof(team));
1830 if ( q3Model ) {
1831 q3Model = qfalse;
1832 updateModel = qtrue;
1833 }
1834 }
1835
1836 moveangles[YAW] += 1; // NERVE - SMF - TEMPORARY
1837
1838 // compare new cvars to old cvars and see if we need to update
1839 {
1840 int v1, v2;
1841
1842 v1 = trap_Cvar_VariableValue( "mp_team" );
1843 v2 = trap_Cvar_VariableValue( "ui_prevTeam" );
1844 if ( v1 != v2 ) {
1845 trap_Cvar_Set( "ui_prevTeam", va( "%i", v1 ) );
1846 updateModel = qtrue;
1847 }
1848
1849 v1 = trap_Cvar_VariableValue( "mp_playerType" );
1850 v2 = trap_Cvar_VariableValue( "ui_prevClass" );
1851 if ( v1 != v2 ) {
1852 trap_Cvar_Set( "ui_prevClass", va( "%i", v1 ) );
1853 updateModel = qtrue;
1854 }
1855
1856 v1 = trap_Cvar_VariableValue( "mp_weapon" );
1857 v2 = trap_Cvar_VariableValue( "ui_prevWeapon" );
1858 if ( v1 != v2 ) {
1859 trap_Cvar_Set( "ui_prevWeapon", va( "%i", v1 ) );
1860 updateModel = qtrue;
1861 }
1862 }
1863
1864 if ( updateModel ) { // NERVE - SMF - TEMPORARY
1865 memset( &info, 0, sizeof( playerInfo_t ) );
1866 viewangles[YAW] = 180 - 10;
1867 viewangles[PITCH] = 0;
1868 viewangles[ROLL] = 0;
1869 // VectorClear( moveangles );
1870 #ifdef MISSIONPACK
1871 UI_PlayerInfo_SetModel( &info, model, head, team );
1872 #else
1873 UI_PlayerInfo_SetModel( &info, model );
1874 #endif // MISSIONPACK
1875 UI_PlayerInfo_SetInfo( &info, LEGS_IDLE, TORSO_STAND, viewangles, moveangles, -1, qfalse );
1876 // UI_RegisterClientModelname( &info, model, head, team);
1877 updateModel = qfalse;
1878 } else {
1879 VectorCopy( moveangles, info.moveAngles );
1880 }
1881
1882 // info.moveAngles[YAW] += 1;
1883 // UI_PlayerInfo_SetInfo( &info, LEGS_IDLE, TORSO_STAND, viewangles, moveangles, WP_MP40, qfalse );
1884 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info, uiInfo.uiDC.realTime / 2 );
1885
1886 }
1887
UI_DrawNetSource(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1888 static void UI_DrawNetSource( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1889 if ( ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources /*uiInfo.numGameTypes*/ ) {
1890 ui_netSource.integer = 0;
1891 }
1892 Text_Paint( rect->x, rect->y, font, scale, color, va( "Source: %s", netSources[ui_netSource.integer] ), 0, 0, textStyle );
1893 }
1894
UI_DrawNetMapPreview(rectDef_t * rect,float scale,vec4_t color)1895 static void UI_DrawNetMapPreview( rectDef_t *rect, float scale, vec4_t color ) {
1896
1897 if ( uiInfo.serverStatus.currentServerPreview > 0 ) {
1898 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.serverStatus.currentServerPreview );
1899 } else {
1900 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, trap_R_RegisterShaderNoMip( "menu/art/unknownmap" ) );
1901 }
1902 }
1903
UI_DrawNetMapCinematic(rectDef_t * rect,float scale,vec4_t color)1904 static void UI_DrawNetMapCinematic( rectDef_t *rect, float scale, vec4_t color ) {
1905 if ( ui_currentNetMap.integer < 0 || ui_currentNetMap.integer > uiInfo.mapCount ) {
1906 ui_currentNetMap.integer = 0;
1907 trap_Cvar_Set( "ui_currentNetMap", "0" );
1908 }
1909
1910 if ( uiInfo.serverStatus.currentServerCinematic >= 0 ) {
1911 trap_CIN_RunCinematic( uiInfo.serverStatus.currentServerCinematic );
1912
1913 if ( ui_fixedAspect.integer ) {
1914 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
1915 float scaledx = rect->x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
1916 float scaledw = rect->w * ( 480.0 / 640.0 );
1917
1918 trap_CIN_SetExtents( uiInfo.serverStatus.currentServerCinematic, scaledx, rect->y, scaledw, rect->h );
1919 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
1920 float scaledy = rect->y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
1921 float scaledh = rect->h * ( 480.0 / 640.0 );
1922
1923 trap_CIN_SetExtents( uiInfo.serverStatus.currentServerCinematic, rect->x, scaledy, rect->w, scaledh );
1924 } else {
1925 trap_CIN_SetExtents( uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h );
1926 }
1927 } else {
1928 trap_CIN_SetExtents( uiInfo.serverStatus.currentServerCinematic, rect->x, rect->y, rect->w, rect->h );
1929 }
1930
1931 trap_CIN_DrawCinematic( uiInfo.serverStatus.currentServerCinematic );
1932 } else {
1933 UI_DrawNetMapPreview( rect, scale, color );
1934 }
1935 }
1936
1937
1938
UI_DrawNetFilter(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1939 static void UI_DrawNetFilter( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1940 if ( ui_serverFilterType.integer < 0 || ui_serverFilterType.integer >= numServerFilters ) {
1941 ui_serverFilterType.integer = 0;
1942 }
1943 Text_Paint( rect->x, rect->y, font, scale, color, va( "Filter: %s", serverFilters[ui_serverFilterType.integer].description ), 0, 0, textStyle );
1944 }
1945
1946
UI_DrawTier(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1947 static void UI_DrawTier( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1948 int i;
1949 i = trap_Cvar_VariableValue( "ui_currentTier" );
1950 if ( i < 0 || i >= uiInfo.tierCount ) {
1951 i = 0;
1952 }
1953 Text_Paint( rect->x, rect->y, font, scale, color, va( "Tier: %s", uiInfo.tierList[i].tierName ),0, 0, textStyle );
1954 }
1955
UI_DrawTierMap(rectDef_t * rect,int index)1956 static void UI_DrawTierMap( rectDef_t *rect, int index ) {
1957 int i;
1958 i = trap_Cvar_VariableValue( "ui_currentTier" );
1959 if ( i < 0 || i >= uiInfo.tierCount ) {
1960 i = 0;
1961 }
1962
1963 if ( uiInfo.tierList[i].mapHandles[index] == -1 ) {
1964 uiInfo.tierList[i].mapHandles[index] = trap_R_RegisterShaderNoMip( va( "levelshots/%s", uiInfo.tierList[i].maps[index] ) );
1965 }
1966
1967 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.tierList[i].mapHandles[index] );
1968 }
1969
UI_EnglishMapName(const char * map)1970 static const char *UI_EnglishMapName( const char *map ) {
1971 int i;
1972 for ( i = 0; i < uiInfo.mapCount; i++ ) {
1973 if ( Q_stricmp( map, uiInfo.mapList[i].mapLoadName ) == 0 ) {
1974 return uiInfo.mapList[i].mapName;
1975 }
1976 }
1977 return "";
1978 }
1979
UI_DrawTierMapName(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1980 static void UI_DrawTierMapName( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1981 int i, j;
1982 i = trap_Cvar_VariableValue( "ui_currentTier" );
1983 if ( i < 0 || i >= uiInfo.tierCount ) {
1984 i = 0;
1985 }
1986 j = trap_Cvar_VariableValue( "ui_currentMap" );
1987 if ( j < 0 || j >= MAPS_PER_TIER ) {
1988 j = 0;
1989 }
1990
1991 Text_Paint( rect->x, rect->y, font, scale, color, UI_EnglishMapName( uiInfo.tierList[i].maps[j] ), 0, 0, textStyle );
1992 }
1993
UI_DrawTierGameType(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)1994 static void UI_DrawTierGameType( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
1995 int i, j;
1996 i = trap_Cvar_VariableValue( "ui_currentTier" );
1997 if ( i < 0 || i >= uiInfo.tierCount ) {
1998 i = 0;
1999 }
2000 j = trap_Cvar_VariableValue( "ui_currentMap" );
2001 if ( j < 0 || j >= MAPS_PER_TIER ) {
2002 j = 0;
2003 }
2004
2005 Text_Paint( rect->x, rect->y, font, scale, color, uiInfo.gameTypes[uiInfo.tierList[i].gameTypes[j]].gameType, 0, 0, textStyle );
2006 }
2007
2008 // TTimo: unused
2009 /*
2010 static const char *UI_OpponentLeaderName( void ) {
2011 int i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_opponentName"));
2012 return uiInfo.teamList[i].teamMembers[0];
2013 }
2014
2015 static const char *UI_AIFromName(const char *name) {
2016 int j;
2017 for (j = 0; j < uiInfo.aliasCount; j++) {
2018 if (Q_stricmp(uiInfo.aliasList[j].name, name) == 0) {
2019 return uiInfo.aliasList[j].ai;
2020 }
2021 }
2022 return "James";
2023 }
2024
2025 static const int UI_AIIndex(const char *name) {
2026 int j;
2027 for (j = 0; j < uiInfo.characterCount; j++) {
2028 if (Q_stricmp(name, uiInfo.characterList[j].name) == 0) {
2029 return j;
2030 }
2031 }
2032 return 0;
2033 }
2034
2035 static const int UI_AIIndexFromName(const char *name) {
2036 int j;
2037 for (j = 0; j < uiInfo.aliasCount; j++) {
2038 if (Q_stricmp(uiInfo.aliasList[j].name, name) == 0) {
2039 return UI_AIIndex(uiInfo.aliasList[j].ai);
2040 }
2041 }
2042 return 0;
2043 }
2044
2045 static const char *UI_OpponentLeaderHead( void ) {
2046 const char *leader = UI_OpponentLeaderName();
2047 return UI_AIFromName(leader);
2048 }
2049
2050 static const char *UI_OpponentLeaderModel( void ) {
2051 int i;
2052 const char *head = UI_OpponentLeaderHead();
2053 for (i = 0; i < uiInfo.characterCount; i++) {
2054 if (Q_stricmp(head, uiInfo.characterList[i].name) == 0) {
2055 if (uiInfo.characterList[i].female) {
2056 return "Janet";
2057 } else {
2058 return "James";
2059 }
2060 }
2061 }
2062 return "James";
2063 }
2064 */
2065
2066 static qboolean updateOpponentModel = qtrue;
UI_DrawOpponent(rectDef_t * rect)2067 static void UI_DrawOpponent( rectDef_t *rect ) {
2068 static playerInfo_t info2;
2069 char model[MAX_QPATH];
2070 char headmodel[MAX_QPATH];
2071 vec3_t viewangles;
2072 vec3_t moveangles;
2073
2074 if ( updateOpponentModel ) {
2075
2076 Q_strncpyz(model, UI_Cvar_VariableString("ui_opponentModel"), sizeof(model));
2077 Q_strncpyz(headmodel, UI_Cvar_VariableString("ui_opponentModel"), sizeof(headmodel));
2078
2079 memset( &info2, 0, sizeof( playerInfo_t ) );
2080 viewangles[YAW] = 180 - 10;
2081 viewangles[PITCH] = 0;
2082 viewangles[ROLL] = 0;
2083 VectorClear( moveangles );
2084 #ifdef MISSIONPACK
2085 UI_PlayerInfo_SetModel( &info2, model, headmodel, "" );
2086 #else
2087 UI_PlayerInfo_SetModel( &info2, model );
2088 #endif // #ifdef MISSIONPACK
2089 UI_PlayerInfo_SetInfo( &info2, LEGS_IDLE, TORSO_STAND, viewangles, vec3_origin, WP_MP40, qfalse );
2090 #ifdef MISSIONPACK
2091 UI_RegisterClientModelname( &info2, model, headmodel, team );
2092 #else
2093 UI_RegisterClientModelname( &info2, model );
2094 #endif // #ifdef MISSIONPACK
2095 updateOpponentModel = qfalse;
2096 }
2097
2098 UI_DrawPlayer( rect->x, rect->y, rect->w, rect->h, &info2, uiInfo.uiDC.realTime / 2 );
2099
2100 }
2101
UI_NextOpponent(void)2102 static void UI_NextOpponent( void ) {
2103 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
2104 int j = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
2105 i++;
2106 if ( i >= uiInfo.teamCount ) {
2107 i = 0;
2108 }
2109 if ( i == j ) {
2110 i++;
2111 if ( i >= uiInfo.teamCount ) {
2112 i = 0;
2113 }
2114 }
2115 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );
2116 }
2117
UI_PriorOpponent(void)2118 static void UI_PriorOpponent( void ) {
2119 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
2120 int j = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
2121 i--;
2122 if ( i < 0 ) {
2123 i = uiInfo.teamCount - 1;
2124 }
2125 if ( i == j ) {
2126 i--;
2127 if ( i < 0 ) {
2128 i = uiInfo.teamCount - 1;
2129 }
2130 }
2131 trap_Cvar_Set( "ui_opponentName", uiInfo.teamList[i].teamName );
2132 }
2133
UI_DrawPlayerLogo(rectDef_t * rect,vec3_t color)2134 static void UI_DrawPlayerLogo( rectDef_t *rect, vec3_t color ) {
2135 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
2136
2137 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2138 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2139 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2140 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2141 }
2142
2143 trap_R_SetColor( color );
2144 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
2145 trap_R_SetColor( NULL );
2146 }
2147
UI_DrawPlayerLogoMetal(rectDef_t * rect,vec3_t color)2148 static void UI_DrawPlayerLogoMetal( rectDef_t *rect, vec3_t color ) {
2149 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
2150 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2151 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2152 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2153 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2154 }
2155
2156 trap_R_SetColor( color );
2157 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );
2158 trap_R_SetColor( NULL );
2159 }
2160
UI_DrawPlayerLogoName(rectDef_t * rect,vec3_t color)2161 static void UI_DrawPlayerLogoName( rectDef_t *rect, vec3_t color ) {
2162 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
2163 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2164 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2165 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2166 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2167 }
2168
2169 trap_R_SetColor( color );
2170 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );
2171 trap_R_SetColor( NULL );
2172 }
2173
UI_DrawOpponentLogo(rectDef_t * rect,vec3_t color)2174 static void UI_DrawOpponentLogo( rectDef_t *rect, vec3_t color ) {
2175 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
2176 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2177 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2178 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2179 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2180 }
2181
2182 trap_R_SetColor( color );
2183 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon );
2184 trap_R_SetColor( NULL );
2185 }
2186
UI_DrawOpponentLogoMetal(rectDef_t * rect,vec3_t color)2187 static void UI_DrawOpponentLogoMetal( rectDef_t *rect, vec3_t color ) {
2188 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
2189 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2190 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2191 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2192 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2193 }
2194
2195 trap_R_SetColor( color );
2196 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Metal );
2197 trap_R_SetColor( NULL );
2198 }
2199
UI_DrawOpponentLogoName(rectDef_t * rect,vec3_t color)2200 static void UI_DrawOpponentLogoName( rectDef_t *rect, vec3_t color ) {
2201 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
2202 if ( uiInfo.teamList[i].teamIcon == -1 ) {
2203 uiInfo.teamList[i].teamIcon = trap_R_RegisterShaderNoMip( uiInfo.teamList[i].imageName );
2204 uiInfo.teamList[i].teamIcon_Metal = trap_R_RegisterShaderNoMip( va( "%s_metal",uiInfo.teamList[i].imageName ) );
2205 uiInfo.teamList[i].teamIcon_Name = trap_R_RegisterShaderNoMip( va( "%s_name", uiInfo.teamList[i].imageName ) );
2206 }
2207
2208 trap_R_SetColor( color );
2209 UI_DrawHandlePic( rect->x, rect->y, rect->w, rect->h, uiInfo.teamList[i].teamIcon_Name );
2210 trap_R_SetColor( NULL );
2211 }
2212
UI_DrawAllMapsSelection(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle,qboolean net)2213 static void UI_DrawAllMapsSelection( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle, qboolean net ) {
2214 #ifdef MISSIONPACK
2215 int map = ( net ) ? ui_currentNetMap.integer : ui_currentMap.integer;
2216 if ( map >= 0 && map < uiInfo.mapCount ) {
2217 Text_Paint( rect->x, rect->y, font, scale, color, uiInfo.mapList[map].mapName, 0, 0, textStyle );
2218 }
2219 #endif // #ifdef MISSIONPACK
2220 }
2221
UI_DrawOpponentName(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2222 static void UI_DrawOpponentName( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2223 Text_Paint( rect->x, rect->y, font, scale, color, UI_Cvar_VariableString( "ui_opponentName" ), 0, 0, textStyle );
2224 }
2225
2226
UI_OwnerDrawWidth(int ownerDraw,int font,float scale)2227 static int UI_OwnerDrawWidth( int ownerDraw, int font, float scale ) {
2228 int i, h, value;
2229 const char *text;
2230 const char *s = NULL;
2231
2232 switch ( ownerDraw ) {
2233 case UI_HANDICAP:
2234 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue( "handicap" ) );
2235 i = 20 - h / 5;
2236 s = handicapValues[i];
2237 break;
2238
2239 //----(SA) added
2240 case UI_SAVEGAMENAME:
2241 s = ui_savegameName.string;
2242 break;
2243
2244 case UI_SAVEGAMEINFO:
2245 i = UI_SavegameIndexFromName2( ui_savegameName.string );
2246 s = uiInfo.savegameList[i].savegameInfoText;
2247 break;
2248 //----(SA) end
2249
2250 case UI_CLANNAME:
2251 s = UI_Cvar_VariableString( "ui_teamName" );
2252 break;
2253 case UI_GAMETYPE:
2254 s = uiInfo.gameTypes[ui_gameType.integer].gameType;
2255 break;
2256 case UI_SKILL:
2257 i = trap_Cvar_VariableValue( "g_spSkill" );
2258 if ( i < 1 || i > numSkillLevels ) {
2259 i = 1;
2260 }
2261 s = skillLevels[i - 1];
2262 break;
2263 case UI_BLUETEAMNAME:
2264 i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_blueTeam" ) );
2265 if ( i >= 0 && i < uiInfo.teamCount ) {
2266 s = va( "%s: %s", "Blue", uiInfo.teamList[i].teamName );
2267 }
2268 break;
2269 case UI_REDTEAMNAME:
2270 i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_redTeam" ) );
2271 if ( i >= 0 && i < uiInfo.teamCount ) {
2272 s = va( "%s: %s", "Red", uiInfo.teamList[i].teamName );
2273 }
2274 break;
2275 case UI_BLUETEAM1:
2276 case UI_BLUETEAM2:
2277 case UI_BLUETEAM3:
2278 case UI_BLUETEAM4:
2279 case UI_BLUETEAM5:
2280 value = trap_Cvar_VariableValue( va( "ui_blueteam%i", ownerDraw - UI_BLUETEAM1 + 1 ) );
2281 if ( value <= 0 ) {
2282 text = "Closed";
2283 } else if ( value == 1 ) {
2284 text = "Human";
2285 } else {
2286 value -= 2;
2287 if ( value >= uiInfo.aliasCount ) {
2288 value = 0;
2289 }
2290 text = uiInfo.aliasList[value].name;
2291 }
2292 s = va( "%i. %s", ownerDraw - UI_BLUETEAM1 + 1, text );
2293 break;
2294 case UI_REDTEAM1:
2295 case UI_REDTEAM2:
2296 case UI_REDTEAM3:
2297 case UI_REDTEAM4:
2298 case UI_REDTEAM5:
2299 value = trap_Cvar_VariableValue( va( "ui_redteam%i", ownerDraw - UI_REDTEAM1 + 1 ) );
2300 if ( value <= 0 ) {
2301 text = "Closed";
2302 } else if ( value == 1 ) {
2303 text = "Human";
2304 } else {
2305 value -= 2;
2306 if ( value >= uiInfo.aliasCount ) {
2307 value = 0;
2308 }
2309 text = uiInfo.aliasList[value].name;
2310 }
2311 s = va( "%i. %s", ownerDraw - UI_REDTEAM1 + 1, text );
2312 break;
2313 case UI_NETSOURCE:
2314 if (ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources) {
2315 ui_netSource.integer = 0;
2316 }
2317 s = va( "Source: %s", netSources[ui_netSource.integer] );
2318 break;
2319 case UI_NETFILTER:
2320 if ( ui_serverFilterType.integer < 0 || ui_serverFilterType.integer >= numServerFilters ) {
2321 ui_serverFilterType.integer = 0;
2322 }
2323 s = va( "Filter: %s", serverFilters[ui_serverFilterType.integer].description );
2324 break;
2325 case UI_TIER:
2326 break;
2327 case UI_TIER_MAPNAME:
2328 break;
2329 case UI_TIER_GAMETYPE:
2330 break;
2331 case UI_ALLMAPS_SELECTION:
2332 break;
2333 case UI_OPPONENT_NAME:
2334 break;
2335 case UI_KEYBINDSTATUS:
2336 if ( Display_KeyBindPending() ) {
2337 // s = "Waiting for new key... Press ESCAPE to cancel";
2338 s = DC->getTranslatedString( "keywait" );
2339 } else {
2340 // s = "Press ENTER or CLICK to change, Press BACKSPACE to clear";
2341 s = DC->getTranslatedString( "keychange" );
2342 }
2343 break;
2344 case UI_SERVERREFRESHDATE:
2345 #ifdef MISSIONPACK
2346 s = UI_Cvar_VariableString( va( "ui_lastServerRefresh_%i", ui_netSource.integer ) );
2347 #endif // #ifdef MISSIONPACK
2348 break;
2349 default:
2350 break;
2351 }
2352
2353 if ( s ) {
2354 return Text_Width( s, font, scale, 0 );
2355 }
2356 return 0;
2357 }
2358
UI_DrawBotName(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2359 static void UI_DrawBotName( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2360 #ifdef MISSIONPACK
2361 int value = uiInfo.botIndex;
2362 int game = trap_Cvar_VariableValue( "g_gametype" );
2363 const char *text;
2364 if ( game >= GT_TEAM ) {
2365 text = uiInfo.characterList[value].name;
2366 } else {
2367 text = UI_GetBotNameByNumber( value );
2368 }
2369 Text_Paint( rect->x, rect->y, font, scale, color, text, 0, 0, textStyle );
2370 #endif // #ifdef MISSIONPACK
2371 }
2372
UI_DrawBotSkill(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2373 static void UI_DrawBotSkill( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2374 if ( uiInfo.skillIndex >= 0 && uiInfo.skillIndex < numSkillLevels ) {
2375 Text_Paint( rect->x, rect->y, font, scale, color, skillLevels[uiInfo.skillIndex], 0, 0, textStyle );
2376 }
2377 }
2378
UI_DrawRedBlue(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2379 static void UI_DrawRedBlue( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2380 Text_Paint( rect->x, rect->y, font, scale, color, ( uiInfo.redBlue == 0 ) ? "Red" : "Blue", 0, 0, textStyle );
2381 }
2382
UI_DrawCrosshair(rectDef_t * rect,float scale,vec4_t color)2383 static void UI_DrawCrosshair( rectDef_t *rect, float scale, vec4_t color ) {
2384 int ch;
2385 ch = ( uiInfo.currentCrosshair % NUM_CROSSHAIRS );
2386
2387 if ( !ch ) {
2388 return;
2389 }
2390
2391 trap_R_SetColor( color );
2392 UI_DrawHandlePic( rect->x, rect->y - rect->h, rect->w, rect->h, uiInfo.uiDC.Assets.crosshairShader[ch] );
2393 trap_R_SetColor( NULL );
2394 }
2395
2396 /*
2397 ===============
2398 UI_BuildPlayerList
2399 ===============
2400 */
UI_BuildPlayerList(void)2401 static void UI_BuildPlayerList( void ) {
2402 uiClientState_t cs;
2403 int n, count, team, team2, playerTeamNumber;
2404 char info[MAX_INFO_STRING];
2405
2406 trap_GetClientState( &cs );
2407 trap_GetConfigString( CS_PLAYERS + cs.clientNum, info, MAX_INFO_STRING );
2408 uiInfo.playerNumber = cs.clientNum;
2409 uiInfo.teamLeader = atoi( Info_ValueForKey( info, "tl" ) );
2410 team = atoi( Info_ValueForKey( info, "t" ) );
2411 trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) );
2412 count = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
2413 uiInfo.playerCount = 0;
2414 uiInfo.myTeamCount = 0;
2415 playerTeamNumber = 0;
2416 for ( n = 0; n < count; n++ ) {
2417 trap_GetConfigString( CS_PLAYERS + n, info, MAX_INFO_STRING );
2418
2419 if ( info[0] ) {
2420 Q_strncpyz( uiInfo.playerNames[uiInfo.playerCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
2421 Q_CleanStr( uiInfo.playerNames[uiInfo.playerCount] );
2422 uiInfo.playerCount++;
2423 team2 = atoi( Info_ValueForKey( info, "t" ) );
2424 if ( team2 == team ) {
2425 Q_strncpyz( uiInfo.teamNames[uiInfo.myTeamCount], Info_ValueForKey( info, "n" ), MAX_NAME_LENGTH );
2426 Q_CleanStr( uiInfo.teamNames[uiInfo.myTeamCount] );
2427 uiInfo.teamClientNums[uiInfo.myTeamCount] = n;
2428 if ( uiInfo.playerNumber == n ) {
2429 playerTeamNumber = uiInfo.myTeamCount;
2430 }
2431 uiInfo.myTeamCount++;
2432 }
2433 }
2434 }
2435
2436 if ( !uiInfo.teamLeader ) {
2437 trap_Cvar_Set( "cg_selectedPlayer", va( "%d", playerTeamNumber ) );
2438 }
2439
2440 n = trap_Cvar_VariableValue( "cg_selectedPlayer" );
2441 if ( n < 0 || n > uiInfo.myTeamCount ) {
2442 n = 0;
2443 }
2444 if ( n < uiInfo.myTeamCount ) {
2445 trap_Cvar_Set( "cg_selectedPlayerName", uiInfo.teamNames[n] );
2446 }
2447 }
2448
2449
UI_DrawSelectedPlayer(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2450 static void UI_DrawSelectedPlayer( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2451 if ( uiInfo.uiDC.realTime > uiInfo.playerRefresh ) {
2452 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
2453 UI_BuildPlayerList();
2454 }
2455 Text_Paint( rect->x, rect->y, font, scale, color, ( uiInfo.teamLeader ) ? UI_Cvar_VariableString( "cg_selectedPlayerName" ) : UI_Cvar_VariableString( "name" ), 0, 0, textStyle );
2456 }
2457
UI_DrawServerRefreshDate(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2458 static void UI_DrawServerRefreshDate( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2459 #ifdef MISSIONPACK
2460 if ( uiInfo.serverStatus.refreshActive ) {
2461 vec4_t lowLight, newColor;
2462 lowLight[0] = 0.8 * color[0];
2463 lowLight[1] = 0.8 * color[1];
2464 lowLight[2] = 0.8 * color[2];
2465 lowLight[3] = 0.8 * color[3];
2466 LerpColor( color,lowLight,newColor,0.5 + 0.5 * sin( uiInfo.uiDC.realTime / PULSE_DIVISOR ) );
2467 Text_Paint( rect->x, rect->y, font, scale, newColor, va( "Getting info for %d servers (ESC to cancel)", trap_LAN_GetServerCount( ui_netSource.integer ) ), 0, 0, textStyle );
2468 } else {
2469 char buff[64];
2470 Q_strncpyz( buff, UI_Cvar_VariableString( va( "ui_lastServerRefresh_%i", ui_netSource.integer ) ), 64 );
2471 Text_Paint( rect->x, rect->y, font, scale, color, va( "Refresh Time: %s", buff ), 0, 0, textStyle );
2472 }
2473 #endif // #ifdef MISSIONPACK
2474 }
2475
UI_DrawServerMOTD(rectDef_t * rect,int font,float scale,vec4_t color)2476 static void UI_DrawServerMOTD( rectDef_t *rect, int font, float scale, vec4_t color ) {
2477 #ifdef MISSIONPACK
2478 if ( uiInfo.serverStatus.motdLen ) {
2479 float maxX;
2480
2481 if ( uiInfo.serverStatus.motdWidth == -1 ) {
2482 uiInfo.serverStatus.motdWidth = 0;
2483 uiInfo.serverStatus.motdPaintX = rect->x + 1;
2484 uiInfo.serverStatus.motdPaintX2 = -1;
2485 }
2486
2487 if ( uiInfo.serverStatus.motdOffset > uiInfo.serverStatus.motdLen ) {
2488 uiInfo.serverStatus.motdOffset = 0;
2489 uiInfo.serverStatus.motdPaintX = rect->x + 1;
2490 uiInfo.serverStatus.motdPaintX2 = -1;
2491 }
2492
2493 if ( uiInfo.uiDC.realTime > uiInfo.serverStatus.motdTime ) {
2494 uiInfo.serverStatus.motdTime = uiInfo.uiDC.realTime + 10;
2495 if ( uiInfo.serverStatus.motdPaintX <= rect->x + 2 ) {
2496 if ( uiInfo.serverStatus.motdOffset < uiInfo.serverStatus.motdLen ) {
2497 uiInfo.serverStatus.motdPaintX += Text_Width( &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], font, scale, 1 ) - 1;
2498 uiInfo.serverStatus.motdOffset++;
2499 } else {
2500 uiInfo.serverStatus.motdOffset = 0;
2501 if ( uiInfo.serverStatus.motdPaintX2 >= 0 ) {
2502 uiInfo.serverStatus.motdPaintX = uiInfo.serverStatus.motdPaintX2;
2503 } else {
2504 uiInfo.serverStatus.motdPaintX = rect->x + rect->w - 2;
2505 }
2506 uiInfo.serverStatus.motdPaintX2 = -1;
2507 }
2508 } else {
2509 //serverStatus.motdPaintX--;
2510 uiInfo.serverStatus.motdPaintX -= 2;
2511 if ( uiInfo.serverStatus.motdPaintX2 >= 0 ) {
2512 //serverStatus.motdPaintX2--;
2513 uiInfo.serverStatus.motdPaintX2 -= 2;
2514 }
2515 }
2516 }
2517
2518 maxX = rect->x + rect->w - 2;
2519 Text_Paint_Limit( &maxX, uiInfo.serverStatus.motdPaintX, rect->y + rect->h - 3, font, scale, color, &uiInfo.serverStatus.motd[uiInfo.serverStatus.motdOffset], 0, 0 );
2520 if ( uiInfo.serverStatus.motdPaintX2 >= 0 ) {
2521 float maxX2 = rect->x + rect->w - 2;
2522 Text_Paint_Limit( &maxX2, uiInfo.serverStatus.motdPaintX2, rect->y + rect->h - 3, font, scale, color, uiInfo.serverStatus.motd, 0, uiInfo.serverStatus.motdOffset );
2523 }
2524 if ( uiInfo.serverStatus.motdOffset && maxX > 0 ) {
2525 // if we have an offset ( we are skipping the first part of the string ) and we fit the string
2526 if ( uiInfo.serverStatus.motdPaintX2 == -1 ) {
2527 uiInfo.serverStatus.motdPaintX2 = rect->x + rect->w - 2;
2528 }
2529 } else {
2530 uiInfo.serverStatus.motdPaintX2 = -1;
2531 }
2532
2533 }
2534 #endif // #ifdef MISSIONPACK
2535 }
2536
UI_DrawKeyBindStatus(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2537 static void UI_DrawKeyBindStatus( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2538 //int ofs = 0; // TTimo: unused
2539 if ( Display_KeyBindPending() ) {
2540 // Text_Paint(rect->x, rect->y, font, scale, color, "Waiting for new key... Press ESCAPE to cancel", 0, 0, textStyle);
2541 Text_Paint( rect->x, rect->y, font, scale, color, DC->getTranslatedString( "keywait" ), 0, 0, textStyle );
2542 } else {
2543 // Text_Paint(rect->x, rect->y, font, scale, color, "Press ENTER or CLICK to change, Press BACKSPACE to clear", 0, 0, textStyle);
2544 Text_Paint( rect->x, rect->y, font, scale, color, DC->getTranslatedString( "keychange" ), 0, 0, textStyle );
2545
2546 }
2547 }
2548
UI_DrawGLInfo(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2549 static void UI_DrawGLInfo( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2550 char * eptr;
2551 char buff[4096];
2552 const char *lines[64];
2553 int y, numLines, i;
2554
2555 Text_Paint( rect->x + 2, rect->y, font, scale, color, va( "VENDOR: %s", uiInfo.uiDC.glconfig.vendor_string ), 0, 30, textStyle );
2556 Text_Paint( rect->x + 2, rect->y + 15, font, scale, color, va( "VERSION: %s: %s", uiInfo.uiDC.glconfig.version_string,uiInfo.uiDC.glconfig.renderer_string ), 0, 30, textStyle );
2557 Text_Paint( rect->x + 2, rect->y + 30, font, 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 );
2558
2559 // build null terminated extension strings
2560 Q_strncpyz( buff, uiInfo.uiDC.glconfig.extensions_string, 4096 );
2561 eptr = buff;
2562 y = rect->y + 45;
2563 numLines = 0;
2564 while ( y < rect->y + rect->h && *eptr )
2565 {
2566 while ( *eptr && *eptr == ' ' )
2567 *eptr++ = '\0';
2568
2569 // don't overflow the line buffer, don't go above 63, as it goes out of the screen anyway
2570 if ( numLines == 63 )
2571 break;
2572
2573 // track start of valid string
2574 if ( *eptr && *eptr != ' ' ) {
2575 lines[numLines++] = eptr;
2576 }
2577
2578 while ( *eptr && *eptr != ' ' )
2579 eptr++;
2580 }
2581
2582 i = 0;
2583 while ( i < numLines ) {
2584 Text_Paint( rect->x + 2, y, font, scale, color, lines[i++], 0, 36, textStyle );
2585 if ( i < numLines ) {
2586 Text_Paint( rect->x + rect->w / 3.0f, y, font, scale, color, lines[i++], 0, 36, textStyle );
2587 }
2588 if ( i < numLines ) {
2589 Text_Paint( rect->x + ( 2.0f * ( rect->w / 3.0f ) ), y, font, scale, color, lines[i++], 0, 36, textStyle );
2590 }
2591 y += 10;
2592 if ( y > rect->y + rect->h - 11 ) {
2593 break;
2594 }
2595 }
2596
2597 // i = 0;
2598 // while (i < numLines) {
2599 // Text_Paint(rect->x + 2, y, font, scale, color, lines[i++], 0, 20, textStyle);
2600 // if (i < numLines) {
2601 // Text_Paint(rect->x + rect->w / 2, y, font, scale, color, lines[i++], 0, 20, textStyle);
2602 // }
2603 // y += 10;
2604 // if (y > rect->y + rect->h - 11) {
2605 // break;
2606 // }
2607 // }
2608
2609
2610 }
2611
2612 // NERVE - SMF
UI_DrawLimboChat(rectDef_t * rect,int font,float scale,vec4_t color,int textStyle)2613 static void UI_DrawLimboChat( rectDef_t *rect, int font, float scale, vec4_t color, int textStyle ) {
2614 int i, count;
2615 char buf[140];
2616 float x, y;
2617
2618 memset( buf, 0, 140 );
2619
2620 // first count strings
2621 for ( i = 0, count = 0; ; i++, count++ ) {
2622 if ( !trap_GetLimboString( i, buf ) ) {
2623 break;
2624 }
2625 }
2626
2627 // now draw strings
2628 for ( i = 0; i < count; i++ ) {
2629 x = rect->x;
2630 y = rect->y + 9 * i;
2631
2632 trap_GetLimboString( i, buf );
2633 Text_Paint( x, y, font, scale, color, buf, 0, 0, textStyle );
2634 }
2635 }
2636 // -NERVE - SMF
2637
2638 // FIXME: table drive
2639 //
UI_OwnerDraw(float x,float y,float w,float h,float text_x,float text_y,int ownerDraw,int ownerDrawFlags,int align,float special,int font,float scale,vec4_t color,qhandle_t shader,int textStyle)2640 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, int font, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
2641 rectDef_t rect;
2642
2643 rect.x = x + text_x;
2644 rect.y = y + text_y;
2645 rect.w = w;
2646 rect.h = h;
2647
2648 switch ( ownerDraw ) {
2649 case UI_HANDICAP:
2650 UI_DrawHandicap( &rect, font, scale, color, textStyle );
2651 break;
2652 case UI_EFFECTS:
2653 UI_DrawEffects( &rect, scale, color );
2654 break;
2655 case UI_PLAYERMODEL:
2656 UI_DrawPlayerModel( &rect );
2657 break;
2658 case UI_CLANNAME:
2659 UI_DrawClanName( &rect, font, scale, color, textStyle );
2660 break;
2661
2662
2663 case UI_SAVEGAME_SHOT: // (SA)
2664 UI_DrawSaveGameShot( &rect, scale, color );
2665 break;
2666
2667 case UI_CLANLOGO:
2668 UI_DrawClanLogo( &rect, scale, color );
2669 break;
2670 case UI_CLANCINEMATIC:
2671 UI_DrawClanCinematic( &rect, scale, color );
2672 break;
2673 case UI_STARTMAPCINEMATIC:
2674 UI_DrawPregameCinematic( &rect, scale, color );
2675 break;
2676 case UI_PREVIEWCINEMATIC:
2677 UI_DrawPreviewCinematic( &rect, scale, color );
2678 break;
2679 case UI_GAMETYPE:
2680 UI_DrawGameType( &rect, font, scale, color, textStyle );
2681 break;
2682 case UI_NETGAMETYPE:
2683 UI_DrawNetGameType( &rect, font, scale, color, textStyle );
2684 break;
2685 case UI_JOINGAMETYPE:
2686 UI_DrawJoinGameType( &rect, font, scale, color, textStyle );
2687 break;
2688 case UI_MAPPREVIEW:
2689 UI_DrawMapPreview( &rect, scale, color, qtrue );
2690 break;
2691
2692 //----(SA) added
2693 case UI_SAVEGAMENAME:
2694 UI_DrawSavegameName( &rect, font, scale, color, textStyle );
2695 break;
2696 case UI_SAVEGAMEINFO:
2697 break;
2698 case UI_LEVELSHOT:
2699 UI_DrawMapLevelshot( &rect );
2700 break;
2701 case UI_LOADSTATUSBAR:
2702 UI_DrawLoadStatus( &rect, color, align );
2703 break;
2704 //----(SA) end
2705
2706 case UI_MAP_TIMETOBEAT:
2707 UI_DrawMapTimeToBeat( &rect, font, scale, color, textStyle );
2708 break;
2709 case UI_MAPCINEMATIC:
2710 UI_DrawMapCinematic( &rect, scale, color, qfalse );
2711 break;
2712 case UI_SKILL:
2713 UI_DrawSkill( &rect, font, scale, color, textStyle );
2714 break;
2715 case UI_BLUETEAMNAME:
2716 UI_DrawTeamName( &rect, font, scale, color, qtrue, textStyle );
2717 break;
2718 case UI_REDTEAMNAME:
2719 UI_DrawTeamName( &rect, font, scale, color, qfalse, textStyle );
2720 break;
2721 case UI_BLUETEAM1:
2722 case UI_BLUETEAM2:
2723 case UI_BLUETEAM3:
2724 case UI_BLUETEAM4:
2725 case UI_BLUETEAM5:
2726 UI_DrawTeamMember( &rect, font, scale, color, qtrue, ownerDraw - UI_BLUETEAM1 + 1, textStyle );
2727 break;
2728 case UI_REDTEAM1:
2729 case UI_REDTEAM2:
2730 case UI_REDTEAM3:
2731 case UI_REDTEAM4:
2732 case UI_REDTEAM5:
2733 UI_DrawTeamMember( &rect, font, scale, color, qfalse, ownerDraw - UI_REDTEAM1 + 1, textStyle );
2734 break;
2735 case UI_NETSOURCE:
2736 UI_DrawNetSource( &rect, font, scale, color, textStyle );
2737 break;
2738 case UI_NETMAPPREVIEW:
2739 UI_DrawNetMapPreview( &rect, scale, color );
2740 break;
2741 case UI_NETMAPCINEMATIC:
2742 UI_DrawNetMapCinematic( &rect, scale, color );
2743 break;
2744 case UI_NETFILTER:
2745 UI_DrawNetFilter( &rect, font, scale, color, textStyle );
2746 break;
2747 case UI_TIER:
2748 UI_DrawTier( &rect, font, scale, color, textStyle );
2749 break;
2750 case UI_OPPONENTMODEL:
2751 UI_DrawOpponent( &rect );
2752 break;
2753 case UI_TIERMAP1:
2754 UI_DrawTierMap( &rect, 0 );
2755 break;
2756 case UI_TIERMAP2:
2757 UI_DrawTierMap( &rect, 1 );
2758 break;
2759 case UI_TIERMAP3:
2760 UI_DrawTierMap( &rect, 2 );
2761 break;
2762 case UI_PLAYERLOGO:
2763 UI_DrawPlayerLogo( &rect, color );
2764 break;
2765 case UI_PLAYERLOGO_METAL:
2766 UI_DrawPlayerLogoMetal( &rect, color );
2767 break;
2768 case UI_PLAYERLOGO_NAME:
2769 UI_DrawPlayerLogoName( &rect, color );
2770 break;
2771 case UI_OPPONENTLOGO:
2772 UI_DrawOpponentLogo( &rect, color );
2773 break;
2774 case UI_OPPONENTLOGO_METAL:
2775 UI_DrawOpponentLogoMetal( &rect, color );
2776 break;
2777 case UI_OPPONENTLOGO_NAME:
2778 UI_DrawOpponentLogoName( &rect, color );
2779 break;
2780 case UI_TIER_MAPNAME:
2781 UI_DrawTierMapName( &rect, font, scale, color, textStyle );
2782 break;
2783 case UI_TIER_GAMETYPE:
2784 UI_DrawTierGameType( &rect, font, scale, color, textStyle );
2785 break;
2786 case UI_ALLMAPS_SELECTION:
2787 UI_DrawAllMapsSelection( &rect, font, scale, color, textStyle, qtrue );
2788 break;
2789 case UI_MAPS_SELECTION:
2790 UI_DrawAllMapsSelection( &rect, font, scale, color, textStyle, qfalse );
2791 break;
2792 case UI_OPPONENT_NAME:
2793 UI_DrawOpponentName( &rect, font, scale, color, textStyle );
2794 break;
2795 case UI_BOTNAME:
2796 UI_DrawBotName( &rect, font, scale, color, textStyle );
2797 break;
2798 case UI_BOTSKILL:
2799 UI_DrawBotSkill( &rect, font, scale, color, textStyle );
2800 break;
2801 case UI_REDBLUE:
2802 UI_DrawRedBlue( &rect, font, scale, color, textStyle );
2803 break;
2804 case UI_CROSSHAIR:
2805 UI_DrawCrosshair( &rect, scale, color );
2806 break;
2807 case UI_SELECTEDPLAYER:
2808 UI_DrawSelectedPlayer( &rect, font, scale, color, textStyle );
2809 break;
2810 case UI_SERVERREFRESHDATE:
2811 UI_DrawServerRefreshDate( &rect, font, scale, color, textStyle );
2812 break;
2813 case UI_SERVERMOTD:
2814 UI_DrawServerMOTD( &rect, font, scale, color );
2815 break;
2816 case UI_GLINFO:
2817 UI_DrawGLInfo( &rect, font, scale, color, textStyle );
2818 break;
2819 case UI_KEYBINDSTATUS:
2820 UI_DrawKeyBindStatus( &rect, font, scale, color, textStyle );
2821 break;
2822 // NERVE - SMF
2823 case UI_LIMBOCHAT:
2824 UI_DrawLimboChat( &rect, font, scale, color, textStyle );
2825 break;
2826 // -NERVE - SMF
2827
2828 default:
2829 break;
2830 }
2831 }
2832
UI_OwnerDrawVisible(int flags)2833 static qboolean UI_OwnerDrawVisible( int flags ) {
2834 qboolean vis = qtrue;
2835
2836 while ( flags ) {
2837
2838 if ( flags & UI_SHOW_FFA ) {
2839 if ( trap_Cvar_VariableValue( "g_gametype" ) != GT_FFA ) {
2840 vis = qfalse;
2841 }
2842 flags &= ~UI_SHOW_FFA;
2843 }
2844
2845 if ( flags & UI_SHOW_NOTFFA ) {
2846 if ( trap_Cvar_VariableValue( "g_gametype" ) == GT_FFA ) {
2847 vis = qfalse;
2848 }
2849 flags &= ~UI_SHOW_NOTFFA;
2850 }
2851
2852 if ( flags & UI_SHOW_LEADER ) {
2853 // these need to show when this client can give orders to a player or a group
2854 if ( !uiInfo.teamLeader ) {
2855 vis = qfalse;
2856 } else {
2857 // if showing yourself
2858 if ( ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber ) {
2859 vis = qfalse;
2860 }
2861 }
2862 flags &= ~UI_SHOW_LEADER;
2863 }
2864 if ( flags & UI_SHOW_NOTLEADER ) {
2865 // these need to show when this client is assigning their own status or they are NOT the leader
2866 if ( uiInfo.teamLeader ) {
2867 // if not showing yourself
2868 if ( !( ui_selectedPlayer.integer < uiInfo.myTeamCount && uiInfo.teamClientNums[ui_selectedPlayer.integer] == uiInfo.playerNumber ) ) {
2869 vis = qfalse;
2870 }
2871 }
2872 flags &= ~UI_SHOW_NOTLEADER;
2873 }
2874 if ( flags & UI_SHOW_FAVORITESERVERS ) {
2875 // this assumes you only put this type of display flag on something showing in the proper context
2876 if ( ui_netSource.integer != UIAS_FAVORITES ) {
2877 vis = qfalse;
2878 }
2879 flags &= ~UI_SHOW_FAVORITESERVERS;
2880 }
2881 if ( flags & UI_SHOW_NOTFAVORITESERVERS ) {
2882 // this assumes you only put this type of display flag on something showing in the proper context
2883 if ( ui_netSource.integer == UIAS_FAVORITES ) {
2884 vis = qfalse;
2885 }
2886 flags &= ~UI_SHOW_NOTFAVORITESERVERS;
2887 }
2888 if ( flags & UI_SHOW_ANYTEAMGAME ) {
2889 if ( uiInfo.gameTypes[ui_gameType.integer].gtEnum <= GT_TEAM ) {
2890 vis = qfalse;
2891 }
2892 flags &= ~UI_SHOW_ANYTEAMGAME;
2893 }
2894 if ( flags & UI_SHOW_ANYNONTEAMGAME ) {
2895 if ( uiInfo.gameTypes[ui_gameType.integer].gtEnum > GT_TEAM ) {
2896 vis = qfalse;
2897 }
2898 flags &= ~UI_SHOW_ANYNONTEAMGAME;
2899 }
2900 if ( flags & UI_SHOW_NETANYTEAMGAME ) {
2901 if ( uiInfo.gameTypes[ui_netGameType.integer].gtEnum <= GT_TEAM ) {
2902 vis = qfalse;
2903 }
2904 flags &= ~UI_SHOW_NETANYTEAMGAME;
2905 }
2906 if ( flags & UI_SHOW_NETANYNONTEAMGAME ) {
2907 if ( uiInfo.gameTypes[ui_netGameType.integer].gtEnum > GT_TEAM ) {
2908 vis = qfalse;
2909 }
2910 flags &= ~UI_SHOW_NETANYNONTEAMGAME;
2911 }
2912 if ( flags & UI_SHOW_NEWHIGHSCORE ) {
2913 if ( uiInfo.newHighScoreTime < uiInfo.uiDC.realTime ) {
2914 vis = qfalse;
2915 } else {
2916 if ( uiInfo.soundHighScore ) {
2917 if ( trap_Cvar_VariableValue( "sv_killserver" ) == 0 ) {
2918 // wait on server to go down before playing sound
2919 trap_S_StartLocalSound( uiInfo.newHighScoreSound, CHAN_ANNOUNCER );
2920 uiInfo.soundHighScore = qfalse;
2921 }
2922 }
2923 }
2924 flags &= ~UI_SHOW_NEWHIGHSCORE;
2925 }
2926 if ( flags & UI_SHOW_NEWBESTTIME ) {
2927 if ( uiInfo.newBestTime < uiInfo.uiDC.realTime ) {
2928 vis = qfalse;
2929 }
2930 flags &= ~UI_SHOW_NEWBESTTIME;
2931 }
2932 if ( flags & UI_SHOW_DEMOAVAILABLE ) {
2933 if ( !uiInfo.demoAvailable ) {
2934 vis = qfalse;
2935 }
2936 flags &= ~UI_SHOW_DEMOAVAILABLE;
2937 } else {
2938 flags = 0;
2939 }
2940 }
2941 return vis;
2942 }
2943
UI_Handicap_HandleKey(int flags,float * special,int key)2944 static qboolean UI_Handicap_HandleKey(int flags, float *special, int key) {
2945 int select = UI_SelectForKey(key);
2946 if (select != 0) {
2947 int h;
2948
2949 h = Com_Clamp( 5, 100, trap_Cvar_VariableValue("handicap") );
2950 h += 5 * select;
2951
2952 if (h > 100) {
2953 h = 5;
2954 } else if (h < 5) {
2955 h = 100;
2956 }
2957
2958 trap_Cvar_SetValue( "handicap", h );
2959 return qtrue;
2960 }
2961 return qfalse;
2962 }
2963
UI_Effects_HandleKey(int flags,float * special,int key)2964 static qboolean UI_Effects_HandleKey(int flags, float *special, int key) {
2965 int select = UI_SelectForKey(key);
2966 if (select != 0) {
2967 uiInfo.effectsColor += select;
2968
2969 if( uiInfo.effectsColor > 6 ) {
2970 uiInfo.effectsColor = 0;
2971 } else if (uiInfo.effectsColor < 0) {
2972 uiInfo.effectsColor = 6;
2973 }
2974
2975 trap_Cvar_SetValue( "color", uitogamecode[uiInfo.effectsColor] );
2976 return qtrue;
2977 }
2978 return qfalse;
2979 }
2980
2981 //----(SA) added
UI_SavegameName_HandleKey(int flags,float * special,int key)2982 static qboolean UI_SavegameName_HandleKey( int flags, float *special, int key ) {
2983
2984 // disable
2985 return qfalse;
2986 #if 0
2987 int select = UI_SelectForKey(key);
2988 if (select != 0) {
2989 int i;
2990
2991 i = UI_SavegameIndexFromName( ui_savegameName.string );
2992
2993 i += select;
2994
2995 if (i >= uiInfo.savegameCount) {
2996 i = 0;
2997 } else if (i < 0) {
2998 i = uiInfo.savegameCount - 1;
2999 }
3000
3001 // set feeder highlight
3002 Menu_SetFeederSelection( NULL, FEEDER_SAVEGAMES, i, NULL );
3003
3004 trap_Cvar_Set( "ui_savegameName", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[i]].savegameName );
3005 trap_Cvar_Set( "ui_savegameInfo", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[i]].savegameInfoText );
3006 return qtrue;
3007 }
3008 return qfalse;
3009 #endif
3010 }
3011 //----(SA) end
3012
UI_ClanName_HandleKey(int flags,float * special,int key)3013 static qboolean UI_ClanName_HandleKey(int flags, float *special, int key) {
3014 int select = UI_SelectForKey(key);
3015 if (select != 0) {
3016 int i;
3017
3018 i = UI_TeamIndexFromName(UI_Cvar_VariableString("ui_teamName"));
3019
3020 if (uiInfo.teamList[i].cinematic >= 0) {
3021 trap_CIN_StopCinematic(uiInfo.teamList[i].cinematic);
3022 uiInfo.teamList[i].cinematic = -1;
3023 }
3024
3025 i += select;
3026
3027 if (i >= uiInfo.teamCount) {
3028 i = 0;
3029 } else if (i < 0) {
3030 i = uiInfo.teamCount - 1;
3031 }
3032
3033 trap_Cvar_Set( "ui_teamName", uiInfo.teamList[i].teamName);
3034 updateModel = qtrue;
3035 return qtrue;
3036 }
3037 return qfalse;
3038 }
3039
UI_GameType_HandleKey(int flags,float * special,int key,qboolean resetMap)3040 static qboolean UI_GameType_HandleKey(int flags, float *special, int key, qboolean resetMap) {
3041 #ifdef MISSIONPACK
3042 int select = UI_SelectForKey(key);
3043 if (select != 0) {
3044 int oldCount = UI_MapCountByGameType(qtrue);
3045
3046 // hard coded mess here
3047 if (select < 0) {
3048 ui_gameType.integer--;
3049 if (ui_gameType.integer == 2) {
3050 ui_gameType.integer = 1;
3051 } else if (ui_gameType.integer < 2) {
3052 ui_gameType.integer = uiInfo.numGameTypes - 1;
3053 }
3054 } else {
3055 ui_gameType.integer++;
3056 if (ui_gameType.integer >= uiInfo.numGameTypes) {
3057 ui_gameType.integer = 1;
3058 } else if (ui_gameType.integer == 2) {
3059 ui_gameType.integer = 3;
3060 }
3061 }
3062
3063 if (uiInfo.gameTypes[ui_gameType.integer].gtEnum < GT_TEAM) {
3064 trap_Cvar_SetValue( "ui_Q3Model", 1 );
3065 } else {
3066 trap_Cvar_SetValue( "ui_Q3Model", 0 );
3067 }
3068
3069 trap_Cvar_SetValue("ui_gameType", ui_gameType.integer);
3070 UI_SetCapFragLimits(qtrue);
3071 UI_LoadBestScores(uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum);
3072 if (resetMap && oldCount != UI_MapCountByGameType(qtrue)) {
3073 trap_Cvar_SetValue( "ui_currentMap", 0);
3074 Menu_SetFeederSelection(NULL, FEEDER_MAPS, 0, NULL);
3075 }
3076 return qtrue;
3077 }
3078 #endif // #ifdef MISSIONPACK
3079 return qfalse;
3080 }
3081
UI_NetGameType_HandleKey(int flags,float * special,int key)3082 static qboolean UI_NetGameType_HandleKey(int flags, float *special, int key) {
3083 #ifdef MISSIONPACK
3084 int select = UI_SelectForKey(key);
3085 if (select != 0) {
3086 ui_netGameType.integer += select;
3087
3088 if (ui_netGameType.integer < 0) {
3089 ui_netGameType.integer = uiInfo.numGameTypes - 1;
3090 } else if (ui_netGameType.integer >= uiInfo.numGameTypes) {
3091 ui_netGameType.integer = 0;
3092 }
3093
3094 trap_Cvar_SetValue( "ui_netGameType", ui_netGameType.integer);
3095 trap_Cvar_SetValue( "ui_actualnetGameType", uiInfo.gameTypes[ui_netGameType.integer].gtEnum);
3096 trap_Cvar_SetValue( "ui_currentNetMap", 0);
3097 UI_MapCountByGameType(qfalse);
3098 Menu_SetFeederSelection(NULL, FEEDER_ALLMAPS, 0, NULL);
3099 return qtrue;
3100 }
3101 #endif // #ifdef MISSIONPACK
3102 return qfalse;
3103 }
3104
UI_JoinGameType_HandleKey(int flags,float * special,int key)3105 static qboolean UI_JoinGameType_HandleKey(int flags, float *special, int key) {
3106 #ifdef MISSIONPACK
3107 int select = UI_SelectForKey(key);
3108 if (select != 0) {
3109 ui_joinGameType.integer += select;
3110
3111 if (ui_joinGameType.integer < 0) {
3112 ui_joinGameType.integer = uiInfo.numJoinGameTypes - 1;
3113 } else if (ui_joinGameType.integer >= uiInfo.numJoinGameTypes) {
3114 ui_joinGameType.integer = 0;
3115 }
3116
3117 trap_Cvar_SetValue( "ui_joinGameType", ui_joinGameType.integer);
3118 UI_BuildServerDisplayList(qtrue);
3119 return qtrue;
3120 }
3121 #endif // #ifdef MISSIONPACK
3122 return qfalse;
3123 }
3124
3125
3126
UI_Skill_HandleKey(int flags,float * special,int key)3127 static qboolean UI_Skill_HandleKey(int flags, float *special, int key) {
3128 int select = UI_SelectForKey(key);
3129 if (select != 0) {
3130 int i = trap_Cvar_VariableValue( "g_spSkill" );
3131
3132 i += select;
3133
3134 if (i < 1) {
3135 i = numSkillLevels;
3136 } else if (i > numSkillLevels) {
3137 i = 1;
3138 }
3139
3140 trap_Cvar_SetValue("g_spSkill", i);
3141 return qtrue;
3142 }
3143 return qfalse;
3144 }
3145
UI_TeamName_HandleKey(int flags,float * special,int key,qboolean blue)3146 static qboolean UI_TeamName_HandleKey(int flags, float *special, int key, qboolean blue) {
3147 int select = UI_SelectForKey(key);
3148 if (select != 0) {
3149 int i;
3150
3151 i = UI_TeamIndexFromName(UI_Cvar_VariableString((blue) ? "ui_blueTeam" : "ui_redTeam"));
3152 i += select;
3153
3154 if (i >= uiInfo.teamCount) {
3155 i = 0;
3156 } else if (i < 0) {
3157 i = uiInfo.teamCount - 1;
3158 }
3159
3160 trap_Cvar_Set( (blue) ? "ui_blueTeam" : "ui_redTeam", uiInfo.teamList[i].teamName);
3161 return qtrue;
3162 }
3163 return qfalse;
3164 }
3165
UI_TeamMember_HandleKey(int flags,float * special,int key,qboolean blue,int num)3166 static qboolean UI_TeamMember_HandleKey(int flags, float *special, int key, qboolean blue, int num) {
3167 int select = UI_SelectForKey(key);
3168 if (select != 0) {
3169 // 0 - None
3170 // 1 - Human
3171 // 2..NumCharacters - Bot
3172 char *cvar = va(blue ? "ui_blueteam%i" : "ui_redteam%i", num);
3173 int value = trap_Cvar_VariableValue(cvar);
3174
3175 value += select;
3176
3177 if (ui_actualNetGameType.integer >= GT_TEAM) {
3178 if (value >= uiInfo.characterCount + 2) {
3179 value = 0;
3180 } else if (value < 0) {
3181 value = uiInfo.characterCount + 2 - 1;
3182 }
3183 } else {
3184 if (value >= UI_GetNumBots() + 2) {
3185 value = 0;
3186 } else if (value < 0) {
3187 value = UI_GetNumBots() + 2 - 1;
3188 }
3189 }
3190
3191 trap_Cvar_SetValue(cvar, value);
3192 return qtrue;
3193 }
3194 return qfalse;
3195 }
3196
UI_NetSource_HandleKey(int flags,float * special,int key)3197 static qboolean UI_NetSource_HandleKey(int flags, float *special, int key) {
3198 #ifdef MISSIONPACK
3199 int select = UI_SelectForKey(key);
3200 if (select != 0) {
3201 ui_netSource.integer += select;
3202
3203 if(ui_netSource.integer >= UIAS_GLOBAL1 && ui_netSource.integer <= UIAS_GLOBAL5)
3204 {
3205 char masterstr[2], cvarname[sizeof("sv_master1")];
3206
3207 while(ui_netSource.integer >= UIAS_GLOBAL1 && ui_netSource.integer <= UIAS_GLOBAL5)
3208 {
3209 Com_sprintf(cvarname, sizeof(cvarname), "sv_master%d", ui_netSource.integer - UIAS_GLOBAL0);
3210 trap_Cvar_VariableStringBuffer(cvarname, masterstr, sizeof(masterstr));
3211 if(*masterstr)
3212 break;
3213
3214 ui_netSource.integer += select;
3215 }
3216 }
3217
3218 if (ui_netSource.integer >= numNetSources) {
3219 ui_netSource.integer = 0;
3220 } else if (ui_netSource.integer < 0) {
3221 ui_netSource.integer = numNetSources - 1;
3222 }
3223
3224 UI_BuildServerDisplayList(qtrue);
3225 UI_StartServerRefresh(qtrue, qfalse);
3226 trap_Cvar_SetValue( "ui_netSource", ui_netSource.integer);
3227 return qtrue;
3228 }
3229 #endif // #ifdef MISSIONPACK
3230 return qfalse;
3231 }
3232
UI_NetFilter_HandleKey(int flags,float * special,int key)3233 static qboolean UI_NetFilter_HandleKey(int flags, float *special, int key) {
3234 #ifdef MISSIONPACK
3235 int select = UI_SelectForKey(key);
3236 if (select != 0) {
3237 ui_serverFilterType.integer += select;
3238
3239 if (ui_serverFilterType.integer >= numServerFilters) {
3240 ui_serverFilterType.integer = 0;
3241 } else if (ui_serverFilterType.integer < 0) {
3242 ui_serverFilterType.integer = numServerFilters - 1;
3243 }
3244 UI_BuildServerDisplayList(qtrue);
3245 return qtrue;
3246 }
3247 #endif // #ifdef MISSIONPACK
3248 return qfalse;
3249 }
3250
UI_OpponentName_HandleKey(int flags,float * special,int key)3251 static qboolean UI_OpponentName_HandleKey(int flags, float *special, int key) {
3252 int select = UI_SelectForKey(key);
3253 if (select != 0) {
3254 if (select < 0) {
3255 UI_PriorOpponent();
3256 } else {
3257 UI_NextOpponent();
3258 }
3259 return qtrue;
3260 }
3261 return qfalse;
3262 }
3263
UI_BotName_HandleKey(int flags,float * special,int key)3264 static qboolean UI_BotName_HandleKey(int flags, float *special, int key) {
3265 int select = UI_SelectForKey(key);
3266 if (select != 0) {
3267 int game = trap_Cvar_VariableValue("g_gametype");
3268 int value = uiInfo.botIndex;
3269
3270 value += select;
3271
3272 if (game >= GT_TEAM) {
3273 if (value >= uiInfo.characterCount) {
3274 value = 0;
3275 } else if (value < 0) {
3276 value = uiInfo.characterCount - 1;
3277 }
3278 } else {
3279 if (value >= UI_GetNumBots()) {
3280 value = 0;
3281 } else if (value < 0) {
3282 value = UI_GetNumBots() - 1;
3283 }
3284 }
3285 uiInfo.botIndex = value;
3286 return qtrue;
3287 }
3288 return qfalse;
3289 }
3290
UI_BotSkill_HandleKey(int flags,float * special,int key)3291 static qboolean UI_BotSkill_HandleKey(int flags, float *special, int key) {
3292 int select = UI_SelectForKey(key);
3293 if (select != 0) {
3294 uiInfo.skillIndex += select;
3295
3296 if (uiInfo.skillIndex >= numSkillLevels) {
3297 uiInfo.skillIndex = 0;
3298 } else if (uiInfo.skillIndex < 0) {
3299 uiInfo.skillIndex = numSkillLevels-1;
3300 }
3301 return qtrue;
3302 }
3303 return qfalse;
3304 }
3305
UI_RedBlue_HandleKey(int flags,float * special,int key)3306 static qboolean UI_RedBlue_HandleKey(int flags, float *special, int key) {
3307 int select = UI_SelectForKey(key);
3308 if (select != 0) {
3309 uiInfo.redBlue ^= 1;
3310 return qtrue;
3311 }
3312 return qfalse;
3313 }
3314
UI_Crosshair_HandleKey(int flags,float * special,int key)3315 static qboolean UI_Crosshair_HandleKey(int flags, float *special, int key) {
3316 int select = UI_SelectForKey(key);
3317 if (select != 0) {
3318 uiInfo.currentCrosshair += select;
3319
3320 if (uiInfo.currentCrosshair >= NUM_CROSSHAIRS) {
3321 uiInfo.currentCrosshair = 0;
3322 } else if (uiInfo.currentCrosshair < 0) {
3323 uiInfo.currentCrosshair = NUM_CROSSHAIRS - 1;
3324 }
3325 trap_Cvar_SetValue("cg_drawCrosshair", uiInfo.currentCrosshair);
3326 return qtrue;
3327 }
3328 return qfalse;
3329 }
3330
3331
3332
UI_SelectedPlayer_HandleKey(int flags,float * special,int key)3333 static qboolean UI_SelectedPlayer_HandleKey(int flags, float *special, int key) {
3334 int select = UI_SelectForKey(key);
3335 if (select != 0) {
3336 int selected;
3337
3338 UI_BuildPlayerList();
3339 if (!uiInfo.teamLeader) {
3340 return qfalse;
3341 }
3342 selected = trap_Cvar_VariableValue("cg_selectedPlayer");
3343
3344 selected += select;
3345
3346 if (selected > uiInfo.myTeamCount) {
3347 selected = 0;
3348 } else if (selected < 0) {
3349 selected = uiInfo.myTeamCount;
3350 }
3351
3352 if (selected == uiInfo.myTeamCount) {
3353 trap_Cvar_Set( "cg_selectedPlayerName", "Everyone");
3354 } else {
3355 trap_Cvar_Set( "cg_selectedPlayerName", uiInfo.teamNames[selected]);
3356 }
3357 trap_Cvar_SetValue( "cg_selectedPlayer", selected);
3358 }
3359 return qfalse;
3360 }
3361
3362
UI_OwnerDrawHandleKey(int ownerDraw,int flags,float * special,int key)3363 static qboolean UI_OwnerDrawHandleKey( int ownerDraw, int flags, float *special, int key ) {
3364 switch ( ownerDraw ) {
3365 case UI_HANDICAP:
3366 return UI_Handicap_HandleKey( flags, special, key );
3367 break;
3368 case UI_EFFECTS:
3369 return UI_Effects_HandleKey( flags, special, key );
3370 break;
3371 //----(SA) added
3372 case UI_SAVEGAMENAME:
3373 case UI_SAVEGAMEINFO:
3374 return UI_SavegameName_HandleKey( flags, special, key );
3375
3376 //----(SA) end
3377 case UI_CLANNAME:
3378 return UI_ClanName_HandleKey( flags, special, key );
3379 break;
3380 case UI_GAMETYPE:
3381 return UI_GameType_HandleKey( flags, special, key, qtrue );
3382 break;
3383 case UI_NETGAMETYPE:
3384 return UI_NetGameType_HandleKey( flags, special, key );
3385 break;
3386 case UI_JOINGAMETYPE:
3387 return UI_JoinGameType_HandleKey( flags, special, key );
3388 break;
3389 case UI_SKILL:
3390 return UI_Skill_HandleKey( flags, special, key );
3391 break;
3392 case UI_BLUETEAMNAME:
3393 return UI_TeamName_HandleKey( flags, special, key, qtrue );
3394 break;
3395 case UI_REDTEAMNAME:
3396 return UI_TeamName_HandleKey( flags, special, key, qfalse );
3397 break;
3398 case UI_BLUETEAM1:
3399 case UI_BLUETEAM2:
3400 case UI_BLUETEAM3:
3401 case UI_BLUETEAM4:
3402 case UI_BLUETEAM5:
3403 UI_TeamMember_HandleKey( flags, special, key, qtrue, ownerDraw - UI_BLUETEAM1 + 1 );
3404 break;
3405 case UI_REDTEAM1:
3406 case UI_REDTEAM2:
3407 case UI_REDTEAM3:
3408 case UI_REDTEAM4:
3409 case UI_REDTEAM5:
3410 UI_TeamMember_HandleKey( flags, special, key, qfalse, ownerDraw - UI_REDTEAM1 + 1 );
3411 break;
3412 case UI_NETSOURCE:
3413 UI_NetSource_HandleKey( flags, special, key );
3414 break;
3415 case UI_NETFILTER:
3416 UI_NetFilter_HandleKey( flags, special, key );
3417 break;
3418 case UI_OPPONENT_NAME:
3419 UI_OpponentName_HandleKey( flags, special, key );
3420 break;
3421 case UI_BOTNAME:
3422 return UI_BotName_HandleKey( flags, special, key );
3423 break;
3424 case UI_BOTSKILL:
3425 return UI_BotSkill_HandleKey( flags, special, key );
3426 break;
3427 case UI_REDBLUE:
3428 UI_RedBlue_HandleKey( flags, special, key );
3429 break;
3430 case UI_CROSSHAIR:
3431 UI_Crosshair_HandleKey( flags, special, key );
3432 break;
3433 case UI_SELECTEDPLAYER:
3434 UI_SelectedPlayer_HandleKey( flags, special, key );
3435 break;
3436 default:
3437 break;
3438 }
3439
3440 return qfalse;
3441 }
3442
3443
UI_GetValue(int ownerDraw,int type)3444 static float UI_GetValue( int ownerDraw, int type ) {
3445 return 0;
3446 }
3447
3448 /*
3449 =================
3450 UI_ServersQsortCompare
3451 =================
3452 */
UI_ServersQsortCompare(const void * arg1,const void * arg2)3453 static int QDECL UI_ServersQsortCompare( const void *arg1, const void *arg2 ) {
3454 #ifdef MISSIONPACK
3455 return trap_LAN_CompareServers( UI_SourceForLAN(), uiInfo.serverStatus.sortKey, uiInfo.serverStatus.sortDir, *(int*)arg1, *(int*)arg2);
3456 #else
3457 return qfalse;
3458 #endif // #ifdef MISSIONPACK
3459 }
3460
3461
3462 /*
3463 =================
3464 UI_ServersSort
3465 =================
3466 */
UI_ServersSort(int column,qboolean force)3467 void UI_ServersSort( int column, qboolean force ) {
3468
3469 if ( !force ) {
3470 if ( uiInfo.serverStatus.sortKey == column ) {
3471 return;
3472 }
3473 }
3474
3475 uiInfo.serverStatus.sortKey = column;
3476 qsort( &uiInfo.serverStatus.displayServers[0], uiInfo.serverStatus.numDisplayServers, sizeof( int ), UI_ServersQsortCompare );
3477
3478 // update displayed levelshot
3479 UI_FeederSelection( FEEDER_SERVERS, uiInfo.serverStatus.currentServer );
3480 }
3481
3482
3483 //----(SA) added
3484
3485
3486 /*
3487 ==============
3488 UI_SavegamesQsortCompare
3489 ==============
3490 */
UI_SavegamesQsortCompare(const void * arg1,const void * arg2)3491 static int QDECL UI_SavegamesQsortCompare( const void *arg1, const void *arg2 ) {
3492 int *ea, *eb, ret;
3493
3494 savegameInfo *sg, *sg2;
3495 int i, j;
3496
3497 ea = (int *)arg1;
3498 eb = (int *)arg2;
3499
3500 if ( *ea == *eb ) {
3501 return 0;
3502 }
3503
3504 sg = &uiInfo.savegameList[*eb];
3505 sg2 = &uiInfo.savegameList[*ea];
3506
3507 if ( uiInfo.savegameStatus.sortKey == SORT_SAVENAME ) {
3508 ret = Q_stricmp( &sg->savegameName[0], &sg2->savegameName[0] );
3509
3510 } else if ( uiInfo.savegameStatus.sortKey == SORT_SAVETIME ) {
3511
3512 // (SA) better way to do this? (i was adding up seconds, but that seems slower than a bunch of comparisons)
3513 i = sg->tm.tm_year;
3514 j = sg2->tm.tm_year;
3515 if ( i < j ) {
3516 ret = -1;
3517 } else if ( i > j ) {
3518 ret = 1;
3519 } else {
3520 i = sg->tm.tm_yday;
3521 j = sg2->tm.tm_yday;
3522 if ( i < j ) {
3523 ret = -1;
3524 } else if ( i > j ) {
3525 ret = 1;
3526 } else {
3527 i = sg->tm.tm_hour;
3528 j = sg2->tm.tm_hour;
3529 if ( i < j ) {
3530 ret = -1;
3531 } else if ( i > j ) {
3532 ret = 1;
3533 } else {
3534 i = sg->tm.tm_min;
3535 j = sg2->tm.tm_min;
3536 if ( i < j ) {
3537 ret = -1;
3538 } else if ( i > j ) {
3539 ret = 1;
3540 } else {
3541 i = sg->tm.tm_sec;
3542 j = sg2->tm.tm_sec;
3543 if ( i < j ) {
3544 ret = -1;
3545 } else if ( i > j ) {
3546 ret = 1;
3547 } else { ret = 0;}
3548 }
3549 }
3550 }
3551 }
3552 } else {
3553 ret = 0;
3554 }
3555
3556 if ( uiInfo.savegameStatus.sortDir ) {
3557 return ret;
3558 } else {
3559 return -ret;
3560 }
3561 }
3562
3563 /*
3564 ==============
3565 UI_SavegameSort
3566 ==============
3567 */
UI_SavegameSort(int column,qboolean force)3568 void UI_SavegameSort( int column, qboolean force ) {
3569 int cursel;
3570
3571 if ( !force ) {
3572 if ( uiInfo.savegameStatus.sortKey == column ) {
3573 return;
3574 }
3575 }
3576 uiInfo.savegameStatus.sortKey = column;
3577
3578 if ( uiInfo.savegameCount ) {
3579 qsort( &uiInfo.savegameStatus.displaySavegames[0], uiInfo.savegameCount, sizeof( int ), UI_SavegamesQsortCompare );
3580
3581 // re-select the one that was selected before sorting
3582 cursel = UI_SavegameIndexFromName( ui_savegameName.string );
3583 UI_FeederSelection( FEEDER_SAVEGAMES, cursel );
3584 Menu_SetFeederSelection( NULL, FEEDER_SAVEGAMES, cursel, NULL );
3585
3586 // and clear out the text entry
3587 trap_Cvar_Set( "ui_savegame", "" );
3588
3589 } else {
3590 trap_Cvar_Set( "ui_savegameName", "" );
3591 trap_Cvar_Set( "ui_savegameInfo", "(no savegames)" );
3592 }
3593
3594 }
3595 //----(SA) end
3596
3597
3598 /*
3599 ===============
3600 UI_LoadMods
3601 ===============
3602 */
UI_LoadMods(void)3603 static void UI_LoadMods( void ) {
3604 int numdirs;
3605 char dirlist[2048];
3606 char *dirptr;
3607 char *descptr;
3608 int i;
3609 int dirlen;
3610
3611 uiInfo.modCount = 0;
3612 numdirs = trap_FS_GetFileList( "$modlist", "", dirlist, sizeof( dirlist ) );
3613 dirptr = dirlist;
3614 for ( i = 0; i < numdirs; i++ ) {
3615 dirlen = strlen( dirptr ) + 1;
3616 descptr = dirptr + dirlen;
3617 uiInfo.modList[uiInfo.modCount].modName = String_Alloc( dirptr );
3618 uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc( descptr );
3619 dirptr += dirlen + strlen( descptr ) + 1;
3620 uiInfo.modCount++;
3621 if ( uiInfo.modCount >= MAX_MODS ) {
3622 break;
3623 }
3624 }
3625
3626 }
3627
3628
3629 /*
3630 ===============
3631 UI_LoadTeams
3632 ===============
3633 */
3634 // TTimo: unused
3635 /*
3636 static void UI_LoadTeams( void ) {
3637 char teamList[4096];
3638 char *teamName;
3639 int i, len, count;
3640
3641 count = trap_FS_GetFileList( "", "team", teamList, 4096 );
3642
3643 if (count) {
3644 teamName = teamList;
3645 for ( i = 0; i < count; i++ ) {
3646 len = strlen( teamName );
3647 UI_ParseTeamInfo(teamName);
3648 teamName += len + 1;
3649 }
3650 }
3651
3652 }
3653 */
3654
3655 /*
3656 ==============
3657 UI_DelSavegame
3658 ==============
3659 */
UI_DelSavegame(void)3660 static void UI_DelSavegame( void ) {
3661 int ret, i;
3662
3663 i = UI_SavegameIndexFromName2( ui_savegameName.string );
3664
3665 ret = trap_FS_Delete( va( "save/%s.svg", uiInfo.savegameList[i].savegameFile ) );
3666
3667 if ( ret ) {
3668 Com_Printf( "Deleted savegame: %s.svg\n", uiInfo.savegameList[i].savegameName );
3669 } else {
3670 Com_Printf( "Unable to delete savegame: %s.svg\n", uiInfo.savegameList[i].savegameName );
3671 }
3672
3673
3674 UI_SavegameSort( uiInfo.savegameStatus.sortKey, qtrue ); // re-sort
3675 }
3676
3677
3678
3679
3680
3681 #define SAVE_INFOSTRING_LENGTH 256 // defined in g_save.c
3682
3683
3684 /*
3685 ==============
3686 UI_ParseSavegame
3687 ==============
3688 */
3689
3690 static char *monthStr[12] =
3691 {
3692 "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
3693 };
3694
3695 /*
3696 ==============
3697 UI_ParseSavegame
3698 ==============
3699 */
UI_ParseSavegame(int index)3700 void UI_ParseSavegame( int index ) {
3701 fileHandle_t f;
3702 qtime_t *tm;
3703 int i, ver;
3704 static char buf[SAVE_INFOSTRING_LENGTH];
3705 char mapname[MAX_QPATH];
3706
3707 trap_FS_FOpenFile( va( "save/%s.svg", uiInfo.savegameList[index].savegameFile ), &f, FS_READ );
3708 if ( !f ) {
3709 return;
3710 }
3711
3712 // read the version
3713 trap_FS_Read( &ver, sizeof( i ), f );
3714
3715
3716 // 'info' if > 11
3717 // 'mission' if > 12
3718 // 'skill' if >13
3719 // 'time' if > 14
3720
3721 // if the version is wrong, just set some defaults and get out
3722 if ( ver < 9 ) { // don't try anything for really old savegames
3723 trap_FS_FCloseFile( f );
3724 uiInfo.savegameList[index].mapName = "unknownmap";
3725 uiInfo.savegameList[index].episode = -1;
3726 uiInfo.savegameList[index].savegameInfoText = "Gametime: (unknown)\nHealth: (unknown)\n(old savegame)";
3727
3728 uiInfo.savegameList[index].date = "temp_date";
3729 uiInfo.savegameList[index].time = "(old savegame)";
3730
3731 memset( &uiInfo.savegameList[index].tm, 0, sizeof( qtime_t ) );
3732 uiInfo.savegameList[index].time = String_Alloc( va( "(old savegame ver: %d)", ver ) );
3733 return;
3734 }
3735
3736 // read the mapname
3737 trap_FS_Read( mapname, MAX_QPATH, f );
3738 uiInfo.savegameList[index].mapName = String_Alloc( &mapname[0] );
3739
3740 // read the level time
3741 trap_FS_Read( &i, sizeof( i ), f );
3742
3743 // read the totalPlayTime
3744 trap_FS_Read( &i, sizeof( i ), f );
3745
3746 // read the episode
3747 trap_FS_Read( &i, sizeof( i ), f );
3748 uiInfo.savegameList[index].episode = i;
3749
3750 if ( ver < 12 ) {
3751 trap_FS_FCloseFile( f );
3752 uiInfo.savegameList[index].savegameInfoText = "Gametime: (unknown)\nHealth: (unknown)\n(old savegame)";
3753 uiInfo.savegameList[index].date = "temp_date";
3754 memset( &uiInfo.savegameList[index].tm, 0, sizeof( qtime_t ) );
3755 uiInfo.savegameList[index].time = String_Alloc( va( "(old savegame ver: %d)", ver ) );
3756 return;
3757 }
3758
3759 // read the info string length
3760 trap_FS_Read( &i, sizeof( i ), f );
3761
3762 // read the info string
3763 trap_FS_Read( buf, i, f );
3764 buf[i] = '\0'; //DAJ made it a char
3765 uiInfo.savegameList[index].savegameInfoText = String_Alloc( buf );
3766
3767 // time
3768 if ( ver > 14 ) {
3769 tm = &uiInfo.savegameList[index].tm;
3770 trap_FS_Read( &tm->tm_sec, sizeof( tm->tm_sec ), f ); // secs after the min
3771 trap_FS_Read( &tm->tm_min, sizeof( tm->tm_min ), f ); // mins after the hour
3772 trap_FS_Read( &tm->tm_hour, sizeof( tm->tm_hour ), f ); // hrs since midnight
3773 trap_FS_Read( &tm->tm_mday, sizeof( tm->tm_mday ), f );
3774 trap_FS_Read( &tm->tm_mon, sizeof( tm->tm_mon ), f );
3775 trap_FS_Read( &tm->tm_year, sizeof( tm->tm_year ), f ); // yrs from 1900
3776 trap_FS_Read( &tm->tm_wday, sizeof( tm->tm_wday ), f );
3777 trap_FS_Read( &tm->tm_yday, sizeof( tm->tm_yday ), f ); // days since jan1 (0-365)
3778 trap_FS_Read( &tm->tm_isdst, sizeof( tm->tm_isdst ), f );
3779 uiInfo.savegameList[index].time = String_Alloc( va( "%s %i, %i %02i:%02i", monthStr[tm->tm_mon], tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour, tm->tm_min ) );
3780 } else {
3781 memset( &uiInfo.savegameList[index].tm, 0, sizeof( qtime_t ) );
3782 uiInfo.savegameList[index].time = String_Alloc( va( "(old save ver: %d)", ver ) );
3783 }
3784
3785 trap_FS_FCloseFile( f );
3786 }
3787
3788 /*
3789 ==============
3790 UI_LoadSavegames
3791 ==============
3792 */
UI_LoadSavegames(char * dir)3793 static void UI_LoadSavegames( char *dir ) {
3794 char sglist[4096];
3795 char *sgname;
3796 int i, len;
3797
3798 if ( dir ) {
3799 uiInfo.savegameCount = trap_FS_GetFileList( va( "save/%s", dir ), "svg", sglist, 4096 );
3800 } else {
3801 uiInfo.savegameCount = trap_FS_GetFileList( "save", "svg", sglist, 4096 );
3802 }
3803
3804 if ( uiInfo.savegameCount ) {
3805 if ( uiInfo.savegameCount > MAX_SAVEGAMES ) {
3806 uiInfo.savegameCount = MAX_SAVEGAMES;
3807 }
3808 sgname = sglist;
3809 for ( i = 0; i < uiInfo.savegameCount; i++ ) {
3810
3811 len = strlen( sgname );
3812
3813 if ( !Q_stricmp( sgname, "current.svg" ) ) { // ignore some savegames that have special uses and shouldn't be loaded by the user directly
3814 i--;
3815 uiInfo.savegameCount -= 1;
3816 sgname += len + 1;
3817 continue;
3818 }
3819
3820 if ( !Q_stricmp( sgname + len - 4,".svg" ) ) {
3821 sgname[len - 4] = '\0';
3822 }
3823 // Q_strupr(sgname);
3824 if ( dir ) {
3825 uiInfo.savegameList[i].savegameFile = String_Alloc( va( "%s/%s", dir, sgname ) );
3826 } else {
3827 uiInfo.savegameList[i].savegameFile = String_Alloc( sgname );
3828 }
3829
3830 uiInfo.savegameList[i].savegameName = String_Alloc( sgname );
3831
3832 // get string into list for sorting too
3833 uiInfo.savegameStatus.displaySavegames[i] = i;
3834 // qsort( &uiInfo.savegameStatus.displaySavegames[0], uiInfo.savegameCount, sizeof(int), UI_SavegamesQsortCompare);
3835
3836 // read savegame and get needed info
3837 UI_ParseSavegame( i );
3838
3839 if ( uiInfo.savegameList[i].episode != -1 ) {
3840 uiInfo.savegameList[i].sshotImage = trap_R_RegisterShaderNoMip( va( "levelshots/episodeshots/e%d.tga", uiInfo.savegameList[i].episode + 1 ) );
3841 } else {
3842 uiInfo.savegameList[i].sshotImage = trap_R_RegisterShaderNoMip( "levelshots/episodeshots/e_unknown.tga" );
3843 }
3844
3845
3846
3847 sgname += len + 1;
3848 }
3849
3850 // sort it
3851 UI_SavegameSort( 0, qtrue );
3852
3853 // set current selection
3854 // i = UI_SavegameIndexFromName(ui_savegameName.string);
3855 // Menu_SetFeederSelection(NULL, FEEDER_SAVEGAMES, i, NULL);
3856 }
3857 }
3858
3859
3860 /*
3861 ===============
3862 UI_LoadMovies
3863 ===============
3864 */
UI_LoadMovies(void)3865 static void UI_LoadMovies( void ) {
3866 char movielist[4096];
3867 char *moviename;
3868 int i, len;
3869
3870 uiInfo.movieCount = trap_FS_GetFileList( "video", "roq", movielist, 4096 );
3871
3872 if ( uiInfo.movieCount ) {
3873 if ( uiInfo.movieCount > MAX_MOVIES ) {
3874 uiInfo.movieCount = MAX_MOVIES;
3875 }
3876 moviename = movielist;
3877 for ( i = 0; i < uiInfo.movieCount; i++ ) {
3878 len = strlen( moviename );
3879 if ( !Q_stricmp( moviename + len - 4,".roq" ) ) {
3880 moviename[len - 4] = '\0';
3881 }
3882 Q_strupr( moviename );
3883 uiInfo.movieList[i] = String_Alloc( moviename );
3884 moviename += len + 1;
3885 }
3886 }
3887
3888 }
3889
3890 #define NAMEBUFSIZE (MAX_DEMOS * 32)
3891
3892 /*
3893 ===============
3894 UI_LoadDemos
3895 ===============
3896 */
UI_LoadDemos(void)3897 static void UI_LoadDemos( void ) {
3898 char demolist[NAMEBUFSIZE];
3899 char demoExt[32];
3900 char *demoname;
3901
3902 int i, j, len;
3903 int protocol, protocolLegacy;
3904
3905 protocolLegacy = trap_Cvar_VariableValue("com_legacyprotocol");
3906 protocol = trap_Cvar_VariableValue("com_protocol");
3907
3908 if(!protocol)
3909 protocol = trap_Cvar_VariableValue("protocol");
3910 if(protocolLegacy == protocol)
3911 protocolLegacy = 0;
3912
3913 Com_sprintf(demoExt, sizeof(demoExt), ".%s%d", DEMOEXT, protocol);
3914 uiInfo.demoCount = trap_FS_GetFileList("demos", demoExt, demolist, ARRAY_LEN(demolist));
3915
3916 demoname = demolist;
3917 i = 0;
3918
3919 for(j = 0; j < 2; j++)
3920 {
3921 if(uiInfo.demoCount > MAX_DEMOS)
3922 uiInfo.demoCount = MAX_DEMOS;
3923
3924 for(; i < uiInfo.demoCount; i++)
3925 {
3926 len = strlen(demoname);
3927 uiInfo.demoList[i] = String_Alloc( demoname );
3928 demoname += len + 1;
3929 }
3930
3931 if(!j)
3932 {
3933 if(protocolLegacy > 0 && uiInfo.demoCount < MAX_DEMOS)
3934 {
3935 Com_sprintf(demoExt, sizeof(demoExt), ".%s%d", DEMOEXT, protocolLegacy);
3936 uiInfo.demoCount += trap_FS_GetFileList("demos", demoExt, demolist, ARRAY_LEN(demolist));
3937 demoname = demolist;
3938 }
3939 else
3940 break;
3941 }
3942 }
3943 }
3944
3945
3946 /*
3947 ==============
3948 UI_SetNextMap
3949 ==============
3950 */
3951 // TTimo: unused
3952 /*
3953 static qboolean UI_SetNextMap(int actual, int index) {
3954 int i;
3955 for (i = actual + 1; i < uiInfo.mapCount; i++) {
3956 if (uiInfo.mapList[i].active) {
3957 Menu_SetFeederSelection(NULL, FEEDER_MAPS, index + 1, "skirmish");
3958 return qtrue;
3959 }
3960 }
3961 return qfalse;
3962 }
3963 */
3964
3965 /*
3966 ==============
3967 UI_StartSkirmish
3968 ==============
3969 */
UI_StartSkirmish(qboolean next)3970 static void UI_StartSkirmish( qboolean next ) {
3971 #ifdef MISSIONPACK
3972 int i, k, g, delay, temp;
3973 float skill;
3974 char buff[MAX_STRING_CHARS];
3975
3976 if ( next ) {
3977 int actual;
3978 int index = trap_Cvar_VariableValue( "ui_mapIndex" );
3979 UI_MapCountByGameType( qtrue );
3980 UI_SelectedMap( index, &actual );
3981 if ( UI_SetNextMap( actual, index ) ) {
3982 } else {
3983 UI_GameType_HandleKey( 0, NULL, K_MOUSE1, qfalse );
3984 UI_MapCountByGameType( qtrue );
3985 Menu_SetFeederSelection( NULL, FEEDER_MAPS, 0, "skirmish" );
3986 }
3987 }
3988
3989 g = uiInfo.gameTypes[ui_gameType.integer].gtEnum;
3990 trap_Cvar_SetValue( "g_gametype", g );
3991 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentMap.integer].mapLoadName ) );
3992 skill = trap_Cvar_VariableValue( "g_spSkill" );
3993 trap_Cvar_Set( "ui_scoreMap", uiInfo.mapList[ui_currentMap.integer].mapName );
3994
3995 k = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_opponentName" ) );
3996
3997 trap_Cvar_Set( "ui_singlePlayerActive", "1" );
3998
3999 // set up sp overrides, will be replaced on postgame
4000 temp = trap_Cvar_VariableValue( "capturelimit" );
4001 trap_Cvar_Set( "ui_saveCaptureLimit", va( "%i", temp ) );
4002 temp = trap_Cvar_VariableValue( "fraglimit" );
4003 trap_Cvar_Set( "ui_saveFragLimit", va( "%i", temp ) );
4004
4005 UI_SetCapFragLimits( qfalse );
4006
4007 temp = trap_Cvar_VariableValue( "cg_drawTimer" );
4008 trap_Cvar_Set( "ui_drawTimer", va( "%i", temp ) );
4009 temp = trap_Cvar_VariableValue( "g_doWarmup" );
4010 trap_Cvar_Set( "ui_doWarmup", va( "%i", temp ) );
4011 temp = trap_Cvar_VariableValue( "g_friendlyFire" );
4012 trap_Cvar_Set( "ui_friendlyFire", va( "%i", temp ) );
4013 temp = trap_Cvar_VariableValue( "sv_maxClients" );
4014 trap_Cvar_Set( "ui_maxClients", va( "%i", temp ) );
4015 temp = trap_Cvar_VariableValue( "g_warmup" );
4016 trap_Cvar_Set( "ui_Warmup", va( "%i", temp ) );
4017 temp = trap_Cvar_VariableValue( "sv_pure" );
4018 trap_Cvar_Set( "ui_pure", va( "%i", temp ) );
4019
4020 trap_Cvar_Set( "cg_cameraOrbit", "0" );
4021 trap_Cvar_Set( "cg_thirdPerson", "0" );
4022 trap_Cvar_Set( "cg_drawTimer", "1" );
4023 trap_Cvar_Set( "g_doWarmup", "1" );
4024 trap_Cvar_Set( "g_warmup", "15" );
4025 trap_Cvar_Set( "sv_pure", "0" );
4026 trap_Cvar_Set( "g_friendlyFire", "0" );
4027 trap_Cvar_Set( "g_redTeam", UI_Cvar_VariableString( "ui_teamName" ) );
4028 trap_Cvar_Set( "g_blueTeam", UI_Cvar_VariableString( "ui_opponentName" ) );
4029
4030 if ( trap_Cvar_VariableValue( "ui_recordSPDemo" ) ) {
4031 Com_sprintf( buff, MAX_STRING_CHARS, "%s_%i", uiInfo.mapList[ui_currentMap.integer].mapLoadName, g );
4032 trap_Cvar_Set( "ui_recordSPDemoName", buff );
4033 }
4034
4035 delay = 500;
4036
4037 if ( g == GT_TOURNAMENT ) {
4038 trap_Cvar_Set( "sv_maxClients", "2" );
4039 Com_sprintf( buff, sizeof( buff ), "wait ; addbot %s %f " ", %i \n", uiInfo.mapList[ui_currentMap.integer].opponentName, skill, delay );
4040 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
4041 } else {
4042 temp = uiInfo.mapList[ui_currentMap.integer].teamMembers * 2;
4043 trap_Cvar_Set( "sv_maxClients", va( "%d", temp ) );
4044 for ( i = 0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers; i++ ) {
4045 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] );
4046 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
4047 delay += 500;
4048 }
4049 k = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
4050 for ( i = 0; i < uiInfo.mapList[ui_currentMap.integer].teamMembers - 1; i++ ) {
4051 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] );
4052 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
4053 delay += 500;
4054 }
4055 }
4056 if ( g >= GT_TEAM ) {
4057 // send team command for vanilla q3 game qvm
4058 trap_Cmd_ExecuteText( EXEC_APPEND, "wait 5; team Red\n" );
4059
4060 // set g_localTeamPref for ioq3 game qvm
4061 trap_Cvar_Set( "g_localTeamPref", "Red" );
4062 }
4063 #endif // #ifdef MISSIONPACK
4064 }
4065
4066 // NERVE - SMF
4067 /*
4068 ==============
4069 WM_ChangePlayerType
4070 ==============
4071 */
4072 itemDef_t *Menu_FindItemByName( menuDef_t *menu, const char *p );
4073 void Menu_ShowItemByName( menuDef_t *menu, const char *p, qboolean bShow );
4074
4075 #define ITEM_GRENADES 1
4076 #define ITEM_MEDKIT 2
4077
4078 #define ITEM_PISTOL 1
4079
4080 #define DEFAULT_PISTOL
4081
4082 #define PT_KNIFE ( 1 )
4083 #define PT_PISTOL ( 1 << 2 )
4084 #define PT_RIFLE ( 1 << 3 )
4085 #define PT_LIGHTONLY ( 1 << 4 )
4086 #define PT_GRENADES ( 1 << 5 )
4087 #define PT_EXPLOSIVES ( 1 << 6 )
4088 #define PT_MEDKIT ( 1 << 7 )
4089
4090 typedef struct {
4091 const char *name;
4092 int items;
4093 } playerType_t;
4094
4095 static playerType_t playerTypes[] = {
4096 { "player_window_soldier", PT_KNIFE | PT_PISTOL | PT_RIFLE | PT_GRENADES },
4097 { "player_window_medic", PT_KNIFE | PT_PISTOL | PT_MEDKIT },
4098 { "player_window_engineer", PT_KNIFE | PT_PISTOL | PT_LIGHTONLY | PT_EXPLOSIVES | PT_GRENADES },
4099 { "player_window_lieutenant", PT_KNIFE | PT_PISTOL | PT_RIFLE | PT_EXPLOSIVES }
4100 };
4101
4102 typedef struct {
4103 int weapindex;
4104
4105 const char *desc;
4106 int flags;
4107 const char *cvar;
4108 int value;
4109 const char *name;
4110
4111 const char *torso_anim;
4112 const char *legs_anim;
4113 } weaponType_t;
4114
4115 // NERVE - SMF - this is the weapon info list [what can and can't be used by character classes]
4116 // - This list is seperate from the actual text names in the listboxes for localization purposes.
4117 // - The list boxes look up this list by the cvar value.
4118 static weaponType_t weaponTypes[] = {
4119 { 0, "NULL", 0, "none", 0, "none", "", "" },
4120
4121 { WP_COLT, "1911 pistol", PT_PISTOL, "mp_weapon", 0, "ui/assets/weapon_colt1911.tga", "firing_pistolB_1", "stand_pistolB" },
4122 { WP_LUGER, "Luger pistol", PT_PISTOL, "mp_weapon", 1, "ui/assets/weapon_luger.tga", "firing_pistolB_1", "stand_pistolB" },
4123 // { 0, "Medkit", PT_MEDKIT, "mp_item2", 2, "ui/assets/item_medkit.tga", "firing_pistolB_1", "stand_pistolB" },
4124
4125 { WP_MP40, "MP40 submachinegun", PT_LIGHTONLY | PT_RIFLE, "mp_weapon", 3, "ui/assets/weapon_mp40.tga", "relaxed_idle_2h_1", "relaxed_idle_2h_1" },
4126 { WP_THOMPSON, "Thompson submachinegun", PT_LIGHTONLY | PT_RIFLE, "mp_weapon", 4, "ui/assets/weapon_thompson.tga", "relaxed_idle_2h_1", "relaxed_idle_2h_1" },
4127 { WP_STEN, "Sten submachinegun", PT_LIGHTONLY | PT_RIFLE, "mp_weapon", 5, "ui/assets/weapon_sten.tga", "relaxed_idle_2h_1", "relaxed_idle_2h_1" },
4128
4129 { WP_MAUSER, "Mauser sniper rifle", PT_RIFLE, "mp_weapon", 6, "ui/assets/weapon_mauser.tga", "stand_rifle", "stand_rifle" },
4130 { WP_GARAND, "Garand rifle", PT_RIFLE, "mp_weapon", 7, "ui/assets/weapon_mauser.tga", "stand_rifle", "stand_rifle" },
4131 { WP_PANZERFAUST, "Panzerfaust", PT_RIFLE, "mp_weapon", 8, "ui/assets/weapon_panzerfaust.tga", "stand_machinegun", "stand_machinegun" },
4132 { WP_VENOM, "Minigun", PT_RIFLE, "mp_weapon", 9, "ui/assets/weapon_venom.tga", "stand_machinegun", "stand_machinegun" },
4133 { WP_FLAMETHROWER, "Flamethrower", PT_RIFLE, "mp_weapon", 10, "ui/assets/weapon_flamethrower.tga","stand_machinegun", "stand_machinegun" },
4134
4135 { WP_GRENADE_PINEAPPLE, "Pineapple grenade", PT_GRENADES, "mp_item1", 11, "ui/assets/weapon_grenade.tga", "firing_pistolB_1", "stand_pistolB" },
4136 { WP_GRENADE_LAUNCHER, "Stick grenade", PT_GRENADES, "mp_item1", 12, "ui/assets/weapon_grenade_ger.tga", "firing_pistolB_1", "stand_pistolB" },
4137
4138 { WP_DYNAMITE, "Explosives", PT_EXPLOSIVES, "mp_item2", 13, "ui/assets/weapon_dynamite.tga", "firing_pistolB_1", "stand_pistolB" },
4139
4140 { 0, NULL, 0, NULL, 0, NULL, NULL, NULL }
4141 };
4142
4143 typedef struct {
4144 char *name;
4145 int flags;
4146 char *shader;
4147 } uiitemType_t;
4148
4149 #define UI_KNIFE_PIC "window_knife_pic"
4150 #define UI_PISTOL_PIC "window_pistol_pic"
4151 #define UI_WEAPON_PIC "window_weapon_pic"
4152 #define UI_ITEM1_PIC "window_item1_pic"
4153 #define UI_ITEM2_PIC "window_item2_pic"
4154
4155 static uiitemType_t itemTypes[] = {
4156 { UI_KNIFE_PIC, PT_KNIFE, "ui/assets/weapon_knife.tga" },
4157 { UI_PISTOL_PIC, PT_PISTOL, "ui/assets/weapon_colt1911.tga" },
4158
4159 { UI_WEAPON_PIC, PT_RIFLE, "ui/assets/weapon_mauser.tga" },
4160
4161 { UI_ITEM1_PIC, PT_MEDKIT, "ui/assets/item_medkit.tga" },
4162
4163 { UI_ITEM1_PIC, PT_GRENADES, "ui/assets/weapon_grenade.tga" },
4164 { UI_ITEM2_PIC, PT_EXPLOSIVES, "ui/assets/weapon_dynamite.tga" },
4165
4166 { NULL, 0, NULL }
4167 };
4168
4169
WM_getWeaponIndex(void)4170 int WM_getWeaponIndex( void ) {
4171 int lookupIndex, i;
4172
4173 lookupIndex = trap_Cvar_VariableValue( "mp_weapon" );
4174
4175 for ( i = 1; weaponTypes[i].name; i++ ) {
4176 if ( weaponTypes[i].value == lookupIndex ) {
4177 return weaponTypes[i].weapindex;
4178 }
4179 }
4180
4181 return 0;
4182 }
4183
WM_getWeaponAnim(const char ** torso_anim,const char ** legs_anim)4184 void WM_getWeaponAnim( const char **torso_anim, const char **legs_anim ) {
4185 int lookupIndex, i;
4186
4187 lookupIndex = trap_Cvar_VariableValue( "mp_weapon" );
4188
4189 for ( i = 1; weaponTypes[i].name; i++ ) {
4190 if ( weaponTypes[i].value == lookupIndex ) {
4191 *torso_anim = weaponTypes[i].torso_anim;
4192 *legs_anim = weaponTypes[i].legs_anim;
4193 return;
4194 }
4195 }
4196 }
4197
WM_ChangePlayerType(void)4198 static void WM_ChangePlayerType( void ) {
4199 int i, j, playerType;
4200 menuDef_t *menu = Menu_GetFocused();
4201 itemDef_t *itemdef, *itemdef2;
4202
4203 playerType = trap_Cvar_VariableValue( "mp_playerType" );
4204
4205 for ( i = 0; i < 4; i++ ) {
4206 itemdef = Menu_FindItemByName( menu, playerTypes[i].name );
4207 if ( !itemdef ) {
4208 continue;
4209 }
4210
4211 if ( i == playerType ) {
4212 Menu_ShowItemByName( itemdef->parent, playerTypes[i].name, qtrue );
4213 } else {
4214 Menu_ShowItemByName( itemdef->parent, playerTypes[i].name, qfalse );
4215 }
4216
4217 // selected only settings
4218 if ( i != playerType ) {
4219 continue;
4220 }
4221
4222 // force all to none first
4223 for ( j = 0; itemTypes[j].name; j++ ) {
4224 itemdef2 = Menu_FindItemByName( menu, itemTypes[j].name );
4225 if ( itemdef2 ) {
4226 itemdef2->window.background = DC->registerShaderNoMip( "ui/assets/item_none.tga" );
4227 }
4228 }
4229
4230 // set values
4231 for ( j = 0; itemTypes[j].name; j++ ) {
4232 itemdef2 = Menu_FindItemByName( menu, itemTypes[j].name );
4233 if ( itemdef2 && ( playerTypes[i].items & itemTypes[j].flags ) ) {
4234 itemdef2->window.background = DC->registerShaderNoMip( itemTypes[j].shader );
4235 }
4236 }
4237 }
4238 }
4239
WM_GetSpawnPoints(void)4240 void WM_GetSpawnPoints( void ) {
4241 char cs[MAX_STRING_CHARS];
4242 const char *s;
4243 int i;
4244
4245 trap_GetConfigString( CS_MULTI_INFO, cs, sizeof( cs ) );
4246 s = Info_ValueForKey( cs, "numspawntargets" );
4247
4248 if ( !s ) {
4249 return;
4250 }
4251
4252 // first index is for autopicking
4253 Q_strncpyz( uiInfo.spawnPoints[0], "Auto Pick", MAX_SPAWNDESC );
4254
4255 uiInfo.spawnCount = atoi( s ) + 1;
4256
4257 for ( i = 1; i < uiInfo.spawnCount; i++ ) {
4258 trap_GetConfigString( CS_MULTI_SPAWNTARGETS + i, cs, sizeof( cs ) );
4259
4260 s = Info_ValueForKey( cs, "spawn_targ" );
4261 if ( !s ) {
4262 return;
4263 }
4264
4265 Q_strncpyz( uiInfo.spawnPoints[i], s, MAX_SPAWNDESC );
4266 }
4267 }
4268
WM_HideItems(void)4269 void WM_HideItems( void ) {
4270 menuDef_t *menu = Menu_GetFocused();
4271
4272 Menu_ShowItemByName( menu, "window_pickplayer", qfalse );
4273 Menu_ShowItemByName( menu, "window_weap", qfalse );
4274 Menu_ShowItemByName( menu, "weap_*", qfalse );
4275 Menu_ShowItemByName( menu, "pistol_*", qfalse );
4276 Menu_ShowItemByName( menu, "grenade_*", qfalse );
4277 Menu_ShowItemByName( menu, "player_type", qfalse );
4278 }
4279
WM_PickItem(int selectionType,int itemIndex)4280 void WM_PickItem( int selectionType, int itemIndex ) {
4281 menuDef_t *menu = Menu_GetFocused();
4282 int playerType;
4283
4284 if ( selectionType == WM_SELECT_TEAM ) {
4285 switch ( itemIndex ) {
4286 case WM_AXIS:
4287 trap_Cvar_Set( "mp_team", "0" );
4288 break;
4289 case WM_ALLIES:
4290 trap_Cvar_Set( "mp_team", "1" );
4291 break;
4292 case WM_SPECTATOR:
4293 trap_Cvar_Set( "mp_team", "2" );
4294 break;
4295 }
4296 } else if ( selectionType == WM_SELECT_CLASS ) {
4297 switch ( itemIndex ) {
4298 case WM_START_SELECT:
4299 break;
4300 case WM_SOLDIER:
4301 trap_Cvar_Set( "mp_playerType", "0" );
4302 trap_Cvar_Set( "mp_weapon", "0" );
4303 break;
4304 case WM_MEDIC:
4305 trap_Cvar_Set( "mp_playerType", "1" );
4306 trap_Cvar_Set( "mp_weapon", "0" );
4307 break;
4308 case WM_ENGINEER:
4309 trap_Cvar_Set( "mp_playerType", "2" );
4310 trap_Cvar_Set( "mp_weapon", "0" );
4311 break;
4312 case WM_LIEUTENANT:
4313 trap_Cvar_Set( "mp_playerType", "3" );
4314 trap_Cvar_Set( "mp_weapon", "0" );
4315 break;
4316 }
4317 } else if ( selectionType == WM_SELECT_WEAPON ) {
4318 if ( itemIndex == WM_START_SELECT ) {
4319 } else {
4320 trap_Cvar_Set( weaponTypes[itemIndex].cvar, va( "%i", weaponTypes[itemIndex].value ) );
4321 }
4322 } else if ( selectionType == WM_SELECT_PISTOL ) {
4323 if ( itemIndex == WM_START_SELECT ) {
4324 // hide all other menus first
4325 WM_HideItems();
4326
4327 // show this menu
4328 Menu_ShowItemByName( menu, "window_weap", qtrue );
4329 Menu_ShowItemByName( menu, "pistol_*", qtrue );
4330 } else {
4331 itemDef_t *itemdef = Menu_FindItemByName( menu, UI_PISTOL_PIC );
4332
4333 trap_Cvar_Set( weaponTypes[itemIndex].cvar, va( "%i", weaponTypes[itemIndex].value ) );
4334
4335 if ( itemdef ) {
4336 itemdef->window.background = DC->registerShaderNoMip( weaponTypes[itemIndex].name );
4337 }
4338
4339 Menu_ShowItemByName( menu, "window_weap", qfalse );
4340 Menu_ShowItemByName( menu, "pistol_*", qfalse );
4341 }
4342 } else if ( selectionType == WM_SELECT_GRENADE ) {
4343 if ( itemIndex == WM_START_SELECT ) {
4344 // hide all other menus first
4345 WM_HideItems();
4346
4347 // show this menu
4348 playerType = trap_Cvar_VariableValue( "mp_playerType" );
4349
4350 if ( playerType == 1 || playerType == 3 ) {
4351 return;
4352 }
4353
4354 Menu_ShowItemByName( menu, "window_weap", qtrue );
4355 Menu_ShowItemByName( menu, "grenade_*", qtrue );
4356 } else {
4357 itemDef_t *itemdef = Menu_FindItemByName( menu, UI_ITEM1_PIC );
4358
4359 trap_Cvar_Set( weaponTypes[itemIndex].cvar, va( "%i", weaponTypes[itemIndex].value ) );
4360
4361 if ( itemdef ) {
4362 itemdef->window.background = DC->registerShaderNoMip( weaponTypes[itemIndex].name );
4363 }
4364
4365 Menu_ShowItemByName( menu, "window_weap", qfalse );
4366 Menu_ShowItemByName( menu, "grenade_*", qfalse );
4367 }
4368 }
4369 }
4370
WM_LimboChat(void)4371 void WM_LimboChat( void ) {
4372 char buf[200];
4373
4374 trap_Cvar_VariableStringBuffer( "ui_cmd", buf, 200 );
4375
4376 if ( strlen( buf ) ) {
4377 trap_Cmd_ExecuteText( EXEC_APPEND, va( "say_limbo %s\n", buf ) );
4378 }
4379
4380 trap_Cvar_Set( "ui_cmd", "" );
4381 }
4382
4383 extern qboolean g_waitingForKey;
4384 extern qboolean g_editingField;
4385 extern itemDef_t *g_editItem;
4386
WM_ActivateLimboChat(void)4387 void WM_ActivateLimboChat( void ) {
4388 menuDef_t *menu;
4389 itemDef_t *itemdef;
4390
4391 Menu_GetFocused();
4392 menu = Menus_ActivateByName( "wm_limboChat" );
4393
4394 if ( !menu || g_editItem ) {
4395 return;
4396 }
4397
4398 itemdef = Menu_FindItemByName( menu, "window_limbo_chat" );
4399
4400 if ( itemdef ) {
4401 itemdef->cursorPos = 0;
4402 g_editingField = qtrue;
4403 g_editItem = itemdef;
4404 DC->setOverstrikeMode( qtrue );
4405 }
4406 }
4407 // -NERVE - SMF
4408
4409 /*
4410 ==============
4411 UI_Update
4412 ==============
4413 */
UI_Update(const char * name)4414 static void UI_Update( const char *name ) {
4415 int val = trap_Cvar_VariableValue( name );
4416
4417 if ( Q_stricmp( name, "ui_SetName" ) == 0 ) {
4418 trap_Cvar_Set( "name", UI_Cvar_VariableString( "ui_Name" ) );
4419 } else if ( Q_stricmp( name, "ui_setRate" ) == 0 ) {
4420 float rate = trap_Cvar_VariableValue( "rate" );
4421 if ( rate >= 5000 ) {
4422 trap_Cvar_Set( "cl_maxpackets", "30" );
4423 trap_Cvar_Set( "cl_packetdup", "1" );
4424 } else if ( rate >= 4000 ) {
4425 trap_Cvar_Set( "cl_maxpackets", "15" );
4426 trap_Cvar_Set( "cl_packetdup", "2" ); // favor less prediction errors when there's packet loss
4427 } else {
4428 trap_Cvar_Set( "cl_maxpackets", "15" );
4429 trap_Cvar_Set( "cl_packetdup", "1" ); // favor lower bandwidth
4430 }
4431 } else if ( Q_stricmp( name, "ui_GetName" ) == 0 ) {
4432 trap_Cvar_Set( "ui_Name", UI_Cvar_VariableString( "name" ) );
4433 } else if ( Q_stricmp( name, "r_colorbits" ) == 0 ) {
4434 switch ( val ) {
4435 case 0:
4436 trap_Cvar_SetValue( "r_depthbits", 0 );
4437 trap_Cvar_SetValue( "r_stencilbits", 0 );
4438 break;
4439 case 16:
4440 trap_Cvar_SetValue( "r_depthbits", 16 );
4441 trap_Cvar_SetValue( "r_stencilbits", 0 );
4442 break;
4443 case 32:
4444 trap_Cvar_SetValue( "r_depthbits", 24 );
4445 trap_Cvar_SetValue( "r_stencilbits", 8 );
4446 break;
4447 }
4448 } else if ( Q_stricmp( name, "r_lodbias" ) == 0 ) {
4449 switch ( val ) {
4450 case 0:
4451 trap_Cvar_SetValue( "r_subdivisions", 4 );
4452 break;
4453 case 1:
4454 trap_Cvar_SetValue( "r_subdivisions", 12 );
4455 break;
4456 case 2:
4457 trap_Cvar_SetValue( "r_subdivisions", 20 );
4458 break;
4459 }
4460 } else if ( Q_stricmp( name, "ui_glCustom" ) == 0 ) {
4461 switch ( val ) {
4462 case 0: // high quality
4463 trap_Cvar_SetValue( "r_subdivisions", 4 );
4464 trap_Cvar_SetValue( "r_vertexlight", 0 );
4465 trap_Cvar_SetValue( "r_lodbias", 0 );
4466 trap_Cvar_SetValue( "r_colorbits", 32 );
4467 trap_Cvar_SetValue( "r_depthbits", 24 );
4468 trap_Cvar_SetValue( "r_stencilbits", 8 );
4469 trap_Cvar_SetValue( "r_picmip", 0 );
4470 trap_Cvar_SetValue( "r_picmip2", 0 );
4471 trap_Cvar_SetValue( "r_texturebits", 32 );
4472 trap_Cvar_SetValue( "r_fastSky", 0 );
4473 trap_Cvar_SetValue( "r_dynamiclight", 1 );
4474 trap_Cvar_SetValue( "r_inGameVideo", 1 );
4475 trap_Cvar_SetValue( "cg_shadows", 1 );
4476 trap_Cvar_SetValue( "cg_brassTime", 2500 );
4477 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
4478 trap_Cvar_SetValue( "r_ext_compressed_textures", 0 );
4479 trap_Cvar_SetValue( "r_overBrightBits", 0 );
4480 trap_Cvar_Set( "cl_renderer", "rend2" );
4481 trap_Cvar_SetValue( "r_hdr", 1 );
4482 trap_Cvar_SetValue( "r_postProcess", 1 );
4483 trap_Cvar_SetValue( "r_toneMap", 1 );
4484 trap_Cvar_SetValue( "r_autoExposure", 1 );
4485 trap_Cvar_SetValue( "r_normalMapping", 1 );
4486 trap_Cvar_SetValue( "r_specularMapping", 1 );
4487 trap_Cvar_SetValue( "r_deluxeMapping", 1 );
4488 trap_Cvar_SetValue( "r_forceSun", 1 );
4489 trap_Cvar_SetValue( "r_drawSunRays", 1 );
4490 trap_Cvar_SetValue( "r_sunShadows", 1 );
4491 trap_Cvar_SetValue( "r_shadowFilter", 1 );
4492 #ifdef USE_BLOOM
4493 trap_Cvar_SetValue( "r_bloom", 1 );
4494 #endif
4495 break;
4496 case 1: // normal
4497 trap_Cvar_SetValue( "r_subdivisions", 4 );
4498 trap_Cvar_SetValue( "r_vertexlight", 0 );
4499 trap_Cvar_SetValue( "r_lodbias", 0 );
4500 trap_Cvar_SetValue( "r_colorbits", 0 );
4501 trap_Cvar_SetValue( "r_depthbits", 0 );
4502 trap_Cvar_SetValue( "r_stencilbits", 0 );
4503 trap_Cvar_SetValue( "r_picmip", 0 );
4504 trap_Cvar_SetValue( "r_picmip2", 1 );
4505 trap_Cvar_SetValue( "r_texturebits", 0 );
4506 trap_Cvar_SetValue( "r_fastSky", 0 );
4507 trap_Cvar_SetValue( "r_dynamiclight", 1 );
4508 trap_Cvar_SetValue( "r_inGameVideo", 1 );
4509 trap_Cvar_SetValue( "cg_shadows", 1 );
4510 trap_Cvar_SetValue( "cg_brassTime", 2500 );
4511 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
4512 trap_Cvar_SetValue( "r_ext_compressed_textures", 0 );
4513 trap_Cvar_SetValue( "r_overBrightBits", 0 );
4514 trap_Cvar_Set( "cl_renderer", "opengl1" );
4515 #ifdef USE_BLOOM
4516 trap_Cvar_SetValue( "r_bloom", 1 );
4517 #endif
4518 break;
4519 case 2: // fast
4520 trap_Cvar_SetValue( "r_subdivisions", 12 );
4521 trap_Cvar_SetValue( "r_vertexlight", 0 );
4522 trap_Cvar_SetValue( "r_lodbias", 1 );
4523 trap_Cvar_SetValue( "r_colorbits", 0 );
4524 trap_Cvar_SetValue( "r_depthbits", 0 );
4525 trap_Cvar_SetValue( "r_stencilbits", 0 );
4526 trap_Cvar_SetValue( "r_picmip", 1 );
4527 trap_Cvar_SetValue( "r_picmip2", 2 );
4528 trap_Cvar_SetValue( "r_texturebits", 0 );
4529 trap_Cvar_SetValue( "cg_shadows", 0 );
4530 trap_Cvar_SetValue( "r_fastSky", 1 );
4531 trap_Cvar_SetValue( "r_dynamiclight", 0 );
4532 trap_Cvar_SetValue( "r_inGameVideo", 0 );
4533 trap_Cvar_SetValue( "cg_brassTime", 0 );
4534 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
4535 trap_Cvar_SetValue( "r_ext_compressed_textures", 1 );
4536 trap_Cvar_SetValue( "r_overBrightBits", 0 );
4537 trap_Cvar_Set( "cl_renderer", "opengl1" );
4538 #ifdef USE_BLOOM
4539 trap_Cvar_SetValue( "r_bloom", 0 );
4540 #endif
4541 break;
4542 case 3: // fastest
4543 trap_Cvar_SetValue( "r_subdivisions", 20 );
4544 trap_Cvar_SetValue( "r_vertexlight", 1 );
4545 trap_Cvar_SetValue( "r_lodbias", 2 );
4546 trap_Cvar_SetValue( "r_colorbits", 0 );
4547 trap_Cvar_SetValue( "r_depthbits", 0 );
4548 trap_Cvar_SetValue( "r_stencilbits", 0 );
4549 trap_Cvar_SetValue( "r_picmip", 2 );
4550 trap_Cvar_SetValue( "r_picmip2", 3 );
4551 trap_Cvar_SetValue( "r_texturebits", 0 );
4552 trap_Cvar_SetValue( "cg_shadows", 0 );
4553 trap_Cvar_SetValue( "cg_brassTime", 0 );
4554 trap_Cvar_SetValue( "r_fastSky", 1 );
4555 trap_Cvar_SetValue( "r_dynamiclight", 0 );
4556 trap_Cvar_SetValue( "r_inGameVideo", 0 );
4557 trap_Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_NEAREST" );
4558 trap_Cvar_SetValue( "r_ext_compressed_textures", 1 );
4559 trap_Cvar_SetValue( "r_overBrightBits", 0 );
4560 trap_Cvar_Set( "cl_renderer", "opengl1" );
4561 #ifdef USE_BLOOM
4562 trap_Cvar_SetValue( "r_bloom", 0 );
4563 #endif
4564 break;
4565
4566 case 999: // 999 is reserved for having set default values ("recommended")
4567 break;
4568 }
4569 } else if ( Q_stricmp( name, "ui_mousePitch" ) == 0 ) {
4570 if ( val == 0 ) {
4571 trap_Cvar_SetValue( "m_pitch", 0.022f );
4572 } else {
4573 trap_Cvar_SetValue( "m_pitch", -0.022f );
4574 }
4575
4576 //----(SA) added
4577 } else if ( Q_stricmp( name, "ui_savegameListAutosave" ) == 0 ) {
4578 if ( val == 0 ) {
4579 UI_LoadSavegames( NULL );
4580 } else {
4581 // TODO: get this from a cvar, so more complicated
4582 // directory structures can be set up later if desired
4583 // cvar = getcvar("ui_savegameSubdir");
4584 // UI_LoadSavegames(cvar.value);
4585 UI_LoadSavegames( "autosave" ); // get from default directory 'main/save/autosave/*.svg'
4586 }
4587 }
4588 //----(SA) end
4589
4590 }
4591
4592
4593 /*
4594 ==============
4595 UI_RunMenuScript
4596 ==============
4597 */
4598
UI_RunMenuScript(char ** args)4599 static void UI_RunMenuScript( char **args ) {
4600 const char *name, *name2;
4601 char buff[1024];
4602
4603 if ( String_Parse( args, &name ) ) {
4604 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4605 if ( Q_stricmp( name, "StartServer" ) == 0 ) {
4606 float skill;
4607 int i, clients;
4608 trap_Cvar_Set( "cg_thirdPerson", "0" );
4609 trap_Cvar_Set( "cg_cameraOrbit", "0" );
4610 trap_Cvar_Set( "ui_singlePlayerActive", "0" );
4611 trap_Cvar_SetValue( "dedicated", Com_Clamp( 0, 2, ui_dedicated.integer ) );
4612 trap_Cvar_SetValue( "g_gametype", Com_Clamp( 0, 8, uiInfo.gameTypes[ui_netGameType.integer].gtEnum ) );
4613 trap_Cmd_ExecuteText( EXEC_APPEND, va( "wait ; wait ; map %s\n", uiInfo.mapList[ui_currentNetMap.integer].mapLoadName ) );
4614
4615 skill = trap_Cvar_VariableValue( "g_spSkill" );
4616
4617 // set max clients based on spots
4618 clients = 0;
4619 for ( i = 0; i < PLAYERS_PER_TEAM; i++ ) {
4620 int bot = trap_Cvar_VariableValue( va( "ui_blueteam%i", i + 1 ) );
4621 if ( bot >= 0 ) {
4622 clients++;
4623 }
4624 bot = trap_Cvar_VariableValue( va( "ui_redteam%i", i + 1 ) );
4625 if ( bot >= 0 ) {
4626 clients++;
4627 }
4628 }
4629 if ( clients == 0 ) {
4630 clients = 8;
4631 }
4632 trap_Cvar_Set( "sv_maxClients", va( "%d",clients ) );
4633
4634 for ( i = 0; i < PLAYERS_PER_TEAM; i++ ) {
4635 int bot = trap_Cvar_VariableValue( va( "ui_blueteam%i", i + 1 ) );
4636 if ( bot > 1 ) {
4637 if ( ui_actualNetGameType.integer >= GT_TEAM ) {
4638 Com_sprintf( buff, sizeof( buff ), "addbot %s %f %s\n", uiInfo.characterList[bot - 2].name, skill, "Blue" );
4639 } else {
4640 // NERVE - SMF - no bots in wolf multiplayer
4641 // Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);
4642 }
4643 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
4644 }
4645 bot = trap_Cvar_VariableValue( va( "ui_redteam%i", i + 1 ) );
4646 if ( bot > 1 ) {
4647 if ( ui_actualNetGameType.integer >= GT_TEAM ) {
4648 Com_sprintf( buff, sizeof( buff ), "addbot %s %f %s\n", uiInfo.characterList[bot - 2].name, skill, "Red" );
4649 } else {
4650 // NERVE - SMF - no bots in wolf multiplayer
4651 // Com_sprintf( buff, sizeof(buff), "addbot %s %f \n", UI_GetBotNameByNumber(bot-2), skill);
4652 }
4653 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
4654 }
4655 }
4656 } else if ( Q_stricmp( name, "updateSPMenu" ) == 0 ) {
4657 UI_SetCapFragLimits( qtrue );
4658 UI_MapCountByGameType( qtrue );
4659 ui_mapIndex.integer = UI_GetIndexFromSelection( ui_currentMap.integer );
4660 trap_Cvar_Set( "ui_mapIndex", va( "%d", ui_mapIndex.integer ) );
4661 Menu_SetFeederSelection( NULL, FEEDER_MAPS, ui_mapIndex.integer, "skirmish" );
4662 UI_GameType_HandleKey( 0, NULL, K_MOUSE1, qfalse );
4663 UI_GameType_HandleKey( 0, NULL, K_MOUSE2, qfalse );
4664 } else if ( Q_stricmp( name, "resetDefaults" ) == 0 ) {
4665 // SP was like...
4666 // trap_Cmd_ExecuteText( EXEC_APPEND, "exec default.cfg\n");
4667 // trap_Cmd_ExecuteText( EXEC_APPEND, "cvar_restart\n");
4668 // Controls_SetDefaults();
4669 #ifdef CINEMATICS_INTRO
4670 // trap_Cvar_Set("com_introPlayed", "1" );
4671 #endif
4672 // trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
4673
4674 // from MP 11/12/01
4675 trap_Cmd_ExecuteText( EXEC_NOW, "cvar_restart\n" ); // NERVE - SMF - changed order
4676 trap_Cmd_ExecuteText( EXEC_NOW, "exec default.cfg\n" );
4677 trap_Cmd_ExecuteText( EXEC_NOW, "exec language.cfg\n" ); // NERVE - SMF
4678 trap_Cmd_ExecuteText( EXEC_NOW, "setRecommended\n" ); // NERVE - SMF
4679 Controls_SetDefaults();
4680 #ifdef CINEMATICS_INTRO
4681 trap_Cvar_Set( "com_introPlayed", "1" );
4682 #endif
4683 trap_Cvar_Set( "com_recommendedSet", "1" ); // NERVE - SMF
4684 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart\n" );
4685 // end from MP
4686 } else if ( Q_stricmp( name, "getCDKey" ) == 0 ) {
4687 char out[17];
4688 trap_GetCDKey( buff, 17 );
4689 trap_Cvar_Set( "cdkey1", "" );
4690 trap_Cvar_Set( "cdkey2", "" );
4691 trap_Cvar_Set( "cdkey3", "" );
4692 trap_Cvar_Set( "cdkey4", "" );
4693 trap_Cvar_Set( "cdkeychecksum", "" );
4694 if ( buff[0] != 32 && strlen( buff ) == CDKEY_LEN ) {
4695 Q_strncpyz( out, buff, 5 );
4696 trap_Cvar_Set( "cdkey1", out );
4697 Q_strncpyz( out, buff + 4, 5 );
4698 trap_Cvar_Set( "cdkey2", out );
4699 Q_strncpyz( out, buff + 8, 5 );
4700 trap_Cvar_Set( "cdkey3", out );
4701 Q_strncpyz( out, buff + 12, 5 );
4702 trap_Cvar_Set( "cdkey4", out );
4703 }
4704
4705 } else if ( Q_stricmp( name, "verifyCDKey" ) == 0 ) {
4706 buff[0] = '\0';
4707 Q_strcat( buff, 1024, UI_Cvar_VariableString( "cdkey1" ) );
4708 Q_strcat( buff, 1024, UI_Cvar_VariableString( "cdkey2" ) );
4709 Q_strcat( buff, 1024, UI_Cvar_VariableString( "cdkey3" ) );
4710 Q_strcat( buff, 1024, UI_Cvar_VariableString( "cdkey4" ) );
4711 trap_Cvar_Set( "cdkey", buff );
4712 if ( trap_VerifyCDKey( buff, UI_Cvar_VariableString( "cdkeychecksum" ) ) ) {
4713 trap_Cvar_Set( "ui_cdkeyvalid", "CD Key Appears to be valid." );
4714 trap_SetCDKey( buff );
4715 } else {
4716 trap_Cvar_Set( "ui_cdkeyvalid", "CD Key does not appear to be valid." );
4717 }
4718 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4719 } else if ( Q_stricmp( name, "loadArenas" ) == 0 ) {
4720 UI_LoadArenasIntoMapList();
4721 UI_MapCountByGameType( qfalse );
4722 Menu_SetFeederSelection( NULL, FEEDER_ALLMAPS, 0, "createserver" );
4723 //#endif // #ifdef MISSIONPACK
4724 } else if ( Q_stricmp( name, "saveControls" ) == 0 ) {
4725 Controls_SetConfig( qtrue );
4726 } else if ( Q_stricmp( name, "loadControls" ) == 0 ) {
4727 Controls_GetConfig();
4728 } else if ( Q_stricmp( name, "clearError" ) == 0 ) {
4729 trap_Cvar_Set( "com_errorMessage", "" );
4730 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4731 } else if ( Q_stricmp( name, "loadGameInfo" ) == 0 ) {
4732 UI_ParseGameInfo( "gameinfo.txt" );
4733 UI_LoadBestScores( uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum );
4734 //#endif // #ifdef MISSIONPACK
4735 } else if ( Q_stricmp( name, "resetScores" ) == 0 ) {
4736 UI_ClearScores();
4737 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4738 } else if ( Q_stricmp( name, "RefreshServers" ) == 0 ) {
4739 UI_StartServerRefresh( qtrue, qtrue );
4740 UI_BuildServerDisplayList( qtrue );
4741 } else if ( Q_stricmp( name, "RefreshFilter" ) == 0 ) {
4742 UI_StartServerRefresh( qfalse, qtrue );
4743 UI_BuildServerDisplayList( qtrue );
4744 } else if ( Q_stricmp( name, "RunSPDemo" ) == 0 ) {
4745 if ( uiInfo.demoAvailable ) {
4746 trap_Cmd_ExecuteText( EXEC_APPEND, va( "demo %s_%i", uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum ) );
4747 }
4748 //#endif // #ifdef MISSIONPACK`
4749 } else if ( Q_stricmp( name, "LoadDemos" ) == 0 ) {
4750 UI_LoadDemos();
4751 } else if ( Q_stricmp( name, "LoadMovies" ) == 0 ) {
4752 UI_LoadMovies();
4753
4754 //----(SA) added
4755 } else if ( Q_stricmp( name, "LoadSaveGames" ) == 0 ) { // get the list
4756 UI_LoadSavegames( NULL );
4757 } else if ( Q_stricmp( name, "Loadgame" ) == 0 ) {
4758 int i = UI_SavegameIndexFromName2( ui_savegameName.string );
4759 // in developer, don't actually load the game
4760 if ( DC->getCVarValue( "developer" ) ) {
4761 Com_Printf( "would load game (developer 0):\n %s\n", uiInfo.savegameList[i].savegameFile );
4762 } else {
4763 trap_Cmd_ExecuteText( EXEC_APPEND, va( "loadgame %s\n", uiInfo.savegameList[i].savegameFile ) );
4764 }
4765
4766 // save. throw dialog box if file exists
4767 } else if ( Q_stricmp( name, "Savegame" ) == 0 ) {
4768 int i;
4769 char name[MAX_NAME_LENGTH];
4770
4771 name[0] = '\0';
4772 Q_strncpyz( name, UI_Cvar_VariableString( "ui_savegame" ), MAX_NAME_LENGTH );
4773
4774 if ( !strlen( name ) ) {
4775 Menus_OpenByName( "save_name_popmenu" );
4776 } else {
4777 // find out if there's an existing savegame with that name
4778 for ( i = 0; i < uiInfo.savegameCount; i++ ) {
4779 if ( Q_stricmp( name, uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[i]].savegameName ) == 0 ) {
4780 Menus_OpenByName( "save_overwrite_popmenu" );
4781 break;
4782 }
4783 }
4784
4785 if ( i == uiInfo.savegameCount ) {
4786 trap_Cmd_ExecuteText( EXEC_APPEND, va( "savegame %s\n", UI_Cvar_VariableString( "ui_savegame" ) ) );
4787 Menus_CloseAll();
4788 }
4789 }
4790 // save with no confirm for overwrite
4791 } else if ( Q_stricmp( name, "Savegame2" ) == 0 ) {
4792 if ( !strlen( name ) ) {
4793 Menus_OpenByName( "save_name_popmenu" );
4794 } else {
4795 trap_Cmd_ExecuteText( EXEC_APPEND, va( "savegame %s\n", UI_Cvar_VariableString( "ui_savegame" ) ) );
4796 Menus_CloseAll();
4797 }
4798 } else if ( Q_stricmp( name, "DelSavegame" ) == 0 ) {
4799 int i = UI_SavegameIndexFromName2( ui_savegameName.string );
4800 if ( DC->getCVarValue( "developer" ) ) {
4801 Com_Printf( "would delete game (developer 0):\n %s\n", uiInfo.savegameList[i].savegameFile );
4802 } else {
4803 UI_DelSavegame();
4804 }
4805 } else if ( Q_stricmp( name, "SavegameSort" ) == 0 ) {
4806 int sortColumn;
4807 if ( Int_Parse( args, &sortColumn ) ) {
4808 // if same column we're already sorting on then flip the direction
4809 if ( sortColumn == uiInfo.savegameStatus.sortKey ) {
4810 uiInfo.savegameStatus.sortDir = !uiInfo.savegameStatus.sortDir;
4811 }
4812 // make sure we sort again
4813 UI_SavegameSort( sortColumn, qtrue );
4814 }
4815 //----(SA) end
4816
4817 //----(SA) added
4818 } else if ( Q_stricmp( name, "playerstart" ) == 0 ) {
4819 trap_Cmd_ExecuteText( EXEC_APPEND, "fade 0 0 0 0 3\n" ); // fade screen up
4820 trap_Cvar_Set( "g_playerstart", "1" ); // set cvar which will trigger "playerstart" in script
4821 Menus_CloseAll();
4822 //----(SA) end
4823
4824 } else if ( Q_stricmp( name, "LoadMods" ) == 0 ) {
4825 UI_LoadMods();
4826 } else if ( Q_stricmp( name, "playMovie" ) == 0 ) {
4827 if ( uiInfo.previewMovie >= 0 ) {
4828 trap_CIN_StopCinematic( uiInfo.previewMovie );
4829 }
4830 trap_Cmd_ExecuteText( EXEC_APPEND, va( "cinematic %s.roq 2\n", uiInfo.movieList[uiInfo.movieIndex] ) );
4831 } else if ( Q_stricmp( name, "RunMod" ) == 0 ) {
4832 trap_Cvar_Set( "fs_game", uiInfo.modList[uiInfo.modIndex].modName );
4833 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
4834 } else if ( Q_stricmp( name, "RunDemo" ) == 0 ) {
4835 trap_Cmd_ExecuteText( EXEC_APPEND, va( "demo %s\n", uiInfo.demoList[uiInfo.demoIndex] ) );
4836 } else if ( Q_stricmp( name, "Wolf" ) == 0 ) {
4837 trap_Cvar_Set( "fs_game", "" );
4838 trap_Cmd_ExecuteText( EXEC_APPEND, "vid_restart;" );
4839 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4840 } else if ( Q_stricmp( name, "closeJoin" ) == 0 ) {
4841 if ( uiInfo.serverStatus.refreshActive ) {
4842 UI_StopServerRefresh();
4843 uiInfo.serverStatus.nextDisplayRefresh = 0;
4844 uiInfo.nextServerStatusRefresh = 0;
4845 uiInfo.nextFindPlayerRefresh = 0;
4846 UI_BuildServerDisplayList( qtrue );
4847 } else {
4848 Menus_CloseByName( "joinserver" );
4849 Menus_OpenByName( "main" );
4850 }
4851 //#endif
4852 } else if ( Q_stricmp( name, "StopRefresh" ) == 0 ) {
4853 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4854 UI_StopServerRefresh();
4855 uiInfo.serverStatus.nextDisplayRefresh = 0;
4856 uiInfo.nextServerStatusRefresh = 0;
4857 uiInfo.nextFindPlayerRefresh = 0;
4858 } else if ( Q_stricmp( name, "UpdateFilter" ) == 0 ) {
4859 // UpdateFilter is called when server broser menu is opened and when a favorite server is deleted.
4860 UI_StartServerRefresh(qtrue, qfalse);
4861 UI_BuildServerDisplayList( qtrue );
4862 UI_FeederSelection( FEEDER_SERVERS, 0 );
4863 } else if ( Q_stricmp( name, "ServerStatus" ) == 0 ) {
4864 trap_LAN_GetServerAddressString( ui_netSource.integer, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], uiInfo.serverStatusAddress, sizeof( uiInfo.serverStatusAddress ) );
4865 UI_BuildServerStatus( qtrue );
4866 } else if ( Q_stricmp( name, "FoundPlayerServerStatus" ) == 0 ) {
4867 Q_strncpyz( uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof( uiInfo.serverStatusAddress ) );
4868 UI_BuildServerStatus( qtrue );
4869 Menu_SetFeederSelection( NULL, FEEDER_FINDPLAYER, 0, NULL );
4870 } else if ( Q_stricmp( name, "FindPlayer" ) == 0 ) {
4871 UI_BuildFindPlayerList( qtrue );
4872 // clear the displayed server status info
4873 uiInfo.serverStatusInfo.numLines = 0;
4874 Menu_SetFeederSelection( NULL, FEEDER_FINDPLAYER, 0, NULL );
4875 } else if ( Q_stricmp( name, "JoinServer" ) == 0 ) {
4876 trap_Cvar_Set( "cg_thirdPerson", "0" );
4877 trap_Cvar_Set( "cg_cameraOrbit", "0" );
4878 trap_Cvar_Set( "ui_singlePlayerActive", "0" );
4879 if ( uiInfo.serverStatus.currentServer >= 0 && uiInfo.serverStatus.currentServer < uiInfo.serverStatus.numDisplayServers ) {
4880 trap_LAN_GetServerAddressString(UI_SourceForLAN(), uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, 1024);
4881 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", buff ) );
4882 }
4883 } else if ( Q_stricmp( name, "FoundPlayerJoinServer" ) == 0 ) {
4884 trap_Cvar_Set( "ui_singlePlayerActive", "0" );
4885 if ( uiInfo.currentFoundPlayerServer >= 0 && uiInfo.currentFoundPlayerServer < uiInfo.numFoundPlayerServers ) {
4886 trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer] ) );
4887 }
4888 //#endif // #ifdef MISSIONPACK
4889 } else if ( Q_stricmp( name, "Quit" ) == 0 ) {
4890 trap_Cvar_Set( "ui_singlePlayerActive", "0" );
4891 trap_Cmd_ExecuteText( EXEC_NOW, "quit" );
4892 } else if ( Q_stricmp( name, "Controls" ) == 0 ) {
4893 trap_Cvar_Set( "cl_paused", "1" );
4894 trap_Key_SetCatcher( KEYCATCH_UI );
4895 Menus_CloseAll();
4896 Menus_ActivateByName( "setup_menu2" );
4897 } else if ( Q_stricmp( name, "Leave" ) == 0 ) {
4898 trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect\n" );
4899 trap_Key_SetCatcher( KEYCATCH_UI );
4900 Menus_CloseAll();
4901 Menus_ActivateByName( "main" );
4902 } else if ( Q_stricmp( name, "ServerSort" ) == 0 ) {
4903 int sortColumn;
4904 if ( Int_Parse( args, &sortColumn ) ) {
4905 // if same column we're already sorting on then flip the direction
4906 if ( sortColumn == uiInfo.serverStatus.sortKey ) {
4907 uiInfo.serverStatus.sortDir = !uiInfo.serverStatus.sortDir;
4908 }
4909 // make sure we sort again
4910 UI_ServersSort( sortColumn, qtrue );
4911 }
4912 } else if ( Q_stricmp( name, "nextSkirmish" ) == 0 ) {
4913 UI_StartSkirmish( qtrue );
4914 } else if ( Q_stricmp( name, "SkirmishStart" ) == 0 ) {
4915 UI_StartSkirmish( qfalse );
4916 } else if ( Q_stricmp( name, "closeingame" ) == 0 ) {
4917 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
4918 trap_Key_ClearStates();
4919 trap_Cvar_Set( "cl_paused", "0" );
4920 Menus_CloseAll();
4921 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4922 } else if ( Q_stricmp( name, "voteMap" ) == 0 ) {
4923 if ( ui_currentNetMap.integer >= 0 && ui_currentNetMap.integer < uiInfo.mapCount ) {
4924 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote map %s\n",uiInfo.mapList[ui_currentNetMap.integer].mapLoadName ) );
4925 }
4926 //#endif // #ifdef MISSIONPACK
4927 } else if ( Q_stricmp( name, "voteKick" ) == 0 ) {
4928 if ( uiInfo.playerIndex >= 0 && uiInfo.playerIndex < uiInfo.playerCount ) {
4929 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote kick %s\n",uiInfo.playerNames[uiInfo.playerIndex] ) );
4930 }
4931 } else if ( Q_stricmp( name, "voteGame" ) == 0 ) {
4932 if ( ui_netGameType.integer >= 0 && ui_netGameType.integer < uiInfo.numGameTypes ) {
4933 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callvote g_gametype %i\n",uiInfo.gameTypes[ui_netGameType.integer].gtEnum ) );
4934 }
4935 } else if ( Q_stricmp( name, "voteLeader" ) == 0 ) {
4936 if ( uiInfo.teamIndex >= 0 && uiInfo.teamIndex < uiInfo.myTeamCount ) {
4937 trap_Cmd_ExecuteText( EXEC_APPEND, va( "callteamvote leader %s\n",uiInfo.teamNames[uiInfo.teamIndex] ) );
4938 }
4939 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
4940 } else if ( Q_stricmp( name, "addBot" ) == 0 ) {
4941 if ( trap_Cvar_VariableValue( "g_gametype" ) >= GT_TEAM ) {
4942 trap_Cmd_ExecuteText( EXEC_APPEND, va( "addbot %s %i %s\n", uiInfo.characterList[uiInfo.botIndex].name, uiInfo.skillIndex + 1, ( uiInfo.redBlue == 0 ) ? "Red" : "Blue" ) );
4943 } else {
4944 // NERVE - SMF - no bots in wolf multiplayer
4945 // trap_Cmd_ExecuteText( EXEC_APPEND, va("addbot %s %i %s\n", UI_GetBotNameByNumber(uiInfo.botIndex), uiInfo.skillIndex+1, (uiInfo.redBlue == 0) ? "Red" : "Blue") );
4946 }
4947 } else if ( Q_stricmp( name, "addFavorite" ) == 0 ) {
4948 if ( ui_netSource.integer != UIAS_FAVORITES ) {
4949 char name[MAX_NAME_LENGTH];
4950 char addr[MAX_ADDRESSLENGTH];
4951 int res;
4952
4953 trap_LAN_GetServerInfo(UI_SourceForLAN(), uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS);
4954 name[0] = addr[0] = '\0';
4955 Q_strncpyz( name, Info_ValueForKey( buff, "hostname" ), sizeof ( name ) );
4956 Q_strncpyz( addr, Info_ValueForKey( buff, "addr" ), sizeof ( addr ) );
4957 if ( strlen( name ) > 0 && strlen( addr ) > 0 ) {
4958 res = trap_LAN_AddServer( AS_FAVORITES, name, addr );
4959 if ( res == 0 ) {
4960 // server already in the list
4961 Com_Printf( "Favorite already in list\n" );
4962 } else if ( res == -1 ) {
4963 // list full
4964 Com_Printf( "Favorite list full\n" );
4965 } else {
4966 // successfully added
4967 Com_Printf( "Added favorite server %s\n", addr );
4968 }
4969 }
4970 }
4971 } else if ( Q_stricmp( name, "deleteFavorite" ) == 0 ) {
4972 if ( ui_netSource.integer == UIAS_FAVORITES ) {
4973 char addr[MAX_ADDRESSLENGTH];
4974 trap_LAN_GetServerInfo( AS_FAVORITES, uiInfo.serverStatus.displayServers[uiInfo.serverStatus.currentServer], buff, MAX_STRING_CHARS );
4975 addr[0] = '\0';
4976 Q_strncpyz( addr, Info_ValueForKey( buff, "addr" ), sizeof ( addr ) );
4977 if ( strlen( addr ) > 0 ) {
4978 trap_LAN_RemoveServer( AS_FAVORITES, addr );
4979 }
4980 }
4981 } else if ( Q_stricmp( name, "createFavorite" ) == 0 ) {
4982 char name[MAX_NAME_LENGTH];
4983 char addr[MAX_ADDRESSLENGTH];
4984 int res;
4985
4986 name[0] = addr[0] = '\0';
4987 Q_strncpyz( name, UI_Cvar_VariableString( "ui_favoriteName" ), sizeof ( name ) );
4988 Q_strncpyz( addr, UI_Cvar_VariableString( "ui_favoriteAddress" ), sizeof ( addr ) );
4989 if ( strlen( name ) > 0 && strlen( addr ) > 0 ) {
4990 res = trap_LAN_AddServer( AS_FAVORITES, name, addr );
4991 if ( res == 0 ) {
4992 // server already in the list
4993 Com_Printf( "Favorite already in list\n" );
4994 } else if ( res == -1 ) {
4995 // list full
4996 Com_Printf( "Favorite list full\n" );
4997 } else {
4998 // successfully added
4999 Com_Printf( "Added favorite server %s\n", addr );
5000 }
5001 }
5002 } else if ( Q_stricmp( name, "orders" ) == 0 ) {
5003 const char *orders;
5004 if ( String_Parse( args, &orders ) ) {
5005 int selectedPlayer = trap_Cvar_VariableValue( "cg_selectedPlayer" );
5006 if ( selectedPlayer < uiInfo.myTeamCount ) {
5007 Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[selectedPlayer] );
5008 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
5009 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
5010 } else {
5011 int i;
5012 for ( i = 0; i < uiInfo.myTeamCount; i++ ) {
5013 if (uiInfo.playerNumber == uiInfo.teamClientNums[i]) {
5014 continue;
5015 }
5016 Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[i] );
5017 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
5018 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
5019 }
5020 }
5021 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
5022 trap_Key_ClearStates();
5023 trap_Cvar_Set( "cl_paused", "0" );
5024 Menus_CloseAll();
5025 }
5026 } else if ( Q_stricmp( name, "voiceOrdersTeam" ) == 0 ) {
5027 const char *orders;
5028 if ( String_Parse( args, &orders ) ) {
5029 int selectedPlayer = trap_Cvar_VariableValue( "cg_selectedPlayer" );
5030 if ( selectedPlayer == uiInfo.myTeamCount ) {
5031 trap_Cmd_ExecuteText( EXEC_APPEND, orders );
5032 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
5033 }
5034 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
5035 trap_Key_ClearStates();
5036 trap_Cvar_Set( "cl_paused", "0" );
5037 Menus_CloseAll();
5038 }
5039 } else if ( Q_stricmp( name, "voiceOrders" ) == 0 ) {
5040 const char *orders;
5041 if ( String_Parse( args, &orders ) ) {
5042 int selectedPlayer = trap_Cvar_VariableValue( "cg_selectedPlayer" );
5043 if ( selectedPlayer < uiInfo.myTeamCount ) {
5044 Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[selectedPlayer] );
5045 trap_Cmd_ExecuteText( EXEC_APPEND, buff );
5046 trap_Cmd_ExecuteText( EXEC_APPEND, "\n" );
5047 }
5048 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
5049 trap_Key_ClearStates();
5050 trap_Cvar_Set( "cl_paused", "0" );
5051 Menus_CloseAll();
5052 }
5053 //#endif // #ifdef MISSIONPACK
5054 } else if ( Q_stricmp( name, "glCustom" ) == 0 ) {
5055 trap_Cvar_Set( "ui_glCustom", "4" );
5056 } else if ( Q_stricmp( name, "update" ) == 0 ) {
5057 if ( String_Parse( args, &name2 ) ) {
5058 UI_Update( name2 );
5059 }
5060 // NERVE - SMF
5061 //----(SA) // start other .exe
5062 } else if ( Q_stricmp( name, "startSingleplayer" ) == 0 ) { // so it doesn't barf if it gets a mp menu
5063 trap_Cmd_ExecuteText( EXEC_APPEND, "startMultiplayer\n" );
5064 } else if ( Q_stricmp( name, "startMultiplayer" ) == 0 ) {
5065 trap_Cmd_ExecuteText( EXEC_APPEND, "startMultiplayer\n" );
5066 //----(SA)
5067 } else if ( Q_stricmp( name, "wm_showPickPlayer" ) == 0 ) {
5068 Menus_CloseAll();
5069 Menus_OpenByName( "wm_pickplayer" );
5070 } else if ( Q_stricmp( name, "wm_showPickTeam" ) == 0 ) {
5071 Menus_CloseAll();
5072 Menus_OpenByName( "wm_pickteam" );
5073 } else if ( Q_stricmp( name, "changePlayerType" ) == 0 ) {
5074 WM_ChangePlayerType();
5075 } else if ( Q_stricmp( name, "getSpawnPoints" ) == 0 ) {
5076 WM_GetSpawnPoints();
5077 } else if ( Q_stricmp( name, "wm_pickitem2" ) == 0 ) {
5078 const char *param, *param2;
5079 int selectType = 0, itemIndex = 0;
5080
5081 if ( String_Parse( args, ¶m ) && String_Parse( args, ¶m2 ) ) {
5082 selectType = atoi( param );
5083 itemIndex = atoi( param2 );
5084 WM_PickItem( selectType, itemIndex );
5085 }
5086 } else if ( Q_stricmp( name, "startMultiplayer" ) == 0 ) {
5087 int team, playerType, weapon, pistol, item1, i;
5088 const char *teamStr, *classStr, *weapStr;
5089
5090 Menus_CloseAll();
5091
5092 // get cvars
5093 team = trap_Cvar_VariableValue( "mp_team" );
5094 playerType = trap_Cvar_VariableValue( "mp_playerType" );
5095 weapon = trap_Cvar_VariableValue( "mp_weapon" );
5096 pistol = trap_Cvar_VariableValue( "mp_pistol" );
5097 item1 = trap_Cvar_VariableValue( "mp_item1" );
5098
5099 // print center message
5100 if ( team == 0 ) {
5101 teamStr = "nazi";
5102 } else if ( team == 1 ) {
5103 teamStr = "allied";
5104 } else {
5105 teamStr = "spectator";
5106 }
5107
5108 if ( playerType == 0 ) {
5109 classStr = "soldier";
5110 } else if ( playerType == 1 ) {
5111 classStr = "medic";
5112 } else if ( playerType == 2 ) {
5113 classStr = "engineer";
5114 } else {
5115 classStr = "lieutenant";
5116 }
5117
5118 weapStr = "";
5119 for ( i = 0; weaponTypes[i].name; i++ ) {
5120 if ( weaponTypes[i].value == weapon ) {
5121 weapStr = weaponTypes[i].desc;
5122 }
5123 }
5124
5125 if ( team != 2 ) {
5126 trap_Cmd_ExecuteText( EXEC_APPEND, va( "limbomessage %s %s %s\n", teamStr, classStr, weapStr ) );
5127 }
5128
5129 // join team
5130 if ( team == 0 ) {
5131 trap_Cmd_ExecuteText( EXEC_APPEND, va( "team %s %i %i %i %i 1\n", "red", playerType, weapon, pistol, item1 ) );
5132 } else if ( team == 1 ) {
5133 trap_Cmd_ExecuteText( EXEC_APPEND, va( "team %s %i %i %i %i 1\n", "blue", playerType, weapon, pistol, item1 ) );
5134 } else {
5135 trap_Cmd_ExecuteText( EXEC_APPEND, va( "team %s %i %i %i %i 1\n", "s", playerType, weapon, pistol, item1 ) );
5136 }
5137
5138 } else if ( Q_stricmp( name, "limboChat" ) == 0 ) {
5139 WM_LimboChat();
5140 } else if ( Q_stricmp( name, "activateLimboChat" ) == 0 ) {
5141 WM_ActivateLimboChat();
5142 // -NERVE - SMF
5143 } else if ( Q_stricmp( name, "setrecommended" ) == 0 ) {
5144 trap_Cmd_ExecuteText( EXEC_APPEND, "setRecommended 1\n" );
5145 } else {
5146 Com_Printf( "unknown UI script %s\n", name );
5147 }
5148 }
5149 }
5150
UI_GetTeamColor(vec4_t * color)5151 static void UI_GetTeamColor( vec4_t *color ) {
5152 }
5153
5154 /*
5155 ==================
5156 UI_MapCountByGameType
5157 ==================
5158 */
UI_MapCountByGameType(qboolean singlePlayer)5159 static int UI_MapCountByGameType( qboolean singlePlayer ) {
5160 int i, c, game;
5161 c = 0;
5162 game = singlePlayer ? uiInfo.gameTypes[ui_gameType.integer].gtEnum : uiInfo.gameTypes[ui_netGameType.integer].gtEnum;
5163 if ( game == GT_SINGLE_PLAYER ) {
5164 game++;
5165 }
5166 if ( game == GT_TEAM ) {
5167 game = GT_FFA;
5168 }
5169
5170 for ( i = 0; i < uiInfo.mapCount; i++ ) {
5171 uiInfo.mapList[i].active = qfalse;
5172 if ( uiInfo.mapList[i].typeBits & ( 1 << game ) ) {
5173 if ( singlePlayer ) {
5174 if ( !( uiInfo.mapList[i].typeBits & ( 1 << GT_SINGLE_PLAYER ) ) ) {
5175 continue;
5176 }
5177 }
5178 c++;
5179 uiInfo.mapList[i].active = qtrue;
5180 }
5181 }
5182 return c;
5183 }
5184
5185 /*
5186 ==================
5187 UI_InsertServerIntoDisplayList
5188 ==================
5189 */
UI_InsertServerIntoDisplayList(int num,int position)5190 static void UI_InsertServerIntoDisplayList( int num, int position ) {
5191 int i;
5192
5193 if ( position < 0 || position > uiInfo.serverStatus.numDisplayServers ) {
5194 return;
5195 }
5196 //
5197 uiInfo.serverStatus.numDisplayServers++;
5198 for ( i = uiInfo.serverStatus.numDisplayServers; i > position; i-- ) {
5199 uiInfo.serverStatus.displayServers[i] = uiInfo.serverStatus.displayServers[i - 1];
5200 }
5201 uiInfo.serverStatus.displayServers[position] = num;
5202
5203 // update displayed levelshot
5204 if ( position == uiInfo.serverStatus.currentServer ) {
5205 UI_FeederSelection( FEEDER_SERVERS, uiInfo.serverStatus.currentServer );
5206 }
5207 }
5208
5209 /*
5210 ==================
5211 UI_RemoveServerFromDisplayList
5212 ==================
5213 */
UI_RemoveServerFromDisplayList(int num)5214 static void UI_RemoveServerFromDisplayList( int num ) {
5215 int i, j;
5216
5217 for ( i = 0; i < uiInfo.serverStatus.numDisplayServers; i++ ) {
5218 if ( uiInfo.serverStatus.displayServers[i] == num ) {
5219 uiInfo.serverStatus.numDisplayServers--;
5220 for ( j = i; j < uiInfo.serverStatus.numDisplayServers; j++ ) {
5221 uiInfo.serverStatus.displayServers[j] = uiInfo.serverStatus.displayServers[j + 1];
5222 }
5223 return;
5224 }
5225 }
5226 }
5227
5228 /*
5229 ==================
5230 UI_BinaryServerInsertion
5231 ==================
5232 */
UI_BinaryServerInsertion(int num)5233 static void UI_BinaryServerInsertion( int num ) {
5234 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5235 int mid, offset, res, len;
5236
5237 // use binary search to insert server
5238 len = uiInfo.serverStatus.numDisplayServers;
5239 mid = len;
5240 offset = 0;
5241 res = 0;
5242 while ( mid > 0 ) {
5243 mid = len >> 1;
5244 //
5245 res = trap_LAN_CompareServers( UI_SourceForLAN(), uiInfo.serverStatus.sortKey,
5246 uiInfo.serverStatus.sortDir, num, uiInfo.serverStatus.displayServers[offset + mid] );
5247
5248 // if equal
5249 if ( res == 0 ) {
5250 UI_InsertServerIntoDisplayList( num, offset + mid );
5251 return;
5252 }
5253 // if larger
5254 else if ( res == 1 ) {
5255 offset += mid;
5256 len -= mid;
5257 }
5258 // if smaller
5259 else {
5260 len -= mid;
5261 }
5262 }
5263 if ( res == 1 ) {
5264 offset++;
5265 }
5266 UI_InsertServerIntoDisplayList( num, offset );
5267 //#endif // #ifdef MISSIONPACK
5268 }
5269
5270 /*
5271 ==================
5272 UI_BuildServerDisplayList
5273 ==================
5274 */
UI_BuildServerDisplayList(int force)5275 static void UI_BuildServerDisplayList( int force ) {
5276 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5277 int i, count, clients, maxClients, ping, len, visible;
5278 char info[MAX_STRING_CHARS];
5279 //qboolean startRefresh = qtrue;// TTimo: unused
5280 static int numinvisible;
5281 int lanSource;
5282
5283 if ( !( force || uiInfo.uiDC.realTime > uiInfo.serverStatus.nextDisplayRefresh ) ) {
5284 return;
5285 }
5286 // if we shouldn't reset
5287 if ( force == 2 ) {
5288 force = 0;
5289 }
5290
5291 // do motd updates here too
5292 trap_Cvar_VariableStringBuffer( "cl_motdString", uiInfo.serverStatus.motd, sizeof( uiInfo.serverStatus.motd ) );
5293 len = strlen( uiInfo.serverStatus.motd );
5294 if ( len == 0 ) {
5295 strcpy( uiInfo.serverStatus.motd, "Welcome to Team Arena!" );
5296 len = strlen( uiInfo.serverStatus.motd );
5297 }
5298 if ( len != uiInfo.serverStatus.motdLen ) {
5299 uiInfo.serverStatus.motdLen = len;
5300 uiInfo.serverStatus.motdWidth = -1;
5301 }
5302
5303 lanSource = UI_SourceForLAN();
5304
5305 if ( force ) {
5306 numinvisible = 0;
5307 // clear number of displayed servers
5308 uiInfo.serverStatus.numDisplayServers = 0;
5309 uiInfo.serverStatus.numPlayersOnServers = 0;
5310 // set list box index to zero
5311 Menu_SetFeederSelection( NULL, FEEDER_SERVERS, 0, NULL );
5312 // mark all servers as visible so we store ping updates for them
5313 trap_LAN_MarkServerVisible(lanSource, -1, qtrue);
5314 }
5315
5316 // get the server count (comes from the master)
5317 count = trap_LAN_GetServerCount(lanSource);
5318 if (count == -1 || (ui_netSource.integer == UIAS_LOCAL && count == 0) ) {
5319 // still waiting on a response from the master
5320 uiInfo.serverStatus.numDisplayServers = 0;
5321 uiInfo.serverStatus.numPlayersOnServers = 0;
5322 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 500;
5323 return;
5324 }
5325
5326 visible = qfalse;
5327 for ( i = 0; i < count; i++ ) {
5328 // if we already got info for this server
5329 if (!trap_LAN_ServerIsVisible(lanSource, i)) {
5330 continue;
5331 }
5332 visible = qtrue;
5333 // get the ping for this server
5334 ping = trap_LAN_GetServerPing(lanSource, i);
5335 if (ping > 0 || ui_netSource.integer == UIAS_FAVORITES) {
5336 // Remove favorite servers so they do not appear multiple times
5337 // or appear when the cached server info was not filtered out
5338 // but the new server info is filtered out.
5339 if (ui_netSource.integer == UIAS_FAVORITES) {
5340 UI_RemoveServerFromDisplayList(i);
5341 }
5342
5343 trap_LAN_GetServerInfo(lanSource, i, info, MAX_STRING_CHARS);
5344
5345 clients = atoi( Info_ValueForKey( info, "clients" ) );
5346
5347 if ( ui_browserShowEmpty.integer == 0 ) {
5348 if ( clients == 0 ) {
5349 if (ping > 0) {
5350 trap_LAN_MarkServerVisible(lanSource, i, qfalse);
5351 }
5352 continue;
5353 }
5354 }
5355
5356 if ( ui_browserShowFull.integer == 0 ) {
5357 maxClients = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
5358 if ( clients == maxClients ) {
5359 if (ping > 0) {
5360 trap_LAN_MarkServerVisible(lanSource, i, qfalse);
5361 }
5362 continue;
5363 }
5364 }
5365
5366 /*
5367 // NERVE - SMF - comment out for now, not recognizing "gametype" properly
5368 if (uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum != -1) {
5369 game = atoi(Info_ValueForKey(info, "gametype"));
5370 if (game != uiInfo.joinGameTypes[ui_joinGameType.integer].gtEnum) {
5371 if (ping > 0) {
5372 trap_LAN_MarkServerVisible(lanSource, i, qfalse);
5373 }
5374 continue;
5375 }
5376 }
5377 */
5378
5379 if ( ui_serverFilterType.integer > 0 ) {
5380 if ( Q_stricmp( Info_ValueForKey( info, "game" ), serverFilters[ui_serverFilterType.integer].basedir ) != 0 ) {
5381 if (ping > 0) {
5382 trap_LAN_MarkServerVisible(lanSource, i, qfalse);
5383 }
5384 continue;
5385 }
5386 }
5387 // insert the server into the list
5388 UI_BinaryServerInsertion( i );
5389 // done with this server
5390 if ( ping > 0 ) {
5391 trap_LAN_MarkServerVisible(lanSource, i, qfalse);
5392 uiInfo.serverStatus.numPlayersOnServers += clients;
5393 numinvisible++;
5394 }
5395 }
5396 }
5397
5398 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime;
5399
5400 // if there were no servers visible for ping updates
5401 if ( !visible ) {
5402 // UI_StopServerRefresh();
5403 // uiInfo.serverStatus.nextDisplayRefresh = 0;
5404 }
5405 //#endif // #ifdef MISSIONPACK
5406 }
5407
5408 typedef struct
5409 {
5410 char *name, *altName;
5411 } serverStatusCvar_t;
5412
5413 serverStatusCvar_t serverStatusCvars[] = {
5414 {"sv_hostname", "Name"},
5415 {"Address", ""},
5416 {"gamename", "Game name"},
5417 {"g_gametype", "Game type"},
5418 {"mapname", "Map"},
5419 {"version", ""},
5420 {"protocol", ""},
5421 {"timelimit", ""},
5422 {"fraglimit", ""},
5423 {NULL, NULL}
5424 };
5425
5426 /*
5427 ==================
5428 UI_SortServerStatusInfo
5429 ==================
5430 */
UI_SortServerStatusInfo(serverStatusInfo_t * info)5431 static void UI_SortServerStatusInfo( serverStatusInfo_t *info ) {
5432 int i, j, index;
5433 char *tmp1, *tmp2;
5434
5435 // FIXME: if "gamename" == "baseq3" or "missionpack" then
5436 // replace the gametype number by FFA, CTF etc.
5437 //
5438 index = 0;
5439 for ( i = 0; serverStatusCvars[i].name; i++ ) {
5440 for ( j = 0; j < info->numLines; j++ ) {
5441 if ( !info->lines[j][1] || info->lines[j][1][0] ) {
5442 continue;
5443 }
5444 if ( !Q_stricmp( serverStatusCvars[i].name, info->lines[j][0] ) ) {
5445 // swap lines
5446 tmp1 = info->lines[index][0];
5447 tmp2 = info->lines[index][3];
5448 info->lines[index][0] = info->lines[j][0];
5449 info->lines[index][3] = info->lines[j][3];
5450 info->lines[j][0] = tmp1;
5451 info->lines[j][3] = tmp2;
5452 //
5453 if ( strlen( serverStatusCvars[i].altName ) ) {
5454 info->lines[index][0] = serverStatusCvars[i].altName;
5455 }
5456 index++;
5457 }
5458 }
5459 }
5460 }
5461
5462 /*
5463 ==================
5464 UI_GetServerStatusInfo
5465 ==================
5466 */
UI_GetServerStatusInfo(const char * serverAddress,serverStatusInfo_t * info)5467 static int UI_GetServerStatusInfo( const char *serverAddress, serverStatusInfo_t *info ) {
5468 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5469 char *p, *score, *ping, *name;
5470 int i, len;
5471
5472 if (info) {
5473 memset(info, 0, sizeof(*info));
5474 }
5475
5476 // ignore initial unset addresses
5477 if (serverAddress && *serverAddress == '\0') {
5478 return qfalse;
5479 }
5480
5481 // reset server status request for this address
5482 if ( !info ) {
5483 trap_LAN_ServerStatus( serverAddress, NULL, 0 );
5484 return qfalse;
5485 }
5486
5487 if ( trap_LAN_ServerStatus( serverAddress, info->text, sizeof( info->text ) ) ) {
5488 Q_strncpyz( info->address, serverAddress, sizeof( info->address ) );
5489 p = info->text;
5490 info->numLines = 0;
5491 info->lines[info->numLines][0] = "Address";
5492 info->lines[info->numLines][1] = "";
5493 info->lines[info->numLines][2] = "";
5494 info->lines[info->numLines][3] = info->address;
5495 info->numLines++;
5496 // get the cvars
5497 while ( p && *p ) {
5498 p = strchr( p, '\\' );
5499 if ( !p ) {
5500 break;
5501 }
5502 *p++ = '\0';
5503 if ( *p == '\\' ) {
5504 break;
5505 }
5506 info->lines[info->numLines][0] = p;
5507 info->lines[info->numLines][1] = "";
5508 info->lines[info->numLines][2] = "";
5509 p = strchr( p, '\\' );
5510 if ( !p ) {
5511 break;
5512 }
5513 *p++ = '\0';
5514 info->lines[info->numLines][3] = p;
5515
5516 info->numLines++;
5517 if ( info->numLines >= MAX_SERVERSTATUS_LINES ) {
5518 break;
5519 }
5520 }
5521 // get the player list
5522 if ( info->numLines < MAX_SERVERSTATUS_LINES - 3 ) {
5523 // empty line
5524 info->lines[info->numLines][0] = "";
5525 info->lines[info->numLines][1] = "";
5526 info->lines[info->numLines][2] = "";
5527 info->lines[info->numLines][3] = "";
5528 info->numLines++;
5529 // header
5530 info->lines[info->numLines][0] = "num";
5531 info->lines[info->numLines][1] = "score";
5532 info->lines[info->numLines][2] = "ping";
5533 info->lines[info->numLines][3] = "name";
5534 info->numLines++;
5535 // parse players
5536 i = 0;
5537 len = 0;
5538 while ( p && *p ) {
5539 if ( *p == '\\' ) {
5540 *p++ = '\0';
5541 }
5542 score = p;
5543 p = strchr( p, ' ' );
5544 if ( !p ) {
5545 break;
5546 }
5547 *p++ = '\0';
5548 ping = p;
5549 p = strchr( p, ' ' );
5550 if ( !p ) {
5551 break;
5552 }
5553 *p++ = '\0';
5554 name = p;
5555 Com_sprintf( &info->pings[len], sizeof( info->pings ) - len, "%d", i );
5556 info->lines[info->numLines][0] = &info->pings[len];
5557 len += strlen( &info->pings[len] ) + 1;
5558 info->lines[info->numLines][1] = score;
5559 info->lines[info->numLines][2] = ping;
5560 info->lines[info->numLines][3] = name;
5561 info->numLines++;
5562 if ( info->numLines >= MAX_SERVERSTATUS_LINES ) {
5563 break;
5564 }
5565 p = strchr( p, '\\' );
5566 if ( !p ) {
5567 break;
5568 }
5569 *p++ = '\0';
5570 //
5571 i++;
5572 }
5573 }
5574 UI_SortServerStatusInfo( info );
5575 return qtrue;
5576 }
5577 //#endif // #ifdef MISSIONPACK
5578 return qfalse;
5579 }
5580
5581 /*
5582 ==================
5583 stristr
5584 ==================
5585 */
stristr(char * str,char * charset)5586 static char *stristr( char *str, char *charset ) {
5587 int i;
5588
5589 while ( *str ) {
5590 for ( i = 0; charset[i] && str[i]; i++ ) {
5591 if ( toupper( charset[i] ) != toupper( str[i] ) ) {
5592 break;
5593 }
5594 }
5595 if ( !charset[i] ) {
5596 return str;
5597 }
5598 str++;
5599 }
5600 return NULL;
5601 }
5602
5603 /*
5604 ==================
5605 UI_BuildFindPlayerList
5606 ==================
5607 */
UI_BuildFindPlayerList(qboolean force)5608 static void UI_BuildFindPlayerList( qboolean force ) {
5609 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5610 static int numFound, numTimeOuts;
5611 int i, j, resend;
5612 serverStatusInfo_t info;
5613 char name[MAX_NAME_LENGTH + 2];
5614 char infoString[MAX_STRING_CHARS];
5615 int lanSource;
5616
5617 if ( !force ) {
5618 if ( !uiInfo.nextFindPlayerRefresh || uiInfo.nextFindPlayerRefresh > uiInfo.uiDC.realTime ) {
5619 return;
5620 }
5621 } else {
5622 memset( &uiInfo.pendingServerStatus, 0, sizeof( uiInfo.pendingServerStatus ) );
5623 uiInfo.numFoundPlayerServers = 0;
5624 uiInfo.currentFoundPlayerServer = 0;
5625 trap_Cvar_VariableStringBuffer( "ui_findPlayer", uiInfo.findPlayerName, sizeof( uiInfo.findPlayerName ) );
5626 Q_CleanStr( uiInfo.findPlayerName );
5627 // should have a string of some length
5628 if ( !strlen( uiInfo.findPlayerName ) ) {
5629 uiInfo.nextFindPlayerRefresh = 0;
5630 return;
5631 }
5632 // set resend time
5633 resend = ui_serverStatusTimeOut.integer / 2 - 10;
5634 if ( resend < 50 ) {
5635 resend = 50;
5636 }
5637 trap_Cvar_Set( "cl_serverStatusResendTime", va( "%d", resend ) );
5638 // reset all server status requests
5639 trap_LAN_ServerStatus( NULL, NULL, 0 );
5640 //
5641 uiInfo.numFoundPlayerServers = 1;
5642 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1],
5643 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1] ),
5644 "searching %d...", uiInfo.pendingServerStatus.num );
5645 numFound = 0;
5646 numTimeOuts++;
5647 }
5648 for ( i = 0; i < MAX_SERVERSTATUSREQUESTS; i++ ) {
5649 // if this pending server is valid
5650 if ( uiInfo.pendingServerStatus.server[i].valid ) {
5651 // try to get the server status for this server
5652 if ( UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, &info ) ) {
5653 //
5654 numFound++;
5655 // parse through the server status lines
5656 for ( j = 0; j < info.numLines; j++ ) {
5657 // should have ping info
5658 if ( !info.lines[j][2] || !info.lines[j][2][0] ) {
5659 continue;
5660 }
5661 // clean string first
5662 Q_strncpyz( name, info.lines[j][3], sizeof( name ) );
5663 Q_CleanStr( name );
5664 // if the player name is a substring
5665 if ( stristr( name, uiInfo.findPlayerName ) ) {
5666 // add to found server list if we have space (always leave space for a line with the number found)
5667 if ( uiInfo.numFoundPlayerServers < MAX_FOUNDPLAYER_SERVERS - 1 ) {
5668 //
5669 Q_strncpyz( uiInfo.foundPlayerServerAddresses[uiInfo.numFoundPlayerServers - 1],
5670 uiInfo.pendingServerStatus.server[i].adrstr,
5671 sizeof( uiInfo.foundPlayerServerAddresses[0] ) );
5672 Q_strncpyz( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1],
5673 uiInfo.pendingServerStatus.server[i].name,
5674 sizeof( uiInfo.foundPlayerServerNames[0] ) );
5675 uiInfo.numFoundPlayerServers++;
5676 } else {
5677 // can't add any more so we're done
5678 uiInfo.pendingServerStatus.num = uiInfo.serverStatus.numDisplayServers;
5679 }
5680 }
5681 }
5682 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1],
5683 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1] ),
5684 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound );
5685 // retrieved the server status so reuse this spot
5686 uiInfo.pendingServerStatus.server[i].valid = qfalse;
5687 }
5688 }
5689 // if empty pending slot or timed out
5690 if ( !uiInfo.pendingServerStatus.server[i].valid ||
5691 uiInfo.pendingServerStatus.server[i].startTime < uiInfo.uiDC.realTime - ui_serverStatusTimeOut.integer ) {
5692 if ( uiInfo.pendingServerStatus.server[i].valid ) {
5693 numTimeOuts++;
5694 }
5695 // reset server status request for this address
5696 UI_GetServerStatusInfo( uiInfo.pendingServerStatus.server[i].adrstr, NULL );
5697 // reuse pending slot
5698 uiInfo.pendingServerStatus.server[i].valid = qfalse;
5699 // if we didn't try to get the status of all servers in the main browser yet
5700 if ( uiInfo.pendingServerStatus.num < uiInfo.serverStatus.numDisplayServers ) {
5701 uiInfo.pendingServerStatus.server[i].startTime = uiInfo.uiDC.realTime;
5702 lanSource = UI_SourceForLAN();
5703 trap_LAN_GetServerAddressString(lanSource, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num],
5704 uiInfo.pendingServerStatus.server[i].adrstr, sizeof( uiInfo.pendingServerStatus.server[i].adrstr ) );
5705 trap_LAN_GetServerInfo(lanSource, uiInfo.serverStatus.displayServers[uiInfo.pendingServerStatus.num], infoString, sizeof(infoString));
5706 Q_strncpyz( uiInfo.pendingServerStatus.server[i].name, Info_ValueForKey( infoString, "hostname" ), sizeof( uiInfo.pendingServerStatus.server[0].name ) );
5707 uiInfo.pendingServerStatus.server[i].valid = qtrue;
5708 uiInfo.pendingServerStatus.num++;
5709 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1],
5710 sizeof( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers - 1] ),
5711 "searching %d/%d...", uiInfo.pendingServerStatus.num, numFound );
5712 }
5713 }
5714 }
5715 for ( i = 0; i < MAX_SERVERSTATUSREQUESTS; i++ ) {
5716 if ( uiInfo.pendingServerStatus.server[i].valid ) {
5717 break;
5718 }
5719 }
5720 // if still trying to retrieve server status info
5721 if ( i < MAX_SERVERSTATUSREQUESTS ) {
5722 uiInfo.nextFindPlayerRefresh = uiInfo.uiDC.realTime + 25;
5723 } else {
5724 // add a line that shows the number of servers found
5725 if ( !uiInfo.numFoundPlayerServers ) {
5726 Com_sprintf( uiInfo.foundPlayerServerNames[0], sizeof( uiInfo.foundPlayerServerNames[0] ), "no servers found" );
5727 } else {
5728 Com_sprintf( uiInfo.foundPlayerServerNames[uiInfo.numFoundPlayerServers-1], sizeof( uiInfo.foundPlayerServerNames[0] ),
5729 "%d server%s found with player %s", uiInfo.numFoundPlayerServers - 1,
5730 uiInfo.numFoundPlayerServers == 2 ? "" : "s", uiInfo.findPlayerName );
5731 }
5732 uiInfo.nextFindPlayerRefresh = 0;
5733 // show the server status info for the selected server
5734 UI_FeederSelection( FEEDER_FINDPLAYER, uiInfo.currentFoundPlayerServer );
5735 }
5736 //#endif // #ifdef MISSIONPACK
5737 }
5738
5739 /*
5740 ==================
5741 UI_BuildServerStatus
5742 ==================
5743 */
UI_BuildServerStatus(qboolean force)5744 static void UI_BuildServerStatus( qboolean force ) {
5745 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5746 if ( uiInfo.nextFindPlayerRefresh ) {
5747 return;
5748 }
5749 if ( !force ) {
5750 if ( !uiInfo.nextServerStatusRefresh || uiInfo.nextServerStatusRefresh > uiInfo.uiDC.realTime ) {
5751 return;
5752 }
5753 } else {
5754 Menu_SetFeederSelection( NULL, FEEDER_SERVERSTATUS, 0, NULL );
5755 uiInfo.serverStatusInfo.numLines = 0;
5756 // reset all server status requests
5757 trap_LAN_ServerStatus( NULL, NULL, 0 );
5758 }
5759 if ( uiInfo.serverStatus.currentServer < 0 || uiInfo.serverStatus.currentServer > uiInfo.serverStatus.numDisplayServers || uiInfo.serverStatus.numDisplayServers == 0 ) {
5760 return;
5761 }
5762 if ( UI_GetServerStatusInfo( uiInfo.serverStatusAddress, &uiInfo.serverStatusInfo ) ) {
5763 uiInfo.nextServerStatusRefresh = 0;
5764 UI_GetServerStatusInfo( uiInfo.serverStatusAddress, NULL );
5765 } else {
5766 uiInfo.nextServerStatusRefresh = uiInfo.uiDC.realTime + 500;
5767 }
5768 //#endif // #ifdef MISSIONPACK
5769 }
5770
5771
5772
5773 /*
5774 ==================
5775 UI_FeederCount
5776 ==================
5777 */
UI_FeederCount(float feederID)5778 static int UI_FeederCount( float feederID ) {
5779 if ( feederID == FEEDER_HEADS ) {
5780 return uiInfo.characterCount;
5781 } else if ( feederID == FEEDER_Q3HEADS ) {
5782 return uiInfo.q3HeadCount;
5783 } else if ( feederID == FEEDER_CINEMATICS ) {
5784 return uiInfo.movieCount;
5785 } else if ( feederID == FEEDER_SAVEGAMES ) {
5786 return uiInfo.savegameCount;
5787 } else if ( feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS ) {
5788 return UI_MapCountByGameType( feederID == FEEDER_MAPS ? qtrue : qfalse );
5789 } else if ( feederID == FEEDER_SERVERS ) {
5790 return uiInfo.serverStatus.numDisplayServers;
5791 } else if ( feederID == FEEDER_SERVERSTATUS ) {
5792 return uiInfo.serverStatusInfo.numLines;
5793 } else if ( feederID == FEEDER_FINDPLAYER ) {
5794 return uiInfo.numFoundPlayerServers;
5795 } else if ( feederID == FEEDER_PLAYER_LIST ) {
5796 if ( uiInfo.uiDC.realTime > uiInfo.playerRefresh ) {
5797 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
5798 UI_BuildPlayerList();
5799 }
5800 return uiInfo.playerCount;
5801 } else if ( feederID == FEEDER_TEAM_LIST ) {
5802 if ( uiInfo.uiDC.realTime > uiInfo.playerRefresh ) {
5803 uiInfo.playerRefresh = uiInfo.uiDC.realTime + 3000;
5804 UI_BuildPlayerList();
5805 }
5806 return uiInfo.myTeamCount;
5807 } else if ( feederID == FEEDER_MODS ) {
5808 return uiInfo.modCount;
5809 } else if ( feederID == FEEDER_DEMOS ) {
5810 return uiInfo.demoCount;
5811 // NERVE - SMF
5812 } else if ( feederID == FEEDER_PICKSPAWN ) {
5813 return uiInfo.spawnCount;
5814 }
5815 // -NERVE - SMF
5816 return 0;
5817 }
5818
UI_SelectedMap(int index,int * actual)5819 static const char *UI_SelectedMap( int index, int *actual ) {
5820 int i, c;
5821 c = 0;
5822 *actual = 0;
5823 for ( i = 0; i < uiInfo.mapCount; i++ ) {
5824 if ( uiInfo.mapList[i].active ) {
5825 if ( c == index ) {
5826 *actual = i;
5827 return uiInfo.mapList[i].mapName;
5828 } else {
5829 c++;
5830 }
5831 }
5832 }
5833 return "";
5834 }
5835
UI_GetIndexFromSelection(int actual)5836 static int UI_GetIndexFromSelection( int actual ) {
5837 int i, c;
5838 c = 0;
5839 for ( i = 0; i < uiInfo.mapCount; i++ ) {
5840 if ( uiInfo.mapList[i].active ) {
5841 if ( i == actual ) {
5842 return c;
5843 }
5844 c++;
5845 }
5846 }
5847 return 0;
5848 }
5849
UI_UpdatePendingPings(void)5850 static void UI_UpdatePendingPings( void ) {
5851 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5852 trap_LAN_ResetPings(UI_SourceForLAN());
5853 uiInfo.serverStatus.refreshActive = qtrue;
5854 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
5855 //#endif // #ifdef MISSIONPACK
5856 }
5857
5858 // NERVE - SMF
UI_FeederAddItem(float feederID,const char * name,int index)5859 static void UI_FeederAddItem( float feederID, const char *name, int index ) {
5860
5861 }
5862 // -NERVE - SMF
5863
5864
5865 /*
5866 ==============
5867 UI_FileText
5868 ==============
5869 */
UI_FileText(char * fileName)5870 static const char *UI_FileText( char *fileName ) {
5871 int len;
5872 fileHandle_t f;
5873 static char buf[MAX_MENUDEFFILE];
5874
5875 len = trap_FS_FOpenFile( fileName, &f, FS_READ );
5876 if ( !f ) {
5877 return NULL;
5878 }
5879
5880 trap_FS_Read( buf, len, f );
5881 buf[len] = 0;
5882 trap_FS_FCloseFile( f );
5883 return &buf[0];
5884 }
5885
5886 //----(SA) added
5887 /*
5888 ==============
5889 UI_translateString
5890 ==============
5891 */
UI_translateString(const char * inString)5892 static const char *UI_translateString( const char *inString ) {
5893 int i, numStrings;
5894
5895 numStrings = sizeof( translateStrings ) / sizeof( translateStrings[0] ) - 1;
5896
5897 for ( i = 0; i < numStrings; i++ ) {
5898 if ( !translateStrings[i].name || !strlen( translateStrings[i].name ) ) {
5899 return inString;
5900 }
5901
5902 if ( !strcmp( inString, translateStrings[i].name ) ) {
5903 if ( translateStrings[i].localname && strlen( translateStrings[i].localname ) ) {
5904 return translateStrings[i].localname;
5905 }
5906 break;
5907 }
5908 }
5909
5910 return inString;
5911 }
5912 //----(SA) end
5913
5914
5915 /*
5916 ==============
5917 UI_FeederItemText
5918 ==============
5919 */
UI_FeederItemText(float feederID,int index,int column,qhandle_t * handle)5920 static const char *UI_FeederItemText( float feederID, int index, int column, qhandle_t *handle ) {
5921 static char info[MAX_STRING_CHARS];
5922 static char hostname[1024];
5923 static char clientBuff[32];
5924 static int lastServerColumn = -1, lastSaveColumn = -1;
5925 static int lastServerTime = 0;
5926 *handle = -1;
5927 if ( feederID == FEEDER_HEADS ) {
5928 if ( index >= 0 && index < uiInfo.characterCount ) {
5929 return uiInfo.characterList[index].name;
5930 }
5931 } else if ( feederID == FEEDER_Q3HEADS ) {
5932 if ( index >= 0 && index < uiInfo.q3HeadCount ) {
5933 return uiInfo.q3HeadNames[index];
5934 }
5935 } else if ( feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS ) {
5936 int actual;
5937 return UI_SelectedMap( index, &actual );
5938 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
5939 } else if ( feederID == FEEDER_SERVERS ) {
5940 if ( index >= 0 && index < uiInfo.serverStatus.numDisplayServers ) {
5941 int ping, game;
5942 if ( lastServerColumn != column || lastServerTime > uiInfo.uiDC.realTime + 5000 ) {
5943 trap_LAN_GetServerInfo(UI_SourceForLAN(), uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
5944 lastServerColumn = column;
5945 lastServerTime = uiInfo.uiDC.realTime;
5946 }
5947 ping = atoi( Info_ValueForKey( info, "ping" ) );
5948 if ( ping == -1 ) {
5949 // if we ever see a ping that is out of date, do a server refresh
5950 // UI_UpdatePendingPings();
5951 }
5952 switch ( column ) {
5953 case SORT_HOST:
5954 if ( ping <= 0 ) {
5955 return Info_ValueForKey( info, "addr" );
5956 } else {
5957 int nettype = atoi(Info_ValueForKey(info, "nettype"));
5958
5959 if (nettype < 0 || nettype >= ARRAY_LEN(netnames)) {
5960 nettype = 0;
5961 }
5962
5963 Com_sprintf( hostname, sizeof( hostname ), "^7|^2%s^7| %s",
5964 netnames[nettype],
5965 Info_ValueForKey( info, "hostname" ));
5966 return hostname;
5967 }
5968 case SORT_MAP: return Info_ValueForKey( info, "mapname" );
5969 case SORT_CLIENTS:
5970 Com_sprintf( clientBuff, sizeof( clientBuff ), "%s (%s)", Info_ValueForKey( info, "clients" ), Info_ValueForKey( info, "sv_maxclients" ) );
5971 return clientBuff;
5972 case SORT_GAME:
5973 game = atoi( Info_ValueForKey( info, "gametype" ) );
5974 if ( game >= 0 && game < numTeamArenaGameTypes ) {
5975 return teamArenaGameTypes[game];
5976 } else {
5977 return "Unknown";
5978 }
5979 case SORT_PING:
5980 if ( ping <= 0 ) {
5981 return "...";
5982 } else {
5983 return Info_ValueForKey( info, "ping" );
5984 }
5985 }
5986 }
5987 } else if ( feederID == FEEDER_SERVERSTATUS ) {
5988 if ( index >= 0 && index < uiInfo.serverStatusInfo.numLines ) {
5989 if ( column >= 0 && column < 4 ) {
5990 return uiInfo.serverStatusInfo.lines[index][column];
5991 }
5992 }
5993 } else if ( feederID == FEEDER_FINDPLAYER ) {
5994 if ( index >= 0 && index < uiInfo.numFoundPlayerServers ) {
5995 //return uiInfo.foundPlayerServerAddresses[index];
5996 return uiInfo.foundPlayerServerNames[index];
5997 }
5998 //#endif // #ifdef MISSIONPACK
5999 } else if ( feederID == FEEDER_PLAYER_LIST ) {
6000 if ( index >= 0 && index < uiInfo.playerCount ) {
6001 return uiInfo.playerNames[index];
6002 }
6003 } else if ( feederID == FEEDER_TEAM_LIST ) {
6004 if ( index >= 0 && index < uiInfo.myTeamCount ) {
6005 return uiInfo.teamNames[index];
6006 }
6007 } else if ( feederID == FEEDER_MODS ) {
6008 if ( index >= 0 && index < uiInfo.modCount ) {
6009 if ( uiInfo.modList[index].modDescr && *uiInfo.modList[index].modDescr ) {
6010 return uiInfo.modList[index].modDescr;
6011 } else {
6012 return uiInfo.modList[index].modName;
6013 }
6014 }
6015 } else if ( feederID == FEEDER_CINEMATICS ) {
6016 if ( index >= 0 && index < uiInfo.movieCount ) {
6017 return uiInfo.movieList[index];
6018 }
6019 } else if ( feederID == FEEDER_SAVEGAMES ) {
6020 if ( index >= 0 && index < uiInfo.savegameCount ) {
6021 // int ping, game;
6022 if ( lastSaveColumn != column ) {
6023 // trap_LAN_GetServerInfo(ui_netSource.integer, uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
6024 lastSaveColumn = column;
6025 }
6026
6027 switch ( column ) {
6028 case SORT_SAVENAME:
6029 return uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameName;
6030 break;
6031 case SORT_SAVETIME:
6032 return uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].time;
6033 break;
6034
6035 }
6036 }
6037 } else if ( feederID == FEEDER_DEMOS ) {
6038 if ( index >= 0 && index < uiInfo.demoCount ) {
6039 return uiInfo.demoList[index];
6040 }
6041 }
6042 // NERVE - SMF
6043 else if ( feederID == FEEDER_PICKSPAWN ) {
6044 return uiInfo.spawnPoints[index];
6045 }
6046 // -NERVE - SMF
6047 return "";
6048 }
6049
6050
UI_FeederItemImage(float feederID,int index)6051 static qhandle_t UI_FeederItemImage( float feederID, int index ) {
6052 if ( feederID == FEEDER_HEADS ) {
6053 if ( index >= 0 && index < uiInfo.characterCount ) {
6054 if ( uiInfo.characterList[index].headImage == -1 ) {
6055 uiInfo.characterList[index].headImage = trap_R_RegisterShaderNoMip( uiInfo.characterList[index].imageName );
6056 }
6057 return uiInfo.characterList[index].headImage;
6058 }
6059 } else if ( feederID == FEEDER_Q3HEADS ) {
6060 if ( index >= 0 && index < uiInfo.q3HeadCount ) {
6061 return uiInfo.q3HeadIcons[index];
6062 }
6063 } else if ( feederID == FEEDER_ALLMAPS || feederID == FEEDER_MAPS ) {
6064 int actual;
6065
6066 UI_SelectedMap( index, &actual );
6067 index = actual;
6068 if ( index >= 0 && index < uiInfo.mapCount ) {
6069 if ( uiInfo.mapList[index].levelShot == -1 ) {
6070 uiInfo.mapList[index].levelShot = trap_R_RegisterShaderNoMip( uiInfo.mapList[index].imageName );
6071 }
6072 return uiInfo.mapList[index].levelShot;
6073 }
6074 } else if ( feederID == FEEDER_SAVEGAMES ) {
6075 if ( index >= 0 && index < uiInfo.savegameCount ) {
6076 if ( uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].sshotImage == -1 ) {
6077 uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].sshotImage = trap_R_RegisterShaderNoMip( va( "levelshots/%s.tga",uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].mapName ) );
6078 }
6079 return uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].sshotImage;
6080 }
6081 }
6082
6083 return 0;
6084 }
6085
UI_FeederSelection(float feederID,int index)6086 static void UI_FeederSelection( float feederID, int index ) {
6087 static char info[MAX_STRING_CHARS];
6088 if ( feederID == FEEDER_HEADS ) {
6089 if ( index >= 0 && index < uiInfo.characterCount ) {
6090 trap_Cvar_Set( "team_model", uiInfo.characterList[index].female ? "janet" : "james" );
6091 trap_Cvar_Set( "team_headmodel", va( "*%s", uiInfo.characterList[index].name ) );
6092 updateModel = qtrue;
6093 }
6094 } else if ( feederID == FEEDER_Q3HEADS ) {
6095 if ( index >= 0 && index < uiInfo.q3HeadCount ) {
6096 trap_Cvar_Set( "model", uiInfo.q3HeadNames[index] );
6097 trap_Cvar_Set( "headmodel", uiInfo.q3HeadNames[index] );
6098 updateModel = qtrue;
6099 }
6100 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
6101 } else if ( feederID == FEEDER_MAPS || feederID == FEEDER_ALLMAPS ) {
6102 int actual, map;
6103 map = ( feederID == FEEDER_ALLMAPS ) ? ui_currentNetMap.integer : ui_currentMap.integer;
6104 if ( uiInfo.mapList[map].cinematic >= 0 ) {
6105 trap_CIN_StopCinematic( uiInfo.mapList[map].cinematic );
6106 uiInfo.mapList[map].cinematic = -1;
6107 }
6108 UI_SelectedMap( index, &actual );
6109 trap_Cvar_Set( "ui_mapIndex", va( "%d", index ) );
6110 ui_mapIndex.integer = index;
6111
6112 if ( feederID == FEEDER_MAPS ) {
6113 ui_currentMap.integer = actual;
6114 trap_Cvar_Set( "ui_currentMap", va( "%d", actual ) );
6115 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 ) );
6116 UI_LoadBestScores( uiInfo.mapList[ui_currentMap.integer].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum );
6117 trap_Cvar_Set( "ui_opponentModel", uiInfo.mapList[ui_currentMap.integer].opponentName );
6118 updateOpponentModel = qtrue;
6119 } else {
6120 ui_currentNetMap.integer = actual;
6121 trap_Cvar_Set( "ui_currentNetMap", va( "%d", actual ) );
6122 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 ) );
6123 }
6124
6125 } else if ( feederID == FEEDER_SERVERS ) {
6126 const char *mapName = NULL;
6127 uiInfo.serverStatus.currentServer = index;
6128 trap_LAN_GetServerInfo(UI_SourceForLAN(), uiInfo.serverStatus.displayServers[index], info, MAX_STRING_CHARS);
6129 uiInfo.serverStatus.currentServerPreview = trap_R_RegisterShaderNoMip( va( "levelshots/%s", Info_ValueForKey( info, "mapname" ) ) );
6130 if ( uiInfo.serverStatus.currentServerCinematic >= 0 ) {
6131 trap_CIN_StopCinematic( uiInfo.serverStatus.currentServerCinematic );
6132 uiInfo.serverStatus.currentServerCinematic = -1;
6133 }
6134 mapName = Info_ValueForKey( info, "mapname" );
6135 if ( mapName && *mapName ) {
6136 uiInfo.serverStatus.currentServerCinematic = trap_CIN_PlayCinematic( va( "%s.roq", mapName ), 0, 0, 0, 0, ( CIN_loop | CIN_silent ) );
6137 }
6138 } else if ( feederID == FEEDER_SERVERSTATUS ) {
6139 //
6140 } else if ( feederID == FEEDER_FINDPLAYER ) {
6141 uiInfo.currentFoundPlayerServer = index;
6142 //
6143 if ( index < uiInfo.numFoundPlayerServers - 1 ) {
6144 // build a new server status for this server
6145 Q_strncpyz( uiInfo.serverStatusAddress, uiInfo.foundPlayerServerAddresses[uiInfo.currentFoundPlayerServer], sizeof( uiInfo.serverStatusAddress ) );
6146 Menu_SetFeederSelection( NULL, FEEDER_SERVERSTATUS, 0, NULL );
6147 UI_BuildServerStatus( qtrue );
6148 }
6149 //#endif // #ifdef MISSIONPACK
6150 } else if ( feederID == FEEDER_PLAYER_LIST ) {
6151 uiInfo.playerIndex = index;
6152 } else if ( feederID == FEEDER_TEAM_LIST ) {
6153 uiInfo.teamIndex = index;
6154 } else if ( feederID == FEEDER_MODS ) {
6155 uiInfo.modIndex = index;
6156 } else if ( feederID == FEEDER_CINEMATICS ) {
6157 uiInfo.movieIndex = index;
6158 if ( uiInfo.previewMovie >= 0 ) {
6159 trap_CIN_StopCinematic( uiInfo.previewMovie );
6160 }
6161 uiInfo.previewMovie = -1;
6162 } else if ( feederID == FEEDER_SAVEGAMES ) {
6163 // menuDef_t *menu;
6164 // itemDef_t *itemdef;
6165
6166 if ( index >= 0 && index < uiInfo.savegameCount ) {
6167
6168 if ( DC->getCVarValue( "developer" ) ) {
6169 Com_Printf( "setting sel save to: %s\n (savename: %s)\n", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameName, uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameFile );
6170 }
6171
6172 // the text entry box
6173 trap_Cvar_Set( "ui_savegame", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameName );
6174
6175 trap_Cvar_Set( "ui_savegameName", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameName );
6176 trap_Cvar_Set( "ui_savegameInfo", uiInfo.savegameList[uiInfo.savegameStatus.displaySavegames[index]].savegameInfoText );
6177
6178 // menu = Menu_GetFocused();
6179 // itemdef = Menu_FindItemByName( menu, "savename" );
6180 // itemdef->cursorPos = 0;
6181 }
6182 } else if ( feederID == FEEDER_DEMOS ) {
6183 uiInfo.demoIndex = index;
6184 // NERVE - SMF
6185 } else if ( feederID == FEEDER_PICKSPAWN ) {
6186 trap_Cmd_ExecuteText( EXEC_NOW, va( "setspawnpt %i\n", index ) );
6187 }
6188 // -NERVE - SMF
6189 }
6190
6191 // TTimo: unused
6192 /*
6193 static qboolean Team_Parse(char **p) {
6194 char *token;
6195 const char *tempStr;
6196 int i;
6197
6198 token = COM_ParseExt(p, qtrue);
6199
6200 if (token[0] != '{') {
6201 return qfalse;
6202 }
6203
6204 while ( 1 ) {
6205
6206 token = COM_ParseExt(p, qtrue);
6207
6208 if (Q_stricmp(token, "}") == 0) {
6209 return qtrue;
6210 }
6211
6212 if ( !token[0] ) {
6213 return qfalse;
6214 }
6215
6216 if (token[0] == '{') {
6217 if (uiInfo.teamCount == MAX_TEAMS) {
6218 uiInfo.teamCount--;
6219 Com_Printf("Too many teams, last team replaced!\n");
6220 }
6221
6222 // seven tokens per line, team name and icon, and 5 team member names
6223 if (!String_Parse(p, &uiInfo.teamList[uiInfo.teamCount].teamName) || !String_Parse(p, &tempStr)) {
6224 return qfalse;
6225 }
6226
6227
6228 uiInfo.teamList[uiInfo.teamCount].imageName = tempStr;
6229 uiInfo.teamList[uiInfo.teamCount].teamIcon = trap_R_RegisterShaderNoMip(uiInfo.teamList[uiInfo.teamCount].imageName);
6230 uiInfo.teamList[uiInfo.teamCount].teamIcon_Metal = trap_R_RegisterShaderNoMip(va("%s_metal",uiInfo.teamList[uiInfo.teamCount].imageName));
6231 uiInfo.teamList[uiInfo.teamCount].teamIcon_Name = trap_R_RegisterShaderNoMip(va("%s_name", uiInfo.teamList[uiInfo.teamCount].imageName));
6232
6233 uiInfo.teamList[uiInfo.teamCount].cinematic = -1;
6234
6235 for (i = 0; i < TEAM_MEMBERS; i++) {
6236 uiInfo.teamList[uiInfo.teamCount].teamMembers[i] = NULL;
6237 if (!String_Parse(p, &uiInfo.teamList[uiInfo.teamCount].teamMembers[i])) {
6238 return qfalse;
6239 }
6240 }
6241
6242 Com_Printf("Loaded team %s with team icon %s.\n", uiInfo.teamList[uiInfo.teamCount].teamName, tempStr);
6243 uiInfo.teamCount++;
6244
6245 token = COM_ParseExt(p, qtrue);
6246 if (token[0] != '}') {
6247 return qfalse;
6248 }
6249 }
6250 }
6251
6252 return qfalse;
6253 }
6254
6255 static qboolean Character_Parse(char **p) {
6256 char *token;
6257 const char *tempStr;
6258
6259 token = COM_ParseExt(p, qtrue);
6260
6261 if (token[0] != '{') {
6262 return qfalse;
6263 }
6264
6265
6266 while ( 1 ) {
6267 token = COM_ParseExt(p, qtrue);
6268
6269 if (Q_stricmp(token, "}") == 0) {
6270 return qtrue;
6271 }
6272
6273 if ( !token[0] ) {
6274 return qfalse;
6275 }
6276
6277 if (token[0] == '{') {
6278 if (uiInfo.characterCount == MAX_HEADS) {
6279 uiInfo.characterCount--;
6280 Com_Printf("Too many characters, last character replaced!\n");
6281 }
6282
6283 // two tokens per line, gametype name and sex
6284 if (!String_Parse(p, &uiInfo.characterList[uiInfo.characterCount].name) || !String_Parse(p, &tempStr)) {
6285 return qfalse;
6286 }
6287
6288 uiInfo.characterList[uiInfo.characterCount].headImage = -1;
6289 uiInfo.characterList[uiInfo.characterCount].imageName = String_Alloc(va("models/players/heads/%s/icon_default.tga", uiInfo.characterList[uiInfo.characterCount].name));
6290
6291 if (tempStr && (tempStr[0] == 'f' || tempStr[0] == 'F')) {
6292 uiInfo.characterList[uiInfo.characterCount].female = qtrue;
6293 } else {
6294 uiInfo.characterList[uiInfo.characterCount].female = qfalse;
6295 }
6296
6297 Com_Printf("Loaded %s character %s.\n", tempStr, uiInfo.characterList[uiInfo.characterCount].name);
6298 uiInfo.characterCount++;
6299
6300 token = COM_ParseExt(p, qtrue);
6301 if (token[0] != '}') {
6302 return qfalse;
6303 }
6304 }
6305 }
6306
6307 return qfalse;
6308 }
6309
6310 static qboolean Alias_Parse(char **p) {
6311 char *token;
6312
6313 token = COM_ParseExt(p, qtrue);
6314
6315 if (token[0] != '{') {
6316 return qfalse;
6317 }
6318
6319 while ( 1 ) {
6320 token = COM_ParseExt(p, qtrue);
6321
6322 if (Q_stricmp(token, "}") == 0) {
6323 return qtrue;
6324 }
6325
6326 if ( !token[0] ) {
6327 return qfalse;
6328 }
6329
6330 if (token[0] == '{') {
6331 if (uiInfo.aliasCount == MAX_ALIASES) {
6332 uiInfo.aliasCount--;
6333 Com_Printf("Too many aliases, last alias replaced!\n");
6334 }
6335
6336 // three tokens per line, character name, bot alias, and preferred action a - all purpose, d - defense, o - offense
6337 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)) {
6338 return qfalse;
6339 }
6340
6341 Com_Printf("Loaded character alias %s using character ai %s.\n", uiInfo.aliasList[uiInfo.aliasCount].name, uiInfo.aliasList[uiInfo.aliasCount].ai);
6342 uiInfo.aliasCount++;
6343
6344 token = COM_ParseExt(p, qtrue);
6345 if (token[0] != '}') {
6346 return qfalse;
6347 }
6348 }
6349 }
6350
6351 return qfalse;
6352 }
6353 */
6354
6355 // mode
6356 // 0 - high level parsing
6357 // 1 - team parsing
6358 // 2 - character parsing
6359 // TTimo: unused
6360 /*
6361 static void UI_ParseTeamInfo(const char *teamFile) {
6362 char *token;
6363 char *p;
6364 char *buff = NULL;
6365 //int mode = 0; // TTimo: unused
6366
6367 buff = GetMenuBuffer(teamFile);
6368 if (!buff) {
6369 return;
6370 }
6371
6372 p = buff;
6373
6374 while ( 1 ) {
6375 token = COM_ParseExt( &p, qtrue );
6376 if( !token[0] || token[0] == '}') {
6377 break;
6378 }
6379
6380 if ( Q_stricmp( token, "}" ) == 0 ) {
6381 break;
6382 }
6383
6384 if (Q_stricmp(token, "teams") == 0) {
6385
6386 if (Team_Parse(&p)) {
6387 continue;
6388 } else {
6389 break;
6390 }
6391 }
6392
6393 if (Q_stricmp(token, "characters") == 0) {
6394 Character_Parse(&p);
6395 }
6396
6397 if (Q_stricmp(token, "aliases") == 0) {
6398 Alias_Parse(&p);
6399 }
6400
6401 }
6402
6403 }
6404 */
6405
6406 /*
6407 ==============
6408 GameType_Parse
6409 ==============
6410 */
GameType_Parse(char ** p,qboolean join)6411 static qboolean GameType_Parse( char **p, qboolean join ) {
6412 char *token;
6413
6414 token = COM_ParseExt( p, qtrue );
6415
6416 if ( token[0] != '{' ) {
6417 return qfalse;
6418 }
6419
6420 if ( join ) {
6421 uiInfo.numJoinGameTypes = 0;
6422 } else {
6423 uiInfo.numGameTypes = 0;
6424 }
6425
6426 while ( 1 ) {
6427 token = COM_ParseExt( p, qtrue );
6428
6429 if ( Q_stricmp( token, "}" ) == 0 ) {
6430 return qtrue;
6431 }
6432
6433 if ( !token[0] ) {
6434 return qfalse;
6435 }
6436
6437 if ( token[0] == '{' ) {
6438 // two tokens per line, gametype name and sex
6439 if ( join ) {
6440 if ( !String_Parse( p, &uiInfo.joinGameTypes[uiInfo.numJoinGameTypes].gameType ) || !Int_Parse( p, &uiInfo.joinGameTypes[uiInfo.numJoinGameTypes].gtEnum ) ) {
6441 return qfalse;
6442 }
6443 } else {
6444 if ( !String_Parse( p, &uiInfo.gameTypes[uiInfo.numGameTypes].gameType ) || !Int_Parse( p, &uiInfo.gameTypes[uiInfo.numGameTypes].gtEnum ) ) {
6445 return qfalse;
6446 }
6447 }
6448
6449 if ( join ) {
6450 if ( uiInfo.numJoinGameTypes < MAX_GAMETYPES ) {
6451 uiInfo.numJoinGameTypes++;
6452 } else {
6453 Com_Printf( "Too many net game types, last one replace!\n" );
6454 }
6455 } else {
6456 if ( uiInfo.numGameTypes < MAX_GAMETYPES ) {
6457 uiInfo.numGameTypes++;
6458 } else {
6459 Com_Printf( "Too many game types, last one replace!\n" );
6460 }
6461 }
6462
6463 token = COM_ParseExt( p, qtrue );
6464 if ( token[0] != '}' ) {
6465 return qfalse;
6466 }
6467 }
6468 }
6469 return qfalse;
6470 }
6471
MapList_Parse(char ** p)6472 static qboolean MapList_Parse( char **p ) {
6473 char *token;
6474
6475 token = COM_ParseExt( p, qtrue );
6476
6477 if ( token[0] != '{' ) {
6478 return qfalse;
6479 }
6480
6481 uiInfo.mapCount = 0;
6482
6483 while ( 1 ) {
6484 token = COM_ParseExt( p, qtrue );
6485
6486 if ( Q_stricmp( token, "}" ) == 0 ) {
6487 return qtrue;
6488 }
6489
6490 if ( !token[0] ) {
6491 return qfalse;
6492 }
6493
6494 if ( token[0] == '{' ) {
6495 if ( !String_Parse( p, &uiInfo.mapList[uiInfo.mapCount].mapName ) || !String_Parse( p, &uiInfo.mapList[uiInfo.mapCount].mapLoadName )
6496 || !Int_Parse( p, &uiInfo.mapList[uiInfo.mapCount].teamMembers ) ) {
6497 return qfalse;
6498 }
6499
6500 if ( !String_Parse( p, &uiInfo.mapList[uiInfo.mapCount].opponentName ) ) {
6501 return qfalse;
6502 }
6503
6504 uiInfo.mapList[uiInfo.mapCount].typeBits = 0;
6505
6506 while ( 1 ) {
6507 token = COM_ParseExt( p, qtrue );
6508 if ( Q_isnumeric( token[0] ) ) {
6509 uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << ( token[0] - 0x030 ) );
6510 if ( !Int_Parse( p, &uiInfo.mapList[uiInfo.mapCount].timeToBeat[token[0] - 0x30] ) ) {
6511 return qfalse;
6512 }
6513 } else {
6514 break;
6515 }
6516 }
6517
6518 //mapList[mapCount].imageName = String_Alloc(va("levelshots/%s", mapList[mapCount].mapLoadName));
6519 //if (uiInfo.mapCount == 0) {
6520 // only load the first cinematic, selection loads the others
6521 // uiInfo.mapList[uiInfo.mapCount].cinematic = trap_CIN_PlayCinematic(va("%s.roq",uiInfo.mapList[uiInfo.mapCount].mapLoadName), qfalse, qfalse, qtrue, 0, 0, 0, 0);
6522 //}
6523 uiInfo.mapList[uiInfo.mapCount].cinematic = -1;
6524 uiInfo.mapList[uiInfo.mapCount].levelShot = trap_R_RegisterShaderNoMip( va( "levelshots/%s_small", uiInfo.mapList[uiInfo.mapCount].mapLoadName ) );
6525
6526 if ( uiInfo.mapCount < MAX_MAPS ) {
6527 uiInfo.mapCount++;
6528 } else {
6529 Com_Printf( "Too many maps, last one replaced!\n" );
6530 }
6531 }
6532 }
6533 return qfalse;
6534 }
6535
UI_ParseGameInfo(const char * teamFile)6536 static void UI_ParseGameInfo( const char *teamFile ) {
6537 char *token;
6538 char *p;
6539 char *buff = NULL;
6540 //int mode = 0; // TTimo: unused
6541
6542 buff = GetMenuBuffer( teamFile );
6543 if ( !buff ) {
6544 return;
6545 }
6546
6547 p = buff;
6548
6549 while ( 1 ) {
6550 token = COM_ParseExt( &p, qtrue );
6551 if ( !token[0] || token[0] == '}' ) {
6552 break;
6553 }
6554
6555 if ( Q_stricmp( token, "}" ) == 0 ) {
6556 break;
6557 }
6558
6559 if ( Q_stricmp( token, "gametypes" ) == 0 ) {
6560
6561 if ( GameType_Parse( &p, qfalse ) ) {
6562 continue;
6563 } else {
6564 break;
6565 }
6566 }
6567
6568 if ( Q_stricmp( token, "joingametypes" ) == 0 ) {
6569
6570 if ( GameType_Parse( &p, qtrue ) ) {
6571 continue;
6572 } else {
6573 break;
6574 }
6575 }
6576
6577 if ( Q_stricmp( token, "maps" ) == 0 ) {
6578 // start a new menu
6579 MapList_Parse( &p );
6580 }
6581
6582 }
6583 }
6584
UI_Pause(qboolean b)6585 static void UI_Pause( qboolean b ) {
6586 if ( b ) {
6587 // pause the game and set the ui keycatcher
6588 trap_Cvar_Set( "cl_paused", "1" );
6589 trap_Key_SetCatcher( KEYCATCH_UI );
6590 } else {
6591 // unpause the game and clear the ui keycatcher
6592 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
6593 trap_Key_ClearStates();
6594 trap_Cvar_Set( "cl_paused", "0" );
6595 }
6596 }
6597
6598 // TTimo: unused
6599 /*
6600 static int UI_OwnerDraw_Width(int ownerDraw) {
6601 // TTimo: end of non-void
6602 return 0;
6603 }
6604 */
6605
UI_PlayCinematic(const char * name,float x,float y,float w,float h)6606 static int UI_PlayCinematic( const char *name, float x, float y, float w, float h ) {
6607 return trap_CIN_PlayCinematic( name, x, y, w, h, ( CIN_loop | CIN_silent ) );
6608 }
6609
UI_StopCinematic(int handle)6610 static void UI_StopCinematic( int handle ) {
6611 if ( handle >= 0 ) {
6612 trap_CIN_StopCinematic( handle );
6613 } else {
6614 handle = abs( handle );
6615 if ( handle == UI_MAPCINEMATIC ) {
6616 if ( uiInfo.mapList[ui_currentMap.integer].cinematic >= 0 ) {
6617 trap_CIN_StopCinematic( uiInfo.mapList[ui_currentMap.integer].cinematic );
6618 uiInfo.mapList[ui_currentMap.integer].cinematic = -1;
6619 }
6620 } else if ( handle == UI_NETMAPCINEMATIC ) {
6621 if ( uiInfo.serverStatus.currentServerCinematic >= 0 ) {
6622 trap_CIN_StopCinematic( uiInfo.serverStatus.currentServerCinematic );
6623 uiInfo.serverStatus.currentServerCinematic = -1;
6624 }
6625 } else if ( handle == UI_CLANCINEMATIC ) {
6626 int i = UI_TeamIndexFromName( UI_Cvar_VariableString( "ui_teamName" ) );
6627 if ( i >= 0 && i < uiInfo.teamCount ) {
6628 if ( uiInfo.teamList[i].cinematic >= 0 ) {
6629 trap_CIN_StopCinematic( uiInfo.teamList[i].cinematic );
6630 uiInfo.teamList[i].cinematic = -1;
6631 }
6632 }
6633 }
6634 }
6635 }
6636
UI_DrawCinematic(int handle,float x,float y,float w,float h)6637 static void UI_DrawCinematic( int handle, float x, float y, float w, float h ) {
6638 if ( ui_fixedAspect.integer ) {
6639 if ( DC->glconfig.vidWidth * 480.0 > DC->glconfig.vidHeight * 640.0 ) {
6640 float scaledx = x * ( 480.0 / 640.0 ) + ( DC->xBias / DC->xscaleStretch);
6641 float scaledw = w * ( 480.0 / 640.0 );
6642
6643 trap_CIN_SetExtents( handle, scaledx, y, scaledw, h );
6644 } else if ( DC->glconfig.vidWidth * 480.0 < DC->glconfig.vidHeight * 640.0 ) {
6645 float scaledy = y * ( 480.0 / 640.0 ) + ( DC->yBias / DC->yscaleStretch);
6646 float scaledh = h * ( 480.0 / 640.0 );
6647
6648 trap_CIN_SetExtents( handle, x, scaledy, w, scaledh );
6649 } else {
6650 trap_CIN_SetExtents( handle, x, y, w, h );
6651 }
6652 } else {
6653 trap_CIN_SetExtents( handle, x, y, w, h );
6654 }
6655
6656 trap_CIN_DrawCinematic( handle );
6657 }
6658
UI_RunCinematicFrame(int handle)6659 static void UI_RunCinematicFrame( int handle ) {
6660 trap_CIN_RunCinematic( handle );
6661 }
6662
6663
6664
6665 /*
6666 =================
6667 PlayerModel_BuildList
6668 =================
6669 */
UI_BuildQ3Model_List(void)6670 static void UI_BuildQ3Model_List( void ) {
6671 int numdirs;
6672 int numfiles;
6673 char dirlist[2048];
6674 char filelist[2048];
6675 char skinname[MAX_QPATH];
6676 char* dirptr;
6677 char* fileptr;
6678 int i;
6679 int j;
6680 int dirlen;
6681 int filelen;
6682
6683 uiInfo.q3HeadCount = 0;
6684
6685 // iterate directory of all player models
6686 numdirs = trap_FS_GetFileList( "models/players", "/", dirlist, 2048 );
6687 dirptr = dirlist;
6688 for ( i = 0; i < numdirs && uiInfo.q3HeadCount < MAX_PLAYERMODELS; i++,dirptr += dirlen + 1 )
6689 {
6690 dirlen = strlen( dirptr );
6691
6692 if ( dirlen && dirptr[dirlen - 1] == '/' ) {
6693 dirptr[dirlen - 1] = '\0';
6694 }
6695
6696 if ( !strcmp( dirptr,"." ) || !strcmp( dirptr,".." ) ) {
6697 continue;
6698 }
6699
6700 // iterate all skin files in directory
6701 numfiles = trap_FS_GetFileList( va( "models/players/%s",dirptr ), "tga", filelist, 2048 );
6702 fileptr = filelist;
6703 for ( j = 0; j < numfiles && uiInfo.q3HeadCount < MAX_PLAYERMODELS; j++,fileptr += filelen + 1 )
6704 {
6705 filelen = strlen( fileptr );
6706
6707 COM_StripExtension(fileptr, skinname, sizeof(skinname));
6708
6709 // look for icon_????
6710 if ( Q_stricmpn( skinname, "icon_", 5 ) == 0 && !( Q_stricmp( skinname,"icon_blue" ) == 0 || Q_stricmp( skinname,"icon_red" ) == 0 ) ) {
6711 if ( Q_stricmp( skinname, "icon_default" ) == 0 ) {
6712 Com_sprintf( uiInfo.q3HeadNames[uiInfo.q3HeadCount], sizeof(uiInfo.q3HeadNames[uiInfo.q3HeadCount]), "%s", dirptr);
6713 } else {
6714 Com_sprintf( uiInfo.q3HeadNames[uiInfo.q3HeadCount], sizeof( uiInfo.q3HeadNames[uiInfo.q3HeadCount] ), "%s/%s",dirptr, skinname + 5 );
6715 }
6716 uiInfo.q3HeadIcons[uiInfo.q3HeadCount++] = trap_R_RegisterShaderNoMip( va( "models/players/%s/%s",dirptr,skinname ) );
6717 }
6718
6719 }
6720 }
6721
6722 }
6723
6724
6725 /*
6726 =================
6727 UI_Init
6728 =================
6729 */
_UI_Init(qboolean inGameLoad)6730 void _UI_Init( qboolean inGameLoad ) {
6731 const char *menuSet;
6732
6733 //uiInfo.inGameLoad = inGameLoad;
6734
6735 UI_RegisterCvars();
6736 UI_InitMemory();
6737
6738 // cache redundant calulations
6739 trap_GetGlconfig( &uiInfo.uiDC.glconfig );
6740
6741 // for 640x480 virtualized screen
6742 if ( ui_fixedAspect.integer ) {
6743 uiInfo.uiDC.xscaleStretch = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
6744 uiInfo.uiDC.yscaleStretch = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
6745 if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) {
6746 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
6747 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
6748 // wide screen
6749 uiInfo.uiDC.xBias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * (640.0/480.0) ) );
6750 uiInfo.uiDC.xscale = uiInfo.uiDC.yscale;
6751 // no narrow screen
6752 uiInfo.uiDC.yBias = 0;
6753 } else {
6754 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
6755 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
6756 // narrow screen
6757 uiInfo.uiDC.yBias = 0.5 * ( uiInfo.uiDC.glconfig.vidHeight - ( uiInfo.uiDC.glconfig.vidWidth * (480.0/640.0) ) );
6758 uiInfo.uiDC.yscale = uiInfo.uiDC.xscale;
6759 // no wide screen
6760 uiInfo.uiDC.xBias = 0;
6761 }
6762 } else {
6763 uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * ( 1.0 / 480.0 );
6764 uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * ( 1.0 / 640.0 );
6765 if ( uiInfo.uiDC.glconfig.vidWidth * 480 > uiInfo.uiDC.glconfig.vidHeight * 640 ) {
6766 // wide screen
6767 uiInfo.uiDC.bias = 0.5 * ( uiInfo.uiDC.glconfig.vidWidth - ( uiInfo.uiDC.glconfig.vidHeight * ( 640.0 / 480.0 ) ) );
6768 } else {
6769 // no wide screen
6770 uiInfo.uiDC.bias = 0;
6771 }
6772 }
6773
6774
6775 //UI_Load();
6776 uiInfo.uiDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip;
6777 uiInfo.uiDC.setColor = &UI_SetColor;
6778 uiInfo.uiDC.drawHandlePic = &UI_DrawHandlePic;
6779 uiInfo.uiDC.drawStretchPic = &trap_R_DrawStretchPic;
6780 uiInfo.uiDC.drawText = &Text_Paint;
6781 uiInfo.uiDC.textWidth = &Text_Width;
6782 uiInfo.uiDC.textHeight = &Text_Height;
6783 uiInfo.uiDC.registerModel = &trap_R_RegisterModel;
6784 uiInfo.uiDC.modelBounds = &trap_R_ModelBounds;
6785 uiInfo.uiDC.fillRect = &UI_FillRect;
6786 uiInfo.uiDC.drawRect = &_UI_DrawRect;
6787 uiInfo.uiDC.drawTopBottom = &_UI_DrawTopBottom;
6788 uiInfo.uiDC.clearScene = &trap_R_ClearScene;
6789 uiInfo.uiDC.drawSides = &_UI_DrawSides;
6790 uiInfo.uiDC.addRefEntityToScene = &trap_R_AddRefEntityToScene;
6791 uiInfo.uiDC.renderScene = &trap_R_RenderScene;
6792 uiInfo.uiDC.registerFont = &trap_R_RegisterFont;
6793 uiInfo.uiDC.ownerDrawItem = &UI_OwnerDraw;
6794 uiInfo.uiDC.getValue = &UI_GetValue;
6795 uiInfo.uiDC.ownerDrawVisible = &UI_OwnerDrawVisible;
6796 uiInfo.uiDC.runScript = &UI_RunMenuScript;
6797 uiInfo.uiDC.getTeamColor = &UI_GetTeamColor;
6798 uiInfo.uiDC.setCVar = trap_Cvar_Set;
6799 uiInfo.uiDC.getCVarString = trap_Cvar_VariableStringBuffer;
6800 uiInfo.uiDC.getCVarValue = trap_Cvar_VariableValue;
6801 uiInfo.uiDC.drawTextWithCursor = &Text_PaintWithCursor;
6802 uiInfo.uiDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode;
6803 uiInfo.uiDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode;
6804 uiInfo.uiDC.startLocalSound = &trap_S_StartLocalSound;
6805 uiInfo.uiDC.ownerDrawHandleKey = &UI_OwnerDrawHandleKey;
6806 uiInfo.uiDC.feederCount = &UI_FeederCount;
6807 uiInfo.uiDC.feederItemImage = &UI_FeederItemImage;
6808 uiInfo.uiDC.feederItemText = &UI_FeederItemText;
6809 uiInfo.uiDC.fileText = &UI_FileText; //----(SA)
6810
6811 uiInfo.uiDC.getTranslatedString = &UI_translateString; //----(SA) added
6812
6813 uiInfo.uiDC.feederSelection = &UI_FeederSelection;
6814 uiInfo.uiDC.feederAddItem = &UI_FeederAddItem; // NERVE - SMF
6815 uiInfo.uiDC.setBinding = &trap_Key_SetBinding;
6816 uiInfo.uiDC.getBindingBuf = &trap_Key_GetBindingBuf;
6817 uiInfo.uiDC.keynumToStringBuf = &trap_Key_KeynumToStringBuf;
6818 uiInfo.uiDC.executeText = &trap_Cmd_ExecuteText;
6819 uiInfo.uiDC.Error = &Com_Error;
6820 uiInfo.uiDC.Print = &Com_Printf;
6821 uiInfo.uiDC.DPrint = &Com_DPrintf;
6822 uiInfo.uiDC.Pause = &UI_Pause;
6823 uiInfo.uiDC.ownerDrawWidth = &UI_OwnerDrawWidth;
6824 uiInfo.uiDC.registerSound = &trap_S_RegisterSound;
6825 uiInfo.uiDC.startBackgroundTrack = &trap_S_StartBackgroundTrack;
6826 uiInfo.uiDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack;
6827 uiInfo.uiDC.playCinematic = &UI_PlayCinematic;
6828 uiInfo.uiDC.stopCinematic = &UI_StopCinematic;
6829 uiInfo.uiDC.drawCinematic = &UI_DrawCinematic;
6830 uiInfo.uiDC.runCinematicFrame = &UI_RunCinematicFrame;
6831
6832 Init_Display( &uiInfo.uiDC );
6833
6834 String_Init();
6835
6836 // load translation text
6837 UI_LoadTranslationStrings();
6838
6839 // uiInfo.uiDC.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor3" );
6840 uiInfo.uiDC.whiteShader = trap_R_RegisterShaderNoMip( "white" );
6841
6842 AssetCache();
6843
6844 uiInfo.teamCount = 0;
6845 uiInfo.characterCount = 0;
6846 uiInfo.aliasCount = 0;
6847
6848 // UI_ParseTeamInfo("teaminfo.txt");
6849 // UI_LoadTeams();
6850 // UI_ParseGameInfo("gameinfo.txt");
6851 // UI_LoadArenas();
6852
6853 menuSet = UI_Cvar_VariableString( "ui_menuFiles" );
6854 if ( menuSet == NULL || menuSet[0] == '\0' ) {
6855 #ifdef WOLF_SP_DEMO
6856 menuSet = "ui/demomenus.txt";
6857 #else
6858 menuSet = "ui/menus.txt";
6859 #endif
6860 }
6861
6862 #if 0
6863 if ( uiInfo.inGameLoad ) {
6864 UI_LoadMenus( "ui/ingame.txt", qtrue );
6865 } else {
6866 }
6867 #else
6868 UI_LoadMenus( menuSet, qtrue );
6869 UI_LoadMenus( "ui/ingame.txt", qfalse );
6870 #endif
6871
6872 Menus_CloseAll();
6873
6874 //#ifdef MISSIONPACK // NERVE - SMF - enabled for multiplayer
6875 trap_LAN_LoadCachedServers();
6876 UI_LoadBestScores( uiInfo.mapList[0].mapLoadName, uiInfo.gameTypes[ui_gameType.integer].gtEnum );
6877 //#endif // #ifdef MISSIONPACK
6878
6879 UI_BuildQ3Model_List();
6880 #ifdef MISSIONPACK
6881 UI_LoadBots();
6882 #endif // #ifdef MISSIONPACK
6883
6884 // sets defaults for ui temp cvars
6885 uiInfo.effectsColor = gamecodetoui[(int)trap_Cvar_VariableValue( "color" ) - 1];
6886 uiInfo.currentCrosshair = (int)trap_Cvar_VariableValue( "cg_drawCrosshair" );
6887 trap_Cvar_Set( "ui_mousePitch", ( trap_Cvar_VariableValue( "m_pitch" ) >= 0 ) ? "0" : "1" );
6888
6889 uiInfo.serverStatus.currentServerCinematic = -1;
6890 uiInfo.previewMovie = -1;
6891
6892 if ( trap_Cvar_VariableValue( "ui_WolfFirstRun" ) == 0 ) {
6893 trap_Cvar_Set( "s_volume", "0.8" );
6894 trap_Cvar_Set( "s_musicvolume", "0.8" );
6895 trap_Cvar_Set( "ui_WolfFirstRun", "1" );
6896 }
6897
6898 trap_Cvar_Register( NULL, "debug_protocol", "", 0 );
6899 }
6900
6901
6902 /*
6903 =================
6904 UI_KeyEvent
6905 =================
6906 */
_UI_KeyEvent(int key,qboolean down)6907 void _UI_KeyEvent( int key, qboolean down ) {
6908
6909 if ( Menu_Count() > 0 ) {
6910 menuDef_t *menu = Menu_GetFocused();
6911 if ( menu ) {
6912 if ( key == K_ESCAPE && down && !Menus_AnyFullScreenVisible() ) {
6913 Menus_CloseAll();
6914 } else {
6915 Menu_HandleKey( menu, key, down );
6916 }
6917 } else {
6918 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
6919 trap_Key_ClearStates();
6920 trap_Cvar_Set( "cl_paused", "0" );
6921 }
6922 }
6923
6924 //if ((s > 0) && (s != menu_null_sound)) {
6925 // trap_S_StartLocalSound( s, CHAN_LOCAL_SOUND );
6926 //}
6927 }
6928
6929 /*
6930 =================
6931 UI_MouseEvent
6932 =================
6933 */
_UI_MouseEvent(int dx,int dy)6934 void _UI_MouseEvent( int dx, int dy ) {
6935 // update mouse screen position
6936 uiInfo.uiDC.cursorx += dx;
6937 if ( uiInfo.uiDC.cursorx < 0 ) {
6938 uiInfo.uiDC.cursorx = 0;
6939 } else if ( uiInfo.uiDC.cursorx > SCREEN_WIDTH ) {
6940 uiInfo.uiDC.cursorx = SCREEN_WIDTH;
6941 }
6942
6943 uiInfo.uiDC.cursory += dy;
6944 if ( uiInfo.uiDC.cursory < 0 ) {
6945 uiInfo.uiDC.cursory = 0;
6946 } else if ( uiInfo.uiDC.cursory > SCREEN_HEIGHT ) {
6947 uiInfo.uiDC.cursory = SCREEN_HEIGHT;
6948 }
6949
6950 if ( Menu_Count() > 0 ) {
6951 //menuDef_t *menu = Menu_GetFocused();
6952 //Menu_HandleMouseMove(menu, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory);
6953 Display_MouseMove( NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory );
6954 }
6955
6956 }
6957
UI_LoadNonIngame(void)6958 void UI_LoadNonIngame( void ) {
6959 const char *menuSet = UI_Cvar_VariableString( "ui_menuFiles" );
6960 if ( menuSet == NULL || menuSet[0] == '\0' ) {
6961 #ifdef WOLF_SP_DEMO
6962 menuSet = "ui/demomenus.txt";
6963 #else
6964 menuSet = "ui/menus.txt";
6965 #endif
6966 }
6967 UI_LoadMenus( menuSet, qfalse );
6968 uiInfo.inGameLoad = qfalse;
6969 }
6970
6971
6972
6973 //----(SA) added
6974 /*
6975 ==============
6976 _UI_GetActiveMenu
6977 ==============
6978 */
_UI_GetActiveMenu(void)6979 uiMenuCommand_t _UI_GetActiveMenu( void ) {
6980 return menutype;
6981 }
6982
6983 //----(SA) end
6984
_UI_SetActiveMenu(uiMenuCommand_t menu)6985 void _UI_SetActiveMenu( uiMenuCommand_t menu ) {
6986 char buf[256];
6987
6988 // this should be the ONLY way the menu system is brought up
6989 // enusure minumum menu data is cached
6990 if ( Menu_Count() > 0 ) {
6991 vec3_t v;
6992 v[0] = v[1] = v[2] = 0;
6993
6994 if ( menu == UIMENU_BRIEFING && menutype == menu ) { // don't let briefing be set multiple times
6995 return;
6996 }
6997
6998 menutype = menu; //----(SA) added
6999
7000 switch ( menu ) {
7001 case UIMENU_NONE:
7002 trap_Key_SetCatcher( trap_Key_GetCatcher() & ~KEYCATCH_UI );
7003 trap_Key_ClearStates();
7004 trap_Cvar_Set( "cl_paused", "0" );
7005 Menus_CloseAll();
7006
7007 return;
7008 case UIMENU_MAIN:
7009 //trap_Cvar_Set( "sv_killserver", "1" );
7010 trap_Key_SetCatcher( KEYCATCH_UI );
7011 //trap_S_StartLocalSound( trap_S_RegisterSound("sound/misc/menu_background.wav", qfalse) , CHAN_LOCAL_SOUND );
7012 //trap_S_StartBackgroundTrack("sound/misc/menu_background.wav", NULL);
7013 if ( uiInfo.inGameLoad ) {
7014 UI_LoadNonIngame();
7015 }
7016 Menus_CloseAll();
7017 Menus_ActivateByName( "main" );
7018 trap_Cvar_VariableStringBuffer( "com_errorMessage", buf, sizeof( buf ) );
7019 if ( strlen( buf ) ) {
7020 #ifdef MISSIONPACK
7021 if ( !ui_singlePlayerActive.integer ) {
7022 #endif // #ifdef MISSIONPACK
7023 Menus_ActivateByName( "error_popmenu" );
7024 #ifdef MISSIONPACK
7025 } else {
7026 trap_Cvar_Set( "com_errorMessage", "" );
7027 }
7028 #endif // #ifdef MISSIONPACK
7029 }
7030 // ensure sound is there for the menu
7031 trap_S_FadeAllSound( 1.0f, 1000 ); // make sure sound fades up
7032
7033 // ensure savegames are loadable
7034 trap_Cvar_Set( "g_reloading", "0" );
7035
7036 return;
7037
7038 case UIMENU_TEAM:
7039 trap_Key_SetCatcher( KEYCATCH_UI );
7040 Menus_ActivateByName( "team" );
7041 return;
7042
7043 //----(SA) added
7044 case UIMENU_ENDGAME:
7045 // ensure sound is there for the menu
7046 trap_S_FadeAllSound( 1.0f, 1000 );
7047 // ensure savegames are loadable
7048 trap_Cvar_Set( "g_reloading", "0" );
7049
7050 trap_Key_SetCatcher( KEYCATCH_UI );
7051 Menus_ActivateByName( "credit" );
7052 return;
7053 //----(SA) end
7054
7055 case UIMENU_NEED_CD:
7056 trap_Key_SetCatcher( KEYCATCH_UI );
7057 Menus_ActivateByName( "needcd" );
7058 // UI_ConfirmMenu( "Insert the CD", NULL, NeedCDAction );
7059 return;
7060
7061 case UIMENU_BAD_CD_KEY:
7062 trap_Key_SetCatcher( KEYCATCH_UI );
7063 Menus_ActivateByName( "badcd" );
7064 // UI_ConfirmMenu( "Bad CD Key", NULL, NeedCDKeyAction );
7065 return;
7066
7067 case UIMENU_POSTGAME:
7068 //trap_Cvar_Set( "sv_killserver", "1" );
7069 trap_Key_SetCatcher( KEYCATCH_UI );
7070 if ( uiInfo.inGameLoad ) {
7071 UI_LoadNonIngame();
7072 }
7073 Menus_CloseAll();
7074 Menus_ActivateByName( "endofgame" );
7075 //UI_ConfirmMenu( "Bad CD Key", NULL, NeedCDKeyAction );
7076 return;
7077
7078 case UIMENU_INGAME:
7079 if ( trap_Cvar_VariableValue( "savegame_loading" ) ) {
7080 return;
7081 }
7082 trap_Cvar_Set( "cl_paused", "1" );
7083 trap_Key_SetCatcher( KEYCATCH_UI );
7084 UI_BuildPlayerList();
7085 Menus_CloseAll();
7086 Menus_ActivateByName( "ingame" );
7087 return;
7088
7089 case UIMENU_PREGAME:
7090 trap_Cvar_Set( "cl_paused", "1" );
7091 trap_Key_SetCatcher( KEYCATCH_UI );
7092 Menus_CloseAll();
7093 Menus_ActivateByName( "pregame" );
7094 return;
7095
7096 case UIMENU_NOTEBOOK:
7097 trap_Cvar_Set( "cl_paused", "1" );
7098 trap_Key_SetCatcher( KEYCATCH_UI );
7099 Menus_CloseAll();
7100 Menus_ActivateByName( "notebook" );
7101 return;
7102
7103 case UIMENU_BOOK1:
7104 case UIMENU_BOOK2:
7105 case UIMENU_BOOK3:
7106 // trap_Cvar_Set( "cl_paused", "1" );
7107 trap_Key_SetCatcher( KEYCATCH_UI );
7108 Menus_CloseAll();
7109 Menus_ActivateByName( va( "hbook%d", ( menu - UIMENU_BOOK1 ) + 1 ) );
7110 return;
7111
7112 case UIMENU_CLIPBOARD:
7113 trap_Cvar_Set( "cl_paused", "1" );
7114 trap_Key_SetCatcher( KEYCATCH_UI );
7115 Menus_CloseAll();
7116 Menus_ActivateByName( "clipboard" );
7117 return;
7118
7119 // case UIMENU_HELP:
7120 // trap_Cvar_Set( "cl_paused", "1" );
7121 // trap_Key_SetCatcher( KEYCATCH_UI );
7122 // Menus_CloseAll();
7123 // Menus_ActivateByName("help");
7124 // return;
7125
7126 case UIMENU_BRIEFING:
7127 Menus_CloseAll();
7128 Menus_ActivateByName( "briefing" );
7129 return;
7130
7131 // NERVE - SMF
7132 case UIMENU_WM_PICKTEAM:
7133 trap_Cvar_Set( "cl_paused", "1" );
7134 trap_Key_SetCatcher( KEYCATCH_UI );
7135 Menus_CloseAll();
7136 Menus_OpenByName( "wm_pickteam" );
7137 return;
7138
7139 case UIMENU_WM_PICKPLAYER:
7140 trap_Cvar_Set( "cl_paused", "1" );
7141 trap_Key_SetCatcher( KEYCATCH_UI );
7142 Menus_CloseAll();
7143 Menus_OpenByName( "wm_pickplayer" );
7144 return;
7145
7146 case UIMENU_WM_QUICKMESSAGE:
7147 trap_Key_SetCatcher( KEYCATCH_UI );
7148 Menus_CloseAll();
7149 Menus_OpenByName( "wm_quickmessage" );
7150 return;
7151
7152 case UIMENU_WM_LIMBO:
7153 trap_Key_SetCatcher( KEYCATCH_UI );
7154 Menus_CloseAll();
7155 Menus_OpenByName( "wm_limboView" );
7156 Menus_OpenByName( "wm_limboChat" );
7157 Menus_OpenByName( "wm_limboModel" );
7158 Menus_OpenByName( "wm_limboOptions" );
7159 Menus_OpenByName( "wm_limboButtonBar" );
7160 return;
7161 // -NERVE - SMF
7162 default:
7163 break;
7164 }
7165 }
7166 }
7167
_UI_IsFullscreen(void)7168 qboolean _UI_IsFullscreen( void ) {
7169 return Menus_AnyFullScreenVisible();
7170 }
7171
7172
7173
7174 static connstate_t lastConnState;
7175 static char lastLoadingText[MAX_INFO_VALUE];
7176
UI_ReadableSize(char * buf,int bufsize,int value)7177 static void UI_ReadableSize( char *buf, int bufsize, int value ) {
7178 if ( value > 1024 * 1024 * 1024 ) { // gigs
7179 Com_sprintf( buf, bufsize, "%d", value / ( 1024 * 1024 * 1024 ) );
7180 Com_sprintf( buf + strlen( buf ), bufsize - strlen( buf ), ".%02d GB",
7181 ( value % ( 1024 * 1024 * 1024 ) ) * 100 / ( 1024 * 1024 * 1024 ) );
7182 } else if ( value > 1024 * 1024 ) { // megs
7183 Com_sprintf( buf, bufsize, "%d", value / ( 1024 * 1024 ) );
7184 Com_sprintf( buf + strlen( buf ), bufsize - strlen( buf ), ".%02d MB",
7185 ( value % ( 1024 * 1024 ) ) * 100 / ( 1024 * 1024 ) );
7186 } else if ( value > 1024 ) { // kilos
7187 Com_sprintf( buf, bufsize, "%d KB", value / 1024 );
7188 } else { // bytes
7189 Com_sprintf( buf, bufsize, "%d bytes", value );
7190 }
7191 }
7192
7193 // Assumes time is in msec
UI_PrintTime(char * buf,int bufsize,int time)7194 static void UI_PrintTime( char *buf, int bufsize, int time ) {
7195 time /= 1000; // change to seconds
7196
7197 if ( time > 3600 ) { // in the hours range
7198 Com_sprintf( buf, bufsize, "%d hr %d min", time / 3600, ( time % 3600 ) / 60 );
7199 } else if ( time > 60 ) { // mins
7200 Com_sprintf( buf, bufsize, "%d min %d sec", time / 60, time % 60 );
7201 } else { // secs
7202 Com_sprintf( buf, bufsize, "%d sec", time );
7203 }
7204 }
7205
Text_PaintCenter(float x,float y,int font,float scale,vec4_t color,const char * text,float adjust)7206 void Text_PaintCenter( float x, float y, int font, float scale, vec4_t color, const char *text, float adjust ) {
7207 int len = Text_Width( text, font, scale, 0 );
7208 Text_Paint( x - len / 2, y, font, scale, color, text, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE );
7209 }
7210
7211
UI_DisplayDownloadInfo(const char * downloadName,float centerPoint,float yStart,int font,float scale)7212 static void UI_DisplayDownloadInfo( const char *downloadName, float centerPoint, float yStart, int font, float scale ) {
7213 static char dlText[] = "Downloading:";
7214 static char etaText[] = "Estimated time left:";
7215 static char xferText[] = "Transfer rate:";
7216
7217 int downloadSize, downloadCount, downloadTime;
7218 char dlSizeBuf[64], totalSizeBuf[64], xferRateBuf[64], dlTimeBuf[64];
7219 int xferRate;
7220 int leftWidth;
7221 const char *s;
7222
7223 downloadSize = trap_Cvar_VariableValue( "cl_downloadSize" );
7224 downloadCount = trap_Cvar_VariableValue( "cl_downloadCount" );
7225 downloadTime = trap_Cvar_VariableValue( "cl_downloadTime" );
7226
7227 leftWidth = 320;
7228
7229 UI_SetColor( colorWhite );
7230 Text_PaintCenter( centerPoint, yStart + 112, font, scale, colorWhite, dlText, 0 );
7231 Text_PaintCenter( centerPoint, yStart + 144, font, scale, colorWhite, etaText, 0 );
7232 Text_PaintCenter( centerPoint, yStart + 208, font, scale, colorWhite, xferText, 0 );
7233
7234 if ( downloadSize > 0 ) {
7235 s = va( "%s (%d%%)", downloadName,
7236 (int)( (float)downloadCount * 100.0f / downloadSize ) );
7237 } else {
7238 s = downloadName;
7239 }
7240
7241 Text_Paint( centerPoint, yStart + 244, font, 0.6f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE );
7242
7243 UI_ReadableSize( dlSizeBuf, sizeof dlSizeBuf, downloadCount );
7244 UI_ReadableSize( totalSizeBuf, sizeof totalSizeBuf, downloadSize );
7245
7246 if ( downloadCount < 4096 || !downloadTime ) {
7247 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, "estimating", 0 );
7248 Text_PaintCenter( leftWidth, 192, font, 0.6f, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 );
7249 } else {
7250 if ( ( uiInfo.uiDC.realTime - downloadTime ) / 1000 ) {
7251 xferRate = downloadCount / ( ( uiInfo.uiDC.realTime - downloadTime ) / 1000 );
7252 } else {
7253 xferRate = 0;
7254 }
7255 UI_ReadableSize( xferRateBuf, sizeof xferRateBuf, xferRate );
7256
7257 // Extrapolate estimated completion time
7258 if ( downloadSize && xferRate ) {
7259 int n = downloadSize / xferRate; // estimated time for entire d/l in secs
7260
7261 // We do it in K (/1024) because we'd overflow around 4MB
7262 UI_PrintTime( dlTimeBuf, sizeof dlTimeBuf,
7263 ( n - ( ( ( downloadCount / 1024 ) * n ) / ( downloadSize / 1024 ) ) ) * 1000 );
7264
7265 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, dlTimeBuf, 0 );
7266 Text_PaintCenter( leftWidth, 192, font, 0.6f, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 );
7267 } else {
7268 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, "estimating", 0 );
7269 if ( downloadSize ) {
7270 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, va( "(%s of %s copied)", dlSizeBuf, totalSizeBuf ), 0 );
7271 } else {
7272 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, va( "(%s copied)", dlSizeBuf ), 0 );
7273 }
7274 }
7275
7276 if ( xferRate ) {
7277 Text_PaintCenter( leftWidth, 160, font, 0.6f, colorWhite, va( "%s/Sec", xferRateBuf ), 0 );
7278 }
7279 }
7280 }
7281
7282 /*
7283 ========================
7284 UI_DrawConnectScreen
7285
7286 This will also be overlaid on the cgame info screen during loading
7287 to prevent it from blinking away too rapidly on local or lan games.
7288 ========================
7289 */
UI_DrawConnectScreen(qboolean overlay)7290 void UI_DrawConnectScreen( qboolean overlay ) {
7291 char *s;
7292 uiClientState_t cstate;
7293 char info[MAX_INFO_VALUE];
7294 char text[256];
7295 float centerPoint, yStart, scale;
7296
7297 menuDef_t *menu = Menus_FindByName( "Connect" );
7298
7299
7300 if ( !overlay && menu ) {
7301 Menu_Paint( menu, qtrue );
7302 }
7303
7304 if ( !overlay ) {
7305 centerPoint = 320;
7306 yStart = 130;
7307 scale = 0.5f;
7308 } else {
7309 return;
7310 }
7311
7312 // see what information we should display
7313 trap_GetClientState( &cstate );
7314
7315 info[0] = '\0';
7316
7317 if ( trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ) ) {
7318 Text_PaintCenter(centerPoint, yStart + 48, UI_FONT_DEFAULT, scale, colorWhite, "Starting up...", ITEM_TEXTSTYLE_SHADOWEDMORE);
7319 }
7320
7321 if ( !Q_stricmp( cstate.servername,"localhost" ) ) {
7322 // Text_PaintCenter(centerPoint, yStart + 48, UI_FONT_DEFAULT, scale, colorWhite, va("Get Psyched!"), ITEM_TEXTSTYLE_SHADOWEDMORE);
7323 } else {
7324 Com_sprintf(text, sizeof(text), "Connecting to %s", cstate.servername);
7325 Text_PaintCenter( centerPoint, yStart + 48, UI_FONT_DEFAULT, scale, colorWhite,text, ITEM_TEXTSTYLE_SHADOWEDMORE );
7326 }
7327
7328 //UI_DrawProportionalString( 320, 96, "Press Esc to abort", UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, menu_text_color );
7329
7330 // display global MOTD at bottom
7331 Text_PaintCenter( centerPoint, 600, UI_FONT_DEFAULT, scale, colorWhite, Info_ValueForKey( cstate.updateInfoString, "motd" ), 0 );
7332 // print any server info (server full, bad version, etc)
7333 if ( cstate.connState < CA_CONNECTED ) {
7334 Text_PaintCenter( centerPoint, yStart + 176, UI_FONT_DEFAULT, scale, colorWhite, cstate.messageString, 0 );
7335 }
7336
7337 if ( lastConnState > cstate.connState ) {
7338 lastLoadingText[0] = '\0';
7339 }
7340 lastConnState = cstate.connState;
7341
7342 switch ( cstate.connState ) {
7343 case CA_CONNECTING:
7344 s = va( "Awaiting connection...%i", cstate.connectPacketCount );
7345 break;
7346 case CA_CHALLENGING:
7347 s = va( "Awaiting challenge...%i", cstate.connectPacketCount );
7348 break;
7349 case CA_CONNECTED: {
7350 char downloadName[MAX_INFO_VALUE];
7351
7352 trap_Cvar_VariableStringBuffer( "cl_downloadName", downloadName, sizeof( downloadName ) );
7353 if ( *downloadName ) {
7354 UI_DisplayDownloadInfo( downloadName, centerPoint, yStart, UI_FONT_DEFAULT, scale );
7355 return;
7356 }
7357 }
7358 s = "Awaiting gamestate...";
7359 break;
7360 case CA_LOADING:
7361 return;
7362 case CA_PRIMED:
7363 return;
7364 default:
7365 return;
7366 }
7367
7368
7369 if ( Q_stricmp( cstate.servername,"localhost" ) ) {
7370 Text_PaintCenter( centerPoint, yStart + 80, UI_FONT_DEFAULT, scale, colorWhite, s, 0 );
7371 }
7372
7373 // password required / connection rejected information goes here
7374 }
7375
7376
7377 /*
7378 ================
7379 cvars
7380 ================
7381 */
7382
7383 typedef struct {
7384 vmCvar_t *vmCvar;
7385 char *cvarName;
7386 char *defaultString;
7387 int cvarFlags;
7388 } cvarTable_t;
7389
7390 vmCvar_t ui_ffa_fraglimit;
7391 vmCvar_t ui_ffa_timelimit;
7392
7393 vmCvar_t ui_tourney_fraglimit;
7394 vmCvar_t ui_tourney_timelimit;
7395
7396 vmCvar_t ui_team_fraglimit;
7397 vmCvar_t ui_team_timelimit;
7398 vmCvar_t ui_team_friendly;
7399
7400 vmCvar_t ui_ctf_capturelimit;
7401 vmCvar_t ui_ctf_timelimit;
7402 vmCvar_t ui_ctf_friendly;
7403
7404 vmCvar_t ui_arenasFile;
7405 vmCvar_t ui_botsFile;
7406 vmCvar_t ui_spScores1;
7407 vmCvar_t ui_spScores2;
7408 vmCvar_t ui_spScores3;
7409 vmCvar_t ui_spScores4;
7410 vmCvar_t ui_spScores5;
7411 vmCvar_t ui_spAwards;
7412 vmCvar_t ui_spVideos;
7413 vmCvar_t ui_spSkill;
7414
7415 vmCvar_t ui_spSelection;
7416 vmCvar_t ui_master;
7417
7418 vmCvar_t ui_brassTime;
7419 vmCvar_t ui_drawCrosshair;
7420 vmCvar_t ui_drawCrosshairNames;
7421 vmCvar_t ui_drawCrosshairPickups; //----(SA) added
7422 vmCvar_t ui_useSuggestedWeapons; //----(SA) added
7423 vmCvar_t ui_marks;
7424 // JOSEPH 12-3-99
7425 vmCvar_t ui_autoactivate;
7426 vmCvar_t ui_emptyswitch; //----(SA) added
7427 // END JOSEPH
7428
7429 vmCvar_t ui_server1;
7430 vmCvar_t ui_server2;
7431 vmCvar_t ui_server3;
7432 vmCvar_t ui_server4;
7433 vmCvar_t ui_server5;
7434 vmCvar_t ui_server6;
7435 vmCvar_t ui_server7;
7436 vmCvar_t ui_server8;
7437 vmCvar_t ui_server9;
7438 vmCvar_t ui_server10;
7439 vmCvar_t ui_server11;
7440 vmCvar_t ui_server12;
7441 vmCvar_t ui_server13;
7442 vmCvar_t ui_server14;
7443 vmCvar_t ui_server15;
7444 vmCvar_t ui_server16;
7445
7446 vmCvar_t ui_cdkeychecked;
7447 vmCvar_t ui_smallFont;
7448 vmCvar_t ui_bigFont;
7449
7450 vmCvar_t ui_selectedPlayer;
7451 vmCvar_t ui_selectedPlayerName;
7452 vmCvar_t ui_netSource;
7453 vmCvar_t ui_menuFiles;
7454 vmCvar_t ui_gameType;
7455 vmCvar_t ui_netGameType;
7456 vmCvar_t ui_actualNetGameType;
7457 vmCvar_t ui_joinGameType;
7458 vmCvar_t ui_dedicated;
7459
7460 vmCvar_t ui_notebookCurrentPage; //----(SA) added
7461 vmCvar_t ui_clipboardName; // the name of the group for the current clipboard item //----(SA) added
7462 vmCvar_t ui_hudAlpha;
7463 vmCvar_t ui_hunkUsed; //----(SA) added
7464 vmCvar_t ui_cameraMode; //----(SA) added
7465 vmCvar_t ui_savegameListAutosave; //----(SA) added
7466 vmCvar_t ui_savegameName;
7467
7468 // NERVE - SMF - cvars for multiplayer
7469 vmCvar_t ui_serverFilterType;
7470 vmCvar_t ui_currentNetMap;
7471 vmCvar_t ui_currentMap;
7472 vmCvar_t ui_mapIndex;
7473
7474 vmCvar_t ui_browserMaster;
7475 vmCvar_t ui_browserGameType;
7476 vmCvar_t ui_browserShowFull;
7477 vmCvar_t ui_browserShowEmpty;
7478
7479 vmCvar_t ui_serverStatusTimeOut;
7480
7481 vmCvar_t ui_Q3Model;
7482 vmCvar_t ui_headModel;
7483 vmCvar_t ui_model;
7484
7485 vmCvar_t ui_limboOptions;
7486
7487 vmCvar_t ui_cmd;
7488
7489 vmCvar_t ui_prevTeam;
7490 vmCvar_t ui_prevClass;
7491 vmCvar_t ui_prevWeapon;
7492
7493 vmCvar_t ui_limboMode;
7494 // -NERVE - SMF
7495
7496 cvarTable_t cvarTable[] = {
7497 { &ui_ffa_fraglimit, "ui_ffa_fraglimit", "20", CVAR_ARCHIVE },
7498 { &ui_ffa_timelimit, "ui_ffa_timelimit", "0", CVAR_ARCHIVE },
7499
7500 { &ui_tourney_fraglimit, "ui_tourney_fraglimit", "0", CVAR_ARCHIVE },
7501 { &ui_tourney_timelimit, "ui_tourney_timelimit", "15", CVAR_ARCHIVE },
7502
7503 { &ui_team_fraglimit, "ui_team_fraglimit", "0", CVAR_ARCHIVE },
7504 { &ui_team_timelimit, "ui_team_timelimit", "20", CVAR_ARCHIVE },
7505 { &ui_team_friendly, "ui_team_friendly", "1", CVAR_ARCHIVE },
7506
7507 { &ui_ctf_capturelimit, "ui_ctf_capturelimit", "8", CVAR_ARCHIVE },
7508 { &ui_ctf_timelimit, "ui_ctf_timelimit", "30", CVAR_ARCHIVE },
7509 { &ui_ctf_friendly, "ui_ctf_friendly", "0", CVAR_ARCHIVE },
7510
7511 { &ui_arenasFile, "g_arenasFile", "", CVAR_INIT | CVAR_ROM },
7512 { &ui_botsFile, "g_botsFile", "", CVAR_INIT | CVAR_ROM },
7513 { &ui_spScores1, "g_spScores1", "", CVAR_ARCHIVE },
7514 { &ui_spScores2, "g_spScores2", "", CVAR_ARCHIVE },
7515 { &ui_spScores3, "g_spScores3", "", CVAR_ARCHIVE },
7516 { &ui_spScores4, "g_spScores4", "", CVAR_ARCHIVE },
7517 { &ui_spScores5, "g_spScores5", "", CVAR_ARCHIVE },
7518 { &ui_spAwards, "g_spAwards", "", CVAR_ARCHIVE },
7519 { &ui_spVideos, "g_spVideos", "", CVAR_ARCHIVE },
7520 { &ui_spSkill, "g_spSkill", "2", CVAR_ARCHIVE | CVAR_LATCH },
7521
7522 { &ui_spSelection, "ui_spSelection", "", CVAR_ROM },
7523 { &ui_master, "ui_master", "0", CVAR_ARCHIVE },
7524
7525 { &ui_browserMaster, "ui_browserMaster", "0", CVAR_ARCHIVE },
7526 { &ui_browserGameType, "ui_browserGameType", "0", CVAR_ARCHIVE },
7527 { &ui_browserShowFull, "ui_browserShowFull", "1", CVAR_ARCHIVE },
7528 { &ui_browserShowEmpty, "ui_browserShowEmpty", "1", CVAR_ARCHIVE },
7529
7530 { &ui_brassTime, "cg_brassTime", "1250", CVAR_ARCHIVE },
7531 { &ui_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },
7532 { &ui_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
7533 { &ui_drawCrosshairPickups, "cg_drawCrosshairPickups", "1", CVAR_ARCHIVE }, //----(SA) added
7534 { &ui_marks, "cg_marktime", "20000", CVAR_ARCHIVE },
7535 { &ui_autoactivate, "cg_autoactivate", "1", CVAR_ARCHIVE },
7536 { &ui_useSuggestedWeapons, "cg_useSuggestedWeapons", "1", CVAR_ARCHIVE }, //----(SA) added
7537 { &ui_emptyswitch, "cg_emptyswitch", "0", CVAR_ARCHIVE }, //----(SA) added
7538
7539 { &ui_fixedAspect, "cg_fixedAspect", "0", CVAR_ARCHIVE | CVAR_LATCH },
7540 { &ui_fixedAspectFOV, "cg_fixedAspectFOV", "1", CVAR_ARCHIVE },
7541
7542 { &ui_server1, "server1", "", CVAR_ARCHIVE },
7543 { &ui_server2, "server2", "", CVAR_ARCHIVE },
7544 { &ui_server3, "server3", "", CVAR_ARCHIVE },
7545 { &ui_server4, "server4", "", CVAR_ARCHIVE },
7546 { &ui_server5, "server5", "", CVAR_ARCHIVE },
7547 { &ui_server6, "server6", "", CVAR_ARCHIVE },
7548 { &ui_server7, "server7", "", CVAR_ARCHIVE },
7549 { &ui_server8, "server8", "", CVAR_ARCHIVE },
7550 { &ui_server9, "server9", "", CVAR_ARCHIVE },
7551 { &ui_server10, "server10", "", CVAR_ARCHIVE },
7552 { &ui_server11, "server11", "", CVAR_ARCHIVE },
7553 { &ui_server12, "server12", "", CVAR_ARCHIVE },
7554 { &ui_server13, "server13", "", CVAR_ARCHIVE },
7555 { &ui_server14, "server14", "", CVAR_ARCHIVE },
7556 { &ui_server15, "server15", "", CVAR_ARCHIVE },
7557 { &ui_server16, "server16", "", CVAR_ARCHIVE },
7558 { &ui_dedicated, "ui_dedicated", "0", CVAR_ARCHIVE },
7559 { &ui_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE},
7560 { &ui_bigFont, "ui_bigFont", "0.4", CVAR_ARCHIVE},
7561 { &ui_cdkeychecked, "ui_cdkeychecked", "0", CVAR_ROM },
7562 { &ui_selectedPlayer, "cg_selectedPlayer", "0", CVAR_ARCHIVE},
7563 { &ui_selectedPlayerName, "cg_selectedPlayerName", "", CVAR_ARCHIVE},
7564 { &ui_netSource, "ui_netSource", "1", CVAR_ARCHIVE },
7565 #ifdef WOLF_SP_DEMO
7566 { &ui_menuFiles, "ui_menuFiles", "ui/demomenus.txt", CVAR_ARCHIVE },
7567 #else
7568 { &ui_menuFiles, "ui_menuFiles", "ui/menus.txt", CVAR_ARCHIVE },
7569 #endif
7570 { &ui_gameType, "ui_gametype", "3", CVAR_ARCHIVE },
7571 { &ui_joinGameType, "ui_joinGametype", "0", CVAR_ARCHIVE },
7572 { &ui_netGameType, "ui_netGametype", "3", CVAR_ARCHIVE },
7573 { &ui_actualNetGameType, "ui_actualNetGametype", "0", CVAR_ARCHIVE },
7574 { &ui_notebookCurrentPage, "ui_notebookCurrentPage", "1", CVAR_ROM},
7575 { &ui_clipboardName, "cg_clipboardName", "", CVAR_ROM },
7576
7577 // NERVE - SMF - multiplayer cvars
7578 { &ui_mapIndex, "ui_mapIndex", "0", CVAR_ARCHIVE },
7579 { &ui_currentMap, "ui_currentMap", "0", CVAR_ARCHIVE },
7580 { &ui_currentNetMap, "ui_currentNetMap", "0", CVAR_ARCHIVE },
7581
7582 { &ui_initialized, "ui_initialized", "0", CVAR_TEMP },
7583 { &ui_debug, "ui_debug", "0", CVAR_TEMP },
7584 { &ui_WolfFirstRun, "ui_WolfFirstRun", "0", CVAR_ARCHIVE},
7585
7586 { &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
7587
7588 // { &ui_Q3Model, "ui_Q3Model", "1", 0 },
7589 // { &ui_headModel, "headModel", "", 0 },
7590
7591 { &ui_limboOptions, "ui_limboOptions", "0", 0 },
7592 { &ui_cmd, "ui_cmd", "", 0 },
7593
7594 { &ui_prevTeam, "ui_prevTeam", "-1", 0 },
7595 { &ui_prevClass, "ui_prevClass", "-1", 0 },
7596 { &ui_prevWeapon, "ui_prevWeapon", "-1", 0 },
7597
7598 { &ui_limboMode, "ui_limboMode", "0", 0 },
7599 // -NERVE - SMF
7600
7601 { &ui_hudAlpha, "cg_hudAlpha", "0.8", CVAR_ARCHIVE },
7602 { &ui_hunkUsed, "com_hunkused", "0", 0 }, //----(SA) added
7603 { &ui_cameraMode, "com_cameraMode", "0", 0}, //----(SA) added
7604
7605 { &ui_savegameName, "ui_savegameName", "", CVAR_ROM},
7606
7607 { NULL, "g_localTeamPref", "", 0 },
7608 };
7609
7610 static int cvarTableSize = ARRAY_LEN( cvarTable );
7611
7612
7613 /*
7614 =================
7615 UI_RegisterCvars
7616 =================
7617 */
UI_RegisterCvars(void)7618 void UI_RegisterCvars( void ) {
7619 int i;
7620 cvarTable_t *cv;
7621
7622 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
7623 trap_Cvar_Register( cv->vmCvar, cv->cvarName, cv->defaultString, cv->cvarFlags );
7624 }
7625 }
7626
7627 /*
7628 =================
7629 UI_UpdateCvars
7630 =================
7631 */
UI_UpdateCvars(void)7632 void UI_UpdateCvars( void ) {
7633 int i;
7634 cvarTable_t *cv;
7635
7636 for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
7637 if ( !cv->vmCvar ) {
7638 continue;
7639 }
7640
7641 trap_Cvar_Update( cv->vmCvar );
7642 }
7643 }
7644
7645 // NERVE - SMF
7646 /*
7647 =================
7648 ArenaServers_StopRefresh
7649 =================
7650 */
UI_StopServerRefresh(void)7651 static void UI_StopServerRefresh( void ) {
7652 int count;
7653
7654 if ( !uiInfo.serverStatus.refreshActive ) {
7655 // not currently refreshing
7656 return;
7657 }
7658 uiInfo.serverStatus.refreshActive = qfalse;
7659 Com_Printf( "%d servers listed in browser with %d players.\n",
7660 uiInfo.serverStatus.numDisplayServers,
7661 uiInfo.serverStatus.numPlayersOnServers );
7662 count = trap_LAN_GetServerCount(UI_SourceForLAN());
7663 if ( count - uiInfo.serverStatus.numDisplayServers > 0 ) {
7664 Com_Printf( "%d servers not listed due to packet loss or pings higher than %d\n",
7665 count - uiInfo.serverStatus.numDisplayServers,
7666 (int) trap_Cvar_VariableValue( "cl_maxPing" ) );
7667 }
7668
7669 }
7670
7671 /*
7672 =================
7673 UI_DoServerRefresh
7674 =================
7675 */
UI_DoServerRefresh(void)7676 static void UI_DoServerRefresh( void ) {
7677 qboolean wait = qfalse;
7678
7679 if ( !uiInfo.serverStatus.refreshActive ) {
7680 return;
7681 }
7682 if (ui_netSource.integer != UIAS_FAVORITES) {
7683 if (ui_netSource.integer == UIAS_LOCAL) {
7684 if (!trap_LAN_GetServerCount(AS_LOCAL)) {
7685 wait = qtrue;
7686 }
7687 } else {
7688 if (trap_LAN_GetServerCount(AS_GLOBAL) < 0) {
7689 wait = qtrue;
7690 }
7691 }
7692 }
7693
7694 if ( uiInfo.uiDC.realTime < uiInfo.serverStatus.refreshtime ) {
7695 if ( wait ) {
7696 return;
7697 }
7698 }
7699
7700 // if still trying to retrieve pings
7701 if (trap_LAN_UpdateVisiblePings(UI_SourceForLAN())) {
7702 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 1000;
7703 } else if ( !wait ) {
7704 // get the last servers in the list
7705 UI_BuildServerDisplayList( 2 );
7706 // stop the refresh
7707 UI_StopServerRefresh();
7708 } else if ( ui_netSource.integer == UIAS_LOCAL ) {
7709 // no local servers found, check again
7710 trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" );
7711 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000;
7712 }
7713 //
7714 UI_BuildServerDisplayList( qfalse );
7715 }
7716
7717 /*
7718 =================
7719 UI_StartServerRefresh
7720 =================
7721 */
UI_StartServerRefresh(qboolean full,qboolean force)7722 static void UI_StartServerRefresh( qboolean full, qboolean force ) {
7723 char *ptr;
7724 int lanSource;
7725 qtime_t q;
7726
7727 // This function is called with force=qfalse when server browser menu opens or net source changes.
7728 // Automatically update local and favorite servers.
7729 // Only auto update master server list if there is no server info cache.
7730 if ( !force && ( ui_netSource.integer >= UIAS_GLOBAL0 && ui_netSource.integer <= UIAS_GLOBAL5 ) ) {
7731 if ( trap_LAN_GetServerCount( UI_SourceForLAN() ) > 0 ) {
7732 return; // have cached list
7733 }
7734 }
7735
7736 trap_RealTime( &q );
7737 trap_Cvar_Set( va( "ui_lastServerRefresh_%i", ui_netSource.integer ), va( "%s-%i, %i at %02i:%02i", MonthAbbrev[q.tm_mon],q.tm_mday, 1900 + q.tm_year,q.tm_hour,q.tm_min ) );
7738
7739 if ( !full ) {
7740 UI_UpdatePendingPings();
7741 return;
7742 }
7743
7744 uiInfo.serverStatus.refreshActive = qtrue;
7745 uiInfo.serverStatus.nextDisplayRefresh = uiInfo.uiDC.realTime + 1000;
7746 // clear number of displayed servers
7747 uiInfo.serverStatus.numDisplayServers = 0;
7748 uiInfo.serverStatus.numPlayersOnServers = 0;
7749
7750 lanSource = UI_SourceForLAN();
7751 // mark all servers as visible so we store ping updates for them
7752 trap_LAN_MarkServerVisible(lanSource, -1, qtrue);
7753 // reset all the pings
7754 trap_LAN_ResetPings(lanSource);
7755 //
7756 if ( ui_netSource.integer == UIAS_LOCAL ) {
7757 trap_Cmd_ExecuteText( EXEC_NOW, "localservers\n" );
7758 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000;
7759 return;
7760 }
7761
7762 uiInfo.serverStatus.refreshtime = uiInfo.uiDC.realTime + 5000;
7763 if( ui_netSource.integer >= UIAS_GLOBAL0 && ui_netSource.integer <= UIAS_GLOBAL5 ) {
7764
7765 ptr = UI_Cvar_VariableString( "debug_protocol" );
7766 if ( strlen( ptr ) ) {
7767 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %s full empty\n", ui_netSource.integer - UIAS_GLOBAL0, ptr ) );
7768 } else {
7769 trap_Cmd_ExecuteText( EXEC_NOW, va( "globalservers %d %d full empty\n", ui_netSource.integer - UIAS_GLOBAL0, (int)trap_Cvar_VariableValue( "protocol" ) ) );
7770 }
7771 }
7772 }
7773 // -NERVE - SMF
7774