codemp/cgame/cg_weapons.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 // cg_weapons.c -- events and effects dealing with weapons
00004 #include "cg_local.h"
00005 #include "fx_local.h"
00006 
00007 extern vec4_t   bluehudtint;
00008 extern vec4_t   redhudtint;
00009 extern float    *hudTintColor;
00010 
00011 /*
00012 Ghoul2 Insert Start
00013 */
00014 // set up the appropriate ghoul2 info to a refent
00015 void CG_SetGhoul2InfoRef( refEntity_t *ent, refEntity_t *s1)
00016 {
00017         ent->ghoul2 = s1->ghoul2;
00018         VectorCopy( s1->modelScale, ent->modelScale);
00019         ent->radius = s1->radius;
00020         VectorCopy( s1->angles, ent->angles);
00021 }
00022 
00023 /*
00024 Ghoul2 Insert End
00025 */
00026 
00027 /*
00028 =================
00029 CG_RegisterItemVisuals
00030 
00031 The server says this item is used on this level
00032 =================
00033 */
00034 void CG_RegisterItemVisuals( int itemNum ) {
00035         itemInfo_t              *itemInfo;
00036         gitem_t                 *item;
00037         int                             handle;
00038 
00039         if ( itemNum < 0 || itemNum >= bg_numItems ) {
00040                 CG_Error( "CG_RegisterItemVisuals: itemNum %d out of range [0-%d]", itemNum, bg_numItems-1 );
00041         }
00042 
00043         itemInfo = &cg_items[ itemNum ];
00044         if ( itemInfo->registered ) {
00045                 return;
00046         }
00047 
00048         item = &bg_itemlist[ itemNum ];
00049 
00050         memset( itemInfo, 0, sizeof( &itemInfo ) );
00051         itemInfo->registered = qtrue;
00052 
00053         if (item->giType == IT_TEAM &&
00054                 (item->giTag == PW_REDFLAG || item->giTag == PW_BLUEFLAG) &&
00055                 cgs.gametype == GT_CTY)
00056         { //in CTY the flag model is different
00057                 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[1] );
00058         }
00059         else if (item->giType == IT_WEAPON &&
00060                 (item->giTag == WP_THERMAL || item->giTag == WP_TRIP_MINE || item->giTag == WP_DET_PACK))
00061         {
00062                 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[1] );
00063         }
00064         else
00065         {
00066                 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[0] );
00067         }
00068 /*
00069 Ghoul2 Insert Start
00070 */
00071         if (!Q_stricmp(&item->world_model[0][strlen(item->world_model[0]) - 4], ".glm"))
00072         {
00073                 handle = trap_G2API_InitGhoul2Model(&itemInfo->g2Models[0], item->world_model[0], 0 , 0, 0, 0, 0);
00074                 if (handle<0)
00075                 {
00076                         itemInfo->g2Models[0] = NULL;
00077                 }
00078                 else
00079                 {
00080                         itemInfo->radius[0] = 60;
00081                 }
00082         }
00083 /*
00084 Ghoul2 Insert End
00085 */
00086         if (item->icon)
00087         {
00088                 if (item->giType == IT_HEALTH)
00089                 { //medpack gets nomip'd by the ui or something I guess.
00090                         itemInfo->icon = trap_R_RegisterShaderNoMip( item->icon );
00091                 }
00092                 else
00093                 {
00094                         itemInfo->icon = trap_R_RegisterShader( item->icon );
00095                 }
00096         }
00097         else
00098         {
00099                 itemInfo->icon = 0;
00100         }
00101 
00102         if ( item->giType == IT_WEAPON ) {
00103                 CG_RegisterWeapon( item->giTag );
00104         }
00105 
00106         //
00107         // powerups have an accompanying ring or sphere
00108         //
00109         if ( item->giType == IT_POWERUP || item->giType == IT_HEALTH || 
00110                 item->giType == IT_ARMOR || item->giType == IT_HOLDABLE ) {
00111                 if ( item->world_model[1] ) {
00112                         itemInfo->models[1] = trap_R_RegisterModel( item->world_model[1] );
00113                 }
00114         }
00115 }
00116 
00117 
00118 /*
00119 ========================================================================================
00120 
00121 VIEW WEAPON
00122 
00123 ========================================================================================
00124 */
00125 
00126 #define WEAPON_FORCE_BUSY_HOLSTER
00127 
00128 #ifdef WEAPON_FORCE_BUSY_HOLSTER
00129 //rww - this was done as a last resort. Forgive me.
00130 static int cgWeapFrame = 0;
00131 static int cgWeapFrameTime = 0;
00132 #endif
00133 
00134 /*
00135 =================
00136 CG_MapTorsoToWeaponFrame
00137 
00138 =================
00139 */
00140 static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame, int animNum ) {
00141         animation_t *animations = bgHumanoidAnimations;
00142 #ifdef WEAPON_FORCE_BUSY_HOLSTER
00143         if (cg.snap->ps.forceHandExtend != HANDEXTEND_NONE || cgWeapFrameTime > cg.time)
00144         { //the reason for the after delay is so that it doesn't snap the weapon frame to the "idle" (0) frame
00145                 //for a very quick moment
00146                 if (cgWeapFrame < 6)
00147                 {
00148                         cgWeapFrame = 6;
00149                         cgWeapFrameTime = cg.time + 10;
00150                 }
00151 
00152                 if (cgWeapFrameTime < cg.time && cgWeapFrame < 10)
00153                 {
00154                         cgWeapFrame++;
00155                         cgWeapFrameTime = cg.time + 10;
00156                 }
00157 
00158                 if (cg.snap->ps.forceHandExtend != HANDEXTEND_NONE &&
00159                         cgWeapFrame == 10)
00160                 {
00161                         cgWeapFrameTime = cg.time + 100;
00162                 }
00163 
00164                 return cgWeapFrame;
00165         }
00166         else
00167         {
00168                 cgWeapFrame = 0;
00169                 cgWeapFrameTime = 0;
00170         }
00171 #endif
00172 
00173         switch( animNum )
00174         {
00175         case TORSO_DROPWEAP1:
00176                 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 5 ) 
00177                 {
00178                         return frame - animations[animNum].firstFrame + 6;
00179                 }
00180                 break;
00181 
00182         case TORSO_RAISEWEAP1:
00183                 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 4 ) 
00184                 {
00185                         return frame - animations[animNum].firstFrame + 6 + 4;
00186                 }
00187                 break;
00188         case BOTH_ATTACK1:
00189         case BOTH_ATTACK2:
00190         case BOTH_ATTACK3:
00191         case BOTH_ATTACK4:
00192         case BOTH_ATTACK10:
00193         case BOTH_THERMAL_THROW:
00194                 if ( frame >= animations[animNum].firstFrame && frame < animations[animNum].firstFrame + 6 ) 
00195                 {
00196                         return 1 + ( frame - animations[animNum].firstFrame );
00197                 }
00198 
00199                 break;
00200         }       
00201         return -1;
00202 }
00203 
00204 
00205 /*
00206 ==============
00207 CG_CalculateWeaponPosition
00208 ==============
00209 */
00210 static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
00211         float   scale;
00212         int             delta;
00213         float   fracsin;
00214 
00215         VectorCopy( cg.refdef.vieworg, origin );
00216         VectorCopy( cg.refdef.viewangles, angles );
00217 
00218         // on odd legs, invert some angles
00219         if ( cg.bobcycle & 1 ) {
00220                 scale = -cg.xyspeed;
00221         } else {
00222                 scale = cg.xyspeed;
00223         }
00224 
00225         // gun angles from bobbing
00226         angles[ROLL] += scale * cg.bobfracsin * 0.005;
00227         angles[YAW] += scale * cg.bobfracsin * 0.01;
00228         angles[PITCH] += cg.xyspeed * cg.bobfracsin * 0.005;
00229 
00230         // drop the weapon when landing
00231         delta = cg.time - cg.landTime;
00232         if ( delta < LAND_DEFLECT_TIME ) {
00233                 origin[2] += cg.landChange*0.25 * delta / LAND_DEFLECT_TIME;
00234         } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
00235                 origin[2] += cg.landChange*0.25 * 
00236                         (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME;
00237         }
00238 
00239 #if 0
00240         // drop the weapon when stair climbing
00241         delta = cg.time - cg.stepTime;
00242         if ( delta < STEP_TIME/2 ) {
00243                 origin[2] -= cg.stepChange*0.25 * delta / (STEP_TIME/2);
00244         } else if ( delta < STEP_TIME ) {
00245                 origin[2] -= cg.stepChange*0.25 * (STEP_TIME - delta) / (STEP_TIME/2);
00246         }
00247 #endif
00248 
00249         // idle drift
00250         scale = cg.xyspeed + 40;
00251         fracsin = sin( cg.time * 0.001 );
00252         angles[ROLL] += scale * fracsin * 0.01;
00253         angles[YAW] += scale * fracsin * 0.01;
00254         angles[PITCH] += scale * fracsin * 0.01;
00255 }
00256 
00257 
00258 /*
00259 ===============
00260 CG_LightningBolt
00261 
00262 Origin will be the exact tag point, which is slightly
00263 different than the muzzle point used for determining hits.
00264 The cent should be the non-predicted cent if it is from the player,
00265 so the endpoint will reflect the simulated strike (lagging the predicted
00266 angle)
00267 ===============
00268 */
00269 static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
00270 //      trace_t  trace;
00271         refEntity_t  beam;
00272 //      vec3_t   forward;
00273 //      vec3_t   muzzlePoint, endPoint;
00274 
00275         //Must be a durational weapon that continuously generates an effect.
00276         if ( cent->currentState.weapon == WP_DEMP2 && cent->currentState.eFlags & EF_ALT_FIRING ) 
00277         { /*nothing*/ }
00278         else
00279         {
00280                 return;
00281         }
00282 
00283         memset( &beam, 0, sizeof( beam ) );
00284 
00285         // NOTENOTE No lightning gun-ish stuff yet.
00286 /*
00287         // CPMA  "true" lightning
00288         if ((cent->currentState.number == cg.predictedPlayerState.clientNum) && (cg_trueLightning.value != 0)) {
00289                 vec3_t angle;
00290                 int i;
00291 
00292                 for (i = 0; i < 3; i++) {
00293                         float a = cent->lerpAngles[i] - cg.refdef.viewangles[i];
00294                         if (a > 180) {
00295                                 a -= 360;
00296                         }
00297                         if (a < -180) {
00298                                 a += 360;
00299                         }
00300 
00301                         angle[i] = cg.refdef.viewangles[i] + a * (1.0 - cg_trueLightning.value);
00302                         if (angle[i] < 0) {
00303                                 angle[i] += 360;
00304                         }
00305                         if (angle[i] > 360) {
00306                                 angle[i] -= 360;
00307                         }
00308                 }
00309 
00310                 AngleVectors(angle, forward, NULL, NULL );
00311                 VectorCopy(cent->lerpOrigin, muzzlePoint );
00312 //              VectorCopy(cg.refdef.vieworg, muzzlePoint );
00313         } else {
00314                 // !CPMA
00315                 AngleVectors( cent->lerpAngles, forward, NULL, NULL );
00316                 VectorCopy(cent->lerpOrigin, muzzlePoint );
00317         }
00318 
00319         // FIXME: crouch
00320         muzzlePoint[2] += DEFAULT_VIEWHEIGHT;
00321 
00322         VectorMA( muzzlePoint, 14, forward, muzzlePoint );
00323 
00324         // project forward by the lightning range
00325         VectorMA( muzzlePoint, LIGHTNING_RANGE, forward, endPoint );
00326 
00327         // see if it hit a wall
00328         CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint, 
00329                 cent->currentState.number, MASK_SHOT );
00330 
00331         // this is the endpoint
00332         VectorCopy( trace.endpos, beam.oldorigin );
00333 
00334         // use the provided origin, even though it may be slightly
00335         // different than the muzzle origin
00336         VectorCopy( origin, beam.origin );
00337 
00338         beam.reType = RT_LIGHTNING;
00339         beam.customShader = cgs.media.lightningShader;
00340         trap_R_AddRefEntityToScene( &beam );
00341 */
00342 
00343         // NOTENOTE No lightning gun-ish stuff yet.
00344 /*
00345         // add the impact flare if it hit something
00346         if ( trace.fraction < 1.0 ) {
00347                 vec3_t  angles;
00348                 vec3_t  dir;
00349 
00350                 VectorSubtract( beam.oldorigin, beam.origin, dir );
00351                 VectorNormalize( dir );
00352 
00353                 memset( &beam, 0, sizeof( beam ) );
00354                 beam.hModel = cgs.media.lightningExplosionModel;
00355 
00356                 VectorMA( trace.endpos, -16, dir, beam.origin );
00357 
00358                 // make a random orientation
00359                 angles[0] = rand() % 360;
00360                 angles[1] = rand() % 360;
00361                 angles[2] = rand() % 360;
00362                 AnglesToAxis( angles, beam.axis );
00363                 trap_R_AddRefEntityToScene( &beam );
00364         }
00365 */
00366 }
00367 
00368 
00369 /*
00370 ========================
00371 CG_AddWeaponWithPowerups
00372 ========================
00373 */
00374 static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) {
00375         // add powerup effects
00376         trap_R_AddRefEntityToScene( gun );
00377 
00378         if (cg.predictedPlayerState.electrifyTime > cg.time)
00379         { //add electrocution shell
00380                 int preShader = gun->customShader;
00381                 if ( rand() & 1 )
00382                 {
00383                         gun->customShader = cgs.media.electricBodyShader;       
00384                 }
00385                 else
00386                 {
00387                         gun->customShader = cgs.media.electricBody2Shader;
00388                 }
00389                 trap_R_AddRefEntityToScene( gun );
00390                 gun->customShader = preShader; //set back just to be safe
00391         }
00392 }
00393 
00394 
00395 /*
00396 =============
00397 CG_AddPlayerWeapon
00398 
00399 Used for both the view weapon (ps is valid) and the world modelother character models (ps is NULL)
00400 The main player will have this called for BOTH cases, so effects like light and
00401 sound should only be done on the world model case.
00402 =============
00403 */
00404 void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team, vec3_t newAngles, qboolean thirdPerson ) {
00405         refEntity_t     gun;
00406         refEntity_t     barrel;
00407         vec3_t          angles;
00408         weapon_t        weaponNum;
00409         weaponInfo_t    *weapon;
00410         centity_t       *nonPredictedCent;
00411         refEntity_t     flash;
00412 
00413         weaponNum = cent->currentState.weapon;
00414 
00415         if (cent->currentState.weapon == WP_EMPLACED_GUN)
00416         {
00417                 return;
00418         }
00419 
00420         if (cg.predictedPlayerState.pm_type == PM_SPECTATOR &&
00421                 cent->currentState.number == cg.predictedPlayerState.clientNum)
00422         { //spectator mode, don't draw it...
00423                 return;
00424         }
00425 
00426         CG_RegisterWeapon( weaponNum );
00427         weapon = &cg_weapons[weaponNum];
00428 /*
00429 Ghoul2 Insert Start
00430 */
00431 
00432         memset( &gun, 0, sizeof( gun ) );
00433 
00434         // only do this if we are in first person, since world weapons are now handled on the server by Ghoul2
00435         if (!thirdPerson)
00436         {
00437 
00438                 // add the weapon
00439                 VectorCopy( parent->lightingOrigin, gun.lightingOrigin );
00440                 gun.shadowPlane = parent->shadowPlane;
00441                 gun.renderfx = parent->renderfx;
00442 
00443                 if (ps)
00444                 {       // this player, in first person view
00445                         gun.hModel = weapon->viewModel;
00446                 }
00447                 else
00448                 {
00449                         gun.hModel = weapon->weaponModel;
00450                 }
00451                 if (!gun.hModel) {
00452                         return;
00453                 }
00454 
00455                 if ( !ps ) {
00456                         // add weapon ready sound
00457                         cent->pe.lightningFiring = qfalse;
00458                         if ( ( cent->currentState.eFlags & EF_FIRING ) && weapon->firingSound ) {
00459                                 // lightning gun and guantlet make a different sound when fire is held down
00460                                 trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->firingSound );
00461                                 cent->pe.lightningFiring = qtrue;
00462                         } else if ( weapon->readySound ) {
00463                                 trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
00464                         }
00465                 }
00466         
00467                 CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon");
00468 
00469                 if (!CG_IsMindTricked(cent->currentState.trickedentindex,
00470                         cent->currentState.trickedentindex2,
00471                         cent->currentState.trickedentindex3,
00472                         cent->currentState.trickedentindex4,
00473                         cg.snap->ps.clientNum))
00474                 {
00475                         CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups ); //don't draw the weapon if the player is invisible
00476                         /*
00477                         if ( weaponNum == WP_STUN_BATON )
00478                         {
00479                                 gun.shaderRGBA[0] = gun.shaderRGBA[1] = gun.shaderRGBA[2] = 25;
00480         
00481                                 gun.customShader = trap_R_RegisterShader( "gfx/effects/stunPass" );
00482                                 gun.renderfx = RF_RGB_TINT | RF_FIRST_PERSON | RF_DEPTHHACK;
00483                                 trap_R_AddRefEntityToScene( &gun );
00484                         }
00485                         */
00486                 }
00487 
00488                 if (weaponNum == WP_STUN_BATON)
00489                 {
00490                         int i = 0;
00491 
00492                         while (i < 3)
00493                         {
00494                                 memset( &barrel, 0, sizeof( barrel ) );
00495                                 VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
00496                                 barrel.shadowPlane = parent->shadowPlane;
00497                                 barrel.renderfx = parent->renderfx;
00498 
00499                                 if (i == 0)
00500                                 {
00501                                         barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel.md3");
00502                                 }
00503                                 else if (i == 1)
00504                                 {
00505                                         barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel2.md3");
00506                                 }
00507                                 else
00508                                 {
00509                                         barrel.hModel = trap_R_RegisterModel("models/weapons2/stun_baton/baton_barrel3.md3");
00510                                 }
00511                                 angles[YAW] = 0;
00512                                 angles[PITCH] = 0;
00513                                 angles[ROLL] = 0;
00514 
00515                                 AnglesToAxis( angles, barrel.axis );
00516 
00517                                 if (i == 0)
00518                                 {
00519                                         CG_PositionRotatedEntityOnTag( &barrel, parent/*&gun*/, /*weapon->weaponModel*/weapon->handsModel, "tag_barrel" );
00520                                 }
00521                                 else if (i == 1)
00522                                 {
00523                                         CG_PositionRotatedEntityOnTag( &barrel, parent/*&gun*/, /*weapon->weaponModel*/weapon->handsModel, "tag_barrel2" );
00524                                 }
00525                                 else
00526                                 {
00527                                         CG_PositionRotatedEntityOnTag( &barrel, parent/*&gun*/, /*weapon->weaponModel*/weapon->handsModel, "tag_barrel3" );
00528                                 }
00529                                 CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
00530 
00531                                 i++;
00532                         }
00533                 }
00534                 else
00535                 {
00536                         // add the spinning barrel
00537                         if ( weapon->barrelModel ) {
00538                                 memset( &barrel, 0, sizeof( barrel ) );
00539                                 VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
00540                                 barrel.shadowPlane = parent->shadowPlane;
00541                                 barrel.renderfx = parent->renderfx;
00542 
00543                                 barrel.hModel = weapon->barrelModel;
00544                                 angles[YAW] = 0;
00545                                 angles[PITCH] = 0;
00546                                 angles[ROLL] = 0;
00547 
00548                                 AnglesToAxis( angles, barrel.axis );
00549 
00550                                 CG_PositionRotatedEntityOnTag( &barrel, parent/*&gun*/, /*weapon->weaponModel*/weapon->handsModel, "tag_barrel" );
00551 
00552                                 CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
00553                         }
00554                 }
00555         }
00556 /*
00557 Ghoul2 Insert End
00558 */
00559 
00560         memset (&flash, 0, sizeof(flash));
00561         CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash");
00562 
00563         VectorCopy(flash.origin, cg.lastFPFlashPoint);
00564 
00565         // Do special charge bits
00566         //-----------------------
00567         if ( (ps || cg.renderingThirdPerson || cg.predictedPlayerState.clientNum != cent->currentState.number) &&
00568                 ( ( cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && cent->currentState.weapon == WP_BRYAR_PISTOL ) ||
00569                   ( cent->currentState.modelindex2 == WEAPON_CHARGING_ALT && cent->currentState.weapon == WP_BRYAR_OLD ) ||
00570                   ( cent->currentState.weapon == WP_BOWCASTER && cent->currentState.modelindex2 == WEAPON_CHARGING ) ||
00571                   ( cent->currentState.weapon == WP_DEMP2 && cent->currentState.modelindex2 == WEAPON_CHARGING_ALT) ) )
00572         {
00573                 int             shader = 0;
00574                 float   val = 0.0f;
00575                 float   scale = 1.0f;
00576                 addspriteArgStruct_t fxSArgs;
00577                 vec3_t flashorigin, flashdir;
00578 
00579                 if (!thirdPerson)
00580                 {
00581                         VectorCopy(flash.origin, flashorigin);
00582                         VectorCopy(flash.axis[0], flashdir);
00583                 }
00584                 else
00585                 {
00586                         mdxaBone_t              boltMatrix;
00587 
00588                         if (!trap_G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
00589                         { //it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
00590                                 return;
00591                         }
00592 
00593                         // go away and get me the bolt position for this frame please
00594                         if (!(trap_G2API_GetBoltMatrix(cent->ghoul2, 1, 0, &boltMatrix, newAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale)))
00595                         {       // Couldn't find bolt point.
00596                                 return;
00597                         }
00598                         
00599                         BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, flashorigin);
00600                         BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_X, flashdir);
00601                 }
00602 
00603                 if ( cent->currentState.weapon == WP_BRYAR_PISTOL ||
00604                         cent->currentState.weapon == WP_BRYAR_OLD)
00605                 {
00606                         // Hardcoded max charge time of 1 second
00607                         val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00608                         shader = cgs.media.bryarFrontFlash;
00609                 }
00610                 else if ( cent->currentState.weapon == WP_BOWCASTER )
00611                 {
00612                         // Hardcoded max charge time of 1 second
00613                         val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00614                         shader = cgs.media.greenFrontFlash;
00615                 }
00616                 else if ( cent->currentState.weapon == WP_DEMP2 )
00617                 {
00618                         val = ( cg.time - cent->currentState.constantLight ) * 0.001f;
00619                         shader = cgs.media.lightningFlash;
00620                         scale = 1.75f;
00621                 }
00622 
00623                 if ( val < 0.0f )
00624                 {
00625                         val = 0.0f;
00626                 }
00627                 else if ( val > 1.0f )
00628                 {
00629                         val = 1.0f;
00630                         if (ps && cent->currentState.number == ps->clientNum)
00631                         {
00632                                 CGCam_Shake( /*0.1f*/0.2f, 100 );
00633                         }
00634                 }
00635                 else
00636                 {
00637                         if (ps && cent->currentState.number == ps->clientNum)
00638                         {
00639                                 CGCam_Shake( val * val * /*0.3f*/0.6f, 100 );
00640                         }
00641                 }
00642 
00643                 val += random() * 0.5f;
00644 
00645                 VectorCopy(flashorigin, fxSArgs.origin);
00646                 VectorClear(fxSArgs.vel);
00647                 VectorClear(fxSArgs.accel);
00648                 fxSArgs.scale = 3.0f*val*scale;
00649                 fxSArgs.dscale = 0.0f;
00650                 fxSArgs.sAlpha = 0.7f;
00651                 fxSArgs.eAlpha = 0.7f;
00652                 fxSArgs.rotation = random()*360;
00653                 fxSArgs.bounce = 0.0f;
00654                 fxSArgs.life = 1.0f;
00655                 fxSArgs.shader = shader;
00656                 fxSArgs.flags = 0x08000000;
00657 
00658                 //FX_AddSprite( flash.origin, NULL, NULL, 3.0f * val, 0.0f, 0.7f, 0.7f, WHITE, WHITE, random() * 360, 0.0f, 1.0f, shader, FX_USE_ALPHA );
00659                 trap_FX_AddSprite(&fxSArgs);
00660         }
00661 
00662         // make sure we aren't looking at cg.predictedPlayerEntity for LG
00663         nonPredictedCent = &cg_entities[cent->currentState.clientNum];
00664 
00665         // if the index of the nonPredictedCent is not the same as the clientNum
00666         // then this is a fake player (like on teh single player podiums), so
00667         // go ahead and use the cent
00668         if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum ) {
00669                 nonPredictedCent = cent;
00670         }
00671 
00672         // add the flash
00673         if ( ( weaponNum == WP_DEMP2)
00674                 && ( nonPredictedCent->currentState.eFlags & EF_FIRING ) ) 
00675         {
00676                 // continuous flash
00677         } else {
00678                 // impulse flash
00679                 if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME) {
00680                         return;
00681                 }
00682         }
00683 
00684         if ( ps || cg.renderingThirdPerson ||
00685                         cent->currentState.number != cg.predictedPlayerState.clientNum ) 
00686         {       // Make sure we don't do the thirdperson model effects for the local player if we're in first person
00687                 vec3_t flashorigin, flashdir;
00688                 refEntity_t     flash;
00689 
00690                 memset (&flash, 0, sizeof(flash));
00691 
00692                 if (!thirdPerson)
00693                 {
00694                         CG_PositionEntityOnTag( &flash, &gun, gun.hModel, "tag_flash");
00695                         VectorCopy(flash.origin, flashorigin);
00696                         VectorCopy(flash.axis[0], flashdir);
00697                 }
00698                 else
00699                 {
00700                         mdxaBone_t              boltMatrix;
00701 
00702                         if (!trap_G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
00703                         { //it's quite possible that we may have have no weapon model and be in a valid state, so return here if this is the case
00704                                 return;
00705                         }
00706 
00707                         // go away and get me the bolt position for this frame please
00708                         if (!(trap_G2API_GetBoltMatrix(cent->ghoul2, 1, 0, &boltMatrix, newAngles, cent->lerpOrigin, cg.time, cgs.gameModels, cent->modelScale)))
00709                         {       // Couldn't find bolt point.
00710                                 return;
00711                         }
00712                         
00713                         BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, flashorigin);
00714                         BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_X, flashdir);
00715                 }
00716 
00717                 if ( cg.time - cent->muzzleFlashTime <= MUZZLE_FLASH_TIME + 10 )
00718                 {       // Handle muzzle flashes
00719                         if ( cent->currentState.eFlags & EF_ALT_FIRING )
00720                         {       // Check the alt firing first.
00721                                 if (weapon->altMuzzleEffect)
00722                                 {
00723                                         if (!thirdPerson)
00724                                         {
00725                                                 trap_FX_PlayEntityEffectID(weapon->altMuzzleEffect, flashorigin, flash.axis, -1, -1, -1, -1  );
00726                                         }
00727                                         else
00728                                         {
00729                                                 trap_FX_PlayEffectID(weapon->altMuzzleEffect, flashorigin, flashdir, -1, -1);
00730                                         }
00731                                 }
00732                         }
00733                         else
00734                         {       // Regular firing
00735                                 if (weapon->muzzleEffect)
00736                                 {
00737                                         if (!thirdPerson)
00738                                         {
00739                                                 trap_FX_PlayEntityEffectID(weapon->muzzleEffect, flashorigin, flash.axis, -1, -1, -1, -1  );
00740                                         }
00741                                         else
00742                                         {
00743                                                 trap_FX_PlayEffectID(weapon->muzzleEffect, flashorigin, flashdir, -1, -1);
00744                                         }
00745                                 }
00746                         }
00747                 }
00748 
00749                 // add lightning bolt
00750                 CG_LightningBolt( nonPredictedCent, flashorigin );
00751 
00752                 if ( weapon->flashDlightColor[0] || weapon->flashDlightColor[1] || weapon->flashDlightColor[2] ) {
00753                         trap_R_AddLightToScene( flashorigin, 300 + (rand()&31), weapon->flashDlightColor[0],
00754                                 weapon->flashDlightColor[1], weapon->flashDlightColor[2] );
00755                 }
00756         }
00757 }
00758 
00759 /*
00760 ==============
00761 CG_AddViewWeapon
00762 
00763 Add the weapon, and flash for the player's view
00764 ==============
00765 */
00766 void CG_AddViewWeapon( playerState_t *ps ) {
00767         refEntity_t     hand;
00768         centity_t       *cent;
00769         clientInfo_t    *ci;
00770         float           fovOffset;
00771         vec3_t          angles;
00772         weaponInfo_t    *weapon;
00773         float   cgFov = cg_fov.value;
00774 
00775         if (cgFov < 1)
00776         {
00777                 cgFov = 1;
00778         }
00779         if (cgFov > 97)
00780         {
00781                 cgFov = 97;
00782         }
00783 
00784         if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
00785                 return;
00786         }
00787 
00788         if ( ps->pm_type == PM_INTERMISSION ) {
00789                 return;
00790         }
00791 
00792         // no gun if in third person view or a camera is active
00793         //if ( cg.renderingThirdPerson || cg.cameraMode) {
00794         if ( cg.renderingThirdPerson ) {
00795                 return;
00796         }
00797 
00798         // allow the gun to be completely removed
00799         if ( !cg_drawGun.integer || cg.predictedPlayerState.zoomMode) {
00800                 vec3_t          origin;
00801 
00802                 if ( cg.predictedPlayerState.eFlags & EF_FIRING ) {
00803                         // special hack for lightning gun...
00804                         VectorCopy( cg.refdef.vieworg, origin );
00805                         VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
00806                         CG_LightningBolt( &cg_entities[ps->clientNum], origin );
00807                 }
00808                 return;
00809         }
00810 
00811         // don't draw if testing a gun model
00812         if ( cg.testGun ) {
00813                 return;
00814         }
00815 
00816         // drop gun lower at higher fov
00817         if ( cgFov > 90 ) {
00818                 fovOffset = -0.2 * ( cgFov - 90 );
00819         } else {
00820                 fovOffset = 0;
00821         }
00822 
00823         cent = &cg_entities[cg.predictedPlayerState.clientNum];
00824         CG_RegisterWeapon( ps->weapon );
00825         weapon = &cg_weapons[ ps->weapon ];
00826 
00827         memset (&hand, 0, sizeof(hand));
00828 
00829         // set up gun position
00830         CG_CalculateWeaponPosition( hand.origin, angles );
00831 
00832         VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[0], hand.origin );
00833         VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
00834         VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
00835 
00836         AnglesToAxis( angles, hand.axis );
00837 
00838         // map torso animations to weapon animations
00839         if ( cg_gun_frame.integer ) {
00840                 // development tool
00841                 hand.frame = hand.oldframe = cg_gun_frame.integer;
00842                 hand.backlerp = 0;
00843         } else {
00844                 // get clientinfo for animation map
00845                 if (cent->currentState.eType == ET_NPC)
00846                 {
00847                         if (!cent->npcClient)
00848                         {
00849                                 return;
00850                         }
00851 
00852                         ci = cent->npcClient;
00853                 }
00854                 else
00855                 {
00856                         ci = &cgs.clientinfo[ cent->currentState.clientNum ];
00857                 }
00858                 hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame, cent->currentState.torsoAnim );
00859                 hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame, cent->currentState.torsoAnim );
00860                 hand.backlerp = cent->pe.torso.backlerp;
00861 
00862                 // Handle the fringe situation where oldframe is invalid
00863                 if ( hand.frame == -1 )
00864                 {
00865                         hand.frame = 0;
00866                         hand.oldframe = 0;
00867                         hand.backlerp = 0;
00868                 }
00869                 else if ( hand.oldframe == -1 )
00870                 {
00871                         hand.oldframe = hand.frame;
00872                         hand.backlerp = 0;
00873                 }
00874         }
00875 
00876         hand.hModel = weapon->handsModel;
00877         hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON;// | RF_MINLIGHT;
00878 
00879         // add everything onto the hand
00880         CG_AddPlayerWeapon( &hand, ps, &cg_entities[cg.predictedPlayerState.clientNum], ps->persistant[PERS_TEAM], angles, qfalse );
00881 }
00882 
00883 /*
00884 ==============================================================================
00885 
00886 WEAPON SELECTION
00887 
00888 ==============================================================================
00889 */
00890 #define ICON_WEAPONS    0
00891 #define ICON_FORCE              1
00892 #define ICON_INVENTORY  2
00893 
00894 
00895 void CG_DrawIconBackground(void)
00896 {
00897         int                             height,xAdd,x2,y2,t;
00898 //      int                             prongLeftX,prongRightX;
00899         float                   inTime = cg.invenSelectTime+WEAPON_SELECT_TIME;
00900         float                   wpTime = cg.weaponSelectTime+WEAPON_SELECT_TIME;
00901         float                   fpTime = cg.forceSelectTime+WEAPON_SELECT_TIME;
00902 //      int                             drawType = cgs.media.weaponIconBackground;
00903 //      int                             yOffset = 0;
00904 
00905 #ifdef _XBOX
00906         //yOffset = -50;
00907 #endif
00908 
00909         // don't display if dead
00910         if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) 
00911         {
00912                 return;
00913         }
00914 
00915         if (cg_hudFiles.integer)
00916         { //simple hud
00917                 return;
00918         }
00919 
00920         x2 = 30;
00921         y2 = SCREEN_HEIGHT-70;
00922 
00923         //prongLeftX =x2+37; 
00924         //prongRightX =x2+544; 
00925 
00926         if (inTime > wpTime)
00927         {
00928 //              drawType = cgs.media.inventoryIconBackground;
00929                 cg.iconSelectTime = cg.invenSelectTime;
00930         }
00931         else
00932         {
00933 //              drawType = cgs.media.weaponIconBackground;
00934                 cg.iconSelectTime = cg.weaponSelectTime;
00935         }
00936 
00937         if (fpTime > inTime && fpTime > wpTime)
00938         {
00939 //              drawType = cgs.media.forceIconBackground;
00940                 cg.iconSelectTime = cg.forceSelectTime;
00941         }
00942 
00943         if ((cg.iconSelectTime+WEAPON_SELECT_TIME)<cg.time)     // Time is up for the HUD to display
00944         {
00945                 if (cg.iconHUDActive)           // The time is up, but we still need to move the prongs back to their original position
00946                 {
00947                         t =  cg.time - (cg.iconSelectTime+WEAPON_SELECT_TIME);
00948                         cg.iconHUDPercent = t/ 130.0f;
00949                         cg.iconHUDPercent = 1 - cg.iconHUDPercent;
00950 
00951                         if (cg.iconHUDPercent<0)
00952                         {
00953                                 cg.iconHUDActive = qfalse;
00954                                 cg.iconHUDPercent=0;
00955                         }
00956 
00957                         xAdd = (int) 8*cg.iconHUDPercent;
00958 
00959                         height = (int) (60.0f*cg.iconHUDPercent);
00960                         //CG_DrawPic( x2+60, y2+30+yOffset, 460, -height, drawType);    // Top half
00961                         //CG_DrawPic( x2+60, y2+30-2+yOffset, 460, height, drawType);   // Bottom half
00962 
00963                 }
00964                 else
00965                 {
00966                         xAdd = 0;
00967                 }
00968 
00969                 return;
00970         }
00971         //prongLeftX =x2+37; 
00972         //prongRightX =x2+544; 
00973 
00974         if (!cg.iconHUDActive)
00975         {
00976                 t = cg.time - cg.iconSelectTime;
00977                 cg.iconHUDPercent = t/ 130.0f;
00978 
00979                 // Calc how far into opening sequence we are
00980                 if (cg.iconHUDPercent>1)
00981                 {
00982                         cg.iconHUDActive = qtrue;
00983                         cg.iconHUDPercent=1;
00984                 }
00985                 else if (cg.iconHUDPercent<0)
00986                 {
00987                         cg.iconHUDPercent=0;
00988                 }
00989         }
00990         else
00991         {
00992                 cg.iconHUDPercent=1;
00993         }
00994 
00995         //trap_R_SetColor( colorTable[CT_WHITE] );                                      
00996         //height = (int) (60.0f*cg.iconHUDPercent);
00997         //CG_DrawPic( x2+60, y2+30+yOffset, 460, -height, drawType);    // Top half
00998         //CG_DrawPic( x2+60, y2+30-2+yOffset, 460, height, drawType);   // Bottom half
00999 
01000         // And now for the prongs
01001 /*      if ((cg.inventorySelectTime+WEAPON_SELECT_TIME)>cg.time)        
01002         {
01003                 cgs.media.currentBackground = ICON_INVENTORY;
01004                 background = &cgs.media.inventoryProngsOn;
01005         }
01006         else if ((cg.weaponSelectTime+WEAPON_SELECT_TIME)>cg.time)      
01007         {
01008                 cgs.media.currentBackground = ICON_WEAPONS;
01009         }
01010         else 
01011         {
01012                 cgs.media.currentBackground = ICON_FORCE;
01013                 background = &cgs.media.forceProngsOn;
01014         }
01015 */
01016         // Side Prongs
01017 //      trap_R_SetColor( colorTable[CT_WHITE]);                                 
01018 //      xAdd = (int) 8*cg.iconHUDPercent;
01019 //      CG_DrawPic( prongLeftX+xAdd, y2-10, 40, 80, background);
01020 //      CG_DrawPic( prongRightX-xAdd, y2-10, -40, 80, background);
01021 
01022 }
01023 
01024 qboolean CG_WeaponCheck(int weap)
01025 {
01026         if (cg.snap->ps.ammo[weaponData[weap].ammoIndex] < weaponData[weap].energyPerShot &&
01027                 cg.snap->ps.ammo[weaponData[weap].ammoIndex] < weaponData[weap].altEnergyPerShot)
01028         {
01029                 return qfalse;
01030         }
01031 
01032         return qtrue;
01033 }
01034 
01035 /*
01036 ===============
01037 CG_WeaponSelectable
01038 ===============
01039 */
01040 static qboolean CG_WeaponSelectable( int i ) {
01041         /*if ( !cg.snap->ps.ammo[weaponData[i].ammoIndex] ) {
01042                 return qfalse;
01043         }*/
01044         if (!i)
01045         {
01046                 return qfalse;
01047         }
01048 
01049         if (cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < weaponData[i].energyPerShot &&
01050                 cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < weaponData[i].altEnergyPerShot)
01051         {
01052                 return qfalse;
01053         }
01054 
01055         if (i == WP_DET_PACK && cg.predictedPlayerState.ammo[weaponData[i].ammoIndex] < 1 &&
01056                 !cg.predictedPlayerState.hasDetPackPlanted)
01057         {
01058                 return qfalse;
01059         }
01060 
01061         if ( ! (cg.predictedPlayerState.stats[ STAT_WEAPONS ] & ( 1 << i ) ) ) {
01062                 return qfalse;
01063         }
01064 
01065         return qtrue;
01066 }
01067 
01068 /*
01069 ===================
01070 CG_DrawWeaponSelect
01071 ===================
01072 */
01073 #ifdef _XBOX
01074 extern bool CL_ExtendSelectTime(void);
01075 #endif
01076 void CG_DrawWeaponSelect( void ) {
01077         int                             i;
01078         int                             bits;
01079         int                             count;
01080         int                             smallIconSize,bigIconSize;
01081         int                             holdX,x,y,pad;
01082         int                             sideLeftIconCnt,sideRightIconCnt;
01083         int                             sideMax,holdCount,iconCnt;
01084         int                             height;
01085         int             yOffset = 0;
01086         qboolean drewConc = qfalse;
01087 
01088         if (cg.predictedPlayerState.emplacedIndex)
01089         { //can't cycle when on a weapon
01090                 cg.weaponSelectTime = 0;
01091         }
01092 
01093         if ((cg.weaponSelectTime+WEAPON_SELECT_TIME)<cg.time)   // Time is up for the HUD to display
01094         {
01095                 return;
01096         }
01097 
01098         // don't display if dead
01099         if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) 
01100         {
01101                 return;
01102         }
01103 
01104 #ifdef _XBOX
01105         if(CL_ExtendSelectTime()) {
01106                 cg.weaponSelectTime = cg.time;
01107         }
01108 
01109         yOffset = -50;
01110 #endif
01111 
01112         // showing weapon select clears pickup item display, but not the blend blob
01113         cg.itemPickupTime = 0;
01114 
01115         bits = cg.predictedPlayerState.stats[ STAT_WEAPONS ];
01116 
01117         // count the number of weapons owned
01118         count = 0;
01119 
01120         if ( !CG_WeaponSelectable(cg.weaponSelect) &&
01121                 (cg.weaponSelect == WP_THERMAL || cg.weaponSelect == WP_TRIP_MINE) )
01122         { //display this weapon that we don't actually "have" as unhighlighted until it's deselected
01123           //since it's selected we must increase the count to display the proper number of valid selectable weapons
01124                 count++;
01125         }
01126 
01127         for ( i = 1 ; i < WP_NUM_WEAPONS ; i++ ) 
01128         {
01129                 if ( bits & ( 1 << i ) ) 
01130                 {
01131                         if ( CG_WeaponSelectable(i) ||
01132                                 (i != WP_THERMAL && i != WP_TRIP_MINE) )
01133                         {
01134                                 count++;
01135                         }
01136                 }
01137         }
01138 
01139         if (count == 0) // If no weapons, don't display
01140         {
01141                 return;
01142         }
01143 
01144         sideMax = 3;    // Max number of icons on the side
01145 
01146         // Calculate how many icons will appear to either side of the center one
01147         holdCount = count - 1;  // -1 for the center icon
01148         if (holdCount == 0)                     // No icons to either side
01149         {
01150                 sideLeftIconCnt = 0;
01151                 sideRightIconCnt = 0;
01152         }
01153         else if (count > (2*sideMax))   // Go to the max on each side
01154         {
01155                 sideLeftIconCnt = sideMax;
01156                 sideRightIconCnt = sideMax;
01157         }
01158         else                                                    // Less than max, so do the calc
01159         {
01160                 sideLeftIconCnt = holdCount/2;
01161                 sideRightIconCnt = holdCount - sideLeftIconCnt;
01162         }
01163 
01164         if ( cg.weaponSelect == WP_CONCUSSION )
01165         {
01166                 i = WP_FLECHETTE;
01167         }
01168         else
01169         {
01170                 i = cg.weaponSelect - 1;
01171         }
01172         if (i<1)
01173         {
01174                 i = LAST_USEABLE_WEAPON;
01175         }
01176 
01177         smallIconSize = 40;
01178         bigIconSize = 80;
01179         pad = 12;
01180 
01181         x = 320;
01182         y = 410;
01183 
01184         // Background
01185 //      memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
01186 //      calcColor[3] = .35f;
01187 //      trap_R_SetColor( calcColor);                                    
01188 
01189         // Left side ICONS
01190         trap_R_SetColor(colorTable[CT_WHITE]);
01191         // Work backwards from current icon
01192         holdX = x - ((bigIconSize/2) + pad + smallIconSize);
01193         height = smallIconSize * 1;//cg.iconHUDPercent;
01194         drewConc = qfalse;
01195 
01196         for (iconCnt=1;iconCnt<(sideLeftIconCnt+1);i--)
01197         {
01198                 if ( i == WP_CONCUSSION )
01199                 {
01200                         i--;
01201                 }
01202                 else if ( i == WP_FLECHETTE && !drewConc && cg.weaponSelect != WP_CONCUSSION )
01203                 {
01204                         i = WP_CONCUSSION;
01205                 }
01206                 if (i<1)
01207                 {
01208                         //i = 13;
01209                         //...don't ever do this.
01210                         i = LAST_USEABLE_WEAPON;
01211                 }
01212 
01213                 if ( !(bits & ( 1 << i )))      // Does he have this weapon?
01214                 {
01215                         if ( i == WP_CONCUSSION )
01216                         {
01217                                 drewConc = qtrue;
01218                                 i = WP_ROCKET_LAUNCHER;
01219                         }
01220                         continue;
01221                 }
01222 
01223                 if ( !CG_WeaponSelectable(i) &&
01224                         (i == WP_THERMAL || i == WP_TRIP_MINE) )
01225                 { //Don't show thermal and tripmine when out of them
01226                         continue;
01227                 }
01228 
01229                 ++iconCnt;                                      // Good icon
01230 
01231                 if (cgs.media.weaponIcons[i])
01232                 {
01233                         weaponInfo_t    *weaponInfo;
01234                         CG_RegisterWeapon( i ); 
01235                         weaponInfo = &cg_weapons[i];
01236 
01237                         trap_R_SetColor(colorTable[CT_WHITE]);
01238                         if (!CG_WeaponCheck(i))
01239                         {
01240                                 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, /*weaponInfo->weaponIconNoAmmo*/cgs.media.weaponIcons_NA[i] );
01241                         }
01242                         else
01243                         {
01244                                 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, /*weaponInfo->weaponIcon*/cgs.media.weaponIcons[i] );
01245                         }
01246 
01247                         holdX -= (smallIconSize+pad);
01248                 }
01249                 if ( i == WP_CONCUSSION )
01250                 {
01251                         drewConc = qtrue;
01252                         i = WP_ROCKET_LAUNCHER;
01253                 }
01254         }
01255 
01256         // Current Center Icon
01257         height = bigIconSize * cg.iconHUDPercent;
01258         if (cgs.media.weaponIcons[cg.weaponSelect])
01259         {
01260                 weaponInfo_t    *weaponInfo;
01261                 CG_RegisterWeapon( cg.weaponSelect );   
01262                 weaponInfo = &cg_weapons[cg.weaponSelect];
01263 
01264                 trap_R_SetColor( colorTable[CT_WHITE]);
01265                 if (!CG_WeaponCheck(cg.weaponSelect))
01266                 {
01267                         CG_DrawPic( x-(bigIconSize/2), (y-((bigIconSize-smallIconSize)/2))+10+yOffset, bigIconSize, bigIconSize, cgs.media.weaponIcons_NA[cg.weaponSelect] );
01268                 }
01269                 else
01270                 {
01271                         CG_DrawPic( x-(bigIconSize/2), (y-((bigIconSize-smallIconSize)/2))+10+yOffset, bigIconSize, bigIconSize, cgs.media.weaponIcons[cg.weaponSelect] );
01272                 }
01273         }
01274 
01275         if ( cg.weaponSelect == WP_CONCUSSION )
01276         {
01277                 i = WP_ROCKET_LAUNCHER;
01278         }
01279         else
01280         {
01281                 i = cg.weaponSelect + 1;
01282         }
01283         if (i> LAST_USEABLE_WEAPON)
01284         {
01285                 i = 1;
01286         }
01287 
01288         // Right side ICONS
01289         // Work forwards from current icon
01290         holdX = x + (bigIconSize/2) + pad;
01291         height = smallIconSize * cg.iconHUDPercent;
01292         for (iconCnt=1;iconCnt<(sideRightIconCnt+1);i++)
01293         {
01294                 if ( i == WP_CONCUSSION )
01295                 {
01296                         i++;
01297                 }
01298                 else if ( i == WP_ROCKET_LAUNCHER && !drewConc && cg.weaponSelect != WP_CONCUSSION )
01299                 {
01300                         i = WP_CONCUSSION;
01301                 }
01302                 if (i>LAST_USEABLE_WEAPON)
01303                 {
01304                         i = 1;
01305                 }
01306 
01307                 if ( !(bits & ( 1 << i )))      // Does he have this weapon?
01308                 {
01309                         if ( i == WP_CONCUSSION )
01310                         {
01311                                 drewConc = qtrue;
01312                                 i = WP_FLECHETTE;
01313                         }
01314                         continue;
01315                 }
01316 
01317                 if ( !CG_WeaponSelectable(i) &&
01318                         (i == WP_THERMAL || i == WP_TRIP_MINE) )
01319                 { //Don't show thermal and tripmine when out of them
01320                         continue;
01321                 }
01322 
01323                 ++iconCnt;                                      // Good icon
01324 
01325                 if (/*weaponData[i].weaponIcon[0]*/cgs.media.weaponIcons[i])
01326                 {
01327                         weaponInfo_t    *weaponInfo;
01328                         CG_RegisterWeapon( i ); 
01329                         weaponInfo = &cg_weapons[i];
01330                         // No ammo for this weapon?
01331                         trap_R_SetColor( colorTable[CT_WHITE]);
01332                         if (!CG_WeaponCheck(i))
01333                         {
01334                                 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons_NA[i] );
01335                         }
01336                         else
01337                         {
01338                                 CG_DrawPic( holdX, y+10+yOffset, smallIconSize, smallIconSize, cgs.media.weaponIcons[i] );
01339                         }
01340 
01341 
01342                         holdX += (smallIconSize+pad);
01343                 }
01344                 if ( i == WP_CONCUSSION )
01345                 {
01346                         drewConc = qtrue;
01347                         i = WP_FLECHETTE;
01348                 }
01349         }
01350 
01351         // draw the selected name
01352         if ( cg_weapons[ cg.weaponSelect ].item ) 
01353         {
01354                 vec4_t                  textColor = { .875f, .718f, .121f, 1.0f };
01355                 char    text[1024];
01356                 char    upperKey[1024];
01357 
01358                 strcpy(upperKey, cg_weapons[ cg.weaponSelect ].item->classname);
01359 
01360