/*
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_scoreboard.c -- fixed scoreboard layouts for gametypes


#include "cg_local.h"

extern cvar_t	*cg_scoreboardStats;

extern cvar_t	*cg_scoreboardFont;
extern cvar_t	*cg_scoreboardWidthScale;

vec4_t	whiteTransparent = { 1.0f, 1.0f, 1.0f, 0.5f };

vec4_t	colorSCBBackground = { 0.25f, 0.25f, 0.25f, 1.0f };
#define SCB_BACKGROUND_ALPHA 0.25f

#define SCB_TEAMNAME_PIXELWIDTH (128 * cg_scoreboardWidthScale->value)
#define SCB_PLAYERNAME_PIXELWIDTH (96 * cg_scoreboardWidthScale->value)
#define SCB_MEDIUMFIELD_PIXELWIDTH (72 * cg_scoreboardWidthScale->value)
#define SCB_SMALLFIELD_PIXELWIDTH (36 * cg_scoreboardWidthScale->value)
#define SCB_TINYFIELD_PIXELWIDTH (24 * cg_scoreboardWidthScale->value)

int SCR_ParseValue( char **s );

/*
================
SCR_DrawBigNumbersString
================
*/
void SCR_DrawBigNumbersString( int x, int y, int fontwidth, int fontheight, char *string, vec4_t color )
{
	unsigned int	i;
	int				num;

	if( !string || !string[0] )
		return;
	
	for( i=0; i<strlen(string); i++ ) 
	{
		if( string[i] == '-' ) {
			num = STAT_MINUS;
		} else {
			num = string[i] - '0';
			if( num < 0 || num > 9 ) num = 0;
		}

		trap_R_DrawStretchPic ( x + (fontwidth*i), y, fontwidth, fontheight, 0, 0, 1, 1, color, CG_MediaShader(cgs.media.sbNums[num]) );
	}
}

/*
================
SCR_PingColor
print pings -> ping colors : 0-49 = green, 50-99 = yellow, 100+ = red
================
*/
vec4_t *SCR_SetPingColor( int ping )
{
	if ( ping >= 0 && ping < 50 )
		return &colorGreen;
	else if ( ping >= 50 && ping < 90 )
		return &colorYellow;
	else if ( ping >= 90 && ping < 120 )
		return &colorOrange;
	else
		return &colorRed;
}

//===============================================================
//
//		GENERIC SCOREBOARD TABS
//
//===============================================================

// it handles all the information for all gametypes, but not all of them
// will set every field of it.
typedef enum {
	SCBTAB_PLAYERFFA,
	SCBTAB_PLAYERRACE,
	SCBTAB_PLAYERDUEL,
	SCBTAB_PLAYERTDM,
	SCBTAB_PLAYERCTF,
	SCBTAB_SPECTATOR,
	SCBTAB_CHALLENGER,
	SCBTAB_CONNECTING,
	MAX_SCBTABS
}scbtype_t;
typedef struct
{
	scbtype_t	type;
	int			playernum;
	int			score;
	int			ping;
	int			kills;
	int			deaths;
	int			suicides;
	int			teamfrags;
	int			team;
	int			ready;
	qboolean	waiting;

	int			min;
	int			sec;
	int			msec;
}scb_playertab_t;

static scb_playertab_t scb_players[MAX_CLIENTS];
static int scb_playercount;

// player stats
static int scb_player_stats[2*(WEAP_TOTAL-WEAP_GUNBLADE)]; // weak strong

//================
//SCB_ColorForPlayer
//================
static vec4_t playerColorTemp;
float *SCB_ColorForPlayer( scb_playertab_t *player ) {
	if( player->team && player->team >= TEAM_RED ) {
		GS_TeamColor( player->team, playerColorTemp );
	} else {
		VectorCopy( colorSCBBackground, playerColorTemp );
	}

	//set alpha
	if( player->playernum == cg.chasedNum ) {
		playerColorTemp[3] = 0.8f;
	} else {
		playerColorTemp[3] = SCB_BACKGROUND_ALPHA;
	}

	return playerColorTemp;
}

void SCB_ParsePlayerStats( char **s ) {
	if( s && *s )
	{
		int i,j;
		memset( scb_player_stats, 0, sizeof(scb_player_stats) );
		j=0;
		for( i = WEAP_GUNBLADE; i < WEAP_TOTAL; i++ )
		{
			// weak
			if( i == WEAP_LASERGUN || i == WEAP_ELECTROBOLT ) {
				scb_player_stats[j] = SCR_ParseValue( s );
			} else {
				scb_player_stats[j] = -1;
			}
			j++;
			// strong
			if( i != WEAP_SHOCKWAVE )
				scb_player_stats[j] = SCR_ParseValue( s );
			else
				scb_player_stats[j] = -1;
			j++;
		}
	}
}

void SCB_ParseFFAPlayerTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_PLAYERFFA;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].score = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].ready = SCR_ParseValue( s );
		scb_playercount++;
	}
}

void SCB_ParseRACEPlayerTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_PLAYERRACE;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].min = SCR_ParseValue( s );
		scb_players[scb_playercount].sec = SCR_ParseValue( s );
		scb_players[scb_playercount].msec = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].ready = SCR_ParseValue( s );
		scb_playercount++;
	}
}

void SCB_ParseDUELPlayerTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_PLAYERDUEL;
		scb_players[scb_playercount].team = SCR_ParseValue( s );
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].score = SCR_ParseValue( s );
		scb_players[scb_playercount].kills = SCR_ParseValue( s );
		scb_players[scb_playercount].deaths = SCR_ParseValue( s );
		scb_players[scb_playercount].suicides = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_playercount++;
	}
}

void SCB_ParseTDMPlayerTab( char **s, int currentTeam ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_PLAYERTDM;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].score = SCR_ParseValue( s );
		scb_players[scb_playercount].kills = SCR_ParseValue( s );
		scb_players[scb_playercount].deaths = SCR_ParseValue( s );
		scb_players[scb_playercount].suicides = SCR_ParseValue( s );
		scb_players[scb_playercount].teamfrags = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].ready = SCR_ParseValue( s );
		scb_players[scb_playercount].team = currentTeam;
		scb_playercount++;
	}
}

void SCB_ParseCTFPlayerTab( char **s, int currentTeam ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_PLAYERCTF;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].score = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].ready = SCR_ParseValue( s );
		scb_players[scb_playercount].team = currentTeam;
		scb_playercount++;
	}
}

void SCB_ParseSpectatorTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_SPECTATOR;
		scb_players[scb_playercount].team = TEAM_SPECTATOR;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].waiting = qfalse;
		scb_playercount++;
	}
}

void SCB_ParseConnectingPlayerTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_CONNECTING;
		scb_players[scb_playercount].team = TEAM_SPECTATOR;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = 0;
		scb_players[scb_playercount].waiting = qfalse;
		scb_playercount++;
	}
}

void SCB_ParseChallengerTab( char **s ) {
	if( s && *s ) {
		memset( &scb_players[scb_playercount], 0, sizeof(scb_playertab_t) );
		scb_players[scb_playercount].type = SCBTAB_CHALLENGER;
		scb_players[scb_playercount].team = TEAM_SPECTATOR;
		scb_players[scb_playercount].playernum = SCR_ParseValue( s );
		scb_players[scb_playercount].ping = SCR_ParseValue( s );
		scb_players[scb_playercount].waiting = qtrue;
		scb_playercount++;
	}
}

#define SCB_FFA_PLAYERTAB_PIXELWIDTH (SCB_PLAYERNAME_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_MEDIUMFIELD_PIXELWIDTH)
int SCB_DrawFFAPlayerTab( scb_playertab_t *player, int x, int y, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];
	int				xoffset = 0;
	vec4_t			*pingcolor;
	size_t			len;

	//draw the box
	trap_R_DrawStretchPic( x + xoffset, 
		y, SCB_FFA_PLAYERTAB_PIXELWIDTH,	//width
		trap_SCR_strHeight( font ),	//height
		0, 0, 1, 1, SCB_ColorForPlayer(player), cgs.shaderWhite );

	//print name
	Q_snprintfz( string, sizeof(string), "%s", cgs.clientInfo[player->playernum].name );
	len = trap_SCR_StrlenForWidth( string, font, SCB_PLAYERNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( x+xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_PLAYERNAME_PIXELWIDTH;

	//print score
	Q_snprintfz( string, sizeof(string), "%3i", player->score );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorYellow );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print ping
	Q_snprintfz( string, sizeof(string), "%3i", player->ping );
	pingcolor = SCR_SetPingColor( player->ping );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, *pingcolor );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print ready
	Q_snprintfz( string, sizeof(string), "%s", (cg.frame.match.state == MATCH_STATE_WARMUP && player->ready) ? "READY" : "" );
	len = trap_SCR_StrlenForWidth( string, font, SCB_MEDIUMFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorGreen );
	//xoffset += SCB_MEDIUMFIELD_PIXELWIDTH;

	return trap_SCR_strHeight( font );
}

#define SCB_RACE_PLAYERTAB_PIXELWIDTH (SCB_PLAYERNAME_PIXELWIDTH+SCB_MEDIUMFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_MEDIUMFIELD_PIXELWIDTH)
int SCB_DrawRACEPlayerTab( scb_playertab_t *player, int x, int y, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];
	vec4_t			*pingcolor;
	int				len, xoffset = 0;

	//draw the box
	trap_R_DrawStretchPic( x + xoffset, 
		y, SCB_RACE_PLAYERTAB_PIXELWIDTH,	//width
		trap_SCR_strHeight( font ),	//height
		0, 0, 1, 1, SCB_ColorForPlayer(player), cgs.shaderWhite );

	//print name
	Q_snprintfz( string, sizeof(string), "%s", cgs.clientInfo[player->playernum].name );
	len = trap_SCR_StrlenForWidth( string, font, SCB_PLAYERNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( x, y, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_PLAYERNAME_PIXELWIDTH;

	//print best lap time
	Q_snprintfz( string, sizeof(string),va("%02i:%02i.%1i", player->min, player->sec, player->msec) );
	len = trap_SCR_StrlenForWidth( string, font, SCB_MEDIUMFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorYellow );
	xoffset += SCB_MEDIUMFIELD_PIXELWIDTH;
	
	//print ping
	Q_snprintfz( string, sizeof(string), "%3i", player->ping );
	pingcolor = SCR_SetPingColor( player->ping );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, *pingcolor );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	//print in_race
	Q_snprintfz( string, sizeof(string), "%s", player->ready==1 ? "IN RACE" : "" );
	len = trap_SCR_StrlenForWidth( string, font, SCB_MEDIUMFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorGreen );
	xoffset += SCB_MEDIUMFIELD_PIXELWIDTH;

	return trap_SCR_strHeight( font );
}

int SCB_DrawDUELPlayerTab( scb_playertab_t *player, int x, int y, qboolean isright, struct mufont_s *font )
{
	vec4_t	tabcolor;
	vec4_t  *pingcolor;
	char	string[MAX_STRING_CHARS];
	int		xname, alignname;
	int		xscore;
	int		scorewidth;
	int		xstats;
	int		len, xoffset = 0, yoffset = 0;
	int		scoreCharSize = 48;
	struct	mufont_s *tittleFont = cgs.fontSystemBig;

	if( !player || player->team < TEAM_RED || player->team > GS_MAX_TEAMS )
		return 0;

	GS_TeamColor( player->team, tabcolor );
	tabcolor[3] = SCB_BACKGROUND_ALPHA;//transparent

	Q_snprintfz( string, sizeof(string), "%i", player->score );
	scorewidth = scoreCharSize * strlen(string);

	if( !isright ) //left side tab
	{
		xscore = x - (scorewidth + 8); // 8 is a space between tabs
		xname = x - (scorewidth + 16);
		alignname = ALIGN_RIGHT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( 0, y+scoreCharSize, x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, tabcolor, cgs.shaderWhite );

		xoffset = -(16+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH);
		xstats = x + xoffset; 
	} else { //right side tab

		xscore = x + 8;
		xname = x + scorewidth + 16;
		alignname = ALIGN_LEFT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( x, y+scoreCharSize, cg.refdef.width - x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, tabcolor, cgs.shaderWhite );

		xoffset = 16;
		xstats = x + xoffset; 
	}

	yoffset = 0;

	// print score box
	SCR_DrawBigNumbersString( xscore, y+yoffset, scoreCharSize, scoreCharSize, va("%i",player->score), colorWhite );
	yoffset += scoreCharSize;

	// print name
	Q_snprintfz( string, sizeof(string), "%s%s", cgs.clientInfo[player->playernum].name, S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, tittleFont, SCB_TEAMNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( xname, y+yoffset, alignname, string, len, tittleFont, colorWhite );

	trap_SCR_DrawString( xstats, y+yoffset, ALIGN_LEFT_TOP, "kill death suic ping", font, colorMdGrey );
	yoffset+=trap_SCR_strHeight( font );

	//print kills
	Q_snprintfz(string, sizeof(string), "%4i", player->kills);
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y+yoffset, ALIGN_LEFT_TOP, string, len, font, colorYellow );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print deaths
	Q_snprintfz(string, sizeof(string), "%4i", player->deaths);
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y+yoffset, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print suicides
	Q_snprintfz(string, sizeof(string), "%4i", player->suicides);
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y+yoffset, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print ping
	Q_snprintfz(string, sizeof(string), "%4i", player->ping);
	pingcolor = SCR_SetPingColor( player->ping );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y+yoffset, ALIGN_LEFT_TOP, string, len, font, *pingcolor );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	//print ready in green
	if( cg.frame.match.state == MATCH_STATE_WARMUP && player->ready ) {
		if (!isright) {
			trap_SCR_DrawString( x, y, ALIGN_RIGHT_TOP, "R ", font, colorGreen );
		} else {
			trap_SCR_DrawString( x + xoffset, y, ALIGN_LEFT_TOP, " R", font, colorGreen );
		}
	}

	return yoffset;
}

#define SCB_TDM_PLAYERTAB_PIXELWIDTH (SCB_PLAYERNAME_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH)
int SCB_DrawTDMPlayerTab( scb_playertab_t *player, int x, int y, qboolean isright, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];
	vec4_t			*pingcolor;
	int				eff;
	int				len, xoffset = 0;

	//draw the box
	trap_R_DrawStretchPic( x + xoffset, 
		y, SCB_TDM_PLAYERTAB_PIXELWIDTH,	//width
		trap_SCR_strHeight( font ),	//height
		0, 0, 1, 1, SCB_ColorForPlayer(player), cgs.shaderWhite );

	//print name
	Q_snprintfz( string, sizeof(string), "%s", cgs.clientInfo[player->playernum].name );
	len = trap_SCR_StrlenForWidth( string, font, SCB_PLAYERNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_PLAYERNAME_PIXELWIDTH;

	//we align right, so offset before writting
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	// print score in yellow
	Q_snprintfz( string, sizeof(string), "%4i%s", player->score, S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_RIGHT_TOP, string, len, font, colorYellow );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	// print kills
	Q_snprintfz( string, sizeof(string), "%4i%s", player->kills, S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_RIGHT_TOP, string, len, font, colorWhite );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;

	// print deaths
	Q_snprintfz( string, sizeof(string), "%4i%s", player->deaths, S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_RIGHT_TOP, string, len, font, colorWhite );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	// print netto frags in orange
	eff = player->kills - (player->deaths + player->teamfrags);
	Q_snprintfz( string, sizeof(string), "%4i%s", eff , S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_RIGHT_TOP, string, len, font, (eff<0)?colorRed:colorOrange );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	// print pings
	Q_snprintfz( string, sizeof(string), "%4i%s", player->ping, S_COLOR_WHITE );
	pingcolor = SCR_SetPingColor( player->ping );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_RIGHT_TOP, string, len, font, *pingcolor );
	//xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	//print ready in green
	if( cg.frame.match.state == MATCH_STATE_WARMUP && player->ready ) {
		if (!isright) {
			trap_SCR_DrawString( x, y, ALIGN_RIGHT_TOP, "R ", font, colorGreen );
		} else {
			trap_SCR_DrawString( x + xoffset, y, ALIGN_LEFT_TOP, " R", font, colorGreen );
		}
	}

	return trap_SCR_strHeight( font );
}

#define SCB_CTF_PLAYERTAB_PIXELWIDTH (SCB_PLAYERNAME_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH+SCB_SMALLFIELD_PIXELWIDTH)
int SCB_DrawCTFPlayerTab( scb_playertab_t *player, int x, int y, qboolean isright, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];
	vec4_t			*pingcolor;
	int				len, xoffset = 0;
	
	//draw the box
	trap_R_DrawStretchPic( x + xoffset, 
		y, SCB_CTF_PLAYERTAB_PIXELWIDTH,	//width
		trap_SCR_strHeight( font ),	//height
		0, 0, 1, 1, SCB_ColorForPlayer(player), cgs.shaderWhite );

	//print name
	Q_snprintfz( string, sizeof(string), "%s", cgs.clientInfo[player->playernum].name );
	len = trap_SCR_StrlenForWidth( string, font, SCB_PLAYERNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( x, y, ALIGN_LEFT_TOP, string, len, font, colorWhite );
	xoffset += SCB_PLAYERNAME_PIXELWIDTH;
	
	// print score in yellow
	Q_snprintfz( string, sizeof(string), "%4i", player->score );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, colorYellow );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	// print pings
	Q_snprintfz( string, sizeof(string), "%4i", player->ping );
	pingcolor = SCR_SetPingColor( player->ping );
	len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
	trap_SCR_DrawStringLen( x + xoffset, y, ALIGN_LEFT_TOP, string, len, font, *pingcolor );
	xoffset += SCB_SMALLFIELD_PIXELWIDTH;
	
	//print ready in green
	if( cg.frame.match.state == MATCH_STATE_WARMUP && player->ready ) {
		if (!isright) {
			trap_SCR_DrawString( x, y, ALIGN_RIGHT_TOP, "R ", font, colorGreen );
		} else {
			trap_SCR_DrawString( x + xoffset, y, ALIGN_LEFT_TOP, " R", font, colorGreen );
		}
	}

	return trap_SCR_strHeight( font );
}

int SCB_DrawChallengerTab( scb_playertab_t *player, int x, int y, int align, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];

	if( !player || player->type != SCBTAB_CHALLENGER )
		return 0;

	// wsw : pb : fix scoreboard color bug
	Q_snprintfz( string, sizeof(string), "%s%s%s %i%s", S_COLOR_WHITE, cgs.clientInfo[player->playernum].name,
		S_COLOR_WHITE, player->ping, S_COLOR_WHITE );
	trap_SCR_DrawString( x, y, align, string, font, colorWhite );

	return trap_SCR_strHeight( font );
}
int SCB_DrawSpectatorTab( scb_playertab_t *player, int x, int y, int align, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];

	if( !player || player->type != SCBTAB_SPECTATOR )
		return 0;

	Q_snprintfz( string, sizeof(string), "%s%s%s %s%i%s", S_COLOR_WHITE, cgs.clientInfo[player->playernum].name,
		S_COLOR_WHITE, SCR_SetPingColor(player->ping), player->ping, S_COLOR_WHITE );
	trap_SCR_DrawString( x, y, align, string, font, colorWhite );

	return trap_SCR_strHeight( font );
}
int SCB_DrawConnectingPlayerTab( scb_playertab_t *player, int x, int y, int align, struct mufont_s *font ) {
	static char 	string[MAX_STRING_CHARS];

	if( !player || player->type != SCBTAB_CONNECTING )
		return 0;

	Q_snprintfz( string, sizeof(string), "%s%s %s%s%s", S_COLOR_WHITE, cgs.clientInfo[player->playernum].name,
		S_COLOR_GREY, "connecting", S_COLOR_WHITE );
	trap_SCR_DrawString( x, y, align, string, font, colorWhite );

	return trap_SCR_strHeight( font );
}
void SCB_DrawSpectators( int x, int y ) {
	struct mufont_s *font = cgs.fontSystemSmall;
	int i, xoffset, yoffset;
	qboolean challengers = qfalse, spectators = qfalse;

	// Center the Waiting to play
	xoffset = 0;
	yoffset = 0;

	// check if there is anyone in the challengers list
	for( i = 0; i < scb_playercount; i++ ) {
		if( scb_players[i].type == SCBTAB_CHALLENGER ) {
			yoffset += trap_SCR_strHeight( font );
			challengers = qtrue;
			break;
		}
	}

	if( challengers ) {
		trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, "Challengers", font, colorMdGrey );
		yoffset += trap_SCR_strHeight( font );
		// draw challengers tabs
		for( i = 0; i < scb_playercount; i++ ) {
			if( scb_players[i].type == SCBTAB_CHALLENGER ) {
				yoffset += SCB_DrawChallengerTab( &scb_players[i], x + xoffset, y + yoffset, ALIGN_CENTER_TOP, font );
			}
		}
	}

	// check if there is anyone in the spectators list
	for( i = 0; i < scb_playercount; i++ ) {
		if( scb_players[i].type == SCBTAB_SPECTATOR || scb_players[i].type == SCBTAB_CONNECTING ) {
			spectators = qtrue;
			yoffset += trap_SCR_strHeight( font );
			break;
		}
	}

	if( spectators ) {
		trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, "Spectators", font, colorMdGrey );
		yoffset += trap_SCR_strHeight( font );
		// draw spectator tabs
		for( i = 0; i < scb_playercount; i++ ) {
			if( scb_players[i].type == SCBTAB_CONNECTING ) {
				yoffset+=SCB_DrawConnectingPlayerTab( &scb_players[i], x + xoffset, y + yoffset, ALIGN_CENTER_TOP, font );
			}
			else if( scb_players[i].type == SCBTAB_SPECTATOR ){
				yoffset+=SCB_DrawSpectatorTab( &scb_players[i], x + xoffset, y + yoffset, ALIGN_CENTER_TOP, font );
			}
		}
	}
}

int SCB_DrawPlayerStats( int x, int y )
{
	struct mufont_s *font = cgs.fontSystemSmall;
	int xoffset, yoffset, lines;
	int i, j, num_weapons, len, weap, xpos, width, done;
	gitem_t *it;
	char string[MAX_STRING_CHARS];
	vec4_t color = { 0.5, 0.5, 0.5, 0.5f };

	// dont display stats
	if( !cg_scoreboardStats->integer )
		return 0;

	// total number of weapon
	num_weapons = WEAP_TOTAL-WEAP_GUNBLADE;

	width = (SCB_TINYFIELD_PIXELWIDTH + 2 * SCB_SMALLFIELD_PIXELWIDTH) * 2 + SCB_SMALLFIELD_PIXELWIDTH;

	xpos = -8 * SCB_TINYFIELD_PIXELWIDTH/2;

	// Center the box
	xoffset = xpos;
	yoffset = trap_SCR_strHeight( font );

	// Room for header, it's actually written later if we have atleast one stat
	yoffset += trap_SCR_strHeight( font );

	lines = 0;
	for( i = 0; i < num_weapons; )
	{
		xoffset = xpos;

		// two weapons per line
		for( j = 0, done = 0; done < 2 && i + j < num_weapons; j++ )
		{
			weap = WEAP_GUNBLADE + i + j;

			if( scb_player_stats[2*(i+j)] == -1 && scb_player_stats[2*(i+j)+1] == -1 )
				continue;

			it = GS_FindItemByTag( weap );

			// short name
			//trap_R_DrawStretchPic( x + xoffset, y + yoffset, trap_SCR_strHeight(font), trap_SCR_strHeight(font),
			//	0, 0, 1, 1, colorWhite, CG_MediaShader(cgs.media.shaderWeaponIcon[i+j]) );
			Q_snprintfz( string, sizeof(string), "%s%2s", it->color, it->short_name);
			len = trap_SCR_StrlenForWidth( string, font, SCB_TINYFIELD_PIXELWIDTH );
			trap_SCR_DrawStringLen( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, string, len, font, colorWhite );
			xoffset += SCB_TINYFIELD_PIXELWIDTH;

			if( weap == WEAP_LASERGUN || weap == WEAP_ELECTROBOLT )
			{
				// weak percent
				if( scb_player_stats[2*(i+j)] != -1 ) {
					Q_snprintfz( string, sizeof(string), "%2d%c", scb_player_stats[2*(i+j)], '%');
					len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
					trap_SCR_DrawStringLen( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, string, len, font, colorWhite );
				}
				xoffset += SCB_SMALLFIELD_PIXELWIDTH;

				// strong percent
				if( scb_player_stats[2*(i+j)+1] != -1 ) {
					Q_snprintfz( string, sizeof(string), "%2d%c", scb_player_stats[2*(i+j)+1], '%');
					len = trap_SCR_StrlenForWidth( string, font, SCB_SMALLFIELD_PIXELWIDTH );
					trap_SCR_DrawStringLen( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, string, len, font, colorWhite );
				}
				xoffset += SCB_SMALLFIELD_PIXELWIDTH;
			}
			else
			{
				Q_snprintfz( string, sizeof(string), "%2d%c", scb_player_stats[2*(i+j)+1], '%');
				len = trap_SCR_StrlenForWidth( string, font, 2*SCB_SMALLFIELD_PIXELWIDTH );
				trap_SCR_DrawStringLen( x + xoffset + SCB_SMALLFIELD_PIXELWIDTH, y + yoffset,
					ALIGN_CENTER_TOP, string, len, font, colorWhite );
				xoffset += 2*SCB_SMALLFIELD_PIXELWIDTH;
			}

			// separator
			xoffset += SCB_SMALLFIELD_PIXELWIDTH;
			done++;
		}

		// next line
		if( done > 0 ) {
			lines++;
			yoffset += trap_SCR_strHeight( font );
		}

		i += j;
	}

	if( lines )
	{
		// if we drow anything, draw header and box too
		xoffset = xpos;
		yoffset = trap_SCR_strHeight( font );

		// header
		len = trap_SCR_StrlenForWidth( "Weapon stats", font, width );
		trap_SCR_DrawStringLen( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, "Weapon stats", len, font, colorMdGrey );
		yoffset += trap_SCR_strHeight( font );

		// box
		trap_R_DrawStretchPic( x + xoffset - SCB_TINYFIELD_PIXELWIDTH/2, y + yoffset, width + SCB_TINYFIELD_PIXELWIDTH,
			lines * trap_SCR_strHeight(font), 0, 0, 1, 1, color, cgs.shaderWhite );

		return (trap_SCR_strHeight(font) * (2+lines));
	}
	else
	{
		return 0;
	}
}

//===============================================================
//
//		DUEL SCOREBOARD
//
//===============================================================

//================
//SCR_DrawPlayerTab_DUEL
//================

//================
//SCR_UpdateDUELScoreboard
//================
void SCR_UpdateDUELScoreboard( char *s )
{
	char	*token;

	//take out the layout id
	token = COM_Parse( &s );
	if( !token ) return;

	scb_playercount = 0;

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

		if( !Q_stricmp( token, "&g" ) ) { //read game name tab
		}
		else if( !Q_stricmp( token, "&p" ) ) { //read a player tab
			SCB_ParseDUELPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&w" ) ) { // read a waiting list player tab
			SCB_ParseChallengerTab( &s );
		}
		else if( !Q_stricmp( token, "&s" ) ) { // read a spectator tab
			SCB_ParseSpectatorTab( &s );
		}
		else if( !Q_stricmp( token, "&c" ) ) {
			SCB_ParseConnectingPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&z" ) ) {
			SCB_ParsePlayerStats( &s );
		}
	}
}

//================
//SCR_DrawDUELScoreboard
//================
void SCR_DrawDUELScoreboard( int x, int y, struct mufont_s *font )
{
	int			i, xoffset, yoffset, ymaxoffset = 0;
	qboolean	rightside = qfalse;

	//draw player tabs
	for( i = 0; i < scb_playercount; i++ )
	{
		yoffset = 0;
		if( rightside ) {
			xoffset = 8;
		} else {
			xoffset = -8;
		}

		if( scb_players[i].type == SCBTAB_PLAYERDUEL )
			yoffset += SCB_DrawDUELPlayerTab( &scb_players[i], x + xoffset, y + yoffset, rightside, font );
		if( yoffset > ymaxoffset )
			ymaxoffset = yoffset;
			
		rightside = !rightside;
	}

	xoffset = 0;

	yoffset = ymaxoffset + trap_SCR_strHeight(font);
	yoffset+=SCB_DrawPlayerStats( x + xoffset, y + yoffset );
	SCB_DrawSpectators( x + xoffset, y + yoffset );
}


//===============================================================
//
//		DM SCOREBOARD
//
//===============================================================

//================
//SCR_UpdateDMScoreboard
//================
void SCR_UpdateDMScoreboard( char *s )
{
	char	*token;

	//take out the layout id
	token = COM_Parse( &s );
	if( !token ) return;

	scb_playercount = 0;

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

		if( !Q_stricmp( token, "&g" ) ) //read game name tab
		{
		}
		else if( !Q_stricmp( token, "&p" ) ) { //read a player tab
			SCB_ParseFFAPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&w" ) ) { // read a waiting list player tab
			SCB_ParseChallengerTab( &s );
		}
		else if( !Q_stricmp( token, "&s" ) ) { //read a player tab
			SCB_ParseSpectatorTab( &s );
		}
		else if( !Q_stricmp( token, "&c" ) ) {
			SCB_ParseConnectingPlayerTab( &s );
		}		
		else if( !Q_stricmp( token, "&z" ) ) {
			SCB_ParsePlayerStats( &s );
		}
	}
}


//================
//SCR_DrawDMScoreboard
//================
void SCR_DrawDMScoreboard( int x, int y, struct mufont_s *font )
{
	int 		i, xoffset, yoffset;

	yoffset = 0;
	xoffset = -SCB_FFA_PLAYERTAB_PIXELWIDTH/2;

	//draw players
	for( i = 0; i < scb_playercount; i++ ) {
		if( scb_players[i].type == SCBTAB_PLAYERFFA )
			yoffset += SCB_DrawFFAPlayerTab( &scb_players[i], x + xoffset, y + yoffset, font );
	}

	xoffset = 0;

	yoffset += trap_SCR_strHeight(font);
	yoffset+=SCB_DrawPlayerStats( x + xoffset, y + yoffset );
	SCB_DrawSpectators( x + xoffset, y + yoffset );
}

//===============================================================
//
//		RACE SCOREBOARD
//
//===============================================================

//================
//SCR_UpdateDMScoreboard
//================
void SCR_UpdateRACEScoreboard( char *s )
{
	char	*token;

	//take out the layout id
	token = COM_Parse( &s );
	if( !token ) return;

	scb_playercount = 0;

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

		if( !Q_stricmp( token, "&g" ) ) { //read game name tab
		}
		else if( !Q_stricmp( token, "&p" ) ) { //read a player tab
			SCB_ParseRACEPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&w" ) ) { // read a waiting list player tab
			SCB_ParseChallengerTab( &s );
		}
		else if( !Q_stricmp( token, "&s" ) ) { //read a player tab
			SCB_ParseSpectatorTab( &s );
		}
		else if( !Q_stricmp( token, "&c" ) ) {
			SCB_ParseConnectingPlayerTab( &s );
		}
	}
}

//================
//SCR_DrawRACEScoreboard
//================
void SCR_DrawRACEScoreboard( int x, int y, struct mufont_s *font )
{
	int i, xoffset = 0, yoffset;

	//yoffset at middle of the screen
	yoffset = 0;
	xoffset = -(SCB_FFA_PLAYERTAB_PIXELWIDTH/2);

	//draw players
	for( i = 0; i < scb_playercount; i++ )
	{
		if( scb_players[i].type == SCBTAB_PLAYERRACE )
			yoffset+=SCB_DrawRACEPlayerTab( &scb_players[i], x + xoffset, y + yoffset, font );
	}

	yoffset += trap_SCR_strHeight(font);
	SCB_DrawSpectators( x, y + yoffset );
}

//===============================================================
//
//		TDM SCOREBOARD
//
//===============================================================

typedef struct
{
	int			teamnum;
	int			teamscore;
	qboolean	updated;

}cg_tdm_scoreboard_teams_t;

static cg_tdm_scoreboard_teams_t tdmteams[GS_MAX_TEAMS];

int SCR_DrawTeamTab( int team, int x, int y, qboolean isright, struct mufont_s *font )
{
	vec4_t	teamcolor;
	char	string[MAX_STRING_CHARS];
	int	xname, alignname;
	int	xscore;
	int	scorewidth, scoreCharSize = 48;
	int	xstats;
	int	i, len;
	int	yoffset=0;
	struct mufont_s *tittleFont = cgs.fontSystemBig;

	GS_TeamColor( team, teamcolor );

	Q_snprintfz(string, sizeof(string), "%i", tdmteams[team].teamscore  );
	scorewidth = scoreCharSize * strlen(string);

	teamcolor[3] = SCB_BACKGROUND_ALPHA; // make transparent

	if( !isright ) //left side tab
	{
		xscore = x - (scorewidth + 8); // 8 is a space between tabs
		xname = x - (scorewidth + 16);
		alignname = ALIGN_RIGHT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( 0, y+scoreCharSize, x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, teamcolor, cgs.shaderWhite );

		xstats = x - 16 - SCB_TDM_PLAYERTAB_PIXELWIDTH;
		
	} else { //right side tab
		
		xscore = x + 8;
		xname = x + scorewidth + 16;
		alignname = ALIGN_LEFT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( x, y+scoreCharSize, cg.refdef.width - x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, teamcolor, cgs.shaderWhite );

		xstats = x + 16;
	}

	teamcolor[3] = 1.0f; // make solid

	yoffset = 0;

	// print score box
	SCR_DrawBigNumbersString( xscore, y+yoffset, scoreCharSize, scoreCharSize, va("%i",tdmteams[team].teamscore), colorWhite );
	yoffset += scoreCharSize;

	// print name
	Q_snprintfz( string, sizeof(string), "%s%s", GS_TeamName(team), S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, tittleFont, SCB_TEAMNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( xname, y+yoffset, alignname, string, len, tittleFont, colorWhite );

	// print players header
	{
		int xheaderoffset = 0;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_LEFT_TOP, "name", font, colorMdGrey );
		xheaderoffset += SCB_PLAYERNAME_PIXELWIDTH;
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;// we align right, so, offset before writting
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "pnts", font, colorMdGrey );
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "kill", font, colorMdGrey );
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "dead", font, colorMdGrey );
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, " eff", font, colorMdGrey );
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "ping", font, colorMdGrey );
		//xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;

		yoffset += trap_SCR_strHeight( font );
	}

	// print all players of this team
	for( i = 0; i < scb_playercount; i++ ) {
		if( scb_players[i].team == team ) {
			yoffset += SCB_DrawTDMPlayerTab( &scb_players[i], xstats, y+yoffset, isright, font );
		}
	}

	return yoffset;
}

//================
//SCR_UpdateTDMScoreboard
//================
void SCR_UpdateTDMScoreboard( char *s )
{
	char	*token;
	int	i, cteam = 0;

	//take out the layout id
	token = COM_Parse( &s );
	if( !token ) return;

	for(i=0; i < GS_MAX_TEAMS; i++)
		tdmteams[i].updated = qfalse;

	scb_playercount = 0;

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

		if( !Q_stricmp( token, "&t" ) ) //read a team tab
		{
			cteam = SCR_ParseValue( &s );
			if( cteam < 0 || cteam > GS_MAX_TEAMS ) 
				CG_Error("Invalid team value in CTF Scoreboard" );

			tdmteams[cteam].teamnum = cteam;
			tdmteams[cteam].teamscore = SCR_ParseValue( &s );
			tdmteams[cteam].updated = qtrue;
		}
		else if( !Q_stricmp( token, "&p" ) ) { //read a player tab
			SCB_ParseTDMPlayerTab( &s, cteam );
		}
		else if( !Q_stricmp( token, "&w" ) ) { // read a waiting list player tab
			SCB_ParseChallengerTab( &s );
		}
		else if( !Q_stricmp( token, "&s" ) ) { //read a spectator tab
			SCB_ParseSpectatorTab( &s );
		}
		else if( !Q_stricmp( token, "&c" ) ) {
			SCB_ParseConnectingPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&z" ) ) {
			SCB_ParsePlayerStats( &s );
		}
	}
}

//================
//SCR_DrawTDMScoreboard
//================
void SCR_DrawTDMScoreboard( int x, int y, struct mufont_s *font )
{
	int 		i, xoffset = 0, yoffset, ymaxoffset = 0;
	qboolean 	rightside = qfalse;

	//draw team tabs
	for( i = 0; i < GS_MAX_TEAMS; i++ ) 
	{
		if( !tdmteams[i].updated ) {
			continue;
		}

		yoffset = 0;
		if( rightside ) {
			xoffset = 8;
		} else {
			xoffset = -8;
		}

		yoffset += SCR_DrawTeamTab( i, x + xoffset, y + yoffset, rightside, font );
		rightside = !rightside;
		if( yoffset > ymaxoffset )
			ymaxoffset = yoffset;

		xoffset = 0;
	}

	// so we draw the spectators below the teammembers
	// we do know how many players the biggest team has.
	yoffset = ymaxoffset + trap_SCR_strHeight(font);
	yoffset+=SCB_DrawPlayerStats( x + xoffset, y + yoffset );
	SCB_DrawSpectators( x + xoffset, y + yoffset );
}


//===============================================================
//
//		CTF SCOREBOARD
//
//===============================================================

typedef struct
{
	int			teamnum;
	int			teamscore;
	int			teamcaps;
	qboolean	updated;

}cg_ctf_scoreboard_teams_t;

static cg_ctf_scoreboard_teams_t ctfteams[GS_MAX_TEAMS];

//================
// SCR_DrawTeamTabCTF
//================
#define TAB_TEAM_MAX_NAME_LEN 16
int SCR_DrawTeamTabCTF( int team, int x, int y, qboolean isright, struct mufont_s *font )
{
	vec4_t	teamcolor;
	char	string[MAX_STRING_CHARS];
	int	len;
	int	xname, alignname;
	int	xscore;
	int	scorewidth;
	int	xstats;
	int	scoreCharSize = 48;
	int	i;
	int	yoffset=0;
	struct mufont_s *tittleFont = cgs.fontSystemBig;

	GS_TeamColor( team, teamcolor );

	Q_snprintfz(string, sizeof(string), "%i", ctfteams[team].teamscore  );
	scorewidth = scoreCharSize * strlen(string);

	teamcolor[3] = SCB_BACKGROUND_ALPHA; // make transparent

	if( !isright ) //left side tab
	{
		xscore = x - (scorewidth + 8); // 8 is a space between tabs
		xname = x - (scorewidth + 16);
		alignname = ALIGN_RIGHT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( 0, y+scoreCharSize, x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, teamcolor, cgs.shaderWhite );

		xstats = x - 16 - SCB_CTF_PLAYERTAB_PIXELWIDTH;
		
	} else { //right side tab
		xscore = x + 8;
		xname = x + scorewidth + 16;
		alignname = ALIGN_LEFT_BOTTOM;

		//draw box
		trap_R_DrawStretchPic( x, y+scoreCharSize, cg.refdef.width - x,	//width
			-((int)trap_SCR_strHeight( tittleFont )),	//height
			0, 0, 1, 1, teamcolor, cgs.shaderWhite );

		xstats = x + 16;
	}

	teamcolor[3] = 1.0f; // make solid

	yoffset = 0;

	// print score box
	SCR_DrawBigNumbersString( xscore, y+yoffset, scoreCharSize, scoreCharSize, va("%i",ctfteams[team].teamcaps), colorWhite );
	yoffset += scoreCharSize;

	// print name
	Q_snprintfz( string, sizeof(string), "%s%s", GS_TeamName(team), S_COLOR_WHITE );
	len = trap_SCR_StrlenForWidth( string, tittleFont, SCB_TEAMNAME_PIXELWIDTH );
	trap_SCR_DrawStringLen( xname, y+yoffset, alignname, string, len, tittleFont, colorWhite );

	// print players header
	{
		int xheaderoffset = 0;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_LEFT_TOP, "name", font, colorMdGrey );
		xheaderoffset += SCB_PLAYERNAME_PIXELWIDTH;
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;// we align right, so, offset before writting
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "pnts", font, colorMdGrey );
		xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;
		trap_SCR_DrawString( xstats+xheaderoffset, y+yoffset, ALIGN_RIGHT_TOP, "ping", font, colorMdGrey );
		//xheaderoffset += SCB_SMALLFIELD_PIXELWIDTH;

		yoffset += trap_SCR_strHeight( font );
	}

	// print all players of this team
	for( i = 0; i < scb_playercount; i++ ) 
	{
		if( scb_players[i].team == team ) {
			yoffset+=SCB_DrawCTFPlayerTab( &scb_players[i], xstats, y+yoffset, isright, font );
		}
	}

	return yoffset;
}

//================
//SCR_UpdateCTFScoreboard
//================
void SCR_UpdateCTFScoreboard( char *s )
{
	char	*token;
	int	i, cteam = 0;

	//take out the layout id
	token = COM_Parse( &s );
	if( !token ) return;

	for(i=0; i < GS_MAX_TEAMS; i++)
		ctfteams[i].updated = qfalse;

	scb_playercount = 0;

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

		if( !Q_stricmp( token, "&t" ) ) //read a team tab
		{
			cteam = SCR_ParseValue( &s );
			if( cteam < 0 || cteam > GS_MAX_TEAMS ) 
				CG_Error("Invalid team value in CTF Scoreboard");

			ctfteams[cteam].teamnum = cteam;
			ctfteams[cteam].teamscore = SCR_ParseValue( &s );
			ctfteams[cteam].teamcaps = SCR_ParseValue( &s );
			ctfteams[cteam].updated = qtrue;
		}
		else if( !Q_stricmp( token, "&p" ) ) { //read a player tab
			SCB_ParseCTFPlayerTab( &s, cteam );
		}
		else if( !Q_stricmp( token, "&w" ) ) { // read a waiting list player tab
			SCB_ParseChallengerTab( &s );
		}
		else if( !Q_stricmp( token, "&s" ) ) { //read a spectator tab
			SCB_ParseSpectatorTab( &s );
		}
		else if( !Q_stricmp( token, "&c" ) ) {
			SCB_ParseConnectingPlayerTab( &s );
		}
		else if( !Q_stricmp( token, "&z" ) ) {
			SCB_ParsePlayerStats( &s );
		}
	}
}

//================
//SCR_DrawCTFScoreboard
//================
void SCR_DrawCTFScoreboard( int x, int y, struct mufont_s *font )
{
	int		t, xoffset, yoffset, ymaxoffset = 0;
	qboolean 	rightside = qfalse;

	//draw team tabs
	for( t = 0; t < GS_MAX_TEAMS; t++ )
	{
		if( t!= TEAM_RED && t!= TEAM_BLUE ) // forces drawing the team tabs
			continue;                                                

		yoffset = 0;
		if( rightside ) {
			xoffset = 8;
		} else {
			xoffset = -8;
		}
		
		yoffset += SCR_DrawTeamTabCTF( t, x + xoffset, y + yoffset, rightside, font );
		if( yoffset > ymaxoffset )
			ymaxoffset = yoffset;
		rightside = !rightside;
		xoffset = 0;
	}

	// so we draw the spectators below the teammembers
	// we do know how many players the biggest team has.
	yoffset = ymaxoffset + trap_SCR_strHeight(font);
	yoffset+=SCB_DrawPlayerStats( x, y + yoffset );
	SCB_DrawSpectators( x, y + yoffset );
}

//===============================================================
//
//		FIXED SCOREBOARD LAYOUT SCHEMES
//
//===============================================================

//  Layouts were great when Q2 didn't have a cgame, and still are
// great for the hud, but, since each mod has it's own cgame now,
// we don't need to send the design through the netcode anymore. It's
// enough for us now with sending the data, and use cgame for applying
// that data to a fixed layout desing

// Each layout can use it's own data format. To identify the string
// as a fixed layout I decided to use a short token, beginning with
// the 'and' character ( '&' ), and followed by a token of no more
// than six characters. The rest of the string is interpreted at
// it's own function, so the format it's particular to it.

char	scoreboard_name[16];

typedef struct {
	char	*name;
	void	(*DrawScoreboard)( int xpos, int ypos, struct mufont_s *font );
	void	(*UpdateScoreboard)( char *s );
}cg_scoreboard_templates_t;

cg_scoreboard_templates_t cg_scoreboards[] = {
	{"&dms", SCR_DrawDMScoreboard, SCR_UpdateDMScoreboard},
	{"&races", SCR_DrawRACEScoreboard, SCR_UpdateRACEScoreboard},
	{"&duels", SCR_DrawDUELScoreboard, SCR_UpdateDUELScoreboard},
	{"&tdms", SCR_DrawTDMScoreboard, SCR_UpdateTDMScoreboard},
	{"&ctfs", SCR_DrawCTFScoreboard, SCR_UpdateCTFScoreboard},
	{NULL}
};

void SCR_DemoToggleScores_f( void )
{
	cg.demoShowScoreboard = !cg.demoShowScoreboard;
}

/*
================
SCR_DrawScoreboard
================
*/
void SCR_DrawScoreboard( void )
{
	cg_scoreboard_templates_t	*scboard;
	char	title[20];
	int		xpos, ypos, len;
	struct mufont_s *font;

	//yoffset at middle of the screen
	xpos = (int)(cg.refdef.width * 0.5);
	ypos = (int)(cg.refdef.height * 0.25) - 24;

	font = trap_SCR_RegisterFont( cg_scoreboardFont->string );
	if( !font ) {
		CG_Printf( "%sWarning: Invalid font in 'cg_scoreboardFont'. Reseting to default%s\n", S_COLOR_YELLOW, S_COLOR_WHITE );
		trap_Cvar_Set( "cg_scoreboardFont", cg_scoreboardFont->dvalue );
		font = trap_SCR_RegisterFont( cg_scoreboardFont->string );
	}

	//title
	Q_snprintfz( title, sizeof(title), "WARSOW %s",
			GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE] ) );
	Q_strupr( title );
	trap_SCR_DrawString( xpos, ypos, ALIGN_CENTER_TOP, title, cgs.fontSystemBig, whiteTransparent );
	ypos += trap_SCR_strHeight( cgs.fontSystemBig );
	len = trap_SCR_StrlenForWidth( cgs.configStrings[CS_HOSTNAME], cgs.fontSystemSmall, cgs.vidWidth*0.75);
	trap_SCR_DrawStringLen( xpos, ypos, ALIGN_CENTER_TOP, cgs.configStrings[CS_HOSTNAME], len, cgs.fontSystemSmall, whiteTransparent );
	ypos += trap_SCR_strHeight( cgs.fontSystemSmall );

	
	if( scoreboard_name[0] != '&' )	{	//must begin with
		return;
	}

	for( scboard = cg_scoreboards; scboard->name; scboard++ )
	{
		if( !Q_stricmp( scboard->name, scoreboard_name ) ) {
			scboard->DrawScoreboard( xpos, ypos, font );
			return;
		}
	}
	
	trap_SCR_DrawString( 16, 4*16, ALIGN_LEFT_TOP, "Invalid Scoreboard Template", cgs.fontSystemMedium, whiteTransparent );
	
	if( developer->integer )
		CG_Printf( "SCR_DrawScoreboard : Unrecognized scoreboard template\n");
}

/*
================
SCR_UpdateScoreboardMessage
================
*/
void SCR_UpdateScoreboardMessage( char *string )
{
	char	*tok, *ptr;
	cg_scoreboard_templates_t	*scboard;
	
	if( !string || !string[0] )
		goto notfound;

	ptr = string;
	tok = COM_Parse( &ptr );
	if( !tok || !tok[0] )
		goto notfound;

	if( *tok != '&' )		//must begin with
		goto notfound;
	
	for( scboard = cg_scoreboards; scboard->name; scboard++ )
	{
		if( !Q_stricmp( scboard->name, tok ) ) {
			Q_strncpyz( scoreboard_name, tok, sizeof(scoreboard_name) );
			scboard->UpdateScoreboard( string );
			return;
		}
	}
notfound:
	// failed
	memset( scoreboard_name, 0, sizeof(scoreboard_name) );
	if( developer->integer )
		CG_Printf( "SCR_UpdateScoreboard : Unrecognized scoreboard template\n");
}

