2013-04-04 14:52:42 +00:00
// 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 "../ui/ui_shared.h"
qboolean CG_WorldCoordToScreenCoordFloat ( vec3_t worldCoord , float * x , float * y ) ;
qboolean CG_CalcMuzzlePoint ( int entityNum , vec3_t muzzle ) ;
// used for scoreboard
extern displayContextDef_t cgDC ;
menuDef_t * menuScoreboard = NULL ;
vec4_t bluehudtint = { 0.5 , 0.5 , 1.0 , 1.0 } ;
vec4_t redhudtint = { 1.0 , 0.5 , 0.5 , 1.0 } ;
float * hudTintColor ;
int sortedTeamPlayers [ TEAM_MAXOVERLAY ] ;
int numSortedTeamPlayers ;
int lastvalidlockdif ;
extern float zoomFov ; //this has to be global client-side
char systemChat [ 256 ] ;
char teamChat1 [ 256 ] ;
char teamChat2 [ 256 ] ;
char * showPowersName [ ] =
{
" Heal " , //FP_HEAL
" Jump " , //FP_LEVITATION
" Speed " , //FP_SPEED
" Push " , //FP_PUSH
" Pull " , //FP_PULL
" Mind Trick " , //FP_TELEPTAHY
" Grip " , //FP_GRIP
" Lightning " , //FP_LIGHTNING
" Dark Rage " , //FP_RAGE
" Protect " , //FP_PROTECT
" Absorb " , //FP_ABSORB
" Team Heal " , //FP_TEAM_HEAL
" Team Replenish " , //FP_TEAM_FORCE
" Drain " , //FP_DRAIN
" Sight " , //FP_SEE
" Saber Attack " , //FP_SABERATTACK
" Saber Defend " , //FP_SABERDEFEND
" Saber Throw " , //FP_SABERTHROW
NULL
} ;
int MenuFontToHandle ( int iMenuFont )
{
switch ( iMenuFont )
{
case FONT_SMALL : return cgDC . Assets . qhSmallFont ;
case FONT_MEDIUM : return cgDC . Assets . qhMediumFont ;
case FONT_LARGE : return cgDC . Assets . qhBigFont ;
}
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 2 D virtual 640 x480 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 . refdefViewAngles [ YAW ] + 180 ) / 10 ) ) * 10 ;
off = ( cg . refdefViewAngles [ 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.01f ) * 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 , 640 , 480 , 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 . predictedPlayerState . 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 ;
}
// 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 , 640 , 480 , 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.01f ) * 0.3f ;
trap_R_SetColor ( color1 ) ;
}
// Draw rotating insert
CG_DrawRotatePic2 ( 320 , 240 , 640 , 480 , - 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 );
max = cg . snap - > ps . ammo [ weaponData [ WP_DISRUPTOR ] . ammoIndex ] / ( float ) ammoData [ weaponData [ WP_DISRUPTOR ] . ammoIndex ] . max ;
if ( max > 1.0f )
{
max = 1.0f ;
}
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 = 320 + sin ( ( fi + 90.0f ) / 57.296f ) * 190 ;
cy = 240 + cos ( ( fi + 90.0f ) / 57.296f ) * 190 ;
CG_DrawRotatePic2 ( cx , cy , 12 , 24 , 90 - fi , cgs . media . disruptorInsertTick ) ;
}
if ( cg . predictedPlayerState . weaponstate = = WEAPON_CHARGING_ALT )
{
trap_R_SetColor ( colorTable [ CT_WHITE ] ) ;
// draw the charge level
max = ( cg . time - cg . predictedPlayerState . weaponChargeTime ) / ( 50.0f * 30.0f ) ; // bad hardcodedness 50 is disruptor charge unit and 30 is max charge units allowed.
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 , 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 . 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 ) {
clipHandle_t cm ;
clientInfo_t * ci ;
float len ;
vec3_t origin ;
vec3_t mins , maxs ;
ci = & cgs . clientinfo [ clientNum ] ;
if ( cg_draw3dIcons . integer ) {
cm = ci - > headModel ;
if ( ! cm ) {
return ;
}
// offset the origin y and z to center the head
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 head nearly fills the box
// assume heads are taller than wide
len = 0.7 * ( maxs [ 2 ] - mins [ 2 ] ) ;
origin [ 0 ] = len / 0.268 ; // len / tan( fov/2 )
// allow per-model tweaking
VectorAdd ( origin , ci - > headOffset , origin ) ;
CG_Draw3DModel ( x , y , w , h , ci - > headModel , ci - > headSkin , origin , headAngles ) ;
} else if ( cg_drawIcons . integer ) {
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 ) {
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 ( cg . time / 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 = cgs . media . neutralFlagModel ;
} else {
return ;
}
CG_Draw3DModel ( x , y , w , h , handle , 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 ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
DrawAmmo
= = = = = = = = = = = = = = = =
*/
void DrawAmmo ( )
{
int x , y ;
x = SCREEN_WIDTH - 80 ;
y = SCREEN_HEIGHT - 80 ;
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHUDLeftFrame1
= = = = = = = = = = = = = = = =
*/
void CG_DrawHUDLeftFrame1 ( int x , int y )
{
// Inner gray wire frame
trap_R_SetColor ( hudTintColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDInnerLeft ) ;
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHUDLeftFrame2
= = = = = = = = = = = = = = = =
*/
void CG_DrawHUDLeftFrame2 ( int x , int y )
{
// Inner gray wire frame
trap_R_SetColor ( hudTintColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDLeftFrame ) ; // Metal frame
}
/*
= = = = = = = = = = = = = = = =
DrawHealthArmor
= = = = = = = = = = = = = = = =
*/
void DrawHealthArmor ( int x , int y )
{
vec4_t calcColor ;
float armorPercent , hold , healthPercent ;
playerState_t * ps ;
int healthAmt ;
int armorAmt ;
ps = & cg . snap - > ps ;
healthAmt = ps - > stats [ STAT_HEALTH ] ;
armorAmt = ps - > stats [ STAT_ARMOR ] ;
if ( healthAmt > ps - > stats [ STAT_MAX_HEALTH ] )
{
healthAmt = ps - > stats [ STAT_MAX_HEALTH ] ;
}
if ( armorAmt > 100 )
{
armorAmt = 100 ;
}
trap_R_SetColor ( colorTable [ CT_WHITE ] ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDLeftFrame ) ; // Circular black background
// Outer Armor circular
memcpy ( calcColor , colorTable [ CT_GREEN ] , sizeof ( vec4_t ) ) ;
hold = armorAmt - ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
armorPercent = ( float ) hold / ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
if ( armorPercent < 0 )
{
armorPercent = 0 ;
}
calcColor [ 0 ] * = armorPercent ;
calcColor [ 1 ] * = armorPercent ;
calcColor [ 2 ] * = armorPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmor1 ) ;
// Inner Armor circular
if ( armorPercent > 0 )
{
armorPercent = 1 ;
}
else
{
armorPercent = ( float ) armorAmt / ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
}
memcpy ( calcColor , colorTable [ CT_GREEN ] , sizeof ( vec4_t ) ) ;
calcColor [ 0 ] * = armorPercent ;
calcColor [ 1 ] * = armorPercent ;
calcColor [ 2 ] * = armorPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmor2 ) ; // Inner Armor circular
if ( ps - > stats [ STAT_ARMOR ] ) // Is there armor? Draw the HUD Armor TIC
{
// Make tic flash if inner armor is at 50% (25% of full armor)
if ( armorPercent < .5 ) // Do whatever the flash timer says
{
if ( cg . HUDTickFlashTime < cg . time ) // Flip at the same time
{
cg . HUDTickFlashTime = cg . time + 100 ;
if ( cg . HUDArmorFlag )
{
cg . HUDArmorFlag = qfalse ;
}
else
{
cg . HUDArmorFlag = qtrue ;
}
}
}
else
{
cg . HUDArmorFlag = qtrue ;
}
}
else // No armor? Don't show it.
{
cg . HUDArmorFlag = qfalse ;
}
memcpy ( calcColor , colorTable [ CT_RED ] , sizeof ( vec4_t ) ) ;
healthPercent = ( float ) healthAmt / ps - > stats [ STAT_MAX_HEALTH ] ;
calcColor [ 0 ] * = healthPercent ;
calcColor [ 1 ] * = healthPercent ;
calcColor [ 2 ] * = healthPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDHealth ) ;
// Make tic flash if health is at 20% of full
if ( healthPercent > .20 )
{
cg . HUDHealthFlag = qtrue ;
}
else
{
if ( cg . HUDTickFlashTime < cg . time ) // Flip at the same time
{
cg . HUDTickFlashTime = cg . time + 100 ;
if ( ( armorPercent > 0 ) & & ( armorPercent < .5 ) ) // Keep the tics in sync if flashing
{
cg . HUDHealthFlag = cg . HUDArmorFlag ;
}
else
{
if ( cg . HUDHealthFlag )
{
cg . HUDHealthFlag = qfalse ;
}
else
{
cg . HUDHealthFlag = qtrue ;
}
}
}
}
// Draw the ticks
if ( cg . HUDHealthFlag )
{
trap_R_SetColor ( colorTable [ CT_RED ] ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDHealthTic ) ;
}
if ( cg . HUDArmorFlag )
{
trap_R_SetColor ( colorTable [ CT_GREEN ] ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmorTic ) ; //
}
trap_R_SetColor ( hudTintColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDLeftStatic ) ; //
trap_R_SetColor ( colorTable [ CT_RED ] ) ;
CG_DrawNumField ( x + 16 , y + 40 , 3 , ps - > stats [ STAT_HEALTH ] , 14 , 18 ,
NUM_FONT_SMALL , qfalse ) ;
trap_R_SetColor ( colorTable [ CT_GREEN ] ) ;
CG_DrawNumField ( x + 18 + 14 , y + 40 + 14 , 3 , ps - > stats [ STAT_ARMOR ] , 14 , 18 ,
NUM_FONT_SMALL , qfalse ) ;
trap_R_SetColor ( hudTintColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDLeft ) ; // Metal frame
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHealth
= = = = = = = = = = = = = = = =
*/
void CG_DrawHealth ( int x , int y )
{
vec4_t calcColor ;
float healthPercent ;
playerState_t * ps ;
int healthAmt ;
ps = & cg . snap - > ps ;
healthAmt = ps - > stats [ STAT_HEALTH ] ;
if ( healthAmt > ps - > stats [ STAT_MAX_HEALTH ] )
{
healthAmt = ps - > stats [ STAT_MAX_HEALTH ] ;
}
memcpy ( calcColor , colorTable [ CT_HUD_RED ] , sizeof ( vec4_t ) ) ;
healthPercent = ( float ) healthAmt / ps - > stats [ STAT_MAX_HEALTH ] ;
calcColor [ 0 ] * = healthPercent ;
calcColor [ 1 ] * = healthPercent ;
calcColor [ 2 ] * = healthPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDHealth ) ;
// Draw the ticks
if ( cg . HUDHealthFlag )
{
trap_R_SetColor ( colorTable [ CT_HUD_RED ] ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDHealthTic ) ;
}
trap_R_SetColor ( colorTable [ CT_HUD_RED ] ) ;
CG_DrawNumField ( x + 16 , y + 40 , 3 , ps - > stats [ STAT_HEALTH ] , 6 , 12 ,
NUM_FONT_SMALL , qfalse ) ;
}
/*
= = = = = = = = = = = = = = = =
CG_DrawArmor
= = = = = = = = = = = = = = = =
*/
void CG_DrawArmor ( int x , int y )
{
vec4_t calcColor ;
float armorPercent , hold ;
playerState_t * ps ;
int armor ;
ps = & cg . snap - > ps ;
// Outer Armor circular
memcpy ( calcColor , colorTable [ CT_HUD_GREEN ] , sizeof ( vec4_t ) ) ;
armor = ps - > stats [ STAT_ARMOR ] ;
if ( armor > ps - > stats [ STAT_MAX_HEALTH ] )
{
armor = ps - > stats [ STAT_MAX_HEALTH ] ;
}
hold = armor - ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
armorPercent = ( float ) hold / ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
if ( armorPercent < 0 )
{
armorPercent = 0 ;
}
calcColor [ 0 ] * = armorPercent ;
calcColor [ 1 ] * = armorPercent ;
calcColor [ 2 ] * = armorPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmor1 ) ;
// Inner Armor circular
if ( armorPercent > 0 )
{
armorPercent = 1 ;
}
else
{
armorPercent = ( float ) ps - > stats [ STAT_ARMOR ] / ( ps - > stats [ STAT_MAX_HEALTH ] / 2 ) ;
}
memcpy ( calcColor , colorTable [ CT_HUD_GREEN ] , sizeof ( vec4_t ) ) ;
calcColor [ 0 ] * = armorPercent ;
calcColor [ 1 ] * = armorPercent ;
calcColor [ 2 ] * = armorPercent ;
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmor2 ) ; // Inner Armor circular
if ( ps - > stats [ STAT_ARMOR ] ) // Is there armor? Draw the HUD Armor TIC
{
// Make tic flash if inner armor is at 50% (25% of full armor)
if ( armorPercent < .5 ) // Do whatever the flash timer says
{
if ( cg . HUDTickFlashTime < cg . time ) // Flip at the same time
{
cg . HUDTickFlashTime = cg . time + 100 ;
if ( cg . HUDArmorFlag )
{
cg . HUDArmorFlag = qfalse ;
}
else
{
cg . HUDArmorFlag = qtrue ;
}
}
}
else
{
cg . HUDArmorFlag = qtrue ;
}
}
else // No armor? Don't show it.
{
cg . HUDArmorFlag = qfalse ;
}
if ( cg . HUDArmorFlag )
{
trap_R_SetColor ( colorTable [ CT_HUD_GREEN ] ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDArmorTic ) ;
}
trap_R_SetColor ( colorTable [ CT_HUD_GREEN ] ) ;
CG_DrawNumField ( x + 18 + 14 , y + 40 + 14 , 3 , ps - > stats [ STAT_ARMOR ] , 6 , 12 ,
NUM_FONT_SMALL , qfalse ) ;
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHUDRightFrame1
= = = = = = = = = = = = = = = =
*/
void CG_DrawHUDRightFrame1 ( int x , int y )
{
trap_R_SetColor ( hudTintColor ) ;
// Inner gray wire frame
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDInnerRight ) ; //
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHUDRightFrame2
= = = = = = = = = = = = = = = =
*/
void CG_DrawHUDRightFrame2 ( int x , int y )
{
trap_R_SetColor ( hudTintColor ) ;
CG_DrawPic ( x , y , 80 , 80 , cgs . media . HUDRightFrame ) ; // Metal frame
}
/*
= = = = = = = = = = = = = = = =
CG_DrawAmmo
= = = = = = = = = = = = = = = =
*/
static void CG_DrawAmmo ( centity_t * cent , int x , int y )
{
playerState_t * ps ;
int numColor_i ;
int i ;
vec4_t calcColor ;
float value , inc , percent ;
ps = & cg . snap - > ps ;
if ( ! cent - > currentState . weapon ) // We don't have a weapon right now
{
return ;
}
if ( cent - > currentState . weapon = = WP_SABER )
{
// value = cent->gent->client->ps.forcePower;
return ;
}
else
{
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 ;
*/
// Firing or reloading?
/* if (( pm->ps->weaponstate == WEAPON_FIRING
& & cg . predictedPlayerState . weaponTime > 100 ) )
{
numColor_i = CT_LTGREY ;
} */
// Overcharged?
// else if ( cent->gent->s.powerups & ( 1 << PW_WEAPON_OVERCHARGE ) )
// {
// numColor_i = CT_WHITE;
// }
// else
// {
// if ( value > 0 )
// {
// if (cg.oldAmmoTime > cg.time)
// {
// numColor_i = CT_YELLOW;
// }
// else
// {
// numColor_i = CT_HUD_ORANGE;
// }
// }
// else
// {
// numColor_i = CT_RED;
// }
// }
numColor_i = CT_HUD_ORANGE ;
trap_R_SetColor ( colorTable [ numColor_i ] ) ;
CG_DrawNumField ( x + 30 , y + 26 , 3 , value , 6 , 12 , NUM_FONT_SMALL , qfalse ) ;
//cg.snap->ps.ammo[weaponData[cg.snap->ps.weapon].ammoIndex]
inc = ( float ) ammoData [ weaponData [ cent - > currentState . weapon ] . ammoIndex ] . max / MAX_TICS ;
value = ps - > ammo [ weaponData [ cent - > currentState . weapon ] . ammoIndex ] ;
for ( i = MAX_TICS - 1 ; i > = 0 ; i - - )
{
if ( value < = 0 ) // partial tic
{
memcpy ( calcColor , colorTable [ CT_BLACK ] , sizeof ( vec4_t ) ) ;
}
else if ( value < inc ) // partial tic
{
memcpy ( calcColor , colorTable [ CT_WHITE ] , sizeof ( vec4_t ) ) ;
percent = value / inc ;
calcColor [ 0 ] * = percent ;
calcColor [ 1 ] * = percent ;
calcColor [ 2 ] * = percent ;
}
else
{
memcpy ( calcColor , colorTable [ CT_WHITE ] , sizeof ( vec4_t ) ) ;
}
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x + ammoTicPos [ i ] . x ,
y + ammoTicPos [ i ] . y ,
ammoTicPos [ i ] . width ,
ammoTicPos [ i ] . height ,
ammoTicPos [ i ] . tic ) ;
value - = inc ;
}
}
/*
= = = = = = = = = = = = = = = =
CG_DrawForcePower
= = = = = = = = = = = = = = = =
*/
void CG_DrawForcePower ( int x , int y )
{
int i ;
vec4_t calcColor ;
float value , inc , percent ;
inc = ( float ) 100 / MAX_TICS ;
value = cg . snap - > ps . fd . forcePower ;
for ( i = MAX_TICS - 1 ; i > = 0 ; i - - )
{
if ( value < = 0 ) // partial tic
{
memcpy ( calcColor , colorTable [ CT_BLACK ] , sizeof ( vec4_t ) ) ;
}
else if ( value < inc ) // partial tic
{
memcpy ( calcColor , colorTable [ CT_WHITE ] , sizeof ( vec4_t ) ) ;
percent = value / inc ;
calcColor [ 0 ] * = percent ;
calcColor [ 1 ] * = percent ;
calcColor [ 2 ] * = percent ;
}
else
{
memcpy ( calcColor , colorTable [ CT_WHITE ] , sizeof ( vec4_t ) ) ;
}
trap_R_SetColor ( calcColor ) ;
CG_DrawPic ( x + forceTicPos [ i ] . x ,
y + forceTicPos [ i ] . y ,
forceTicPos [ i ] . width ,
forceTicPos [ i ] . height ,
forceTicPos [ i ] . tic ) ;
value - = inc ;
}
}
/*
= = = = = = = = = = = = = = = =
CG_DrawHUD
= = = = = = = = = = = = = = = =
*/
void CG_DrawHUD ( centity_t * cent )
{
menuDef_t * menuHUD = NULL ;
if ( cgs . gametype > = GT_TEAM )
{ // tint the hud items based on team
if ( cg . snap - > ps . persistant [ PERS_TEAM ] = = TEAM_RED )
hudTintColor = redhudtint ;
else if ( cg . snap - > ps . persistant [ PERS_TEAM ] = = TEAM_BLUE )
hudTintColor = bluehudtint ;
else // If we're not on a team for whatever reason, leave things as they are.
hudTintColor = colorTable [ CT_WHITE ] ;
}
else
{ // tint the hud items white (dont' tint)
hudTintColor = colorTable [ CT_WHITE ] ;
}
menuHUD = Menus_FindByName ( " lefthud " ) ;
if ( menuHUD )
{
CG_DrawHUDLeftFrame1 ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawArmor ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawHealth ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawHUDLeftFrame2 ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
}
else
{ //Apparently we failed to get proper coordinates from the menu, so resort to manually inputting them.
CG_DrawHUDLeftFrame1 ( 0 , SCREEN_HEIGHT - 80 ) ;
CG_DrawArmor ( 0 , SCREEN_HEIGHT - 80 ) ;
CG_DrawHealth ( 0 , SCREEN_HEIGHT - 80 ) ;
CG_DrawHUDLeftFrame2 ( 0 , SCREEN_HEIGHT - 80 ) ;
}
menuHUD = Menus_FindByName ( " righthud " ) ;
if ( menuHUD )
{
CG_DrawHUDRightFrame1 ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawForcePower ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawAmmo ( cent , menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
CG_DrawHUDRightFrame2 ( menuHUD - > window . rect . x , menuHUD - > window . rect . y ) ;
}
else
{ //Apparently we failed to get proper coordinates from the menu, so resort to manually inputting them.
CG_DrawHUDRightFrame1 ( SCREEN_WIDTH - 80 , SCREEN_HEIGHT - 80 ) ;
CG_DrawForcePower ( SCREEN_WIDTH - 80 , SCREEN_HEIGHT - 80 ) ;
CG_DrawAmmo ( cent , SCREEN_WIDTH - 80 , SCREEN_HEIGHT - 80 ) ;
CG_DrawHUDRightFrame2 ( SCREEN_WIDTH - 80 , SCREEN_HEIGHT - 80 ) ;
}
}
# define MAX_SHOWPOWERS NUM_FORCE_POWERS
qboolean ForcePower_Valid ( int i )
{
if ( i = = FP_LEVITATION | |
i = = FP_SABERATTACK | |
i = = FP_SABERDEFEND | |
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 ;
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 ) ;
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 , smallIconSize , smallIconSize , cgs . media . forcePowerIcons [ forcePowerSorted [ i ] ] ) ;
holdX - = ( smallIconSize + pad ) ;
}
}
if ( ForcePower_Valid ( cg . forceSelect ) )
{
// Current Center Icon
if ( cgs . media . forcePowerIcons [ cg . forceSelect ] )
{
CG_DrawPic ( x - ( bigIconSize / 2 ) , ( y - ( ( bigIconSize - smallIconSize ) / 2 ) ) , bigIconSize , 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 ;
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 , smallIconSize , smallIconSize , cgs . media . forcePowerIcons [ forcePowerSorted [ i ] ] ) ; //only cache the icon for display
holdX + = ( smallIconSize + pad ) ;
}
}
if ( showPowersName [ cg . forceSelect ] )
{
UI_DrawProportionalString ( 320 , y + 33 , 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 ) ;
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 ( cgs . media . invenIcons [ i ] )
{
trap_R_SetColor ( NULL ) ;
CG_DrawPic ( holdX , y + 10 , smallIconSize , 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 ) ;
}
}
// Current Center Icon
height = bigIconSize * cg . iconHUDPercent ;
if ( cgs . media . invenIcons [ cg . itemSelect ] )
{
trap_R_SetColor ( NULL ) ;
CG_DrawPic ( x - ( bigIconSize / 2 ) , ( y - ( ( bigIconSize - smallIconSize ) / 2 ) ) + 10 , bigIconSize , 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 ) ; */
if ( bg_itemlist [ BG_GetItemIndexByTag ( cg . itemSelect , IT_HOLDABLE ) ] . pickup_name )
{
2013-04-04 18:01:17 +00:00
vec4_t textColor = { .312f , .75f , .621f , 1.0f } ;
2013-04-04 14:52:42 +00:00
2013-04-04 18:01:17 +00:00
UI_DrawProportionalString ( 320 , y + 48 , bg_itemlist [ BG_GetItemIndexByTag ( cg . itemSelect , IT_HOLDABLE ) ] . pickup_name , UI_CENTER | UI_SMALLFONT , textColor ) ;
2013-04-04 14:52:42 +00:00
}
}
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 ;
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 ( cgs . media . invenIcons [ i ] )
{
trap_R_SetColor ( NULL ) ;
CG_DrawPic ( holdX , y + 10 , smallIconSize , 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 ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
CG_DrawStats
= = = = = = = = = = = = = = = =
*/
static void CG_DrawStats ( void )
{
centity_t * cent ;
/* playerState_t *ps;
vec3_t angles ;
// vec3_t origin;
if ( cg_drawStatus . integer = = 0 ) {
return ;
}
*/
cent = & cg_entities [ cg . snap - > ps . clientNum ] ;
/* ps = &cg.snap->ps;
VectorClear ( angles ) ;
// Do start
if ( ! cg . interfaceStartupDone )
{
CG_InterfaceStartup ( ) ;
}
cgi_UI_MenuPaintAll ( ) ; */
CG_DrawHUD ( cent ) ;
/*CG_DrawArmor(cent);
CG_DrawHealth ( cent ) ;
CG_DrawAmmo ( cent ) ;
CG_DrawTalk ( cent ) ; */
}
/*
= = = = = = = = = = = = = = = =
CG_DrawTeamBackground
= = = = = = = = = = = = = = = =
*/
void CG_DrawTeamBackground ( int x , int y , int w , int h , float alpha , int team )
{
vec4_t hcolor ;
hcolor [ 3 ] = alpha ;
if ( team = = TEAM_RED ) {
hcolor [ 0 ] = 1 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0 ;
} else if ( team = = TEAM_BLUE ) {
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 1 ;
} else {
return ;
}
trap_R_SetColor ( hcolor ) ;
CG_DrawPic ( x , y , w , h , cgs . media . teamStatusBar ) ;
trap_R_SetColor ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
UPPER RIGHT CORNER
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = =
CG_DrawAttacker
= = = = = = = = = = = = = = = =
*/
static float CG_DrawAttacker ( float y ) {
int t ;
float size ;
vec3_t angles ;
const char * info ;
const char * name ;
int clientNum ;
if ( cg . predictedPlayerState . stats [ STAT_HEALTH ] < = 0 ) {
return y ;
}
if ( ! cg . attackerTime ) {
return y ;
}
clientNum = cg . predictedPlayerState . persistant [ PERS_ATTACKER ] ;
if ( clientNum < 0 | | clientNum > = MAX_CLIENTS | | clientNum = = cg . snap - > ps . clientNum ) {
return y ;
}
t = cg . time - cg . attackerTime ;
if ( t > ATTACKER_HEAD_TIME ) {
cg . attackerTime = 0 ;
return y ;
}
size = ICON_SIZE * 1.25 ;
angles [ PITCH ] = 0 ;
angles [ YAW ] = 180 ;
angles [ ROLL ] = 0 ;
CG_DrawHead ( 640 - size , y , size , size , clientNum , angles ) ;
info = CG_ConfigString ( CS_PLAYERS + clientNum ) ;
name = Info_ValueForKey ( info , " n " ) ;
y + = size ;
CG_DrawBigString ( 640 - ( Q_PrintStrlen ( name ) * BIGCHAR_WIDTH ) , y , name , 0.5 ) ;
return y + BIGCHAR_HEIGHT + 2 ;
}
/*
= = = = = = = = = = = = = = = = = =
CG_DrawSnapshot
= = = = = = = = = = = = = = = = = =
*/
static float CG_DrawSnapshot ( float y ) {
char * s ;
int w ;
s = va ( " time:%i snap:%i cmd:%i " , cg . snap - > serverTime ,
cg . latestSnapshotNum , cgs . serverCommandSequence ) ;
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 635 - w , y + 2 , s , 1.0F ) ;
return y + BIGCHAR_HEIGHT + 4 ;
}
/*
= = = = = = = = = = = = = = = = = =
CG_DrawFPS
= = = = = = = = = = = = = = = = = =
*/
# define FPS_FRAMES 4
static float CG_DrawFPS ( float y ) {
char * s ;
int w ;
static int previousTimes [ FPS_FRAMES ] ;
static int index ;
int i , total ;
int fps ;
static int previous ;
int t , frameTime ;
// don't use serverTime, because that will be drifting to
// correct for internet lag changes, timescales, timedemos, etc
t = trap_Milliseconds ( ) ;
frameTime = t - previous ;
previous = t ;
previousTimes [ index % FPS_FRAMES ] = frameTime ;
index + + ;
if ( index > FPS_FRAMES ) {
// average multiple frames together to smooth changes out a bit
total = 0 ;
for ( i = 0 ; i < FPS_FRAMES ; i + + ) {
total + = previousTimes [ i ] ;
}
if ( ! total ) {
total = 1 ;
}
fps = 1000 * FPS_FRAMES / total ;
s = va ( " %ifps " , fps ) ;
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 635 - w , y + 2 , s , 1.0F ) ;
}
return y + BIGCHAR_HEIGHT + 4 ;
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawTimer
= = = = = = = = = = = = = = = = =
*/
static float CG_DrawTimer ( float y ) {
char * s ;
int w ;
int mins , seconds , tens ;
int msec ;
msec = cg . time - cgs . levelStartTime ;
seconds = msec / 1000 ;
mins = seconds / 60 ;
seconds - = mins * 60 ;
tens = seconds / 10 ;
seconds - = tens * 10 ;
s = va ( " %i:%i%i " , mins , tens , seconds ) ;
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 635 - w , y + 2 , s , 1.0F ) ;
return y + BIGCHAR_HEIGHT + 4 ;
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawTeamOverlay
= = = = = = = = = = = = = = = = =
*/
static float CG_DrawTeamOverlay ( float y , qboolean right , qboolean upper ) {
int x , w , h , xx ;
int i , j , len ;
const char * p ;
vec4_t hcolor ;
int pwidth , lwidth ;
int plyrs ;
char st [ 16 ] ;
clientInfo_t * ci ;
gitem_t * item ;
int ret_y , count ;
if ( ! cg_drawTeamOverlay . integer ) {
return y ;
}
if ( cg . snap - > ps . persistant [ PERS_TEAM ] ! = TEAM_RED & & cg . snap - > ps . persistant [ PERS_TEAM ] ! = TEAM_BLUE ) {
return y ; // Not on any team
}
plyrs = 0 ;
// max player name width
pwidth = 0 ;
count = ( numSortedTeamPlayers > 8 ) ? 8 : numSortedTeamPlayers ;
for ( i = 0 ; i < count ; i + + ) {
ci = cgs . clientinfo + sortedTeamPlayers [ i ] ;
if ( ci - > infoValid & & ci - > team = = cg . snap - > ps . persistant [ PERS_TEAM ] ) {
plyrs + + ;
len = CG_DrawStrlen ( ci - > name ) ;
if ( len > pwidth )
pwidth = len ;
}
}
if ( ! plyrs )
return y ;
if ( pwidth > TEAM_OVERLAY_MAXNAME_WIDTH )
pwidth = TEAM_OVERLAY_MAXNAME_WIDTH ;
// max location name width
lwidth = 0 ;
for ( i = 1 ; i < MAX_LOCATIONS ; i + + ) {
p = CG_ConfigString ( CS_LOCATIONS + i ) ;
if ( p & & * p ) {
len = CG_DrawStrlen ( p ) ;
if ( len > lwidth )
lwidth = len ;
}
}
if ( lwidth > TEAM_OVERLAY_MAXLOCATION_WIDTH )
lwidth = TEAM_OVERLAY_MAXLOCATION_WIDTH ;
w = ( pwidth + lwidth + 4 + 7 ) * TINYCHAR_WIDTH ;
if ( right )
x = 640 - w ;
else
x = 0 ;
h = plyrs * TINYCHAR_HEIGHT ;
if ( upper ) {
ret_y = y + h ;
} else {
y - = h ;
ret_y = y ;
}
if ( cg . snap - > ps . persistant [ PERS_TEAM ] = = TEAM_RED ) {
hcolor [ 0 ] = 1.0f ;
hcolor [ 1 ] = 0.0f ;
hcolor [ 2 ] = 0.0f ;
hcolor [ 3 ] = 0.33f ;
} else { // if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE )
hcolor [ 0 ] = 0.0f ;
hcolor [ 1 ] = 0.0f ;
hcolor [ 2 ] = 1.0f ;
hcolor [ 3 ] = 0.33f ;
}
trap_R_SetColor ( hcolor ) ;
CG_DrawPic ( x , y , w , h , cgs . media . teamStatusBar ) ;
trap_R_SetColor ( NULL ) ;
for ( i = 0 ; i < count ; i + + ) {
ci = cgs . clientinfo + sortedTeamPlayers [ i ] ;
if ( ci - > infoValid & & ci - > team = = cg . snap - > ps . persistant [ PERS_TEAM ] ) {
hcolor [ 0 ] = hcolor [ 1 ] = hcolor [ 2 ] = hcolor [ 3 ] = 1.0 ;
xx = x + TINYCHAR_WIDTH ;
CG_DrawStringExt ( xx , y ,
ci - > name , hcolor , qfalse , qfalse ,
TINYCHAR_WIDTH , TINYCHAR_HEIGHT , TEAM_OVERLAY_MAXNAME_WIDTH ) ;
if ( lwidth ) {
p = CG_ConfigString ( CS_LOCATIONS + ci - > location ) ;
if ( ! p | | ! * p )
p = " unknown " ;
len = CG_DrawStrlen ( p ) ;
if ( len > lwidth )
len = lwidth ;
// xx = x + TINYCHAR_WIDTH * 2 + TINYCHAR_WIDTH * pwidth +
// ((lwidth/2 - len/2) * TINYCHAR_WIDTH);
xx = x + TINYCHAR_WIDTH * 2 + TINYCHAR_WIDTH * pwidth ;
CG_DrawStringExt ( xx , y ,
p , hcolor , qfalse , qfalse , TINYCHAR_WIDTH , TINYCHAR_HEIGHT ,
TEAM_OVERLAY_MAXLOCATION_WIDTH ) ;
}
CG_GetColorForHealth ( ci - > health , ci - > armor , hcolor ) ;
Com_sprintf ( st , sizeof ( st ) , " %3i %3i " , ci - > health , ci - > armor ) ;
xx = x + TINYCHAR_WIDTH * 3 +
TINYCHAR_WIDTH * pwidth + TINYCHAR_WIDTH * lwidth ;
CG_DrawStringExt ( xx , y ,
st , hcolor , qfalse , qfalse ,
TINYCHAR_WIDTH , TINYCHAR_HEIGHT , 0 ) ;
// draw weapon icon
xx + = TINYCHAR_WIDTH * 3 ;
if ( cg_weapons [ ci - > curWeapon ] . weaponIcon ) {
CG_DrawPic ( xx , y , TINYCHAR_WIDTH , TINYCHAR_HEIGHT ,
cg_weapons [ ci - > curWeapon ] . weaponIcon ) ;
} else {
CG_DrawPic ( xx , y , TINYCHAR_WIDTH , TINYCHAR_HEIGHT ,
cgs . media . deferShader ) ;
}
// Draw powerup icons
if ( right ) {
xx = x ;
} else {
xx = x + w - TINYCHAR_WIDTH ;
}
for ( j = 0 ; j < = PW_NUM_POWERUPS ; j + + ) {
if ( ci - > powerups & ( 1 < < j ) ) {
item = BG_FindItemForPowerup ( j ) ;
if ( item ) {
CG_DrawPic ( xx , y , TINYCHAR_WIDTH , TINYCHAR_HEIGHT ,
trap_R_RegisterShader ( item - > icon ) ) ;
if ( right ) {
xx - = TINYCHAR_WIDTH ;
} else {
xx + = TINYCHAR_WIDTH ;
}
}
}
}
y + = TINYCHAR_HEIGHT ;
}
}
return ret_y ;
//#endif
}
/*
= = = = = = = = = = = = = = = = = = = = =
CG_DrawUpperRight
= = = = = = = = = = = = = = = = = = = = =
*/
static void CG_DrawUpperRight ( void ) {
float y ;
y = 0 ;
if ( cgs . gametype > = GT_TEAM & & cg_drawTeamOverlay . integer = = 1 ) {
y = CG_DrawTeamOverlay ( y , qtrue , qtrue ) ;
}
if ( cg_drawSnapshot . integer ) {
y = CG_DrawSnapshot ( y ) ;
}
if ( cg_drawFPS . integer ) {
y = CG_DrawFPS ( y ) ;
}
if ( cg_drawTimer . integer ) {
y = CG_DrawTimer ( y ) ;
}
if ( cg_drawAttacker . integer ) {
y = CG_DrawAttacker ( y ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
CG_DrawReward
= = = = = = = = = = = = = = = = = = =
*/
static void CG_DrawReward ( void ) {
float * color ;
int i , count ;
float x , y ;
char buf [ 32 ] ;
if ( ! cg_drawRewards . integer ) {
return ;
}
color = CG_FadeColor ( cg . rewardTime , REWARD_TIME ) ;
if ( ! color ) {
if ( cg . rewardStack > 0 ) {
for ( i = 0 ; i < cg . rewardStack ; i + + ) {
cg . rewardSound [ i ] = cg . rewardSound [ i + 1 ] ;
cg . rewardShader [ i ] = cg . rewardShader [ i + 1 ] ;
cg . rewardCount [ i ] = cg . rewardCount [ i + 1 ] ;
}
cg . rewardTime = cg . time ;
cg . rewardStack - - ;
color = CG_FadeColor ( cg . rewardTime , REWARD_TIME ) ;
trap_S_StartLocalSound ( cg . rewardSound [ 0 ] , CHAN_ANNOUNCER ) ;
} else {
return ;
}
}
trap_R_SetColor ( color ) ;
/*
count = cg . rewardCount [ 0 ] / 10 ; // number of big rewards to draw
if ( count ) {
y = 4 ;
x = 320 - count * ICON_SIZE ;
for ( i = 0 ; i < count ; i + + ) {
CG_DrawPic ( x , y , ( ICON_SIZE * 2 ) - 4 , ( ICON_SIZE * 2 ) - 4 , cg . rewardShader [ 0 ] ) ;
x + = ( ICON_SIZE * 2 ) ;
}
}
count = cg . rewardCount [ 0 ] - count * 10 ; // number of small rewards to draw
*/
if ( cg . rewardCount [ 0 ] > = 10 ) {
y = 56 ;
x = 320 - ICON_SIZE / 2 ;
CG_DrawPic ( x , y , ICON_SIZE - 4 , ICON_SIZE - 4 , cg . rewardShader [ 0 ] ) ;
Com_sprintf ( buf , sizeof ( buf ) , " %d " , cg . rewardCount [ 0 ] ) ;
x = ( SCREEN_WIDTH - SMALLCHAR_WIDTH * CG_DrawStrlen ( buf ) ) / 2 ;
CG_DrawStringExt ( x , y + ICON_SIZE , buf , color , qfalse , qtrue ,
SMALLCHAR_WIDTH , SMALLCHAR_HEIGHT , 0 ) ;
}
else {
count = cg . rewardCount [ 0 ] ;
y = 56 ;
x = 320 - count * ICON_SIZE / 2 ;
for ( i = 0 ; i < count ; i + + ) {
CG_DrawPic ( x , y , ICON_SIZE - 4 , ICON_SIZE - 4 , cg . rewardShader [ 0 ] ) ;
x + = ICON_SIZE ;
}
}
trap_R_SetColor ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
LAGOMETER
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define LAG_SAMPLES 128
typedef struct {
int frameSamples [ LAG_SAMPLES ] ;
int frameCount ;
int snapshotFlags [ LAG_SAMPLES ] ;
int snapshotSamples [ LAG_SAMPLES ] ;
int snapshotCount ;
} lagometer_t ;
lagometer_t lagometer ;
/*
= = = = = = = = = = = = = =
CG_AddLagometerFrameInfo
Adds the current interpolate / extrapolate bar for this frame
= = = = = = = = = = = = = =
*/
void CG_AddLagometerFrameInfo ( void ) {
int offset ;
offset = cg . time - cg . latestSnapshotTime ;
lagometer . frameSamples [ lagometer . frameCount & ( LAG_SAMPLES - 1 ) ] = offset ;
lagometer . frameCount + + ;
}
/*
= = = = = = = = = = = = = =
CG_AddLagometerSnapshotInfo
Each time a snapshot is received , log its ping time and
the number of snapshots that were dropped before it .
Pass NULL for a dropped packet .
= = = = = = = = = = = = = =
*/
void CG_AddLagometerSnapshotInfo ( snapshot_t * snap ) {
// dropped packet
if ( ! snap ) {
lagometer . snapshotSamples [ lagometer . snapshotCount & ( LAG_SAMPLES - 1 ) ] = - 1 ;
lagometer . snapshotCount + + ;
return ;
}
// add this snapshot's info
lagometer . snapshotSamples [ lagometer . snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap - > ping ;
lagometer . snapshotFlags [ lagometer . snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap - > snapFlags ;
lagometer . snapshotCount + + ;
}
/*
= = = = = = = = = = = = = =
CG_DrawDisconnect
Should we draw something differnet for long lag vs no packets ?
= = = = = = = = = = = = = =
*/
static void CG_DrawDisconnect ( void ) {
float x , y ;
int cmdNum ;
usercmd_t cmd ;
const char * s ;
int w ; // bk010215 - FIXME char message[1024];
// draw the phone jack if we are completely past our buffers
cmdNum = trap_GetCurrentCmdNumber ( ) - CMD_BACKUP + 1 ;
trap_GetUserCmd ( cmdNum , & cmd ) ;
if ( cmd . serverTime < = cg . snap - > ps . commandTime
| | cmd . serverTime > cg . time ) { // special check for map_restart // bk 0102165 - FIXME
return ;
}
// also add text in center of screen
s = " Connection Interrupted " ; // bk 010215 - FIXME
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 320 - w / 2 , 100 , s , 1.0F ) ;
// blink the icon
if ( ( cg . time > > 9 ) & 1 ) {
return ;
}
x = 640 - 48 ;
y = 480 - 48 ;
CG_DrawPic ( x , y , 48 , 48 , trap_R_RegisterShader ( " gfx/2d/net.tga " ) ) ;
}
# define MAX_LAGOMETER_PING 900
# define MAX_LAGOMETER_RANGE 300
/*
= = = = = = = = = = = = = =
CG_DrawLagometer
= = = = = = = = = = = = = =
*/
static void CG_DrawLagometer ( void ) {
int a , x , y , i ;
float v ;
float ax , ay , aw , ah , mid , range ;
int color ;
float vscale ;
if ( ! cg_lagometer . integer | | cgs . localServer ) {
CG_DrawDisconnect ( ) ;
return ;
}
//
// draw the graph
//
x = 640 - 48 ;
y = 480 - 144 ;
trap_R_SetColor ( NULL ) ;
CG_DrawPic ( x , y , 48 , 48 , cgs . media . lagometerShader ) ;
ax = x ;
ay = y ;
aw = 48 ;
ah = 48 ;
color = - 1 ;
range = ah / 3 ;
mid = ay + range ;
vscale = range / MAX_LAGOMETER_RANGE ;
// draw the frame interpoalte / extrapolate graph
for ( a = 0 ; a < aw ; a + + ) {
i = ( lagometer . frameCount - 1 - a ) & ( LAG_SAMPLES - 1 ) ;
v = lagometer . frameSamples [ i ] ;
v * = vscale ;
if ( v > 0 ) {
if ( color ! = 1 ) {
color = 1 ;
trap_R_SetColor ( g_color_table [ ColorIndex ( COLOR_YELLOW ) ] ) ;
}
if ( v > range ) {
v = range ;
}
trap_R_DrawStretchPic ( ax + aw - a , mid - v , 1 , v , 0 , 0 , 0 , 0 , cgs . media . whiteShader ) ;
} else if ( v < 0 ) {
if ( color ! = 2 ) {
color = 2 ;
trap_R_SetColor ( g_color_table [ ColorIndex ( COLOR_BLUE ) ] ) ;
}
v = - v ;
if ( v > range ) {
v = range ;
}
trap_R_DrawStretchPic ( ax + aw - a , mid , 1 , v , 0 , 0 , 0 , 0 , cgs . media . whiteShader ) ;
}
}
// draw the snapshot latency / drop graph
range = ah / 2 ;
vscale = range / MAX_LAGOMETER_PING ;
for ( a = 0 ; a < aw ; a + + ) {
i = ( lagometer . snapshotCount - 1 - a ) & ( LAG_SAMPLES - 1 ) ;
v = lagometer . snapshotSamples [ i ] ;
if ( v > 0 ) {
if ( lagometer . snapshotFlags [ i ] & SNAPFLAG_RATE_DELAYED ) {
if ( color ! = 5 ) {
color = 5 ; // YELLOW for rate delay
trap_R_SetColor ( g_color_table [ ColorIndex ( COLOR_YELLOW ) ] ) ;
}
} else {
if ( color ! = 3 ) {
color = 3 ;
trap_R_SetColor ( g_color_table [ ColorIndex ( COLOR_GREEN ) ] ) ;
}
}
v = v * vscale ;
if ( v > range ) {
v = range ;
}
trap_R_DrawStretchPic ( ax + aw - a , ay + ah - v , 1 , v , 0 , 0 , 0 , 0 , cgs . media . whiteShader ) ;
} else if ( v < 0 ) {
if ( color ! = 4 ) {
color = 4 ; // RED for dropped snapshots
trap_R_SetColor ( g_color_table [ ColorIndex ( COLOR_RED ) ] ) ;
}
trap_R_DrawStretchPic ( ax + aw - a , ay + ah - range , 1 , range , 0 , 0 , 0 , 0 , cgs . media . whiteShader ) ;
}
}
trap_R_SetColor ( NULL ) ;
if ( cg_nopredict . integer | | cg_synchronousClients . integer ) {
CG_DrawBigString ( ax , ay , " snc " , 1.0 ) ;
}
CG_DrawDisconnect ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CENTER PRINTING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = =
CG_CenterPrint
Called for important messages that should stay in the center of the screen
for a few moments
= = = = = = = = = = = = = =
*/
void CG_CenterPrint ( const char * str , int y , int charWidth ) {
char * s ;
Q_strncpyz ( cg . centerPrint , str , sizeof ( cg . centerPrint ) ) ;
cg . centerPrintTime = cg . time ;
cg . centerPrintY = y ;
cg . centerPrintCharWidth = charWidth ;
// count the number of lines for centering
cg . centerPrintLines = 1 ;
s = cg . centerPrint ;
while ( * s ) {
if ( * s = = ' \n ' )
cg . centerPrintLines + + ;
s + + ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
CG_DrawCenterString
= = = = = = = = = = = = = = = = = = =
*/
static void CG_DrawCenterString ( void ) {
char * start ;
int l ;
int x , y , w ;
int h ;
float * color ;
const float scale = 1.0 ; //0.5
if ( ! cg . centerPrintTime ) {
return ;
}
color = CG_FadeColor ( cg . centerPrintTime , 1000 * cg_centertime . value ) ;
if ( ! color ) {
return ;
}
trap_R_SetColor ( color ) ;
start = cg . centerPrint ;
y = cg . centerPrintY - cg . centerPrintLines * BIGCHAR_HEIGHT / 2 ;
while ( 1 ) {
char linebuffer [ 1024 ] ;
for ( l = 0 ; l < 50 ; l + + ) {
if ( ! start [ l ] | | start [ l ] = = ' \n ' ) {
break ;
}
linebuffer [ l ] = start [ l ] ;
}
linebuffer [ l ] = 0 ;
w = CG_Text_Width ( linebuffer , scale , FONT_MEDIUM ) ;
h = CG_Text_Height ( linebuffer , scale , FONT_MEDIUM ) ;
x = ( SCREEN_WIDTH - w ) / 2 ;
CG_Text_Paint ( x , y + h , scale , color , linebuffer , 0 , 0 , ITEM_TEXTSTYLE_SHADOWEDMORE , FONT_MEDIUM ) ;
y + = h + 6 ;
while ( * start & & ( * start ! = ' \n ' ) ) {
start + + ;
}
if ( ! * start ) {
break ;
}
start + + ;
}
trap_R_SetColor ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
CROSSHAIR
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = =
CG_DrawCrosshair
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawCrosshair ( vec3_t worldPoint , int chEntValid ) {
float w , h ;
qhandle_t hShader ;
float f ;
float x , y ;
if ( ! cg_drawCrosshair . integer )
{
return ;
}
if ( cg . predictedPlayerState . zoomMode ! = 0 )
{ //not while scoped
return ;
}
if ( cg_crosshairHealth . integer )
{
vec4_t hcolor ;
CG_ColorForHealth ( hcolor ) ;
trap_R_SetColor ( hcolor ) ;
}
else
{
//set color based on what kind of ent is under crosshair
if ( cg . crosshairClientNum > = ENTITYNUM_WORLD )
{
trap_R_SetColor ( NULL ) ;
}
else if ( chEntValid & & ( cg_entities [ cg . crosshairClientNum ] . currentState . number < MAX_CLIENTS | | cg_entities [ cg . crosshairClientNum ] . currentState . shouldtarget ) )
{
vec4_t ecolor = { 0 , 0 , 0 , 0 } ;
centity_t * crossEnt = & cg_entities [ cg . crosshairClientNum ] ;
if ( crossEnt - > currentState . number < MAX_CLIENTS )
{
if ( cgs . gametype > = GT_TEAM & &
cgs . clientinfo [ crossEnt - > currentState . number ] . team = = cgs . clientinfo [ cg . snap - > ps . clientNum ] . team )
{
//Allies are green
ecolor [ 0 ] = 0.0 ; //R
ecolor [ 1 ] = 1.0 ; //G
ecolor [ 2 ] = 0.0 ; //B
}
else
{
//Enemies are red
ecolor [ 0 ] = 1.0 ; //R
ecolor [ 1 ] = 0.0 ; //G
ecolor [ 2 ] = 0.0 ; //B
}
if ( cg . snap - > ps . duelInProgress )
{
if ( crossEnt - > currentState . number ! = cg . snap - > ps . duelIndex )
{ //grey out crosshair for everyone but your foe if you're in a duel
ecolor [ 0 ] = 0.4 ;
ecolor [ 1 ] = 0.4 ;
ecolor [ 2 ] = 0.4 ;
}
}
else if ( crossEnt - > currentState . bolt1 )
{ //this fellow is in a duel. We just checked if we were in a duel above, so
//this means we aren't and he is. Which of course means our crosshair greys out over him.
ecolor [ 0 ] = 0.4 ;
ecolor [ 1 ] = 0.4 ;
ecolor [ 2 ] = 0.4 ;
}
}
else if ( crossEnt - > currentState . shouldtarget )
{
//VectorCopy( crossEnt->startRGBA, ecolor );
if ( ! ecolor [ 0 ] & & ! ecolor [ 1 ] & & ! ecolor [ 2 ] )
{
// We really don't want black, so set it to yellow
ecolor [ 0 ] = 1.0F ; //R
ecolor [ 1 ] = 0.8F ; //G
ecolor [ 2 ] = 0.3F ; //B
}
if ( crossEnt - > currentState . owner = = cg . snap - > ps . clientNum | |
( cgs . gametype > = GT_TEAM & & crossEnt - > currentState . teamowner = = cgs . clientinfo [ cg . snap - > ps . clientNum ] . team ) )
{
ecolor [ 0 ] = 0.0 ; //R
ecolor [ 1 ] = 1.0 ; //G
ecolor [ 2 ] = 0.0 ; //B
}
else if ( crossEnt - > currentState . teamowner = = 16 | |
( cgs . gametype > = GT_TEAM & & crossEnt - > currentState . teamowner & & crossEnt - > currentState . teamowner ! = cgs . clientinfo [ cg . snap - > ps . clientNum ] . team ) )
{
ecolor [ 0 ] = 1.0 ; //R
ecolor [ 1 ] = 0.0 ; //G
ecolor [ 2 ] = 0.0 ; //B
}
}
ecolor [ 3 ] = 1.0 ;
trap_R_SetColor ( ecolor ) ;
}
}
w = h = cg_crosshairSize . value ;
// pulse the size of the crosshair when picking up items
f = cg . time - cg . itemPickupBlendTime ;
if ( f > 0 & & f < ITEM_BLOB_TIME ) {
f / = ITEM_BLOB_TIME ;
w * = ( 1 + f ) ;
h * = ( 1 + f ) ;
}
if ( worldPoint & & VectorLength ( worldPoint ) )
{
if ( ! CG_WorldCoordToScreenCoordFloat ( worldPoint , & x , & y ) )
{ //off screen, don't draw it
return ;
}
x - = 320 ;
y - = 240 ;
}
else
{
x = cg_crosshairX . integer ;
y = cg_crosshairY . integer ;
}
hShader = cgs . media . crosshairShader [ cg_drawCrosshair . integer % NUM_CROSSHAIRS ] ;
trap_R_DrawStretchPic ( x + cg . refdef . x + 0.5 * ( 640 - w ) ,
y + cg . refdef . y + 0.5 * ( 480 - h ) ,
w , h , 0 , 0 , 1 , 1 , hShader ) ;
}
qboolean CG_WorldCoordToScreenCoordFloat ( vec3_t worldCoord , float * x , float * y )
{
int xcenter , ycenter ;
vec3_t local , transformed ;
vec3_t vfwd ;
vec3_t vright ;
vec3_t vup ;
float xzi ;
float yzi ;
// 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
AngleVectors ( cg . refdefViewAngles , vfwd , vright , vup ) ;
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 ;
}
xzi = xcenter / transformed [ 2 ] * ( 90.0 / cg . refdef . fov_x ) ;
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_SaberClashFlare
= = = = = = = = = = = = = = = = = = = =
*/
int g_saberFlashTime = 0 ;
vec3_t g_saberFlashPos = { 0 , 0 , 0 } ;
void CG_SaberClashFlare ( void )
{
int t , maxTime = 150 ;
vec3_t dif ;
vec3_t color ;
int x , y ;
float v , len ;
trace_t tr ;
t = cg . time - g_saberFlashTime ;
if ( t < = 0 | | t > = maxTime )
{
return ;
}
// Don't do clashes for things that are behind us
VectorSubtract ( g_saberFlashPos , cg . refdef . vieworg , dif ) ;
if ( DotProduct ( dif , cg . refdef . viewaxis [ 0 ] ) < 0.2 )
{
return ;
}
CG_Trace ( & tr , cg . refdef . vieworg , NULL , NULL , g_saberFlashPos , - 1 , CONTENTS_SOLID ) ;
if ( tr . fraction < 1.0f )
{
return ;
}
len = VectorNormalize ( dif ) ;
// clamp to a known range
if ( len > 800 )
{
len = 800 ;
}
v = ( 1.0f - ( ( float ) t / maxTime ) ) * ( ( 1.0f - ( len / 800.0f ) ) * 2.0f + 0.35f ) ;
CG_WorldCoordToScreenCoord ( g_saberFlashPos , & x , & y ) ;
VectorSet ( color , 0.8f , 0.8f , 0.8f ) ;
trap_R_SetColor ( color ) ;
CG_DrawPic ( x - ( v * 300 ) , y - ( v * 300 ) ,
v * 600 , v * 600 ,
trap_R_RegisterShader ( " gfx/effects/saberFlare " ) ) ;
}
//--------------------------------------------------------------
static void CG_DrawHolocronIcons ( void )
//--------------------------------------------------------------
{
int icon_size = 40 ;
int i = 0 ;
int startx = 10 ;
int starty = 10 ; //SCREEN_HEIGHT - icon_size*3;
int endx = icon_size ;
int endy = icon_size ;
if ( cg . snap - > ps . zoomMode )
{ //don't display over zoom mask
return ;
}
while ( i < NUM_FORCE_POWERS )
{
if ( cg . snap - > ps . holocronBits & ( 1 < < forcePowerSorted [ i ] ) )
{
CG_DrawPic ( startx , starty , endx , endy , cgs . media . forcePowerIcons [ forcePowerSorted [ i ] ] ) ;
starty + = ( icon_size + 2 ) ; //+2 for spacing
if ( ( starty + icon_size ) > = SCREEN_HEIGHT - 80 )
{
starty = 10 ; //SCREEN_HEIGHT - icon_size*3;
startx + = ( icon_size + 2 ) ;
}
}
i + + ;
}
}
static qboolean CG_IsDurationPower ( int power )
{
if ( power = = FP_HEAL | |
power = = FP_SPEED | |
power = = FP_TELEPATHY | |
power = = FP_RAGE | |
power = = FP_PROTECT | |
power = = FP_ABSORB | |
power = = FP_SEE )
{
return qtrue ;
}
return qfalse ;
}
//--------------------------------------------------------------
static void CG_DrawActivePowers ( void )
//--------------------------------------------------------------
{
int icon_size = 40 ;
int i = 0 ;
int startx = icon_size * 2 + 16 ;
int starty = SCREEN_HEIGHT - icon_size * 2 ;
int endx = icon_size ;
int endy = icon_size ;
if ( cg . snap - > ps . zoomMode )
{ //don't display over zoom mask
return ;
}
while ( i < NUM_FORCE_POWERS )
{
if ( ( cg . snap - > ps . fd . forcePowersActive & ( 1 < < forcePowerSorted [ i ] ) ) & &
CG_IsDurationPower ( forcePowerSorted [ i ] ) )
{
CG_DrawPic ( startx , starty , endx , endy , cgs . media . forcePowerIcons [ forcePowerSorted [ i ] ] ) ;
startx + = ( icon_size + 2 ) ; //+2 for spacing
if ( ( startx + icon_size ) > = SCREEN_WIDTH - 80 )
{
startx = icon_size * 2 + 16 ;
starty + = ( icon_size + 2 ) ;
}
}
i + + ;
}
2013-04-04 18:01:17 +00:00
//additionally, draw an icon force force rage recovery
if ( cg . snap - > ps . fd . forceRageRecoveryTime > cg . time )
{
CG_DrawPic ( startx , starty , endx , endy , cgs . media . rageRecShader ) ;
}
2013-04-04 14:52:42 +00:00
}
//--------------------------------------------------------------
static void CG_DrawRocketLocking ( int lockEntNum , int lockTime )
//--------------------------------------------------------------
{
int cx , cy ;
vec3_t org ;
static int oldDif = 0 ;
centity_t * cent = & cg_entities [ lockEntNum ] ;
vec4_t color = { 0.0f , 0.0f , 0.0f , 0.0f } ;
int dif = ( cg . time - cg . snap - > ps . rocketLockTime ) / ( 1200.0f / /*8.0f*/ 16.0f ) ;
int i ;
if ( ! cg . snap - > ps . rocketLockTime )
{
return ;
}
if ( cg . snap - > ps . rocketLockTime ! = - 1 )
{
lastvalidlockdif = dif ;
}
else
{
dif = lastvalidlockdif ;
}
if ( ! cent )
{
return ;
}
VectorCopy ( cent - > lerpOrigin , org ) ;
if ( CG_WorldCoordToScreenCoord ( org , & cx , & cy ) )
{
// we care about distance from enemy to eye, so this is good enough
float sz = Distance ( cent - > lerpOrigin , cg . refdef . vieworg ) / 1024.0f ;
if ( sz > 1.0f )
{
sz = 1.0f ;
}
else if ( sz < 0.0f )
{
sz = 0.0f ;
}
sz = ( 1.0f - sz ) * ( 1.0f - sz ) * 32 + 6 ;
cy + = sz * 0.5f ;
if ( dif < 0 )
{
oldDif = 0 ;
return ;
}
else if ( dif > 8 )
{
dif = 8 ;
}
// do sounds
if ( oldDif ! = dif )
{
if ( dif = = 8 )
{
trap_S_StartSound ( org , 0 , CHAN_AUTO , trap_S_RegisterSound ( " sound/weapons/rocket/lock.wav " ) ) ;
}
else
{
trap_S_StartSound ( org , 0 , CHAN_AUTO , trap_S_RegisterSound ( " sound/weapons/rocket/tick.wav " ) ) ;
}
}
oldDif = dif ;
for ( i = 0 ; i < dif ; i + + )
{
color [ 0 ] = 1.0f ;
color [ 1 ] = 0.0f ;
color [ 2 ] = 0.0f ;
color [ 3 ] = 0.1f * i + 0.2f ;
trap_R_SetColor ( color ) ;
// our slices are offset by about 45 degrees.
CG_DrawRotatePic ( cx - sz , cy - sz , sz , sz , i * 45.0f , trap_R_RegisterShaderNoMip ( " gfx/2d/wedge " ) ) ;
}
// we are locked and loaded baby
if ( dif = = 8 )
{
color [ 0 ] = color [ 1 ] = color [ 2 ] = sin ( cg . time * 0.05f ) * 0.5f + 0.5f ;
color [ 3 ] = 1.0f ; // this art is additive, so the alpha value does nothing
trap_R_SetColor ( color ) ;
CG_DrawPic ( cx - sz , cy - sz * 2 , sz * 2 , sz * 2 , trap_R_RegisterShaderNoMip ( " gfx/2d/lock " ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = =
CG_ScanForCrosshairEntity
= = = = = = = = = = = = = = = = =
*/
static void CG_ScanForCrosshairEntity ( void ) {
trace_t trace ;
vec3_t start , end ;
int content ;
if ( cg_dynamicCrosshair . integer )
{
vec3_t d_f , d_rt , d_up ;
/*
if ( cg . snap - > ps . weapon = = WP_NONE | |
cg . snap - > ps . weapon = = WP_SABER | |
cg . snap - > ps . weapon = = WP_STUN_BATON )
{
VectorCopy ( cg . refdef . vieworg , start ) ;
AngleVectors ( cg . refdefViewAngles , d_f , d_rt , d_up ) ;
}
else
*/
//For now we still want to draw the crosshair in relation to the player's world coordinates
//even if we have a melee weapon/no weapon.
{
if ( cg . snap & & cg . snap - > ps . weapon = = WP_EMPLACED_GUN & & cg . snap - > ps . emplacedIndex )
{
vec3_t pitchConstraint ;
VectorCopy ( cg . refdefViewAngles , pitchConstraint ) ;
if ( cg . renderingThirdPerson )
{
VectorCopy ( cg . predictedPlayerState . viewangles , pitchConstraint ) ;
}
else
{
VectorCopy ( cg . refdefViewAngles , pitchConstraint ) ;
}
if ( pitchConstraint [ PITCH ] > 40 )
{
pitchConstraint [ PITCH ] = 40 ;
}
AngleVectors ( pitchConstraint , d_f , d_rt , d_up ) ;
}
else
{
vec3_t pitchConstraint ;
if ( cg . renderingThirdPerson )
{
VectorCopy ( cg . predictedPlayerState . viewangles , pitchConstraint ) ;
}
else
{
VectorCopy ( cg . refdefViewAngles , pitchConstraint ) ;
}
AngleVectors ( pitchConstraint , d_f , d_rt , d_up ) ;
}
CG_CalcMuzzlePoint ( cg . snap - > ps . clientNum , start ) ;
}
//FIXME: increase this? Increase when zoom in?
VectorMA ( start , 4096 , d_f , end ) ; //was 8192
}
else
{
VectorCopy ( cg . refdef . vieworg , start ) ;
VectorMA ( start , 131072 , cg . refdef . viewaxis [ 0 ] , end ) ;
}
CG_Trace ( & trace , start , vec3_origin , vec3_origin , end ,
cg . snap - > ps . clientNum , CONTENTS_SOLID | CONTENTS_BODY ) ;
if ( trace . entityNum < MAX_CLIENTS )
{
if ( CG_IsMindTricked ( cg_entities [ trace . entityNum ] . currentState . trickedentindex ,
cg_entities [ trace . entityNum ] . currentState . trickedentindex2 ,
cg_entities [ trace . entityNum ] . currentState . trickedentindex3 ,
cg_entities [ trace . entityNum ] . currentState . trickedentindex4 ,
cg . snap - > ps . clientNum ) )
{
if ( cg . crosshairClientNum = = trace . entityNum )
{
cg . crosshairClientNum = ENTITYNUM_NONE ;
cg . crosshairClientTime = 0 ;
}
CG_DrawCrosshair ( trace . endpos , 0 ) ;
return ; //this entity is mind-tricking the current client, so don't render it
}
}
if ( cg . snap - > ps . persistant [ PERS_TEAM ] ! = TEAM_SPECTATOR )
{
if ( trace . entityNum < /*MAX_CLIENTS*/ ENTITYNUM_WORLD )
{
CG_DrawCrosshair ( trace . endpos , 1 ) ;
}
else
{
CG_DrawCrosshair ( trace . endpos , 0 ) ;
}
}
// if ( trace.entityNum >= MAX_CLIENTS ) {
// return;
// }
// if the player is in fog, don't show it
content = trap_CM_PointContents ( trace . endpos , 0 ) ;
if ( content & CONTENTS_FOG ) {
return ;
}
if ( trace . entityNum > = MAX_CLIENTS ) {
cg . crosshairClientNum = trace . entityNum ;
cg . crosshairClientTime = cg . time ;
return ;
}
// update the fade timer
cg . crosshairClientNum = trace . entityNum ;
cg . crosshairClientTime = cg . time ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CG_DrawCrosshairNames
= = = = = = = = = = = = = = = = = = = = =
*/
static void CG_DrawCrosshairNames ( void ) {
float * color ;
vec4_t tcolor ;
char * name ;
int baseColor ;
if ( ! cg_drawCrosshair . integer ) {
return ;
}
if ( ! cg_drawCrosshairNames . integer ) {
return ;
}
// scan the known entities to see if the crosshair is sighted on one
CG_ScanForCrosshairEntity ( ) ;
if ( cg . crosshairClientNum > = MAX_CLIENTS )
{
return ;
}
// draw the name of the player being looked at
color = CG_FadeColor ( cg . crosshairClientTime , 1000 ) ;
if ( ! color ) {
trap_R_SetColor ( NULL ) ;
return ;
}
name = cgs . clientinfo [ cg . crosshairClientNum ] . name ;
if ( cgs . gametype > = GT_TEAM )
{
if ( cgs . clientinfo [ cg . crosshairClientNum ] . team = = TEAM_RED )
{
baseColor = CT_RED ;
}
else
{
baseColor = CT_BLUE ;
}
/*
//For now instead of team-based we'll make it oriented based on which team we're on
if ( cgs . clientinfo [ cg . crosshairClientNum ] . team = = cgs . clientinfo [ cg . snap - > ps . clientNum ] . team )
{
baseColor = CT_GREEN ;
}
else
{
baseColor = CT_RED ;
}
*/
}
else
{
//baseColor = CT_WHITE;
baseColor = CT_RED ; //just make it red in nonteam modes since everyone is hostile and crosshair will be red on them too
}
if ( cg . snap - > ps . duelInProgress )
{
if ( cg . crosshairClientNum ! = cg . snap - > ps . duelIndex )
{ //grey out crosshair for everyone but your foe if you're in a duel
baseColor = CT_BLACK ;
}
}
else if ( cg_entities [ cg . crosshairClientNum ] . currentState . bolt1 )
{ //this fellow is in a duel. We just checked if we were in a duel above, so
//this means we aren't and he is. Which of course means our crosshair greys out over him.
baseColor = CT_BLACK ;
}
tcolor [ 0 ] = colorTable [ baseColor ] [ 0 ] ;
tcolor [ 1 ] = colorTable [ baseColor ] [ 1 ] ;
tcolor [ 2 ] = colorTable [ baseColor ] [ 2 ] ;
tcolor [ 3 ] = color [ 3 ] * 0.5f ;
UI_DrawProportionalString ( 320 , 170 , name , UI_CENTER , tcolor ) ;
trap_R_SetColor ( NULL ) ;
}
//==============================================================================
/*
= = = = = = = = = = = = = = = = =
CG_DrawSpectator
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawSpectator ( void ) {
CG_DrawBigString ( 320 - 9 * 8 , 440 , " SPECTATOR " , 1.0F ) ;
if ( cgs . gametype = = GT_TOURNAMENT ) {
CG_DrawBigString ( 320 - 15 * 8 , 460 , " waiting to play " , 1.0F ) ;
}
else if ( cgs . gametype > = GT_TEAM ) {
CG_DrawBigString ( 320 - 39 * 8 , 460 , " press ESC and use the JOIN menu to play " , 1.0F ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawVote
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawVote ( void ) {
char * s ;
int sec ;
if ( ! cgs . voteTime ) {
return ;
}
// play a talk beep whenever it is modified
if ( cgs . voteModified ) {
cgs . voteModified = qfalse ;
// trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
}
sec = ( VOTE_TIME - ( cg . time - cgs . voteTime ) ) / 1000 ;
if ( sec < 0 ) {
sec = 0 ;
}
s = va ( " VOTE(%i):%s yes:%i no:%i " , sec , cgs . voteString , cgs . voteYes , cgs . voteNo ) ;
CG_DrawSmallString ( 0 , 58 , s , 1.0F ) ;
s = " or press ESC then click Vote " ;
CG_DrawSmallString ( 0 , 58 + SMALLCHAR_HEIGHT + 2 , s , 1.0F ) ;
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawTeamVote
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawTeamVote ( void ) {
char * s ;
int sec , cs_offset ;
if ( cgs . clientinfo - > team = = TEAM_RED )
cs_offset = 0 ;
else if ( cgs . clientinfo - > team = = TEAM_BLUE )
cs_offset = 1 ;
else
return ;
if ( ! cgs . teamVoteTime [ cs_offset ] ) {
return ;
}
// play a talk beep whenever it is modified
if ( cgs . teamVoteModified [ cs_offset ] ) {
cgs . teamVoteModified [ cs_offset ] = qfalse ;
// trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
}
sec = ( VOTE_TIME - ( cg . time - cgs . teamVoteTime [ cs_offset ] ) ) / 1000 ;
if ( sec < 0 ) {
sec = 0 ;
}
s = va ( " TEAMVOTE(%i):%s yes:%i no:%i " , sec , cgs . teamVoteString [ cs_offset ] ,
cgs . teamVoteYes [ cs_offset ] , cgs . teamVoteNo [ cs_offset ] ) ;
CG_DrawSmallString ( 0 , 90 , s , 1.0F ) ;
}
static qboolean CG_DrawScoreboard ( ) {
return CG_DrawOldScoreboard ( ) ;
#if 0
static qboolean firstTime = qtrue ;
float fade , * fadeColor ;
if ( menuScoreboard ) {
menuScoreboard - > window . flags & = ~ WINDOW_FORCED ;
}
if ( cg_paused . integer ) {
cg . deferredPlayerLoading = 0 ;
firstTime = qtrue ;
return qfalse ;
}
// should never happen in Team Arena
if ( cgs . gametype = = GT_SINGLE_PLAYER & & cg . predictedPlayerState . pm_type = = PM_INTERMISSION ) {
cg . deferredPlayerLoading = 0 ;
firstTime = qtrue ;
return qfalse ;
}
// don't draw scoreboard during death while warmup up
if ( cg . warmup & & ! cg . showScores ) {
return qfalse ;
}
if ( cg . showScores | | cg . predictedPlayerState . pm_type = = PM_DEAD | | cg . predictedPlayerState . pm_type = = PM_INTERMISSION ) {
fade = 1.0 ;
fadeColor = colorWhite ;
} else {
fadeColor = CG_FadeColor ( cg . scoreFadeTime , FADE_TIME ) ;
if ( ! fadeColor ) {
// next time scoreboard comes up, don't print killer
cg . deferredPlayerLoading = 0 ;
cg . killerName [ 0 ] = 0 ;
firstTime = qtrue ;
return qfalse ;
}
fade = * fadeColor ;
}
if ( menuScoreboard = = NULL ) {
if ( cgs . gametype > = GT_TEAM ) {
menuScoreboard = Menus_FindByName ( " teamscore_menu " ) ;
} else {
menuScoreboard = Menus_FindByName ( " score_menu " ) ;
}
}
if ( menuScoreboard ) {
if ( firstTime ) {
CG_SetScoreSelection ( menuScoreboard ) ;
firstTime = qfalse ;
}
Menu_Paint ( menuScoreboard , qtrue ) ;
}
// load any models that have been deferred
if ( + + cg . deferredPlayerLoading > 10 ) {
CG_LoadDeferredPlayers ( ) ;
}
return qtrue ;
# endif
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawIntermission
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawIntermission ( void ) {
// int key;
//if (cg_singlePlayer.integer) {
// CG_DrawCenterString();
// return;
//}
cg . scoreFadeTime = cg . time ;
cg . scoreBoardShowing = CG_DrawScoreboard ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawFollow
= = = = = = = = = = = = = = = = =
*/
static qboolean CG_DrawFollow ( void ) {
float x ;
vec4_t color ;
const char * name ;
if ( ! ( cg . snap - > ps . pm_flags & PMF_FOLLOW ) ) {
return qfalse ;
}
color [ 0 ] = 1 ;
color [ 1 ] = 1 ;
color [ 2 ] = 1 ;
color [ 3 ] = 1 ;
CG_DrawBigString ( 320 - 9 * 8 , 24 , " following " , 1.0F ) ;
name = cgs . clientinfo [ cg . snap - > ps . clientNum ] . name ;
x = 0.5 * ( 640 - GIANT_WIDTH * CG_DrawStrlen ( name ) ) ;
CG_DrawStringExt ( x , 40 , name , color , qtrue , qtrue , GIANT_WIDTH , GIANT_HEIGHT , 0 ) ;
return qtrue ;
}
static void CG_DrawTemporaryStats ( )
{ //placeholder for testing (draws ammo and force power)
#if 0
char s [ 512 ] ;
if ( ! cg . snap )
{
return ;
}
sprintf ( s , " Force: %i " , cg . snap - > ps . fd . forcePower ) ;
CG_DrawBigString ( SCREEN_WIDTH - 164 , SCREEN_HEIGHT - 128 , s , 1.0f ) ;
sprintf ( s , " Ammo: %i " , cg . snap - > ps . ammo [ weaponData [ cg . snap - > ps . weapon ] . ammoIndex ] ) ;
CG_DrawBigString ( SCREEN_WIDTH - 164 , SCREEN_HEIGHT - 112 , s , 1.0f ) ;
sprintf ( s , " Health: %i " , cg . snap - > ps . stats [ STAT_HEALTH ] ) ;
CG_DrawBigString ( 8 , SCREEN_HEIGHT - 128 , s , 1.0f ) ;
sprintf ( s , " Armor: %i " , cg . snap - > ps . stats [ STAT_ARMOR ] ) ;
CG_DrawBigString ( 8 , SCREEN_HEIGHT - 112 , s , 1.0f ) ;
# endif
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawAmmoWarning
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawAmmoWarning ( void ) {
#if 0
const char * s ;
int w ;
if ( ! cg_drawStatus . integer )
{
return ;
}
if ( cg_drawAmmoWarning . integer = = 0 ) {
return ;
}
if ( ! cg . lowAmmoWarning ) {
return ;
}
if ( cg . lowAmmoWarning = = 2 ) {
s = " OUT OF AMMO " ;
} else {
s = " LOW AMMO WARNING " ;
}
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 320 - w / 2 , 64 , s , 1.0F ) ;
# endif
}
/*
= = = = = = = = = = = = = = = = =
CG_DrawWarmup
= = = = = = = = = = = = = = = = =
*/
static void CG_DrawWarmup ( void ) {
int w ;
int sec ;
int i ;
float scale ;
clientInfo_t * ci1 , * ci2 ;
int cw ;
const char * s ;
sec = cg . warmup ;
if ( ! sec ) {
return ;
}
if ( sec < 0 ) {
s = " Waiting for players " ;
w = CG_DrawStrlen ( s ) * BIGCHAR_WIDTH ;
CG_DrawBigString ( 320 - w / 2 , 24 , s , 1.0F ) ;
cg . warmupCount = 0 ;
return ;
}
if ( cgs . gametype = = GT_TOURNAMENT ) {
// find the two active players
ci1 = NULL ;
ci2 = NULL ;
for ( i = 0 ; i < cgs . maxclients ; i + + ) {
if ( cgs . clientinfo [ i ] . infoValid & & cgs . clientinfo [ i ] . team = = TEAM_FREE ) {
if ( ! ci1 ) {
ci1 = & cgs . clientinfo [ i ] ;
} else {
ci2 = & cgs . clientinfo [ i ] ;
}
}
}
if ( ci1 & & ci2 ) {
s = va ( " %s vs %s " , ci1 - > name , ci2 - > name ) ;
w = CG_Text_Width ( s , 0.6f , FONT_MEDIUM ) ;
CG_Text_Paint ( 320 - w / 2 , 60 , 0.6f , colorWhite , s , 0 , 0 , ITEM_TEXTSTYLE_SHADOWEDMORE , FONT_MEDIUM ) ;
}
} else {
if ( cgs . gametype = = GT_FFA ) {
s = " Free For All " ;
} else if ( cgs . gametype = = GT_HOLOCRON ) {
s = " Holocron FFA " ;
} else if ( cgs . gametype = = GT_JEDIMASTER ) {
s = " Jedi Master " ;
} else if ( cgs . gametype = = GT_TEAM ) {
s = " Team FFA " ;
} else if ( cgs . gametype = = GT_SAGA ) {
s = " Saga " ;
} else if ( cgs . gametype = = GT_CTF ) {
s = " Capture the Flag " ;
} else if ( cgs . gametype = = GT_CTY ) {
s = " Capture the Ysalimari " ;
} else {
s = " " ;
}
w = CG_Text_Width ( s , 0.6f , FONT_MEDIUM ) ;
CG_Text_Paint ( 320 - w / 2 , 90 , 0.6f , colorWhite , s , 0 , 0 , ITEM_TEXTSTYLE_SHADOWEDMORE , FONT_MEDIUM ) ;
}
sec = ( sec - cg . time ) / 1000 ;
if ( sec < 0 ) {
cg . warmup = 0 ;
sec = 0 ;
}
s = va ( " Starts in: %i " , sec + 1 ) ;
if ( sec ! = cg . warmupCount ) {
cg . warmupCount = sec ;
switch ( sec ) {
case 0 :
trap_S_StartLocalSound ( cgs . media . count1Sound , CHAN_ANNOUNCER ) ;
break ;
case 1 :
trap_S_StartLocalSound ( cgs . media . count2Sound , CHAN_ANNOUNCER ) ;
break ;
case 2 :
trap_S_StartLocalSound ( cgs . media . count3Sound , CHAN_ANNOUNCER ) ;
break ;
default :
break ;
}
}
scale = 0.45f ;
switch ( cg . warmupCount ) {
case 0 :
cw = 28 ;
scale = 0.54f ;
break ;
case 1 :
cw = 24 ;
scale = 0.51f ;
break ;
case 2 :
cw = 20 ;
scale = 0.48f ;
break ;
default :
cw = 16 ;
scale = 0.45f ;
break ;
}
w = CG_Text_Width ( s , scale , FONT_MEDIUM ) ;
CG_Text_Paint ( 320 - w / 2 , 125 , scale , colorWhite , s , 0 , 0 , ITEM_TEXTSTYLE_SHADOWEDMORE , FONT_MEDIUM ) ;
}
//==================================================================================
/*
= = = = = = = = = = = = = = = = =
CG_DrawTimedMenus
= = = = = = = = = = = = = = = = =
*/
void CG_DrawTimedMenus ( ) {
if ( cg . voiceTime ) {
int t = cg . time - cg . voiceTime ;
if ( t > 2500 ) {
Menus_CloseByName ( " voiceMenu " ) ;
trap_Cvar_Set ( " cl_conXOffset " , " 0 " ) ;
cg . voiceTime = 0 ;
}
}
}
static void CG_DrawPowerupIcons ( )
{
int j ;
int ico_size = 64 ;
int y = ico_size / 2 ;
gitem_t * item ;
if ( ! cg . snap )
{
return ;
}
for ( j = 0 ; j < = PW_NUM_POWERUPS ; j + + )
{
if ( cg . snap - > ps . powerups [ j ] > cg . time )
{
int secondsleft = ( cg . snap - > ps . powerups [ j ] - cg . time ) / 1000 ;
item = BG_FindItemForPowerup ( j ) ;
if ( item )
{
int icoShader = 0 ;
if ( cgs . gametype = = GT_CTY & & ( j = = PW_REDFLAG | | j = = PW_BLUEFLAG ) )
{
if ( j = = PW_REDFLAG )
{
icoShader = trap_R_RegisterShader ( " gfx/hud/mpi_rflag_ys " ) ;
}
else
{
icoShader = trap_R_RegisterShader ( " gfx/hud/mpi_bflag_ys " ) ;
}
}
else
{
icoShader = trap_R_RegisterShader ( item - > icon ) ;
}
CG_DrawPic ( ( 640 - ( ico_size * 1.5 ) ) , y , ico_size , ico_size , icoShader ) ;
y + = ico_size ;
if ( j ! = PW_REDFLAG & & j ! = PW_BLUEFLAG & & secondsleft < 999 )
{
UI_DrawProportionalString ( ( 640 - ( ico_size * 1.5 ) ) + ( ico_size / 2 ) , y - 8 , va ( " %i " , secondsleft ) , UI_CENTER | UI_SMALLFONT | UI_DROPSHADOW , colorTable [ CT_WHITE ] ) ;
}
y + = ( ico_size / 3 ) ;
}
}
}
}
void CG_DrawFlagStatus ( )
{
int myFlagTakenShader = 0 ;
int theirFlagShader = 0 ;
int team = 0 ;
int startDrawPos = 2 ;
int ico_size = 32 ;
if ( ! cg . snap )
{
return ;
}
if ( cgs . gametype ! = GT_CTF & & cgs . gametype ! = GT_CTY )
{
return ;
}
team = cg . snap - > ps . persistant [ PERS_TEAM ] ;
if ( cgs . gametype = = GT_CTY )
{
if ( team = = TEAM_RED )
{
myFlagTakenShader = trap_R_RegisterShader ( " gfx/hud/mpi_rflag_x " ) ;
theirFlagShader = trap_R_RegisterShader ( " gfx/hud/mpi_bflag_ys " ) ;
}
else
{
myFlagTakenShader = trap_R_RegisterShader ( " gfx/hud/mpi_bflag_x " ) ;
theirFlagShader = trap_R_RegisterShader ( " gfx/hud/mpi_rflag_ys " ) ;
}
}
else
{
if ( team = = TEAM_RED )
{
myFlagTakenShader = trap_R_RegisterShader ( " gfx/hud/mpi_rflag_x " ) ;
theirFlagShader = trap_R_RegisterShader ( " gfx/hud/mpi_bflag " ) ;
}
else
{
myFlagTakenShader = trap_R_RegisterShader ( " gfx/hud/mpi_bflag_x " ) ;
theirFlagShader = trap_R_RegisterShader ( " gfx/hud/mpi_rflag " ) ;
}
}
if ( CG_YourTeamHasFlag ( ) )
{
CG_DrawPic ( startDrawPos , 365 , ico_size , ico_size , theirFlagShader ) ;
startDrawPos + = ico_size + 2 ;
}
if ( CG_OtherTeamHasFlag ( ) )
{
CG_DrawPic ( startDrawPos , 365 , ico_size , ico_size , myFlagTakenShader ) ;
}
}
int cgRageTime = 0 ;
int cgRageFadeTime = 0 ;
float cgRageFadeVal = 0 ;
int cgRageRecTime = 0 ;
int cgRageRecFadeTime = 0 ;
float cgRageRecFadeVal = 0 ;
int cgAbsorbTime = 0 ;
int cgAbsorbFadeTime = 0 ;
float cgAbsorbFadeVal = 0 ;
int cgProtectTime = 0 ;
int cgProtectFadeTime = 0 ;
float cgProtectFadeVal = 0 ;
int cgYsalTime = 0 ;
int cgYsalFadeTime = 0 ;
float cgYsalFadeVal = 0 ;
/*
= = = = = = = = = = = = = = = = =
CG_Draw2D
= = = = = = = = = = = = = = = = =
*/
static void CG_Draw2D ( void ) {
float inTime = cg . invenSelectTime + WEAPON_SELECT_TIME ;
float wpTime = cg . weaponSelectTime + WEAPON_SELECT_TIME ;
float bestTime ;
int drawSelect = 0 ;
float fallTime , rageTime , rageRecTime , absorbTime , protectTime , ysalTime ;
vec4_t hcolor ;
if ( cgs . orderPending & & cg . time > cgs . orderTime ) {
CG_CheckOrderPending ( ) ;
}
// if we are taking a levelshot for the menu, don't draw anything
if ( cg . levelShot ) {
return ;
}
if ( cg_draw2D . integer = = 0 ) {
return ;
}
if ( cg . snap - > ps . pm_type = = PM_INTERMISSION ) {
CG_DrawIntermission ( ) ;
return ;
}
if ( cg . snap - > ps . fd . forcePowersActive & ( 1 < < FP_RAGE ) )
{
if ( ! cgRageTime )
{
cgRageTime = cg . time ;
}
rageTime = ( float ) ( cg . time - cgRageTime ) ;
rageTime / = 9000 ;
if ( rageTime < 0 )
{
rageTime = 0 ;
}
if ( rageTime > 0.15 )
{
rageTime = 0.15 ;
}
hcolor [ 3 ] = rageTime ;
hcolor [ 0 ] = 0.7 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0 ;
if ( ! cg . renderingThirdPerson )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgRageFadeTime = 0 ;
cgRageFadeVal = 0 ;
}
else if ( cgRageTime )
{
if ( ! cgRageFadeTime )
{
cgRageFadeTime = cg . time ;
cgRageFadeVal = 0.15 ;
}
rageTime = cgRageFadeVal ;
cgRageFadeVal - = ( cg . time - cgRageFadeTime ) * 0.000005 ;
if ( rageTime < 0 )
{
rageTime = 0 ;
}
if ( rageTime > 0.15 )
{
rageTime = 0.15 ;
}
if ( cg . snap - > ps . fd . forceRageRecoveryTime > cg . time )
{
float checkRageRecTime = rageTime ;
if ( checkRageRecTime < 0.15 )
{
checkRageRecTime = 0.15 ;
}
hcolor [ 3 ] = checkRageRecTime ;
hcolor [ 0 ] = rageTime * 4 ;
if ( hcolor [ 0 ] < 0.2 )
{
hcolor [ 0 ] = 0.2 ;
}
hcolor [ 1 ] = 0.2 ;
hcolor [ 2 ] = 0.2 ;
}
else
{
hcolor [ 3 ] = rageTime ;
hcolor [ 0 ] = 0.7 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0 ;
}
if ( ! cg . renderingThirdPerson & & rageTime )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
else
{
if ( cg . snap - > ps . fd . forceRageRecoveryTime > cg . time )
{
hcolor [ 3 ] = 0.15 ;
hcolor [ 0 ] = 0.2 ;
hcolor [ 1 ] = 0.2 ;
hcolor [ 2 ] = 0.2 ;
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgRageTime = 0 ;
}
}
else if ( cg . snap - > ps . fd . forceRageRecoveryTime > cg . time )
{
if ( ! cgRageRecTime )
{
cgRageRecTime = cg . time ;
}
rageRecTime = ( float ) ( cg . time - cgRageRecTime ) ;
rageRecTime / = 9000 ;
if ( rageRecTime < 0.15 ) //0)
{
rageRecTime = 0.15 ; //0;
}
if ( rageRecTime > 0.15 )
{
rageRecTime = 0.15 ;
}
hcolor [ 3 ] = rageRecTime ;
hcolor [ 0 ] = 0.2 ;
hcolor [ 1 ] = 0.2 ;
hcolor [ 2 ] = 0.2 ;
if ( ! cg . renderingThirdPerson )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgRageRecFadeTime = 0 ;
cgRageRecFadeVal = 0 ;
}
else if ( cgRageRecTime )
{
if ( ! cgRageRecFadeTime )
{
cgRageRecFadeTime = cg . time ;
cgRageRecFadeVal = 0.15 ;
}
rageRecTime = cgRageRecFadeVal ;
cgRageRecFadeVal - = ( cg . time - cgRageRecFadeTime ) * 0.000005 ;
if ( rageRecTime < 0 )
{
rageRecTime = 0 ;
}
if ( rageRecTime > 0.15 )
{
rageRecTime = 0.15 ;
}
hcolor [ 3 ] = rageRecTime ;
hcolor [ 0 ] = 0.2 ;
hcolor [ 1 ] = 0.2 ;
hcolor [ 2 ] = 0.2 ;
if ( ! cg . renderingThirdPerson & & rageRecTime )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
else
{
cgRageRecTime = 0 ;
}
}
if ( cg . snap - > ps . fd . forcePowersActive & ( 1 < < FP_ABSORB ) )
{
if ( ! cgAbsorbTime )
{
cgAbsorbTime = cg . time ;
}
absorbTime = ( float ) ( cg . time - cgAbsorbTime ) ;
absorbTime / = 9000 ;
if ( absorbTime < 0 )
{
absorbTime = 0 ;
}
if ( absorbTime > 0.15 )
{
absorbTime = 0.15 ;
}
hcolor [ 3 ] = absorbTime / 2 ;
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0.7 ;
if ( ! cg . renderingThirdPerson )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgAbsorbFadeTime = 0 ;
cgAbsorbFadeVal = 0 ;
}
else if ( cgAbsorbTime )
{
if ( ! cgAbsorbFadeTime )
{
cgAbsorbFadeTime = cg . time ;
cgAbsorbFadeVal = 0.15 ;
}
absorbTime = cgAbsorbFadeVal ;
cgAbsorbFadeVal - = ( cg . time - cgAbsorbFadeTime ) * 0.000005 ;
if ( absorbTime < 0 )
{
absorbTime = 0 ;
}
if ( absorbTime > 0.15 )
{
absorbTime = 0.15 ;
}
hcolor [ 3 ] = absorbTime / 2 ;
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0.7 ;
if ( ! cg . renderingThirdPerson & & absorbTime )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
else
{
cgAbsorbTime = 0 ;
}
}
if ( cg . snap - > ps . fd . forcePowersActive & ( 1 < < FP_PROTECT ) )
{
if ( ! cgProtectTime )
{
cgProtectTime = cg . time ;
}
protectTime = ( float ) ( cg . time - cgProtectTime ) ;
protectTime / = 9000 ;
if ( protectTime < 0 )
{
protectTime = 0 ;
}
if ( protectTime > 0.15 )
{
protectTime = 0.15 ;
}
hcolor [ 3 ] = protectTime / 2 ;
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0.7 ;
hcolor [ 2 ] = 0 ;
if ( ! cg . renderingThirdPerson )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgProtectFadeTime = 0 ;
cgProtectFadeVal = 0 ;
}
else if ( cgProtectTime )
{
if ( ! cgProtectFadeTime )
{
cgProtectFadeTime = cg . time ;
cgProtectFadeVal = 0.15 ;
}
protectTime = cgProtectFadeVal ;
cgProtectFadeVal - = ( cg . time - cgProtectFadeTime ) * 0.000005 ;
if ( protectTime < 0 )
{
protectTime = 0 ;
}
if ( protectTime > 0.15 )
{
protectTime = 0.15 ;
}
hcolor [ 3 ] = protectTime / 2 ;
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0.7 ;
hcolor [ 2 ] = 0 ;
if ( ! cg . renderingThirdPerson & & protectTime )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
else
{
cgProtectTime = 0 ;
}
}
if ( cg . snap - > ps . rocketLockIndex ! = MAX_CLIENTS & & ( cg . time - cg . snap - > ps . rocketLockTime ) > 0 )
{
CG_DrawRocketLocking ( cg . snap - > ps . rocketLockIndex , cg . snap - > ps . rocketLockTime ) ;
}
if ( BG_HasYsalimari ( cgs . gametype , & cg . snap - > ps ) )
{
if ( ! cgYsalTime )
{
cgYsalTime = cg . time ;
}
ysalTime = ( float ) ( cg . time - cgYsalTime ) ;
ysalTime / = 9000 ;
if ( ysalTime < 0 )
{
ysalTime = 0 ;
}
if ( ysalTime > 0.15 )
{
ysalTime = 0.15 ;
}
hcolor [ 3 ] = ysalTime / 2 ;
hcolor [ 0 ] = 0.7 ;
hcolor [ 1 ] = 0.7 ;
hcolor [ 2 ] = 0 ;
if ( ! cg . renderingThirdPerson )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
cgYsalFadeTime = 0 ;
cgYsalFadeVal = 0 ;
}
else if ( cgYsalTime )
{
if ( ! cgYsalFadeTime )
{
cgYsalFadeTime = cg . time ;
cgYsalFadeVal = 0.15 ;
}
ysalTime = cgYsalFadeVal ;
cgYsalFadeVal - = ( cg . time - cgYsalFadeTime ) * 0.000005 ;
if ( ysalTime < 0 )
{
ysalTime = 0 ;
}
if ( ysalTime > 0.15 )
{
ysalTime = 0.15 ;
}
hcolor [ 3 ] = ysalTime / 2 ;
hcolor [ 0 ] = 0.7 ;
hcolor [ 1 ] = 0.7 ;
hcolor [ 2 ] = 0 ;
if ( ! cg . renderingThirdPerson & & ysalTime )
{
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
else
{
cgYsalTime = 0 ;
}
}
if ( cg . snap - > ps . rocketLockIndex ! = MAX_CLIENTS & & ( cg . time - cg . snap - > ps . rocketLockTime ) > 0 )
{
CG_DrawRocketLocking ( cg . snap - > ps . rocketLockIndex , cg . snap - > ps . rocketLockTime ) ;
}
if ( cg . snap - > ps . holocronBits )
{
CG_DrawHolocronIcons ( ) ;
}
2013-04-04 18:01:17 +00:00
if ( cg . snap - > ps . fd . forcePowersActive | | cg . snap - > ps . fd . forceRageRecoveryTime > cg . time )
2013-04-04 14:52:42 +00:00
{
CG_DrawActivePowers ( ) ;
}
// Draw this before the text so that any text won't get clipped off
CG_DrawZoomMask ( ) ;
/*
if ( cg . cameraMode ) {
return ;
}
*/
if ( cg . snap - > ps . persistant [ PERS_TEAM ] = = TEAM_SPECTATOR ) {
CG_DrawSpectator ( ) ;
CG_DrawCrosshair ( NULL , 0 ) ;
CG_DrawCrosshairNames ( ) ;
} else {
// don't draw any status if dead or the scoreboard is being explicitly shown
if ( ! cg . showScores & & cg . snap - > ps . stats [ STAT_HEALTH ] > 0 ) {
if ( /*cg_drawStatus.integer*/ 0 ) {
//Reenable if stats are drawn with menu system again
Menu_PaintAll ( ) ;
CG_DrawTimedMenus ( ) ;
}
//CG_DrawTemporaryStats();
CG_DrawAmmoWarning ( ) ;
CG_DrawCrosshairNames ( ) ;
if ( cg_drawStatus . integer )
{
CG_DrawIconBackground ( ) ;
}
if ( inTime > wpTime )
{
drawSelect = 1 ;
bestTime = cg . invenSelectTime ;
}
else //only draw the most recent since they're drawn in the same place
{
drawSelect = 2 ;
bestTime = cg . weaponSelectTime ;
}
if ( cg . forceSelectTime > bestTime )
{
drawSelect = 3 ;
}
switch ( drawSelect )
{
case 1 :
CG_DrawInvenSelect ( ) ;
break ;
case 2 :
CG_DrawWeaponSelect ( ) ;
break ;
case 3 :
CG_DrawForceSelect ( ) ;
break ;
default :
break ;
}
if ( cg_drawStatus . integer )
{
CG_DrawPowerupIcons ( ) ;
CG_DrawFlagStatus ( ) ;
}
CG_SaberClashFlare ( ) ;
if ( cg_drawStatus . integer )
{
CG_DrawStats ( ) ;
}
//Do we want to use this system again at some point?
//CG_DrawReward();
}
}
if ( cg . snap - > ps . fallingToDeath )
{
fallTime = ( float ) ( cg . time - cg . snap - > ps . fallingToDeath ) ;
fallTime / = FALL_FADE_TIME ;
if ( fallTime < 0 )
{
fallTime = 0 ;
}
if ( fallTime > 1 )
{
fallTime = 1 ;
}
hcolor [ 3 ] = fallTime ;
hcolor [ 0 ] = 0 ;
hcolor [ 1 ] = 0 ;
hcolor [ 2 ] = 0 ;
CG_DrawRect ( 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_WIDTH * SCREEN_HEIGHT , hcolor ) ;
}
CG_DrawVote ( ) ;
CG_DrawTeamVote ( ) ;
CG_DrawLagometer ( ) ;
if ( ! cg_paused . integer ) {
CG_DrawUpperRight ( ) ;
}
if ( ! CG_DrawFollow ( ) ) {
CG_DrawWarmup ( ) ;
}
// don't draw center string if scoreboard is up
cg . scoreBoardShowing = CG_DrawScoreboard ( ) ;
if ( ! cg . scoreBoardShowing ) {
CG_DrawCenterString ( ) ;
}
}
static void CG_DrawTourneyScoreboard ( ) {
}
/*
= = = = = = = = = = = = = = = = = = = = =
CG_DrawActive
Perform all drawing needed to completely fill the screen
= = = = = = = = = = = = = = = = = = = = =
*/
void CG_DrawActive ( stereoFrame_t stereoView ) {
float separation ;
vec3_t baseOrg ;
// optionally draw the info screen instead
if ( ! cg . snap ) {
CG_DrawInformation ( ) ;
return ;
}
// optionally draw the tournement scoreboard instead
if ( cg . snap - > ps . persistant [ PERS_TEAM ] = = TEAM_SPECTATOR & &
( cg . snap - > ps . pm_flags & PMF_SCOREBOARD ) ) {
CG_DrawTourneyScoreboard ( ) ;
return ;
}
switch ( stereoView ) {
case STEREO_CENTER :
separation = 0 ;
break ;
case STEREO_LEFT :
separation = - cg_stereoSeparation . value / 2 ;
break ;
case STEREO_RIGHT :
separation = cg_stereoSeparation . value / 2 ;
break ;
default :
separation = 0 ;
CG_Error ( " CG_DrawActive: Undefined stereoView " ) ;
}
// clear around the rendered view if sized down
CG_TileClear ( ) ;
// offset vieworg appropriately if we're doing stereo separation
VectorCopy ( cg . refdef . vieworg , baseOrg ) ;
if ( separation ! = 0 ) {
VectorMA ( cg . refdef . vieworg , - separation , cg . refdef . viewaxis [ 1 ] , cg . refdef . vieworg ) ;
}
// draw 3D view
trap_R_RenderScene ( & cg . refdef ) ;
// restore original viewpoint if running stereo
if ( separation ! = 0 ) {
VectorCopy ( baseOrg , cg . refdef . vieworg ) ;
}
// draw status bar and other floating elements
CG_Draw2D ( ) ;
}