/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// cg_screen.c -- master status bar, crosshairs, hud, etc

/*

  full screen console
  put up loading plaque
  blanked background with loading plaque
  blanked background with menu
  cinematics
  full screen image for quit and victory

  end of unit intermissions

  */

#include "cg_local.h"

vrect_t		scr_vrect;

cvar_t		*cg_viewSize;
cvar_t		*cg_centerTime;
cvar_t		*cg_showFPS;
cvar_t		*cg_showPointedPlayer;
cvar_t		*cg_showHUD;
cvar_t		*cg_draw2D;
cvar_t		*cg_weaponlist;
cvar_t		*cg_debugLoading;

cvar_t		*cg_crosshair;
cvar_t		*cg_crosshair_size;
cvar_t		*cg_crosshair_color;

cvar_t		*cg_crosshair_strong;
cvar_t		*cg_crosshair_strong_size;
cvar_t		*cg_crosshair_strong_color;

cvar_t		*cg_clientHUD;
cvar_t		*cg_debug_HUD;
cvar_t		*cg_showSpeedMeter;
cvar_t		*cg_showTimer;

cvar_t		*cg_showPlayerNames;
cvar_t		*cg_showPlayerNames_alpha;
cvar_t		*cg_showPlayerNames_zfar;
cvar_t		*cg_showPlayerNames_xoffset;
cvar_t		*cg_showPlayerNames_yoffset;

cvar_t		*cg_scoreboardFont;
cvar_t		*cg_scoreboardWidthScale;

cvar_t		*cg_showWeaponSelect;	// wsw : pb : display a little box around selected weapon in weaponlist
cvar_t		*cg_showTeamLocations;

/*
===============================================================================

CENTER PRINTING

===============================================================================
*/

char		scr_centerstring[1024];
float		scr_centertime_start;	// for slow victory printing
float		scr_centertime_off;
int			scr_center_lines;
int			scr_erase_center;

/*
==============
SCR_CenterPrint

Called for important messages that should stay in the center of the screen
for a few moments
==============
*/
void SCR_CenterPrint( char *str )
{
	char	*s;

	Q_strncpyz( scr_centerstring, str, sizeof(scr_centerstring) );
	scr_centertime_off = cg_centerTime->value;
	scr_centertime_start = cg.time;

	// count the number of lines for centering
	scr_center_lines = 1;
	s = scr_centerstring;
	while( *s )
		if( *s++ == '\n' )
			scr_center_lines++;
}

void SCR_CenterPrintToUpper( char *str )
{
	char	*s;

	Q_strncpyz( scr_centerstring, str, sizeof(scr_centerstring) );
	scr_centertime_off = cg_centerTime->value;
	scr_centertime_start = cg.time;

	// count the number of lines for centering
	scr_center_lines = 1;
	s = scr_centerstring;
	while( *s ) {
		if( *s == '\n' ) {
			scr_center_lines++;
		} else {
			*s = toupper(*s);
		} 
		s++;	
	}
}

void SCR_DrawCenterString( void )
{
	int		y;
	struct mufont_s *font = cgs.fontSystemMedium;
	char *helpmessage = scr_centerstring;
	int x = cgs.vidWidth / 2;
	int width = cgs.vidWidth / 2;
	size_t len;

	// don't draw when scoreboard is up
	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD )
		return;

	if( scr_center_lines <= 4 )
		y = cgs.vidHeight*0.35;
	else
		y = 48;

	if( width < 320 )
		width = 320;

	while( (len = trap_SCR_StrlenForWidth( helpmessage, font, width )) ) {
		trap_SCR_DrawStringLen( x, y, ALIGN_CENTER_TOP, helpmessage, len, font, colorWhite );
		helpmessage += len;
		if( helpmessage[0] == '\n' ) {
			y += trap_SCR_strHeight( font );
			helpmessage++;
		}
	}
}

void SCR_CheckDrawCenterString( void )
{
	scr_centertime_off -= cg.frameTime;
	if( scr_centertime_off <= 0 )
		return;

	SCR_DrawCenterString();
}

//=============================================================================

/*
=================
SCR_CalcVrect

Sets scr_vrect, the coordinates of the rendered window
=================
*/
void SCR_CalcVrect( void )
{
	int		size;

	// bound viewsize
	if( cg_viewSize->integer < 40 )
		trap_Cvar_Set( "cg_viewsize", "40" );
	else if( cg_viewSize->integer > 100 )
		trap_Cvar_Set( "cg_viewsize", "100" );

	size = cg_viewSize->integer;

	scr_vrect.width = cgs.vidWidth*size/100;
	scr_vrect.width &= ~7;

	scr_vrect.height = cgs.vidHeight*size/100;
	scr_vrect.height &= ~1;

	scr_vrect.x = (cgs.vidWidth - scr_vrect.width)/2;
	scr_vrect.y = (cgs.vidHeight - scr_vrect.height)/2;
}

/*
=================
SCR_SizeUp_f

Keybinding command
=================
*/
void SCR_SizeUp_f( void ) {
	trap_Cvar_SetValue( "cg_viewSize", cg_viewSize->integer + 10 );
}

/*
=================
SCR_SizeDown_f

Keybinding command
=================
*/
void SCR_SizeDown_f( void ) {
	trap_Cvar_SetValue( "cg_viewSize", cg_viewSize->integer - 10 );
}

//============================================================================

/*
==================
SCR_Init
==================
*/
void SCR_Init (void)
{
	cg_viewSize =			trap_Cvar_Get( "cg_viewSize", "100", CVAR_ARCHIVE );
	cg_showFPS =			trap_Cvar_Get( "cg_showFPS", "0", CVAR_ARCHIVE );
	cg_showHUD =			trap_Cvar_Get( "cg_showHUD", "1", CVAR_ARCHIVE );
	cg_draw2D =				trap_Cvar_Get( "cg_draw2D", "1", 0 );
	cg_centerTime =			trap_Cvar_Get( "cg_centerTime", "2.5", 0 );
	cg_debugLoading =		trap_Cvar_Get( "cg_debugLoading", "0", CVAR_ARCHIVE );
	cg_weaponlist =			trap_Cvar_Get( "cg_weaponlist", "1", CVAR_ARCHIVE );

	cg_crosshair =			trap_Cvar_Get( "cg_crosshair", "1", CVAR_ARCHIVE );
	cg_crosshair_size =		trap_Cvar_Get( "cg_crosshair_size", "32", CVAR_ARCHIVE );
	cg_crosshair_color =	trap_Cvar_Get( "cg_crosshair_color", "255 255 255", CVAR_ARCHIVE );
	cg_crosshair_color->modified = qtrue;

	cg_crosshair_strong =		trap_Cvar_Get( "cg_crosshair_strong", "0", CVAR_ARCHIVE );
	cg_crosshair_strong_size =	trap_Cvar_Get( "cg_crosshair_strong_size", "32", CVAR_ARCHIVE );
	cg_crosshair_strong_color =	trap_Cvar_Get( "cg_crosshair_strong_color", "255 255 255", CVAR_ARCHIVE );
	cg_crosshair_strong_color->modified = qtrue;

	// wsw : jal
	cg_clientHUD =			trap_Cvar_Get( "cg_clientHUD", "default", CVAR_ARCHIVE );
	cg_showTimer =			trap_Cvar_Get( "cg_showTimer", "1", CVAR_ARCHIVE );
	cg_showSpeedMeter =		trap_Cvar_Get( "cg_showSpeedMeter", "0", CVAR_ARCHIVE );
	cg_showPointedPlayer =	trap_Cvar_Get( "cg_showPointedPlayer", "1", CVAR_ARCHIVE );
	cg_showWeaponSelect =	trap_Cvar_Get( "cg_showWeaponSelect", "1", CVAR_ARCHIVE );	// wsw : pb : display a little box around selected weapon in weaponlist
	cg_showTeamLocations =	trap_Cvar_Get( "cg_showTeamLocations", "1", CVAR_ARCHIVE );

	cg_showPlayerNames =		trap_Cvar_Get( "cg_showPlayerNames", "1", CVAR_ARCHIVE );
	cg_showPlayerNames_alpha =	trap_Cvar_Get( "cg_showPlayerNames_alpha", "0.4", CVAR_ARCHIVE );
	cg_showPlayerNames_zfar =	trap_Cvar_Get( "cg_showPlayerNames_zfar", "824", CVAR_ARCHIVE );
	cg_showPlayerNames_xoffset = trap_Cvar_Get( "cg_showPlayerNames_xoffset", "0", CVAR_ARCHIVE );
	cg_showPlayerNames_yoffset = trap_Cvar_Get( "cg_showPlayerNames_yoffset", "16", CVAR_ARCHIVE );

	cg_scoreboardFont = trap_Cvar_Get( "cg_scoreboardFont", DEFAULT_FONT_SCOREBOARD, CVAR_ARCHIVE );
	cg_scoreboardWidthScale = trap_Cvar_Get( "cg_scoreboardWidthScale", "1.0", CVAR_ARCHIVE );

	// wsw : hud debug prints
	cg_debug_HUD =				trap_Cvar_Get( "cg_debug_HUD", "0", 0 );
//
// register our commands
//
	trap_Cmd_AddCommand( "sizeup", SCR_SizeUp_f );
	trap_Cmd_AddCommand( "sizedown", SCR_SizeDown_f );
	trap_Cmd_AddCommand( "help_hud", Cmd_CG_PrintHudHelp_f );
}

/*
==================
SCR_Shutdown
==================
*/
void SCR_Shutdown (void)
{
	trap_Cmd_RemoveCommand( "sizeup" );
	trap_Cmd_RemoveCommand( "sizedown" );
	trap_Cmd_RemoveCommand( "help_hud" );
}


/*
================
SCR_ParseValue
================
*/
int SCR_ParseValue( char **s )
{
	int		index;
	char	*token;

	token = COM_Parse( s );
	if( !token[0] )
		return 0;
	else if( token[0] != '%' )
		return atoi( token );

	index = atoi( token + 1 );
	if( index < 0 || index >= PS_MAX_STATS )
		CG_Error( "Bad stat index: %i", index );

	return cg.frame.playerState.stats[index];
}

/*
==============
SCR_DrawQuadEffect - wsw : jal
==============
*/
void SCR_DrawQuadEffect( void )
{
	vec4_t	color;
	player_state_t *ps = &cg.frame.playerState;

	// effects are not updated for spectator entities
	if( ( ps->pmove.pm_type == PM_SPECTATOR && cg.chasedNum == cgs.playerNum ) ||
	    !( cg_entities[cg.chasedNum+1].current.effects & EF_QUAD ) )
		return;

	//if( GS_Gametype_IsTeamBased( cg.frame.playerState.stats[STAT_GAMETYPE] ) ) 
	{
		color[0] = 1.0f;
		color[1] = 0.1f;
		color[2] = 0.1f;
		color[3] = 0.3f;
		trap_R_DrawStretchPic( 0, 0, cgs.vidWidth, cgs.vidHeight, 0, 0, 1, 1, color, cgs.shaderWhite );
		return;
	}
}

//==============
//SCR_DrawPlayerNames
// shows player names at their feets.
// TODO: Healthbars on teammates.
//==============
void SCR_DrawPlayerNames( void ) 
{
	static vec4_t	whiteTransparent = { 1.0f, 1.0f, 1.0f, 0.5f };
	int			i;
	centity_t	*cent;
	vec2_t		coords;
	vec3_t		dir;
	float		dist;
	trace_t		trace;
	float		fadeFrac;
	float		alpha;

	if( !cg_showPlayerNames->integer || cg_showPlayerNames_zfar->value <= 0.0f )
		return;

	// don't draw when scoreboard is up
	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD )
		return;

	alpha = cg_showPlayerNames_alpha->value;
	if( alpha <= 0.0f ) return;
	if( alpha > 1.0f ) alpha = 1.0f;

	for( i = 0; i < MAX_CLIENTS; i++ ) 
	{
		if( i == cgs.playerNum || i == cg.chasedNum )
			continue;

		//don't draw the name if the name is being drawn as pointed player
		if( cg_showPointedPlayer->integer &&
			cg.pointedNum && cg.pointedNum == i+1 )
			continue;

		cent = cg_entities + i + 1;
		if( cent->serverFrame != cg.frame.serverFrame )
			continue;

		if( !cent->current.modelindex )
			continue;

		// Kill if behind the view
		VectorSubtract( cent->ent.origin, cg.refdef.vieworg, dir );
		dist = VectorNormalize2( dir, dir ) * cg.view_fracDistFOV;
		if( dist > cg_showPlayerNames_zfar->value )
			continue;

		if( DotProduct( dir, cg.v_forward ) < 0 )
			continue;

		fadeFrac = (cg_showPlayerNames_zfar->value - dist) / (cg_showPlayerNames_zfar->value * 0.25f);
		if( fadeFrac > 1.0f )
			fadeFrac = 1.0f;
		
		whiteTransparent[3] = alpha * fadeFrac;
		
		CG_Trace( &trace, cg.refdef.vieworg, vec3_origin, vec3_origin, cent->ent.origin, cg.chasedNum+1, MASK_OPAQUE );
		if( trace.fraction == 1.0f ) {
			// find the 3d point in 2d screen
			trap_R_TransformVectorToScreen( &cg.refdef, cent->ent.origin, coords );
			trap_SCR_DrawStringLen( coords[0]+cg_showPlayerNames_xoffset->integer,
				(cg.refdef.height - coords[1])+cg_showPlayerNames_yoffset->integer,
				ALIGN_LEFT_MIDDLE, cgs.clientInfo[i].name, 12, cgs.fontSystemSmall, whiteTransparent );
		}
	}
}

/*
==============
SCR_DrawNet
==============
*/
void SCR_DrawNet( int x, int y, int w, int h, int align, vec4_t color )
{
	int incomingAcknowledged, outgoingSequence;

	trap_NET_GetCurrentState( &incomingAcknowledged, &outgoingSequence );
	if( outgoingSequence - incomingAcknowledged < CMD_BACKUP-1 )
		return;
	x = CG_HorizontalAlignForWidth( x, align, w );
	y = CG_VerticalAlignForHeight( y, align, h );
	trap_R_DrawStretchPic( x, y, w, h, 0, 0, 1, 1, color, CG_MediaShader(cgs.media.shaderNet) );
}

/*
=================
SCR_DrawCrosshair
=================
*/
void SCR_DrawCrosshair( int x, int y, int align )
{
	static vec4_t chColor = { 255, 255, 255, 255 };
	static vec4_t chColorStrong = { 255, 255, 255, 255 };
	int rgbcolor;
	int selected_weapon;

	if( cg_crosshair->modified ) {
		if( cg_crosshair->integer >= NUM_CROSSHAIRS || cg_crosshair->integer < 0 )
			trap_Cvar_Set( "cg_crosshair", va("%i", 0 ) ); 
		cg_crosshair->modified = qfalse;
	}

	if( cg_crosshair_size->modified ) {
		if( cg_crosshair_size->integer < 0 || cg_crosshair_size->integer > 2000 )
			trap_Cvar_Set( "cg_crosshair_size", va("%i", 32 ) ); 
		cg_crosshair_size->modified = qfalse;
	}

	if( cg_crosshair_color->modified ) {
		rgbcolor = COM_ReadColorRGBString( cg_crosshair_color->string );
		if( rgbcolor != -1 ) {
			Vector4Set( chColor, COLOR_R(rgbcolor), COLOR_G(rgbcolor), COLOR_B(rgbcolor), 255 ); 
		} else {
			Vector4Set( chColor, 255, 255, 255, 255 );
		}
		cg_crosshair_color->modified = qfalse;
	}

	if( cg_crosshair_strong->modified ) {
		if( cg_crosshair_strong->integer >= NUM_CROSSHAIRS || cg_crosshair_strong->integer < 0 )
			trap_Cvar_Set( "cg_crosshair_strong", va("%i", 0 ) );
		cg_crosshair_strong->modified = qfalse;
	}

	if( cg_crosshair_strong_size->modified ) {
		if( cg_crosshair_strong_size->integer < 0 || cg_crosshair_strong_size->integer > 2000 )
			trap_Cvar_Set( "cg_crosshair_strong_size", va("%i", 32 ) ); 
		cg_crosshair_strong_size->modified = qfalse;
	}

	if( cg_crosshair_strong_color->modified ) {
		rgbcolor = COM_ReadColorRGBString( cg_crosshair_strong_color->string );
		if( rgbcolor != -1 ) {
			Vector4Set( chColorStrong, COLOR_R(rgbcolor), COLOR_G(rgbcolor), COLOR_B(rgbcolor), 255 ); 
		} else {
			Vector4Set( chColorStrong, 255, 255, 255, 255 );
		}
		cg_crosshair_strong_color->modified = qfalse;
	}

	if( cg.latched_weapon == WEAP_NONE ) {
		selected_weapon = cg.frame.playerState.stats[STAT_WEAPON_ITEM];
	} else {
		selected_weapon = cg.latched_weapon;
	}
	if( selected_weapon < WEAP_GUNBLADE || selected_weapon >= WEAP_TOTAL )
		selected_weapon = WEAP_GUNBLADE;

	if( cg.frame.playerState.weaponlist[selected_weapon-1][1] && cg_crosshair_strong->integer ) // strong
	{
		x = CG_HorizontalAlignForWidth( x, align, cg_crosshair_strong_size->integer );
		y = CG_VerticalAlignForHeight( y, align, cg_crosshair_strong_size->integer );

		trap_R_DrawStretchPic( x, y, cg_crosshair_strong_size->integer, cg_crosshair_strong_size->integer,
			0, 0, 1, 1, chColorStrong,
			CG_MediaShader(cgs.media.shaderCrosshair[cg_crosshair_strong->integer]) );
	}
	else // weak
	{
		if( !cg_crosshair->integer )
			return;

		x = CG_HorizontalAlignForWidth( x, align, cg_crosshair_size->integer );
		y = CG_VerticalAlignForHeight( y, align, cg_crosshair_size->integer );

		trap_R_DrawStretchPic( x, y, cg_crosshair_size->integer, cg_crosshair_size->integer,
			0, 0, 1, 1, chColor, CG_MediaShader(cgs.media.shaderCrosshair[cg_crosshair->integer]) );
	}
}

//================
//CG_DrawSpeed
//================
/*static*/ void CG_DrawSpeed( int x, int y, int align, struct mufont_s *font, vec4_t color )
{
	static double dieciseisavo = (1.0/16.0);
	player_state_t	*ps;
	vec3_t	hvel;

	if( !cg.frameTime || !cg_showSpeedMeter->integer )
		return;

	// do a rough one. Just the distance between ops and ps
	// find the previous frame to interpolate from
	ps = &cg.frame.playerState;
	VectorSet( hvel, ps->pmove.velocity[0]*dieciseisavo, ps->pmove.velocity[1]*dieciseisavo, 0 );

	trap_SCR_DrawString( x, y, align, va( "speed:%4i", (int)VectorLength( hvel ) ), font, color );
}

//================
//CG_DrawFPS
//================
/*static */void CG_DrawFPS( int x, int y, int align, struct mufont_s *font, vec4_t color )
{
#define FPSSAMPLESCOUNT 32
#define FPSSAMPLESMASK (FPSSAMPLESCOUNT-1)
	static int fps;
	static double oldtime;
	static int oldframecount;
	static float frameTimes[FPSSAMPLESCOUNT];
	static float avFrameTime;
	int i;
	double t;

	if( !cg.frameTime || !cg_showFPS->integer )
		return;

	frameTimes[cg.frameCount & FPSSAMPLESMASK] = cg.frameTime;
	if ( cg_showFPS->integer != 2 ) {
		for( avFrameTime = 0.0f, i = 0; i < FPSSAMPLESCOUNT; i++ ) {
			avFrameTime += frameTimes[cg.frameCount & FPSSAMPLESMASK];
		}
		avFrameTime /= FPSSAMPLESCOUNT;
		fps = (int)(1.0f/avFrameTime);
	} else {
		t = cg.realTime * 0.001f;

		if ( (t - oldtime) >= 0.25 ) {	// updates 4 times a second
			fps = (cg.frameCount - oldframecount) / (t - oldtime) + 0.5;
			oldframecount = cg.frameCount;
			oldtime = t;
		}
	}

	trap_SCR_DrawString( x, y, align, va( "%3ifps", fps ), font, color );
}

//================
//CG_DrawClock
//================
/*static*/ void CG_DrawClock( int x, int y, int align, struct mufont_s *font, vec4_t color )
{
	if( !cg_showTimer->integer )
		return;

	if( cg.frame.match.state < MATCH_STATE_WARMUP || cg.frame.match.state > MATCH_STATE_PLAYTIME )
		return;

	if( cg_showTimer->integer == 2 ) {
		trap_SCR_DrawString( x, y, align, va( "%02i:%02i", cg.frame.match.clock_mins, cg.frame.match.clock_secs ),
			font, color );
	} else {
		trap_SCR_DrawString( x, y, align,
			va( "%02i:%02i:%02d", cg.frame.match.clock_mins, cg.frame.match.clock_secs, cg.frame.match.clock_msecs ),
			font, color );
	}
}

//================
//CG_DrawPointed
//================
static unsigned int point_remove_time;
static int pointed_health;
static int pointed_armor;
static int pointed_armor_type;
/*static*/ void CG_DrawPointed( int x, int y, int align, struct mufont_s *font, vec4_t color )
{
	float	alpha;
	vec2_t	coords;
	static vec4_t	alphacolor, alphagreen = { 0, 1, 0, 0 }, alphared = { 1, 0, 0, 0 }, alphayellow = { 1, 1, 0, 0 }, alphamagenta= {1, 0, 1, 1};
	int		barwidth = trap_SCR_strWidth("_",font, 0) * 8; // size of 8 characters
	int		barheight = trap_SCR_strHeight(font) * 0.25; // quarter of a character height
	int		barseparator = barheight * 0.333;

	//never draw pointed in 3rd person
	if( cg.thirdPerson || !cg_showPointedPlayer->integer )
		return;

	// don't draw when scoreboard is up
	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD )
		return;
	
	if( cg.frame.playerState.stats[STAT_POINTED_PLAYER] )
	{
		qboolean mega = qfalse;
		cg.pointedNum = cg.frame.playerState.stats[STAT_POINTED_PLAYER];
		//pointed_health = cg.frame.playerState.stats[STAT_POINTED_TEAMPLAYER];
		point_remove_time = cg.time + 150;

		pointed_health = 3.2 * (cg.frame.playerState.stats[STAT_POINTED_TEAMPLAYER] &0x1F);
		mega = cg.frame.playerState.stats[STAT_POINTED_TEAMPLAYER]&0x20;
		pointed_armor = 5 * (cg.frame.playerState.stats[STAT_POINTED_TEAMPLAYER]>>6 &0x3F);
		pointed_armor_type = (cg.frame.playerState.stats[STAT_POINTED_TEAMPLAYER]>>12 &0xF);
		if( mega ) {
			pointed_health += 100;
			if( pointed_health > 200 )
				pointed_health = 200;
		}
	}

	if( point_remove_time <= cg.time ) {
		cg.pointedNum = 0;
	}

	if( !cg.pointedNum )
		return;

	// if 1 show at player head, if 2 at hud defined position
	if( cg_showPointedPlayer->integer < 2 ) {
		centity_t *cent;
		vec3_t headorigin;
		cent = &cg_entities[cg.pointedNum];
		if( cent->serverFrame != cg.frame.serverFrame )
			return;

		VectorSet( headorigin, cent->ent.origin[0], cent->ent.origin[1], cent->ent.origin[2]+playerbox_stand_maxs[2]+16 );

		// find the 3d point in 2d screen
		trap_R_TransformVectorToScreen( &cg.refdef, headorigin, coords );
		x = coords[0];
		y = cg.refdef.height - coords[1];
		align = ALIGN_CENTER_BOTTOM;
	}

	alpha = (float)( point_remove_time - cg.time ) / 150.0f;
	if( alpha > 1.0f ) alpha = 1.0f;
	alphacolor[0] = color[0];
	alphacolor[1] = color[1];
	alphacolor[2] = color[2];
	alphacolor[3] = color[3] * alpha;

	trap_SCR_DrawString( x, y - trap_SCR_strHeight(font), align,
		cgs.clientInfo[ cg.pointedNum - 1 ].name,
		font, alphacolor );

	if( !pointed_health )
		return;

	//we have to aling first, then draw as left top, cause we want the bar to grow from left to right
	x = CG_HorizontalAlignForWidth( x, align, barwidth );
	y = CG_VerticalAlignForHeight( y, align, barheight);

	//assign hud alpha to colored bar
	alphagreen[3] = alphared[3] = alphayellow[3] = alphamagenta[3] = color[3] * alpha;
	//make the white background more transparent than the hud defined color
	alphacolor[3] *= 0.5f;
	//background
	CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight*3, 100, 100, alphacolor );
	//health
	y += barseparator;
	if( pointed_health > 100 ) {
		alphagreen[3] = alphamagenta[3] = 1.0f;
		CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, 100, 100, alphagreen );
		CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, pointed_health - 100, 100, alphamagenta );
		alphagreen[3] = alphamagenta[3] = alphared[3];
	} else {
		CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, pointed_health, 100, alphagreen );
	}

	if( pointed_armor ) {
		y += barseparator + barheight;
		if( pointed_armor_type == 3 ) // red
			CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, pointed_armor, 150, alphared );
		else if( pointed_armor_type == 2 ) // yellow
			CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, pointed_armor, 150, alphayellow );
		else  // green
			CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, barwidth, barheight, pointed_armor, 150, alphagreen );
	}
}

//================
//SCR_DrawTeamInfo
//================
void SCR_DrawTeamInfo( int x, int y, int align, struct mufont_s *font, vec4_t color )
{
	char	string[128];
	int		team;
	int		teammate;
	char	*ptr, *tok, *loc;
	int		height, pixheight;
	int		locationTag;
#ifdef VSAYS
	centity_t *cent;
#endif

	if( !(cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_TEAMTAB) )
		return;

	// don't draw when scoreboard is up
	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD )
		return;

	if( !cg_showHUD->integer|| !cg_showTeamLocations->integer )
		return;

	team = cg.frame.playerState.stats[STAT_TEAM];
	if( team <= TEAM_PLAYERS || team >= GS_MAX_TEAMS 
		|| !GS_Gametype_IsTeamBased(cg.frame.playerState.stats[STAT_GAMETYPE])
		|| cg.frame.playerState.stats[STAT_GAMETYPE] == GAMETYPE_DUEL )
		return;

	// time to parse the teaminfo string
	if( !strlen(cg.teaminfo) )
		return;

	height = trap_SCR_strHeight( font );

	// find longest line
	ptr = cg.teaminfo;
	pixheight = 0;
	while( ptr ) {
		tok = COM_Parse( &ptr );
		if( !tok || !strlen(tok) )
			break;

		teammate = atoi(tok);
		if( teammate < 0 || teammate >= MAX_CLIENTS )
			break;

		loc = COM_Parse( &ptr );
		if( !loc || !strlen(loc) )
			break;

		locationTag = atoi(loc);
		if( locationTag >= MAX_LOCATIONS )
			locationTag = 0;

		pixheight += height;
	}

	y = CG_VerticalAlignForHeight( y, align, pixheight );

	ptr = cg.teaminfo;
	while( ptr ) {
		tok = COM_Parse( &ptr );
		if( !tok || !strlen(tok) )
			return;

		teammate = atoi(tok);
		if( teammate < 0 || teammate >= MAX_CLIENTS )
			return;

		loc = COM_Parse( &ptr );
		if( !loc || !strlen(loc) )
			return;

		locationTag = atoi(loc);
		if( locationTag >= MAX_LOCATIONS )
			locationTag = 0;

		Q_snprintfz( string, sizeof(string), "%s%s %s%s", cgs.clientInfo[teammate].name, S_COLOR_WHITE,
				cgs.configStrings[CS_LOCATIONS+locationTag], S_COLOR_WHITE );

		// draw the head-icon in the case this player has one
#ifdef VSAYS
		cent = &cg_entities[teammate+1];
		if( cent->localEffects[LOCALEFFECT_VSAY_HEADICON_TIMEOUT] > cg.time &&
			cent->localEffects[LOCALEFFECT_VSAY_HEADICON] > 0 && cent->localEffects[LOCALEFFECT_VSAY_HEADICON] < VSAY_TOTAL ) {
			trap_R_DrawStretchPic( CG_HorizontalAlignForWidth( x, align, height ),
				CG_VerticalAlignForHeight( y, align, height ),
				height, height, 0, 0, 1, 1,
				color, CG_MediaShader(cgs.media.shaderVSayIcon[cent->localEffects[LOCALEFFECT_VSAY_HEADICON]]) );
		}
#endif

		trap_SCR_DrawString( x + height * ( align % 3 == 0 ), y, align, string, font, color );

		y += height; 
	}
}

//=============================================================================

//================
//CG_LoadLayout
//================
void CG_LoadLayout( char *s ) 
{
	Q_strncpyz( cg.layout, s, sizeof(cg.layout) );
}

//================
//CG_InGameMenu 
//================
void CG_InGameMenu( void ) 
{
	static char menuparms[MAX_STRING_CHARS];
	int is_challenger = 0, needs_ready = 0;
	int gametype = cg.frame.playerState.stats[STAT_GAMETYPE];
	int realteam;
	
	realteam = (cg.frame.playerState.pmove.pm_type == PM_CHASECAM) ? TEAM_SPECTATOR : cg.frame.playerState.stats[STAT_TEAM];

	if( cgs.serverRules.has_challengers && realteam == TEAM_SPECTATOR )
		is_challenger = (cg.frame.valid && (cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_CHALLENGER));

	if( cg.frame.match.state <= MATCH_STATE_WARMUP && realteam != TEAM_SPECTATOR )
		needs_ready = !(cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_READY);

	Q_snprintfz( menuparms, sizeof(menuparms), "menu_game %i %i %i %i %i \"Warsow %s\"",
		gametype ,
		GS_Gametype_IsTeamBased(gametype),
		realteam,
		(realteam == TEAM_SPECTATOR)?(cgs.serverRules.has_challengers + is_challenger):0,
		needs_ready,
		GS_Gametype_ShortName(gametype) );

	trap_Cmd_ExecuteText( EXEC_APPEND, menuparms );
}

//=============================================================================

//==============
//SCR_DrawLoading
//==============
void SCR_DrawLoading( void )
{
	char str[MAX_QPATH];
	struct mufont_s *font = cgs.fontSystemBig;

	if( cgs.configStrings[CS_MAPNAME][0] ) {
		// draw a level shot
		trap_R_DrawStretchPic( 0, 0, cgs.vidWidth, cgs.vidHeight, 
			0, 0, 1, 1, colorWhite, cgs.shaderLevelshot );
		trap_R_DrawStretchPic( 0, 0, cgs.vidWidth, cgs.vidHeight, 
			0, 0, 2.5, 2, colorWhite, cgs.shaderLevelshotDetail );

		// draw map name
		Q_snprintfz( str, sizeof(str), "Loading %s", cgs.configStrings[CS_MAPNAME] );
		trap_SCR_DrawString( cgs.vidWidth/2, 16, ALIGN_CENTER_TOP, str, font, colorWhite );

		// what we're loading at the moment
		if( cg.loadingstring[0] ) {
			if ( cg.loadingstring[0] == '-' && !cg.loadingstring[1])
				Q_strncpyz( str, "awaiting snapshot...", sizeof(str) );
			else
				Q_snprintfz( str, sizeof(str), "loading... %s", cg.loadingstring );
			trap_SCR_DrawString( cgs.vidWidth/2, 96, ALIGN_CENTER_TOP, str, font, colorWhite );
		}

		if( cg.checkname[0] ) {
			char prefix[] = "filename: ";
			Q_snprintfz( str, sizeof(str), "%s%s", prefix, cg.checkname );
			trap_SCR_DrawString( cgs.vidWidth/2, cgs.vidHeight - 20, ALIGN_CENTER_TOP, str, font, colorWhite );
		}
	}
}


//================
//CG_LoadingString
//================
void CG_LoadingString( char *str )
{
	Q_strncpyz( cg.loadingstring, str, sizeof(cg.loadingstring) );
	trap_R_UpdateScreen ();
}

//================
//CG_LoadingFilename
//================
void CG_LoadingFilename( char *str )
{
	if ( !cg_debugLoading->integer ) {
		cg.checkname[0] = 0;
		return;
	}

	Q_strncpyz( cg.checkname, str, sizeof(cg.checkname) );
	trap_R_UpdateScreen ();
}

//==============
//SCR_TileClearRect
//
//This repeats tile graphic to fill the screen around a sized down
//refresh window.
//==============
void SCR_TileClearRect( int x, int y, int w, int h, struct shader_s *shader )
{
	float iw, ih;

	iw = 1.0f / 64.0;
	ih = 1.0f / 64.0;

	trap_R_DrawStretchPic( x, y, w, h, x*iw, y*ih, (x+w)*iw, (y+h)*ih, colorWhite, shader );
}

/*
==============
SCR_TileClear

Clear any parts of the tiled background that were drawn on last frame
==============
*/
void SCR_TileClear( void )
{
	int		w, h;
	int		top, bottom, left, right;
	struct shader_s *backTile;

	if ( cg_viewSize->integer == 100 )
		return;		// full screen rendering

	w = cgs.vidWidth;
	h = cgs.vidHeight;

	top = scr_vrect.y;
	bottom = top + scr_vrect.height-1;
	left = scr_vrect.x;
	right = left + scr_vrect.width-1;

	backTile = CG_MediaShader ( cgs.media.shaderBackTile );

	// clear above view screen
	SCR_TileClearRect( 0, 0, w, top, backTile );

	// clear below view screen
	SCR_TileClearRect( 0, bottom, w, h - bottom, backTile );

	// clear left of view screen
	SCR_TileClearRect( 0, top, left, bottom - top + 1, backTile );

	// clear left of view screen
	SCR_TileClearRect( right, top, w - right, bottom - top + 1, backTile );
}


//===============================================================

/*
================
SCR_ExecuteLayoutString
================
*/
void SCR_ExecuteLayoutString( char *s )
{
	int		x, y, w, h;
	int		align;
	int		value;
	char	*token;
	int		width;
	int		index, stack;
	qboolean skip;
	qboolean flash;
	vec4_t	color, flashColor;

	if( !s || !s[0] )
		return;

	x = y = 0;
	w = h = 1;
	align = ALIGN_LEFT_TOP;
	width = 3;
	Vector4Copy( colorWhite, color );
	Vector4Copy( colorWhite, flashColor );
	stack = 0;
	skip = qfalse;
	flash = qfalse; // wsw : jal : we aren't using flashes

	while( s ) {
		token = COM_Parse( &s );

		if( stack > 0 ) {
			if( !Q_stricmp( token, "endif") ) {
				stack--;
				if( !stack )
					skip = qfalse;
				continue;
			}
		}

		if( !Q_stricmp( token, "if" ) ) {
			if( skip || !SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifeq" ) ) {
			if( skip || SCR_ParseValue( &s ) != SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifbit" ) ) {
			if( skip || !(SCR_ParseValue( &s ) & SCR_ParseValue( &s )) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifle" ) ) {
			if( skip || SCR_ParseValue( &s ) > SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifl" ) ) {
			if( skip || SCR_ParseValue( &s ) >= SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifge" ) ) {
			if( skip || SCR_ParseValue( &s ) < SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !Q_stricmp( token, "ifg" ) ) {
			if( skip || SCR_ParseValue( &s ) <= SCR_ParseValue( &s ) ) {
				stack++;
				skip = qtrue; // skip to endif
			}
		} else if( !skip ) {
			if( !Q_stricmp( token, "xl" ) ) {
				x = (int)(SCR_ParseValue(&s)*cgs.vidWidth/800);
			} else if( !Q_stricmp( token, "xr" ) ) {
				x = cgs.vidWidth + (int)(SCR_ParseValue(&s)*cgs.vidWidth/800);
			} else if( !Q_stricmp( token, "xv" ) ) {
				x = cgs.vidWidth / 2 + (int)(SCR_ParseValue(&s)*cgs.vidWidth/800);
			} else if( !Q_stricmp( token, "yt" ) ) {
				y = (int)(SCR_ParseValue(&s)*cgs.vidHeight/600);
			} else if( !Q_stricmp( token, "yb" ) ) {
				y = cgs.vidHeight + (int)(SCR_ParseValue(&s)*cgs.vidHeight/600);
			} else if( !Q_stricmp( token, "yv" ) ) {
				y = cgs.vidHeight / 2 + (int)(SCR_ParseValue(&s)*cgs.vidHeight/600);
			} else if( !Q_stricmp( token, "align" ) ) {
				align = (SCR_ParseValue(&s)-1)+3*(SCR_ParseValue(&s)-1);
			} else if( !Q_stricmp( token, "size" ) ){
				w = (int)(SCR_ParseValue( &s )*cgs.vidWidth/800);
				h = (int)(SCR_ParseValue( &s )*cgs.vidHeight/600);
			} else if( !Q_stricmp( token, "color" ) ) {
				color[0] = atof( COM_Parse( &s ) ); clamp( color[0], 0, 1 );
				color[1] = atof( COM_Parse( &s ) ); clamp( color[1], 0, 1 );
				color[2] = atof( COM_Parse( &s ) ); clamp( color[2], 0, 1 );
				color[3] = atof( COM_Parse( &s ) ); clamp( color[3], 0, 1 );
			} else if( !Q_stricmp( token, "flashColor" ) ) {
				flashColor[0] = atof( COM_Parse( &s ) ); clamp( flashColor[0], 0, 1 );
				flashColor[1] = atof( COM_Parse( &s ) ); clamp( flashColor[1], 0, 1 );
				flashColor[2] = atof( COM_Parse( &s ) ); clamp( flashColor[2], 0, 1 );
				flashColor[3] = atof( COM_Parse( &s ) ); clamp( flashColor[3], 0, 1 );
			} else if( !Q_stricmp( token, "pic" ) ) {	// draw a pic from a stat number
				value = SCR_ParseValue( &s );
				if( value < 0 || value >= MAX_IMAGES )
					CG_Error( "Pic >= MAX_IMAGES" );
				if( cgs.configStrings[CS_IMAGES + value][0] ) {
					x = CG_HorizontalAlignForWidth( x, align, w );
					y = CG_VerticalAlignForHeight( y, align, h );
					trap_R_DrawStretchPic( x, y, w, h, 0, 0, 1, 1, color, trap_R_RegisterPic(cgs.configStrings[CS_IMAGES+value]) );
				}
			} else if( !Q_stricmp( token, "picn" ) ) {	// draw a pic from a name
				x = CG_HorizontalAlignForWidth( x, align, w );
				y = CG_VerticalAlignForHeight( y, align, h );
				trap_R_DrawStretchPic ( x, y, w, h, 0, 0, 1, 1, colorWhite, trap_R_RegisterPic( COM_Parse ( &s ) ) );
			} else if( !Q_stricmp( token, "model" ) ) {	// draw a model from a stat number
				struct model_s *model;

				value = SCR_ParseValue( &s );
				if( value < 0 || value >= MAX_MODELS )
					CG_Error( "Model >= MAX_MODELS" );
				model = value > 1 ? CG_RegisterModel( cgs.configStrings[CS_MODELS+value] ) : NULL; // skelmod
				CG_DrawHUDModel( x, y, align, w, h, model, NULL, atof( COM_Parse ( &s ) ) );
			} else if( !Q_stricmp( token, "modeln" ) ) {// draw a model from a name
				struct model_s *model;
				struct shader_s *shader;

				model = CG_RegisterModel( COM_Parse( &s ) );	// skelmod
				token = COM_Parse( &s );
				shader = Q_stricmp( token, "NULL" ) ? trap_R_RegisterPic ( token ) : NULL;
				CG_DrawHUDModel( x, y, align, w, h, model, shader, atof( COM_Parse ( &s ) ) );
			} else if( !Q_stricmp( token, "num" ) ) {	// draw a number
				width = SCR_ParseValue( &s );
				value = SCR_ParseValue( &s );
				CG_DrawHUDField( x, y, align, flash ? flashColor : color, 32, width, value );
			} else if( !Q_stricmp( token, "num2" ) ) {	// draw a number
				width = SCR_ParseValue( &s );
				value = SCR_ParseValue( &s );
				CG_DrawHUDField( x, y, align, flash ? flashColor : color, 16, width, value );
			} else if( !Q_stricmp( token, "curtime" ) ) {	// draw a time value
				char str[32];
				int m, sec, d;
				value = cg.frame.playerState.stats[STAT_RACE_TIME];
				if (value)
				{
					// NO MORE WORKING
					//if (cg.frame.playerState.stats[STAT_RACE_STARTED] )
						value = (cg.time/100) - value;
					d = value % 10;
					sec = (value / 10) % 60;
					m = (value / 600);
					Q_snprintfz( str, 32, "%02i:%02i:%01i", m, sec, d );
					trap_SCR_DrawString( x, y, align, str, cgs.fontSystemMedium, colorWhite );
				}
			} else if( !Q_stricmp( token, "matchbesttime" ) ) {	// draw a time value
				char str[32];
				int m, sec, d;
				value = cg.frame.playerState.stats[STAT_RACE_MATCHBESTTIME];
				if (value)
				{
					d = value % 10;
					sec = (value / 10) % 60;
					m = (value / 600);
					Q_snprintfz( str, 32, "%02i:%02i:%01i", m, sec, d );
					trap_SCR_DrawString( x, y, align, str, cgs.fontSystemMedium, colorWhite );
				}
			} else if( !Q_stricmp( token, "plrbesttime" ) ) {	// draw a time value
				char str[32];
				int m, sec, d;
				value = cg.frame.playerState.stats[STAT_RACE_PLAYERBESTTIME];
				if (value)
				{
					d = value % 10;
					sec = (value / 10) % 60;
					m = (value / 600);
					Q_snprintfz( str, 32, "%02i:%02i:%01i", m, sec, d );
					trap_SCR_DrawString( x, y, align, str, cgs.fontSystemMedium, colorWhite );
				}
			} else if( !Q_stricmp( token, "speed" ) ) {
				CG_DrawSpeed( x, y, align, cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "fps" ) ) {
				CG_DrawFPS( x, y, align, cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "clock" ) ) {
				CG_DrawClock( x, y, align, cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "match_message" ) && cg_showhelp->integer ) {
				trap_SCR_DrawString( x, y, align, cg.matchmessage, cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "pointing" ) ) {
				CG_DrawPointed( x, y, align, cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "stat_string" ) ) {
				index = SCR_ParseValue( &s );
				if( index < 0 || index >= MAX_CONFIGSTRINGS )
					CG_Error( "Bad stat_string index" );
				trap_SCR_DrawString( x, y, align, cgs.configStrings[index], cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "string" ) ) {
				trap_SCR_DrawString( x, y, align, COM_Parse( &s ), cgs.fontSystemMedium, flash ? flashColor : color );
			} else if( !Q_stricmp( token, "rect" ) ) {
				CG_DrawHUDRect( x, y, align, w, h, SCR_ParseValue( &s ), SCR_ParseValue( &s ), flash ? flashColor : color );
			// ByMiK
			} else if( !Q_stricmp( token, "weaponlist" ) ) {
				// TODO: align support
				int ix, iy, wx, wy, sx, sy;
				ix = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidWidth/800 );
				iy = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidHeight/600 );
				wx = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidWidth/800 );
				wy = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidHeight/600 );
				sx = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidWidth/800 );
				sy = (int)(atoi ( COM_Parse ( &s ) ) * cgs.vidHeight/600 );
				SCR_DrawWeaponList( x, y, ix, iy, wx, wy, sx, sy );
			} else if( !Q_stricmp( token, "playername" ) ) { // wsw : jal
				value = SCR_ParseValue( &s );
				if( value > 0 && value <= MAX_CLIENTS && cgs.clientInfo[value-1].name )
					trap_SCR_DrawString( x, y, align, cgs.clientInfo[value-1].name, cgs.fontSystemMedium, flash ? flashColor : color );
			}
		}
	}
}

/*
================
SCR_DrawStats

The status bar is a small layout program that
is based on the stats array
================
*/
void SCR_DrawStats( void )
{
	if( !cg_showHUD->integer )
		return;

	CG_ExecuteLayoutProgram( cg.statusBar );
}

/*
================
SCR_DrawLayout
================
*/
void SCR_DrawLayout( void ) 
{
	SCR_ExecuteLayoutString( cg.layout );
}

/*
================
SCR_DrawInventory
================
*/
#define	DISPLAY_ITEMS	17

void SCR_DrawInventory( void )
{
	int		i, j;
	int		num, selected_num, item;
	int		index[MAX_ITEMS];
	char	string[1024];
	int		x, y;
	char	binding[1024];
	char	*bind, *buf;
	int		selected;
	int		top;
	int		lineHeight = trap_SCR_strHeight( cgs.fontSystemSmall );

	selected = cg.frame.playerState.stats[STAT_SELECTED_ITEM];

	num = 0;
	selected_num = 0;
	for( i = 0; i < MAX_ITEMS; i++ ) {
		if( i == selected )
			selected_num = num;
		if( cg.inventory[i] ) {
			index[num] = i;
			num++;
		}
	}

	// determine scroll point
	top = selected_num - DISPLAY_ITEMS / 2;
	if( num - top < DISPLAY_ITEMS )
		top = num - DISPLAY_ITEMS;
	if( top < 0 )
		top = 0;

	x = (cgs.vidWidth-256) / 2;
	y = (cgs.vidHeight-240) / 2;

	y += 24;
	x += 24;

	trap_SCR_DrawString( x, y, ALIGN_LEFT_TOP, "hotkey ### item", cgs.fontSystemSmall, colorWhite );
	trap_SCR_DrawString( x, y+lineHeight, ALIGN_LEFT_TOP, "------ --- ----", cgs.fontSystemSmall, colorWhite );

	y += lineHeight * 2;
	for( i = top; i < num && i < top+DISPLAY_ITEMS; i++ ) {
		item = index[i];

		// search for a binding
		Q_snprintfz( binding, sizeof(binding), "use %s", cgs.configStrings[CS_ITEMS+item] );
		bind = "";

		for( j = 0; j < 256; j++ ) {
			buf = trap_Key_GetBindingBuf( j );
			if( buf && !Q_stricmp( buf, binding ) ) {
				bind = trap_Key_KeynumToString( j );
				break;
			}
		}

		Q_snprintfz( string, sizeof(string), "%6s %3i %s", bind, cg.inventory[item], cgs.configStrings[CS_ITEMS+item] );

		if ( item != selected ) {
			trap_SCR_DrawString( x, y, ALIGN_LEFT_TOP, string, cgs.fontSystemSmall, colorWhite );
		} else {	// draw a blinky cursor by the selected item
			if ( (int)(cg.realTime*10) & 1 )
				trap_SCR_DrawString( x-trap_SCR_strWidth("*",cgs.fontSystemSmall,1), y, ALIGN_LEFT_TOP, "*", cgs.fontSystemSmall, colorYellow );
			trap_SCR_DrawString( x, y, ALIGN_LEFT_TOP, string, cgs.fontSystemSmall, colorYellow );
		}

		y += lineHeight;
	}
}


//=======================================================
void SCR_DrawScoreboard( void );	// wsw : jal : predefined layouts for scoreboards

/*
==================
SCR_Draw2D
==================
*/
void SCR_Draw2D( void )
{
	if( !cg_draw2D->integer )
		return;

	if( cg_clientHUD->modified ) {
		CG_LoadStatusBar();
		cg_clientHUD->modified = qfalse;
	}

	SCR_DrawQuadEffect();

	SCR_DrawPlayerNames();

	SCR_DrawStats();

	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_GENERIC )
		SCR_DrawLayout();
	if( cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_INVENTORY )
		SCR_DrawInventory();
	if( (cg.frame.playerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SCOREBOARD && !cg.demoPlaying) ||
		(cg.demoPlaying && (cg.demoShowScoreboard || cg.frame.match.state > MATCH_STATE_PLAYTIME ||
		(cg.frame.playerState.pmove.pm_type != PM_SPECTATOR && cg.frame.playerState.stats[STAT_HEALTH] <= 0))) )
		SCR_DrawScoreboard ();

	SCR_CheckDrawCenterString();
}
