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