codemp/cgame/cg_draw.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 // cg_draw.c -- draw all of the graphical elements during
00004 // active (after loading) gameplay
00005 
00006 #include "cg_local.h"
00007 
00008 #include "bg_saga.h"
00009 
00010 #include "../ui/ui_shared.h"
00011 #include "../ui/ui_public.h"
00012 
00013 extern float CG_RadiusForCent( centity_t *cent );
00014 qboolean CG_WorldCoordToScreenCoordFloat(vec3_t worldCoord, float *x, float *y);
00015 qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle );
00016 static void CG_DrawSiegeTimer(int timeRemaining, qboolean isMyTeam);
00017 static void CG_DrawSiegeDeathTimer( int timeRemaining );
00018 // nmckenzie: DUEL_HEALTH
00019 void CG_DrawDuelistHealth ( float x, float y, float w, float h, int duelist );
00020 
00021 // used for scoreboard
00022 extern displayContextDef_t cgDC;
00023 menuDef_t *menuScoreboard = NULL;
00024 vec4_t  bluehudtint = {0.5, 0.5, 1.0, 1.0};
00025 vec4_t  redhudtint = {1.0, 0.5, 0.5, 1.0};
00026 float   *hudTintColor;
00027 
00028 int sortedTeamPlayers[TEAM_MAXOVERLAY];
00029 int     numSortedTeamPlayers;
00030 
00031 int lastvalidlockdif;
00032 
00033 extern float zoomFov; //this has to be global client-side
00034 
00035 char systemChat[256];
00036 char teamChat1[256];
00037 char teamChat2[256];
00038 
00039 // The time at which you died and the time it will take for you to rejoin game.
00040 int cg_siegeDeathTime = 0;
00041 
00042 #define MAX_HUD_TICS 4
00043 const char *armorTicName[MAX_HUD_TICS] = 
00044 {
00045 "armor_tic1", 
00046 "armor_tic2", 
00047 "armor_tic3", 
00048 "armor_tic4", 
00049 };
00050 
00051 const char *healthTicName[MAX_HUD_TICS] = 
00052 {
00053 "health_tic1", 
00054 "health_tic2", 
00055 "health_tic3", 
00056 "health_tic4", 
00057 };
00058 
00059 const char *forceTicName[MAX_HUD_TICS] = 
00060 {
00061 "force_tic1", 
00062 "force_tic2", 
00063 "force_tic3", 
00064 "force_tic4", 
00065 };
00066 
00067 const char *ammoTicName[MAX_HUD_TICS] = 
00068 {
00069 "ammo_tic1", 
00070 "ammo_tic2", 
00071 "ammo_tic3", 
00072 "ammo_tic4", 
00073 };
00074 
00075 char *showPowersName[] = 
00076 {
00077         "HEAL2",//FP_HEAL
00078         "JUMP2",//FP_LEVITATION
00079         "SPEED2",//FP_SPEED
00080         "PUSH2",//FP_PUSH
00081         "PULL2",//FP_PULL
00082         "MINDTRICK2",//FP_TELEPTAHY
00083         "GRIP2",//FP_GRIP
00084         "LIGHTNING2",//FP_LIGHTNING
00085         "DARK_RAGE2",//FP_RAGE
00086         "PROTECT2",//FP_PROTECT
00087         "ABSORB2",//FP_ABSORB
00088         "TEAM_HEAL2",//FP_TEAM_HEAL
00089         "TEAM_REPLENISH2",//FP_TEAM_FORCE
00090         "DRAIN2",//FP_DRAIN
00091         "SEEING2",//FP_SEE
00092         "SABER_OFFENSE2",//FP_SABER_OFFENSE
00093         "SABER_DEFENSE2",//FP_SABER_DEFENSE
00094         "SABER_THROW2",//FP_SABERTHROW
00095         NULL
00096 };
00097 
00098 //Called from UI shared code. For now we'll just redirect to the normal anim load function.
00099 #include "../namespace_begin.h"
00100 
00101 
00102 int UI_ParseAnimationFile(const char *filename, animation_t *animset, qboolean isHumanoid) 
00103 {
00104         return BG_ParseAnimationFile(filename, animset, isHumanoid);
00105 }
00106 
00107 int MenuFontToHandle(int iMenuFont)
00108 {
00109         switch (iMenuFont)
00110         {
00111                 case FONT_SMALL:        return cgDC.Assets.qhSmallFont;
00112                 case FONT_SMALL2:       return cgDC.Assets.qhSmall2Font;
00113                 case FONT_MEDIUM:       return cgDC.Assets.qhMediumFont;
00114                 case FONT_LARGE:        return cgDC.Assets.qhMediumFont;//cgDC.Assets.qhBigFont;
00115                         //fixme? Big fonr isn't registered...?
00116         }
00117 
00118         return cgDC.Assets.qhMediumFont;
00119 }
00120 
00121 #include "../namespace_end.h"
00122 
00123 int CG_Text_Width(const char *text, float scale, int iMenuFont) 
00124 {
00125         int iFontIndex = MenuFontToHandle(iMenuFont);
00126 
00127         return trap_R_Font_StrLenPixels(text, iFontIndex, scale);
00128 }
00129 
00130 int CG_Text_Height(const char *text, float scale, int iMenuFont) 
00131 {
00132         int iFontIndex = MenuFontToHandle(iMenuFont);
00133 
00134         return trap_R_Font_HeightPixels(iFontIndex, scale);
00135 }
00136 
00137 #include "../qcommon/qfiles.h"  // for STYLE_BLINK etc
00138 void CG_Text_Paint(float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style, int iMenuFont) 
00139 {
00140         int iStyleOR = 0;
00141         int iFontIndex = MenuFontToHandle(iMenuFont);
00142         
00143         switch (style)
00144         {
00145         case  ITEM_TEXTSTYLE_NORMAL:                    iStyleOR = 0;break;                                     // JK2 normal text
00146         case  ITEM_TEXTSTYLE_BLINK:                             iStyleOR = STYLE_BLINK;break;           // JK2 fast blinking
00147         case  ITEM_TEXTSTYLE_PULSE:                             iStyleOR = STYLE_BLINK;break;           // JK2 slow pulsing
00148         case  ITEM_TEXTSTYLE_SHADOWED:                  iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
00149         case  ITEM_TEXTSTYLE_OUTLINED:                  iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
00150         case  ITEM_TEXTSTYLE_OUTLINESHADOWED:   iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
00151         case  ITEM_TEXTSTYLE_SHADOWEDMORE:              iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
00152         }
00153 
00154         trap_R_Font_DrawString( x,              // int ox
00155                                                         y,              // int oy
00156                                                         text,   // const char *text
00157                                                         color,  // paletteRGBA_c c
00158                                                         iStyleOR | iFontIndex,  // const int iFontHandle
00159                                                         !limit?-1:limit,                // iCharLimit (-1 = none)
00160                                                         scale   // const float scale = 1.0f
00161                                                         );
00162 }
00163 
00164 /*
00165 qboolean CG_WorldCoordToScreenCoord(vec3_t worldCoord, int *x, int *y)
00166 
00167   Take any world coord and convert it to a 2D virtual 640x480 screen coord
00168 */
00169 /*
00170 qboolean CG_WorldCoordToScreenCoordFloat(vec3_t worldCoord, float *x, float *y)
00171 {
00172         int     xcenter, ycenter;
00173         vec3_t  local, transformed;
00174 
00175 //      xcenter = cg.refdef.width / 2;//gives screen coords adjusted for resolution
00176 //      ycenter = cg.refdef.height / 2;//gives screen coords adjusted for resolution
00177         
00178         //NOTE: did it this way because most draw functions expect virtual 640x480 coords
00179         //      and adjust them for current resolution
00180         xcenter = 640 / 2;//gives screen coords in virtual 640x480, to be adjusted when drawn
00181         ycenter = 480 / 2;//gives screen coords in virtual 640x480, to be adjusted when drawn
00182 
00183         VectorSubtract (worldCoord, cg.refdef.vieworg, local);
00184 
00185         transformed[0] = DotProduct(local,vright);
00186         transformed[1] = DotProduct(local,vup);
00187         transformed[2] = DotProduct(local,vfwd);                
00188 
00189         // Make sure Z is not negative.
00190         if(transformed[2] < 0.01)
00191         {
00192                 return qfalse;
00193         }
00194         // Simple convert to screen coords.
00195         float xzi = xcenter / transformed[2] * (90.0/cg.refdef.fov_x);
00196         float yzi = ycenter / transformed[2] * (90.0/cg.refdef.fov_y);
00197 
00198         *x = xcenter + xzi * transformed[0];
00199         *y = ycenter - yzi * transformed[1];
00200 
00201         return qtrue;
00202 }
00203 
00204 qboolean CG_WorldCoordToScreenCoord( vec3_t worldCoord, int *x, int *y )
00205 {
00206         float   xF, yF;
00207         qboolean retVal = CG_WorldCoordToScreenCoordFloat( worldCoord, &xF, &yF );
00208         *x = (int)xF;
00209         *y = (int)yF;
00210         return retVal;
00211 }
00212 */
00213 
00214 /*
00215 ================
00216 CG_DrawZoomMask
00217 
00218 ================
00219 */
00220 static void CG_DrawZoomMask( void )
00221 {
00222         vec4_t          color1;
00223         float           level;
00224         static qboolean flip = qtrue;
00225 
00226 //      int ammo = cg_entities[0].gent->client->ps.ammo[weaponData[cent->currentState.weapon].ammoIndex];
00227         float cx, cy;
00228 //      int val[5];
00229         float max, fi;
00230 
00231         // Check for Binocular specific zooming since we'll want to render different bits in each case
00232         if ( cg.predictedPlayerState.zoomMode == 2 )
00233         {
00234                 int val, i;
00235                 float off;
00236 
00237                 // zoom level
00238                 level = (float)(80.0f - cg.predictedPlayerState.zoomFov) / 80.0f;
00239 
00240                 // ...so we'll clamp it
00241                 if ( level < 0.0f )
00242                 {
00243                         level = 0.0f;
00244                 }
00245                 else if ( level > 1.0f )
00246                 {
00247                         level = 1.0f;
00248                 }
00249 
00250                 // Using a magic number to convert the zoom level to scale amount
00251                 level *= 162.0f;
00252 
00253                 // draw blue tinted distortion mask, trying to make it as small as is necessary to fill in the viewable area
00254                 trap_R_SetColor( colorTable[CT_WHITE] );
00255                 CG_DrawPic( 34, 48, 570, 362, cgs.media.binocularStatic );
00256         
00257                 // Black out the area behind the numbers
00258                 trap_R_SetColor( colorTable[CT_BLACK]);
00259                 CG_DrawPic( 212, 367, 200, 40, cgs.media.whiteShader );
00260 
00261                 // Numbers should be kind of greenish
00262                 color1[0] = 0.2f;
00263                 color1[1] = 0.4f;
00264                 color1[2] = 0.2f;
00265                 color1[3] = 0.3f;
00266                 trap_R_SetColor( color1 );
00267 
00268                 // Draw scrolling numbers, use intervals 10 units apart--sorry, this section of code is just kind of hacked
00269                 //      up with a bunch of magic numbers.....
00270                 val = ((int)((cg.refdef.viewangles[YAW] + 180) / 10)) * 10;
00271                 off = (cg.refdef.viewangles[YAW] + 180) - val;
00272 
00273                 for ( i = -10; i < 30; i += 10 )
00274                 {
00275                         val -= 10;
00276 
00277                         if ( val < 0 )
00278                         {
00279                                 val += 360;
00280                         }
00281 
00282                         // we only want to draw the very far left one some of the time, if it's too far to the left it will
00283                         //      poke outside the mask.
00284                         if (( off > 3.0f && i == -10 ) || i > -10 )
00285                         {
00286                                 // draw the value, but add 200 just to bump the range up...arbitrary, so change it if you like
00287                                 CG_DrawNumField( 155 + i * 10 + off * 10, 374, 3, val + 200, 24, 14, NUM_FONT_CHUNKY, qtrue );
00288                                 CG_DrawPic( 245 + (i-1) * 10 + off * 10, 376, 6, 6, cgs.media.whiteShader );
00289                         }
00290                 }
00291 
00292                 CG_DrawPic( 212, 367, 200, 28, cgs.media.binocularOverlay );
00293 
00294                 color1[0] = sin( cg.time * 0.01f ) * 0.5f + 0.5f;
00295                 color1[0] = color1[0] * color1[0];
00296                 color1[1] = color1[0];
00297                 color1[2] = color1[0];
00298                 color1[3] = 1.0f;
00299 
00300                 trap_R_SetColor( color1 );
00301 
00302                 CG_DrawPic( 82, 94, 16, 16, cgs.media.binocularCircle );
00303 
00304                 // Flickery color
00305                 color1[0] = 0.7f + crandom() * 0.1f;
00306                 color1[1] = 0.8f + crandom() * 0.1f;
00307                 color1[2] = 0.7f + crandom() * 0.1f;
00308                 color1[3] = 1.0f;
00309                 trap_R_SetColor( color1 );
00310         
00311                 CG_DrawPic( 0, 0, 640, 480, cgs.media.binocularMask );
00312 
00313                 CG_DrawPic( 4, 282 - level, 16, 16, cgs.media.binocularArrow );
00314 
00315                 // The top triangle bit randomly flips 
00316                 if ( flip )
00317                 {
00318                         CG_DrawPic( 330, 60, -26, -30, cgs.media.binocularTri );
00319                 }
00320                 else
00321                 {
00322                         CG_DrawPic( 307, 40, 26, 30, cgs.media.binocularTri );
00323                 }
00324 
00325                 if ( random() > 0.98f && ( cg.time & 1024 ))
00326                 {
00327                         flip = !flip;
00328                 }
00329         }
00330         else if ( cg.predictedPlayerState.zoomMode)
00331         {
00332                 // disruptor zoom mode
00333                 level = (float)(50.0f - zoomFov) / 50.0f;//(float)(80.0f - zoomFov) / 80.0f;
00334 
00335                 // ...so we'll clamp it
00336                 if ( level < 0.0f )
00337                 {
00338                         level = 0.0f;
00339                 }
00340                 else if ( level > 1.0f )
00341                 {
00342                         level = 1.0f;
00343                 }
00344 
00345                 // Using a magic number to convert the zoom level to a rotation amount that correlates more or less with the zoom artwork. 
00346                 level *= 103.0f;
00347 
00348                 // Draw target mask
00349                 trap_R_SetColor( colorTable[CT_WHITE] );
00350                 CG_DrawPic( 0, 0, 640, 480, cgs.media.disruptorMask );
00351 
00352                 // apparently 99.0f is the full zoom level
00353                 if ( level >= 99 )
00354                 {
00355                         // Fully zoomed, so make the rotating insert pulse
00356                         color1[0] = 1.0f; 
00357                         color1[1] = 1.0f;
00358                         color1[2] = 1.0f;
00359                         color1[3] = 0.7f + sin( cg.time * 0.01f ) * 0.3f;
00360 
00361                         trap_R_SetColor( color1 );
00362                 }
00363 
00364                 // Draw rotating insert
00365                 CG_DrawRotatePic2( 320, 240, 640, 480, -level, cgs.media.disruptorInsert );
00366 
00367                 // Increase the light levels under the center of the target
00368 //              CG_DrawPic( 198, 118, 246, 246, cgs.media.disruptorLight );
00369 
00370                 // weirdness.....converting ammo to a base five number scale just to be geeky.
00371 /*              val[0] = ammo % 5;
00372                 val[1] = (ammo / 5) % 5;
00373                 val[2] = (ammo / 25) % 5;
00374                 val[3] = (ammo / 125) % 5;
00375                 val[4] = (ammo / 625) % 5;
00376                 
00377                 color1[0] = 0.2f;
00378                 color1[1] = 0.55f + crandom() * 0.1f;
00379                 color1[2] = 0.5f + crandom() * 0.1f;
00380                 color1[3] = 1.0f;
00381                 trap_R_SetColor( color1 );
00382 
00383                 for ( int t = 0; t < 5; t++ )
00384                 {
00385                         cx = 320 + sin( (t*10+45)/57.296f ) * 192;
00386                         cy = 240 + cos( (t*10+45)/57.296f ) * 192;
00387 
00388                         CG_DrawRotatePic2( cx, cy, 24, 38, 45 - t * 10, trap_R_RegisterShader( va("gfx/2d/char%d",val[4-t] )));
00389                 }
00390 */
00391                 //max = ( cg_entities[0].gent->health / 100.0f );
00392 
00393                 
00394                 if ( (cg.snap->ps.eFlags & EF_DOUBLE_AMMO) )
00395                 {
00396                         max = cg.snap->ps.ammo[weaponData[WP_DISRUPTOR].ammoIndex] / ((float)ammoData[weaponData[WP_DISRUPTOR].ammoIndex].max*2.0f);
00397                 }
00398                 else
00399                 {
00400                         max = cg.snap->ps.ammo[weaponData[WP_DISRUPTOR].ammoIndex] / (float)ammoData[weaponData[WP_DISRUPTOR].ammoIndex].max;
00401                 }
00402                 if ( max > 1.0f )
00403                 {
00404                         max = 1.0f;
00405                 }
00406 
00407                 color1[0] = (1.0f - max) * 2.0f; 
00408                 color1[1] = max * 1.5f;
00409                 color1[2] = 0.0f;
00410                 color1[3] = 1.0f;
00411 
00412                 // If we are low on health, make us flash
00413                 if ( max < 0.15f && ( cg.time & 512 ))
00414                 {
00415                         VectorClear( color1 );
00416                 }
00417 
00418                 if ( color1[0] > 1.0f )
00419                 {
00420                         color1[0] = 1.0f;
00421                 }
00422 
00423                 if ( color1[1] > 1.0f )
00424                 {
00425                         color1[1] = 1.0f;
00426                 }
00427 
00428                 trap_R_SetColor( color1 );
00429 
00430                 max *= 58.0f;
00431 
00432                 for (fi = 18.5f; fi <= 18.5f + max; fi+= 3 ) // going from 15 to 45 degrees, with 5 degree increments
00433                 {
00434                         cx = 320 + sin( (fi+90.0f)/57.296f ) * 190;
00435                         cy = 240 + cos( (fi+90.0f)/57.296f ) * 190;
00436 
00437                         CG_DrawRotatePic2( cx, cy, 12, 24, 90 - fi, cgs.media.disruptorInsertTick );
00438                 }
00439 
00440                 if ( cg.predictedPlayerState.weaponstate == WEAPON_CHARGING_ALT )
00441                 {
00442                         trap_R_SetColor( colorTable[CT_WHITE] );
00443 
00444                         // draw the charge level
00445                         max = ( cg.time - cg.predictedPlayerState.weaponChargeTime ) / ( 50.0f * 30.0f ); // bad hardcodedness 50 is disruptor charge unit and 30 is max charge units allowed.
00446 
00447                         if ( max > 1.0f )
00448                         {
00449                                 max = 1.0f;
00450                         }
00451 
00452                         trap_R_DrawStretchPic(257, 435, 134*max, 34, 0, 0, max, 1, cgs.media.disruptorChargeShader);
00453                 }
00454 //              trap_R_SetColor( colorTable[CT_WHITE] );
00455 //              CG_DrawPic( 0, 0, 640, 480, cgs.media.disruptorMask );
00456 
00457         }
00458 }
00459 
00460 
00461 /*
00462 ================
00463 CG_Draw3DModel
00464 
00465 ================
00466 */
00467 void CG_Draw3DModel( float x, float y, float w, float h, qhandle_t model, void *ghoul2, int g2radius, qhandle_t skin, vec3_t origin, vec3_t angles ) {
00468         refdef_t                refdef;
00469         refEntity_t             ent;
00470 
00471         if ( !cg_draw3dIcons.integer || !cg_drawIcons.integer ) {
00472                 return;
00473         }
00474 
00475         memset( &refdef, 0, sizeof( refdef ) );
00476 
00477         memset( &ent, 0, sizeof( ent ) );
00478         AnglesToAxis( angles, ent.axis );
00479         VectorCopy( origin, ent.origin );
00480         ent.hModel = model;
00481         ent.ghoul2 = ghoul2;
00482         ent.radius = g2radius;
00483         ent.customSkin = skin;
00484         ent.renderfx = RF_NOSHADOW;             // no stencil shadows
00485 
00486         refdef.rdflags = RDF_NOWORLDMODEL;
00487 
00488         AxisClear( refdef.viewaxis );
00489 
00490         refdef.fov_x = 30;
00491         refdef.fov_y = 30;
00492 
00493         refdef.x = x;
00494         refdef.y = y;
00495         refdef.width = w;
00496         refdef.height = h;
00497 
00498         refdef.time = cg.time;
00499 
00500         trap_R_ClearScene();
00501         trap_R_AddRefEntityToScene( &ent );
00502         trap_R_RenderScene( &refdef );
00503 }
00504 
00505 /*
00506 ================
00507 CG_DrawHead
00508 
00509 Used for both the status bar and the scoreboard
00510 ================
00511 */
00512 void CG_DrawHead( float x, float y, float w, float h, int clientNum, vec3_t headAngles ) 
00513 {
00514         clientInfo_t    *ci;
00515 
00516         if (clientNum >= MAX_CLIENTS)
00517         { //npc?
00518                 return;
00519         }
00520 
00521         ci = &cgs.clientinfo[ clientNum ];
00522 
00523         CG_DrawPic( x, y, w, h, ci->modelIcon );
00524 
00525         // if they are deferred, draw a cross out
00526         if ( ci->deferred ) 
00527         {
00528                 CG_DrawPic( x, y, w, h, cgs.media.deferShader );
00529         }
00530 }
00531 
00532 /*
00533 ================
00534 CG_DrawFlagModel
00535 
00536 Used for both the status bar and the scoreboard
00537 ================
00538 */
00539 void CG_DrawFlagModel( float x, float y, float w, float h, int team, qboolean force2D ) {
00540         qhandle_t               cm;
00541         float                   len;
00542         vec3_t                  origin, angles;
00543         vec3_t                  mins, maxs;
00544         qhandle_t               handle;
00545 
00546         if ( !force2D && cg_draw3dIcons.integer ) {
00547 
00548                 VectorClear( angles );
00549 
00550                 cm = cgs.media.redFlagModel;
00551 
00552                 // offset the origin y and z to center the flag
00553                 trap_R_ModelBounds( cm, mins, maxs );
00554 
00555                 origin[2] = -0.5 * ( mins[2] + maxs[2] );
00556                 origin[1] = 0.5 * ( mins[1] + maxs[1] );
00557 
00558                 // calculate distance so the flag nearly fills the box
00559                 // assume heads are taller than wide
00560                 len = 0.5 * ( maxs[2] - mins[2] );              
00561                 origin[0] = len / 0.268;        // len / tan( fov/2 )
00562 
00563                 angles[YAW] = 60 * sin( cg.time / 2000.0 );;
00564 
00565                 if( team == TEAM_RED ) {
00566                         handle = cgs.media.redFlagModel;
00567                 } else if( team == TEAM_BLUE ) {
00568                         handle = cgs.media.blueFlagModel;
00569                 } else if( team == TEAM_FREE ) {
00570                         handle = 0;//cgs.media.neutralFlagModel;
00571                 } else {
00572                         return;
00573                 }
00574                 CG_Draw3DModel( x, y, w, h, handle, NULL, 0, 0, origin, angles );
00575         } else if ( cg_drawIcons.integer ) {
00576                 gitem_t *item;
00577 
00578                 if( team == TEAM_RED ) {
00579                         item = BG_FindItemForPowerup( PW_REDFLAG );
00580                 } else if( team == TEAM_BLUE ) {
00581                         item = BG_FindItemForPowerup( PW_BLUEFLAG );
00582                 } else if( team == TEAM_FREE ) {
00583                         item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
00584                 } else {
00585                         return;
00586                 }
00587                 if (item) {
00588                   CG_DrawPic( x, y, w, h, cg_items[ ITEM_INDEX(item) ].icon );
00589                 }
00590         }
00591 }
00592 
00593 /*
00594 ================
00595 DrawAmmo
00596 ================
00597 */
00598 void DrawAmmo()
00599 {
00600         int x, y;
00601 
00602         x = SCREEN_WIDTH-80;
00603         y = SCREEN_HEIGHT-80;
00604 
00605 }
00606 
00607 
00608 
00609 /*
00610 ================
00611 CG_DrawHealth
00612 ================
00613 */
00614 void CG_DrawHealth( menuDef_t *menuHUD )
00615 {
00616         vec4_t                  calcColor;
00617         playerState_t   *ps;
00618         int                             healthAmt;
00619         int                             i,currValue,inc;
00620         itemDef_t               *focusItem;
00621         float percent;
00622 
00623         // Can we find the menu?
00624         if (!menuHUD)
00625         {
00626                 return;
00627         }
00628 
00629         ps = &cg.snap->ps;
00630 
00631         // What's the health?
00632         healthAmt = ps->stats[STAT_HEALTH];
00633         if (healthAmt > ps->stats[STAT_MAX_HEALTH])
00634         {
00635                 healthAmt = ps->stats[STAT_MAX_HEALTH];
00636         }
00637 
00638 
00639         inc = (float) ps->stats[STAT_MAX_HEALTH] / MAX_HUD_TICS;
00640         currValue = healthAmt;
00641 
00642         // Print the health tics, fading out the one which is partial health
00643         for (i=(MAX_HUD_TICS-1);i>=0;i--)
00644         {
00645                 focusItem = Menu_FindItemByName(menuHUD, healthTicName[i]);
00646 
00647                 if (!focusItem) // This is bad
00648                 {
00649                         continue;
00650                 }
00651 
00652                 memcpy(calcColor, hudTintColor, sizeof(vec4_t));
00653 
00654                 if (currValue <= 0)     // don't show tic
00655                 {
00656                         break;
00657                 }
00658                 else if (currValue < inc)       // partial tic (alpha it out)
00659                 {
00660                         percent = (float) currValue / inc;
00661                         calcColor[3] *= percent;                // Fade it out
00662                 }
00663 
00664                 trap_R_SetColor( calcColor);
00665 
00666                 CG_DrawPic( 
00667                         focusItem->window.rect.x,
00668                         focusItem->window.rect.y,
00669                         focusItem->window.rect.w, 
00670                         focusItem->window.rect.h, 
00671                         focusItem->window.background
00672                         );
00673 
00674                 currValue -= inc;
00675         }
00676 
00677         // Print the mueric amount
00678         focusItem = Menu_FindItemByName(menuHUD, "healthamount");
00679         if (focusItem)
00680         {
00681                 // Print health amount
00682                 trap_R_SetColor( focusItem->window.foreColor ); 
00683 
00684                 CG_DrawNumField (
00685                         focusItem->window.rect.x, 
00686                         focusItem->window.rect.y, 
00687                         3, 
00688                         ps->stats[STAT_HEALTH], 
00689                         focusItem->window.rect.w, 
00690                         focusItem->window.rect.h, 
00691                         NUM_FONT_SMALL,
00692                         qfalse);
00693         }
00694 
00695 }
00696 
00697 /*
00698 ================
00699 CG_DrawArmor
00700 ================
00701 */
00702 void CG_DrawArmor( menuDef_t *menuHUD )
00703 {
00704         vec4_t                  calcColor;
00705         playerState_t   *ps;
00706         int                             armor, maxArmor;
00707         itemDef_t               *focusItem;
00708         float                   percent,quarterArmor;
00709         int                             i,currValue,inc;
00710 
00711         //ps = &cg.snap->ps;
00712         ps = &cg.predictedPlayerState;
00713 
00714         // Can we find the menu?
00715         if (!menuHUD)
00716         {
00717                 return;
00718         }
00719 
00720         armor = ps->stats[STAT_ARMOR];
00721         maxArmor = ps->stats[STAT_MAX_HEALTH];
00722 
00723         if (armor> maxArmor)
00724         {
00725                 armor = maxArmor;
00726         }
00727 
00728         currValue = armor;
00729         inc = (float) maxArmor / MAX_HUD_TICS;
00730 
00731         memcpy(calcColor, hudTintColor, sizeof(vec4_t));
00732         for (i=(MAX_HUD_TICS-1);i>=0;i--)
00733         {
00734                 focusItem = Menu_FindItemByName(menuHUD, armorTicName[i]);
00735 
00736                 if (!focusItem) // This is bad
00737                 {
00738                         continue;
00739                 }
00740 
00741                 memcpy(calcColor, hudTintColor, sizeof(vec4_t));
00742 
00743                 if (currValue <= 0)     // don't show tic
00744                 {
00745                         break;
00746                 }
00747                 else if (currValue < inc)       // partial tic (alpha it out)
00748                 {
00749                         percent = (float) currValue / inc;
00750                         calcColor[3] *= percent;
00751                 }
00752 
00753                 trap_R_SetColor( calcColor);
00754 
00755                 if ((i==(MAX_HUD_TICS-1)) && (currValue < inc))
00756                 {
00757                         if (cg.HUDArmorFlag)
00758                         {
00759                                 CG_DrawPic( 
00760                                         focusItem->window.rect.x,
00761                                         focusItem->window.rect.y,
00762                                         focusItem->window.rect.w, 
00763                                         focusItem->window.rect.h, 
00764                                         focusItem->window.background
00765                                         );
00766                         }
00767                 }
00768                 else 
00769                 {
00770                                 CG_DrawPic( 
00771                                         focusItem->window.rect.x,
00772                                         focusItem->window.rect.y,
00773                                         focusItem->window.rect.w, 
00774                                         focusItem->window.rect.h, 
00775                                         focusItem->window.background
00776                                         );
00777                 }
00778 
00779                 currValue -= inc;
00780         }
00781 
00782         focusItem = Menu_FindItemByName(menuHUD, "armoramount");
00783 
00784         if (focusItem)
00785         {
00786                 // Print armor amount
00787                 trap_R_SetColor( focusItem->window.foreColor ); 
00788 
00789                 CG_DrawNumField (
00790                         focusItem->window.rect.x, 
00791                         focusItem->window.rect.y, 
00792                         3, 
00793                         armor, 
00794                         focusItem->window.rect.w, 
00795                         focusItem->window.rect.h, 
00796                         NUM_FONT_SMALL,
00797                         qfalse);
00798         }
00799 
00800         // If armor is low, flash a graphic to warn the player
00801         if (armor)      // Is there armor? Draw the HUD Armor TIC
00802         {
00803                 quarterArmor = (float) (ps->stats[STAT_MAX_HEALTH] / 4.0f);
00804 
00805                 // Make tic flash if armor is at 25% of full armor
00806                 if (ps->stats[STAT_ARMOR] < quarterArmor)               // Do whatever the flash timer says
00807                 {
00808                         if (cg.HUDTickFlashTime < cg.time)                      // Flip at the same time
00809                         {
00810                                 cg.HUDTickFlashTime = cg.time + 400;
00811                                 if (cg.HUDArmorFlag)
00812                                 {
00813                                         cg.HUDArmorFlag = qfalse;
00814                                 }
00815                                 else
00816                                 {
00817                                         cg.HUDArmorFlag = qtrue;
00818                                 }
00819                         }
00820                 }
00821                 else
00822                 {
00823                         cg.HUDArmorFlag=qtrue;
00824                 }
00825         }
00826         else                                            // No armor? Don't show it.
00827         {
00828                 cg.HUDArmorFlag=qfalse;
00829         }
00830 
00831 }
00832 
00833 /*
00834 ================
00835 CG_DrawSaberStyle
00836 
00837 If the weapon is a light saber (which needs no ammo) then draw a graphic showing
00838 the saber style (fast, medium, strong)
00839 ================
00840 */
00841 static void CG_DrawSaberStyle( centity_t *cent, menuDef_t *menuHUD)
00842 {
00843         itemDef_t               *focusItem;
00844 
00845         if (!cent->currentState.weapon ) // We don't have a weapon right now
00846         {
00847                 return;
00848         }
00849 
00850         if ( cent->currentState.weapon != WP_SABER )
00851         {
00852                 return;
00853         }
00854 
00855         // Can we find the menu?
00856         if (!menuHUD)
00857         {
00858                 return;
00859         }
00860 
00861 
00862         // draw the current saber style in this window
00863         switch ( cg.predictedPlayerState.fd.saberDrawAnimLevel )
00864         {
00865         case 1://FORCE_LEVEL_1:
00866         case 5://FORCE_LEVEL_5://Tavion
00867 
00868                 focusItem = Menu_FindItemByName(menuHUD, "saberstyle_fast");
00869 
00870                 if (focusItem)
00871                 {
00872                         trap_R_SetColor( hudTintColor );
00873 
00874                         CG_DrawPic( 
00875                                 focusItem->window.rect.x,
00876                                 focusItem->window.rect.y,
00877                                 focusItem->window.rect.w, 
00878                                 focusItem->window.rect.h, 
00879                                 focusItem->window.background
00880                                 );
00881                 }
00882 
00883                 break;
00884         case 2://FORCE_LEVEL_2:
00885         case 6://SS_DUAL
00886         case 7://SS_STAFF
00887                 focusItem = Menu_FindItemByName(menuHUD, "saberstyle_medium");
00888 
00889                 if (focusItem)
00890                 {
00891                         trap_R_SetColor( hudTintColor );
00892 
00893                         CG_DrawPic( 
00894                                 focusItem->window.rect.x,
00895                                 focusItem->window.rect.y,
00896                                 focusItem->window.rect.w, 
00897                                 focusItem->window.rect.h, 
00898                                 focusItem->window.background
00899                                 );
00900                 }
00901                 break;
00902         case 3://FORCE_LEVEL_3:
00903         case 4://FORCE_LEVEL_4://Desann
00904                 focusItem = Menu_FindItemByName(menuHUD, "saberstyle_strong");
00905 
00906                 if (focusItem)
00907                 {
00908                         trap_R_SetColor( hudTintColor );
00909 
00910                         CG_DrawPic( 
00911                                 focusItem->window.rect.x,
00912                                 focusItem->window.rect.y,
00913                                 focusItem->window.rect.w, 
00914                                 focusItem->window.rect.h, 
00915                                 focusItem->window.background
00916                                 );
00917                 }
00918                 break;
00919         }
00920 
00921 }
00922 
00923 /*
00924 ================
00925 CG_DrawAmmo
00926 ================
00927 */
00928 static void CG_DrawAmmo( centity_t      *cent,menuDef_t *menuHUD)
00929 {
00930         playerState_t   *ps;
00931         int                             i;
00932         vec4_t                  calcColor;
00933         float                   value,inc = 0.0f,percent;
00934         itemDef_t               *focusItem;
00935 
00936         ps = &cg.snap->ps;
00937 
00938         // Can we find the menu?
00939         if (!menuHUD)
00940         {
00941                 return;
00942         }
00943 
00944         if (!cent->currentState.weapon ) // We don't have a weapon right now
00945         {
00946                 return;
00947         }
00948 
00949         value = ps->ammo[weaponData[cent->currentState.weapon].ammoIndex];
00950         if (value < 0)  // No ammo
00951         {
00952                 return;
00953         }
00954 
00955         focusItem = Menu_FindItemByName(menuHUD, "ammoamount");
00956         trap_R_SetColor( hudTintColor );
00957 
00958         if (weaponData[cent->currentState.weapon].energyPerShot == 0 &&
00959                 weaponData[cent->currentState.weapon].altEnergyPerShot == 0)
00960         { //just draw "infinite"
00961                 inc = 8 / MAX_HUD_TICS;
00962                 value = 8;
00963 
00964                 focusItem = Menu_FindItemByName(menuHUD, "ammoinfinite");
00965                 trap_R_SetColor( hudTintColor );
00966                 if (focusItem)
00967                 {
00968                         UI_DrawProportionalString(focusItem->window.rect.x, focusItem->window.rect.y, "--", NUM_FONT_SMALL, focusItem->window.foreColor);
00969                 }
00970         }
00971         else
00972         {
00973                 focusItem = Menu_FindItemByName(menuHUD, "ammoamount");
00974                 trap_R_SetColor( hudTintColor );
00975                 if (focusItem)
00976                 {
00977 
00978                         if ( (cent->currentState.eFlags & EF_DOUBLE_AMMO) )
00979                         {
00980                                 inc = (float) (ammoData[weaponData[cent->currentState.weapon].ammoIndex].max*2.0f) / MAX_HUD_TICS;
00981                         }
00982                         else
00983                         {
00984                                 inc = (float) ammoData[weaponData[cent->currentState.weapon].ammoIndex].max / MAX_HUD_TICS;
00985                         }
00986                         value =ps->ammo[weaponData[cent->currentState.weapon].ammoIndex];
00987 
00988                         CG_DrawNumField (
00989                                 focusItem->window.rect.x, 
00990                                 focusItem->window.rect.y, 
00991                                 3, 
00992                                 value, 
00993                                 focusItem->window.rect.w, 
00994                                 focusItem->window.rect.h, 
00995                                 NUM_FONT_SMALL,
00996                                 qfalse);
00997                 }
00998         }
00999 
01000         // Draw tics
01001         for (i=MAX_HUD_TICS-1;i>=0;i--)
01002         {
01003                 focusItem = Menu_FindItemByName(menuHUD, ammoTicName[i]);
01004 
01005                 if (!focusItem)
01006                 {
01007                         continue;
01008                 }
01009 
01010                 memcpy(calcColor, hudTintColor, sizeof(vec4_t));
01011 
01012                 if ( value <= 0 )       // done
01013                 {
01014                         break;
01015                 }
01016                 else if (value < inc)   // partial tic
01017                 {
01018                         percent = value / inc;
01019                         calcColor[3] = percent;
01020                 }
01021 
01022                 trap_R_SetColor( calcColor);
01023 
01024                 CG_DrawPic( 
01025                         focusItem->window.rect.x,
01026                         focusItem->window.rect.y,
01027                         focusItem->window.rect.w, 
01028                         focusItem->window.rect.h, 
01029                         focusItem->window.background
01030                         );
01031 
01032                 value -= inc;
01033         }
01034 
01035 }
01036 
01037 /*
01038 ================
01039 CG_DrawForcePower
01040 ================
01041 */
01042 void CG_DrawForcePower( menuDef_t *menuHUD )
01043 {
01044         int                             i;
01045         vec4_t                  calcColor;
01046         float                   value,inc,percent;
01047         itemDef_t               *focusItem;
01048         const int               maxForcePower = 100;
01049         qboolean        flash=qfalse;
01050 
01051         // Can we find the menu?
01052         if (!menuHUD)
01053         {
01054                 return;
01055         }
01056 
01057         // Make the hud flash by setting forceHUDTotalFlashTime above cg.time
01058         if (cg.forceHUDTotalFlashTime > cg.time )
01059         {
01060                 flash = qtrue;
01061                 if (cg.forceHUDNextFlashTime < cg.time) 
01062                 {
01063                         cg.forceHUDNextFlashTime = cg.time + 400;
01064                         trap_S_StartSound (NULL, 0, CHAN_LOCAL, cgs.media.noforceSound );
01065 
01066                         if (cg.forceHUDActive)
01067                         {
01068                                 cg.forceHUDActive = qfalse;
01069                         }
01070                         else
01071                         {
01072                                 cg.forceHUDActive = qtrue;
01073                         }
01074 
01075                 }
01076         }
01077         else    // turn HUD back on if it had just finished flashing time.
01078         {
01079                 cg.forceHUDNextFlashTime = 0;
01080                 cg.forceHUDActive = qtrue;
01081         }
01082 
01083 //      if (!cg.forceHUDActive)
01084 //      {
01085 //              return;
01086 //      }
01087 
01088         inc = (float)  maxForcePower / MAX_HUD_TICS;
01089         value = cg.snap->ps.fd.forcePower;
01090 
01091         for (i=MAX_HUD_TICS-1;i>=0;i--)
01092         {
01093                 focusItem = Menu_FindItemByName(menuHUD, forceTicName[i]);
01094 
01095                 if (!focusItem)
01096                 {
01097                         continue;
01098                 }
01099 
01100 //              memcpy(calcColor, hudTintColor, sizeof(vec4_t));
01101 
01102                 if ( value <= 0 )       // done
01103                 {
01104                         break;
01105                 }
01106                 else if (value < inc)   // partial tic
01107                 {
01108                         if (flash)
01109                         {
01110                                 memcpy(calcColor,  colorTable[CT_RED], sizeof(vec4_t));
01111                         }
01112                         else 
01113                         {
01114                                 memcpy(calcColor,  colorTable[CT_WHITE], sizeof(vec4_t));
01115                         }
01116 
01117                         percent = value / inc;
01118                         calcColor[3] = percent;
01119                 }
01120                 else
01121                 {
01122                         if (flash)
01123                         {
01124                                 memcpy(calcColor,  colorTable[CT_RED], sizeof(vec4_t));
01125                         }
01126                         else 
01127                         {
01128                                 memcpy(calcColor,  colorTable[CT_WHITE], sizeof(vec4_t));
01129                         }
01130                 }
01131 
01132                 trap_R_SetColor( calcColor);
01133 
01134                 CG_DrawPic( 
01135                         focusItem->window.rect.x,
01136                         focusItem->window.rect.y,
01137                         focusItem->window.rect.w, 
01138                         focusItem->window.rect.h, 
01139                         focusItem->window.background
01140                         );
01141 
01142                 value -= inc;
01143         }
01144 
01145         focusItem = Menu_FindItemByName(menuHUD, "forceamount");
01146 
01147         if (focusItem)
01148         {
01149                 // Print force amount
01150                 trap_R_SetColor( focusItem->window.foreColor ); 
01151 
01152                 CG_DrawNumField (
01153                         focusItem->window.rect.x, 
01154                         focusItem->window.rect.y, 
01155                         3, 
01156                         cg.snap->ps.fd.forcePower, 
01157                         focusItem->window.rect.w, 
01158                         focusItem->window.rect.h, 
01159                         NUM_FONT_SMALL,
01160                         qfalse);
01161         }
01162 }
01163 
01164 /*
01165 ================
01166 CG_DrawHUD
01167 ================
01168 */
01169 void CG_DrawHUD(centity_t       *cent)
01170 {
01171         menuDef_t       *menuHUD = NULL;
01172         itemDef_t       *focusItem = NULL;
01173         const char *scoreStr = NULL;
01174         int     scoreBias;
01175         char scoreBiasStr[16];
01176 
01177         if (cg_hudFiles.integer)
01178         {
01179                 int x = 0;
01180                 int y = SCREEN_HEIGHT-80;
01181                 char ammoString[64];
01182                 int weapX = x;
01183 
01184                 UI_DrawProportionalString( x+16, y+40, va( "%i", cg.snap->ps.stats[STAT_HEALTH] ),
01185                         UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_RED] );
01186 
01187                 UI_DrawProportionalString( x+18+14, y+40+14, va( "%i", cg.snap->ps.stats[STAT_ARMOR] ),
01188                         UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_GREEN] );
01189 
01190                 if (cg.snap->ps.weapon == WP_SABER)
01191                 {
01192                         if (cg.snap->ps.fd.saberDrawAnimLevel == SS_DUAL)
01193                         {
01194                                 Com_sprintf(ammoString, sizeof(ammoString), "AKIMBO");
01195                                 weapX += 16;
01196                         }
01197                         else if (cg.snap->ps.fd.saberDrawAnimLevel == SS_STAFF)
01198                         {
01199                                 Com_sprintf(ammoString, sizeof(ammoString), "STAFF");
01200                                 weapX += 16;
01201                         }
01202                         else if (cg.snap->ps.fd.saberDrawAnimLevel == FORCE_LEVEL_3)
01203                         {
01204                                 Com_sprintf(ammoString, sizeof(ammoString), "STRONG");
01205                                 weapX += 16;
01206                         }
01207                         else if (cg.snap->ps.fd.saberDrawAnimLevel == FORCE_LEVEL_2)
01208                         {
01209                                 Com_sprintf(ammoString, sizeof(ammoString), "MEDIUM");
01210                                 weapX += 16;
01211                         }
01212                         else
01213                         {
01214                                 Com_sprintf(ammoString, sizeof(ammoString), "FAST");
01215                         }
01216                 }
01217                 else
01218                 {
01219                         Com_sprintf(ammoString, sizeof(ammoString), "%i", cg.snap->ps.ammo[weaponData[cent->currentState.weapon].ammoIndex]);
01220                 }
01221                 
01222                 UI_DrawProportionalString( SCREEN_WIDTH-(weapX+16+32), y+40, va( "%s", ammoString ),
01223                         UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_ORANGE] );
01224 
01225                 UI_DrawProportionalString( SCREEN_WIDTH-(x+18+14+32), y+40+14, va( "%i", cg.snap->ps.fd.forcePower),
01226                         UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_ICON_BLUE] );
01227 
01228                 return;
01229         }
01230 
01231         if (cgs.gametype >= GT_TEAM && cgs.gametype != GT_SIEGE)
01232         {       // tint the hud items based on team
01233                 if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED )
01234                         hudTintColor = redhudtint;
01235                 else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE )
01236                         hudTintColor = bluehudtint;
01237                 else // If we're not on a team for whatever reason, leave things as they are.
01238                         hudTintColor = colorTable[CT_WHITE];
01239         }
01240         else
01241         {       // tint the hud items white (dont' tint)
01242                 hudTintColor = colorTable[CT_WHITE];
01243         }
01244 
01245         // Draw the left HUD 
01246         menuHUD = Menus_FindByName("lefthud");
01247         if (menuHUD)
01248         {
01249                 itemDef_t *focusItem;
01250 
01251                 // Print scanline
01252                 focusItem = Menu_FindItemByName(menuHUD, "scanline");
01253                 if (focusItem)
01254                 {
01255                         trap_R_SetColor( hudTintColor );        
01256                         CG_DrawPic( 
01257                                 focusItem->window.rect.x, 
01258                                 focusItem->window.rect.y, 
01259                                 focusItem->window.rect.w, 
01260                                 focusItem->window.rect.h, 
01261                                 focusItem->window.background 
01262                                 );                      
01263                 }
01264 
01265                 // Print frame
01266                 focusItem = Menu_FindItemByName(menuHUD, "frame");
01267                 if (focusItem)
01268                 {
01269                         trap_R_SetColor( hudTintColor );        
01270                         CG_DrawPic( 
01271                                 focusItem->window.rect.x, 
01272                                 focusItem->window.rect.y, 
01273                                 focusItem->window.rect.w, 
01274                                 focusItem->window.rect.h, 
01275                                 focusItem->window.background 
01276                                 );                      
01277                 }
01278 
01279                 if (cg.predictedPlayerState.pm_type != PM_SPECTATOR)
01280                 {
01281                         CG_DrawArmor(menuHUD);
01282                         CG_DrawHealth(menuHUD);
01283                 }
01284         }
01285         else
01286         { 
01287                 //CG_Error("CG_ChatBox_ArrayInsert: unable to locate HUD menu file ");
01288         }
01289 
01290         //scoreStr = va("Score: %i", cgs.clientinfo[cg.snap->ps.clientNum].score);
01291         if ( cgs.gametype == GT_DUEL )
01292         {//A duel that requires more than one kill to knock the current enemy back to the queue
01293                 //show current kills out of how many needed
01294                 scoreStr = va("%s: %i/%i", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE], cgs.fraglimit);
01295         }
01296         else if (0 && cgs.gametype < GT_TEAM )
01297         {       // This is a teamless mode, draw the score bias.
01298                 scoreBias = cg.snap->ps.persistant[PERS_SCORE] - cgs.scores1;
01299                 if (scoreBias == 0)
01300                 {       // We are the leader!
01301                         if (cgs.scores2 <= 0)
01302                         {       // Nobody to be ahead of yet.
01303                                 Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), "");
01304                         }
01305                         else
01306                         {
01307                                 scoreBias = cg.snap->ps.persistant[PERS_SCORE] - cgs.scores2;
01308                                 if (scoreBias == 0)
01309                                 {
01310                                         Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (Tie)");
01311                                 }
01312                                 else
01313                                 {
01314                                         Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (+%d)", scoreBias);
01315                                 }
01316                         }
01317                 }
01318                 else // if (scoreBias < 0)
01319                 {       // We are behind!
01320                         Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (%d)", scoreBias);
01321                 }
01322                 scoreStr = va("%s: %i%s", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE], scoreBiasStr);
01323         }
01324         else
01325         {       // Don't draw a bias.
01326                 scoreStr = va("%s: %i", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE]);
01327         }
01328 
01329         menuHUD = Menus_FindByName("righthud");
01330 
01331         if (menuHUD)
01332         {
01333                 if (cgs.gametype != GT_POWERDUEL)
01334                 {
01335                         focusItem = Menu_FindItemByName(menuHUD, "score_line");
01336                         if (focusItem)
01337                         {
01338                                 UI_DrawScaledProportionalString(
01339                                         focusItem->window.rect.x, 
01340                                         focusItem->window.rect.y, 
01341                                         scoreStr, 
01342                                         UI_RIGHT|UI_DROPSHADOW, 
01343                                         focusItem->window.foreColor, 
01344                                         0.7);
01345                         }
01346                 }
01347 
01348                 // Print scanline
01349                 focusItem = Menu_FindItemByName(menuHUD, "scanline");
01350                 if (focusItem)
01351                 {
01352