/codemp/cgame/cg_draw.c
C | 8534 lines | 6389 code | 1213 blank | 932 comment | 1635 complexity | ae3b1e5de7cae0e92a46aa7392141981 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- // Copyright (C) 1999-2000 Id Software, Inc.
- //
- // cg_draw.c -- draw all of the graphical elements during
- // active (after loading) gameplay
- #include "cg_local.h"
- #include "game/bg_saga.h"
- #include "ui/ui_shared.h"
- #include "ui/ui_public.h"
- extern float CG_RadiusForCent( centity_t *cent );
- qboolean CG_WorldCoordToScreenCoordFloat(vec3_t worldCoord, float *x, float *y);
- qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle );
- static void CG_DrawSiegeTimer(int timeRemaining, qboolean isMyTeam);
- static void CG_DrawSiegeDeathTimer( int timeRemaining );
- // nmckenzie: DUEL_HEALTH
- void CG_DrawDuelistHealth ( float x, float y, float w, float h, int duelist );
- // used for scoreboard
- extern displayContextDef_t cgDC;
- menuDef_t *menuScoreboard = NULL;
- int sortedTeamPlayers[TEAM_MAXOVERLAY];
- int numSortedTeamPlayers;
- float lastvalidlockdif;
- extern float zoomFov; //this has to be global client-side
- char systemChat[256];
- char teamChat1[256];
- char teamChat2[256];
- // The time at which you died and the time it will take for you to rejoin game.
- int cg_siegeDeathTime = 0;
- #define MAX_HUD_TICS 4
- const char *armorTicName[MAX_HUD_TICS] =
- {
- "armor_tic1",
- "armor_tic2",
- "armor_tic3",
- "armor_tic4",
- };
- const char *healthTicName[MAX_HUD_TICS] =
- {
- "health_tic1",
- "health_tic2",
- "health_tic3",
- "health_tic4",
- };
- const char *forceTicName[MAX_HUD_TICS] =
- {
- "force_tic1",
- "force_tic2",
- "force_tic3",
- "force_tic4",
- };
- const char *ammoTicName[MAX_HUD_TICS] =
- {
- "ammo_tic1",
- "ammo_tic2",
- "ammo_tic3",
- "ammo_tic4",
- };
- char *showPowersName[] =
- {
- "HEAL2",//FP_HEAL
- "JUMP2",//FP_LEVITATION
- "SPEED2",//FP_SPEED
- "PUSH2",//FP_PUSH
- "PULL2",//FP_PULL
- "MINDTRICK2",//FP_TELEPTAHY
- "GRIP2",//FP_GRIP
- "LIGHTNING2",//FP_LIGHTNING
- "DARK_RAGE2",//FP_RAGE
- "PROTECT2",//FP_PROTECT
- "ABSORB2",//FP_ABSORB
- "TEAM_HEAL2",//FP_TEAM_HEAL
- "TEAM_REPLENISH2",//FP_TEAM_FORCE
- "DRAIN2",//FP_DRAIN
- "SEEING2",//FP_SEE
- "SABER_OFFENSE2",//FP_SABER_OFFENSE
- "SABER_DEFENSE2",//FP_SABER_DEFENSE
- "SABER_THROW2",//FP_SABERTHROW
- NULL
- };
- //Called from UI shared code. For now we'll just redirect to the normal anim load function.
- int UI_ParseAnimationFile(const char *filename, animation_t *animset, qboolean isHumanoid)
- {
- return BG_ParseAnimationFile(filename, animset, isHumanoid);
- }
- int MenuFontToHandle(int iMenuFont)
- {
- switch (iMenuFont)
- {
- case FONT_SMALL: return cgDC.Assets.qhSmallFont;
- case FONT_SMALL2: return cgDC.Assets.qhSmall2Font;
- case FONT_MEDIUM: return cgDC.Assets.qhMediumFont;
- case FONT_LARGE: return cgDC.Assets.qhMediumFont;//cgDC.Assets.qhBigFont;
- //fixme? Big fonr isn't registered...?
- }
- return cgDC.Assets.qhMediumFont;
- }
- int CG_Text_Width(const char *text, float scale, int iMenuFont)
- {
- int iFontIndex = MenuFontToHandle(iMenuFont);
- return trap_R_Font_StrLenPixels(text, iFontIndex, scale);
- }
- int CG_Text_Height(const char *text, float scale, int iMenuFont)
- {
- int iFontIndex = MenuFontToHandle(iMenuFont);
- return trap_R_Font_HeightPixels(iFontIndex, scale);
- }
- #include "qcommon/qfiles.h" // for STYLE_BLINK etc
- void CG_Text_Paint(float x, float y, float scale, vec4_t color, const char *text, float adjust, int limit, int style, int iMenuFont)
- {
- int iStyleOR = 0;
- int iFontIndex = MenuFontToHandle(iMenuFont);
-
- switch (style)
- {
- case ITEM_TEXTSTYLE_NORMAL: iStyleOR = 0;break; // JK2 normal text
- case ITEM_TEXTSTYLE_BLINK: iStyleOR = STYLE_BLINK;break; // JK2 fast blinking
- case ITEM_TEXTSTYLE_PULSE: iStyleOR = STYLE_BLINK;break; // JK2 slow pulsing
- case ITEM_TEXTSTYLE_SHADOWED: iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
- case ITEM_TEXTSTYLE_OUTLINED: iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
- case ITEM_TEXTSTYLE_OUTLINESHADOWED: iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
- case ITEM_TEXTSTYLE_SHADOWEDMORE: iStyleOR = (int)STYLE_DROPSHADOW;break; // JK2 drop shadow ( need a color for this )
- }
- trap_R_Font_DrawString( x, // int ox
- y, // int oy
- text, // const char *text
- color, // paletteRGBA_c c
- iStyleOR | iFontIndex, // const int iFontHandle
- !limit?-1:limit, // iCharLimit (-1 = none)
- scale // const float scale = 1.0f
- );
- }
- /*
- qboolean CG_WorldCoordToScreenCoord(vec3_t worldCoord, int *x, int *y)
- Take any world coord and convert it to a 2D virtual 640x480 screen coord
- */
- /*
- qboolean CG_WorldCoordToScreenCoordFloat(vec3_t worldCoord, float *x, float *y)
- {
- int xcenter, ycenter;
- vec3_t local, transformed;
- // xcenter = cg.refdef.width / 2;//gives screen coords adjusted for resolution
- // ycenter = cg.refdef.height / 2;//gives screen coords adjusted for resolution
-
- //NOTE: did it this way because most draw functions expect virtual 640x480 coords
- // and adjust them for current resolution
- xcenter = 640 / 2;//gives screen coords in virtual 640x480, to be adjusted when drawn
- ycenter = 480 / 2;//gives screen coords in virtual 640x480, to be adjusted when drawn
- VectorSubtract (worldCoord, cg.refdef.vieworg, local);
- transformed[0] = DotProduct(local,vright);
- transformed[1] = DotProduct(local,vup);
- transformed[2] = DotProduct(local,vfwd);
- // Make sure Z is not negative.
- if(transformed[2] < 0.01)
- {
- return qfalse;
- }
- // Simple convert to screen coords.
- float xzi = xcenter / transformed[2] * (90.0/cg.refdef.fov_x);
- float yzi = ycenter / transformed[2] * (90.0/cg.refdef.fov_y);
- *x = xcenter + xzi * transformed[0];
- *y = ycenter - yzi * transformed[1];
- return qtrue;
- }
- qboolean CG_WorldCoordToScreenCoord( vec3_t worldCoord, int *x, int *y )
- {
- float xF, yF;
- qboolean retVal = CG_WorldCoordToScreenCoordFloat( worldCoord, &xF, &yF );
- *x = (int)xF;
- *y = (int)yF;
- return retVal;
- }
- */
- /*
- ================
- CG_DrawZoomMask
- ================
- */
- static void CG_DrawZoomMask( void )
- {
- vec4_t color1;
- float level;
- static qboolean flip = qtrue;
- // int ammo = cg_entities[0].gent->client->ps.ammo[weaponData[cent->currentState.weapon].ammoIndex];
- float cx, cy;
- // int val[5];
- float max, fi;
- // Check for Binocular specific zooming since we'll want to render different bits in each case
- if ( cg.predictedPlayerState.zoomMode == 2 )
- {
- int val, i;
- float off;
- // zoom level
- level = (float)(80.0f - cg.predictedPlayerState.zoomFov) / 80.0f;
- // ...so we'll clamp it
- if ( level < 0.0f )
- {
- level = 0.0f;
- }
- else if ( level > 1.0f )
- {
- level = 1.0f;
- }
- // Using a magic number to convert the zoom level to scale amount
- level *= 162.0f;
- // draw blue tinted distortion mask, trying to make it as small as is necessary to fill in the viewable area
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic( 34, 48, 570, 362, cgs.media.binocularStatic );
-
- // Black out the area behind the numbers
- trap_R_SetColor( colorTable[CT_BLACK]);
- CG_DrawPic( 212, 367, 200, 40, cgs.media.whiteShader );
- // Numbers should be kind of greenish
- color1[0] = 0.2f;
- color1[1] = 0.4f;
- color1[2] = 0.2f;
- color1[3] = 0.3f;
- trap_R_SetColor( color1 );
- // Draw scrolling numbers, use intervals 10 units apart--sorry, this section of code is just kind of hacked
- // up with a bunch of magic numbers.....
- val = ((int)((cg.refdef.viewangles[YAW] + 180) / 10)) * 10;
- off = (cg.refdef.viewangles[YAW] + 180) - val;
- for ( i = -10; i < 30; i += 10 )
- {
- val -= 10;
- if ( val < 0 )
- {
- val += 360;
- }
- // we only want to draw the very far left one some of the time, if it's too far to the left it will
- // poke outside the mask.
- if (( off > 3.0f && i == -10 ) || i > -10 )
- {
- // draw the value, but add 200 just to bump the range up...arbitrary, so change it if you like
- CG_DrawNumField( 155 + i * 10 + off * 10, 374, 3, val + 200, 24, 14, NUM_FONT_CHUNKY, qtrue );
- CG_DrawPic( 245 + (i-1) * 10 + off * 10, 376, 6, 6, cgs.media.whiteShader );
- }
- }
- CG_DrawPic( 212, 367, 200, 28, cgs.media.binocularOverlay );
- color1[0] = sin( cg.time * 0.01 + cg.timeFraction * 0.01 ) * 0.5f + 0.5f;
- color1[0] = color1[0] * color1[0];
- color1[1] = color1[0];
- color1[2] = color1[0];
- color1[3] = 1.0f;
- trap_R_SetColor( color1 );
- CG_DrawPic( 82, 94, 16, 16, cgs.media.binocularCircle );
- // Flickery color
- color1[0] = 0.7f + crandom() * 0.1f;
- color1[1] = 0.8f + crandom() * 0.1f;
- color1[2] = 0.7f + crandom() * 0.1f;
- color1[3] = 1.0f;
- trap_R_SetColor( color1 );
-
- CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, cgs.media.binocularMask );
- CG_DrawPic( 4, 282 - level, 16, 16, cgs.media.binocularArrow );
- // The top triangle bit randomly flips
- if ( flip )
- {
- CG_DrawPic( 330, 60, -26, -30, cgs.media.binocularTri );
- }
- else
- {
- CG_DrawPic( 307, 40, 26, 30, cgs.media.binocularTri );
- }
- if ( random() > 0.98f && ( cg.time & 1024 ))
- {
- flip = !flip;
- }
- }
- else if (cg.zoomMode)
- {
- // disruptor zoom mode
- level = (float)(50.0f - zoomFov) / 50.0f;//(float)(80.0f - zoomFov) / 80.0f;
- // ...so we'll clamp it
- if ( level < 0.0f )
- {
- level = 0.0f;
- }
- else if ( level > 1.0f )
- {
- level = 1.0f;
- }
- if (!cg.playerPredicted)
- level = 0.46f;
- // Using a magic number to convert the zoom level to a rotation amount that correlates more or less with the zoom artwork.
- level *= 103.0f;
- // Draw target mask
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, cgs.media.disruptorMask );
- // apparently 99.0f is the full zoom level
- if ( level >= 99 )
- {
- // Fully zoomed, so make the rotating insert pulse
- color1[0] = 1.0f;
- color1[1] = 1.0f;
- color1[2] = 1.0f;
- color1[3] = 0.7f + sin( cg.time * 0.01 + cg.timeFraction * 0.01 ) * 0.3f;
- trap_R_SetColor( color1 );
- }
- // Draw rotating insert
- CG_DrawRotatePic2( SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT, -level, cgs.media.disruptorInsert );
- // Increase the light levels under the center of the target
- // CG_DrawPic( 198, 118, 246, 246, cgs.media.disruptorLight );
- // weirdness.....converting ammo to a base five number scale just to be geeky.
- /* val[0] = ammo % 5;
- val[1] = (ammo / 5) % 5;
- val[2] = (ammo / 25) % 5;
- val[3] = (ammo / 125) % 5;
- val[4] = (ammo / 625) % 5;
-
- color1[0] = 0.2f;
- color1[1] = 0.55f + crandom() * 0.1f;
- color1[2] = 0.5f + crandom() * 0.1f;
- color1[3] = 1.0f;
- trap_R_SetColor( color1 );
- for ( int t = 0; t < 5; t++ )
- {
- cx = 320 + sin( (t*10+45)/57.296f ) * 192;
- cy = 240 + cos( (t*10+45)/57.296f ) * 192;
- CG_DrawRotatePic2( cx, cy, 24, 38, 45 - t * 10, trap_R_RegisterShader( va("gfx/2d/char%d",val[4-t] )));
- }
- */
- //max = ( cg_entities[0].gent->health / 100.0f );
- if (cg.playerPredicted) {
- if ( (cg.snap->ps.eFlags & EF_DOUBLE_AMMO) )
- max = cg.snap->ps.ammo[weaponData[WP_DISRUPTOR].ammoIndex] / ((float)ammoData[weaponData[WP_DISRUPTOR].ammoIndex].max*2.0f);
- else
- max = cg.snap->ps.ammo[weaponData[WP_DISRUPTOR].ammoIndex] / (float)ammoData[weaponData[WP_DISRUPTOR].ammoIndex].max;
- if ( max > 1.0f )
- max = 1.0f;
- } else {
- max = 0.5f; // let it be half
- }
- color1[0] = (1.0f - max) * 2.0f;
- color1[1] = max * 1.5f;
- color1[2] = 0.0f;
- color1[3] = 1.0f;
- // If we are low on health, make us flash
- if ( max < 0.15f && ( cg.time & 512 ))
- {
- VectorClear( color1 );
- }
- if ( color1[0] > 1.0f )
- {
- color1[0] = 1.0f;
- }
- if ( color1[1] > 1.0f )
- {
- color1[1] = 1.0f;
- }
- trap_R_SetColor( color1 );
- max *= 58.0f;
- for (fi = 18.5f; fi <= 18.5f + max; fi+= 3 ) // going from 15 to 45 degrees, with 5 degree increments
- {
- cx = SCREEN_WIDTH / 2 + sin( (fi+90.0f)/57.296f ) * 190;
- cy = SCREEN_HEIGHT / 2 + cos( (fi+90.0f)/57.296f ) * 190;
- CG_DrawRotatePic2( cx, cy, 12, 24, 90 - fi, cgs.media.disruptorInsertTick );
- }
- if ((cg.playerPredicted && cg.predictedPlayerState.weaponstate == WEAPON_CHARGING_ALT)
- || (!cg.playerPredicted && cg.charging && cg.chargeTime && cg.time > cg.chargeTime))
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- // draw the charge level
- if (cg.playerPredicted)
- max = ((cg.time - cg.predictedPlayerState.weaponChargeTime) + cg.timeFraction) / (50.0f * 30.0f); // bad hardcodedness 50 is disruptor charge unit and 30 is max charge units allowed.
- else
- max = ((cg.time - cg.chargeTime) + cg.timeFraction) / (50.0f * 30.0f);
- if ( max > 1.0f )
- {
- max = 1.0f;
- }
- trap_R_DrawStretchPic(257, 435, 134*max, 34, 0, 0, max, 1, cgs.media.disruptorChargeShader);
- }
- // trap_R_SetColor( colorTable[CT_WHITE] );
- // CG_DrawPic( 0, 0, 640, 480, cgs.media.disruptorMask );
- }
- }
- /*
- ================
- CG_Draw3DModel
- ================
- */
- 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 ) {
- refdef_t refdef;
- refEntity_t ent;
- if ( !cg_draw3DIcons.integer || !cg_drawIcons.integer ) {
- return;
- }
- memset( &refdef, 0, sizeof( refdef ) );
- memset( &ent, 0, sizeof( ent ) );
- AnglesToAxis( angles, ent.axis );
- VectorCopy( origin, ent.origin );
- ent.hModel = model;
- ent.ghoul2 = ghoul2;
- ent.radius = g2radius;
- ent.customSkin = skin;
- ent.renderfx = RF_NOSHADOW; // no stencil shadows
- refdef.rdflags = RDF_NOWORLDMODEL;
- AxisClear( refdef.viewaxis );
- refdef.fov_x = 30;
- refdef.fov_y = 30;
- refdef.x = x;
- refdef.y = y;
- refdef.width = w;
- refdef.height = h;
- refdef.time = cg.time;
- trap_R_ClearScene();
- trap_R_AddRefEntityToScene( &ent );
- trap_R_RenderScene( &refdef );
- }
- /*
- ================
- CG_DrawHead
- Used for both the status bar and the scoreboard
- ================
- */
- void CG_DrawHead( float x, float y, float w, float h, int clientNum, vec3_t headAngles )
- {
- clientInfo_t *ci;
- if (clientNum >= MAX_CLIENTS)
- { //npc?
- return;
- }
- ci = &cgs.clientinfo[ clientNum ];
- CG_DrawPic( x, y, w, h, ci->modelIcon );
- // if they are deferred, draw a cross out
- if ( ci->deferred )
- {
- CG_DrawPic( x, y, w, h, cgs.media.deferShader );
- }
- }
- /*
- ================
- CG_DrawFlagModel
- Used for both the status bar and the scoreboard
- ================
- */
- void CG_DrawFlagModel( float x, float y, float w, float h, int team, qboolean force2D ) {
- qhandle_t cm;
- float len;
- vec3_t origin, angles;
- vec3_t mins, maxs;
- qhandle_t handle;
- if ( !force2D && cg_draw3DIcons.integer ) {
- //Raz: need to adjust the coords only for 3d models
- // 2d icons use virtual screen coords
- x *= cgs.screenXScale;
- y *= cgs.screenYScale;
- w *= cgs.screenXScale;
- h *= cgs.screenYScale;
- VectorClear( angles );
- cm = cgs.media.redFlagModel;
- // offset the origin y and z to center the flag
- trap_R_ModelBounds( cm, mins, maxs );
- origin[2] = -0.5 * ( mins[2] + maxs[2] );
- origin[1] = 0.5 * ( mins[1] + maxs[1] );
- // calculate distance so the flag nearly fills the box
- // assume heads are taller than wide
- len = 0.5 * ( maxs[2] - mins[2] );
- origin[0] = len / 0.268; // len / tan( fov/2 )
- angles[YAW] = 60 * sin((double)((double)cg.time + cg.timeFraction) / 2000.0);;
- if( team == TEAM_RED ) {
- handle = cgs.media.redFlagModel;
- } else if( team == TEAM_BLUE ) {
- handle = cgs.media.blueFlagModel;
- } else if( team == TEAM_FREE ) {
- handle = 0;//cgs.media.neutralFlagModel;
- } else {
- return;
- }
- CG_Draw3DModel( x, y, w, h, handle, NULL, 0, 0, origin, angles );
- } else if ( cg_drawIcons.integer ) {
- gitem_t *item;
- if( team == TEAM_RED ) {
- item = BG_FindItemForPowerup( PW_REDFLAG );
- } else if( team == TEAM_BLUE ) {
- item = BG_FindItemForPowerup( PW_BLUEFLAG );
- } else if( team == TEAM_FREE ) {
- item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
- } else {
- return;
- }
- if (item) {
- CG_DrawPic( x, y, w, h, cg_items[ ITEM_INDEX(item) ].icon );
- }
- }
- }
- /*
- ================
- CG_DrawHealth
- ================
- */
- void CG_DrawHealth( menuDef_t *menuHUD )
- {
- vec4_t calcColor;
- playerState_t *ps;
- int healthAmt;
- int i,currValue,inc;
- itemDef_t *focusItem;
- float percent;
- // Can we find the menu?
- if (!menuHUD)
- {
- return;
- }
- ps = &cg.snap->ps;
- // What's the health?
- healthAmt = ps->stats[STAT_HEALTH];
- if (healthAmt > ps->stats[STAT_MAX_HEALTH])
- {
- healthAmt = ps->stats[STAT_MAX_HEALTH];
- }
- inc = (float) ps->stats[STAT_MAX_HEALTH] / MAX_HUD_TICS;
- currValue = healthAmt;
- // Print the health tics, fading out the one which is partial health
- for (i=(MAX_HUD_TICS-1);i>=0;i--)
- {
- focusItem = Menu_FindItemByName(menuHUD, healthTicName[i]);
- if (!focusItem) // This is bad
- {
- continue;
- }
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- if (currValue <= 0) // don't show tic
- {
- break;
- }
- else if (currValue < inc) // partial tic (alpha it out)
- {
- percent = (float) currValue / inc;
- calcColor[3] *= percent; // Fade it out
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- focusItem->window.rect.x*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- currValue -= inc;
- }
- // Print the mueric amount
- focusItem = Menu_FindItemByName(menuHUD, "healthamount");
- if (focusItem)
- {
- // Print health amount
- trap_R_SetColor( focusItem->window.foreColor );
- CG_DrawNumField (
- focusItem->window.rect.x*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- 3,
- ps->stats[STAT_HEALTH],
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- NUM_FONT_SMALL,
- qfalse);
- }
- }
- /*
- ================
- CG_DrawArmor
- ================
- */
- void CG_DrawArmor( menuDef_t *menuHUD )
- {
- vec4_t calcColor;
- playerState_t *ps;
- int maxArmor;
- itemDef_t *focusItem;
- float percent,quarterArmor;
- int i,currValue,inc;
- //ps = &cg.snap->ps;
- ps = &cg.predictedPlayerState;
- // Can we find the menu?
- if (!menuHUD)
- {
- return;
- }
- maxArmor = ps->stats[STAT_MAX_HEALTH];
- currValue = ps->stats[STAT_ARMOR];
- inc = (float) maxArmor / MAX_HUD_TICS;
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- for (i=(MAX_HUD_TICS-1);i>=0;i--)
- {
- focusItem = Menu_FindItemByName(menuHUD, armorTicName[i]);
- if (!focusItem) // This is bad
- {
- continue;
- }
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- if (currValue <= 0) // don't show tic
- {
- break;
- }
- else if (currValue < inc) // partial tic (alpha it out)
- {
- percent = (float) currValue / inc;
- calcColor[3] *= percent;
- }
- trap_R_SetColor( calcColor);
- if ((i==(MAX_HUD_TICS-1)) && (currValue < inc))
- {
- if (cg.HUDArmorFlag)
- {
- CG_DrawPic(
- focusItem->window.rect.x*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- }
- else
- {
- CG_DrawPic(
- focusItem->window.rect.x*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- currValue -= inc;
- }
- focusItem = Menu_FindItemByName(menuHUD, "armoramount");
- if (focusItem)
- {
- // Print armor amount
- trap_R_SetColor( focusItem->window.foreColor );
- CG_DrawNumField (
- focusItem->window.rect.x*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- 3,
- ps->stats[STAT_ARMOR],
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- NUM_FONT_SMALL,
- qfalse);
- }
- // If armor is low, flash a graphic to warn the player
- if (ps->stats[STAT_ARMOR]) // Is there armor? Draw the HUD Armor TIC
- {
- quarterArmor = (float) (ps->stats[STAT_MAX_HEALTH] / 4.0f);
- // Make tic flash if armor is at 25% of full armor
- if (ps->stats[STAT_ARMOR] < quarterArmor) // Do whatever the flash timer says
- {
- if (cg.HUDTickFlashTime < cg.time) // Flip at the same time
- {
- cg.HUDTickFlashTime = cg.time + 400;
- if (cg.HUDArmorFlag)
- {
- cg.HUDArmorFlag = qfalse;
- }
- else
- {
- cg.HUDArmorFlag = qtrue;
- }
- }
- }
- else
- {
- cg.HUDArmorFlag=qtrue;
- }
- }
- else // No armor? Don't show it.
- {
- cg.HUDArmorFlag=qfalse;
- }
- }
- /*
- ================
- CG_DrawSaberStyle
- If the weapon is a light saber (which needs no ammo) then draw a graphic showing
- the saber style (fast, medium, strong)
- ================
- */
- static void CG_DrawSaberStyle( centity_t *cent, menuDef_t *menuHUD)
- {
- itemDef_t *focusItem;
- if (!cent->currentState.weapon ) // We don't have a weapon right now
- {
- return;
- }
- if ( cent->currentState.weapon != WP_SABER )
- {
- return;
- }
- // Can we find the menu?
- if (!menuHUD)
- {
- return;
- }
- // draw the current saber style in this window
- switch ( cg.predictedPlayerState.fd.saberDrawAnimLevel )
- {
- case 1://FORCE_LEVEL_1:
- case 5://FORCE_LEVEL_5://Tavion
- focusItem = Menu_FindItemByName(menuHUD, "saberstyle_fast");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- break;
- case 2://FORCE_LEVEL_2:
- case 6://SS_DUAL
- case 7://SS_STAFF
- focusItem = Menu_FindItemByName(menuHUD, "saberstyle_medium");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- break;
- case 3://FORCE_LEVEL_3:
- case 4://FORCE_LEVEL_4://Desann
- focusItem = Menu_FindItemByName(menuHUD, "saberstyle_strong");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- break;
- }
- }
- /*
- ================
- CG_DrawAmmo
- ================
- */
- static void CG_DrawAmmo( centity_t *cent,menuDef_t *menuHUD)
- {
- playerState_t *ps;
- int i;
- vec4_t calcColor;
- float value=0.0f,inc = 0.0f,percent;
- itemDef_t *focusItem;
- ps = &cg.snap->ps;
- // Can we find the menu?
- if (!menuHUD)
- {
- return;
- }
- if (!cent->currentState.weapon ) // We don't have a weapon right now
- {
- return;
- }
- value = ps->ammo[weaponData[cent->currentState.weapon].ammoIndex];
- if (value < 0) // No ammo
- {
- return;
- }
- //
- // ammo
- //
- if (cg.oldammo < value)
- {
- cg.oldAmmoTime = cg.time + 200;
- }
- cg.oldammo = value;
- focusItem = Menu_FindItemByName(menuHUD, "ammoamount");
- if (weaponData[cent->currentState.weapon].energyPerShot == 0 &&
- weaponData[cent->currentState.weapon].altEnergyPerShot == 0)
- { //just draw "infinite"
- inc = 8 / MAX_HUD_TICS;
- value = 8;
- focusItem = Menu_FindItemByName(menuHUD, "ammoinfinite");
- trap_R_SetColor( colorTable[CT_YELLOW] );
- if (focusItem)
- {
- UI_DrawProportionalString(SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef, focusItem->window.rect.y, "--", NUM_FONT_SMALL, focusItem->window.foreColor);
- }
- }
- else
- {
- focusItem = Menu_FindItemByName(menuHUD, "ammoamount");
- // Firing or reloading?
- if (( cg.predictedPlayerState.weaponstate == WEAPON_FIRING
- && cg.predictedPlayerState.weaponTime > 100 ))
- {
- memcpy(calcColor, colorTable[CT_LTGREY], sizeof(vec4_t));
- }
- else
- {
- if ( value > 0 )
- {
- if (cg.oldAmmoTime > cg.time)
- {
- memcpy(calcColor, colorTable[CT_YELLOW], sizeof(vec4_t));
- }
- else
- {
- memcpy(calcColor, focusItem->window.foreColor, sizeof(vec4_t));
- }
- }
- else
- {
- memcpy(calcColor, colorTable[CT_RED], sizeof(vec4_t));
- }
- }
- trap_R_SetColor( calcColor );
- if (focusItem)
- {
- if ( (cent->currentState.eFlags & EF_DOUBLE_AMMO) )
- {
- inc = (float) (ammoData[weaponData[cent->currentState.weapon].ammoIndex].max*2.0f) / MAX_HUD_TICS;
- }
- else
- {
- inc = (float) ammoData[weaponData[cent->currentState.weapon].ammoIndex].max / MAX_HUD_TICS;
- }
- value =ps->ammo[weaponData[cent->currentState.weapon].ammoIndex];
- CG_DrawNumField (
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- 3,
- value,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- NUM_FONT_SMALL,
- qfalse);
- }
- }
- trap_R_SetColor( colorTable[CT_WHITE] );
- // Draw tics
- for (i=MAX_HUD_TICS-1;i>=0;i--)
- {
- focusItem = Menu_FindItemByName(menuHUD, ammoTicName[i]);
- if (!focusItem)
- {
- continue;
- }
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- if ( value <= 0 ) // done
- {
- break;
- }
- else if (value < inc) // partial tic
- {
- percent = value / inc;
- calcColor[3] = percent;
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- value -= inc;
- }
- }
- /*
- ================
- CG_DrawForcePower
- ================
- */
- void CG_DrawForcePower( menuDef_t *menuHUD )
- {
- int i;
- vec4_t calcColor;
- float value,inc,percent;
- itemDef_t *focusItem;
- const int maxForcePower = 100;
- qboolean flash=qfalse;
- // Can we find the menu?
- if (!menuHUD)
- {
- return;
- }
- if (cg.forceHUDTotalFlashTime < cg.time) {
- cg.forceHUDTotalFlashTime = 0;
- cg.forceHUDNextFlashTime = 0;
- }// else {
- // cg.forceHUDTotalFlashTime = cg.time + 1000;
- // }
- // Make the hud flash by setting forceHUDTotalFlashTime above cg.time
- if (cg.forceHUDTotalFlashTime > cg.time )
- {
- flash = qtrue;
- if (cg.forceHUDNextFlashTime < cg.time)
- {
- cg.forceHUDNextFlashTime = cg.time + 400;
- trap_S_StartSound (NULL, 0, CHAN_LOCAL, cgs.media.noforceSound );
- if (cg.forceHUDActive)
- {
- cg.forceHUDActive = qfalse;
- }
- else
- {
- cg.forceHUDActive = qtrue;
- }
- }
- }
- else // turn HUD back on if it had just finished flashing time.
- {
- cg.forceHUDNextFlashTime = 0;
- cg.forceHUDActive = qtrue;
- }
- // if (!cg.forceHUDActive)
- // {
- // return;
- // }
- inc = (float) maxForcePower / MAX_HUD_TICS;
- value = cg.snap->ps.fd.forcePower;
- for (i=MAX_HUD_TICS-1;i>=0;i--)
- {
- focusItem = Menu_FindItemByName(menuHUD, forceTicName[i]);
- if (!focusItem)
- {
- continue;
- }
- // memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- if ( value <= 0 ) // done
- {
- break;
- }
- else if (value < inc) // partial tic
- {
- if (flash)
- {
- memcpy(calcColor, colorTable[CT_RED], sizeof(vec4_t));
- }
- else
- {
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- }
- percent = value / inc;
- calcColor[3] = percent;
- }
- else
- {
- if (flash)
- {
- memcpy(calcColor, colorTable[CT_RED], sizeof(vec4_t));
- }
- else
- {
- memcpy(calcColor, colorTable[CT_WHITE], sizeof(vec4_t));
- }
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- SCREEN_WIDTH - (SCREEN_WIDTH - (float)focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- value -= inc;
- }
- focusItem = Menu_FindItemByName(menuHUD, "forceamount");
- if (focusItem)
- {
- // Print force amount
- trap_R_SetColor( focusItem->window.foreColor );
- CG_DrawNumField (
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef,
- focusItem->window.rect.y,
- 3,
- cg.snap->ps.fd.forcePower,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- NUM_FONT_SMALL,
- qfalse);
- }
- }
- /*
- ================
- CG_DrawHUD
- ================
- */
- void CG_DrawHUD(centity_t *cent)
- {
- menuDef_t *menuHUD = NULL;
- itemDef_t *focusItem = NULL;
- const char *scoreStr = NULL;
- int scoreBias;
- char scoreBiasStr[16];
- if (cg_hudFiles.integer)
- {
- int x = 0;
- int y = SCREEN_HEIGHT-80;
- char ammoString[64];
- int weapX = x;
- if (cg.predictedPlayerState.pm_type != PM_SPECTATOR)
- {
- UI_DrawProportionalString( (x+16)*cgs.widthRatioCoef, y+40, va( "%i", cg.snap->ps.stats[STAT_HEALTH] ),
- UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_RED] );
- UI_DrawProportionalString( (x+18+14)*cgs.widthRatioCoef, y+40+14, va( "%i", cg.snap->ps.stats[STAT_ARMOR] ),
- UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_GREEN] );
- if (cg.snap->ps.weapon == WP_SABER)
- {
- if (cg.snap->ps.fd.saberDrawAnimLevel == SS_DUAL)
- {
- Com_sprintf(ammoString, sizeof(ammoString), "AKIMBO");
- weapX += 16;
- }
- else if (cg.snap->ps.fd.saberDrawAnimLevel == SS_STAFF)
- {
- Com_sprintf(ammoString, sizeof(ammoString), "STAFF");
- weapX += 16;
- }
- else if (cg.snap->ps.fd.saberDrawAnimLevel == FORCE_LEVEL_3)
- {
- Com_sprintf(ammoString, sizeof(ammoString), "STRONG");
- weapX += 16;
- }
- else if (cg.snap->ps.fd.saberDrawAnimLevel == FORCE_LEVEL_2)
- {
- Com_sprintf(ammoString, sizeof(ammoString), "MEDIUM");
- weapX += 16;
- }
- else
- {
- Com_sprintf(ammoString, sizeof(ammoString), "FAST");
- }
- }
- else if (weaponData[cent->currentState.weapon].energyPerShot == 0 && weaponData[cent->currentState.weapon].altEnergyPerShot == 0)
- {
- Q_strncpyz(ammoString, "--", sizeof(ammoString));
- }
- else
- {
- Com_sprintf(ammoString, sizeof(ammoString), "%i", cg.snap->ps.ammo[weaponData[cent->currentState.weapon].ammoIndex]);
- }
-
- UI_DrawProportionalString( SCREEN_WIDTH-(weapX+16+32), y+40, va( "%s", ammoString ),
- UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_HUD_ORANGE] );
- UI_DrawProportionalString( SCREEN_WIDTH-(x+18+14+32), y+40+14, va( "%i", cg.snap->ps.fd.forcePower),
- UI_SMALLFONT|UI_DROPSHADOW, colorTable[CT_ICON_BLUE] );
- }
- return;
- }
- if (cg.predictedPlayerState.pm_type != PM_SPECTATOR)
- {
- // Draw the left HUD
- menuHUD = Menus_FindByName("lefthud");
- Menu_Paint( menuHUD, qtrue );
- if (menuHUD)
- {
- itemDef_t *focusItem;
- // Print scanline
- focusItem = Menu_FindItemByName(menuHUD, "scanline");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- focusItem->window.rect.x,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- // Print frame
- focusItem = Menu_FindItemByName(menuHUD, "frame");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- focusItem->window.rect.x,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- CG_DrawArmor(menuHUD);
- CG_DrawHealth(menuHUD);
- }
- else
- {
- //CG_Error("CG_ChatBox_ArrayInsert: unable to locate HUD menu file ");
- }
- //scoreStr = va("Score: %i", cgs.clientinfo[cg.snap->ps.clientNum].score);
- if ( cgs.gametype == GT_DUEL )
- {//A duel that requires more than one kill to knock the current enemy back to the queue
- //show current kills out of how many needed
- scoreStr = va("%s: %i/%i", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE], cgs.fraglimit);
- }
- else if (0 && cgs.gametype < GT_TEAM )
- { // This is a teamless mode, draw the score bias.
- scoreBias = cg.snap->ps.persistant[PERS_SCORE] - cgs.scores1;
- if (scoreBias == 0)
- { // We are the leader!
- if (cgs.scores2 <= 0)
- { // Nobody to be ahead of yet.
- Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), "");
- }
- else
- {
- scoreBias = cg.snap->ps.persistant[PERS_SCORE] - cgs.scores2;
- if (scoreBias == 0)
- {
- Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (Tie)");
- }
- else
- {
- Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (+%d)", scoreBias);
- }
- }
- }
- else // if (scoreBias < 0)
- { // We are behind!
- Com_sprintf(scoreBiasStr, sizeof(scoreBiasStr), " (%d)", scoreBias);
- }
- scoreStr = va("%s: %i%s", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE], scoreBiasStr);
- }
- else
- { // Don't draw a bias.
- scoreStr = va("%s: %i", CG_GetStringEdString("MP_INGAME", "SCORE"), cg.snap->ps.persistant[PERS_SCORE]);
- }
- menuHUD = Menus_FindByName("righthud");
- Menu_Paint( menuHUD, qtrue );
- if (menuHUD)
- {
- if (cgs.gametype != GT_POWERDUEL)
- {
- focusItem = Menu_FindItemByName(menuHUD, "score_line");
- if (focusItem)
- {
- UI_DrawScaledProportionalString(
- SCREEN_WIDTH - (SCREEN_WIDTH - focusItem->window.rect.x)*cgs.widthRatioCoef - 17,
- focusItem->window.rect.y,
- scoreStr,
- UI_RIGHT|UI_DROPSHADOW,
- focusItem->window.foreColor,
- 0.7f);
- }
- }
- // Print scanline
- focusItem = Menu_FindItemByName(menuHUD, "scanline");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- focusItem->window.rect.x,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- focusItem = Menu_FindItemByName(menuHUD, "frame");
- if (focusItem)
- {
- trap_R_SetColor( colorTable[CT_WHITE] );
- CG_DrawPic(
- focusItem->window.rect.x,
- focusItem->window.rect.y,
- focusItem->window.rect.w*cgs.widthRatioCoef,
- focusItem->window.rect.h,
- focusItem->window.background
- );
- }
- CG_DrawForcePower(menuHUD);
- // Draw ammo tics or saber style
- if ( cent->currentState.weapon == WP_SABER )
- {
- CG_DrawSaberStyle(cent,menuHUD);
- }
- else
- {
- CG_DrawAmmo(cent,menuHUD);
- }
- }
- else
- {
- //CG_Error("CG_ChatBox_ArrayInsert: unable to locate HUD menu file ");
- }
- }
- }
- #define MAX_SHOWPOWERS NUM_FORCE_POWERS
- qboolean ForcePower_Valid(int i)
- {
- if (i == FP_LEVITATION ||
- i == FP_SABER_OFFENSE ||
- i == FP_SABER_DEFENSE ||
- i == FP_SABERTHROW)
- {
- return qfalse;
- }
- if (cg.snap->ps.fd.forcePowersKnown & (1 << i))
- {
- return qtrue;
- }
-
- return qfalse;
- }
- /*
- ===================
- CG_DrawForceSelect
- ===================
- */
- void CG_DrawForceSelect( void )
- {
- int i;
- int count;
- int smallIconSize,bigIconSize;
- int holdX,x,y,x2,y2,pad,length;
- int sideLeftIconCnt,sideRightIconCnt;
- int sideMax,holdCount,iconCnt;
- int yOffset = 0;
- x2 = 0;
- y2 = 0;
- // don't display if dead
- if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
- {
- return;
- }
- if ((cg.forceSelectTime+WEAPON_SELECT_TIME)<cg.time) // Time is up for the HUD to display
- {
- cg.forceSelect = cg.snap->ps.fd.forcePowerSelected;
- return;
- }
- if (!cg.snap->ps.fd.forcePowersKnown)
- {
- return;
- }
- // count the number of powers owned
- count = 0;
- for (i=0;i < NUM_FORCE_POWERS;++i)
- {
- if (ForcePower_Valid(i))
- {
- count++;
- }
- }
- if (count == 0) // If no force powers, don't display
- {
- return;
- }
- sideMax = 3; // Max number of icons on the side
- // Calculate how many icons will appear to either side of the center one
- holdCount = count - 1; // -1 for the center icon
- if (holdCount == 0) // No icons to either side
- {
- sideLeftIconCnt = 0;
- sideRightIconCnt = 0;
- }
- else if (count > (2*sideMax)) // Go to the max on each side
- {
- sideLeftIconCnt = sideMax;
- sideRightIconCnt = sideMax;
- }
- else // Less than max, so do the calc
- {
- sideLeftIconCnt = holdCount/2;
- sideRightIconCnt = holdCount - sideLeftIconCnt;
- }
- smallIconSize = 30;
- bigIconSize = 60;
- pad = 12;
- x = 320;
- y = 425;
- // Background
- length = (sideLeftIconCnt * smallIconSize) + (sideLeftIconCnt*pad) +
- bigIconSize + (sideRightIconCnt * smallIconSize) + (sideRightIconCnt*pad) + 12;
-
- i = BG_ProperForceIndex(cg.forceSelect) - 1;
- if (i < 0)
- {
- i = MAX_SHOWPOWERS;
- }
- trap_R_SetColor(NULL);
- // Work backwards from current icon
- holdX = x - ((bigIconSize/2) + pad + smallIconSize)*cgs.widthRatioCoef;
- for (iconCnt=1;iconCnt<(sideLeftIconCnt+1);i--)
- {
- if (i < 0)
- {
- i = MAX_SHOWPOWERS;
- }
- if (!ForcePower_Valid(forcePowerSorted[i])) // Does he have this power?
- {
- continue;
- }
- ++iconCnt; // Good icon
- if (cgs.media.forcePowerIcons[forcePowerSorted[i]])
- {
- CG_DrawPic( holdX, y + yOffset, smallIconSize*cgs.widthRatioCoef, smallIconSize, cgs.media.forcePowerIcons[forcePowerSorted[i]] );
- holdX -= (smallIconSize+pad)*cgs.widthRatioCoef;
- }
- }
- if (ForcePower_Valid(cg.forceSelect))
- {
- // Current Center Icon
- if (cgs.media.forcePowerIcons[cg.forceSelect])
- {
- CG_DrawPic( x-(bigIconSize/2)*cgs.widthRatioCoef, (y-((bigIconSize-smallIconSize)/2)) + yOffset, bigIconSize*cgs.widthRatioCoef, bigIconSize, cgs.media.forcePowerIcons[cg.forceSelect] ); //only cache the icon for display
- }
- }
- i = BG_ProperForceIndex(cg.forceSelect) + 1;
- if (i>MAX_SHOWPOWERS)
- {
- i = 0;
- }
- // Work forwards from current icon
- holdX = x + ((bigIconSize/2) + pad)*cgs.widthRatioCoef;
- for (iconCnt=1;iconCnt<(sideRightIconCnt+1);i++)
- {
- if (i>MAX_SHOWPOWERS)
- {
- i = 0;
- }
- if (!ForcePower_Valid(forcePowerSorted[i])) // Does he have this power?
- {
- continue;
- }
- ++iconCnt; // Good icon
- if (cgs.media.forcePowerIcons[forcePowerSorted[i]])
- {
- CG_DrawPic( holdX, y + yOffset, smallIconSize*cgs.widthRatioCoef, smallIconSize, cgs.media.forcePowerIcons[forcePowerSorted[i]] ); //only cache the icon for display
- holdX += (smallIconSize+pad)*cgs.widthRatioCoef;
- }
- }
- if ( showPowersName[cg.forceSelect] )
- {
- UI_DrawProportionalString(320, y + 30 + yOffset, CG_GetStringEdString("SP_INGAME", showPowersName[cg.forceSelect]), UI_CENTER | UI_SMALLFONT, colorTable[CT_ICON_BLUE]);
- }
- }
- /*
- ===================
- CG_DrawInventorySelect
- ===================
- */
- void CG_DrawInvenSelect( void )
- {
- int i;
- int sideMax,holdCount,iconCnt;
- int smallIconSize,bigIconSize;
- int sideLeftIconCnt,sideRightIconCnt;
- int count;
- int holdX,x,y,y2,pad;
- int height;
- float addX;
- // don't display if dead
- if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
- {
- return;
- }
- if ((cg.invenSelectTime+WEAPON_SELECT_TIME)<cg.time) // Time is up for the HUD to display
- {
- return;
- }
- if (!cg.snap->ps.stats[STAT_HOLDABLE_ITEM] || !cg.snap->ps.stats[STAT_HOLDABLE_ITEMS])
- {
- return;
- }
- if (cg.itemSelect == -1)
- {
- cg.itemSelect = bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag;
- }
- //const int bits = cg.snap->ps.stats[ STAT_ITEMS ];
- // count the number of items owned
- count = 0;
- for ( i = 0 ; i < HI_NUM_HOLDABLE ; i++ )
- {
- if (/*CG_InventorySelectable(i) && inv_icons[i]*/
- (cg.snap->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << i)) )
- {
- count++;
- }
- }
- if (!count)
- {
- y2 = 0; //err?
- UI_DrawProportionalString(320, y2 + 22, "EMPTY INVENTORY", UI_CENTER | UI_SMALLFONT, colorTable[CT_ICON_BLUE]);
- return;
- }
- sideMax = 3; // Max number of icons on the side
- // Calculate how many icons will appear to either side of the center one
- holdCount = count - 1; // -1 for the center icon
- if (holdCount == 0) // No icons to either side
- {
- sideLeftIconCnt = 0;
- sideRightIconCnt = 0;
- }
- else if (count > (2*sideMax)) // Go to the max on each side
- {
- sideLeftIconCnt = sideMax;
- sideRightIconCnt = sideMax;
- }
- else // Less than max, so do the calc
- {
- sideLeftIconCnt = holdCount/2;
- sideRightIconCnt = holdCount - sideLeftIconCnt;
- }
- i = cg.itemSelect - 1;
- if (i<0)
- {
- i = HI_NUM_HOLDABLE-1;
- }
- smallIconSize = 40;
- bigIconSize = 80;
- pad = 16;
- x = 320;
- y = 410;
- // Left side ICONS
- // Work backwards from current icon
- holdX = x - ((bigIconSize/2) + pad + smallIconSize)*cgs.widthRatioCoef;
- height = smallIconSize * cg.iconHUDPercent;
- addX = (float) smallIconSize * .75;
- for (iconCnt=0;iconCnt<sideLeftIconCnt;i--)
- {
- if (i<0)
- {
- i = HI_NUM_HOLDABLE-1;
- }
- if ( !(cg.snap->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << i)) || i == cg.itemSelect )
- {
- continue;
- }
- ++iconCnt; // Good icon
- if (!BG_IsItemSelectable(&cg.predictedPlayerState, i))
- {
- continue;
- }
- if (cgs.media.invenIcons[i])
- {
- trap_R_SetColor(NULL);
- CG_DrawPic( holdX, y+10, smallIconSize*cgs.widthRatioCoef, smallIconSize, cgs.media.invenIcons[i] );
- trap_R_SetColor(colorTable[CT_ICON_BLUE]);
- /*CG_DrawNumField (holdX + addX, y + smallIconSize, 2, cg.snap->ps.inventory[i], 6, 12,
- NUM_FONT_SMALL,qfalse);
- */
- holdX -= (smallIconSize+pad)*cgs.widthRatioCoef;
- }
- }
- // Current Center Icon
- height = bigIconSize * cg.iconHUDPercent;
- if (cgs.media.invenIcons[cg.itemSelect] && BG_IsItemSelectable(&cg.predictedPlayerState, cg.itemSelect))
- {
- int itemNdex;
- trap_R_SetColor(NULL);
- CG_DrawPic( x-(bigIconSize/2)*cgs.widthRatioCoef, (y-((bigIconSize-smallIconSize)/2))+10, bigIconSize*cgs.widthRatioCoef, bigIconSize, cgs.media.invenIcons[cg.itemSelect] );
- addX = (float) bigIconSize * .75;
- trap_R_SetColor(colorTable[CT_ICON_BLUE]);
- /*CG_DrawNumField ((x-(bigIconSize/2)) + addX, y, 2, cg.snap->ps.inventory[cg.inventorySelect], 6, 12,
- NUM_FONT_SMALL,qfalse);*/
- itemNdex = BG_GetItemIndexByTag(cg.itemSelect, IT_HOLDABLE);
- if (bg_itemlist[itemNdex].classname)
- {
- vec4_t textColor = { .312f, .75f, .621f, 1.0f };
- char text[1024];
- char upperKey[1024];
- strcpy(upperKey, bg_itemlist[itemNdex].classname);
-
- if ( trap_SP_GetStringTextString( va("SP_INGAME_%s",Q_strupr(upperKey)), text, sizeof( text )))
- {
- UI_DrawProportionalString(320, y+45, text, UI_CENTER | UI_SMALLFONT, textColor);
- }
- else
- {
- UI_DrawProportionalString(320, y+45, bg_itemlist[itemNdex].classname, UI_CENTER | UI_SMALLFONT, textColor);
- }
- }
- }
- i = cg.itemSelect + 1;
- if (i> HI_NUM_HOLDABLE-1)
- {
- i = 0;
- }
- // Right side ICONS
- // Work forwards from current icon
- holdX = x + ((bigIconSize/2) + pad)*cgs.widthRatioCoef;
- height = smallIconSize * cg.iconHUDPercent;
- addX = (float) smallIconSize * .75;
- for (iconCnt=0;iconCnt<sideRightIconCnt;i++)
- {
- if (i> HI_NUM_HOLDABLE-1)
- {
- i = 0;
- }
- if ( !(cg.snap->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << i)) || i == cg.itemSelect )
- {
- continue;
- }
- ++iconCnt; // Good icon
- if (!BG_IsItemSelectable(&cg.predictedPlayerState, i))
- {
- continue;
- }
- if (cgs.media.invenIcons[i])
- {
- trap_R_SetColor(NULL);
- CG_DrawPic( holdX, y+10, smallIconSize*cgs.widthRatioCoef, smallIconSize, cgs.media.invenIcons[i] );
- trap_R_SetColor(colorTable[CT_ICON_BLUE]);
- /*CG_DrawNumField (holdX + addX, y + smallIconSize, 2, cg.snap->ps.inventory[i], 6, 12,
- NUM_FONT_SMALL,qfalse);*/
- holdX += (smallIconSize+pad)*cgs.widthRatioCoef;
- }
- }
- }
- int cg_targVeh = ENTITYNUM_NONE;
- int cg_targVehLastTime = 0;
- qboolean CG_CheckTargetVehicle( centity_t **pTargetVeh, float *alpha )
- {
- int targetNum = ENTITYNUM_NONE;
- centity_t *targetVeh = NULL;
-
- if ( !pTargetVeh || !alpha )
- {//hey, where are my pointers?
- return qfalse;
- }
- *alpha = 1.0f;
- //FIXME: need to clear all of these when you die?
- if ( cg.predictedPlayerState.rocketLockIndex < ENTITYNUM_WORLD )
- {
- targetNum = cg.predictedPlayerState.rocketLockIndex;
- }
- else if ( cg.crosshairVehNum < ENTITYNUM_WORLD
- && cg.time - cg.crosshairVehTime < 3000 )
- {//crosshair was on a vehicle in the last 3 seconds
- targetNum = cg.crosshairVehNum;
- }
- else if ( cg.crosshairClientNum < ENTITYNUM_WORLD )
- {
- targetNum = cg.crosshairClientNum;
- }
- if ( targetNum < MAX_CLIENTS )
- {//real client
- if ( cg_entities[targetNum].currentState.m_iVehicleNum >= MAX_CLIENTS )
- {//in a vehicle
- targetNum = cg_entities[targetNum].currentState.m_iVehicleNum;
- }
- }
- if ( targetNum < ENTITYNUM_WORLD
- && targetNum >= MAX_CLIENTS )
- {
- //centity_t *targetVeh = &cg_entities[targetNum];
- targetVeh = &cg_entities[targetNum];
- if ( targetVeh->currentState.NPC_class == CLASS_VEHICLE
- && targetVeh->m_pVehicle
- && targetVeh->m_pVehicle->m_pVehicleInfo
- && targetVeh->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER )
- {//it's a vehicle
- cg_targVeh = targetNum;
- cg_targVehLastTime = cg.time;
- *alpha = 1.0f;
- }
- else
- {
- targetVeh = NULL;
- }
- }
- if ( targetVeh )
- {
- *pTargetVeh = targetVeh;
- return qtrue;
- }
- if ( cg_targVehLastTime && cg.time - cg_targVehLastTime < 3000 )
- {
- targetVeh = &cg_entities[cg_targVeh];
- //stay at full alpha for 1 sec after lose them from crosshair
- if ( cg.time-cg_targVehLastTime < 1000 )
- *alpha = 1.0f;
- else //fade out over 2 secs
- *alpha = 1.0f-(((cg.time-cg_targVehLastTime)+cg.timeFraction-1000)/2000.0f);
- }
- return qfalse;
- }
- #define MAX_VHUD_SHIELD_TICS 12
- #define MAX_VHUD_SPEED_TICS 5
- #define MAX_VHUD_ARMOR_TICS 5
- #define MAX_VHUD_AMMO_TICS 5
- float CG_DrawVehicleShields( const menuDef_t *menuHUD, const centity_t *veh )
- {
- int i;
- char itemName[64];
- float inc, currValue,maxShields;
- vec4_t calcColor;
- itemDef_t *item;
- float percShields;
- item = Menu_FindItemByName((menuDef_t *) menuHUD, "armorbackground");
- if (item)
- {
- trap_R_SetColor( item->window.foreColor );
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- }
- maxShields = veh->m_pVehicle->m_pVehicleInfo->shields;
- currValue = cg.predictedVehicleState.stats[STAT_ARMOR];
- percShields = (float)currValue/(float)maxShields;
- // Print all the tics of the shield graphic
- // Look at the amount of health left and show only as much of the graphic as there is health.
- // Use alpha to fade out partial section of health
- inc = (float) maxShields / MAX_VHUD_ARMOR_TICS;
- for (i=1;i<=MAX_VHUD_ARMOR_TICS;i++)
- {
- sprintf( itemName, "armor_tic%d", i );
- item = Menu_FindItemByName((menuDef_t *) menuHUD, itemName);
- if (!item)
- {
- continue;
- }
- memcpy(calcColor, item->window.foreColor, sizeof(vec4_t));
- if (currValue <= 0) // don't show tic
- {
- break;
- }
- else if (currValue < inc) // partial tic (alpha it out)
- {
- float percent = currValue / inc;
- calcColor[3] *= percent; // Fade it out
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- currValue -= inc;
- }
- return percShields;
- }
- int cg_vehicleAmmoWarning = 0;
- int cg_vehicleAmmoWarningTime = 0;
- void CG_DrawVehicleAmmo( const menuDef_t *menuHUD, const centity_t *veh )
- {
- int i;
- char itemName[64];
- float inc, currValue,maxAmmo;
- vec4_t calcColor;
- itemDef_t *item;
- item = Menu_FindItemByName((menuDef_t *) menuHUD, "ammobackground");
- if (item)
- {
- trap_R_SetColor( item->window.foreColor );
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- }
- maxAmmo = veh->m_pVehicle->m_pVehicleInfo->weapon[0].ammoMax;
- currValue = cg.predictedVehicleState.ammo[0];
-
- inc = (float) maxAmmo / MAX_VHUD_AMMO_TICS;
- for (i=1;i<=MAX_VHUD_AMMO_TICS;i++)
- {
- sprintf( itemName, "ammo_tic%d", i );
- item = Menu_FindItemByName((menuDef_t *)menuHUD, itemName);
- if (!item)
- {
- continue;
- }
- if ( cg_vehicleAmmoWarningTime > cg.time
- && cg_vehicleAmmoWarning == 0 )
- {
- memcpy(calcColor, g_color_table[ColorIndex(COLOR_RED)], sizeof(vec4_t));
- calcColor[3] = sin(cg.time*0.005+cg.timeFraction*0.005)*0.5f+0.5f;
- }
- else
- {
- memcpy(calcColor, item->window.foreColor, sizeof(vec4_t));
- if (currValue <= 0) // don't show tic
- {
- break;
- }
- else if (currValue < inc) // partial tic (alpha it out)
- {
- float percent = currValue / inc;
- calcColor[3] *= percent; // Fade it out
- }
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- currValue -= inc;
- }
- }
- void CG_DrawVehicleAmmoUpper( const menuDef_t *menuHUD, const centity_t *veh )
- {
- int i;
- char itemName[64];
- float inc, currValue,maxAmmo;
- vec4_t calcColor;
- itemDef_t *item;
- item = Menu_FindItemByName((menuDef_t *)menuHUD, "ammoupperbackground");
- if (item)
- {
- trap_R_SetColor( item->window.foreColor );
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- }
- maxAmmo = veh->m_pVehicle->m_pVehicleInfo->weapon[0].ammoMax;
- currValue = cg.predictedVehicleState.ammo[0];
- inc = (float) maxAmmo / MAX_VHUD_AMMO_TICS;
- for (i=1;i<MAX_VHUD_AMMO_TICS;i++)
- {
- sprintf( itemName, "ammoupper_tic%d", i );
- // Com_sprintf(itemName, sizeof(itemName), "ammoupper_tic%d", i );
- item = Menu_FindItemByName((menuDef_t *)menuHUD, itemName);
- if (!item)
- {
- continue;
- }
- if ( cg_vehicleAmmoWarningTime > cg.time
- && cg_vehicleAmmoWarning == 0 )
- {
- memcpy(calcColor, g_color_table[ColorIndex(COLOR_RED)], sizeof(vec4_t));
- calcColor[3] = sin(cg.time*0.005+cg.timeFraction*0.005)*0.5f+0.5f;
- }
- else
- {
- memcpy(calcColor, item->window.foreColor, sizeof(vec4_t));
- if (currValue <= 0) // don't show tic
- {
- break;
- }
- else if (currValue < inc) // partial tic (alpha it out)
- {
- float percent = currValue / inc;
- calcColor[3] *= percent; // Fade it out
- }
- }
- trap_R_SetColor( calcColor);
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- item->window.background );
- currValue -= inc;
- }
- }
- void CG_DrawVehicleAmmoLower( const menuDef_t *menuHUD, const centity_t *veh )
- {
- int i;
- char itemName[64];
- float inc, currValue,maxAmmo;
- vec4_t calcColor;
- itemDef_t *item;
- item = Menu_FindItemByName((menuDef_t *)menuHUD, "ammolowerbackground");
- if (item)
- {
- trap_R_SetColor( item->window.foreColor );
- CG_DrawPic(
- item->window.rect.x,
- item->window.rect.y,
- item->window.rect.w,
- item->window.rect.h,
- …
Large files files are truncated, but you can click here to view the full file