1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2005 - 2015, ioquake3 contributors
7 Copyright (C) 2013 - 2015, OpenJK contributors
8 
9 This file is part of the OpenJK source code.
10 
11 OpenJK is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License version 2 as
13 published by the Free Software Foundation.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 ===========================================================================
23 */
24 
25 // cg_main.c -- initialization and primary entry point for cgame
26 #include "cg_local.h"
27 
28 #include "ui/ui_shared.h"
29 
30 NORETURN_PTR void (*Com_Error)( int level, const char *error, ... );
31 void (*Com_Printf)( const char *msg, ... );
32 
33 // display context for new ui stuff
34 displayContextDef_t cgDC;
35 
36 extern int cgSiegeRoundState;
37 extern int cgSiegeRoundTime;
38 /*
39 Ghoul2 Insert Start
40 */
41 void CG_InitItems(void);
42 /*
43 Ghoul2 Insert End
44 */
45 
46 void CG_InitJetpackGhoul2(void);
47 void CG_CleanJetpackGhoul2(void);
48 
49 void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum );
50 void CG_Shutdown( void );
51 
52 void CG_CalcEntityLerpPositions( centity_t *cent );
53 void CG_ROFF_NotetrackCallback( centity_t *cent, const char *notetrack);
54 
55 void UI_CleanupGhoul2(void);
56 
57 static int	C_PointContents(void);
58 static void C_GetLerpOrigin(void);
59 static void C_GetLerpData(void);
60 static void C_Trace(void);
61 static void C_G2Trace(void);
62 static void C_G2Mark(void);
63 static int	CG_RagCallback(int callType);
64 static void C_ImpactMark(void);
65 
66 extern autoMapInput_t cg_autoMapInput; //cg_view.c
67 extern int cg_autoMapInputTime;
68 extern vec3_t cg_autoMapAngle;
69 
70 void CG_MiscEnt(void);
71 void CG_DoCameraShake( vec3_t origin, float intensity, int radius, int time );
72 
73 //do we have any force powers that we would normally need to cycle to?
CG_NoUseableForce(void)74 qboolean CG_NoUseableForce(void)
75 {
76 	int i = FP_HEAL;
77 	while (i < NUM_FORCE_POWERS)
78 	{
79 		if (i != FP_SABERTHROW &&
80 			i != FP_SABER_OFFENSE &&
81 			i != FP_SABER_DEFENSE &&
82 			i != FP_LEVITATION)
83 		{ //valid selectable power
84 			if (cg.predictedPlayerState.fd.forcePowersKnown & (1 << i))
85 			{ //we have it
86 				return qfalse;
87 			}
88 		}
89 		i++;
90 	}
91 
92 	//no useable force powers, I guess.
93 	return qtrue;
94 }
95 
C_PointContents(void)96 static int C_PointContents( void ) {
97 	TCGPointContents *data = &cg.sharedBuffer.pointContents;
98 	return CG_PointContents( data->mPoint, data->mPassEntityNum );
99 }
100 
C_GetLerpOrigin(void)101 static void C_GetLerpOrigin( void ) {
102 	TCGVectorData *data = &cg.sharedBuffer.vectorData;
103 	VectorCopy( cg_entities[data->mEntityNum].lerpOrigin, data->mPoint );
104 }
105 
106 // only used by FX system to pass to getboltmat
C_GetLerpData(void)107 static void C_GetLerpData( void ) {
108 	TCGGetBoltData *data = &cg.sharedBuffer.getBoltData;
109 
110 	VectorCopy( cg_entities[data->mEntityNum].lerpOrigin, data->mOrigin );
111 	VectorCopy( cg_entities[data->mEntityNum].modelScale, data->mScale );
112 	VectorCopy( cg_entities[data->mEntityNum].lerpAngles, data->mAngles );
113 	if ( cg_entities[data->mEntityNum].currentState.eType == ET_PLAYER ) {
114 		// normal player
115 		data->mAngles[PITCH] = 0.0f;
116 		data->mAngles[ROLL] = 0.0f;
117 	}
118 	else if ( cg_entities[data->mEntityNum].currentState.eType == ET_NPC ) {
119 		// an NPC
120 		Vehicle_t *pVeh = cg_entities[data->mEntityNum].m_pVehicle;
121 		if ( !pVeh ) {
122 			// for vehicles, we may or may not want to 0 out pitch and roll
123 			data->mAngles[PITCH] = 0.0f;
124 			data->mAngles[ROLL] = 0.0f;
125 		}
126 		else if ( pVeh->m_pVehicleInfo->type == VH_SPEEDER ) {
127 			// speeder wants no pitch but a roll
128 			data->mAngles[PITCH] = 0.0f;
129 		}
130 		else if ( pVeh->m_pVehicleInfo->type != VH_FIGHTER ) {
131 			// fighters want all angles
132 			data->mAngles[PITCH] = 0.0f;
133 			data->mAngles[ROLL] = 0.0f;
134 		}
135 	}
136 }
137 
C_Trace(void)138 static void C_Trace( void ) {
139 	TCGTrace *td = &cg.sharedBuffer.trace;
140 	CG_Trace( &td->mResult, td->mStart, td->mMins, td->mMaxs, td->mEnd, td->mSkipNumber, td->mMask );
141 }
142 
C_G2Trace(void)143 static void C_G2Trace( void ) {
144 	TCGTrace *td = &cg.sharedBuffer.trace;
145 	CG_G2Trace( &td->mResult, td->mStart, td->mMins, td->mMaxs, td->mEnd, td->mSkipNumber, td->mMask );
146 }
147 
C_G2Mark(void)148 static void C_G2Mark( void ) {
149 	TCGG2Mark *td = &cg.sharedBuffer.g2Mark;
150 	trace_t tr;
151 	vec3_t end;
152 
153 	VectorMA( td->start, 64.0f, td->dir, end );
154 	CG_G2Trace( &tr, td->start, NULL, NULL, end, ENTITYNUM_NONE, MASK_PLAYERSOLID );
155 
156 	if ( tr.entityNum < ENTITYNUM_WORLD && cg_entities[tr.entityNum].ghoul2 ) {
157 		// hit someone with a ghoul2 instance, let's project the decal on them then.
158 		centity_t *cent = &cg_entities[tr.entityNum];
159 
160 	//	CG_TestLine( tr.endpos, end, 2000, 0x0000ff, 1 );
161 
162 		CG_AddGhoul2Mark( td->shader, td->size, tr.endpos, end, tr.entityNum, cent->lerpOrigin, cent->lerpAngles[YAW],
163 			cent->ghoul2, cent->modelScale, Q_irand( 2000, 4000 ) );
164 		// I'm making fx system decals have a very short lifetime.
165 	}
166 }
167 
CG_DebugBoxLines(vec3_t mins,vec3_t maxs,int duration)168 static void CG_DebugBoxLines( vec3_t mins, vec3_t maxs, int duration ) {
169 	vec3_t start, end, vert;
170 	float x = maxs[0] - mins[0];
171 	float y = maxs[1] - mins[1];
172 
173 	start[2] = maxs[2];
174 	vert[2] = mins[2];
175 
176 	vert[0] = mins[0];
177 	vert[1] = mins[1];
178 	start[0] = vert[0];
179 	start[1] = vert[1];
180 	CG_TestLine(start, vert, duration, 0x00000ff, 1);
181 
182 	vert[0] = mins[0];
183 	vert[1] = maxs[1];
184 	start[0] = vert[0];
185 	start[1] = vert[1];
186 	CG_TestLine(start, vert, duration, 0x00000ff, 1);
187 
188 	vert[0] = maxs[0];
189 	vert[1] = mins[1];
190 	start[0] = vert[0];
191 	start[1] = vert[1];
192 	CG_TestLine(start, vert, duration, 0x00000ff, 1);
193 
194 	vert[0] = maxs[0];
195 	vert[1] = maxs[1];
196 	start[0] = vert[0];
197 	start[1] = vert[1];
198 	CG_TestLine(start, vert, duration, 0x00000ff, 1);
199 
200 	// top of box
201 	VectorCopy(maxs, start);
202 	VectorCopy(maxs, end);
203 	start[0] -= x;
204 	CG_TestLine(start, end, duration, 0x00000ff, 1);
205 	end[0] = start[0];
206 	end[1] -= y;
207 	CG_TestLine(start, end, duration, 0x00000ff, 1);
208 	start[1] = end[1];
209 	start[0] += x;
210 	CG_TestLine(start, end, duration, 0x00000ff, 1);
211 	CG_TestLine(start, maxs, duration, 0x00000ff, 1);
212 	// bottom of box
213 	VectorCopy(mins, start);
214 	VectorCopy(mins, end);
215 	start[0] += x;
216 	CG_TestLine(start, end, duration, 0x00000ff, 1);
217 	end[0] = start[0];
218 	end[1] += y;
219 	CG_TestLine(start, end, duration, 0x00000ff, 1);
220 	start[1] = end[1];
221 	start[0] -= x;
222 	CG_TestLine(start, end, duration, 0x00000ff, 1);
223 	CG_TestLine(start, mins, duration, 0x00000ff, 1);
224 }
225 
226 //handle ragdoll callbacks, for events and debugging -rww
CG_RagCallback(int callType)227 static int CG_RagCallback(int callType)
228 {
229 	switch(callType)
230 	{
231 	case RAG_CALLBACK_DEBUGBOX:
232 		{
233 			ragCallbackDebugBox_t *callData = &cg.sharedBuffer.rcbDebugBox;
234 
235 			CG_DebugBoxLines(callData->mins, callData->maxs, callData->duration);
236 		}
237 		break;
238 	case RAG_CALLBACK_DEBUGLINE:
239 		{
240 			ragCallbackDebugLine_t *callData = &cg.sharedBuffer.rcbDebugLine;
241 
242 			CG_TestLine(callData->start, callData->end, callData->time, callData->color, callData->radius);
243 		}
244 		break;
245 	case RAG_CALLBACK_BONESNAP:
246 		{
247 			ragCallbackBoneSnap_t *callData = &cg.sharedBuffer.rcbBoneSnap;
248 			centity_t *cent = &cg_entities[callData->entNum];
249 			int snapSound = trap->S_RegisterSound(va("sound/player/bodyfall_human%i.wav", Q_irand(1, 3)));
250 
251 			trap->S_StartSound(cent->lerpOrigin, callData->entNum, CHAN_AUTO, snapSound);
252 		}
253 	case RAG_CALLBACK_BONEIMPACT:
254 		break;
255 	case RAG_CALLBACK_BONEINSOLID:
256 #if 0
257 		{
258 			ragCallbackBoneInSolid_t *callData = &cg.sharedBuffer.rcbBoneInSolid;
259 
260 			if (callData->solidCount > 16)
261 			{ //don't bother if we're just tapping into solidity, we'll probably recover on our own
262 				centity_t *cent = &cg_entities[callData->entNum];
263 				vec3_t slideDir;
264 
265 				VectorSubtract(cent->lerpOrigin, callData->bonePos, slideDir);
266 				VectorAdd(cent->ragOffsets, slideDir, cent->ragOffsets);
267 
268 				cent->hasRagOffset = qtrue;
269 			}
270 		}
271 #endif
272 		break;
273 	case RAG_CALLBACK_TRACELINE:
274 		{
275 			ragCallbackTraceLine_t *callData = &cg.sharedBuffer.rcbTraceLine;
276 
277 			CG_Trace(&callData->tr, callData->start, callData->mins, callData->maxs,
278 				callData->end, callData->ignore, callData->mask);
279 		}
280 		break;
281 	default:
282 		Com_Error(ERR_DROP, "Invalid callType in CG_RagCallback");
283 		break;
284 	}
285 
286 	return 0;
287 }
288 
C_ImpactMark(void)289 static void C_ImpactMark( void ) {
290 	TCGImpactMark *data = &cg.sharedBuffer.impactMark;
291 
292 //	CG_ImpactMark( (int)arg0, (const float *)arg1, (const float *)arg2, (float)arg3, (float)arg4, (float)arg5, (float)arg6,
293 //		(float)arg7, qtrue, (float)arg8, qfalse );
294 
295 	CG_ImpactMark( data->mHandle, data->mPoint, data->mAngle, data->mRotation, data->mRed, data->mGreen, data->mBlue,
296 		data->mAlphaStart, qtrue, data->mSizeStart, qfalse );
297 }
298 
CG_MiscEnt(void)299 void CG_MiscEnt( void ) {
300 	int i, modelIndex;
301 	TCGMiscEnt *data = &cg.sharedBuffer.miscEnt;
302 	cg_staticmodel_t *staticmodel;
303 
304 	if( cgs.numMiscStaticModels >= MAX_STATIC_MODELS ) {
305 		trap->Error( ERR_DROP, "^1MAX_STATIC_MODELS(%i) hit", MAX_STATIC_MODELS );
306 	}
307 
308 	modelIndex = trap->R_RegisterModel(data->mModel);
309 	if (modelIndex == 0) {
310 		trap->Error( ERR_DROP, "client_model failed to load model '%s'", data->mModel );
311 		return;
312 	}
313 
314 	staticmodel = &cgs.miscStaticModels[cgs.numMiscStaticModels++];
315 	staticmodel->model = modelIndex;
316 	AnglesToAxis( data->mAngles, staticmodel->axes );
317 	for ( i = 0; i < 3; i++ ) {
318 		VectorScale( staticmodel->axes[i], data->mScale[i], staticmodel->axes[i] );
319 	}
320 
321 	VectorCopy( data->mOrigin, staticmodel->org );
322 	staticmodel->zoffset = 0.f;
323 
324 	if( staticmodel->model ) {
325 		vec3_t mins, maxs;
326 
327 		trap->R_ModelBounds( staticmodel->model, mins, maxs );
328 
329 		VectorScaleVector(mins, data->mScale, mins);
330 		VectorScaleVector(maxs, data->mScale, maxs);
331 
332 		staticmodel->radius = RadiusFromBounds( mins, maxs );
333 	} else {
334 		staticmodel->radius = 0;
335 	}
336 }
337 
338 /*
339 Ghoul2 Insert Start
340 */
341 /*
342 void CG_ResizeG2Bolt(boltInfo_v *bolt, int newCount)
343 {
344 	bolt->resize(newCount);
345 }
346 
347 void CG_ResizeG2Surface(surfaceInfo_v *surface, int newCount)
348 {
349 	surface->resize(newCount);
350 }
351 
352 void CG_ResizeG2Bone(boneInfo_v *bone, int newCount)
353 {
354 	bone->resize(newCount);
355 }
356 
357 void CG_ResizeG2(CGhoul2Info_v *ghoul2, int newCount)
358 {
359 	ghoul2->resize(newCount);
360 }
361 
362 void CG_ResizeG2TempBone(mdxaBone_v *tempBone, int newCount)
363 {
364 	tempBone->resize(newCount);
365 }
366 */
367 /*
368 Ghoul2 Insert End
369 */
370 cg_t				cg;
371 cgs_t				cgs;
372 centity_t			cg_entities[MAX_GENTITIES];
373 
374 centity_t			*cg_permanents[MAX_GENTITIES]; //rwwRMG - added
375 int					cg_numpermanents = 0;
376 
377 weaponInfo_t		cg_weapons[MAX_WEAPONS];
378 itemInfo_t			cg_items[MAX_ITEMS];
379 
CG_CrosshairPlayer(void)380 int CG_CrosshairPlayer( void ) {
381 	if ( cg.time > (cg.crosshairClientTime + 1000) )
382 		return -1;
383 
384 	if ( cg.crosshairClientNum >= MAX_CLIENTS )
385 		return -1;
386 
387 	return cg.crosshairClientNum;
388 }
389 
CG_LastAttacker(void)390 int CG_LastAttacker( void ) {
391 	if ( !cg.attackerTime )
392 		return -1;
393 
394 	return cg.snap->ps.persistant[PERS_ATTACKER];
395 }
396 
397 /*
398 ================
399 CG_Argv
400 ================
401 */
CG_Argv(int arg)402 const char *CG_Argv( int arg ) {
403 	static char	buffer[MAX_STRING_CHARS] = {0};
404 
405 	trap->Cmd_Argv( arg, buffer, sizeof( buffer ) );
406 
407 	return buffer;
408 }
409 
410 
411 //========================================================================
412 
413 //so shared code can get the local time depending on the side it's executed on
BG_GetTime(void)414 int BG_GetTime(void)
415 {
416 	return cg.time;
417 }
418 
419 /*
420 =================
421 CG_RegisterItemSounds
422 
423 The server says this item is used on this level
424 =================
425 */
CG_RegisterItemSounds(int itemNum)426 static void CG_RegisterItemSounds( int itemNum ) {
427 	gitem_t			*item;
428 	char			data[MAX_QPATH];
429 	char			*s, *start;
430 	int				len;
431 
432 	item = &bg_itemlist[ itemNum ];
433 
434 	if( item->pickup_sound ) {
435 		trap->S_RegisterSound( item->pickup_sound );
436 	}
437 
438 	// parse the space seperated precache string for other media
439 	s = item->sounds;
440 	if (!s || !s[0])
441 		return;
442 
443 	while (*s) {
444 		start = s;
445 		while (*s && *s != ' ') {
446 			s++;
447 		}
448 
449 		len = s-start;
450 		if (len >= MAX_QPATH || len < 5) {
451 			trap->Error( ERR_DROP, "PrecacheItem: %s has bad precache string",
452 				item->classname);
453 			return;
454 		}
455 		memcpy (data, start, len);
456 		data[len] = 0;
457 		if ( *s ) {
458 			s++;
459 		}
460 
461 		trap->S_RegisterSound( data );
462 	}
463 
464 	// parse the space seperated precache string for other media
465 	s = item->precaches;
466 	if (!s || !s[0])
467 		return;
468 
469 	while (*s) {
470 		start = s;
471 		while (*s && *s != ' ') {
472 			s++;
473 		}
474 
475 		len = s-start;
476 		if (len >= MAX_QPATH || len < 5) {
477 			trap->Error( ERR_DROP, "PrecacheItem: %s has bad precache string",
478 				item->classname);
479 			return;
480 		}
481 		memcpy (data, start, len);
482 		data[len] = 0;
483 		if ( *s ) {
484 			s++;
485 		}
486 
487 		if ( !strcmp(data+len-3, "efx" )) {
488 			trap->FX_RegisterEffect( data );
489 		}
490 	}
491 }
492 
CG_AS_Register(void)493 static void CG_AS_Register(void)
494 {
495 	const char *soundName;
496 	int i;
497 
498 //	CG_LoadingString( "ambient sound sets" );
499 
500 	//Load the ambient sets
501 #if 0 //as_preCacheMap was game-side.. that is evil.
502 	trap->AS_AddPrecacheEntry( "#clear" );	// ;-)
503 	//FIXME: Don't ask... I had to get around a really nasty MS error in the templates with this...
504 	namePrecache_m::iterator	pi;
505 	STL_ITERATE( pi, as_preCacheMap )
506 	{
507 		cgi_AS_AddPrecacheEntry( ((*pi).first).c_str() );
508 	}
509 #else
510 	trap->AS_AddPrecacheEntry( "#clear" );
511 
512 	for ( i = 1 ; i < MAX_AMBIENT_SETS ; i++ ) {
513 		soundName = CG_ConfigString( CS_AMBIENT_SET+i );
514 		if ( !soundName || !soundName[0] )
515 		{
516 			break;
517 		}
518 
519 		trap->AS_AddPrecacheEntry(soundName);
520 	}
521 	soundName = CG_ConfigString( CS_GLOBAL_AMBIENT_SET );
522 	if (soundName && soundName[0] && Q_stricmp(soundName, "default"))
523 	{ //global soundset
524 		trap->AS_AddPrecacheEntry(soundName);
525 	}
526 #endif
527 
528 	trap->AS_ParseSets();
529 }
530 
531 //a global weather effect (rain, snow, etc)
CG_ParseWeatherEffect(const char * str)532 void CG_ParseWeatherEffect(const char *str)
533 {
534 	char *sptr = (char *)str;
535 	sptr++; //pass the '*'
536 	trap->R_WorldEffectCommand(sptr);
537 }
538 
539 extern int cgSiegeRoundBeganTime;
CG_ParseSiegeState(const char * str)540 void CG_ParseSiegeState(const char *str)
541 {
542 	int i = 0;
543 	int j = 0;
544 //	int prevState = cgSiegeRoundState;
545 	char b[1024];
546 
547 	while (str[i] && str[i] != '|')
548 	{
549 		b[j] = str[i];
550 		i++;
551 		j++;
552 	}
553 	b[j] = 0;
554 	cgSiegeRoundState = atoi(b);
555 
556 	if (str[i] == '|')
557 	{
558 		j = 0;
559 		i++;
560 		while (str[i])
561 		{
562 			b[j] = str[i];
563 			i++;
564 			j++;
565 		}
566 		b[j] = 0;
567 //		if (cgSiegeRoundState != prevState)
568 		{ //it changed
569 			cgSiegeRoundTime = atoi(b);
570 			if (cgSiegeRoundState == 0 || cgSiegeRoundState == 2)
571 			{
572 				cgSiegeRoundBeganTime = cgSiegeRoundTime;
573 			}
574 		}
575 	}
576 	else
577 	{
578 	    cgSiegeRoundTime = cg.time;
579 	}
580 }
581 
582 /*
583 =================
584 CG_RegisterSounds
585 
586 called during a precache command
587 =================
588 */
589 void CG_PrecacheNPCSounds(const char *str);
590 void CG_ParseSiegeObjectiveStatus(const char *str);
591 extern int cg_beatingSiegeTime;
592 extern int cg_siegeWinTeam;
CG_RegisterSounds(void)593 static void CG_RegisterSounds( void ) {
594 	int		i;
595 	char	items[MAX_ITEMS+1];
596 	char	name[MAX_QPATH];
597 	const char	*soundName;
598 
599 	CG_AS_Register();
600 
601 //	CG_LoadingString( "sounds" );
602 
603 	trap->S_RegisterSound( "sound/weapons/melee/punch1.mp3" );
604 	trap->S_RegisterSound( "sound/weapons/melee/punch2.mp3" );
605 	trap->S_RegisterSound( "sound/weapons/melee/punch3.mp3" );
606 	trap->S_RegisterSound( "sound/weapons/melee/punch4.mp3" );
607 	trap->S_RegisterSound("sound/movers/objects/saber_slam");
608 
609 	trap->S_RegisterSound("sound/player/bodyfall_human1.wav");
610 	trap->S_RegisterSound("sound/player/bodyfall_human2.wav");
611 	trap->S_RegisterSound("sound/player/bodyfall_human3.wav");
612 
613 	//test effects
614 	trap->FX_RegisterEffect("effects/mp/test_sparks.efx");
615 	trap->FX_RegisterEffect("effects/mp/test_wall_impact.efx");
616 
617 	cgs.media.oneMinuteSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM004" );
618 	cgs.media.fiveMinuteSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM005" );
619 	cgs.media.oneFragSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM001" );
620 	cgs.media.twoFragSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM002" );
621 	cgs.media.threeFragSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM003");
622 	cgs.media.count3Sound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM035" );
623 	cgs.media.count2Sound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM036" );
624 	cgs.media.count1Sound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM037" );
625 	cgs.media.countFightSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM038" );
626 
627 	cgs.media.hackerIconShader			= trap->R_RegisterShaderNoMip("gfx/mp/c_icon_tech");
628 
629 	cgs.media.redSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/red_glow" );
630 	cgs.media.redSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/red_line" );
631 	cgs.media.orangeSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/orange_glow" );
632 	cgs.media.orangeSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/orange_line" );
633 	cgs.media.yellowSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/yellow_glow" );
634 	cgs.media.yellowSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/yellow_line" );
635 	cgs.media.greenSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/green_glow" );
636 	cgs.media.greenSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/green_line" );
637 	cgs.media.blueSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/blue_glow" );
638 	cgs.media.blueSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/blue_line" );
639 	cgs.media.purpleSaberGlowShader		= trap->R_RegisterShader( "gfx/effects/sabers/purple_glow" );
640 	cgs.media.purpleSaberCoreShader		= trap->R_RegisterShader( "gfx/effects/sabers/purple_line" );
641 	cgs.media.saberBlurShader			= trap->R_RegisterShader( "gfx/effects/sabers/saberBlur" );
642 	cgs.media.swordTrailShader			= trap->R_RegisterShader( "gfx/effects/sabers/swordTrail" );
643 
644 	cgs.media.forceCoronaShader			= trap->R_RegisterShaderNoMip( "gfx/hud/force_swirl" );
645 
646 	cgs.media.yellowDroppedSaberShader	= trap->R_RegisterShader("gfx/effects/yellow_glow");
647 
648 	cgs.media.rivetMarkShader			= trap->R_RegisterShader( "gfx/damage/rivetmark" );
649 
650 	trap->R_RegisterShader( "gfx/effects/saberFlare" );
651 
652 	trap->R_RegisterShader( "powerups/ysalimarishell" );
653 
654 	trap->R_RegisterShader( "gfx/effects/forcePush" );
655 
656 	trap->R_RegisterShader( "gfx/misc/red_dmgshield" );
657 	trap->R_RegisterShader( "gfx/misc/red_portashield" );
658 	trap->R_RegisterShader( "gfx/misc/blue_dmgshield" );
659 	trap->R_RegisterShader( "gfx/misc/blue_portashield" );
660 
661 	trap->R_RegisterShader( "models/map_objects/imp_mine/turret_chair_dmg.tga" );
662 
663 	for (i=1 ; i<9 ; i++)
664 	{
665 		trap->S_RegisterSound(va("sound/weapons/saber/saberhup%i.wav", i));
666 	}
667 
668 	for (i=1 ; i<10 ; i++)
669 	{
670 		trap->S_RegisterSound(va("sound/weapons/saber/saberblock%i.wav", i));
671 	}
672 
673 	for (i=1 ; i<4 ; i++)
674 	{
675 		trap->S_RegisterSound(va("sound/weapons/saber/bounce%i.wav", i));
676 	}
677 
678 	trap->S_RegisterSound( "sound/weapons/saber/enemy_saber_on.wav" );
679 	trap->S_RegisterSound( "sound/weapons/saber/enemy_saber_off.wav" );
680 
681 	trap->S_RegisterSound( "sound/weapons/saber/saberhum1.wav" );
682 	trap->S_RegisterSound( "sound/weapons/saber/saberon.wav" );
683 	trap->S_RegisterSound( "sound/weapons/saber/saberoffquick.wav" );
684 	trap->S_RegisterSound( "sound/weapons/saber/saberhitwall1" );
685 	trap->S_RegisterSound( "sound/weapons/saber/saberhitwall2" );
686 	trap->S_RegisterSound( "sound/weapons/saber/saberhitwall3" );
687 	trap->S_RegisterSound("sound/weapons/saber/saberhit.wav");
688 	trap->S_RegisterSound("sound/weapons/saber/saberhit1.wav");
689 	trap->S_RegisterSound("sound/weapons/saber/saberhit2.wav");
690 	trap->S_RegisterSound("sound/weapons/saber/saberhit3.wav");
691 
692 	trap->S_RegisterSound("sound/weapons/saber/saber_catch.wav");
693 
694 	cgs.media.teamHealSound = trap->S_RegisterSound("sound/weapons/force/teamheal.wav");
695 	cgs.media.teamRegenSound = trap->S_RegisterSound("sound/weapons/force/teamforce.wav");
696 
697 	trap->S_RegisterSound("sound/weapons/force/heal.wav");
698 	trap->S_RegisterSound("sound/weapons/force/speed.wav");
699 	trap->S_RegisterSound("sound/weapons/force/see.wav");
700 	trap->S_RegisterSound("sound/weapons/force/rage.wav");
701 	trap->S_RegisterSound("sound/weapons/force/lightning");
702 	trap->S_RegisterSound("sound/weapons/force/lightninghit1");
703 	trap->S_RegisterSound("sound/weapons/force/lightninghit2");
704 	trap->S_RegisterSound("sound/weapons/force/lightninghit3");
705 	trap->S_RegisterSound("sound/weapons/force/drain.wav");
706 	trap->S_RegisterSound("sound/weapons/force/jumpbuild.wav");
707 	trap->S_RegisterSound("sound/weapons/force/distract.wav");
708 	trap->S_RegisterSound("sound/weapons/force/distractstop.wav");
709 	trap->S_RegisterSound("sound/weapons/force/pull.wav");
710 	trap->S_RegisterSound("sound/weapons/force/push.wav");
711 
712 	for (i=1 ; i<3 ; i++)
713 	{
714 		trap->S_RegisterSound(va("sound/weapons/thermal/bounce%i.wav", i));
715 	}
716 
717 	trap->S_RegisterSound("sound/movers/switches/switch2.wav");
718 	trap->S_RegisterSound("sound/movers/switches/switch3.wav");
719 	trap->S_RegisterSound("sound/ambience/spark5.wav");
720 	trap->S_RegisterSound("sound/chars/turret/ping.wav");
721 	trap->S_RegisterSound("sound/chars/turret/startup.wav");
722 	trap->S_RegisterSound("sound/chars/turret/shutdown.wav");
723 	trap->S_RegisterSound("sound/chars/turret/move.wav");
724 	trap->S_RegisterSound("sound/player/pickuphealth.wav");
725 	trap->S_RegisterSound("sound/player/pickupshield.wav");
726 
727 	trap->S_RegisterSound("sound/effects/glassbreak1.wav");
728 
729 	trap->S_RegisterSound( "sound/weapons/rocket/tick.wav" );
730 	trap->S_RegisterSound( "sound/weapons/rocket/lock.wav" );
731 
732 	trap->S_RegisterSound("sound/weapons/force/speedloop.wav");
733 
734 	trap->S_RegisterSound("sound/weapons/force/protecthit.mp3"); //PDSOUND_PROTECTHIT
735 	trap->S_RegisterSound("sound/weapons/force/protect.mp3"); //PDSOUND_PROTECT
736 	trap->S_RegisterSound("sound/weapons/force/absorbhit.mp3"); //PDSOUND_ABSORBHIT
737 	trap->S_RegisterSound("sound/weapons/force/absorb.mp3"); //PDSOUND_ABSORB
738 	trap->S_RegisterSound("sound/weapons/force/jump.mp3"); //PDSOUND_FORCEJUMP
739 	trap->S_RegisterSound("sound/weapons/force/grip.mp3"); //PDSOUND_FORCEGRIP
740 
741 	if ( cgs.gametype >= GT_TEAM || com_buildScript.integer ) {
742 
743 #ifdef JK2AWARDS
744 		cgs.media.captureAwardSound = trap->S_RegisterSound( "sound/teamplay/flagcapture_yourteam.wav" );
745 #endif
746 		cgs.media.redLeadsSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM046");
747 		cgs.media.blueLeadsSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM045");
748 		cgs.media.teamsTiedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM032" );
749 
750 		cgs.media.redScoredSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM044");
751 		cgs.media.blueScoredSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM043" );
752 
753 		if ( cgs.gametype == GT_CTF || com_buildScript.integer ) {
754 			cgs.media.redFlagReturnedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM042" );
755 			cgs.media.blueFlagReturnedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM041" );
756 			cgs.media.redTookFlagSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM040" );
757 			cgs.media.blueTookFlagSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM039" );
758 		}
759 		if ( cgs.gametype == GT_CTY /*|| com_buildScript.integer*/ ) {
760 			cgs.media.redYsalReturnedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM050" );
761 			cgs.media.blueYsalReturnedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM049" );
762 			cgs.media.redTookYsalSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM048" );
763 			cgs.media.blueTookYsalSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM047" );
764 		}
765 	}
766 
767 	cgs.media.drainSound = trap->S_RegisterSound("sound/weapons/force/drained.mp3");
768 
769 	cgs.media.happyMusic = trap->S_RegisterSound("music/goodsmall.mp3");
770 	cgs.media.dramaticFailure = trap->S_RegisterSound("music/badsmall.mp3");
771 
772 	//PRECACHE ALL MUSIC HERE (don't need to precache normally because it's streamed off the disk)
773 	if (com_buildScript.integer)
774 	{
775 		trap->S_StartBackgroundTrack( "music/mp/duel.mp3", "music/mp/duel.mp3", qfalse );
776 	}
777 
778 	cg.loadLCARSStage = 1;
779 
780 	cgs.media.selectSound = trap->S_RegisterSound( "sound/weapons/change.wav" );
781 
782 	cgs.media.teleInSound = trap->S_RegisterSound( "sound/player/telein.wav" );
783 	cgs.media.teleOutSound = trap->S_RegisterSound( "sound/player/teleout.wav" );
784 	cgs.media.respawnSound = trap->S_RegisterSound( "sound/items/respawn1.wav" );
785 
786 	trap->S_RegisterSound( "sound/movers/objects/objectHit.wav" );
787 
788 	cgs.media.talkSound = trap->S_RegisterSound( "sound/player/talk.wav" );
789 	cgs.media.landSound = trap->S_RegisterSound( "sound/player/land1.wav");
790 	cgs.media.fallSound = trap->S_RegisterSound( "sound/player/fallsplat.wav");
791 
792 	cgs.media.crackleSound = trap->S_RegisterSound( "sound/effects/energy_crackle.wav" );
793 #ifdef JK2AWARDS
794 	cgs.media.impressiveSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM025" );
795 	cgs.media.excellentSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM053" );
796 	cgs.media.deniedSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM017" );
797 	cgs.media.humiliationSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM019" );
798 	cgs.media.defendSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM024" );
799 #endif
800 
801 	/*
802 	cgs.media.takenLeadSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM051");
803 	cgs.media.tiedLeadSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM032");
804 	cgs.media.lostLeadSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM052");
805 	*/
806 
807 	cgs.media.rollSound					= trap->S_RegisterSound( "sound/player/roll1.wav");
808 
809 	cgs.media.noforceSound				= trap->S_RegisterSound( "sound/weapons/force/noforce" );
810 
811 	cgs.media.watrInSound				= trap->S_RegisterSound( "sound/player/watr_in.wav");
812 	cgs.media.watrOutSound				= trap->S_RegisterSound( "sound/player/watr_out.wav");
813 	cgs.media.watrUnSound				= trap->S_RegisterSound( "sound/player/watr_un.wav");
814 
815 	cgs.media.explosionModel			= trap->R_RegisterModel ( "models/map_objects/mp/sphere.md3" );
816 	cgs.media.surfaceExplosionShader	= trap->R_RegisterShader( "surfaceExplosion" );
817 
818 	cgs.media.disruptorShader			= trap->R_RegisterShader( "gfx/effects/burn");
819 
820 	if (com_buildScript.integer)
821 	{
822 		trap->R_RegisterShader( "gfx/effects/turretflashdie" );
823 	}
824 
825 	cgs.media.solidWhite = trap->R_RegisterShader( "gfx/effects/solidWhite_cull" );
826 
827 	trap->R_RegisterShader("gfx/misc/mp_light_enlight_disable");
828 	trap->R_RegisterShader("gfx/misc/mp_dark_enlight_disable");
829 
830 	trap->R_RegisterModel ( "models/map_objects/mp/sphere.md3" );
831 	trap->R_RegisterModel("models/items/remote.md3");
832 
833 	cgs.media.holocronPickup = trap->S_RegisterSound( "sound/player/holocron.wav" );
834 
835 	// Zoom
836 	cgs.media.zoomStart = trap->S_RegisterSound( "sound/interface/zoomstart.wav" );
837 	cgs.media.zoomLoop	= trap->S_RegisterSound( "sound/interface/zoomloop.wav" );
838 	cgs.media.zoomEnd	= trap->S_RegisterSound( "sound/interface/zoomend.wav" );
839 
840 	for (i=0 ; i<4 ; i++) {
841 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/stone_step%i.wav", i+1);
842 		cgs.media.footsteps[FOOTSTEP_STONEWALK][i] = trap->S_RegisterSound (name);
843 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/stone_run%i.wav", i+1);
844 		cgs.media.footsteps[FOOTSTEP_STONERUN][i] = trap->S_RegisterSound (name);
845 
846 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/metal_step%i.wav", i+1);
847 		cgs.media.footsteps[FOOTSTEP_METALWALK][i] = trap->S_RegisterSound (name);
848 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/metal_run%i.wav", i+1);
849 		cgs.media.footsteps[FOOTSTEP_METALRUN][i] = trap->S_RegisterSound (name);
850 
851 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/pipe_step%i.wav", i+1);
852 		cgs.media.footsteps[FOOTSTEP_PIPEWALK][i] = trap->S_RegisterSound (name);
853 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/pipe_run%i.wav", i+1);
854 		cgs.media.footsteps[FOOTSTEP_PIPERUN][i] = trap->S_RegisterSound (name);
855 
856 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/water_run%i.wav", i+1);
857 		cgs.media.footsteps[FOOTSTEP_SPLASH][i] = trap->S_RegisterSound (name);
858 
859 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/water_walk%i.wav", i+1);
860 		cgs.media.footsteps[FOOTSTEP_WADE][i] = trap->S_RegisterSound (name);
861 
862 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/water_wade_0%i.wav", i+1);
863 		cgs.media.footsteps[FOOTSTEP_SWIM][i] = trap->S_RegisterSound (name);
864 
865 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/snow_step%i.wav", i+1);
866 		cgs.media.footsteps[FOOTSTEP_SNOWWALK][i] = trap->S_RegisterSound (name);
867 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/snow_run%i.wav", i+1);
868 		cgs.media.footsteps[FOOTSTEP_SNOWRUN][i] = trap->S_RegisterSound (name);
869 
870 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/sand_walk%i.wav", i+1);
871 		cgs.media.footsteps[FOOTSTEP_SANDWALK][i] = trap->S_RegisterSound (name);
872 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/sand_run%i.wav", i+1);
873 		cgs.media.footsteps[FOOTSTEP_SANDRUN][i] = trap->S_RegisterSound (name);
874 
875 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/grass_step%i.wav", i+1);
876 		cgs.media.footsteps[FOOTSTEP_GRASSWALK][i] = trap->S_RegisterSound (name);
877 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/grass_run%i.wav", i+1);
878 		cgs.media.footsteps[FOOTSTEP_GRASSRUN][i] = trap->S_RegisterSound (name);
879 
880 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/dirt_step%i.wav", i+1);
881 		cgs.media.footsteps[FOOTSTEP_DIRTWALK][i] = trap->S_RegisterSound (name);
882 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/dirt_run%i.wav", i+1);
883 		cgs.media.footsteps[FOOTSTEP_DIRTRUN][i] = trap->S_RegisterSound (name);
884 
885 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/mud_walk%i.wav", i+1);
886 		cgs.media.footsteps[FOOTSTEP_MUDWALK][i] = trap->S_RegisterSound (name);
887 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/mud_run%i.wav", i+1);
888 		cgs.media.footsteps[FOOTSTEP_MUDRUN][i] = trap->S_RegisterSound (name);
889 
890 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/gravel_walk%i.wav", i+1);
891 		cgs.media.footsteps[FOOTSTEP_GRAVELWALK][i] = trap->S_RegisterSound (name);
892 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/gravel_run%i.wav", i+1);
893 		cgs.media.footsteps[FOOTSTEP_GRAVELRUN][i] = trap->S_RegisterSound (name);
894 
895 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/rug_step%i.wav", i+1);
896 		cgs.media.footsteps[FOOTSTEP_RUGWALK][i] = trap->S_RegisterSound (name);
897 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/rug_run%i.wav", i+1);
898 		cgs.media.footsteps[FOOTSTEP_RUGRUN][i] = trap->S_RegisterSound (name);
899 
900 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/wood_walk%i.wav", i+1);
901 		cgs.media.footsteps[FOOTSTEP_WOODWALK][i] = trap->S_RegisterSound (name);
902 		Com_sprintf (name, sizeof(name), "sound/player/footsteps/wood_run%i.wav", i+1);
903 		cgs.media.footsteps[FOOTSTEP_WOODRUN][i] = trap->S_RegisterSound (name);
904 	}
905 
906 	// only register the items that the server says we need
907 	Q_strncpyz(items, CG_ConfigString(CS_ITEMS), sizeof(items));
908 
909 	for ( i = 1 ; i < bg_numItems ; i++ ) {
910 		if ( items[ i ] == '1' || com_buildScript.integer ) {
911 			CG_RegisterItemSounds( i );
912 		}
913 	}
914 
915 	for ( i = 1 ; i < MAX_SOUNDS ; i++ ) {
916 		soundName = CG_ConfigString( CS_SOUNDS+i );
917 		if ( !soundName[0] ) {
918 			break;
919 		}
920 		if ( soundName[0] == '*' )
921 		{
922 			if (soundName[1] == '$')
923 			{ //an NPC soundset
924 				CG_PrecacheNPCSounds(soundName);
925 			}
926 			continue;	// custom sound
927 		}
928 		cgs.gameSounds[i] = trap->S_RegisterSound( soundName );
929 	}
930 
931 	for ( i = 1 ; i < MAX_FX ; i++ ) {
932 		soundName = CG_ConfigString( CS_EFFECTS+i );
933 		if ( !soundName[0] ) {
934 			break;
935 		}
936 
937 		if (soundName[0] == '*')
938 		{ //it's a special global weather effect
939 			CG_ParseWeatherEffect(soundName);
940 			cgs.gameEffects[i] = 0;
941 		}
942 		else
943 		{
944 			cgs.gameEffects[i] = trap->FX_RegisterEffect( soundName );
945 		}
946 	}
947 
948 	// register all the server specified icons
949 	for ( i = 1; i < MAX_ICONS; i ++ )
950 	{
951 		const char* iconName;
952 
953 		iconName = CG_ConfigString ( CS_ICONS + i );
954 		if ( !iconName[0] )
955 		{
956 			break;
957 		}
958 
959 		cgs.gameIcons[i] = trap->R_RegisterShaderNoMip ( iconName );
960 	}
961 
962 	soundName = CG_ConfigString(CS_SIEGE_STATE);
963 
964 	if (soundName[0])
965 	{
966 		CG_ParseSiegeState(soundName);
967 	}
968 
969 	soundName = CG_ConfigString(CS_SIEGE_WINTEAM);
970 
971 	if (soundName[0])
972 	{
973 		cg_siegeWinTeam = atoi(soundName);
974 	}
975 
976 	if (cgs.gametype == GT_SIEGE)
977 	{
978 		CG_ParseSiegeObjectiveStatus(CG_ConfigString(CS_SIEGE_OBJECTIVES));
979 		cg_beatingSiegeTime = atoi(CG_ConfigString(CS_SIEGE_TIMEOVERRIDE));
980 		if ( cg_beatingSiegeTime )
981 		{
982 			CG_SetSiegeTimerCvar ( cg_beatingSiegeTime );
983 		}
984 	}
985 
986 	cg.loadLCARSStage = 2;
987 
988 	// FIXME: only needed with item
989 	cgs.media.deploySeeker = trap->S_RegisterSound ("sound/chars/seeker/misc/hiss");
990 	cgs.media.medkitSound = trap->S_RegisterSound ("sound/items/use_bacta.wav");
991 
992 	cgs.media.winnerSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM006" );
993 	cgs.media.loserSound = trap->S_RegisterSound( "sound/chars/protocol/misc/40MOM010" );
994 }
995 
996 
997 //-------------------------------------
998 // CG_RegisterEffects
999 //
1000 // Handles precaching all effect files
1001 //	and any shader, model, or sound
1002 //	files an effect may use.
1003 //-------------------------------------
CG_RegisterEffects(void)1004 static void CG_RegisterEffects( void )
1005 {
1006 	/*
1007 	const char	*effectName;
1008 	int			i;
1009 
1010 	for ( i = 1 ; i < MAX_FX ; i++ )
1011 	{
1012 		effectName = CG_ConfigString( CS_EFFECTS + i );
1013 
1014 		if ( !effectName[0] )
1015 		{
1016 			break;
1017 		}
1018 
1019 		trap->FX_RegisterEffect( effectName );
1020 	}
1021 	*/
1022 	//the above was redundant as it's being done in CG_RegisterSounds
1023 
1024 	// Set up the glass effects mini-system.
1025 	CG_InitGlass();
1026 
1027 	//footstep effects
1028 	cgs.effects.footstepMud = trap->FX_RegisterEffect( "materials/mud" );
1029 	cgs.effects.footstepSand = trap->FX_RegisterEffect( "materials/sand" );
1030 	cgs.effects.footstepSnow = trap->FX_RegisterEffect( "materials/snow" );
1031 	cgs.effects.footstepGravel = trap->FX_RegisterEffect( "materials/gravel" );
1032 	//landing effects
1033 	cgs.effects.landingMud = trap->FX_RegisterEffect( "materials/mud_large" );
1034 	cgs.effects.landingSand = trap->FX_RegisterEffect( "materials/sand_large" );
1035 	cgs.effects.landingDirt = trap->FX_RegisterEffect( "materials/dirt_large" );
1036 	cgs.effects.landingSnow = trap->FX_RegisterEffect( "materials/snow_large" );
1037 	cgs.effects.landingGravel = trap->FX_RegisterEffect( "materials/gravel_large" );
1038 	//splashes
1039 	cgs.effects.waterSplash = trap->FX_RegisterEffect( "env/water_impact" );
1040 	cgs.effects.lavaSplash = trap->FX_RegisterEffect( "env/lava_splash" );
1041 	cgs.effects.acidSplash = trap->FX_RegisterEffect( "env/acid_splash" );
1042 }
1043 
1044 //===================================================================================
1045 
1046 extern char *forceHolocronModels[];
1047 int CG_HandleAppendedSkin(char *modelName);
1048 void CG_CacheG2AnimInfo(char *modelName);
1049 /*
1050 =================
1051 CG_RegisterGraphics
1052 
1053 This function may execute for a couple of minutes with a slow disk.
1054 =================
1055 */
CG_RegisterGraphics(void)1056 static void CG_RegisterGraphics( void ) {
1057 	int			i;
1058 	int			breakPoint;
1059 	char		items[MAX_ITEMS+1];
1060 
1061 	static char		*sb_nums[11] = {
1062 		"gfx/2d/numbers/zero",
1063 		"gfx/2d/numbers/one",
1064 		"gfx/2d/numbers/two",
1065 		"gfx/2d/numbers/three",
1066 		"gfx/2d/numbers/four",
1067 		"gfx/2d/numbers/five",
1068 		"gfx/2d/numbers/six",
1069 		"gfx/2d/numbers/seven",
1070 		"gfx/2d/numbers/eight",
1071 		"gfx/2d/numbers/nine",
1072 		"gfx/2d/numbers/minus",
1073 	};
1074 
1075 	static char		*sb_t_nums[11] = {
1076 		"gfx/2d/numbers/t_zero",
1077 		"gfx/2d/numbers/t_one",
1078 		"gfx/2d/numbers/t_two",
1079 		"gfx/2d/numbers/t_three",
1080 		"gfx/2d/numbers/t_four",
1081 		"gfx/2d/numbers/t_five",
1082 		"gfx/2d/numbers/t_six",
1083 		"gfx/2d/numbers/t_seven",
1084 		"gfx/2d/numbers/t_eight",
1085 		"gfx/2d/numbers/t_nine",
1086 		"gfx/2d/numbers/t_minus",
1087 	};
1088 
1089 	static char		*sb_c_nums[11] = {
1090 		"gfx/2d/numbers/c_zero",
1091 		"gfx/2d/numbers/c_one",
1092 		"gfx/2d/numbers/c_two",
1093 		"gfx/2d/numbers/c_three",
1094 		"gfx/2d/numbers/c_four",
1095 		"gfx/2d/numbers/c_five",
1096 		"gfx/2d/numbers/c_six",
1097 		"gfx/2d/numbers/c_seven",
1098 		"gfx/2d/numbers/c_eight",
1099 		"gfx/2d/numbers/c_nine",
1100 		"gfx/2d/numbers/t_minus", //?????
1101 	};
1102 
1103 	// clear any references to old media
1104 	memset( &cg.refdef, 0, sizeof( cg.refdef ) );
1105 	trap->R_ClearScene();
1106 
1107 	CG_LoadingString( cgs.mapname );
1108 
1109 	trap->R_LoadWorld( cgs.mapname );
1110 
1111 	// precache status bar pics
1112 //	CG_LoadingString( "game media" );
1113 
1114 	for ( i=0 ; i<11 ; i++) {
1115 		cgs.media.numberShaders[i] = trap->R_RegisterShader( sb_nums[i] );
1116 	}
1117 
1118 	cg.loadLCARSStage = 3;
1119 
1120 	for ( i=0; i < 11; i++ )
1121 	{
1122 		cgs.media.numberShaders[i]			= trap->R_RegisterShaderNoMip( sb_nums[i] );
1123 		cgs.media.smallnumberShaders[i]		= trap->R_RegisterShaderNoMip( sb_t_nums[i] );
1124 		cgs.media.chunkyNumberShaders[i]	= trap->R_RegisterShaderNoMip( sb_c_nums[i] );
1125 	}
1126 
1127 	trap->R_RegisterShaderNoMip ( "gfx/mp/pduel_icon_lone" );
1128 	trap->R_RegisterShaderNoMip ( "gfx/mp/pduel_icon_double" );
1129 
1130 	cgs.media.balloonShader = trap->R_RegisterShader( "gfx/mp/chat_icon" );
1131 	cgs.media.vchatShader = trap->R_RegisterShader( "gfx/mp/vchat_icon" );
1132 
1133 	cgs.media.deferShader = trap->R_RegisterShaderNoMip( "gfx/2d/defer.tga" );
1134 
1135 	cgs.media.radarShader			= trap->R_RegisterShaderNoMip ( "gfx/menus/radar/radar.png" );
1136 	cgs.media.siegeItemShader		= trap->R_RegisterShaderNoMip ( "gfx/menus/radar/goalitem" );
1137 	cgs.media.mAutomapPlayerIcon	= trap->R_RegisterShader( "gfx/menus/radar/arrow_w" );
1138 	cgs.media.mAutomapRocketIcon	= trap->R_RegisterShader( "gfx/menus/radar/rocket" );
1139 
1140 	cgs.media.wireframeAutomapFrame_left = trap->R_RegisterShader( "gfx/mp_automap/mpauto_frame_left" );
1141 	cgs.media.wireframeAutomapFrame_right = trap->R_RegisterShader( "gfx/mp_automap/mpauto_frame_right" );
1142 	cgs.media.wireframeAutomapFrame_top = trap->R_RegisterShader( "gfx/mp_automap/mpauto_frame_top" );
1143 	cgs.media.wireframeAutomapFrame_bottom = trap->R_RegisterShader( "gfx/mp_automap/mpauto_frame_bottom" );
1144 
1145 	cgs.media.lagometerShader = trap->R_RegisterShaderNoMip("gfx/2d/lag" );
1146 	cgs.media.connectionShader = trap->R_RegisterShaderNoMip( "gfx/2d/net" );
1147 
1148 	trap->FX_InitSystem(&cg.refdef);
1149 	CG_RegisterEffects();
1150 
1151 	cgs.media.boltShader = trap->R_RegisterShader( "gfx/misc/blueLine" );
1152 
1153 	cgs.effects.turretShotEffect = trap->FX_RegisterEffect( "turret/shot" );
1154 	cgs.effects.mEmplacedDeadSmoke = trap->FX_RegisterEffect("emplaced/dead_smoke.efx");
1155 	cgs.effects.mEmplacedExplode = trap->FX_RegisterEffect("emplaced/explode.efx");
1156 	cgs.effects.mTurretExplode = trap->FX_RegisterEffect("turret/explode.efx");
1157 	cgs.effects.mSparkExplosion = trap->FX_RegisterEffect("sparks/spark_explosion.efx");
1158 	cgs.effects.mTripmineExplosion = trap->FX_RegisterEffect("tripMine/explosion.efx");
1159 	cgs.effects.mDetpackExplosion = trap->FX_RegisterEffect("detpack/explosion.efx");
1160 	cgs.effects.mFlechetteAltBlow = trap->FX_RegisterEffect("flechette/alt_blow.efx");
1161 	cgs.effects.mStunBatonFleshImpact = trap->FX_RegisterEffect("stunBaton/flesh_impact.efx");
1162 	cgs.effects.mAltDetonate = trap->FX_RegisterEffect("demp2/altDetonate.efx");
1163 	cgs.effects.mSparksExplodeNoSound = trap->FX_RegisterEffect("sparks/spark_exp_nosnd");
1164 	cgs.effects.mTripMineLaser = trap->FX_RegisterEffect("tripMine/laser.efx");
1165 	cgs.effects.mEmplacedMuzzleFlash = trap->FX_RegisterEffect( "effects/emplaced/muzzle_flash" );
1166 	cgs.effects.mConcussionAltRing = trap->FX_RegisterEffect("concussion/alt_ring");
1167 
1168 	cgs.effects.mHyperspaceStars = trap->FX_RegisterEffect("ships/hyperspace_stars");
1169 	cgs.effects.mBlackSmoke = trap->FX_RegisterEffect( "volumetric/black_smoke" );
1170 	cgs.effects.mShipDestDestroyed = trap->FX_RegisterEffect("effects/ships/dest_destroyed.efx");
1171 	cgs.effects.mShipDestBurning = trap->FX_RegisterEffect("effects/ships/dest_burning.efx");
1172 	cgs.effects.mBobaJet = trap->FX_RegisterEffect("effects/boba/jet.efx");
1173 
1174 
1175 	cgs.effects.itemCone = trap->FX_RegisterEffect("mp/itemcone.efx");
1176 	cgs.effects.mTurretMuzzleFlash = trap->FX_RegisterEffect("effects/turret/muzzle_flash.efx");
1177 	cgs.effects.mSparks = trap->FX_RegisterEffect("sparks/spark_nosnd.efx"); //sparks/spark.efx
1178 	cgs.effects.mSaberCut = trap->FX_RegisterEffect("saber/saber_cut.efx");
1179 	cgs.effects.mSaberBlock = trap->FX_RegisterEffect("saber/saber_block.efx");
1180 	cgs.effects.mSaberBloodSparks = trap->FX_RegisterEffect("saber/blood_sparks_mp.efx");
1181 	cgs.effects.mSaberBloodSparksSmall = trap->FX_RegisterEffect("saber/blood_sparks_25_mp.efx");
1182 	cgs.effects.mSaberBloodSparksMid = trap->FX_RegisterEffect("saber/blood_sparks_50_mp.efx");
1183 	cgs.effects.mSpawn = trap->FX_RegisterEffect("mp/spawn.efx");
1184 	cgs.effects.mJediSpawn = trap->FX_RegisterEffect("mp/jedispawn.efx");
1185 	cgs.effects.mBlasterDeflect = trap->FX_RegisterEffect("blaster/deflect.efx");
1186 	cgs.effects.mBlasterSmoke = trap->FX_RegisterEffect("blaster/smoke_bolton");
1187 	cgs.effects.mForceConfustionOld = trap->FX_RegisterEffect("force/confusion_old.efx");
1188 
1189 	cgs.effects.forceLightning		= trap->FX_RegisterEffect( "effects/force/lightning.efx" );
1190 	cgs.effects.forceLightningWide	= trap->FX_RegisterEffect( "effects/force/lightningwide.efx" );
1191 	cgs.effects.forceDrain		= trap->FX_RegisterEffect( "effects/mp/drain.efx" );
1192 	cgs.effects.forceDrainWide	= trap->FX_RegisterEffect( "effects/mp/drainwide.efx" );
1193 	cgs.effects.forceDrained	= trap->FX_RegisterEffect( "effects/mp/drainhit.efx");
1194 
1195 	cgs.effects.mDisruptorDeathSmoke = trap->FX_RegisterEffect("disruptor/death_smoke");
1196 
1197 	for ( i = 0 ; i < NUM_CROSSHAIRS ; i++ ) {
1198 		cgs.media.crosshairShader[i] = trap->R_RegisterShaderNoMip( va("gfx/2d/crosshair%c", 'a'+i) );
1199 	}
1200 
1201 	cg.loadLCARSStage = 4;
1202 
1203 	cgs.media.backTileShader = trap->R_RegisterShader( "gfx/2d/backtile" );
1204 
1205 	//precache the fpls skin
1206 	//trap->R_RegisterSkin("models/players/kyle/model_fpls2.skin");
1207 
1208 	cgs.media.itemRespawningPlaceholder = trap->R_RegisterShader("powerups/placeholder");
1209 	cgs.media.itemRespawningRezOut = trap->R_RegisterShader("powerups/rezout");
1210 
1211 	cgs.media.playerShieldDamage = trap->R_RegisterShader("gfx/misc/personalshield");
1212 	cgs.media.protectShader = trap->R_RegisterShader("gfx/misc/forceprotect");
1213 	cgs.media.forceSightBubble = trap->R_RegisterShader("gfx/misc/sightbubble");
1214 	cgs.media.forceShell = trap->R_RegisterShader("powerups/forceshell");
1215 	cgs.media.sightShell = trap->R_RegisterShader("powerups/sightshell");
1216 
1217 	cgs.media.itemHoloModel = trap->R_RegisterModel("models/map_objects/mp/holo.md3");
1218 
1219 	if (cgs.gametype == GT_HOLOCRON || com_buildScript.integer)
1220 	{
1221 		for ( i=0; i < NUM_FORCE_POWERS; i++ )
1222 		{
1223 			if (forceHolocronModels[i] &&
1224 				forceHolocronModels[i][0])
1225 			{
1226 				trap->R_RegisterModel(forceHolocronModels[i]);
1227 			}
1228 		}
1229 	}
1230 
1231 	if ( cgs.gametype == GT_CTF || cgs.gametype == GT_CTY || com_buildScript.integer ) {
1232 		if (com_buildScript.integer)
1233 		{
1234 			trap->R_RegisterModel( "models/flags/r_flag.md3" );
1235 			trap->R_RegisterModel( "models/flags/b_flag.md3" );
1236 			trap->R_RegisterModel( "models/flags/r_flag_ysal.md3" );
1237 			trap->R_RegisterModel( "models/flags/b_flag_ysal.md3" );
1238 		}
1239 
1240 		if (cgs.gametype == GT_CTF)
1241 		{
1242 			cgs.media.redFlagModel = trap->R_RegisterModel( "models/flags/r_flag.md3" );
1243 			cgs.media.blueFlagModel = trap->R_RegisterModel( "models/flags/b_flag.md3" );
1244 		}
1245 		else if(cgs.gametype == GT_CTY)
1246 		{
1247 			cgs.media.redFlagModel = trap->R_RegisterModel( "models/flags/r_flag_ysal.md3" );
1248 			cgs.media.blueFlagModel = trap->R_RegisterModel( "models/flags/b_flag_ysal.md3" );
1249 		}
1250 
1251 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_rflag_x" );
1252 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_bflag_x" );
1253 
1254 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_rflag_ys" );
1255 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_bflag_ys" );
1256 
1257 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_rflag" );
1258 		trap->R_RegisterShaderNoMip( "gfx/hud/mpi_bflag" );
1259 
1260 		trap->R_RegisterShaderNoMip("gfx/2d/net.tga");
1261 	}
1262 
1263 	if ( cgs.gametype >= GT_TEAM || com_buildScript.integer ) {
1264 		cgs.media.teamRedShader = trap->R_RegisterShader( "sprites/team_red" );
1265 		cgs.media.teamBlueShader = trap->R_RegisterShader( "sprites/team_blue" );
1266 		//cgs.media.redQuadShader = trap->R_RegisterShader("powerups/blueflag" );
1267 		cgs.media.teamStatusBar = trap->R_RegisterShader( "gfx/2d/colorbar.tga" );
1268 	}
1269 	else if ( cgs.gametype == GT_JEDIMASTER )
1270 	{
1271 		cgs.media.teamRedShader = trap->R_RegisterShader( "sprites/team_red" );
1272 	}
1273 
1274 	if (cgs.gametype == GT_POWERDUEL || com_buildScript.integer)
1275 	{
1276 		cgs.media.powerDuelAllyShader = trap->R_RegisterShader("gfx/mp/pduel_icon_double");//trap->R_RegisterShader("gfx/mp/pduel_gameicon_ally");
1277 	}
1278 
1279 	cgs.media.heartShader			= trap->R_RegisterShaderNoMip( "ui/assets/statusbar/selectedhealth.tga" );
1280 
1281 	cgs.media.ysaliredShader		= trap->R_RegisterShader( "powerups/ysaliredshell");
1282 	cgs.media.ysaliblueShader		= trap->R_RegisterShader( "powerups/ysaliblueshell");
1283 	cgs.media.ysalimariShader		= trap->R_RegisterShader( "powerups/ysalimarishell");
1284 	cgs.media.boonShader			= trap->R_RegisterShader( "powerups/boonshell");
1285 	cgs.media.endarkenmentShader	= trap->R_RegisterShader( "powerups/endarkenmentshell");
1286 	cgs.media.enlightenmentShader	= trap->R_RegisterShader( "powerups/enlightenmentshell");
1287 	cgs.media.invulnerabilityShader = trap->R_RegisterShader( "powerups/invulnerabilityshell");
1288 
1289 #ifdef JK2AWARDS
1290 	cgs.media.medalImpressive		= trap->R_RegisterShaderNoMip( "medal_impressive" );
1291 	cgs.media.medalExcellent		= trap->R_RegisterShaderNoMip( "medal_excellent" );
1292 	cgs.media.medalGauntlet			= trap->R_RegisterShaderNoMip( "medal_gauntlet" );
1293 	cgs.media.medalDefend			= trap->R_RegisterShaderNoMip( "medal_defend" );
1294 	cgs.media.medalAssist			= trap->R_RegisterShaderNoMip( "medal_assist" );
1295 	cgs.media.medalCapture			= trap->R_RegisterShaderNoMip( "medal_capture" );
1296 #endif
1297 
1298 	// Binocular interface
1299 	cgs.media.binocularCircle		= trap->R_RegisterShader( "gfx/2d/binCircle" );
1300 	cgs.media.binocularMask			= trap->R_RegisterShader( "gfx/2d/binMask" );
1301 	cgs.media.binocularArrow		= trap->R_RegisterShader( "gfx/2d/binSideArrow" );
1302 	cgs.media.binocularTri			= trap->R_RegisterShader( "gfx/2d/binTopTri" );
1303 	cgs.media.binocularStatic		= trap->R_RegisterShader( "gfx/2d/binocularWindow" );
1304 	cgs.media.binocularOverlay		= trap->R_RegisterShader( "gfx/2d/binocularNumOverlay" );
1305 
1306 	cg.loadLCARSStage = 5;
1307 
1308 	// Chunk models
1309 	//FIXME: jfm:? bother to conditionally load these if an ent has this material type?
1310 	for ( i = 0; i < NUM_CHUNK_MODELS; i++ )
1311 	{
1312 		cgs.media.chunkModels[CHUNK_METAL2][i]	= trap->R_RegisterModel( va( "models/chunks/metal/metal1_%i.md3", i+1 ) ); //_ /switched\ _
1313 		cgs.media.chunkModels[CHUNK_METAL1][i]	= trap->R_RegisterModel( va( "models/chunks/metal/metal2_%i.md3", i+1 ) ); //  \switched/
1314 		cgs.media.chunkModels[CHUNK_ROCK1][i]	= trap->R_RegisterModel( va( "models/chunks/rock/rock1_%i.md3", i+1 ) );
1315 		cgs.media.chunkModels[CHUNK_ROCK2][i]	= trap->R_RegisterModel( va( "models/chunks/rock/rock2_%i.md3", i+1 ) );
1316 		cgs.media.chunkModels[CHUNK_ROCK3][i]	= trap->R_RegisterModel( va( "models/chunks/rock/rock3_%i.md3", i+1 ) );
1317 		cgs.media.chunkModels[CHUNK_CRATE1][i]	= trap->R_RegisterModel( va( "models/chunks/crate/crate1_%i.md3", i+1 ) );
1318 		cgs.media.chunkModels[CHUNK_CRATE2][i]	= trap->R_RegisterModel( va( "models/chunks/crate/crate2_%i.md3", i+1 ) );
1319 		cgs.media.chunkModels[CHUNK_WHITE_METAL][i]	= trap->R_RegisterModel( va( "models/chunks/metal/wmetal1_%i.md3", i+1 ) );
1320 	}
1321 
1322 	cgs.media.chunkSound			= trap->S_RegisterSound("sound/weapons/explosions/glasslcar");
1323 	cgs.media.grateSound			= trap->S_RegisterSound( "sound/effects/grate_destroy" );
1324 	cgs.media.rockBreakSound		= trap->S_RegisterSound("sound/effects/wall_smash");
1325 	cgs.media.rockBounceSound[0]	= trap->S_RegisterSound("sound/effects/stone_bounce");
1326 	cgs.media.rockBounceSound[1]	= trap->S_RegisterSound("sound/effects/stone_bounce2");
1327 	cgs.media.metalBounceSound[0]	= trap->S_RegisterSound("sound/effects/metal_bounce");
1328 	cgs.media.metalBounceSound[1]	= trap->S_RegisterSound("sound/effects/metal_bounce2");
1329 	cgs.media.glassChunkSound		= trap->S_RegisterSound("sound/weapons/explosions/glassbreak1");
1330 	cgs.media.crateBreakSound[0]	= trap->S_RegisterSound("sound/weapons/explosions/crateBust1" );
1331 	cgs.media.crateBreakSound[1]	= trap->S_RegisterSound("sound/weapons/explosions/crateBust2" );
1332 
1333 /*
1334 Ghoul2 Insert Start
1335 */
1336 	CG_InitItems();
1337 /*
1338 Ghoul2 Insert End
1339 */
1340 	memset( cg_weapons, 0, sizeof( cg_weapons ) );
1341 
1342 	// only register the items that the server says we need
1343 	Q_strncpyz(items, CG_ConfigString(CS_ITEMS), sizeof(items));
1344 
1345 	for ( i = 1 ; i < bg_numItems ; i++ ) {
1346 		if ( items[ i ] == '1' || com_buildScript.integer ) {
1347 			CG_LoadingItem( i );
1348 			CG_RegisterItemVisuals( i );
1349 		}
1350 	}
1351 
1352 	cg.loadLCARSStage = 6;
1353 
1354 	cgs.media.glassShardShader	= trap->R_RegisterShader( "gfx/misc/test_crackle" );
1355 
1356 	// doing one shader just makes it look like a shell.  By using two shaders with different bulge offsets and different texture scales, it has a much more chaotic look
1357 	cgs.media.electricBodyShader			= trap->R_RegisterShader( "gfx/misc/electric" );
1358 	cgs.media.electricBody2Shader			= trap->R_RegisterShader( "gfx/misc/fullbodyelectric2" );
1359 
1360 	cgs.media.fsrMarkShader					= trap->R_RegisterShader( "footstep_r" );
1361 	cgs.media.fslMarkShader					= trap->R_RegisterShader( "footstep_l" );
1362 	cgs.media.fshrMarkShader				= trap->R_RegisterShader( "footstep_heavy_r" );
1363 	cgs.media.fshlMarkShader				= trap->R_RegisterShader( "footstep_heavy_l" );
1364 
1365 	cgs.media.refractionShader				= trap->R_RegisterShader("effects/refraction");
1366 
1367 	cgs.media.cloakedShader					= trap->R_RegisterShader( "gfx/effects/cloakedShader" );
1368 
1369 	// wall marks
1370 	cgs.media.shadowMarkShader	= trap->R_RegisterShader( "markShadow" );
1371 	cgs.media.wakeMarkShader	= trap->R_RegisterShader( "wake" );
1372 
1373 	cgs.media.viewPainShader					= trap->R_RegisterShader( "gfx/misc/borgeyeflare" );
1374 	cgs.media.viewPainShader_Shields			= trap->R_RegisterShader( "gfx/mp/dmgshader_shields" );
1375 	cgs.media.viewPainShader_ShieldsAndHealth	= trap->R_RegisterShader( "gfx/mp/dmgshader_shieldsandhealth" );
1376 
1377 	// register the inline models
1378 	breakPoint = cgs.numInlineModels = trap->CM_NumInlineModels();
1379 	for ( i = 1 ; i < cgs.numInlineModels ; i++ ) {
1380 		char	name[10];
1381 		vec3_t			mins, maxs;
1382 		int				j;
1383 
1384 		Com_sprintf( name, sizeof(name), "*%i", i );
1385 		cgs.inlineDrawModel[i] = trap->R_RegisterModel( name );
1386 		if (!cgs.inlineDrawModel[i])
1387 		{
1388 			breakPoint = i;
1389 			break;
1390 		}
1391 
1392 		trap->R_ModelBounds( cgs.inlineDrawModel[i], mins, maxs );
1393 		for ( j = 0 ; j < 3 ; j++ ) {
1394 			cgs.inlineModelMidpoints[i][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
1395 		}
1396 	}
1397 
1398 	cg.loadLCARSStage = 7;
1399 
1400 	// register all the server specified models
1401 	for (i=1 ; i<MAX_MODELS ; i++) {
1402 		const char		*cModelName;
1403 		char modelName[MAX_QPATH];
1404 
1405 		cModelName = CG_ConfigString( CS_MODELS+i );
1406 		if ( !cModelName[0] ) {
1407 			break;
1408 		}
1409 
1410 		strcpy(modelName, cModelName);
1411 		if (strstr(modelName, ".glm") || modelName[0] == '$')
1412 		{ //Check to see if it has a custom skin attached.
1413 			CG_HandleAppendedSkin(modelName);
1414 			CG_CacheG2AnimInfo(modelName);
1415 		}
1416 
1417 		if (modelName[0] != '$' && modelName[0] != '@')
1418 		{ //don't register vehicle names and saber names as models.
1419 			cgs.gameModels[i] = trap->R_RegisterModel( modelName );
1420 		}
1421 		else
1422 		{//FIXME: register here so that stuff gets precached!!!
1423 			cgs.gameModels[i] = 0;
1424 		}
1425 	}
1426 	cg.loadLCARSStage = 8;
1427 /*
1428 Ghoul2 Insert Start
1429 */
1430 
1431 
1432 //	CG_LoadingString( "BSP instances" );
1433 
1434 	for(i = 1; i < MAX_SUB_BSP; i++)
1435 	{
1436 		const char		*bspName = 0;
1437 		vec3_t			mins, maxs;
1438 		int				j;
1439 		int				sub = 0;
1440 		char			temp[MAX_QPATH];
1441 
1442 		bspName = CG_ConfigString( CS_BSP_MODELS+i );
1443 		if ( !bspName[0] )
1444 		{
1445 			break;
1446 		}
1447 
1448 		trap->CM_LoadMap( bspName, qtrue );
1449 		cgs.inlineDrawModel[breakPoint] = trap->R_RegisterModel( bspName );
1450 		trap->R_ModelBounds( cgs.inlineDrawModel[breakPoint], mins, maxs );
1451 		for ( j = 0 ; j < 3 ; j++ )
1452 		{
1453 			cgs.inlineModelMidpoints[breakPoint][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
1454 		}
1455 		breakPoint++;
1456 		for(sub=1;sub<MAX_MODELS;sub++)
1457 		{
1458 			Com_sprintf(temp, MAX_QPATH, "*%d-%d", i, sub);
1459 			cgs.inlineDrawModel[breakPoint] = trap->R_RegisterModel( temp );
1460 			if (!cgs.inlineDrawModel[breakPoint])
1461 			{
1462 				break;
1463 			}
1464 			trap->R_ModelBounds( cgs.inlineDrawModel[breakPoint], mins, maxs );
1465 			for ( j = 0 ; j < 3 ; j++ )
1466 			{
1467 				cgs.inlineModelMidpoints[breakPoint][j] = mins[j] + 0.5 * ( maxs[j] - mins[j] );
1468 			}
1469 			breakPoint++;
1470 		}
1471 	}
1472 
1473 	/*
1474 	CG_LoadingString("skins");
1475 	// register all the server specified models
1476 	for (i=1 ; i<MAX_CHARSKINS ; i++) {
1477 		const char		*modelName;
1478 
1479 		modelName = CG_ConfigString( CS_CHARSKINS+i );
1480 		if ( !modelName[0] ) {
1481 			break;
1482 		}
1483 		cgs.skins[i] = trap->R_RegisterSkin( modelName );
1484 	}
1485 	*/
1486 	//rww - removed and replaced with CS_G2BONES. For custom skins
1487 	//the new method is to append a * after an indexed model name and
1488 	//then append the skin name after that (note that this is only
1489 	//used for NPCs)
1490 
1491 //	CG_LoadingString("weapons");
1492 
1493 	CG_InitG2Weapons();
1494 
1495 /*
1496 Ghoul2 Insert End
1497 */
1498 	cg.loadLCARSStage = 9;
1499 
1500 
1501 	// new stuff
1502 	cgs.media.patrolShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/patrol.tga");
1503 	cgs.media.assaultShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/assault.tga");
1504 	cgs.media.campShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/camp.tga");
1505 	cgs.media.followShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/follow.tga");
1506 	cgs.media.defendShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/defend.tga");
1507 	cgs.media.retrieveShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/retrieve.tga");
1508 	cgs.media.escortShader = trap->R_RegisterShaderNoMip("ui/assets/statusbar/escort.tga");
1509 	cgs.media.cursor = trap->R_RegisterShaderNoMip( "menu/art/3_cursor2" );
1510 	cgs.media.sizeCursor = trap->R_RegisterShaderNoMip( "ui/assets/sizecursor.tga" );
1511 	cgs.media.selectCursor = trap->R_RegisterShaderNoMip( "ui/assets/selectcursor.tga" );
1512 
1513 	cgs.media.halfShieldModel	= trap->R_RegisterModel ( "models/weaphits/testboom.md3" );
1514 	cgs.media.halfShieldShader	= trap->R_RegisterShader( "halfShieldShell" );
1515 
1516 	trap->FX_RegisterEffect("force/force_touch");
1517 }
1518 
CG_GetStringEdString(char * refSection,char * refName)1519 const char *CG_GetStringEdString(char *refSection, char *refName)
1520 {
1521 	static char text[2][1024];	//just incase it's nested
1522 	static int		index = 0;
1523 
1524 	index ^= 1;
1525 	trap->SE_GetStringTextString(va("%s_%s", refSection, refName), text[index], sizeof(text[0]));
1526 	return text[index];
1527 }
1528 
1529 int	CG_GetClassCount(team_t team,int siegeClass );
1530 int CG_GetTeamNonScoreCount(team_t team);
1531 
CG_SiegeCountCvars(void)1532 void CG_SiegeCountCvars( void )
1533 {
1534 	int classGfx[6];
1535 
1536 	trap->Cvar_Set( "ui_tm1_cnt",va("%d",CG_GetTeamNonScoreCount(TEAM_RED )));
1537 	trap->Cvar_Set( "ui_tm2_cnt",va("%d",CG_GetTeamNonScoreCount(TEAM_BLUE )));
1538 	trap->Cvar_Set( "ui_tm3_cnt",va("%d",CG_GetTeamNonScoreCount(TEAM_SPECTATOR )));
1539 
1540 	// This is because the only way we can match up classes is by the gfx handle.
1541 	classGfx[0] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_infantry");
1542 	classGfx[1] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_heavy_weapons");
1543 	classGfx[2] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_demolitionist");
1544 	classGfx[3] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_vanguard");
1545 	classGfx[4] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_support");
1546 	classGfx[5] = trap->R_RegisterShaderNoMip("gfx/mp/c_icon_jedi_general");
1547 
1548 	trap->Cvar_Set( "ui_tm1_c0_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[0])));
1549 	trap->Cvar_Set( "ui_tm1_c1_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[1])));
1550 	trap->Cvar_Set( "ui_tm1_c2_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[2])));
1551 	trap->Cvar_Set( "ui_tm1_c3_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[3])));
1552 	trap->Cvar_Set( "ui_tm1_c4_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[4])));
1553 	trap->Cvar_Set( "ui_tm1_c5_cnt",va("%d",CG_GetClassCount(TEAM_RED,classGfx[5])));
1554 
1555 	trap->Cvar_Set( "ui_tm2_c0_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[0])));
1556 	trap->Cvar_Set( "ui_tm2_c1_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[1])));
1557 	trap->Cvar_Set( "ui_tm2_c2_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[2])));
1558 	trap->Cvar_Set( "ui_tm2_c3_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[3])));
1559 	trap->Cvar_Set( "ui_tm2_c4_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[4])));
1560 	trap->Cvar_Set( "ui_tm2_c5_cnt",va("%d",CG_GetClassCount(TEAM_BLUE,classGfx[5])));
1561 
1562 }
1563 
1564 /*
1565 =======================
1566 CG_BuildSpectatorString
1567 
1568 =======================
1569 */
CG_BuildSpectatorString(void)1570 void CG_BuildSpectatorString(void) {
1571 	int i;
1572 	cg.spectatorList[0] = 0;
1573 
1574 	// Count up the number of players per team and per class
1575 	CG_SiegeCountCvars();
1576 
1577 	for (i = 0; i < MAX_CLIENTS; i++) {
1578 		if (cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_SPECTATOR ) {
1579 			Q_strcat(cg.spectatorList, sizeof(cg.spectatorList), va("%s     ", cgs.clientinfo[i].name));
1580 		}
1581 	}
1582 	i = strlen(cg.spectatorList);
1583 	if (i != cg.spectatorLen) {
1584 		cg.spectatorLen = i;
1585 		cg.spectatorWidth = -1;
1586 	}
1587 }
1588 
1589 
1590 /*
1591 ===================
1592 CG_RegisterClients
1593 ===================
1594 */
CG_RegisterClients(void)1595 static void CG_RegisterClients( void ) {
1596 	int		i;
1597 
1598 	CG_LoadingClient(cg.clientNum);
1599 	CG_NewClientInfo(cg.clientNum, qfalse);
1600 
1601 	for (i=0 ; i<MAX_CLIENTS ; i++) {
1602 		const char		*clientInfo;
1603 
1604 		if (cg.clientNum == i) {
1605 			continue;
1606 		}
1607 
1608 		clientInfo = CG_ConfigString( CS_PLAYERS+i );
1609 		if ( !clientInfo[0]) {
1610 			continue;
1611 		}
1612 		CG_LoadingClient( i );
1613 		CG_NewClientInfo( i, qfalse);
1614 	}
1615 	CG_BuildSpectatorString();
1616 }
1617 
1618 //===========================================================================
1619 
1620 /*
1621 =================
1622 CG_ConfigString
1623 =================
1624 */
CG_ConfigString(int index)1625 const char *CG_ConfigString( int index ) {
1626 	if ( index < 0 || index >= MAX_CONFIGSTRINGS ) {
1627 		trap->Error( ERR_DROP, "CG_ConfigString: bad index: %i", index );
1628 	}
1629 	return cgs.gameState.stringData + cgs.gameState.stringOffsets[ index ];
1630 }
1631 
1632 //==================================================================
1633 
1634 /*
1635 ======================
1636 CG_StartMusic
1637 
1638 ======================
1639 */
CG_StartMusic(qboolean bForceStart)1640 void CG_StartMusic( qboolean bForceStart ) {
1641 	char	*s;
1642 	char	parm1[MAX_QPATH], parm2[MAX_QPATH];
1643 
1644 	// start the background music
1645 	s = (char *)CG_ConfigString( CS_MUSIC );
1646 	Q_strncpyz( parm1, COM_Parse( (const char **)&s ), sizeof( parm1 ) );
1647 	Q_strncpyz( parm2, COM_Parse( (const char **)&s ), sizeof( parm2 ) );
1648 
1649 	trap->S_StartBackgroundTrack( parm1, parm2, !bForceStart );
1650 }
1651 
CG_GetMenuBuffer(const char * filename)1652 char *CG_GetMenuBuffer(const char *filename) {
1653 	int	len;
1654 	fileHandle_t	f;
1655 	static char buf[MAX_MENUFILE];
1656 
1657 	len = trap->FS_Open( filename, &f, FS_READ );
1658 	if ( !f ) {
1659 		trap->Print( S_COLOR_RED "menu file not found: %s, using default\n", filename );
1660 		return NULL;
1661 	}
1662 	if ( len >= MAX_MENUFILE ) {
1663 		trap->Print( S_COLOR_RED "menu file too large: %s is %i, max allowed is %i\n", filename, len, MAX_MENUFILE );
1664 		trap->FS_Close( f );
1665 		return NULL;
1666 	}
1667 
1668 	trap->FS_Read( buf, len, f );
1669 	buf[len] = 0;
1670 	trap->FS_Close( f );
1671 
1672 	return buf;
1673 }
1674 
1675 //
1676 // ==============================
1677 // new hud stuff ( mission pack )
1678 // ==============================
1679 //
CG_Asset_Parse(int handle)1680 qboolean CG_Asset_Parse(int handle) {
1681 	pc_token_t token;
1682 
1683 	if (!trap->PC_ReadToken(handle, &token))
1684 		return qfalse;
1685 	if (Q_stricmp(token.string, "{") != 0) {
1686 		return qfalse;
1687 	}
1688 
1689 	while ( 1 ) {
1690 		if (!trap->PC_ReadToken(handle, &token))
1691 			return qfalse;
1692 
1693 		if (Q_stricmp(token.string, "}") == 0) {
1694 			return qtrue;
1695 		}
1696 
1697 		// font
1698 		if (Q_stricmp(token.string, "font") == 0) {
1699 			int pointSize;
1700 			if (!trap->PC_ReadToken(handle, &token) || !PC_Int_Parse(handle, &pointSize)) {
1701 				return qfalse;
1702 			}
1703 
1704 //			cgDC.registerFont(token.string, pointSize, &cgDC.Assets.textFont);
1705 			cgDC.Assets.qhMediumFont = cgDC.RegisterFont(token.string);
1706 			continue;
1707 		}
1708 
1709 		// smallFont
1710 		if (Q_stricmp(token.string, "smallFont") == 0) {
1711 			int pointSize;
1712 			if (!trap->PC_ReadToken(handle, &token) || !PC_Int_Parse(handle, &pointSize)) {
1713 				return qfalse;
1714 			}
1715 //			cgDC.registerFont(token.string, pointSize, &cgDC.Assets.smallFont);
1716 			cgDC.Assets.qhSmallFont = cgDC.RegisterFont(token.string);
1717 			continue;
1718 		}
1719 
1720 		// smallFont
1721 		if (Q_stricmp(token.string, "small2Font") == 0) {
1722 			int pointSize;
1723 			if (!trap->PC_ReadToken(handle, &token) || !PC_Int_Parse(handle, &pointSize)) {
1724 				return qfalse;
1725 			}
1726 //			cgDC.registerFont(token.string, pointSize, &cgDC.Assets.smallFont);
1727 			cgDC.Assets.qhSmall2Font = cgDC.RegisterFont(token.string);
1728 			continue;
1729 		}
1730 
1731 		// font
1732 		if (Q_stricmp(token.string, "bigfont") == 0) {
1733 			int pointSize;
1734 			if (!trap->PC_ReadToken(handle, &token) || !PC_Int_Parse(handle, &pointSize)) {
1735 				return qfalse;
1736 			}
1737 //			cgDC.registerFont(token.string, pointSize, &cgDC.Assets.bigFont);
1738 			cgDC.Assets.qhBigFont = cgDC.RegisterFont(token.string);
1739 			continue;
1740 		}
1741 
1742 		// gradientbar
1743 		if (Q_stricmp(token.string, "gradientbar") == 0) {
1744 			if (!trap->PC_ReadToken(handle, &token)) {
1745 				return qfalse;
1746 			}
1747 			cgDC.Assets.gradientBar = trap->R_RegisterShaderNoMip(token.string);
1748 			continue;
1749 		}
1750 
1751 		// enterMenuSound
1752 		if (Q_stricmp(token.string, "menuEnterSound") == 0) {
1753 			if (!trap->PC_ReadToken(handle, &token)) {
1754 				return qfalse;
1755 			}
1756 			cgDC.Assets.menuEnterSound = trap->S_RegisterSound( token.string );
1757 			continue;
1758 		}
1759 
1760 		// exitMenuSound
1761 		if (Q_stricmp(token.string, "menuExitSound") == 0) {
1762 			if (!trap->PC_ReadToken(handle, &token)) {
1763 				return qfalse;
1764 			}
1765 			cgDC.Assets.menuExitSound = trap->S_RegisterSound( token.string );
1766 			continue;
1767 		}
1768 
1769 		// itemFocusSound
1770 		if (Q_stricmp(token.string, "itemFocusSound") == 0) {
1771 			if (!trap->PC_ReadToken(handle, &token)) {
1772 				return qfalse;
1773 			}
1774 			cgDC.Assets.itemFocusSound = trap->S_RegisterSound( token.string );
1775 			continue;
1776 		}
1777 
1778 		// menuBuzzSound
1779 		if (Q_stricmp(token.string, "menuBuzzSound") == 0) {
1780 			if (!trap->PC_ReadToken(handle, &token)) {
1781 				return qfalse;
1782 			}
1783 			cgDC.Assets.menuBuzzSound = trap->S_RegisterSound( token.string );
1784 			continue;
1785 		}
1786 
1787 		if (Q_stricmp(token.string, "cursor") == 0) {
1788 			if (!PC_String_Parse(handle, &cgDC.Assets.cursorStr)) {
1789 				return qfalse;
1790 			}
1791 			cgDC.Assets.cursor = trap->R_RegisterShaderNoMip( cgDC.Assets.cursorStr);
1792 			continue;
1793 		}
1794 
1795 		if (Q_stricmp(token.string, "fadeClamp") == 0) {
1796 			if (!PC_Float_Parse(handle, &cgDC.Assets.fadeClamp)) {
1797 				return qfalse;
1798 			}
1799 			continue;
1800 		}
1801 
1802 		if (Q_stricmp(token.string, "fadeCycle") == 0) {
1803 			if (!PC_Int_Parse(handle, &cgDC.Assets.fadeCycle)) {
1804 				return qfalse;
1805 			}
1806 			continue;
1807 		}
1808 
1809 		if (Q_stricmp(token.string, "fadeAmount") == 0) {
1810 			if (!PC_Float_Parse(handle, &cgDC.Assets.fadeAmount)) {
1811 				return qfalse;
1812 			}
1813 			continue;
1814 		}
1815 
1816 		if (Q_stricmp(token.string, "shadowX") == 0) {
1817 			if (!PC_Float_Parse(handle, &cgDC.Assets.shadowX)) {
1818 				return qfalse;
1819 			}
1820 			continue;
1821 		}
1822 
1823 		if (Q_stricmp(token.string, "shadowY") == 0) {
1824 			if (!PC_Float_Parse(handle, &cgDC.Assets.shadowY)) {
1825 				return qfalse;
1826 			}
1827 			continue;
1828 		}
1829 
1830 		if (Q_stricmp(token.string, "shadowColor") == 0) {
1831 			if (!PC_Color_Parse(handle, &cgDC.Assets.shadowColor)) {
1832 				return qfalse;
1833 			}
1834 			cgDC.Assets.shadowFadeClamp = cgDC.Assets.shadowColor[3];
1835 			continue;
1836 		}
1837 	}
1838 	return qfalse; // bk001204 - why not?
1839 }
1840 
CG_ParseMenu(const char * menuFile)1841 void CG_ParseMenu(const char *menuFile) {
1842 	pc_token_t token;
1843 	int handle;
1844 
1845 	handle = trap->PC_LoadSource(menuFile);
1846 	if (!handle)
1847 		handle = trap->PC_LoadSource("ui/testhud.menu");
1848 	if (!handle)
1849 		return;
1850 
1851 	while ( 1 ) {
1852 		if (!trap->PC_ReadToken( handle, &token )) {
1853 			break;
1854 		}
1855 
1856 		//if ( Q_stricmp( token, "{" ) ) {
1857 		//	Com_Printf( "Missing { in menu file\n" );
1858 		//	break;
1859 		//}
1860 
1861 		//if ( menuCount == MAX_MENUS ) {
1862 		//	Com_Printf( "Too many menus!\n" );
1863 		//	break;
1864 		//}
1865 
1866 		if ( token.string[0] == '}' ) {
1867 			break;
1868 		}
1869 
1870 		if (Q_stricmp(token.string, "assetGlobalDef") == 0) {
1871 			if (CG_Asset_Parse(handle)) {
1872 				continue;
1873 			} else {
1874 				break;
1875 			}
1876 		}
1877 
1878 
1879 		if (Q_stricmp(token.string, "menudef") == 0) {
1880 			// start a new menu
1881 			Menu_New(handle);
1882 		}
1883 	}
1884 	trap->PC_FreeSource(handle);
1885 }
1886 
1887 
CG_Load_Menu(const char ** p)1888 qboolean CG_Load_Menu(const char **p)
1889 {
1890 
1891 	char *token;
1892 
1893 	token = COM_ParseExt((const char **)p, qtrue);
1894 
1895 	if (token[0] != '{') {
1896 		return qfalse;
1897 	}
1898 
1899 	while ( 1 ) {
1900 
1901 		token = COM_ParseExt((const char **)p, qtrue);
1902 
1903 		if (Q_stricmp(token, "}") == 0) {
1904 			return qtrue;
1905 		}
1906 
1907 		if ( !token || token[0] == 0 ) {
1908 			return qfalse;
1909 		}
1910 
1911 		CG_ParseMenu(token);
1912 	}
1913 	return qfalse;
1914 }
1915 
1916 
CG_OwnerDrawHandleKey(int ownerDraw,int flags,float * special,int key)1917 static qboolean CG_OwnerDrawHandleKey(int ownerDraw, int flags, float *special, int key) {
1918 	return qfalse;
1919 }
1920 
1921 
CG_FeederCount(float feederID)1922 static int CG_FeederCount(float feederID) {
1923 	int i, count;
1924 	count = 0;
1925 	if (feederID == FEEDER_REDTEAM_LIST) {
1926 		for (i = 0; i < cg.numScores; i++) {
1927 			if (cg.scores[i].team == TEAM_RED) {
1928 				count++;
1929 			}
1930 		}
1931 	} else if (feederID == FEEDER_BLUETEAM_LIST) {
1932 		for (i = 0; i < cg.numScores; i++) {
1933 			if (cg.scores[i].team == TEAM_BLUE) {
1934 				count++;
1935 			}
1936 		}
1937 	} else if (feederID == FEEDER_SCOREBOARD) {
1938 		return cg.numScores;
1939 	}
1940 	return count;
1941 }
1942 
1943 
CG_SetScoreSelection(void * p)1944 void CG_SetScoreSelection(void *p) {
1945 	menuDef_t *menu = (menuDef_t*)p;
1946 	playerState_t *ps = &cg.snap->ps;
1947 	int i, red, blue;
1948 	red = blue = 0;
1949 	for (i = 0; i < cg.numScores; i++) {
1950 		if (cg.scores[i].team == TEAM_RED) {
1951 			red++;
1952 		} else if (cg.scores[i].team == TEAM_BLUE) {
1953 			blue++;
1954 		}
1955 		if (ps->clientNum == cg.scores[i].client) {
1956 			cg.selectedScore = i;
1957 		}
1958 	}
1959 
1960 	if (menu == NULL) {
1961 		// just interested in setting the selected score
1962 		return;
1963 	}
1964 
1965 	if ( cgs.gametype >= GT_TEAM ) {
1966 		int feeder = FEEDER_REDTEAM_LIST;
1967 		i = red;
1968 		if (cg.scores[cg.selectedScore].team == TEAM_BLUE) {
1969 			feeder = FEEDER_BLUETEAM_LIST;
1970 			i = blue;
1971 		}
1972 		Menu_SetFeederSelection(menu, feeder, i, NULL);
1973 	} else {
1974 		Menu_SetFeederSelection(menu, FEEDER_SCOREBOARD, cg.selectedScore, NULL);
1975 	}
1976 }
1977 
1978 // FIXME: might need to cache this info
CG_InfoFromScoreIndex(int index,int team,int * scoreIndex)1979 static clientInfo_t * CG_InfoFromScoreIndex(int index, int team, int *scoreIndex) {
1980 	int i, count;
1981 	if ( cgs.gametype >= GT_TEAM ) {
1982 		count = 0;
1983 		for (i = 0; i < cg.numScores; i++) {
1984 			if (cg.scores[i].team == team) {
1985 				if (count == index) {
1986 					*scoreIndex = i;
1987 					return &cgs.clientinfo[cg.scores[i].client];
1988 				}
1989 				count++;
1990 			}
1991 		}
1992 	}
1993 	*scoreIndex = index;
1994 	return &cgs.clientinfo[ cg.scores[index].client ];
1995 }
1996 
CG_FeederItemText(float feederID,int index,int column,qhandle_t * handle1,qhandle_t * handle2,qhandle_t * handle3)1997 static const char *CG_FeederItemText(float feederID, int index, int column,
1998 									 qhandle_t *handle1, qhandle_t *handle2, qhandle_t *handle3) {
1999 	gitem_t *item;
2000 	int scoreIndex = 0;
2001 	clientInfo_t *info = NULL;
2002 	int team = -1;
2003 	score_t *sp = NULL;
2004 
2005 	*handle1 = *handle2 = *handle3 = -1;
2006 
2007 	if (feederID == FEEDER_REDTEAM_LIST) {
2008 		team = TEAM_RED;
2009 	} else if (feederID == FEEDER_BLUETEAM_LIST) {
2010 		team = TEAM_BLUE;
2011 	}
2012 
2013 	info = CG_InfoFromScoreIndex(index, team, &scoreIndex);
2014 	sp = &cg.scores[scoreIndex];
2015 
2016 	if (info && info->infoValid) {
2017 		switch (column) {
2018 			case 0:
2019 				if ( info->powerups & ( 1 << PW_NEUTRALFLAG ) ) {
2020 					item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
2021 					*handle1 = cg_items[ ITEM_INDEX(item) ].icon;
2022 				} else if ( info->powerups & ( 1 << PW_REDFLAG ) ) {
2023 					item = BG_FindItemForPowerup( PW_REDFLAG );
2024 					*handle1 = cg_items[ ITEM_INDEX(item) ].icon;
2025 				} else if ( info->powerups & ( 1 << PW_BLUEFLAG ) ) {
2026 					item = BG_FindItemForPowerup( PW_BLUEFLAG );
2027 					*handle1 = cg_items[ ITEM_INDEX(item) ].icon;
2028 				} else {
2029 					/*
2030 					if ( info->botSkill > 0 && info->botSkill <= 5 ) {
2031 						*handle1 = cgs.media.botSkillShaders[ info->botSkill - 1 ];
2032 					} else if ( info->handicap < 100 ) {
2033 					return va("%i", info->handicap );
2034 					}
2035 					*/
2036 				}
2037 			break;
2038 			case 1:
2039 				if (team == -1) {
2040 					return "";
2041 				} else {
2042 					*handle1 = CG_StatusHandle(info->teamTask);
2043 				}
2044 		  break;
2045 			case 2:
2046 				if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << sp->client ) ) {
2047 					return "Ready";
2048 				}
2049 				if (team == -1) {
2050 					if (cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) {
2051 						return va("%i/%i", info->wins, info->losses);
2052 					} else if (info->infoValid && info->team == TEAM_SPECTATOR ) {
2053 						return "Spectator";
2054 					} else {
2055 						return "";
2056 					}
2057 				} else {
2058 					if (info->teamLeader) {
2059 						return "Leader";
2060 					}
2061 				}
2062 			break;
2063 			case 3:
2064 				return info->name;
2065 			break;
2066 			case 4:
2067 				return va("%i", info->score);
2068 			break;
2069 			case 5:
2070 				return va("%4i", sp->time);
2071 			break;
2072 			case 6:
2073 				if ( sp->ping == -1 ) {
2074 					return "connecting";
2075 				}
2076 				return va("%4i", sp->ping);
2077 			break;
2078 		}
2079 	}
2080 
2081 	return "";
2082 }
2083 
CG_FeederItemImage(float feederID,int index)2084 static qhandle_t CG_FeederItemImage(float feederID, int index) {
2085 	return 0;
2086 }
2087 
CG_FeederSelection(float feederID,int index,itemDef_t * item)2088 static qboolean CG_FeederSelection(float feederID, int index, itemDef_t *item) {
2089 	if ( cgs.gametype >= GT_TEAM ) {
2090 		int i, count;
2091 		int team = (feederID == FEEDER_REDTEAM_LIST) ? TEAM_RED : TEAM_BLUE;
2092 		count = 0;
2093 		for (i = 0; i < cg.numScores; i++) {
2094 			if (cg.scores[i].team == team) {
2095 				if (index == count) {
2096 					cg.selectedScore = i;
2097 				}
2098 				count++;
2099 			}
2100 		}
2101 	} else {
2102 		cg.selectedScore = index;
2103 	}
2104 
2105 	return qtrue;
2106 }
2107 
CG_Cvar_Get(const char * cvar)2108 static float CG_Cvar_Get(const char *cvar) {
2109 	char buff[128];
2110 	memset(buff, 0, sizeof(buff));
2111 	trap->Cvar_VariableStringBuffer(cvar, buff, sizeof(buff));
2112 	return atof(buff);
2113 }
2114 
CG_Text_PaintWithCursor(float x,float y,float scale,vec4_t color,const char * text,int cursorPos,char cursor,int limit,int style,int iMenuFont)2115 void CG_Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style, int iMenuFont) {
2116 	CG_Text_Paint(x, y, scale, color, text, 0, limit, style, iMenuFont);
2117 }
2118 
CG_OwnerDrawWidth(int ownerDraw,float scale)2119 static int CG_OwnerDrawWidth(int ownerDraw, float scale) {
2120 	switch (ownerDraw) {
2121 	  case CG_GAME_TYPE:
2122 			return CG_Text_Width(BG_GetGametypeString( cgs.gametype ), scale, FONT_MEDIUM);
2123 	  case CG_GAME_STATUS:
2124 			return CG_Text_Width(CG_GetGameStatusText(), scale, FONT_MEDIUM);
2125 			break;
2126 	  case CG_KILLER:
2127 			return CG_Text_Width(CG_GetKillerText(), scale, FONT_MEDIUM);
2128 			break;
2129 	  case CG_RED_NAME:
2130 			return CG_Text_Width(DEFAULT_REDTEAM_NAME/*cg_redTeamName.string*/, scale, FONT_MEDIUM);
2131 			break;
2132 	  case CG_BLUE_NAME:
2133 			return CG_Text_Width(DEFAULT_BLUETEAM_NAME/*cg_blueTeamName.string*/, scale, FONT_MEDIUM);
2134 			break;
2135 	}
2136 	return 0;
2137 }
2138 
CG_PlayCinematic(const char * name,float x,float y,float w,float h)2139 static int CG_PlayCinematic(const char *name, float x, float y, float w, float h) {
2140 	return trap->CIN_PlayCinematic(name, x, y, w, h, CIN_loop);
2141 }
2142 
CG_StopCinematic(int handle)2143 static void CG_StopCinematic(int handle) {
2144 	trap->CIN_StopCinematic(handle);
2145 }
2146 
CG_DrawCinematic(int handle,float x,float y,float w,float h)2147 static void CG_DrawCinematic(int handle, float x, float y, float w, float h) {
2148 	trap->CIN_SetExtents(handle, x, y, w, h);
2149 	trap->CIN_DrawCinematic(handle);
2150 }
2151 
CG_RunCinematicFrame(int handle)2152 static void CG_RunCinematicFrame(int handle) {
2153 	trap->CIN_RunCinematic(handle);
2154 }
2155 
2156 /*
2157 =================
2158 CG_LoadMenus();
2159 
2160 =================
2161 */
CG_LoadMenus(const char * menuFile)2162 void CG_LoadMenus(const char *menuFile)
2163 {
2164 	const char	*token;
2165 	const char	*p;
2166 	int	len;
2167 	fileHandle_t	f;
2168 	static char buf[MAX_MENUDEFFILE];
2169 
2170 	len = trap->FS_Open( menuFile, &f, FS_READ );
2171 
2172 	if ( !f )
2173 	{
2174 		if( Q_isanumber( menuFile ) ) // cg_hudFiles 1
2175 			trap->Print( S_COLOR_GREEN "hud menu file skipped, using default\n" );
2176 		else
2177 			trap->Print( S_COLOR_YELLOW "hud menu file not found: %s, using default\n", menuFile );
2178 
2179 		len = trap->FS_Open( "ui/jahud.txt", &f, FS_READ );
2180 		if (!f)
2181 		{
2182 			trap->Error( ERR_DROP, S_COLOR_RED "default hud menu file not found: ui/jahud.txt, unable to continue!" );
2183 		}
2184 	}
2185 
2186 	if ( len >= MAX_MENUDEFFILE )
2187 	{
2188 		trap->FS_Close( f );
2189 		trap->Error( ERR_DROP, S_COLOR_RED "menu file too large: %s is %i, max allowed is %i", menuFile, len, MAX_MENUDEFFILE );
2190 	}
2191 
2192 	trap->FS_Read( buf, len, f );
2193 	buf[len] = 0;
2194 	trap->FS_Close( f );
2195 
2196 	p = buf;
2197 
2198 	COM_BeginParseSession ("CG_LoadMenus");
2199 	while ( 1 )
2200 	{
2201 		token = COM_ParseExt( &p, qtrue );
2202 		if( !token || token[0] == 0 || token[0] == '}')
2203 		{
2204 			break;
2205 		}
2206 
2207 		if ( Q_stricmp( token, "}" ) == 0 )
2208 		{
2209 			break;
2210 		}
2211 
2212 		if (Q_stricmp(token, "loadmenu") == 0)
2213 		{
2214 			if (CG_Load_Menu(&p))
2215 			{
2216 				continue;
2217 			}
2218 			else
2219 			{
2220 				break;
2221 			}
2222 		}
2223 	}
2224 
2225 	//Com_Printf("UI menu load time = %d milli seconds\n", cgi_Milliseconds() - start);
2226 }
2227 
2228 /*
2229 =================
2230 CG_LoadHudMenu();
2231 
2232 =================
2233 */
CG_LoadHudMenu()2234 void CG_LoadHudMenu()
2235 {
2236 	const char *hudSet;
2237 
2238 	cgDC.registerShaderNoMip			= trap->R_RegisterShaderNoMip;
2239 	cgDC.setColor						= trap->R_SetColor;
2240 	cgDC.drawHandlePic					= &CG_DrawPic;
2241 	cgDC.drawStretchPic					= trap->R_DrawStretchPic;
2242 	cgDC.drawText						= &CG_Text_Paint;
2243 	cgDC.textWidth						= &CG_Text_Width;
2244 	cgDC.textHeight						= &CG_Text_Height;
2245 	cgDC.registerModel					= trap->R_RegisterModel;
2246 	cgDC.modelBounds					= trap->R_ModelBounds;
2247 	cgDC.fillRect						= &CG_FillRect;
2248 	cgDC.drawRect						= &CG_DrawRect;
2249 	cgDC.drawSides						= &CG_DrawSides;
2250 	cgDC.drawTopBottom					= &CG_DrawTopBottom;
2251 	cgDC.clearScene						= trap->R_ClearScene;
2252 	cgDC.addRefEntityToScene			= trap->R_AddRefEntityToScene;
2253 	cgDC.renderScene					= trap->R_RenderScene;
2254 	cgDC.RegisterFont					= trap->R_RegisterFont;
2255 	cgDC.Font_StrLenPixels				= trap->R_Font_StrLenPixels;
2256 	cgDC.Font_StrLenChars				= trap->R_Font_StrLenChars;
2257 	cgDC.Font_HeightPixels				= trap->R_Font_HeightPixels;
2258 	cgDC.Font_DrawString				= trap->R_Font_DrawString;
2259 	cgDC.Language_IsAsian				= trap->R_Language_IsAsian;
2260 	cgDC.Language_UsesSpaces			= trap->R_Language_UsesSpaces;
2261 	cgDC.AnyLanguage_ReadCharFromString	= trap->R_AnyLanguage_ReadCharFromString;
2262 	cgDC.ownerDrawItem					= &CG_OwnerDraw;
2263 	cgDC.getValue						= &CG_GetValue;
2264 	cgDC.ownerDrawVisible				= &CG_OwnerDrawVisible;
2265 	cgDC.runScript						= &CG_RunMenuScript;
2266 	cgDC.deferScript					= &CG_DeferMenuScript;
2267 	cgDC.getTeamColor					= &CG_GetTeamColor;
2268 	cgDC.setCVar						= trap->Cvar_Set;
2269 	cgDC.getCVarString					= trap->Cvar_VariableStringBuffer;
2270 	cgDC.getCVarValue					= CG_Cvar_Get;
2271 	cgDC.drawTextWithCursor				= &CG_Text_PaintWithCursor;
2272 	//cgDC.setOverstrikeMode			= &trap->Key_SetOverstrikeMode;
2273 	//cgDC.getOverstrikeMode			= &trap->Key_GetOverstrikeMode;
2274 	cgDC.startLocalSound				= trap->S_StartLocalSound;
2275 	cgDC.ownerDrawHandleKey				= &CG_OwnerDrawHandleKey;
2276 	cgDC.feederCount					= &CG_FeederCount;
2277 	cgDC.feederItemImage				= &CG_FeederItemImage;
2278 	cgDC.feederItemText					= &CG_FeederItemText;
2279 	cgDC.feederSelection				= &CG_FeederSelection;
2280 	//cgDC.setBinding					= &trap->Key_SetBinding;
2281 	//cgDC.getBindingBuf				= &trap->Key_GetBindingBuf;
2282 	//cgDC.keynumToStringBuf			= &trap->Key_KeynumToStringBuf;
2283 	//cgDC.executeText					= &trap->Cmd_ExecuteText;
2284 	cgDC.Error							= Com_Error;
2285 	cgDC.Print							= Com_Printf;
2286 	cgDC.ownerDrawWidth					= &CG_OwnerDrawWidth;
2287 	//cgDC.Pause						= &CG_Pause;
2288 	cgDC.registerSound					= trap->S_RegisterSound;
2289 	cgDC.startBackgroundTrack			= trap->S_StartBackgroundTrack;
2290 	cgDC.stopBackgroundTrack			= trap->S_StopBackgroundTrack;
2291 	cgDC.playCinematic					= &CG_PlayCinematic;
2292 	cgDC.stopCinematic					= &CG_StopCinematic;
2293 	cgDC.drawCinematic					= &CG_DrawCinematic;
2294 	cgDC.runCinematicFrame				= &CG_RunCinematicFrame;
2295 	cgDC.ext.Font_StrLenPixels			= trap->ext.R_Font_StrLenPixels;
2296 
2297 
2298 	Init_Display(&cgDC);
2299 
2300 	Menu_Reset();
2301 
2302 	hudSet = cg_hudFiles.string;
2303 	if (hudSet[0] == '\0')
2304 	{
2305 		hudSet = "ui/jahud.txt";
2306 	}
2307 
2308 	CG_LoadMenus(hudSet);
2309 
2310 }
2311 
CG_AssetCache()2312 void CG_AssetCache() {
2313 	//if (Assets.textFont == NULL) {
2314 	//  trap->R_RegisterFont("fonts/arial.ttf", 72, &Assets.textFont);
2315 	//}
2316 	//Com_Printf("Menu Size: %i bytes\n", sizeof(Menus));
2317 	cgDC.Assets.gradientBar = trap->R_RegisterShaderNoMip( ASSET_GRADIENTBAR );
2318 	cgDC.Assets.fxBasePic = trap->R_RegisterShaderNoMip( ART_FX_BASE );
2319 	cgDC.Assets.fxPic[0] = trap->R_RegisterShaderNoMip( ART_FX_RED );
2320 	cgDC.Assets.fxPic[1] = trap->R_RegisterShaderNoMip( ART_FX_YELLOW );
2321 	cgDC.Assets.fxPic[2] = trap->R_RegisterShaderNoMip( ART_FX_GREEN );
2322 	cgDC.Assets.fxPic[3] = trap->R_RegisterShaderNoMip( ART_FX_TEAL );
2323 	cgDC.Assets.fxPic[4] = trap->R_RegisterShaderNoMip( ART_FX_BLUE );
2324 	cgDC.Assets.fxPic[5] = trap->R_RegisterShaderNoMip( ART_FX_CYAN );
2325 	cgDC.Assets.fxPic[6] = trap->R_RegisterShaderNoMip( ART_FX_WHITE );
2326 	cgDC.Assets.scrollBar = trap->R_RegisterShaderNoMip( ASSET_SCROLLBAR );
2327 	cgDC.Assets.scrollBarArrowDown = trap->R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWDOWN );
2328 	cgDC.Assets.scrollBarArrowUp = trap->R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWUP );
2329 	cgDC.Assets.scrollBarArrowLeft = trap->R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWLEFT );
2330 	cgDC.Assets.scrollBarArrowRight = trap->R_RegisterShaderNoMip( ASSET_SCROLLBAR_ARROWRIGHT );
2331 	cgDC.Assets.scrollBarThumb = trap->R_RegisterShaderNoMip( ASSET_SCROLL_THUMB );
2332 	cgDC.Assets.sliderBar = trap->R_RegisterShaderNoMip( ASSET_SLIDER_BAR );
2333 	cgDC.Assets.sliderThumb = trap->R_RegisterShaderNoMip( ASSET_SLIDER_THUMB );
2334 }
2335 
2336 /*
2337 
2338 
2339 /*
2340 Ghoul2 Insert Start
2341 */
2342 
2343 // initialise the cg_entities structure - take into account the ghoul2 stl stuff in the active snap shots
CG_Init_CG(void)2344 void CG_Init_CG(void)
2345 {
2346 	memset( &cg, 0, sizeof(cg));
2347 }
2348 
2349 // initialise the cg_entities structure - take into account the ghoul2 stl stuff
CG_Init_CGents(void)2350 void CG_Init_CGents(void)
2351 {
2352 	memset(&cg_entities, 0, sizeof(cg_entities));
2353 }
2354 
2355 
CG_InitItems(void)2356 void CG_InitItems(void)
2357 {
2358 	memset( cg_items, 0, sizeof( cg_items ) );
2359 }
2360 
CG_TransitionPermanent(void)2361 void CG_TransitionPermanent(void)
2362 {
2363 	centity_t	*cent = cg_entities;
2364 	int			i;
2365 
2366 	cg_numpermanents = 0;
2367 	for(i=0;i<MAX_GENTITIES;i++,cent++)
2368 	{
2369 		if (trap->GetDefaultState(i, &cent->currentState))
2370 		{
2371 			cent->nextState = cent->currentState;
2372 			VectorCopy (cent->currentState.origin, cent->lerpOrigin);
2373 			VectorCopy (cent->currentState.angles, cent->lerpAngles);
2374 			cent->currentValid = qtrue;
2375 
2376 			cg_permanents[cg_numpermanents++] = cent;
2377 		}
2378 	}
2379 }
2380 
2381 /*
2382 Ghoul2 Insert End
2383 */
2384 
2385 extern playerState_t *cgSendPS[MAX_GENTITIES]; //is not MAX_CLIENTS because NPCs exceed MAX_CLIENTS
2386 void CG_PmoveClientPointerUpdate();
2387 
2388 void WP_SaberLoadParms( void );
2389 void BG_VehicleLoadParms( void );
2390 
2391 /*
2392 =================
2393 CG_Init
2394 
2395 Called after every level change or subsystem restart
2396 Will perform callbacks to make the loading info screen update.
2397 =================
2398 */
CG_Init(int serverMessageNum,int serverCommandSequence,int clientNum)2399 void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum )
2400 {
2401 	static gitem_t *item;
2402 	char buf[64];
2403 	const char	*s;
2404 	int i = 0;
2405 
2406 	BG_InitAnimsets(); //clear it out
2407 
2408 	trap->RegisterSharedMemory( cg.sharedBuffer.raw );
2409 
2410 	//Load external vehicle data
2411 	BG_VehicleLoadParms();
2412 
2413 	// clear everything
2414 /*
2415 Ghoul2 Insert Start
2416 */
2417 
2418 //	memset( cg_entities, 0, sizeof( cg_entities ) );
2419 	CG_Init_CGents();
2420 // this is a No-No now we have stl vector classes in here.
2421 //	memset( &cg, 0, sizeof( cg ) );
2422 	CG_Init_CG();
2423 	CG_InitItems();
2424 
2425 	//create the global jetpack instance
2426 	CG_InitJetpackGhoul2();
2427 
2428 	CG_PmoveClientPointerUpdate();
2429 
2430 /*
2431 Ghoul2 Insert End
2432 */
2433 
2434 	//Load sabers.cfg data
2435 	WP_SaberLoadParms();
2436 
2437 	// this is kinda dumb as well, but I need to pre-load some fonts in order to have the text available
2438 	//	to say I'm loading the assets.... which includes loading the fonts. So I'll set these up as reasonable
2439 	//	defaults, then let the menu asset parser (which actually specifies the ingame fonts) load over them
2440 	//	if desired during parse.  Dunno how legal it is to store in these cgDC things, but it causes no harm
2441 	//	and even if/when they get overwritten they'll be legalised by the menu asset parser :-)
2442 //	CG_LoadFonts();
2443 	cgDC.Assets.qhSmallFont  = trap->R_RegisterFont("ocr_a");
2444 	cgDC.Assets.qhMediumFont = trap->R_RegisterFont("ergoec");
2445 	cgDC.Assets.qhBigFont = cgDC.Assets.qhMediumFont;
2446 
2447 	memset( &cgs, 0, sizeof( cgs ) );
2448 	memset( cg_weapons, 0, sizeof(cg_weapons) );
2449 
2450 	cg.clientNum = clientNum;
2451 
2452 	cgs.processedSnapshotNum = serverMessageNum;
2453 	cgs.serverCommandSequence = serverCommandSequence;
2454 
2455 	cg.loadLCARSStage		= 0;
2456 
2457 	cg.itemSelect = -1;
2458 	cg.forceSelect = -1;
2459 
2460 	// load a few needed things before we do any screen updates
2461 	cgs.media.charsetShader		= trap->R_RegisterShaderNoMip( "gfx/2d/charsgrid_med" );
2462 	cgs.media.whiteShader		= trap->R_RegisterShader( "white" );
2463 
2464 	cgs.media.loadBarLED		= trap->R_RegisterShaderNoMip( "gfx/hud/load_tick" );
2465 	cgs.media.loadBarLEDCap		= trap->R_RegisterShaderNoMip( "gfx/hud/load_tick_cap" );
2466 	cgs.media.loadBarLEDSurround= trap->R_RegisterShaderNoMip( "gfx/hud/mp_levelload" );
2467 
2468 	// Force HUD set up
2469 	cg.forceHUDActive = qtrue;
2470 	cg.forceHUDTotalFlashTime = 0;
2471 	cg.forceHUDNextFlashTime = 0;
2472 
2473 	i = WP_NONE+1;
2474 	while (i <= LAST_USEABLE_WEAPON)
2475 	{
2476 		item = BG_FindItemForWeapon(i);
2477 
2478 		if (item && item->icon && item->icon[0])
2479 		{
2480 			cgs.media.weaponIcons[i] = trap->R_RegisterShaderNoMip(item->icon);
2481 			cgs.media.weaponIcons_NA[i] = trap->R_RegisterShaderNoMip(va("%s_na", item->icon));
2482 		}
2483 		else
2484 		{ //make sure it is zero'd (default shader)
2485 			cgs.media.weaponIcons[i] = 0;
2486 			cgs.media.weaponIcons_NA[i] = 0;
2487 		}
2488 		i++;
2489 	}
2490 	trap->Cvar_VariableStringBuffer("com_buildscript", buf, sizeof(buf));
2491 	if (atoi(buf))
2492 	{
2493 		trap->R_RegisterShaderNoMip("gfx/hud/w_icon_saberstaff");
2494 		trap->R_RegisterShaderNoMip("gfx/hud/w_icon_duallightsaber");
2495 	}
2496 	i = 0;
2497 
2498 	// HUD artwork for cycling inventory,weapons and force powers
2499 	cgs.media.weaponIconBackground		= trap->R_RegisterShaderNoMip( "gfx/hud/background");
2500 	cgs.media.forceIconBackground		= trap->R_RegisterShaderNoMip( "gfx/hud/background_f");
2501 	cgs.media.inventoryIconBackground	= trap->R_RegisterShaderNoMip( "gfx/hud/background_i");
2502 
2503 	//rww - precache holdable item icons here
2504 	while (i < bg_numItems)
2505 	{
2506 		if (bg_itemlist[i].giType == IT_HOLDABLE)
2507 		{
2508 			if (bg_itemlist[i].icon)
2509 			{
2510 				cgs.media.invenIcons[bg_itemlist[i].giTag] = trap->R_RegisterShaderNoMip(bg_itemlist[i].icon);
2511 			}
2512 			else
2513 			{
2514 				cgs.media.invenIcons[bg_itemlist[i].giTag] = 0;
2515 			}
2516 		}
2517 
2518 		i++;
2519 	}
2520 
2521 	//rww - precache force power icons here
2522 	i = 0;
2523 
2524 	while (i < NUM_FORCE_POWERS)
2525 	{
2526 		cgs.media.forcePowerIcons[i] = trap->R_RegisterShaderNoMip(HolocronIcons[i]);
2527 
2528 		i++;
2529 	}
2530 	cgs.media.rageRecShader = trap->R_RegisterShaderNoMip("gfx/mp/f_icon_ragerec");
2531 
2532 
2533 	//body decal shaders -rww
2534 	cgs.media.bdecal_bodyburn1 = trap->R_RegisterShader("gfx/damage/bodyburnmark1");
2535 	cgs.media.bdecal_saberglow = trap->R_RegisterShader("gfx/damage/saberglowmark");
2536 	cgs.media.bdecal_burn1 = trap->R_RegisterShader("gfx/damage/bodybigburnmark1");
2537 	cgs.media.mSaberDamageGlow = trap->R_RegisterShader("gfx/effects/saberDamageGlow");
2538 
2539 	CG_RegisterCvars();
2540 
2541 	CG_InitConsoleCommands();
2542 
2543 	cg.renderingThirdPerson = cg_thirdPerson.integer;
2544 
2545 	cg.weaponSelect = WP_BRYAR_PISTOL;
2546 
2547 	cgs.redflag = cgs.blueflag = -1; // For compatibily, default to unset for
2548 	cgs.flagStatus = -1;
2549 	// old servers
2550 
2551 	// get the rendering configuration from the client system
2552 	trap->GetGlconfig( &cgs.glconfig );
2553 	cgs.screenXScale = cgs.glconfig.vidWidth / 640.0;
2554 	cgs.screenYScale = cgs.glconfig.vidHeight / 480.0;
2555 
2556 	// get the gamestate from the client system
2557 	trap->GetGameState( &cgs.gameState );
2558 
2559 	CG_TransitionPermanent(); //rwwRMG - added
2560 
2561 	// check version
2562 	s = CG_ConfigString( CS_GAME_VERSION );
2563 	if ( strcmp( s, GAME_VERSION ) ) {
2564 		trap->Error( ERR_DROP, "Client/Server game mismatch: %s/%s", GAME_VERSION, s );
2565 	}
2566 
2567 	s = CG_ConfigString( CS_LEVEL_START_TIME );
2568 	cgs.levelStartTime = atoi( s );
2569 
2570 	CG_ParseServerinfo();
2571 
2572 	// load the new map
2573 //	CG_LoadingString( "collision map" );
2574 
2575 	trap->CM_LoadMap( cgs.mapname, qfalse );
2576 
2577 	String_Init();
2578 
2579 	cg.loading = qtrue;		// force players to load instead of defer
2580 
2581 	//make sure saber data is loaded before this! (so we can precache the appropriate hilts)
2582 	CG_InitSiegeMode();
2583 
2584 	CG_RegisterSounds();
2585 
2586 //	CG_LoadingString( "graphics" );
2587 
2588 	CG_RegisterGraphics();
2589 
2590 //	CG_LoadingString( "clients" );
2591 
2592 	CG_RegisterClients();		// if low on memory, some clients will be deferred
2593 
2594 	CG_AssetCache();
2595 	CG_LoadHudMenu();      // load new hud stuff
2596 
2597 	cg.loading = qfalse;	// future players will be deferred
2598 
2599 	CG_InitLocalEntities();
2600 
2601 	CG_InitMarkPolys();
2602 
2603 	// remove the last loading update
2604 	cg.infoScreenText[0] = 0;
2605 
2606 	// Make sure we have update values (scores)
2607 	CG_SetConfigValues();
2608 
2609 	CG_StartMusic(qfalse);
2610 
2611 //	CG_LoadingString( "Clearing light styles" );
2612 	CG_ClearLightStyles();
2613 
2614 //	CG_LoadingString( "Creating automap data" );
2615 	//init automap
2616 	trap->R_InitializeWireframeAutomap();
2617 
2618 	CG_LoadingString( "" );
2619 
2620 	CG_ShaderStateChanged();
2621 
2622 	trap->S_ClearLoopingSounds();
2623 
2624 	cg.distanceCull = trap->R_GetDistanceCull();
2625 
2626 	CG_ParseEntitiesFromString();
2627 }
2628 
2629 //makes sure returned string is in localized format
CG_GetLocationString(const char * loc)2630 const char *CG_GetLocationString(const char *loc)
2631 {
2632 	static char text[1024]={0};
2633 
2634 	if (!loc || loc[0] != '@')
2635 	{ //just a raw string
2636 		return loc;
2637 	}
2638 
2639 	trap->SE_GetStringTextString(loc+1, text, sizeof(text));
2640 	return text;
2641 }
2642 
2643 //clean up all the ghoul2 allocations, the nice and non-hackly way -rww
2644 void CG_KillCEntityG2(int entNum);
CG_DestroyAllGhoul2(void)2645 void CG_DestroyAllGhoul2(void)
2646 {
2647 	int i = 0;
2648 	int j;
2649 
2650 //	Com_Printf("... CGameside GHOUL2 Cleanup\n");
2651 	while (i < MAX_GENTITIES)
2652 	{ //free all dynamically allocated npc client info structs and ghoul2 instances
2653 		CG_KillCEntityG2(i);
2654 		i++;
2655 	}
2656 
2657 	//Clean the weapon instances
2658 	CG_ShutDownG2Weapons();
2659 
2660 	i = 0;
2661 	while (i < MAX_ITEMS)
2662 	{ //and now for items
2663 		j = 0;
2664 		while (j < MAX_ITEM_MODELS)
2665 		{
2666 			if (cg_items[i].g2Models[j] && trap->G2_HaveWeGhoul2Models(cg_items[i].g2Models[j]))
2667 			{
2668 				trap->G2API_CleanGhoul2Models(&cg_items[i].g2Models[j]);
2669 				cg_items[i].g2Models[j] = NULL;
2670 			}
2671 			j++;
2672 		}
2673 		i++;
2674 	}
2675 
2676 	//Clean the global jetpack instance
2677 	CG_CleanJetpackGhoul2();
2678 }
2679 
2680 /*
2681 =================
2682 CG_Shutdown
2683 
2684 Called before every level change or subsystem restart
2685 =================
2686 */
CG_Shutdown(void)2687 void CG_Shutdown( void )
2688 {
2689 	BG_ClearAnimsets(); //free all dynamic allocations made through the engine
2690 
2691     CG_DestroyAllGhoul2();
2692 
2693 //	Com_Printf("... FX System Cleanup\n");
2694 	trap->FX_FreeSystem();
2695 	trap->ROFF_Clean();
2696 
2697 	//reset weather
2698 	trap->R_WorldEffectCommand("die");
2699 
2700 	UI_CleanupGhoul2();
2701 	//If there was any ghoul2 stuff in our side of the shared ui code, then remove it now.
2702 
2703 	// some mods may need to do cleanup work here,
2704 	// like closing files or archiving session data
2705 }
2706 
2707 /*
2708 ===============
2709 CG_NextForcePower_f
2710 ===============
2711 */
CG_NextForcePower_f(void)2712 void CG_NextForcePower_f( void )
2713 {
2714 	int current;
2715 	usercmd_t cmd;
2716 	if ( !cg.snap )
2717 	{
2718 		return;
2719 	}
2720 
2721 	if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
2722 	{
2723 		return;
2724 	}
2725 
2726 	current = trap->GetCurrentCmdNumber();
2727 	trap->GetUserCmd(current, &cmd);
2728 	if ((cmd.buttons & BUTTON_USE) || CG_NoUseableForce())
2729 	{
2730 		CG_NextInventory_f();
2731 		return;
2732 	}
2733 
2734 	if (cg.snap->ps.pm_flags & PMF_FOLLOW)
2735 	{
2736 		return;
2737 	}
2738 
2739 //	BG_CycleForce(&cg.snap->ps, 1);
2740 	if (cg.forceSelect != -1)
2741 	{
2742 		cg.snap->ps.fd.forcePowerSelected = cg.forceSelect;
2743 	}
2744 
2745 	BG_CycleForce(&cg.snap->ps, 1);
2746 
2747 	if (cg.snap->ps.fd.forcePowersKnown & (1 << cg.snap->ps.fd.forcePowerSelected))
2748 	{
2749 		cg.forceSelect = cg.snap->ps.fd.forcePowerSelected;
2750 		cg.forceSelectTime = cg.time;
2751 	}
2752 }
2753 
2754 /*
2755 ===============
2756 CG_PrevForcePower_f
2757 ===============
2758 */
CG_PrevForcePower_f(void)2759 void CG_PrevForcePower_f( void )
2760 {
2761 	int current;
2762 	usercmd_t cmd;
2763 	if ( !cg.snap )
2764 	{
2765 		return;
2766 	}
2767 
2768 	if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
2769 	{
2770 		return;
2771 	}
2772 
2773 	current = trap->GetCurrentCmdNumber();
2774 	trap->GetUserCmd(current, &cmd);
2775 	if ((cmd.buttons & BUTTON_USE) || CG_NoUseableForce())
2776 	{
2777 		CG_PrevInventory_f();
2778 		return;
2779 	}
2780 
2781 	if (cg.snap->ps.pm_flags & PMF_FOLLOW)
2782 	{
2783 		return;
2784 	}
2785 
2786 //	BG_CycleForce(&cg.snap->ps, -1);
2787 	if (cg.forceSelect != -1)
2788 	{
2789 		cg.snap->ps.fd.forcePowerSelected = cg.forceSelect;
2790 	}
2791 
2792 	BG_CycleForce(&cg.snap->ps, -1);
2793 
2794 	if (cg.snap->ps.fd.forcePowersKnown & (1 << cg.snap->ps.fd.forcePowerSelected))
2795 	{
2796 		cg.forceSelect = cg.snap->ps.fd.forcePowerSelected;
2797 		cg.forceSelectTime = cg.time;
2798 	}
2799 }
2800 
CG_NextInventory_f(void)2801 void CG_NextInventory_f(void)
2802 {
2803 	if ( !cg.snap )
2804 	{
2805 		return;
2806 	}
2807 
2808 	if (cg.snap->ps.pm_flags & PMF_FOLLOW)
2809 	{
2810 		return;
2811 	}
2812 
2813 	if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
2814 	{
2815 		return;
2816 	}
2817 
2818 	if (cg.itemSelect != -1)
2819 	{
2820 		cg.snap->ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(cg.itemSelect, IT_HOLDABLE);
2821 	}
2822 	BG_CycleInven(&cg.snap->ps, 1);
2823 
2824 	if (cg.snap->ps.stats[STAT_HOLDABLE_ITEM])
2825 	{
2826 		cg.itemSelect = bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag;
2827 		cg.invenSelectTime = cg.time;
2828 	}
2829 }
2830 
CG_PrevInventory_f(void)2831 void CG_PrevInventory_f(void)
2832 {
2833 	if ( !cg.snap )
2834 	{
2835 		return;
2836 	}
2837 
2838 	if (cg.snap->ps.pm_flags & PMF_FOLLOW)
2839 	{
2840 		return;
2841 	}
2842 
2843 	if (cg.predictedPlayerState.pm_type == PM_SPECTATOR)
2844 	{
2845 		return;
2846 	}
2847 
2848 	if (cg.itemSelect != -1)
2849 	{
2850 		cg.snap->ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(cg.itemSelect, IT_HOLDABLE);
2851 	}
2852 	BG_CycleInven(&cg.snap->ps, -1);
2853 
2854 	if (cg.snap->ps.stats[STAT_HOLDABLE_ITEM])
2855 	{
2856 		cg.itemSelect = bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag;
2857 		cg.invenSelectTime = cg.time;
2858 	}
2859 }
2860 
_CG_MouseEvent(int x,int y)2861 static void _CG_MouseEvent( int x, int y ) {
2862 	cgDC.cursorx = cgs.cursorX;
2863 	cgDC.cursory = cgs.cursorY;
2864 	CG_MouseEvent( x, y );
2865 }
2866 
CG_IncomingConsoleCommand(void)2867 static qboolean CG_IncomingConsoleCommand( void ) {
2868 	//rww - let mod authors filter client console messages so they can cut them off if they want.
2869 	//return qtrue if the command is ok. Otherwise, you can set char 0 on the command str to 0 and return
2870 	//qfalse to not execute anything, or you can fill conCommand in with something valid and return 0
2871 	//in order to have that string executed in place. Some example code:
2872 #if 0
2873 	TCGIncomingConsoleCommand *icc = &cg.sharedBuffer.icc;
2874 	if ( strstr( icc->conCommand, "wait" ) )
2875 	{ //filter out commands contaning wait
2876 		Com_Printf( "You can't use commands containing the string wait with MyMod v1.0\n" );
2877 		icc->conCommand[0] = 0;
2878 		return qfalse;
2879 	}
2880 	else if ( strstr( icc->conCommand, "blah" ) )
2881 	{ //any command containing the string "blah" is redirected to "quit"
2882 		strcpy( icc->conCommand, "quit" );
2883 		return qfalse;
2884 	}
2885 #endif
2886 	return qtrue;
2887 }
2888 
CG_GetOrigin(int entID,vec3_t out)2889 static void CG_GetOrigin( int entID, vec3_t out ) {
2890 	VectorCopy( cg_entities[entID].currentState.pos.trBase, out );
2891 }
2892 
CG_GetAngles(int entID,vec3_t out)2893 static void CG_GetAngles( int entID, vec3_t out ) {
2894 	VectorCopy( cg_entities[entID].currentState.apos.trBase, out );
2895 }
2896 
CG_GetOriginTrajectory(int entID)2897 static trajectory_t *CG_GetOriginTrajectory( int entID ) {
2898 	return &cg_entities[entID].nextState.pos;
2899 }
2900 
CG_GetAngleTrajectory(int entID)2901 static trajectory_t *CG_GetAngleTrajectory( int entID ) {
2902 	return &cg_entities[entID].nextState.apos;
2903 }
2904 
_CG_ROFF_NotetrackCallback(int entID,const char * notetrack)2905 static void _CG_ROFF_NotetrackCallback( int entID, const char *notetrack ) {
2906 	CG_ROFF_NotetrackCallback( &cg_entities[entID], notetrack );
2907 }
2908 
CG_MapChange(void)2909 static void CG_MapChange( void ) {
2910 	// this may be called more than once for a given map change, as the server is going to attempt to send out
2911 	// multiple broadcasts in hopes that the client will receive one of them
2912 	cg.mMapChange = qtrue;
2913 }
2914 
CG_AutomapInput(void)2915 static void CG_AutomapInput( void ) {
2916 	autoMapInput_t *autoInput = &cg.sharedBuffer.autoMapInput;
2917 
2918 	memcpy( &cg_autoMapInput, autoInput, sizeof( autoMapInput_t ) );
2919 
2920 #if 0
2921 	if ( !arg0 ) //if this is non-0, it's actually a one-frame mouse event
2922 		cg_autoMapInputTime = cg.time + 1000;
2923 	else
2924 #endif
2925 	{
2926 		if ( cg_autoMapInput.yaw )		cg_autoMapAngle[YAW] += cg_autoMapInput.yaw;
2927 		if ( cg_autoMapInput.pitch )	cg_autoMapAngle[PITCH] += cg_autoMapInput.pitch;
2928 		cg_autoMapInput.yaw = 0.0f;
2929 		cg_autoMapInput.pitch = 0.0f;
2930 	}
2931 }
2932 
CG_FX_CameraShake(void)2933 static void CG_FX_CameraShake( void ) {
2934 	TCGCameraShake *data = &cg.sharedBuffer.cameraShake;
2935 	CG_DoCameraShake( data->mOrigin, data->mIntensity, data->mRadius, data->mTime );
2936 }
2937 
2938 /*
2939 ============
2940 GetModuleAPI
2941 ============
2942 */
2943 
2944 cgameImport_t *trap = NULL;
2945 
GetModuleAPI(int apiVersion,cgameImport_t * import)2946 Q_EXPORT cgameExport_t* QDECL GetModuleAPI( int apiVersion, cgameImport_t *import )
2947 {
2948 	static cgameExport_t cge = {0};
2949 
2950 	assert( import );
2951 	trap = import;
2952 	Com_Printf	= trap->Print;
2953 	Com_Error	= trap->Error;
2954 
2955 	memset( &cge, 0, sizeof( cge ) );
2956 
2957 	if ( apiVersion != CGAME_API_VERSION ) {
2958 		trap->Print( "Mismatched CGAME_API_VERSION: expected %i, got %i\n", CGAME_API_VERSION, apiVersion );
2959 		return NULL;
2960 	}
2961 
2962 	cge.Init					= CG_Init;
2963 	cge.Shutdown				= CG_Shutdown;
2964 	cge.ConsoleCommand			= CG_ConsoleCommand;
2965 	cge.DrawActiveFrame			= CG_DrawActiveFrame;
2966 	cge.CrosshairPlayer			= CG_CrosshairPlayer;
2967 	cge.LastAttacker			= CG_LastAttacker;
2968 	cge.KeyEvent				= CG_KeyEvent;
2969 	cge.MouseEvent				= _CG_MouseEvent;
2970 	cge.EventHandling			= CG_EventHandling;
2971 	cge.PointContents			= C_PointContents;
2972 	cge.GetLerpOrigin			= C_GetLerpOrigin;
2973 	cge.GetLerpData				= C_GetLerpData;
2974 	cge.Trace					= C_Trace;
2975 	cge.G2Trace					= C_G2Trace;
2976 	cge.G2Mark					= C_G2Mark;
2977 	cge.RagCallback				= CG_RagCallback;
2978 	cge.IncomingConsoleCommand	= CG_IncomingConsoleCommand;
2979 	cge.NoUseableForce			= CG_NoUseableForce;
2980 	cge.GetOrigin				= CG_GetOrigin;
2981 	cge.GetAngles				= CG_GetAngles;
2982 	cge.GetOriginTrajectory		= CG_GetOriginTrajectory;
2983 	cge.GetAngleTrajectory		= CG_GetAngleTrajectory;
2984 	cge.ROFF_NotetrackCallback	= _CG_ROFF_NotetrackCallback;
2985 	cge.MapChange				= CG_MapChange;
2986 	cge.AutomapInput			= CG_AutomapInput;
2987 	cge.MiscEnt					= CG_MiscEnt;
2988 	cge.CameraShake				= CG_FX_CameraShake;
2989 
2990 	return &cge;
2991 }
2992 
2993 /*
2994 ================
2995 vmMain
2996 
2997 This is the only way control passes into the module.
2998 This must be the very first function compiled into the .q3vm file
2999 ================
3000 */
vmMain(int 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)3001 Q_EXPORT intptr_t vmMain( int command, intptr_t arg0, intptr_t arg1, intptr_t arg2, intptr_t arg3, intptr_t arg4,
3002 	intptr_t arg5, intptr_t arg6, intptr_t arg7, intptr_t arg8, intptr_t arg9, intptr_t arg10, intptr_t arg11 )
3003 {
3004 	switch ( command ) {
3005 	case CG_INIT:
3006 		CG_Init( arg0, arg1, arg2 );
3007 		return 0;
3008 
3009 	case CG_SHUTDOWN:
3010 		CG_Shutdown();
3011 		return 0;
3012 
3013 	case CG_CONSOLE_COMMAND:
3014 		return CG_ConsoleCommand();
3015 
3016 	case CG_DRAW_ACTIVE_FRAME:
3017 		CG_DrawActiveFrame( arg0, arg1, arg2 );
3018 		return 0;
3019 
3020 	case CG_CROSSHAIR_PLAYER:
3021 		return CG_CrosshairPlayer();
3022 
3023 	case CG_LAST_ATTACKER:
3024 		return CG_LastAttacker();
3025 
3026 	case CG_KEY_EVENT:
3027 		CG_KeyEvent( arg0, arg1 );
3028 		return 0;
3029 
3030 	case CG_MOUSE_EVENT:
3031 		_CG_MouseEvent( arg0, arg1 );
3032 		return 0;
3033 
3034 	case CG_EVENT_HANDLING:
3035 		CG_EventHandling( arg0 );
3036 		return 0;
3037 
3038 	case CG_POINT_CONTENTS:
3039 		return C_PointContents();
3040 
3041 	case CG_GET_LERP_ORIGIN:
3042 		C_GetLerpOrigin();
3043 		return 0;
3044 
3045 	case CG_GET_LERP_DATA:
3046 		C_GetLerpData();
3047 		return 0;
3048 
3049 	case CG_GET_GHOUL2:
3050 		return (intptr_t)cg_entities[arg0].ghoul2; //NOTE: This is used by the effect bolting which is actually not used at all.
3051 											  //I'm fairly sure if you try to use it with vm's it will just give you total
3052 											  //garbage. In other words, use at your own risk.
3053 
3054 	case CG_GET_MODEL_LIST:
3055 		return (intptr_t)cgs.gameModels;
3056 
3057 	case CG_CALC_LERP_POSITIONS:
3058 		CG_CalcEntityLerpPositions( &cg_entities[arg0] );
3059 		return 0;
3060 
3061 	case CG_TRACE:
3062 		C_Trace();
3063 		return 0;
3064 
3065 	case CG_GET_SORTED_FORCE_POWER:
3066 		return forcePowerSorted[arg0];
3067 
3068 	case CG_G2TRACE:
3069 		C_G2Trace();
3070 		return 0;
3071 
3072 	case CG_G2MARK:
3073 		C_G2Mark();
3074 		return 0;
3075 
3076 	case CG_RAG_CALLBACK:
3077 		return CG_RagCallback( arg0 );
3078 
3079 	case CG_INCOMING_CONSOLE_COMMAND:
3080 		return CG_IncomingConsoleCommand();
3081 
3082 	case CG_GET_USEABLE_FORCE:
3083 		return CG_NoUseableForce();
3084 
3085 	case CG_GET_ORIGIN:
3086 		CG_GetOrigin( arg0, (float *)arg1 );
3087 		return 0;
3088 
3089 	case CG_GET_ANGLES:
3090 		CG_GetAngles( arg0, (float *)arg1 );
3091 		return 0;
3092 
3093 	case CG_GET_ORIGIN_TRAJECTORY:
3094 		return (intptr_t)CG_GetOriginTrajectory( arg0 );
3095 
3096 	case CG_GET_ANGLE_TRAJECTORY:
3097 		return (intptr_t)CG_GetAngleTrajectory( arg0 );
3098 
3099 	case CG_ROFF_NOTETRACK_CALLBACK:
3100 		_CG_ROFF_NotetrackCallback( arg0, (const char *)arg1 );
3101 		return 0;
3102 
3103 	case CG_IMPACT_MARK:
3104 		C_ImpactMark();
3105 		return 0;
3106 
3107 	case CG_MAP_CHANGE:
3108 		CG_MapChange();
3109 		return 0;
3110 
3111 	case CG_AUTOMAP_INPUT:
3112 		CG_AutomapInput();
3113 		return 0;
3114 
3115 	case CG_MISC_ENT:
3116 		CG_MiscEnt();
3117 		return 0;
3118 
3119 	case CG_FX_CAMERASHAKE:
3120 		CG_FX_CameraShake();
3121 		return 0;
3122 
3123 	default:
3124 		trap->Error( ERR_DROP, "vmMain: unknown command %i", command );
3125 		break;
3126 	}
3127 	return -1;
3128 }
3129