1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 //
23 // cg_main.c -- initialization and primary entry point for cgame
24 #include "cg_local.h"
25 
26 #ifdef MISSIONPACK
27 #include "../ui/ui_shared.h"
28 // display context for new ui stuff
29 displayContextDef_t cgDC;
30 #endif
31 
32 int forceModelModificationCount = -1;
33 
34 void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum );
35 void CG_Shutdown( void );
36 
37 
38 /*
39 ================
40 vmMain
41 
42 This is the only way control passes into the module.
43 This must be the very first function compiled into the .q3vm file
44 ================
45 */
vmMain(int command,int arg0,int arg1,int arg2,int arg3,int arg4,int arg5,int arg6,int arg7,int arg8,int arg9,int arg10,int arg11)46 intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11  ) {
47 
48 	switch ( command ) {
49 	case CG_INIT:
50 		CG_Init( arg0, arg1, arg2 );
51 		return 0;
52 	case CG_SHUTDOWN:
53 		CG_Shutdown();
54 		return 0;
55 	case CG_CONSOLE_COMMAND:
56 		return CG_ConsoleCommand();
57 	case CG_DRAW_ACTIVE_FRAME:
58 		CG_DrawActiveFrame( arg0, arg1, arg2 );
59 		return 0;
60 	case CG_CROSSHAIR_PLAYER:
61 		return CG_CrosshairPlayer();
62 	case CG_LAST_ATTACKER:
63 		return CG_LastAttacker();
64 	case CG_KEY_EVENT:
65 		CG_KeyEvent(arg0, arg1);
66 		return 0;
67 	case CG_MOUSE_EVENT:
68 #ifdef MISSIONPACK
69 		cgDC.cursorx = cgs.cursorX;
70 		cgDC.cursory = cgs.cursorY;
71 #endif
72 		CG_MouseEvent(arg0, arg1);
73 		return 0;
74 	case CG_EVENT_HANDLING:
75 		CG_EventHandling(arg0);
76 		return 0;
77 	default:
78 		CG_Error( "vmMain: unknown command %i", command );
79 		break;
80 	}
81 	return -1;
82 }
83 
84 
85 cg_t				cg;
86 cgs_t				cgs;
87 centity_t			cg_entities[MAX_GENTITIES];
88 weaponInfo_t		cg_weapons[MAX_WEAPONS];
89 itemInfo_t			cg_items[MAX_ITEMS];
90 
91 
92 vmCvar_t	cg_railTrailTime;
93 vmCvar_t	cg_centertime;
94 vmCvar_t	cg_runpitch;
95 vmCvar_t	cg_runroll;
96 vmCvar_t	cg_bobup;
97 vmCvar_t	cg_bobpitch;
98 vmCvar_t	cg_bobroll;
99 vmCvar_t	cg_swingSpeed;
100 vmCvar_t	cg_shadows;
101 vmCvar_t	cg_gibs;
102 vmCvar_t	cg_drawTimer;
103 vmCvar_t	cg_drawFPS;
104 vmCvar_t	cg_drawSnapshot;
105 vmCvar_t	cg_draw3dIcons;
106 vmCvar_t	cg_drawIcons;
107 vmCvar_t	cg_drawAmmoWarning;
108 vmCvar_t	cg_drawCrosshair;
109 vmCvar_t	cg_drawCrosshairNames;
110 vmCvar_t	cg_drawRewards;
111 vmCvar_t	cg_crosshairSize;
112 vmCvar_t	cg_crosshairX;
113 vmCvar_t	cg_crosshairY;
114 vmCvar_t	cg_crosshairHealth;
115 vmCvar_t	cg_draw2D;
116 vmCvar_t	cg_drawStatus;
117 vmCvar_t	cg_animSpeed;
118 vmCvar_t	cg_debugAnim;
119 vmCvar_t	cg_debugPosition;
120 vmCvar_t	cg_debugEvents;
121 vmCvar_t	cg_errorDecay;
122 vmCvar_t	cg_nopredict;
123 vmCvar_t	cg_noPlayerAnims;
124 vmCvar_t	cg_showmiss;
125 vmCvar_t	cg_footsteps;
126 vmCvar_t	cg_addMarks;
127 vmCvar_t	cg_brassTime;
128 vmCvar_t	cg_viewsize;
129 vmCvar_t	cg_drawGun;
130 vmCvar_t	cg_gun_frame;
131 vmCvar_t	cg_gun_x;
132 vmCvar_t	cg_gun_y;
133 vmCvar_t	cg_gun_z;
134 vmCvar_t	cg_tracerChance;
135 vmCvar_t	cg_tracerWidth;
136 vmCvar_t	cg_tracerLength;
137 vmCvar_t	cg_autoswitch;
138 vmCvar_t	cg_ignore;
139 vmCvar_t	cg_simpleItems;
140 vmCvar_t	cg_fov;
141 vmCvar_t	cg_zoomFov;
142 vmCvar_t	cg_thirdPerson;
143 vmCvar_t	cg_thirdPersonRange;
144 vmCvar_t	cg_thirdPersonAngle;
145 vmCvar_t	cg_lagometer;
146 vmCvar_t	cg_drawAttacker;
147 vmCvar_t	cg_synchronousClients;
148 vmCvar_t 	cg_teamChatTime;
149 vmCvar_t 	cg_teamChatHeight;
150 vmCvar_t 	cg_stats;
151 vmCvar_t 	cg_buildScript;
152 vmCvar_t 	cg_forceModel;
153 vmCvar_t	cg_paused;
154 vmCvar_t	cg_blood;
155 vmCvar_t	cg_predictItems;
156 vmCvar_t	cg_deferPlayers;
157 vmCvar_t	cg_drawTeamOverlay;
158 vmCvar_t	cg_teamOverlayUserinfo;
159 vmCvar_t	cg_drawFriend;
160 vmCvar_t	cg_teamChatsOnly;
161 vmCvar_t	cg_noVoiceChats;
162 vmCvar_t	cg_noVoiceText;
163 vmCvar_t	cg_hudFiles;
164 vmCvar_t 	cg_scorePlum;
165 vmCvar_t 	cg_smoothClients;
166 vmCvar_t	pmove_fixed;
167 //vmCvar_t	cg_pmove_fixed;
168 vmCvar_t	pmove_msec;
169 vmCvar_t	cg_pmove_msec;
170 vmCvar_t	cg_cameraMode;
171 vmCvar_t	cg_cameraOrbit;
172 vmCvar_t	cg_cameraOrbitDelay;
173 vmCvar_t	cg_timescaleFadeEnd;
174 vmCvar_t	cg_timescaleFadeSpeed;
175 vmCvar_t	cg_timescale;
176 vmCvar_t	cg_smallFont;
177 vmCvar_t	cg_bigFont;
178 vmCvar_t	cg_noTaunt;
179 vmCvar_t	cg_noProjectileTrail;
180 vmCvar_t	cg_oldRail;
181 vmCvar_t	cg_oldRocket;
182 vmCvar_t	cg_oldPlasma;
183 vmCvar_t	cg_trueLightning;
184 
185 #ifdef MISSIONPACK
186 vmCvar_t 	cg_redTeamName;
187 vmCvar_t 	cg_blueTeamName;
188 vmCvar_t	cg_currentSelectedPlayer;
189 vmCvar_t	cg_currentSelectedPlayerName;
190 vmCvar_t	cg_singlePlayer;
191 vmCvar_t	cg_enableDust;
192 vmCvar_t	cg_enableBreath;
193 vmCvar_t	cg_singlePlayerActive;
194 vmCvar_t	cg_recordSPDemo;
195 vmCvar_t	cg_recordSPDemoName;
196 vmCvar_t	cg_obeliskRespawnDelay;
197 #endif
198 
199 typedef struct {
200 	vmCvar_t	*vmCvar;
201 	char		*cvarName;
202 	char		*defaultString;
203 	int			cvarFlags;
204 } cvarTable_t;
205 
206 static cvarTable_t cvarTable[] = {
207 	{ &cg_ignore, "cg_ignore", "0", 0 },	// used for debugging
208 	{ &cg_autoswitch, "cg_autoswitch", "1", CVAR_ARCHIVE },
209 	{ &cg_drawGun, "cg_drawGun", "1", CVAR_ARCHIVE },
210 	{ &cg_zoomFov, "cg_zoomfov", "22.5", CVAR_ARCHIVE },
211 	{ &cg_fov, "cg_fov", "90", CVAR_ARCHIVE },
212 	{ &cg_viewsize, "cg_viewsize", "100", CVAR_ARCHIVE },
213 	{ &cg_shadows, "cg_shadows", "1", CVAR_ARCHIVE  },
214 	{ &cg_gibs, "cg_gibs", "1", CVAR_ARCHIVE  },
215 	{ &cg_draw2D, "cg_draw2D", "1", CVAR_ARCHIVE  },
216 	{ &cg_drawStatus, "cg_drawStatus", "1", CVAR_ARCHIVE  },
217 	{ &cg_drawTimer, "cg_drawTimer", "0", CVAR_ARCHIVE  },
218 	{ &cg_drawFPS, "cg_drawFPS", "0", CVAR_ARCHIVE  },
219 	{ &cg_drawSnapshot, "cg_drawSnapshot", "0", CVAR_ARCHIVE  },
220 	{ &cg_draw3dIcons, "cg_draw3dIcons", "1", CVAR_ARCHIVE  },
221 	{ &cg_drawIcons, "cg_drawIcons", "1", CVAR_ARCHIVE  },
222 	{ &cg_drawAmmoWarning, "cg_drawAmmoWarning", "1", CVAR_ARCHIVE  },
223 	{ &cg_drawAttacker, "cg_drawAttacker", "1", CVAR_ARCHIVE  },
224 	{ &cg_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE },
225 	{ &cg_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE },
226 	{ &cg_drawRewards, "cg_drawRewards", "1", CVAR_ARCHIVE },
227 	{ &cg_crosshairSize, "cg_crosshairSize", "24", CVAR_ARCHIVE },
228 	{ &cg_crosshairHealth, "cg_crosshairHealth", "1", CVAR_ARCHIVE },
229 	{ &cg_crosshairX, "cg_crosshairX", "0", CVAR_ARCHIVE },
230 	{ &cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE },
231 	{ &cg_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE },
232 	{ &cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE },
233 	{ &cg_addMarks, "cg_marks", "1", CVAR_ARCHIVE },
234 	{ &cg_lagometer, "cg_lagometer", "1", CVAR_ARCHIVE },
235 	{ &cg_railTrailTime, "cg_railTrailTime", "400", CVAR_ARCHIVE  },
236 	{ &cg_gun_x, "cg_gunX", "0", CVAR_CHEAT },
237 	{ &cg_gun_y, "cg_gunY", "0", CVAR_CHEAT },
238 	{ &cg_gun_z, "cg_gunZ", "0", CVAR_CHEAT },
239 	{ &cg_centertime, "cg_centertime", "3", CVAR_CHEAT },
240 	{ &cg_runpitch, "cg_runpitch", "0.002", CVAR_ARCHIVE},
241 	{ &cg_runroll, "cg_runroll", "0.005", CVAR_ARCHIVE },
242 	{ &cg_bobup , "cg_bobup", "0.005", CVAR_CHEAT },
243 	{ &cg_bobpitch, "cg_bobpitch", "0.002", CVAR_ARCHIVE },
244 	{ &cg_bobroll, "cg_bobroll", "0.002", CVAR_ARCHIVE },
245 	{ &cg_swingSpeed, "cg_swingSpeed", "0.3", CVAR_CHEAT },
246 	{ &cg_animSpeed, "cg_animspeed", "1", CVAR_CHEAT },
247 	{ &cg_debugAnim, "cg_debuganim", "0", CVAR_CHEAT },
248 	{ &cg_debugPosition, "cg_debugposition", "0", CVAR_CHEAT },
249 	{ &cg_debugEvents, "cg_debugevents", "0", CVAR_CHEAT },
250 	{ &cg_errorDecay, "cg_errordecay", "100", 0 },
251 	{ &cg_nopredict, "cg_nopredict", "0", 0 },
252 	{ &cg_noPlayerAnims, "cg_noplayeranims", "0", CVAR_CHEAT },
253 	{ &cg_showmiss, "cg_showmiss", "0", 0 },
254 	{ &cg_footsteps, "cg_footsteps", "1", CVAR_CHEAT },
255 	{ &cg_tracerChance, "cg_tracerchance", "0.4", CVAR_CHEAT },
256 	{ &cg_tracerWidth, "cg_tracerwidth", "1", CVAR_CHEAT },
257 	{ &cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT },
258 	{ &cg_thirdPersonRange, "cg_thirdPersonRange", "40", CVAR_CHEAT },
259 	{ &cg_thirdPersonAngle, "cg_thirdPersonAngle", "0", CVAR_CHEAT },
260 	{ &cg_thirdPerson, "cg_thirdPerson", "0", 0 },
261 	{ &cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE  },
262 	{ &cg_teamChatHeight, "cg_teamChatHeight", "0", CVAR_ARCHIVE  },
263 	{ &cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE  },
264 	{ &cg_predictItems, "cg_predictItems", "1", CVAR_ARCHIVE },
265 #ifdef MISSIONPACK
266 	{ &cg_deferPlayers, "cg_deferPlayers", "0", CVAR_ARCHIVE },
267 #else
268 	{ &cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE },
269 #endif
270 	{ &cg_drawTeamOverlay, "cg_drawTeamOverlay", "0", CVAR_ARCHIVE },
271 	{ &cg_teamOverlayUserinfo, "teamoverlay", "0", CVAR_ROM | CVAR_USERINFO },
272 	{ &cg_stats, "cg_stats", "0", 0 },
273 	{ &cg_drawFriend, "cg_drawFriend", "1", CVAR_ARCHIVE },
274 	{ &cg_teamChatsOnly, "cg_teamChatsOnly", "0", CVAR_ARCHIVE },
275 	{ &cg_noVoiceChats, "cg_noVoiceChats", "0", CVAR_ARCHIVE },
276 	{ &cg_noVoiceText, "cg_noVoiceText", "0", CVAR_ARCHIVE },
277 	// the following variables are created in other parts of the system,
278 	// but we also reference them here
279 	{ &cg_buildScript, "com_buildScript", "0", 0 },	// force loading of all possible data amd error on failures
280 	{ &cg_paused, "cl_paused", "0", CVAR_ROM },
281 	{ &cg_blood, "com_blood", "1", CVAR_ARCHIVE },
282 	{ &cg_synchronousClients, "g_synchronousClients", "0", 0 },	// communicated by systeminfo
283 #ifdef MISSIONPACK
284 	{ &cg_redTeamName, "g_redteam", DEFAULT_REDTEAM_NAME, CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_USERINFO },
285 	{ &cg_blueTeamName, "g_blueteam", DEFAULT_BLUETEAM_NAME, CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_USERINFO },
286 	{ &cg_currentSelectedPlayer, "cg_currentSelectedPlayer", "0", CVAR_ARCHIVE},
287 	{ &cg_currentSelectedPlayerName, "cg_currentSelectedPlayerName", "", CVAR_ARCHIVE},
288 	{ &cg_singlePlayer, "ui_singlePlayerActive", "0", CVAR_USERINFO},
289 	{ &cg_enableDust, "g_enableDust", "0", CVAR_SERVERINFO},
290 	{ &cg_enableBreath, "g_enableBreath", "0", CVAR_SERVERINFO},
291 	{ &cg_singlePlayerActive, "ui_singlePlayerActive", "0", CVAR_USERINFO},
292 	{ &cg_recordSPDemo, "ui_recordSPDemo", "0", CVAR_ARCHIVE},
293 	{ &cg_recordSPDemoName, "ui_recordSPDemoName", "", CVAR_ARCHIVE},
294 	{ &cg_obeliskRespawnDelay, "g_obeliskRespawnDelay", "10", CVAR_SERVERINFO},
295 	{ &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE},
296 #endif
297 	{ &cg_cameraOrbit, "cg_cameraOrbit", "0", CVAR_CHEAT},
298 	{ &cg_cameraOrbitDelay, "cg_cameraOrbitDelay", "50", CVAR_ARCHIVE},
299 	{ &cg_timescaleFadeEnd, "cg_timescaleFadeEnd", "1", 0},
300 	{ &cg_timescaleFadeSpeed, "cg_timescaleFadeSpeed", "0", 0},
301 	{ &cg_timescale, "timescale", "1", 0},
302 	{ &cg_scorePlum, "cg_scorePlums", "1", CVAR_USERINFO | CVAR_ARCHIVE},
303 	{ &cg_smoothClients, "cg_smoothClients", "0", CVAR_USERINFO | CVAR_ARCHIVE},
304 	{ &cg_cameraMode, "com_cameraMode", "0", CVAR_CHEAT},
305 
306 	{ &pmove_fixed, "pmove_fixed", "0", 0},
307 	{ &pmove_msec, "pmove_msec", "8", 0},
308 	{ &cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE},
309 	{ &cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE},
310 	{ &cg_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE},
311 	{ &cg_bigFont, "ui_bigFont", "0.4", CVAR_ARCHIVE},
312 	{ &cg_oldRail, "cg_oldRail", "1", CVAR_ARCHIVE},
313 	{ &cg_oldRocket, "cg_oldRocket", "1", CVAR_ARCHIVE},
314 	{ &cg_oldPlasma, "cg_oldPlasma", "1", CVAR_ARCHIVE},
315 	{ &cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE}
316 //	{ &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE }
317 };
318 
319 static int  cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] );
320 
321 /*
322 =================
323 CG_RegisterCvars
324 =================
325 */
CG_RegisterCvars(void)326 void CG_RegisterCvars( void ) {
327 	int			i;
328 	cvarTable_t	*cv;
329 	char		var[MAX_TOKEN_CHARS];
330 
331 	for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
332 		trap_Cvar_Register( cv->vmCvar, cv->cvarName,
333 			cv->defaultString, cv->cvarFlags );
334 	}
335 
336 	// see if we are also running the server on this machine
337 	trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) );
338 	cgs.localServer = atoi( var );
339 
340 	forceModelModificationCount = cg_forceModel.modificationCount;
341 
342 	trap_Cvar_Register(NULL, "model", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );
343 	trap_Cvar_Register(NULL, "headmodel", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );
344 	trap_Cvar_Register(NULL, "team_model", DEFAULT_TEAM_MODEL, CVAR_USERINFO | CVAR_ARCHIVE );
345 	trap_Cvar_Register(NULL, "team_headmodel", DEFAULT_TEAM_HEAD, CVAR_USERINFO | CVAR_ARCHIVE );
346 }
347 
348 /*
349 ===================
350 CG_ForceModelChange
351 ===================
352 */
CG_ForceModelChange(void)353 static void CG_ForceModelChange( void ) {
354 	int		i;
355 
356 	for (i=0 ; i<MAX_CLIENTS ; i++) {
357 		const char		*clientInfo;
358 
359 		clientInfo = CG_ConfigString( CS_PLAYERS+i );
360 		if ( !clientInfo[0] ) {
361 			continue;
362 		}
363 		CG_NewClientInfo( i );
364 	}
365 }
366 
367 /*
368 =================
369 CG_UpdateCvars
370 =================
371 */
CG_UpdateCvars(void)372 void CG_UpdateCvars( void ) {
373 	int			i;
374 	cvarTable_t	*cv;
375 
376 	for ( i = 0, cv = cvarTable ; i < cvarTableSize ; i++, cv++ ) {
377 		trap_Cvar_Update( cv->vmCvar );
378 	}
379 
380 	// check for modications here
381 
382 	// If team overlay is on, ask for updates from the server.  If its off,
383 	// let the server know so we don't receive it
384 	if ( drawTeamOverlayModificationCount != cg_drawTeamOverlay.modificationCount ) {
385 		drawTeamOverlayModificationCount = cg_drawTeamOverlay.modificationCount;
386 
387 		if ( cg_drawTeamOverlay.integer > 0 ) {
388 			trap_Cvar_Set( "teamoverlay", "1" );
389 		} else {
390 			trap_Cvar_Set( "teamoverlay", "0" );
391 		}
392 	}
393 
394 	// if force model changed
395 	if ( forceModelModificationCount != cg_forceModel.modificationCount ) {
396 		forceModelModificationCount = cg_forceModel.modificationCount;
397 		CG_ForceModelChange();
398 	}
399 }
400 
CG_CrosshairPlayer(void)401 int CG_CrosshairPlayer( void ) {
402 	if ( cg.time > ( cg.crosshairClientTime + 1000 ) ) {
403 		return -1;
404 	}
405 	return cg.crosshairClientNum;
406 }
407 
CG_LastAttacker(void)408 int CG_LastAttacker( void ) {
409 	if ( !cg.attackerTime ) {
410 		return -1;
411 	}
412 	return cg.snap->ps.persistant[PERS_ATTACKER];
413 }
414 
CG_Printf(const char * msg,...)415 void QDECL CG_Printf( const char *msg, ... ) {
416 	va_list		argptr;
417 	char		text[1024];
418 
419 	va_start (argptr, msg);
420 	Q_vsnprintf (text, sizeof(text), msg, argptr);
421 	va_end (argptr);
422 
423 	trap_Print( text );
424 }
425 
CG_Error(const char * msg,...)426 void QDECL CG_Error( const char *msg, ... ) {
427 	va_list		argptr;
428 	char		text[1024];
429 
430 	va_start (argptr, msg);
431 	Q_vsnprintf (text, sizeof(text), msg, argptr);
432 	va_end (argptr);
433 
434 	trap_Error( text );
435 }
436 
Com_Error(int level,const char * error,...)437 void QDECL Com_Error( int level, const char *error, ... ) {
438 	va_list		argptr;
439 	char		text[1024];
440 
441 	va_start (argptr, error);
442 	Q_vsnprintf (text, sizeof(text), error, argptr);
443 	va_end (argptr);
444 
445 	CG_Error( "%s", text);
446 }
447 
Com_Printf(const char * msg,...)448 void QDECL Com_Printf( const char *msg, ... ) {
449 	va_list		argptr;
450 	char		text[1024];
451 
452 	va_start (argptr, msg);
453 	Q_vsnprintf (text, sizeof(text), msg, argptr);
454 	va_end (argptr);
455 
456 	CG_Printf ("%s", text);
457 }
458 
459 /*
460 ================
461 CG_Argv
462 ================
463 */
CG_Argv(int arg)464 const char *CG_Argv( int arg ) {
465 	static char	buffer[MAX_STRING_CHARS];
466 
467 	trap_Argv( arg, buffer, sizeof( buffer ) );
468 
469 	return buffer;
470 }
471 
472 
473 //========================================================================
474 
475 /*
476 =================
477 CG_RegisterItemSounds
478 
479 The server says this item is used on this level
480 =================
481 */
CG_RegisterItemSounds(int itemNum)482 static void CG_RegisterItemSounds( int itemNum ) {
483 	gitem_t			*item;
484 	char			data[MAX_QPATH];
485 	char			*s, *start;
486 	int				len;
487 
488 	item = &bg_itemlist[ itemNum ];
489 
490 	if( item->pickup_sound ) {
491 		trap_S_RegisterSound( item->pickup_sound, qfalse );
492 	}
493 
494 	// parse the space seperated precache string for other media
495 	s = item->sounds;
496 	if (!s || !s[0])
497 		return;
498 
499 	while (*s) {
500 		start = s;
501 		while (*s && *s != ' ') {
502 			s++;
503 		}
504 
505 		len = s-start;
506 		if (len >= MAX_QPATH || len < 5) {
507 			CG_Error( "PrecacheItem: %s has bad precache string",
508 				item->classname);
509 			return;
510 		}
511 		memcpy (data, start, len);
512 		data[len] = 0;
513 		if ( *s ) {
514 			s++;
515 		}
516 
517 		if ( !strcmp(data+len-3, "wav" )) {
518 			trap_S_RegisterSound( data, qfalse );
519 		}
520 	}
521 }
522 
523 
524 /*
525 =================
526 CG_RegisterSounds
527 
528 called during a precache command
529 =================
530 */
CG_RegisterSounds(void)531 static void CG_RegisterSounds( void ) {
532 	int		i;
533 	char	items[MAX_ITEMS+1];
534 	char	name[MAX_QPATH];
535 	const char	*soundName;
536 
537 	// voice commands
538 #ifdef MISSIONPACK
539 	CG_LoadVoiceChats();
540 #endif
541 
542 	cgs.media.oneMinuteSound = trap_S_RegisterSound( "sound/feedback/1_minute.wav", qtrue );
543 	cgs.media.fiveMinuteSound = trap_S_RegisterSound( "sound/feedback/5_minute.wav", qtrue );
544 	cgs.media.suddenDeathSound = trap_S_RegisterSound( "sound/feedback/sudden_death.wav", qtrue );
545 	cgs.media.oneFragSound = trap_S_RegisterSound( "sound/feedback/1_frag.wav", qtrue );
546 	cgs.media.twoFragSound = trap_S_RegisterSound( "sound/feedback/2_frags.wav", qtrue );
547 	cgs.media.threeFragSound = trap_S_RegisterSound( "sound/feedback/3_frags.wav", qtrue );
548 	cgs.media.count3Sound = trap_S_RegisterSound( "sound/feedback/three.wav", qtrue );
549 	cgs.media.count2Sound = trap_S_RegisterSound( "sound/feedback/two.wav", qtrue );
550 	cgs.media.count1Sound = trap_S_RegisterSound( "sound/feedback/one.wav", qtrue );
551 	cgs.media.countFightSound = trap_S_RegisterSound( "sound/feedback/fight.wav", qtrue );
552 	cgs.media.countPrepareSound = trap_S_RegisterSound( "sound/feedback/prepare.wav", qtrue );
553 #ifdef MISSIONPACK
554 	cgs.media.countPrepareTeamSound = trap_S_RegisterSound( "sound/feedback/prepare_team.wav", qtrue );
555 #endif
556 
557 	if ( cgs.gametype >= GT_TEAM || cg_buildScript.integer ) {
558 
559 		cgs.media.captureAwardSound = trap_S_RegisterSound( "sound/teamplay/flagcapture_yourteam.wav", qtrue );
560 		cgs.media.redLeadsSound = trap_S_RegisterSound( "sound/feedback/redleads.wav", qtrue );
561 		cgs.media.blueLeadsSound = trap_S_RegisterSound( "sound/feedback/blueleads.wav", qtrue );
562 		cgs.media.teamsTiedSound = trap_S_RegisterSound( "sound/feedback/teamstied.wav", qtrue );
563 		cgs.media.hitTeamSound = trap_S_RegisterSound( "sound/feedback/hit_teammate.wav", qtrue );
564 
565 		cgs.media.redScoredSound = trap_S_RegisterSound( "sound/teamplay/voc_red_scores.wav", qtrue );
566 		cgs.media.blueScoredSound = trap_S_RegisterSound( "sound/teamplay/voc_blue_scores.wav", qtrue );
567 
568 		cgs.media.captureYourTeamSound = trap_S_RegisterSound( "sound/teamplay/flagcapture_yourteam.wav", qtrue );
569 		cgs.media.captureOpponentSound = trap_S_RegisterSound( "sound/teamplay/flagcapture_opponent.wav", qtrue );
570 
571 		cgs.media.returnYourTeamSound = trap_S_RegisterSound( "sound/teamplay/flagreturn_yourteam.wav", qtrue );
572 		cgs.media.returnOpponentSound = trap_S_RegisterSound( "sound/teamplay/flagreturn_opponent.wav", qtrue );
573 
574 		cgs.media.takenYourTeamSound = trap_S_RegisterSound( "sound/teamplay/flagtaken_yourteam.wav", qtrue );
575 		cgs.media.takenOpponentSound = trap_S_RegisterSound( "sound/teamplay/flagtaken_opponent.wav", qtrue );
576 
577 		if ( cgs.gametype == GT_CTF || cg_buildScript.integer ) {
578 			cgs.media.redFlagReturnedSound = trap_S_RegisterSound( "sound/teamplay/voc_red_returned.wav", qtrue );
579 			cgs.media.blueFlagReturnedSound = trap_S_RegisterSound( "sound/teamplay/voc_blue_returned.wav", qtrue );
580 			cgs.media.enemyTookYourFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_enemy_flag.wav", qtrue );
581 			cgs.media.yourTeamTookEnemyFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_team_flag.wav", qtrue );
582 		}
583 
584 #ifdef MISSIONPACK
585 		if ( cgs.gametype == GT_1FCTF || cg_buildScript.integer ) {
586 			// FIXME: get a replacement for this sound ?
587 			cgs.media.neutralFlagReturnedSound = trap_S_RegisterSound( "sound/teamplay/flagreturn_opponent.wav", qtrue );
588 			cgs.media.yourTeamTookTheFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_team_1flag.wav", qtrue );
589 			cgs.media.enemyTookTheFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_enemy_1flag.wav", qtrue );
590 		}
591 
592 		if ( cgs.gametype == GT_1FCTF || cgs.gametype == GT_CTF || cg_buildScript.integer ) {
593 			cgs.media.youHaveFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_you_flag.wav", qtrue );
594 			cgs.media.holyShitSound = trap_S_RegisterSound("sound/feedback/voc_holyshit.wav", qtrue);
595 		}
596 
597 		if ( cgs.gametype == GT_OBELISK || cg_buildScript.integer ) {
598 			cgs.media.yourBaseIsUnderAttackSound = trap_S_RegisterSound( "sound/teamplay/voc_base_attack.wav", qtrue );
599 		}
600 #else
601 		cgs.media.youHaveFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_you_flag.wav", qtrue );
602 		cgs.media.holyShitSound = trap_S_RegisterSound("sound/feedback/voc_holyshit.wav", qtrue);
603 		cgs.media.neutralFlagReturnedSound = trap_S_RegisterSound( "sound/teamplay/flagreturn_opponent.wav", qtrue );
604 		cgs.media.yourTeamTookTheFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_team_1flag.wav", qtrue );
605 		cgs.media.enemyTookTheFlagSound = trap_S_RegisterSound( "sound/teamplay/voc_enemy_1flag.wav", qtrue );
606 #endif
607 	}
608 
609 	cgs.media.tracerSound = trap_S_RegisterSound( "sound/weapons/machinegun/buletby1.wav", qfalse );
610 	cgs.media.selectSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse );
611 	cgs.media.wearOffSound = trap_S_RegisterSound( "sound/items/wearoff.wav", qfalse );
612 	cgs.media.useNothingSound = trap_S_RegisterSound( "sound/items/use_nothing.wav", qfalse );
613 	cgs.media.gibSound = trap_S_RegisterSound( "sound/player/gibsplt1.wav", qfalse );
614 	cgs.media.gibBounce1Sound = trap_S_RegisterSound( "sound/player/gibimp1.wav", qfalse );
615 	cgs.media.gibBounce2Sound = trap_S_RegisterSound( "sound/player/gibimp2.wav", qfalse );
616 	cgs.media.gibBounce3Sound = trap_S_RegisterSound( "sound/player/gibimp3.wav", qfalse );
617 
618 #ifdef MISSIONPACK
619 	cgs.media.useInvulnerabilitySound = trap_S_RegisterSound( "sound/items/invul_activate.wav", qfalse );
620 	cgs.media.invulnerabilityImpactSound1 = trap_S_RegisterSound( "sound/items/invul_impact_01.wav", qfalse );
621 	cgs.media.invulnerabilityImpactSound2 = trap_S_RegisterSound( "sound/items/invul_impact_02.wav", qfalse );
622 	cgs.media.invulnerabilityImpactSound3 = trap_S_RegisterSound( "sound/items/invul_impact_03.wav", qfalse );
623 	cgs.media.invulnerabilityJuicedSound = trap_S_RegisterSound( "sound/items/invul_juiced.wav", qfalse );
624 	cgs.media.obeliskHitSound1 = trap_S_RegisterSound( "sound/items/obelisk_hit_01.wav", qfalse );
625 	cgs.media.obeliskHitSound2 = trap_S_RegisterSound( "sound/items/obelisk_hit_02.wav", qfalse );
626 	cgs.media.obeliskHitSound3 = trap_S_RegisterSound( "sound/items/obelisk_hit_03.wav", qfalse );
627 	cgs.media.obeliskRespawnSound = trap_S_RegisterSound( "sound/items/obelisk_respawn.wav", qfalse );
628 
629 	cgs.media.ammoregenSound = trap_S_RegisterSound("sound/items/cl_ammoregen.wav", qfalse);
630 	cgs.media.doublerSound = trap_S_RegisterSound("sound/items/cl_doubler.wav", qfalse);
631 	cgs.media.guardSound = trap_S_RegisterSound("sound/items/cl_guard.wav", qfalse);
632 	cgs.media.scoutSound = trap_S_RegisterSound("sound/items/cl_scout.wav", qfalse);
633 #endif
634 
635 	cgs.media.teleInSound = trap_S_RegisterSound( "sound/world/telein.wav", qfalse );
636 	cgs.media.teleOutSound = trap_S_RegisterSound( "sound/world/teleout.wav", qfalse );
637 	cgs.media.respawnSound = trap_S_RegisterSound( "sound/items/respawn1.wav", qfalse );
638 
639 	cgs.media.noAmmoSound = trap_S_RegisterSound( "sound/weapons/noammo.wav", qfalse );
640 
641 	cgs.media.talkSound = trap_S_RegisterSound( "sound/player/talk.wav", qfalse );
642 	cgs.media.landSound = trap_S_RegisterSound( "sound/player/land1.wav", qfalse);
643 
644 	cgs.media.hitSound = trap_S_RegisterSound( "sound/feedback/hit.wav", qfalse );
645 #ifdef MISSIONPACK
646 	cgs.media.hitSoundHighArmor = trap_S_RegisterSound( "sound/feedback/hithi.wav", qfalse );
647 	cgs.media.hitSoundLowArmor = trap_S_RegisterSound( "sound/feedback/hitlo.wav", qfalse );
648 #endif
649 
650 	cgs.media.impressiveSound = trap_S_RegisterSound( "sound/feedback/impressive.wav", qtrue );
651 	cgs.media.excellentSound = trap_S_RegisterSound( "sound/feedback/excellent.wav", qtrue );
652 	cgs.media.deniedSound = trap_S_RegisterSound( "sound/feedback/denied.wav", qtrue );
653 	cgs.media.humiliationSound = trap_S_RegisterSound( "sound/feedback/humiliation.wav", qtrue );
654 	cgs.media.assistSound = trap_S_RegisterSound( "sound/feedback/assist.wav", qtrue );
655 	cgs.media.defendSound = trap_S_RegisterSound( "sound/feedback/defense.wav", qtrue );
656 #ifdef MISSIONPACK
657 	cgs.media.firstImpressiveSound = trap_S_RegisterSound( "sound/feedback/first_impressive.wav", qtrue );
658 	cgs.media.firstExcellentSound = trap_S_RegisterSound( "sound/feedback/first_excellent.wav", qtrue );
659 	cgs.media.firstHumiliationSound = trap_S_RegisterSound( "sound/feedback/first_gauntlet.wav", qtrue );
660 #endif
661 
662 	cgs.media.takenLeadSound = trap_S_RegisterSound( "sound/feedback/takenlead.wav", qtrue);
663 	cgs.media.tiedLeadSound = trap_S_RegisterSound( "sound/feedback/tiedlead.wav", qtrue);
664 	cgs.media.lostLeadSound = trap_S_RegisterSound( "sound/feedback/lostlead.wav", qtrue);
665 
666 #ifdef MISSIONPACK
667 	cgs.media.voteNow = trap_S_RegisterSound( "sound/feedback/vote_now.wav", qtrue);
668 	cgs.media.votePassed = trap_S_RegisterSound( "sound/feedback/vote_passed.wav", qtrue);
669 	cgs.media.voteFailed = trap_S_RegisterSound( "sound/feedback/vote_failed.wav", qtrue);
670 #endif
671 
672 	cgs.media.watrInSound = trap_S_RegisterSound( "sound/player/watr_in.wav", qfalse);
673 	cgs.media.watrOutSound = trap_S_RegisterSound( "sound/player/watr_out.wav", qfalse);
674 	cgs.media.watrUnSound = trap_S_RegisterSound( "sound/player/watr_un.wav", qfalse);
675 
676 	cgs.media.jumpPadSound = trap_S_RegisterSound ("sound/world/jumppad.wav", qfalse );
677 
678 	for (i=0 ; i<4 ; i++) {
679 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/step%i.wav", i+1);
680 		cgs.media.footsteps[FOOTSTEP_NORMAL][i] = trap_S_RegisterSound (name, qfalse);
681 
682 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/boot%i.wav", i+1);
683 		cgs.media.footsteps[FOOTSTEP_BOOT][i] = trap_S_RegisterSound (name, qfalse);
684 
685 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/flesh%i.wav", i+1);
686 		cgs.media.footsteps[FOOTSTEP_FLESH][i] = trap_S_RegisterSound (name, qfalse);
687 
688 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/mech%i.wav", i+1);
689 		cgs.media.footsteps[FOOTSTEP_MECH][i] = trap_S_RegisterSound (name, qfalse);
690 
691 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/energy%i.wav", i+1);
692 		cgs.media.footsteps[FOOTSTEP_ENERGY][i] = trap_S_RegisterSound (name, qfalse);
693 
694 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/splash%i.wav", i+1);
695 		cgs.media.footsteps[FOOTSTEP_SPLASH][i] = trap_S_RegisterSound (name, qfalse);
696 
697 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/clank%i.wav", i+1);
698 		cgs.media.footsteps[FOOTSTEP_METAL][i] = trap_S_RegisterSound (name, qfalse);
699 	}
700 
701 	// only register the items that the server says we need
702 	Q_strncpyz(items, CG_ConfigString(CS_ITEMS), sizeof(items));
703 
704 	for ( i = 1 ; i < bg_numItems ; i++ ) {
705 //		if ( items[ i ] == '1' || cg_buildScript.integer ) {
706 			CG_RegisterItemSounds( i );
707 //		}
708 	}
709 
710 	for ( i = 1 ; i < MAX_SOUNDS ; i++ ) {
711 		soundName = CG_ConfigString( CS_SOUNDS+i );
712 		if ( !soundName[0] ) {
713 			break;
714 		}
715 		if ( soundName[0] == '*' ) {
716 			continue;	// custom sound
717 		}
718 		cgs.gameSounds[i] = trap_S_RegisterSound( soundName, qfalse );
719 	}
720 
721 	// FIXME: only needed with item
722 	cgs.media.flightSound = trap_S_RegisterSound( "sound/items/flight.wav", qfalse );
723 	cgs.media.medkitSound = trap_S_RegisterSound ("sound/items/use_medkit.wav", qfalse);
724 	cgs.media.quadSound = trap_S_RegisterSound("sound/items/damage3.wav", qfalse);
725 	cgs.media.sfx_ric1 = trap_S_RegisterSound ("sound/weapons/machinegun/ric1.wav", qfalse);
726 	cgs.media.sfx_ric2 = trap_S_RegisterSound ("sound/weapons/machinegun/ric2.wav", qfalse);
727 	cgs.media.sfx_ric3 = trap_S_RegisterSound ("sound/weapons/machinegun/ric3.wav", qfalse);
728 	cgs.media.sfx_railg = trap_S_RegisterSound ("sound/weapons/railgun/railgf1a.wav", qfalse);
729 	cgs.media.sfx_rockexp = trap_S_RegisterSound ("sound/weapons/rocket/rocklx1a.wav", qfalse);
730 	cgs.media.sfx_plasmaexp = trap_S_RegisterSound ("sound/weapons/plasma/plasmx1a.wav", qfalse);
731 #ifdef MISSIONPACK
732 	cgs.media.sfx_proxexp = trap_S_RegisterSound( "sound/weapons/proxmine/wstbexpl.wav" , qfalse);
733 	cgs.media.sfx_nghit = trap_S_RegisterSound( "sound/weapons/nailgun/wnalimpd.wav" , qfalse);
734 	cgs.media.sfx_nghitflesh = trap_S_RegisterSound( "sound/weapons/nailgun/wnalimpl.wav" , qfalse);
735 	cgs.media.sfx_nghitmetal = trap_S_RegisterSound( "sound/weapons/nailgun/wnalimpm.wav", qfalse );
736 	cgs.media.sfx_chghit = trap_S_RegisterSound( "sound/weapons/vulcan/wvulimpd.wav", qfalse );
737 	cgs.media.sfx_chghitflesh = trap_S_RegisterSound( "sound/weapons/vulcan/wvulimpl.wav", qfalse );
738 	cgs.media.sfx_chghitmetal = trap_S_RegisterSound( "sound/weapons/vulcan/wvulimpm.wav", qfalse );
739 	cgs.media.weaponHoverSound = trap_S_RegisterSound( "sound/weapons/weapon_hover.wav", qfalse );
740 	cgs.media.kamikazeExplodeSound = trap_S_RegisterSound( "sound/items/kam_explode.wav", qfalse );
741 	cgs.media.kamikazeImplodeSound = trap_S_RegisterSound( "sound/items/kam_implode.wav", qfalse );
742 	cgs.media.kamikazeFarSound = trap_S_RegisterSound( "sound/items/kam_explode_far.wav", qfalse );
743 	cgs.media.winnerSound = trap_S_RegisterSound( "sound/feedback/voc_youwin.wav", qfalse );
744 	cgs.media.loserSound = trap_S_RegisterSound( "sound/feedback/voc_youlose.wav", qfalse );
745 	cgs.media.youSuckSound = trap_S_RegisterSound( "sound/misc/yousuck.wav", qfalse );
746 
747 	cgs.media.wstbimplSound = trap_S_RegisterSound("sound/weapons/proxmine/wstbimpl.wav", qfalse);
748 	cgs.media.wstbimpmSound = trap_S_RegisterSound("sound/weapons/proxmine/wstbimpm.wav", qfalse);
749 	cgs.media.wstbimpdSound = trap_S_RegisterSound("sound/weapons/proxmine/wstbimpd.wav", qfalse);
750 	cgs.media.wstbactvSound = trap_S_RegisterSound("sound/weapons/proxmine/wstbactv.wav", qfalse);
751 #endif
752 
753 	cgs.media.regenSound = trap_S_RegisterSound("sound/items/regen.wav", qfalse);
754 	cgs.media.protectSound = trap_S_RegisterSound("sound/items/protect3.wav", qfalse);
755 	cgs.media.n_healthSound = trap_S_RegisterSound("sound/items/n_health.wav", qfalse );
756 	cgs.media.hgrenb1aSound = trap_S_RegisterSound("sound/weapons/grenade/hgrenb1a.wav", qfalse);
757 	cgs.media.hgrenb2aSound = trap_S_RegisterSound("sound/weapons/grenade/hgrenb2a.wav", qfalse);
758 
759 #ifdef MISSIONPACK
760 	trap_S_RegisterSound("sound/player/james/death1.wav", qfalse );
761 	trap_S_RegisterSound("sound/player/james/death2.wav", qfalse );
762 	trap_S_RegisterSound("sound/player/james/death3.wav", qfalse );
763 	trap_S_RegisterSound("sound/player/james/jump1.wav", qfalse );
764 	trap_S_RegisterSound("sound/player/james/pain25_1.wav", qfalse );
765 	trap_S_RegisterSound("sound/player/james/pain75_1.wav", qfalse );
766 	trap_S_RegisterSound("sound/player/james/pain100_1.wav", qfalse );
767 	trap_S_RegisterSound("sound/player/james/falling1.wav", qfalse );
768 	trap_S_RegisterSound("sound/player/james/gasp.wav", qfalse );
769 	trap_S_RegisterSound("sound/player/james/drown.wav", qfalse );
770 	trap_S_RegisterSound("sound/player/james/fall1.wav", qfalse );
771 	trap_S_RegisterSound("sound/player/james/taunt.wav", qfalse );
772 
773 	trap_S_RegisterSound("sound/player/janet/death1.wav", qfalse );
774 	trap_S_RegisterSound("sound/player/janet/death2.wav", qfalse );
775 	trap_S_RegisterSound("sound/player/janet/death3.wav", qfalse );
776 	trap_S_RegisterSound("sound/player/janet/jump1.wav", qfalse );
777 	trap_S_RegisterSound("sound/player/janet/pain25_1.wav", qfalse );
778 	trap_S_RegisterSound("sound/player/janet/pain75_1.wav", qfalse );
779 	trap_S_RegisterSound("sound/player/janet/pain100_1.wav", qfalse );
780 	trap_S_RegisterSound("sound/player/janet/falling1.wav", qfalse );
781 	trap_S_RegisterSound("sound/player/janet/gasp.wav", qfalse );
782 	trap_S_RegisterSound("sound/player/janet/drown.wav", qfalse );
783 	trap_S_RegisterSound("sound/player/janet/fall1.wav", qfalse );
784 	trap_S_RegisterSound("sound/player/janet/taunt.wav", qfalse );
785 #endif
786 
787 }
788 
789 
790 //===================================================================================
791 
792 
793 /*
794 =================
795 CG_RegisterGraphics
796 
797 This function may execute for a couple of minutes with a slow disk.
798 =================
799 */
CG_RegisterGraphics(void)800 static void CG_RegisterGraphics( void ) {
801 	int			i;
802 	char		items[MAX_ITEMS+1];
803 	static char		*sb_nums[11] = {
804 		"gfx/2d/numbers/zero_32b",
805 		"gfx/2d/numbers/one_32b",
806 		"gfx/2d/numbers/two_32b",
807 		"gfx/2d/numbers/three_32b",
808 		"gfx/2d/numbers/four_32b",
809 		"gfx/2d/numbers/five_32b",
810 		"gfx/2d/numbers/six_32b",
811 		"gfx/2d/numbers/seven_32b",
812 		"gfx/2d/numbers/eight_32b",
813 		"gfx/2d/numbers/nine_32b",
814 		"gfx/2d/numbers/minus_32b",
815 	};
816 
817 	// clear any references to old media
818 	memset( &cg.refdef, 0, sizeof( cg.refdef ) );
819 	trap_R_ClearScene();
820 
821 	CG_LoadingString( cgs.mapname );
822 
823 	trap_R_LoadWorldMap( cgs.mapname );
824 
825 	// precache status bar pics
826 	CG_LoadingString( "game media" );
827 
828 	for ( i=0 ; i<11 ; i++) {
829 		cgs.media.numberShaders[i] = trap_R_RegisterShader( sb_nums[i] );
830 	}
831 
832 	cgs.media.botSkillShaders[0] = trap_R_RegisterShader( "menu/art/skill1.tga" );
833 	cgs.media.botSkillShaders[1] = trap_R_RegisterShader( "menu/art/skill2.tga" );
834 	cgs.media.botSkillShaders[2] = trap_R_RegisterShader( "menu/art/skill3.tga" );
835 	cgs.media.botSkillShaders[3] = trap_R_RegisterShader( "menu/art/skill4.tga" );
836 	cgs.media.botSkillShaders[4] = trap_R_RegisterShader( "menu/art/skill5.tga" );
837 
838 	cgs.media.viewBloodShader = trap_R_RegisterShader( "viewBloodBlend" );
839 
840 	cgs.media.deferShader = trap_R_RegisterShaderNoMip( "gfx/2d/defer.tga" );
841 
842 	cgs.media.scoreboardName = trap_R_RegisterShaderNoMip( "menu/tab/name.tga" );
843 	cgs.media.scoreboardPing = trap_R_RegisterShaderNoMip( "menu/tab/ping.tga" );
844 	cgs.media.scoreboardScore = trap_R_RegisterShaderNoMip( "menu/tab/score.tga" );
845 	cgs.media.scoreboardTime = trap_R_RegisterShaderNoMip( "menu/tab/time.tga" );
846 
847 	cgs.media.smokePuffShader = trap_R_RegisterShader( "smokePuff" );
848 	cgs.media.smokePuffRageProShader = trap_R_RegisterShader( "smokePuffRagePro" );
849 	cgs.media.shotgunSmokePuffShader = trap_R_RegisterShader( "shotgunSmokePuff" );
850 #ifdef MISSIONPACK
851 	cgs.media.nailPuffShader = trap_R_RegisterShader( "nailtrail" );
852 	cgs.media.blueProxMine = trap_R_RegisterModel( "models/weaphits/proxmineb.md3" );
853 #endif
854 	cgs.media.plasmaBallShader = trap_R_RegisterShader( "sprites/plasma1" );
855 	cgs.media.bloodTrailShader = trap_R_RegisterShader( "bloodTrail" );
856 	cgs.media.lagometerShader = trap_R_RegisterShader("lagometer" );
857 	cgs.media.connectionShader = trap_R_RegisterShader( "disconnected" );
858 
859 	cgs.media.waterBubbleShader = trap_R_RegisterShader( "waterBubble" );
860 
861 	cgs.media.tracerShader = trap_R_RegisterShader( "gfx/misc/tracer" );
862 	cgs.media.selectShader = trap_R_RegisterShader( "gfx/2d/select" );
863 
864 	for ( i = 0 ; i < NUM_CROSSHAIRS ; i++ ) {
865 		cgs.media.crosshairShader[i] = trap_R_RegisterShader( va("gfx/2d/crosshair%c", 'a'+i) );
866 	}
867 
868 	cgs.media.backTileShader = trap_R_RegisterShader( "gfx/2d/backtile" );
869 	cgs.media.noammoShader = trap_R_RegisterShader( "icons/noammo" );
870 
871 	// powerup shaders
872 	cgs.media.quadShader = trap_R_RegisterShader("powerups/quad" );
873 	cgs.media.quadWeaponShader = trap_R_RegisterShader("powerups/quadWeapon" );
874 	cgs.media.battleSuitShader = trap_R_RegisterShader("powerups/battleSuit" );
875 	cgs.media.battleWeaponShader = trap_R_RegisterShader("powerups/battleWeapon" );
876 	cgs.media.invisShader = trap_R_RegisterShader("powerups/invisibility" );
877 	cgs.media.regenShader = trap_R_RegisterShader("powerups/regen" );
878 	cgs.media.hastePuffShader = trap_R_RegisterShader("hasteSmokePuff" );
879 
880 #ifdef MISSIONPACK
881 	if ( cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF || cgs.gametype == GT_HARVESTER || cg_buildScript.integer ) {
882 #else
883 	if ( cgs.gametype == GT_CTF || cg_buildScript.integer ) {
884 #endif
885 		cgs.media.redCubeModel = trap_R_RegisterModel( "models/powerups/orb/r_orb.md3" );
886 		cgs.media.blueCubeModel = trap_R_RegisterModel( "models/powerups/orb/b_orb.md3" );
887 		cgs.media.redCubeIcon = trap_R_RegisterShader( "icons/skull_red" );
888 		cgs.media.blueCubeIcon = trap_R_RegisterShader( "icons/skull_blue" );
889 	}
890 
891 #ifdef MISSIONPACK
892 	if ( cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF || cgs.gametype == GT_HARVESTER || cg_buildScript.integer ) {
893 #else
894 	if ( cgs.gametype == GT_CTF || cg_buildScript.integer ) {
895 #endif
896 		cgs.media.redFlagModel = trap_R_RegisterModel( "models/flags/r_flag.md3" );
897 		cgs.media.blueFlagModel = trap_R_RegisterModel( "models/flags/b_flag.md3" );
898 		cgs.media.redFlagShader[0] = trap_R_RegisterShaderNoMip( "icons/iconf_red1" );
899 		cgs.media.redFlagShader[1] = trap_R_RegisterShaderNoMip( "icons/iconf_red2" );
900 		cgs.media.redFlagShader[2] = trap_R_RegisterShaderNoMip( "icons/iconf_red3" );
901 		cgs.media.blueFlagShader[0] = trap_R_RegisterShaderNoMip( "icons/iconf_blu1" );
902 		cgs.media.blueFlagShader[1] = trap_R_RegisterShaderNoMip( "icons/iconf_blu2" );
903 		cgs.media.blueFlagShader[2] = trap_R_RegisterShaderNoMip( "icons/iconf_blu3" );
904 #ifdef MISSIONPACK
905 		cgs.media.flagPoleModel = trap_R_RegisterModel( "models/flag2/flagpole.md3" );
906 		cgs.media.flagFlapModel = trap_R_RegisterModel( "models/flag2/flagflap3.md3" );
907 
908 		cgs.media.redFlagFlapSkin = trap_R_RegisterSkin( "models/flag2/red.skin" );
909 		cgs.media.blueFlagFlapSkin = trap_R_RegisterSkin( "models/flag2/blue.skin" );
910 		cgs.media.neutralFlagFlapSkin = trap_R_RegisterSkin( "models/flag2/white.skin" );
911 
912 		cgs.media.redFlagBaseModel = trap_R_RegisterModel( "models/mapobjects/flagbase/red_base.md3" );
913 		cgs.media.blueFlagBaseModel = trap_R_RegisterModel( "models/mapobjects/flagbase/blue_base.md3" );
914 		cgs.media.neutralFlagBaseModel = trap_R_RegisterModel( "models/mapobjects/flagbase/ntrl_base.md3" );
915 #endif
916 	}
917 
918 #ifdef MISSIONPACK
919 	if ( cgs.gametype == GT_1FCTF || cg_buildScript.integer ) {
920 		cgs.media.neutralFlagModel = trap_R_RegisterModel( "models/flags/n_flag.md3" );
921 		cgs.media.flagShader[0] = trap_R_RegisterShaderNoMip( "icons/iconf_neutral1" );
922 		cgs.media.flagShader[1] = trap_R_RegisterShaderNoMip( "icons/iconf_red2" );
923 		cgs.media.flagShader[2] = trap_R_RegisterShaderNoMip( "icons/iconf_blu2" );
924 		cgs.media.flagShader[3] = trap_R_RegisterShaderNoMip( "icons/iconf_neutral3" );
925 	}
926 
927 	if ( cgs.gametype == GT_OBELISK || cg_buildScript.integer ) {
928 		cgs.media.overloadBaseModel = trap_R_RegisterModel( "models/powerups/overload_base.md3" );
929 		cgs.media.overloadTargetModel = trap_R_RegisterModel( "models/powerups/overload_target.md3" );
930 		cgs.media.overloadLightsModel = trap_R_RegisterModel( "models/powerups/overload_lights.md3" );
931 		cgs.media.overloadEnergyModel = trap_R_RegisterModel( "models/powerups/overload_energy.md3" );
932 	}
933 
934 	if ( cgs.gametype == GT_HARVESTER || cg_buildScript.integer ) {
935 		cgs.media.harvesterModel = trap_R_RegisterModel( "models/powerups/harvester/harvester.md3" );
936 		cgs.media.harvesterRedSkin = trap_R_RegisterSkin( "models/powerups/harvester/red.skin" );
937 		cgs.media.harvesterBlueSkin = trap_R_RegisterSkin( "models/powerups/harvester/blue.skin" );
938 		cgs.media.harvesterNeutralModel = trap_R_RegisterModel( "models/powerups/obelisk/obelisk.md3" );
939 	}
940 
941 	cgs.media.redKamikazeShader = trap_R_RegisterShader( "models/weaphits/kamikred" );
942 	cgs.media.dustPuffShader = trap_R_RegisterShader("hasteSmokePuff" );
943 #endif
944 
945 	if ( cgs.gametype >= GT_TEAM || cg_buildScript.integer ) {
946 		cgs.media.friendShader = trap_R_RegisterShader( "sprites/foe" );
947 		cgs.media.redQuadShader = trap_R_RegisterShader("powerups/blueflag" );
948 		cgs.media.teamStatusBar = trap_R_RegisterShader( "gfx/2d/colorbar.tga" );
949 #ifdef MISSIONPACK
950 		cgs.media.blueKamikazeShader = trap_R_RegisterShader( "models/weaphits/kamikblu" );
951 #endif
952 	}
953 
954 	cgs.media.armorModel = trap_R_RegisterModel( "models/powerups/armor/armor_yel.md3" );
955 	cgs.media.armorIcon  = trap_R_RegisterShaderNoMip( "icons/iconr_yellow" );
956 
957 	cgs.media.machinegunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/m_shell.md3" );
958 	cgs.media.shotgunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/s_shell.md3" );
959 
960 	cgs.media.gibAbdomen = trap_R_RegisterModel( "models/gibs/abdomen.md3" );
961 	cgs.media.gibArm = trap_R_RegisterModel( "models/gibs/arm.md3" );
962 	cgs.media.gibChest = trap_R_RegisterModel( "models/gibs/chest.md3" );
963 	cgs.media.gibFist = trap_R_RegisterModel( "models/gibs/fist.md3" );
964 	cgs.media.gibFoot = trap_R_RegisterModel( "models/gibs/foot.md3" );
965 	cgs.media.gibForearm = trap_R_RegisterModel( "models/gibs/forearm.md3" );
966 	cgs.media.gibIntestine = trap_R_RegisterModel( "models/gibs/intestine.md3" );
967 	cgs.media.gibLeg = trap_R_RegisterModel( "models/gibs/leg.md3" );
968 	cgs.media.gibSkull = trap_R_RegisterModel( "models/gibs/skull.md3" );
969 	cgs.media.gibBrain = trap_R_RegisterModel( "models/gibs/brain.md3" );
970 
971 	cgs.media.smoke2 = trap_R_RegisterModel( "models/weapons2/shells/s_shell.md3" );
972 
973 	cgs.media.balloonShader = trap_R_RegisterShader( "sprites/balloon3" );
974 
975 	cgs.media.bloodExplosionShader = trap_R_RegisterShader( "bloodExplosion" );
976 
977 	cgs.media.bulletFlashModel = trap_R_RegisterModel("models/weaphits/bullet.md3");
978 	cgs.media.ringFlashModel = trap_R_RegisterModel("models/weaphits/ring02.md3");
979 	cgs.media.dishFlashModel = trap_R_RegisterModel("models/weaphits/boom01.md3");
980 #ifdef MISSIONPACK
981 	cgs.media.teleportEffectModel = trap_R_RegisterModel( "models/powerups/pop.md3" );
982 #else
983 	cgs.media.teleportEffectModel = trap_R_RegisterModel( "models/misc/telep.md3" );
984 	cgs.media.teleportEffectShader = trap_R_RegisterShader( "teleportEffect" );
985 #endif
986 #ifdef MISSIONPACK
987 	cgs.media.kamikazeEffectModel = trap_R_RegisterModel( "models/weaphits/kamboom2.md3" );
988 	cgs.media.kamikazeShockWave = trap_R_RegisterModel( "models/weaphits/kamwave.md3" );
989 	cgs.media.kamikazeHeadModel = trap_R_RegisterModel( "models/powerups/kamikazi.md3" );
990 	cgs.media.kamikazeHeadTrail = trap_R_RegisterModel( "models/powerups/trailtest.md3" );
991 	cgs.media.guardPowerupModel = trap_R_RegisterModel( "models/powerups/guard_player.md3" );
992 	cgs.media.scoutPowerupModel = trap_R_RegisterModel( "models/powerups/scout_player.md3" );
993 	cgs.media.doublerPowerupModel = trap_R_RegisterModel( "models/powerups/doubler_player.md3" );
994 	cgs.media.ammoRegenPowerupModel = trap_R_RegisterModel( "models/powerups/ammo_player.md3" );
995 	cgs.media.invulnerabilityImpactModel = trap_R_RegisterModel( "models/powerups/shield/impact.md3" );
996 	cgs.media.invulnerabilityJuicedModel = trap_R_RegisterModel( "models/powerups/shield/juicer.md3" );
997 	cgs.media.medkitUsageModel = trap_R_RegisterModel( "models/powerups/regen.md3" );
998 	cgs.media.heartShader = trap_R_RegisterShaderNoMip( "ui/assets/statusbar/selectedhealth.tga" );
999 
1000 #endif
1001 
1002 	cgs.media.invulnerabilityPowerupModel = trap_R_RegisterModel( "models/powerups/shield/shield.md3" );
1003 	cgs.media.medalImpressive = trap_R_RegisterShaderNoMip( "medal_impressive" );
1004 	cgs.media.medalExcellent = trap_R_RegisterShaderNoMip( "medal_excellent" );
1005 	cgs.media.medalGauntlet = trap_R_RegisterShaderNoMip( "medal_gauntlet" );
1006 	cgs.media.medalDefend = trap_R_RegisterShaderNoMip( "medal_defend" );
1007 	cgs.media.medalAssist = trap_R_RegisterShaderNoMip( "medal_assist" );
1008 	cgs.media.medalCapture = trap_R_RegisterShaderNoMip( "medal_capture" );
1009 
1010 
1011 	memset( cg_items, 0, sizeof( cg_items ) );
1012 	memset( cg_weapons, 0, sizeof( cg_weapons ) );
1013 
1014 	// only register the items that the server says we need
1015 	Q_strncpyz(items, CG_ConfigString(CS_ITEMS), sizeof(items));
1016 
1017 	for ( i = 1 ; i < bg_numItems ; i++ ) {
1018 		if ( items[ i ] == '1' || cg_buildScript.integer ) {
1019 			CG_LoadingItem( i );
1020 			CG_RegisterItemVisuals( i );
1021 		}
1022 	}
1023 
1024 	// wall marks
1025 	cgs.media.bulletMarkShader = trap_R_RegisterShader( "gfx/damage/bullet_mrk" );
1026 	cgs.media.burnMarkShader = trap_R_RegisterShader( "gfx/damage/burn_med_mrk" );
1027 	cgs.media.holeMarkShader = trap_R_RegisterShader( "gfx/damage/hole_lg_mrk" );
1028 	cgs.media.energyMarkShader = trap_R_RegisterShader( "gfx/damage/plasma_mrk" );
1029 	cgs.media.shadowMarkShader = trap_R_RegisterShader( "markShadow" );
1030 	cgs.media.wakeMarkShader = trap_R_RegisterShader( "wake" );
1031 	cgs.media.bloodMarkShader = trap_R_RegisterShader( "bloodMark" );
1032 
1033 	// register the inline models
1034 	cgs.numInlineModels = trap_CM_NumInlineModels();
1035 	for ( i = 1 ; i < cgs.numInlineModels ; i++ ) {
1036 		char	name[10];
1037 		vec3_t			mins, maxs;
1038 		int				j;
1039 
1040 		Com_sprintf( name, sizeof(name), "*%i", i );
1041 		cgs.inlineDrawModel[i] = trap_R_RegisterModel( name );
1042 		trap_R_ModelBounds( cgs.inlineDrawModel[i], mins, maxs );
1043 		for ( j = 0 ; j < 3 ; j++ ) {
1044 			cgs.inlineModelMidpoints[i][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
1045 		}
1046 	}
1047 
1048 	// register all the server specified models
1049 	for (i=1 ; i<MAX_MODELS ; i++) {
1050 		const char		*modelName;
1051 
1052 		modelName = CG_ConfigString( CS_MODELS+i );
1053 		if ( !modelName[0] ) {
1054 			break;
1055 		}
1056 		cgs.gameModels[i] = trap_R_RegisterModel( modelName );
1057 	}
1058 
1059 #ifdef MISSIONPACK
1060 	// new stuff
1061 	cgs.media.patrolShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/patrol.tga");
1062 	cgs.media.assaultShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/assault.tga");
1063 	cgs.media.campShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/camp.tga");
1064 	cgs.media.followShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/follow.tga");
1065 	cgs.media.defendShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/defend.tga");
1066 	cgs.media.teamLeaderShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/team_leader.tga");
1067 	cgs.media.retrieveShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/retrieve.tga");
1068 	cgs.media.escortShader = trap_R_RegisterShaderNoMip("ui/assets/statusbar/escort.tga");
1069 	cgs.media.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" );
1070 	cgs.media.sizeCursor = trap_R_RegisterShaderNoMip( "ui/assets/sizecursor.tga" );
1071 	cgs.media.selectCursor = trap_R_RegisterShaderNoMip( "ui/assets/selectcursor.tga" );
1072 	cgs.media.flagShaders[0] = trap_R_RegisterShaderNoMip("ui/assets/statusbar/flag_in_base.tga");
1073 	cgs.media.flagShaders[1] = trap_R_RegisterShaderNoMip("ui/assets/statusbar/flag_capture.tga");
1074 	cgs.media.flagShaders[2] = trap_R_RegisterShaderNoMip("ui/assets/statusbar/flag_missing.tga");
1075 
1076 	trap_R_RegisterModel( "models/players/james/lower.md3" );
1077 	trap_R_RegisterModel( "models/players/james/upper.md3" );
1078 	trap_R_RegisterModel( "models/players/heads/james/james.md3" );
1079 
1080 	trap_R_RegisterModel( "models/players/janet/lower.md3" );
1081 	trap_R_RegisterModel( "models/players/janet/upper.md3" );
1082 	trap_R_RegisterModel( "models/players/heads/janet/janet.md3" );
1083 
1084 #endif
1085 	CG_ClearParticles ();
1086 /*
1087 	for (i=1; i<MAX_PARTICLES_AREAS; i++)
1088 	{
1089 		{
1090 			int rval;
1091 
1092 			rval = CG_NewParticleArea ( CS_PARTICLES + i);
1093 			if (!rval)
1094 				break;
1095 		}
1096 	}
1097 */
1098 }
1099 
1100 
1101 
1102 /*
1103 =======================
1104 CG_BuildSpectatorString
1105 
1106 =======================
1107 */
1108 void CG_BuildSpectatorString(void) {
1109 	int i;
1110 	cg.spectatorList[0] = 0;
1111 	for (i = 0; i < MAX_CLIENTS; i++) {
1112 		if (cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_SPECTATOR ) {
1113 			Q_strcat(cg.spectatorList, sizeof(cg.spectatorList), va("%s     ", cgs.clientinfo[i].name));
1114 		}
1115 	}
1116 	i = strlen(cg.spectatorList);
1117 	if (i != cg.spectatorLen) {
1118 		cg.spectatorLen = i;
1119 		cg.spectatorWidth = -1;
1120 	}
1121 }
1122 
1123 
1124 /*
1125 ===================
1126 CG_RegisterClients
1127 ===================
1128 */
1129 static void CG_RegisterClients( void ) {
1130 	int		i;
1131 
1132 	CG_LoadingClient(cg.clientNum);
1133 	CG_NewClientInfo(cg.clientNum);
1134 
1135 	for (i=0 ; i<MAX_CLIENTS ; i++) {
1136 		const char		*clientInfo;
1137 
1138 		if (cg.clientNum == i) {
1139 			continue;
1140 		}
1141 
1142 		clientInfo = CG_ConfigString( CS_PLAYERS+i );
1143 		if ( !clientInfo[0]) {
1144 			continue;
1145 		}
1146 		CG_LoadingClient( i );
1147 		CG_NewClientInfo( i );
1148 	}
1149 	CG_BuildSpectatorString();
1150 }
1151 
1152 //===========================================================================
1153 
1154 /*
1155 =================
1156 CG_ConfigString
1157 =================
1158 */
1159 const char *CG_ConfigString( int index ) {
1160 	if ( index < 0 || index >= MAX_CONFIGSTRINGS ) {
1161 		CG_Error( "CG_ConfigString: bad index: %i", index );
1162 	}
1163 	return cgs.gameState.stringData + cgs.gameState.stringOffsets[ index ];
1164 }
1165 
1166 //==================================================================
1167 
1168 /*
1169 ======================
1170 CG_StartMusic
1171 
1172 ======================
1173 */
1174 void CG_StartMusic( void ) {
1175 	char	*s;
1176 	char	parm1[MAX_QPATH], parm2[MAX_QPATH];
1177 
1178 	// start the background music
1179 	s = (char *)CG_ConfigString( CS_MUSIC );
1180 	Q_strncpyz( parm1, Com_Parse( &s ), sizeof( parm1 ) );
1181 	Q_strncpyz( parm2, Com_Parse( &s ), sizeof( parm2 ) );
1182 
1183 	trap_S_StartBackgroundTrack( parm1, parm2 );
1184 }
1185 #ifdef MISSIONPACK
1186 char *CG_GetMenuBuffer(const char *filename) {
1187 	int	len;
1188 	fileHandle_t	f;
1189 	static char buf[MAX_MENUFILE];
1190 
1191 	len = trap_FS_FOpenFile( filename, &f, FS_READ );
1192 	if ( !f ) {
1193 		trap_Print( va( S_COLOR_RED "menu file not found: %s, using default\n", filename ) );
1194 		return NULL;
1195 	}
1196 	if ( len >= MAX_MENUFILE ) {
1197 		trap_Print( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", filename, len, MAX_MENUFILE ) );
1198 		trap_FS_FCloseFile( f );
1199 		return NULL;
1200 	}
1201 
1202 	trap_FS_Read( buf, len, f );
1203 	buf[len] = 0;
1204 	trap_FS_FCloseFile( f );
1205 
1206 	return buf;
1207 }
1208 
1209 //
1210 // ==============================
1211 // new hud stuff ( mission pack )
1212 // ==============================
1213 //
1214 qboolean CG_Asset_Parse(int handle) {
1215 	pc_token_t token;
1216 	const char *tempStr;
1217 
1218 	if (!trap_PC_ReadToken(handle, &token))
1219 		return qfalse;
1220 	if (Q_stricmp(token.string, "{") != 0) {
1221 		return qfalse;
1222 	}
1223 
1224 	while ( 1 ) {
1225 		if (!trap_PC_ReadToken(handle, &token))
1226 			return qfalse;
1227 
1228 		if (Q_stricmp(token.string, "}") == 0) {
1229 			return qtrue;
1230 		}
1231 
1232 		// font
1233 		if (Q_stricmp(token.string, "font") == 0) {
1234 			int pointSize;
1235 			if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle, &pointSize)) {
1236 				return qfalse;
1237 			}
1238 			cgDC.registerFont(tempStr, pointSize, &cgDC.Assets.textFont);
1239 			continue;
1240 		}
1241 
1242 		// smallFont
1243 		if (Q_stricmp(token.string, "smallFont") == 0) {
1244 			int pointSize;
1245 			if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle, &pointSize)) {
1246 				return qfalse;
1247 			}
1248 			cgDC.registerFont(tempStr, pointSize, &cgDC.Assets.smallFont);
1249 			continue;
1250 		}
1251 
1252 		// font
1253 		if (Q_stricmp(token.string, "bigfont") == 0) {
1254 			int pointSize;
1255 			if (!PC_String_Parse(handle, &tempStr) || !PC_Int_Parse(handle, &pointSize)) {
1256 				return qfalse;
1257 			}
1258 			cgDC.registerFont(tempStr, pointSize, &cgDC.Assets.bigFont);
1259 			continue;
1260 		}
1261 
1262 		// gradientbar
1263 		if (Q_stricmp(token.string, "gradientbar") == 0) {
1264 			if (!PC_String_Parse(handle, &tempStr)) {
1265 				return qfalse;
1266 			}
1267 			cgDC.Assets.gradientBar = trap_R_RegisterShaderNoMip(tempStr);
1268 			continue;
1269 		}
1270 
1271 		// enterMenuSound
1272 		if (Q_stricmp(token.string, "menuEnterSound") == 0) {
1273 			if (!PC_String_Parse(handle, &tempStr)) {
1274 				return qfalse;
1275 			}
1276 			cgDC.Assets.menuEnterSound = trap_S_RegisterSound( tempStr, qfalse );
1277 			continue;
1278 		}
1279 
1280 		// exitMenuSound
1281 		if (Q_stricmp(token.string, "menuExitSound") == 0) {
1282 			if (!PC_String_Parse(handle, &tempStr)) {
1283 				return qfalse;
1284 			}
1285 			cgDC.Assets.menuExitSound = trap_S_RegisterSound( tempStr, qfalse );
1286 			continue;
1287 		}
1288 
1289 		// itemFocusSound
1290 		if (Q_stricmp(token.string, "itemFocusSound") == 0) {
1291 			if (!PC_String_Parse(handle, &tempStr)) {
1292 				return qfalse;
1293 			}
1294 			cgDC.Assets.itemFocusSound = trap_S_RegisterSound( tempStr, qfalse );
1295 			continue;
1296 		}
1297 
1298 		// menuBuzzSound
1299 		if (Q_stricmp(token.string, "menuBuzzSound") == 0) {
1300 			if (!PC_String_Parse(handle, &tempStr)) {
1301 				return qfalse;
1302 			}
1303 			cgDC.Assets.menuBuzzSound = trap_S_RegisterSound( tempStr, qfalse );
1304 			continue;
1305 		}
1306 
1307 		if (Q_stricmp(token.string, "cursor") == 0) {
1308 			if (!PC_String_Parse(handle, &cgDC.Assets.cursorStr)) {
1309 				return qfalse;
1310 			}
1311 			cgDC.Assets.cursor = trap_R_RegisterShaderNoMip( cgDC.Assets.cursorStr);
1312 			continue;
1313 		}
1314 
1315 		if (Q_stricmp(token.string, "fadeClamp") == 0) {
1316 			if (!PC_Float_Parse(handle, &cgDC.Assets.fadeClamp)) {
1317 				return qfalse;
1318 			}
1319 			continue;
1320 		}
1321 
1322 		if (Q_stricmp(token.string, "fadeCycle") == 0) {
1323 			if (!PC_Int_Parse(handle, &cgDC.Assets.fadeCycle)) {
1324 				return qfalse;
1325 			}
1326 			continue;
1327 		}
1328 
1329 		if (Q_stricmp(token.string, "fadeAmount") == 0) {
1330 			if (!PC_Float_Parse(handle, &cgDC.Assets.fadeAmount)) {
1331 				return qfalse;
1332 			}
1333 			continue;
1334 		}
1335 
1336 		if (Q_stricmp(token.string, "shadowX") == 0) {
1337 			if (!PC_Float_Parse(handle, &cgDC.Assets.shadowX)) {
1338 				return qfalse;
1339 			}
1340 			continue;
1341 		}
1342 
1343 		if (Q_stricmp(token.string, "shadowY") == 0) {
1344 			if (!PC_Float_Parse(handle, &cgDC.Assets.shadowY)) {
1345 				return qfalse;
1346 			}
1347 			continue;
1348 		}
1349 
1350 		if (Q_stricmp(token.string, "shadowColor") == 0) {
1351 			if (!PC_Color_Parse(handle, &cgDC.Assets.shadowColor)) {
1352 				return qfalse;
1353 			}
1354 			cgDC.Assets.shadowFadeClamp = cgDC.Assets.shadowColor[3];
1355 			continue;
1356 		}
1357 	}
1358 	return qfalse;
1359 }
1360 
1361 void CG_ParseMenu(const char *menuFile) {
1362 	pc_token_t token;
1363 	int handle;
1364 
1365 	handle = trap_PC_LoadSource(menuFile);
1366 	if (!handle)
1367 		handle = trap_PC_LoadSource("ui/testhud.menu");
1368 	if (!handle)
1369 		return;
1370 
1371 	while ( 1 ) {
1372 		if (!trap_PC_ReadToken( handle, &token )) {
1373 			break;
1374 		}
1375 
1376 		//if ( Q_stricmp( token, "{" ) ) {
1377 		//	Com_Printf( "Missing { in menu file\n" );
1378 		//	break;
1379 		//}
1380 
1381 		//if ( menuCount == MAX_MENUS ) {
1382 		//	Com_Printf( "Too many menus!\n" );
1383 		//	break;
1384 		//}
1385 
1386 		if ( token.string[0] == '}' ) {
1387 			break;
1388 		}
1389 
1390 		if (Q_stricmp(token.string, "assetGlobalDef") == 0) {
1391 			if (CG_Asset_Parse(handle)) {
1392 				continue;
1393 			} else {
1394 				break;
1395 			}
1396 		}
1397 
1398 
1399 		if (Q_stricmp(token.string, "menudef") == 0) {
1400 			// start a new menu
1401 			Menu_New(handle);
1402 		}
1403 	}
1404 	trap_PC_FreeSource(handle);
1405 }
1406 
1407 qboolean CG_Load_Menu(char **p) {
1408 	char *token;
1409 
1410 	token = Com_ParseExt(p, qtrue);
1411 
1412 	if (token[0] != '{') {
1413 		return qfalse;
1414 	}
1415 
1416 	while ( 1 ) {
1417 
1418 		token = Com_ParseExt(p, qtrue);
1419 
1420 		if (Q_stricmp(token, "}") == 0) {
1421 			return qtrue;
1422 		}
1423 
1424 		if ( !token || token[0] == 0 ) {
1425 			return qfalse;
1426 		}
1427 
1428 		CG_ParseMenu(token);
1429 	}
1430 	return qfalse;
1431 }
1432 
1433 
1434 
1435 void CG_LoadMenus(const char *menuFile) {
1436 	char	*token;
1437 	char *p;
1438 	int	len, start;
1439 	fileHandle_t	f;
1440 	static char buf[MAX_MENUDEFFILE];
1441 
1442 	start = trap_Milliseconds();
1443 
1444 	len = trap_FS_FOpenFile( menuFile, &f, FS_READ );
1445 	if ( !f ) {
1446 		trap_Error( va( S_COLOR_YELLOW "menu file not found: %s, using default\n", menuFile ) );
1447 		len = trap_FS_FOpenFile( "ui/hud.txt", &f, FS_READ );
1448 		if (!f) {
1449 			trap_Error( va( S_COLOR_RED "default menu file not found: ui/hud.txt, unable to continue!\n") );
1450 		}
1451 	}
1452 
1453 	if ( len >= MAX_MENUDEFFILE ) {
1454 		trap_Error( va( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", menuFile, len, MAX_MENUDEFFILE ) );
1455 		trap_FS_FCloseFile( f );
1456 		return;
1457 	}
1458 
1459 	trap_FS_Read( buf, len, f );
1460 	buf[len] = 0;
1461 	trap_FS_FCloseFile( f );
1462 
1463 	COM_Compress(buf);
1464 
1465 	Menu_Reset();
1466 
1467 	p = buf;
1468 
1469 	while ( 1 ) {
1470 		token = Com_ParseExt( &p, qtrue );
1471 		if( !token || token[0] == 0 || token[0] == '}') {
1472 			break;
1473 		}
1474 
1475 		//if ( Q_stricmp( token, "{" ) ) {
1476 		//	Com_Printf( "Missing { in menu file\n" );
1477 		//	break;
1478 		//}
1479 
1480 		//if ( menuCount == MAX_MENUS ) {
1481 		//	Com_Printf( "Too many menus!\n" );
1482 		//	break;
1483 		//}
1484 
1485 		if ( Q_stricmp( token, "}" ) == 0 ) {
1486 			break;
1487 		}
1488 
1489 		if (Q_stricmp(token, "loadmenu") == 0) {
1490 			if (CG_Load_Menu(&p)) {
1491 				continue;
1492 			} else {
1493 				break;
1494 			}
1495 		}
1496 	}
1497 
1498 	Com_Printf("UI menu load time = %d milli seconds\n", trap_Milliseconds() - start);
1499 
1500 }
1501 
1502 
1503 
1504 static qboolean CG_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key) {
1505 	return qfalse;
1506 }
1507 
1508 
1509 static int CG_FeederCount(float feederID) {
1510 	int i, count;
1511 	count = 0;
1512 	if (feederID == FEEDER_REDTEAM_LIST) {
1513 		for (i = 0; i < cg.numScores; i++) {
1514 			if (cg.scores[i].team == TEAM_RED) {
1515 				count++;
1516 			}
1517 		}
1518 	} else if (feederID == FEEDER_BLUETEAM_LIST) {
1519 		for (i = 0; i < cg.numScores; i++) {
1520 			if (cg.scores[i].team == TEAM_BLUE) {
1521 				count++;
1522 			}
1523 		}
1524 	} else if (feederID == FEEDER_SCOREBOARD) {
1525 		return cg.numScores;
1526 	}
1527 	return count;
1528 }
1529 
1530 
1531 void CG_SetScoreSelection(void *p) {
1532 	menuDef_t *menu = (menuDef_t*)p;
1533 	playerState_t *ps = &cg.snap->ps;
1534 	int i, red, blue;
1535 	red = blue = 0;
1536 	for (i = 0; i < cg.numScores; i++) {
1537 		if (cg.scores[i].team == TEAM_RED) {
1538 			red++;
1539 		} else if (cg.scores[i].team == TEAM_BLUE) {
1540 			blue++;
1541 		}
1542 		if (ps->clientNum == cg.scores[i].client) {
1543 			cg.selectedScore = i;
1544 		}
1545 	}
1546 
1547 	if (menu == NULL) {
1548 		// just interested in setting the selected score
1549 		return;
1550 	}
1551 
1552 	if ( cgs.gametype >= GT_TEAM ) {
1553 		int feeder = FEEDER_REDTEAM_LIST;
1554 		i = red;
1555 		if (cg.scores[cg.selectedScore].team == TEAM_BLUE) {
1556 			feeder = FEEDER_BLUETEAM_LIST;
1557 			i = blue;
1558 		}
1559 		Menu_SetFeederSelection(menu, feeder, i, NULL);
1560 	} else {
1561 		Menu_SetFeederSelection(menu, FEEDER_SCOREBOARD, cg.selectedScore, NULL);
1562 	}
1563 }
1564 
1565 // FIXME: might need to cache this info
1566 static clientInfo_t * CG_InfoFromScoreIndex(int index, int team, int *scoreIndex) {
1567 	int i, count;
1568 	if ( cgs.gametype >= GT_TEAM ) {
1569 		count = 0;
1570 		for (i = 0; i < cg.numScores; i++) {
1571 			if (cg.scores[i].team == team) {
1572 				if (count == index) {
1573 					*scoreIndex = i;
1574 					return &cgs.clientinfo[cg.scores[i].client];
1575 				}
1576 				count++;
1577 			}
1578 		}
1579 	}
1580 	*scoreIndex = index;
1581 	return &cgs.clientinfo[ cg.scores[index].client ];
1582 }
1583 
1584 static const char *CG_FeederItemText(float feederID, int index, int column, qhandle_t *handle) {
1585 	gitem_t *item;
1586 	int scoreIndex = 0;
1587 	clientInfo_t *info = NULL;
1588 	int team = -1;
1589 	score_t *sp = NULL;
1590 
1591 	*handle = -1;
1592 
1593 	if (feederID == FEEDER_REDTEAM_LIST) {
1594 		team = TEAM_RED;
1595 	} else if (feederID == FEEDER_BLUETEAM_LIST) {
1596 		team = TEAM_BLUE;
1597 	}
1598 
1599 	info = CG_InfoFromScoreIndex(index, team, &scoreIndex);
1600 	sp = &cg.scores[scoreIndex];
1601 
1602 	if (info && info->infoValid) {
1603 		switch (column) {
1604 			case 0:
1605 				if ( info->powerups & ( 1 << PW_NEUTRALFLAG ) ) {
1606 					item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
1607 					*handle = cg_items[ ITEM_INDEX(item) ].icon;
1608 				} else if ( info->powerups & ( 1 << PW_REDFLAG ) ) {
1609 					item = BG_FindItemForPowerup( PW_REDFLAG );
1610 					*handle = cg_items[ ITEM_INDEX(item) ].icon;
1611 				} else if ( info->powerups & ( 1 << PW_BLUEFLAG ) ) {
1612 					item = BG_FindItemForPowerup( PW_BLUEFLAG );
1613 					*handle = cg_items[ ITEM_INDEX(item) ].icon;
1614 				} else {
1615 					if ( info->botSkill > 0 && info->botSkill <= 5 ) {
1616 						*handle = cgs.media.botSkillShaders[ info->botSkill - 1 ];
1617 					} else if ( info->handicap < 100 ) {
1618 					return va("%i", info->handicap );
1619 					}
1620 				}
1621 			break;
1622 			case 1:
1623 				if (team == -1) {
1624 					return "";
1625 				} else {
1626 					*handle = CG_StatusHandle(info->teamTask);
1627 				}
1628 		  break;
1629 			case 2:
1630 				if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << sp->client ) ) {
1631 					return "Ready";
1632 				}
1633 				if (team == -1) {
1634 					if (cgs.gametype == GT_TOURNAMENT) {
1635 						return va("%i/%i", info->wins, info->losses);
1636 					} else if (info->infoValid && info->team == TEAM_SPECTATOR ) {
1637 						return "Spectator";
1638 					} else {
1639 						return "";
1640 					}
1641 				} else {
1642 					if (info->teamLeader) {
1643 						return "Leader";
1644 					}
1645 				}
1646 			break;
1647 			case 3:
1648 				return info->name;
1649 			break;
1650 			case 4:
1651 				return va("%i", info->score);
1652 			break;
1653 			case 5:
1654 				return va("%4i", sp->time);
1655 			break;
1656 			case 6:
1657 				if ( sp->ping == -1 ) {
1658 					return "connecting";
1659 				}
1660 				return va("%4i", sp->ping);
1661 			break;
1662 		}
1663 	}
1664 
1665 	return "";
1666 }
1667 
1668 static qhandle_t CG_FeederItemImage(float feederID, int index) {
1669 	return 0;
1670 }
1671 
1672 static void CG_FeederSelection(float feederID, int index) {
1673 	if ( cgs.gametype >= GT_TEAM ) {
1674 		int i, count;
1675 		int team = (feederID == FEEDER_REDTEAM_LIST) ? TEAM_RED : TEAM_BLUE;
1676 		count = 0;
1677 		for (i = 0; i < cg.numScores; i++) {
1678 			if (cg.scores[i].team == team) {
1679 				if (index == count) {
1680 					cg.selectedScore = i;
1681 				}
1682 				count++;
1683 			}
1684 		}
1685 	} else {
1686 		cg.selectedScore = index;
1687 	}
1688 }
1689 #endif
1690 
1691 #ifdef MISSIONPACK
1692 static float CG_Cvar_Get(const char *cvar) {
1693 	char buff[128];
1694 	memset(buff, 0, sizeof(buff));
1695 	trap_Cvar_VariableStringBuffer(cvar, buff, sizeof(buff));
1696 	return atof(buff);
1697 }
1698 #endif
1699 
1700 #ifdef MISSIONPACK
1701 void CG_Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style) {
1702 	CG_Text_Paint(x, y, scale, color, text, 0, limit, style);
1703 }
1704 
1705 static int CG_OwnerDrawWidth(int ownerDraw, float scale) {
1706 	switch (ownerDraw) {
1707 	  case CG_GAME_TYPE:
1708 			return CG_Text_Width(CG_GameTypeString(), scale, 0);
1709 	  case CG_GAME_STATUS:
1710 			return CG_Text_Width(CG_GetGameStatusText(), scale, 0);
1711 			break;
1712 	  case CG_KILLER:
1713 			return CG_Text_Width(CG_GetKillerText(), scale, 0);
1714 			break;
1715 	  case CG_RED_NAME:
1716 			return CG_Text_Width(cg_redTeamName.string, scale, 0);
1717 			break;
1718 	  case CG_BLUE_NAME:
1719 			return CG_Text_Width(cg_blueTeamName.string, scale, 0);
1720 			break;
1721 
1722 
1723 	}
1724 	return 0;
1725 }
1726 
1727 static int CG_PlayCinematic(const char *name, float x, float y, float w, float h) {
1728   return trap_CIN_PlayCinematic(name, x, y, w, h, CIN_loop);
1729 }
1730 
1731 static void CG_StopCinematic(int handle) {
1732   trap_CIN_StopCinematic(handle);
1733 }
1734 
1735 static void CG_DrawCinematic(int handle, float x, float y, float w, float h) {
1736   trap_CIN_SetExtents(handle, x, y, w, h);
1737   trap_CIN_DrawCinematic(handle);
1738 }
1739 
1740 static void CG_RunCinematicFrame(int handle) {
1741   trap_CIN_RunCinematic(handle);
1742 }
1743 
1744 /*
1745 =================
1746 CG_LoadHudMenu();
1747 
1748 =================
1749 */
1750 void CG_LoadHudMenu( void ) {
1751 	char buff[1024];
1752 	const char *hudSet;
1753 
1754 	cgDC.registerShaderNoMip = &trap_R_RegisterShaderNoMip;
1755 	cgDC.setColor = &trap_R_SetColor;
1756 	cgDC.drawHandlePic = &CG_DrawPic;
1757 	cgDC.drawStretchPic = &trap_R_DrawStretchPic;
1758 	cgDC.drawText = &CG_Text_Paint;
1759 	cgDC.textWidth = &CG_Text_Width;
1760 	cgDC.textHeight = &CG_Text_Height;
1761 	cgDC.registerModel = &trap_R_RegisterModel;
1762 	cgDC.modelBounds = &trap_R_ModelBounds;
1763 	cgDC.fillRect = &CG_FillRect;
1764 	cgDC.drawRect = &CG_DrawRect;
1765 	cgDC.drawSides = &CG_DrawSides;
1766 	cgDC.drawTopBottom = &CG_DrawTopBottom;
1767 	cgDC.clearScene = &trap_R_ClearScene;
1768 	cgDC.addRefEntityToScene = &trap_R_AddRefEntityToScene;
1769 	cgDC.renderScene = &trap_R_RenderScene;
1770 	cgDC.registerFont = &trap_R_RegisterFont;
1771 	cgDC.ownerDrawItem = &CG_OwnerDraw;
1772 	cgDC.getValue = &CG_GetValue;
1773 	cgDC.ownerDrawVisible = &CG_OwnerDrawVisible;
1774 	cgDC.runScript = &CG_RunMenuScript;
1775 	cgDC.getTeamColor = &CG_GetTeamColor;
1776 	cgDC.setCVar = trap_Cvar_Set;
1777 	cgDC.getCVarString = trap_Cvar_VariableStringBuffer;
1778 	cgDC.getCVarValue = CG_Cvar_Get;
1779 	cgDC.drawTextWithCursor = &CG_Text_PaintWithCursor;
1780 	//cgDC.setOverstrikeMode = &trap_Key_SetOverstrikeMode;
1781 	//cgDC.getOverstrikeMode = &trap_Key_GetOverstrikeMode;
1782 	cgDC.startLocalSound = &trap_S_StartLocalSound;
1783 	cgDC.ownerDrawHandleKey = &CG_OwnerDrawHandleKey;
1784 	cgDC.feederCount = &CG_FeederCount;
1785 	cgDC.feederItemImage = &CG_FeederItemImage;
1786 	cgDC.feederItemText = &CG_FeederItemText;
1787 	cgDC.feederSelection = &CG_FeederSelection;
1788 	//cgDC.setBinding = &trap_Key_SetBinding;
1789 	//cgDC.getBindingBuf = &trap_Key_GetBindingBuf;
1790 	//cgDC.keynumToStringBuf = &trap_Key_KeynumToStringBuf;
1791 	//cgDC.executeText = &trap_Cmd_ExecuteText;
1792 	cgDC.Error = &Com_Error;
1793 	cgDC.Print = &Com_Printf;
1794 	cgDC.ownerDrawWidth = &CG_OwnerDrawWidth;
1795 	//cgDC.Pause = &CG_Pause;
1796 	cgDC.registerSound = &trap_S_RegisterSound;
1797 	cgDC.startBackgroundTrack = &trap_S_StartBackgroundTrack;
1798 	cgDC.stopBackgroundTrack = &trap_S_StopBackgroundTrack;
1799 	cgDC.playCinematic = &CG_PlayCinematic;
1800 	cgDC.stopCinematic = &CG_StopCinematic;
1801 	cgDC.drawCinematic = &CG_DrawCinematic;
1802 	cgDC.runCinematicFrame = &CG_RunCinematicFrame;
1803 
1804 	Init_Display(&cgDC);
1805 
1806 	Menu_Reset();
1807 
1808 	trap_Cvar_VariableStringBuffer("cg_hudFiles", buff, sizeof(buff));
1809 	hudSet = buff;
1810 	if (hudSet[0] == '\0') {
1811 		hudSet = "ui/hud.txt";
1812 	}
1813 
1814 	CG_LoadMenus(hudSet);
1815 }
1816 
1817 void CG_AssetCache( void ) {
1818 	//if (Assets.textFont == NULL) {
1819 	//  trap_R_RegisterFont("fonts/arial.ttf", 72, &Assets.textFont);
1820 	//}
1821 	//Assets.background = trap_R_RegisterShaderNoMip( ASSET_BACKGROUND );
1822 	//Com_Printf("Menu Size: %i bytes\n", sizeof(Menus));
1823 	cgDC.Assets.gradientBar = trap_R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
1824 	cgDC.Assets.fxBasePic = trap_R_RegisterShaderNoMip( ART_FX_BASE );
1825 	cgDC.Assets.fxPic[0] = trap_R_RegisterShaderNoMip( ART_FX_RED );
1826 	cgDC.Assets.fxPic[1] = trap_R_RegisterShaderNoMip( ART_FX_YELLOW );
1827 	cgDC.Assets.fxPic[2] = trap_R_RegisterShaderNoMip( ART_FX_GREEN );
1828 	cgDC.Assets.fxPic[3] = trap_R_RegisterShaderNoMip( ART_FX_TEAL );
1829 	cgDC.Assets.fxPic[4] = trap_R_RegisterShaderNoMip( ART_FX_BLUE );
1830 	cgDC.Assets.fxPic[5] = trap_R_RegisterShaderNoMip( ART_FX_CYAN );
1831 	cgDC.Assets.fxPic[6] = trap_R_RegisterShaderNoMip( ART_FX_WHITE );
1832 	cgDC.Assets.scrollBar = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR );
1833 	cgDC.Assets.scrollBarArrowDown = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
1834 	cgDC.Assets.scrollBarArrowUp = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
1835 	cgDC.Assets.scrollBarArrowLeft = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
1836 	cgDC.Assets.scrollBarArrowRight = trap_R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
1837 	cgDC.Assets.scrollBarThumb = trap_R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
1838 	cgDC.Assets.sliderBar = trap_R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
1839 	cgDC.Assets.sliderThumb = trap_R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
1840 }
1841 #endif
1842 /*
1843 =================
1844 CG_Init
1845 
1846 Called after every level change or subsystem restart
1847 Will perform callbacks to make the loading info screen update.
1848 =================
1849 */
1850 void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) {
1851 	const char	*s;
1852 
1853 	// clear everything
1854 	memset( &cgs, 0, sizeof( cgs ) );
1855 	memset( &cg, 0, sizeof( cg ) );
1856 	memset( cg_entities, 0, sizeof(cg_entities) );
1857 	memset( cg_weapons, 0, sizeof(cg_weapons) );
1858 	memset( cg_items, 0, sizeof(cg_items) );
1859 
1860 	cg.clientNum = clientNum;
1861 
1862 	cgs.processedSnapshotNum = serverMessageNum;
1863 	cgs.serverCommandSequence = serverCommandSequence;
1864 
1865 	// load a few needed things before we do any screen updates
1866 	cgs.media.charsetShader		= trap_R_RegisterShader( "gfx/2d/bigchars" );
1867 	cgs.media.whiteShader		= trap_R_RegisterShader( "white" );
1868 	cgs.media.charsetProp		= trap_R_RegisterShaderNoMip( "menu/art/font1_prop.tga" );
1869 	cgs.media.charsetPropGlow	= trap_R_RegisterShaderNoMip( "menu/art/font1_prop_glo.tga" );
1870 	cgs.media.charsetPropB		= trap_R_RegisterShaderNoMip( "menu/art/font2_prop.tga" );
1871 
1872 	CG_RegisterCvars();
1873 
1874 	CG_InitConsoleCommands();
1875 
1876 	cg.weaponSelect = WP_MACHINEGUN;
1877 
1878 	cgs.redflag = cgs.blueflag = -1; // For compatibily, default to unset for
1879 	cgs.flagStatus = -1;
1880 	// old servers
1881 
1882 	// get the rendering configuration from the client system
1883 	trap_GetGlconfig( &cgs.glconfig );
1884 	cgs.screenXScale = cgs.glconfig.vidWidth / 640.0;
1885 	cgs.screenYScale = cgs.glconfig.vidHeight / 480.0;
1886 
1887 	// get the gamestate from the client system
1888 	trap_GetGameState( &cgs.gameState );
1889 
1890 	// check version
1891 	s = CG_ConfigString( CS_GAME_VERSION );
1892 	if ( strcmp( s, GAME_VERSION ) ) {
1893 		CG_Error( "Client/Server game mismatch: %s/%s", GAME_VERSION, s );
1894 	}
1895 
1896 	s = CG_ConfigString( CS_LEVEL_START_TIME );
1897 	cgs.levelStartTime = atoi( s );
1898 
1899 	CG_ParseServerinfo();
1900 
1901 	// load the new map
1902 	CG_LoadingString( "collision map" );
1903 
1904 	trap_CM_LoadMap( cgs.mapname );
1905 
1906 #ifdef MISSIONPACK
1907 	String_Init();
1908 #endif
1909 
1910 	cg.loading = qtrue;		// force players to load instead of defer
1911 
1912 	CG_LoadingString( "sounds" );
1913 
1914 	CG_RegisterSounds();
1915 
1916 	CG_LoadingString( "graphics" );
1917 
1918 	CG_RegisterGraphics();
1919 
1920 	CG_LoadingString( "clients" );
1921 
1922 	CG_RegisterClients();		// if low on memory, some clients will be deferred
1923 
1924 #ifdef MISSIONPACK
1925 	CG_AssetCache();
1926 	CG_LoadHudMenu();      // load new hud stuff
1927 #endif
1928 
1929 	cg.loading = qfalse;	// future players will be deferred
1930 
1931 	CG_InitLocalEntities();
1932 
1933 	CG_InitMarkPolys();
1934 
1935 	// remove the last loading update
1936 	cg.infoScreenText[0] = 0;
1937 
1938 	// Make sure we have update values (scores)
1939 	CG_SetConfigValues();
1940 
1941 	CG_StartMusic();
1942 
1943 	CG_LoadingString( "" );
1944 
1945 #ifdef MISSIONPACK
1946 	CG_InitTeamChat();
1947 #endif
1948 
1949 	CG_ShaderStateChanged();
1950 
1951 	trap_S_ClearLoopingSounds( qtrue );
1952 }
1953 
1954 /*
1955 =================
1956 CG_Shutdown
1957 
1958 Called before every level change or subsystem restart
1959 =================
1960 */
1961 void CG_Shutdown( void ) {
1962 	// some mods may need to do cleanup work here,
1963 	// like closing files or archiving session data
1964 }
1965 
1966 
1967 /*
1968 ==================
1969 CG_EventHandling
1970 ==================
1971  type 0 - no event handling
1972       1 - team menu
1973       2 - hud editor
1974 
1975 */
1976 #ifndef MISSIONPACK
1977 void CG_EventHandling(int type) {
1978 }
1979 
1980 
1981 
1982 void CG_KeyEvent(int key, qboolean down) {
1983 }
1984 
1985 void CG_MouseEvent(int x, int y) {
1986 }
1987 #endif
1988 
1989