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, &param ) &&  String_Parse( args, &param2 ) ) {
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