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, ¢->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