

/************************************
  REVISION LOG ENTRY
  Revision By: INCINERATOR
  Revised on 7/1/2003 10:30:39 AM
  Comments: Ripped from alliance 2.5 code
  modified to work with battlebots and newexpert
  added team color backgrounds with forcolor options
 ************************************/


#include "cg_local.h"
#include "alliance_scoreboard.h"

//Score board x positioning constants
#define SB_LEFT_X             54  //if we use left we also use right
#define SB_CENTER_X           (320 - ( (27/*17*/ * SMALLCHAR_WIDTH) + (3 * SB_SEPARATOR) ) / 2) //if we use center, we DONT use left or right
#define SB_RIGHT_X            320 + 6//(640 - SB_LEFT_X - SB_SCORE_W - SB_PING_W - SB_TIME_W - SB_NAME_W - ( 3 * SB_SEPARATOR) )

//Score board y positioning constants
#define SB_HEADER_HEIGHT      SMALLCHAR_HEIGHT
#define SB_HEADER             53//55//86       //column headers start here
#define SB_SCORESTART         (SB_HEADER + SB_HEADER_HEIGHT + 10)  //scores start here

//various heights
#define SB_MAXCLIENTS_NORM    8//(SB_STATUSBAR - SB_SCORESTART / SB_HEIGHT_NORMAL)  //# of non interleaved scores
#define SB_MAXCLIENTS_INTER   16//(SB_STATUSBAR - SB_SCORESTART / SB_HEIGHT_INTER)   //# of interleaved scores
#define SB_MAXCLIENTS_SPECS   4

#define SB_HEIGHT_NORMAL      40   //Height of a normal row
#define SB_HEIGHT_INTER       16   //Height of a interleaved row (should be a little smaller
						            //then half the normal height, we dont want to get too close)
#define SB_HEIGHT_SPECS       16

#define SB_STATUSBAR          400 //420 //Where statusbar starts so we dont overwrite

//column header widths (used in right alignment)
#define SB_SCORE_W            (SMALLCHAR_WIDTH * 5)
#define SB_PING_W             (SMALLCHAR_WIDTH * 4)
#define SB_TIME_W             (SMALLCHAR_WIDTH * 4)
#define SB_NAME_W             (SMALLCHAR_WIDTH * 4) 

//Left header starts
#define SB_SCORE_LEFT_X       (SB_LEFT_X)      
#define SB_PING_LEFT_X		   (SB_LEFT_X + (3 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 1) )
#define SB_TIME_LEFT_X		   (SB_LEFT_X + (7 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 2) )
#define SB_NAME_LEFT_X		   (SB_LEFT_X + (11 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 3) )

//right header starts
#define SB_SCORE_RIGHT_X	   (SB_RIGHT_X)
#define SB_PING_RIGHT_X	   (SB_RIGHT_X + (3 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 1) )
#define SB_TIME_RIGHT_X	   (SB_RIGHT_X + (7 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 2) )
#define SB_NAME_RIGHT_X	   (SB_RIGHT_X + (11 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 3) )

//center header starts
#define SB_SCORE_CENTER_X	   (SB_CENTER_X)
#define SB_PING_CENTER_X	   (SB_CENTER_X + (4 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 1) )
#define SB_TIME_CENTER_X	   (SB_CENTER_X + (7 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 2) )
#define SB_NAME_CENTER_X	   (SB_CENTER_X + (10 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 3) )

//first column specs
#define SB_SPEC_PING_LEFT_X   (SB_LEFT_X)
#define SB_SPEC_TIME_LEFT_X   (SB_LEFT_X + (4 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 1) )
#define SB_SPEC_NAME_LEFT_X   (SB_LEFT_X + (8 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 2) )

//second column specs
#define SB_SPEC_PING_RIGHT_X  (SB_RIGHT_X)
#define SB_SPEC_TIME_RIGHT_X  (SB_RIGHT_X + (4 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 1) )
#define SB_SPEC_NAME_RIGHT_X  (SB_RIGHT_X + (8 * SMALLCHAR_WIDTH) + (SB_SEPARATOR * 2) )

#define SB_CENTER             0
#define SB_TWOCOLS            1

#define SB_SEPARATOR          (SMALLCHAR_WIDTH * 3) //20 //distance between headings, keep on a character boundry

//Okay, my new scoreboard. If we can we'll display the scores in the center of the screen in a good sized font.
//If there is not enough room we'll ditch the center scores and go with a two column scoreboardt. Either way 
//the pics at the top of the score board have been scrapped and replaced with text (should be no problem to 
//add back in if need be). Also changed the coloring a bit.



void JH_Vector4Cpy( vec4_t in, vec4_t out )
{
	out[0] = in[0];
	out[1] = in[1];
	out[2] = in[2];
	out[3] = in[3];
} //END JH_Vector4Cpy(...)




/*---------------------------------------------------------------------------
	FUNCTION PROTOTYPES
---------------------------------------------------------------------------*/
static void JH_DrawClientScore( int col, int y, score_t *score, float *color, float fade, int spec );
static void JH_DrawScores     ( int pos, float fade, int maxClients, int lineHeight );
static int  JH_DrawTeamScores ( float fade, int maxClients, int lineHeight );
static int  JH_DrawSpectators ( float fade, int maxCol, int lineHeight );
//static int  JH_DrawEliminated ( float fade, int maxCol, int lineHeight, int start );
static void JH_CutStr         ( char *name, int size );


// AW
qboolean bw_displayed; // true if scoreboard is being displayed


int bw_ctfFragsRed = 0;
int bw_ctfFragsBlue = 0;



/*---------------------------------------------------------------------------
	FUNCTION: JH_DrawClientScore

	Draws a single client score on the board
---------------------------------------------------------------------------*/
static void JH_DrawClientScore( int col, int y, score_t *score, float *color, float fade, int spec )
{
	char			string[1024];
	char			cleanName[MAX_STRING_CHARS];
	clientInfo_t	*ci;
	vec4_t			c;

	JH_Vector4Cpy( colorWhite, c );

	//same check that ID used in their code
	if ( score->client < 0 || score->client >= cgs.maxclients )
	{
		Com_Printf( "Bad score->client: %i\n", score->client );
		return;
	}

	ci = &cgs.clientinfo[ score->client ];

	strcpy( cleanName, ci->name );
	//Q_CleanStr( cleanName );
	// Right now, our scoreboards can only display names <= 24 chars
	JH_CutStr( cleanName, 24 );

	if ( cgs.gametype >= GT_CTF ) {
		if (ci->powerups & ( 1 << PW_REDFLAG )) {
			CG_DrawFlagModel( col, y , 16, 16, TEAM_RED, qfalse );
			//CG_DrawPic( col, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, cgs.media.redFlagModel );  
		} else if (ci->powerups & ( 1 << PW_BLUEFLAG )) {
			CG_DrawFlagModel( col, y , 16, 16, TEAM_BLUE, qfalse );
			//CG_DrawPic( col, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, cgs.media.blueFlagModel );  

		}
#ifdef MISSIONPACK 
		else if (ci->powerups & ( 1 << PW_NEUTRALFLAG )) {
			CG_DrawFlagModel( col, y , 16, 16, TEAM_FREE, qfalse );
			//CG_DrawPic( col, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, cgs.media.neutralFlagModel );  
		}
#endif

	}

	if ( spec )	{
		if ( score->ping != -1 ) {
			Com_sprintf(string, sizeof(string), "%4i %6i   %s", score->ping, score->time, cleanName );
		} else {
			Com_sprintf(string, sizeof(string), "%s    %s", "Connecting", cleanName );
		}
	} else {
		if ( score->ping != -1 ) {
			if ( cgs.gametype >= GT_TEAM ) {
				if ( cgs.gametype >= GT_CTF ) {
					Com_sprintf( string, sizeof( string ), "%5i %4i %2i %2i %2i %s", 
						score->score, score->ping, score->time,	score->captures, score->returns , cleanName );
                    //CG_DrawPic( col + 18 * SMALLCHAR_WIDTH , y, SMALLCHAR_HEIGHT, SMALLCHAR_HEIGHT, 
					//	cgs.media.jerseys[cgs.clientinfo[ score->client ].jersey - 1] );
				} else {
					Com_sprintf( string, sizeof( string ), "%5i %4i          %s", 
						score->score, score->ping, cleanName );
	                //CG_DrawPic( col + 18 * SMALLCHAR_WIDTH , y, SMALLCHAR_HEIGHT, SMALLCHAR_HEIGHT, 
					//	cgs.media.jerseys[cgs.clientinfo[ score->client ].jersey - 1] );
				}
			} else {
				Com_sprintf( string, sizeof( string ), "%5i %5i %5i  %s", 
					score->score, score->ping, score->time, cleanName );
			}
		} else {
			Com_sprintf( string, sizeof( string ), " %s        %s", "Connecting", cleanName );
		}
	}

	//draw the score
	CG_DrawStringExt( col, y, string, c, qfalse, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

	//display a 'R' if the player is set to go after intermission
	if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << score->client ) )	{
		CG_DrawSmallStringColor( col - SMALLCHAR_WIDTH - 2, y, "R", colorGreen );
	}

	// Draw in any awarded medals
	/*
	if ( ci->powerups & (1 << PW_DMVP) && cgs.gametype >= GT_CTF ) {
		CG_DrawPic( 133, 438, 45, 45, cgs.media.hudMedalDef );
		CG_DrawStringExt( 133 + 44, 438 + 20 - (SMALLCHAR_HEIGHT / 2), ci->name, colorYellow, qtrue, qtrue, 
			SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
	}

	if ( ci->powerups & (1 << PW_OMVP) && cgs.gametype >= GT_CTF  ) {
		CG_DrawPic( 399, 438, 45, 45, cgs.media.hudMedalOff );
		CG_DrawStringExt( 399 + 44, 438 + 20 - (SMALLCHAR_HEIGHT / 2), ci->name, colorYellow, qtrue, qtrue, 
			SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
	}
	*/		

	//Draw Standard Q3 Award medals, like in Tier Play

	if (( score->client == cg.snap->ps.clientNum ) && ( !spec )) {
		char count[3];
		int offset;

		// Hugo - don't override TeamTracker
		//offset = 0;
		//if (!cg_drawhudpos.integer) // left TeamTracker
			offset = 590; // show medals on the right

		// Headshots
/*
		Com_sprintf(count, 3, "%i", score->returns);	
		CG_DrawPic ( 10 + offset,50,25,25,cgs.media.medalHeadshot);//pick a new one
		CG_DrawStringExt( 35 + offset, 63 - (SMALLCHAR_HEIGHT / 2), count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
*/		
		// Humiliation
		Com_sprintf(count, 3, "%i", score->guantletCount);
		CG_DrawPic ( 10 + offset,75,25,25,cgs.media.medalGauntlet);
		CG_DrawStringExt( 35 + offset, 85 - (SMALLCHAR_HEIGHT / 2), count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

		// Excellent
		Com_sprintf(count, 3, "%i", score->excellentCount);
		CG_DrawPic ( 10 + offset,100,25,25,cgs.media.medalExcellent);
		CG_DrawStringExt( 35 + offset, 110 - (SMALLCHAR_HEIGHT / 2), count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
        
		// Impressive
		Com_sprintf(count, 3, "%i", score->impressiveCount);	
	    CG_DrawPic ( 10 + offset,125,25,25,cgs.media.medalImpressive);
		CG_DrawStringExt( 35 + offset, 135 - (SMALLCHAR_HEIGHT / 2), count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

		// Accuracy
		Com_sprintf(count, 3, "%i", score->accuracy);	
	    CG_DrawPic ( 10 + offset,150,25,25,cgs.media.medalAccuracy);
		//CG_DrawStringExt( 10 + offset, 150 - (SMALLCHAR_HEIGHT / 2),  "Accuracy", colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
		CG_DrawStringExt( 35 + offset, 160 - (SMALLCHAR_HEIGHT / 2), count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

		// Frags
		Com_sprintf(count, 3, "%i", cg.snap->ps.stats[STAT_FRAGS]);	
	    CG_DrawPic ( 10 + offset,175,25,25,cgs.media.medalFrags);
		//CG_DrawStringExt( 10 + offset, 175 - (SMALLCHAR_HEIGHT / 2),  "Frags", colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
		CG_DrawStringExt( 35 + offset, 185 - (SMALLCHAR_HEIGHT / 2),  count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

		if (cgs.gametype >= GT_CTF){ 
			// Captures
			Com_sprintf(count, 3, "%i", score->captures);	
            CG_DrawPic ( 10 + offset,200,25,25,cgs.media.medalCapture);
			CG_DrawStringExt( 35 + offset, 210 - (SMALLCHAR_HEIGHT / 2),  count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

			// Defend
			Com_sprintf(count, 3, "%i", score->defendCount);	
			CG_DrawPic ( 10 + offset,225,25,25,cgs.media.medalDefend);
			CG_DrawStringExt( 35 + offset, 235 - (SMALLCHAR_HEIGHT / 2),  count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );

			// Assists
			Com_sprintf(count, 3, "%i", score->assistCount);	
	    	CG_DrawPic ( 10 + offset,250,25,25,cgs.media.medalAssist);			
			CG_DrawStringExt( 35 + offset, 260 - (SMALLCHAR_HEIGHT / 2),  count, colorYellow, qtrue, qtrue, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
		}
	}
}



/*---------------------------------------------------------------------------
FUNCTION: JH_DrawScoreboard

Layout the scoreboard and then add the scores
---------------------------------------------------------------------------*/
qboolean JH_DrawScoreboard( void )
{
	int y, pos, maxClients, lineHeight, maxCol, red, blue, i, height, y_start;
	float  fade;
	float  color[4];      //an extra color entry
	float *fadeColor;
	score_t	     *score;
	clientInfo_t *ci;
    int tColor, eColor;
	

	//BEGIN: same initial checks used in ids code
	tColor = getColorFromString(cg_teamColor.string);
    eColor = getColorFromString(cg_enemyColor.string);

	// don't draw anything if the menu or console is up
	if ( cg_paused.integer ) {
		cg.deferredPlayerLoading = 0;
		return qfalse;
	}

	if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
		cg.deferredPlayerLoading = 0;
		return qfalse;
	}

	//If we are dead, at the end of a level or in an intermission use white text
	if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD ||
		cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
		fade = 1.0;
		fadeColor = colorWhite;
	} else { //otherwise use a nice faded color
		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;
			return qfalse;
		}
		fade = *fadeColor;
	}
	
	//END: same initial checks used in ids code (I LEFT OUT FRAGGED BY LINE AND RANK FOR NOW)

	//Determin how many cols we need and set starting pos and y vals and draw the headers
	//also draw a red line under the heading
	y = SB_HEADER;

	color[0] = 0.7f;
	color[1] = 0;
	color[2] = 0;
	color[3] = fade * 0.5;
	
	//NOTE: the if statements here for selecting the color backdrop can probably be changed to do the
	//      selection a bit faster....maybe fix that later. This is a mess, I realize that...I will fix it later :-)
	if ( cg.numScores > SB_MAXCLIENTS_INTER || cgs.gametype >= GT_TEAM ) 
	{
		//use two cols
		pos = SB_TWOCOLS;

		if ( cgs.gametype < GT_TEAM ) {
			height  = SMALLCHAR_HEIGHT + 2;
			y_start = y;
		} else {
			height  = (SMALLCHAR_HEIGHT * 2) + 2;
			y_start = y - SMALLCHAR_HEIGHT;
		}
		
		//CG_DrawPic( SB_LEFT_X , y_start , (640 - SB_LEFT_X * 2) , height, cgs.media.scoreboardtest);
		//CG_DrawPic( 0 , 0, 640 , 480 , cgs.media.scoreboardtest);

		//add a shaded color backdrop
		if ( cgs.gametype < GT_TEAM ) {
			color[0] = color[2] = .25;
			color[3] = fade * 0.4;	
			CG_FillRect( SB_LEFT_X, y_start, (640 - SB_LEFT_X * 2), height, color );
			//CG_DrawTeamBackground( SB_LEFT_X, y_start, (640 - SB_LEFT_X * 2), height , 0.33f, TEAM_RED );
		} else {
			color[0] = 0.2f;
			CG_FillRect( SB_LEFT_X, y_start, (320 - SB_LEFT_X - 2), height, color ); 
			//CG_DrawTeamBackground( SB_LEFT_X, y_start, (320 - SB_LEFT_X - 2), height , 0.33f, TEAM_RED );
		}

		//Draw first col
		CG_DrawSmallString( SB_SCORE_LEFT_X, y, "Score", fade );
		CG_DrawSmallString( SB_PING_LEFT_X, y, "Ping", fade );
		if ( cgs.gametype >= GT_TEAM ) {
			if ( cgs.gametype >= GT_CTF ) {
				CG_DrawSmallString( SB_TIME_LEFT_X - SMALLCHAR_WIDTH, y, "T FC RT", fade );
			}// else {
			//	CG_DrawSmallString( SB_TIME_LEFT_X - SMALLCHAR_WIDTH, y, "Jersey", fade );
			//}
		} else {
			CG_DrawSmallString( SB_TIME_LEFT_X - SMALLCHAR_WIDTH, y, " Time", fade );
		}
		CG_DrawSmallString( SB_NAME_LEFT_X, y, "Name", fade );

		//add a shaded team color backdrop
		if ( cgs.gametype >= GT_TEAM ) {
			color[0] = 0;
			color[2] = 0.2f;
			CG_FillRect( 320 + 6, y_start, (320 - SB_LEFT_X - 2), height, color ); 
			//CG_DrawTeamBackground( 320 + 6, y_start, (320 - SB_LEFT_X - 2), height , 0.33f, TEAM_RED );
		}

		//Draw second col
		CG_DrawSmallString( SB_SCORE_RIGHT_X, y, "Score", fade );
		CG_DrawSmallString( SB_PING_RIGHT_X, y, "Ping", fade );
		if ( cgs.gametype >= GT_TEAM ) {
			if ( cgs.gametype >= GT_CTF ) {
				CG_DrawSmallString( SB_TIME_RIGHT_X - SMALLCHAR_WIDTH, y, "T FC RT", fade );
			} //else {
			//	CG_DrawSmallString( SB_TIME_RIGHT_X - SMALLCHAR_WIDTH, y, "Jersey", fade );
			//}
		} else {
			CG_DrawSmallString( SB_TIME_RIGHT_X - SMALLCHAR_WIDTH, y, " Time ", fade );
		}
		CG_DrawSmallString( SB_NAME_RIGHT_X, y, "Name", fade );

		//for two cols we gotta use interleaved scores
		maxClients = SB_MAXCLIENTS_INTER;
		lineHeight = SB_HEIGHT_INTER;

		//If it really is a team game, divide sides up into blue and red
		if ( cgs.gametype >= GT_TEAM ) {
			red  = 0;
			blue = 0;

			//figure out how many people on each team
			for ( i = 0; i < cg.numScores; i++ ) {
				//get the current score and client
				score = &cg.scores[i];
				ci    = &cgs.clientinfo[ score->client ];

				if ( ci->team == TEAM_RED ) {
					red++;
				} else if ( ci->team == TEAM_BLUE ) {
					blue++;
				}
			}	

			if ( blue > red ) {
				maxCol = blue;
			} else {
				maxCol = red;
			}

			maxCol = JH_DrawSpectators( fade, maxCol, lineHeight );
			maxCol = 20 - maxCol;

			if ( maxCol < 0 ) // begin AW I changed these two lines 0 --> 1
				maxCol = 0;

			//
			//Red Team
			//
			color[0] = 0.7f;
			color[2] = 0;
			CG_FillRect( SB_LEFT_X, y + SMALLCHAR_HEIGHT + ((SMALLCHAR_HEIGHT - 2) / 2), 
				(320 - SB_LEFT_X - 2), 2, color);
			
			//CG_DrawTeamBackground( 320 + 6, y_start, (320 - SB_LEFT_X - 2), height , 0.33f, TEAM_RED );
			
			//add a shaded team color backdrop
			color[0] = 0.2f;
			
			//CG_FillRect( SB_LEFT_X, y + (2 * SMALLCHAR_HEIGHT) - 2, (320 - SB_LEFT_X - 2), 
			//	(maxCol * SB_HEIGHT_INTER) - 20, color ); 

			CG_DrawTeamBackground( SB_LEFT_X, y + (2 * SMALLCHAR_HEIGHT) - 2, (320 - SB_LEFT_X - 2), 
				(maxCol * SB_HEIGHT_INTER) - 20 , 0.33f, TEAM_RED );

			//
			//Blue Team
			//
			color[0] = 0;
			color[2] = 0.7f;
			CG_FillRect( 320 + 6, y + SMALLCHAR_HEIGHT + ((SMALLCHAR_HEIGHT - 2) / 2), 
				(320 - SB_LEFT_X - 2), 2, color);

			//add a shaded team color backdrop
			color[2] = 0.2f;
			//CG_FillRect( 320 + 6, y + (2 * SMALLCHAR_HEIGHT) - 2, (320 - SB_LEFT_X - 2), 
			//	(maxCol * SB_HEIGHT_INTER) - 20, color );

			CG_DrawTeamBackground( 320 + 6, y + (2 * SMALLCHAR_HEIGHT) - 2, (320 - SB_LEFT_X - 2), 
				(maxCol * SB_HEIGHT_INTER) - 20 , 0.33f, TEAM_BLUE );

			JH_DrawTeamScores( fade, maxClients, lineHeight );
			//CG_DrawPic( SB_LEFT_X , y_start , (640 - SB_LEFT_X * 2) , (maxCol * SB_HEIGHT_INTER) - 20, cgs.media.scoreboardtest);
			CG_DrawPic( 0 , 0, 640 , 480 , cgs.media.scoreboardtest);

		} else {
			CG_FillRect( SB_LEFT_X, y + SMALLCHAR_HEIGHT + ((SMALLCHAR_HEIGHT - 2) / 2), (640 - SB_LEFT_X * 2), 3, color);
			JH_DrawScores( pos, fade, maxClients, lineHeight );
		}
	} else {
		//use one col in center
		pos = SB_CENTER;

		maxClients = SB_MAXCLIENTS_INTER;
		lineHeight = SB_HEIGHT_INTER;

		color[0] = color[2] = .25;
		color[1] = 0;
		color[3] = fade * 0.4;
		CG_FillRect( SB_CENTER_X, y, ( (27 * SMALLCHAR_WIDTH) + (3 * SB_SEPARATOR) ), SMALLCHAR_HEIGHT + 2, color);

		CG_DrawSmallString( SB_SCORE_CENTER_X, y, "Score", fade );
		CG_DrawSmallString( SB_PING_CENTER_X, y, "Ping", fade );
		if ( cgs.gametype >= GT_TEAM ) {
			if ( cgs.gametype >= GT_CTF ) {
				CG_DrawSmallString( SB_TIME_CENTER_X - SMALLCHAR_WIDTH, y, " FC FR", fade );
			}
			//else {
			//	CG_DrawSmallString( SB_TIME_CENTER_X - SMALLCHAR_WIDTH, y, "Jersey", fade );
			//}
		} else {
			CG_DrawSmallString( SB_TIME_CENTER_X - SMALLCHAR_WIDTH, y, " Time", fade );
		}
		CG_DrawSmallString( SB_NAME_CENTER_X, y, "Name", fade );

		color[3] = fade * 0.7;
		color[0] = color[2] = .5;
		CG_FillRect( SB_CENTER_X, y + 20, ( (27 * SMALLCHAR_WIDTH) + (3 * SB_SEPARATOR) ), 3, color);
		JH_DrawScores( pos, fade, maxClients, lineHeight );
	}

	// load any models that have been deferred
	if ( ++cg.deferredPlayerLoading > 10 ) {
		CG_LoadDeferredPlayers();
	}

	return qtrue;
}


/*---------------------------------------------------------------------------
FUNCTION: JH_DrawScores

Rank and draw scores for a normal dm game
---------------------------------------------------------------------------*/
static void JH_DrawScores( int pos, float fade, int maxClients, int lineHeight )
{
	int           x, y, i, count, maxCol; 
	float         color[4], backcolor[4];
	score_t	     *score;
	int length, start;
	char string[1024];

	y        = SB_SCORESTART;
	color[3] = fade;

	backcolor[0] = backcolor[2] = .25;
	backcolor[1] = 0;
	backcolor[3] = fade * 0.4;


	if ( !pos )	{ //if one col
		count = 0;
		x     = SB_CENTER_X;

		maxCol = JH_DrawSpectators( fade, cg.numScores, lineHeight );
		maxCol = 20 - maxCol;

		//Draw in a nice purple backdrop
		CG_FillRect( SB_CENTER_X, y, ( (27 * SMALLCHAR_WIDTH) + (3 * SB_SEPARATOR) ), 
			(maxCol * SB_HEIGHT_INTER - SB_HEIGHT_INTER), backcolor ); 

		for ( i = 0; i < cg.numScores; i++ ) {
			//get the current score and client
			score = &cg.scores[i];
			if ( cgs.clientinfo[ score->client ].team == TEAM_FREE ) {
				JH_DrawClientScore( x, y + lineHeight * count, score, color, fade, 0 );	
				count++;
			}
		}
	} else { //two cols
		maxCol = JH_DrawSpectators( fade, cg.numScores, lineHeight );
		maxCol = 20 - maxCol;
		count = 0;
		x     = SB_LEFT_X;

		//draw a nice purple backdrop
		CG_FillRect( SB_LEFT_X, y, (640 - SB_LEFT_X * 2), 
			(maxCol * SB_HEIGHT_INTER - SB_HEIGHT_INTER), backcolor );

		//fill the first column, then the second
		for ( i = 0; i < cg.numScores; i++ ) {
			//get the current score and client
			score = &cg.scores[i];

			//switch to second column
			if ( i == maxClients ) {
				count = 0;
				x     = SB_RIGHT_X;
			}

			if ( cgs.clientinfo[ score->client ].team == TEAM_FREE ) {
				JH_DrawClientScore( x, y + lineHeight * count, score, color, fade, 0 );
				count++;
			}
		}
	}


	// fraglimit on top
	Com_sprintf(string, sizeof(string), "fraglimit %d", cgs.fraglimit);

	// center
	length = strlen(string);
	// width is always 640, scaled for resolution
	start = (640 - SMALLCHAR_WIDTH*length)/2;

	CG_DrawSmallString( start, SB_HEADER -
						SMALLCHAR_HEIGHT*2, string, fade ); 

	// map name next
	Com_sprintf(string, sizeof(string), "%s: %s",
				Info_ValueForKey(CG_ConfigString(CS_SERVERINFO),
								 "mapname"),
				CG_ConfigString(CS_MESSAGE));

	// center
	length = strlen(string);
	// width is always 640, scaled for resolution
	start = (640 - SMALLCHAR_WIDTH*length)/2;

	CG_DrawSmallString( start, SB_HEADER -
						SMALLCHAR_HEIGHT, string, fade ); 

} //END JH_DrawScores


/*---------------------------------------------------------------------------
FUNCTION: JH_DrawTeamScores

Rank and draw scores for a team game (ctf or dm)
---------------------------------------------------------------------------*/
static int JH_DrawTeamScores( float fade, int maxClients, int lineHeight )
{
	int				x, y, i, count1, count2;//, frags1, frags2; //AW
	double          rAvgPing, bAvgPing;
	float			color[4];
	char			string[1024];
	const char		*string1;
	score_t			*score;
	clientInfo_t	*ci;
	int				limit;
	int				length, start;
	
	color[3] = fade;
	count1   = 0;
	rAvgPing = 0;
	bAvgPing = 0;
	bw_ctfFragsRed  = 0;
	bw_ctfFragsBlue = 0;

	x		 = SB_LEFT_X;
	y        = SB_SCORESTART;

	//fill the first column with red team
	for ( i = 0; i < cg.numScores; i++ ) {
		//get the current score and client
		score = &cg.scores[i];
		ci    = &cgs.clientinfo[ score->client ];

		//skip the blue team scores
		if ( ci->team != TEAM_RED)
			continue;
	
		rAvgPing += score->ping;
		bw_ctfFragsRed += score->score;
		JH_DrawClientScore( x, y + lineHeight * count1, score, color, fade, 0 );
		count1++;
	}	

	count2 = 0;
	x      = SB_RIGHT_X;

	//fill the second column with blue team
	for ( i = 0; i < cg.numScores; i++ ) {
		//get the current score and client
		score = &cg.scores[i];
		ci    = &cgs.clientinfo[ score->client ];

		//skip the red team scores
		if ( ci->team != TEAM_BLUE)
			continue;

		bAvgPing += score->ping;
		bw_ctfFragsBlue += score->score;
		JH_DrawClientScore( x, y + lineHeight * count2, score, color, fade, 0 );
		count2++;
	}

	//draw in team frags
	if( cgs.gametype >= GT_CTF ) {
		// red
		if ( count1 ) { // team not empty
			Com_sprintf( string, sizeof( string ), "%5i", bw_ctfFragsRed); 
			CG_DrawSmallString( SB_LEFT_X, SB_HEADER - SMALLCHAR_HEIGHT, string, fade );
		}
		//blue
		if(count2) {
			Com_sprintf( string, sizeof( string ), "%5i", bw_ctfFragsBlue); 
			CG_DrawSmallString( SB_RIGHT_X, SB_HEADER - SMALLCHAR_HEIGHT, string, fade );
		}
	}



	if ( cgs.gametype >= GT_CTF ) {
		limit = cgs.capturelimit;
	} else { 
		limit = cgs.fraglimit;
	}

	if (limit) {
		// red
		Com_sprintf( string, sizeof( string ), "%3i/%i", cg.teamScores[0], limit );
		CG_DrawBigString( SB_LEFT_X + 185, SB_HEADER - 6, string, fade );

		// blue
		Com_sprintf( string, sizeof( string ), "%3i/%i", cg.teamScores[1], limit );
		CG_DrawBigString( SB_RIGHT_X + 185, SB_HEADER - 6, string, fade ); 
	} else {
		// red
		Com_sprintf( string, sizeof( string ), "%3i", cg.teamScores[0]);
		CG_DrawBigString( SB_LEFT_X + 220, SB_HEADER - 6, string, fade );

		// blue
		Com_sprintf( string, sizeof( string ), "%3i", cg.teamScores[1]);
		CG_DrawBigString( SB_RIGHT_X + 220, SB_HEADER - 6, string, fade ); 
	}

	if(count1) // Joe, only divide if team isn't empty
		rAvgPing = ceil( rAvgPing / count1 );
	if(count2) // Joe, only divide if team isn't empty
		bAvgPing = ceil( bAvgPing / count2 );


	// Draw in average ping for each team

	if(count1) { // team not empty
		Com_sprintf( string, sizeof( string ), "%4i", rAvgPing < 0 ? 0 : (int)rAvgPing );
		CG_DrawSmallString( SB_LEFT_X + SMALLCHAR_WIDTH * 6, SB_HEADER - SMALLCHAR_HEIGHT, string, fade ); 
	}

	if(count2) {
		Com_sprintf( string, sizeof( string ), "%4i", bAvgPing < 0 ? 0 : (int)bAvgPing ); 
		CG_DrawSmallString( SB_RIGHT_X +SMALLCHAR_WIDTH * 6, SB_HEADER - SMALLCHAR_HEIGHT, string, fade ); 
	}

	color[0] = color[1] = color[2] = 0;
	color[3] = fade * 0.5;
	CG_FillRect( SB_LEFT_X, SB_HEADER - SMALLCHAR_HEIGHT * 2, (320 - SB_LEFT_X) * 2 + 4, SMALLCHAR_HEIGHT, color);

	// map file name and map long name on top

	string1 = va("%s : Map Name: %s\n", Info_ValueForKey(CG_ConfigString(CS_SERVERINFO), "mapname"),CG_ConfigString(CS_MESSAGE));

	// center
	length = strlen(string1);
	// width is always 640, scaled for resolution
	start = (640 - SMALLCHAR_WIDTH*length)/2;
	CG_DrawSmallString( start, SB_HEADER -	SMALLCHAR_HEIGHT * 2, string1, fade ); 

	return 0;

}


/*---------------------------------------------------------------------------
FUNCTION: JH_DrawSpectators

Draw the spectators at the bottom and adjust the height
---------------------------------------------------------------------------*/
static int JH_DrawSpectators( float fade, int maxCol, int lineHeight )
{
	score_t *score;
	int x, y, i, count, rows;
	float color[4];
	int observers[2][ MAX_CLIENTS ];
	int spec_count, red_count, blue_count, total_rows;

	//first see if we have any spectators to draw
	count = 0;
	spec_count = red_count = blue_count = 0;

	for( i = 0; i < cg.numScores; i++ )	{
		if ( cgs.clientinfo[ cg.scores[i].client ].team == TEAM_SPECTATOR )	{
			spec_count++;
		} else if ( cgs.clientinfo[ cg.scores[i].client ].team == TEAM_SPECTATOR_RED ) {
			observers[0][ red_count ] = i;
			red_count++;
		} else if ( cgs.clientinfo[ cg.scores[i].client ].team == TEAM_SPECTATOR_BLUE )	{
			observers[1][ blue_count ] = i;
			blue_count++;
		}
	}

	if ( !spec_count && !red_count && !blue_count )
		return 0;

	x = SB_LEFT_X;
	y = 403 - ( ((int)ceil( (spec_count + red_count + blue_count)/2.0)) * lineHeight); 

	//add a shaded team color backdrop
	color[0] = color[1] = color[2] = 0.15f;
	color[3] = fade * 0.5;
	CG_FillRect( SB_LEFT_X, y, (320 - SB_LEFT_X) * 2 + 4, SMALLCHAR_HEIGHT + 2, color ); 

	color[0] = color[1] = color[2] = 0.063f;

	CG_DrawSmallString( SB_SPEC_PING_LEFT_X, y, "Ping", fade );
	CG_DrawSmallString( SB_SPEC_TIME_LEFT_X, y, "Time", fade );
	CG_DrawSmallString( SB_SPEC_NAME_LEFT_X, y, "Name", fade );

	CG_DrawSmallString( SB_SPEC_PING_RIGHT_X, y, "Ping", fade );
	CG_DrawSmallString( SB_SPEC_TIME_RIGHT_X, y, "Time", fade );
	CG_DrawSmallString( SB_SPEC_NAME_RIGHT_X, y, "Name", fade );

	//solid underline
	CG_FillRect( SB_LEFT_X, y + 20, (320 - SB_LEFT_X) * 2 + 4, 3, color);

	//draw specs
	count = 0;
	rows = 0;
	y    += 26; 

	if ( spec_count ) {
		//draw a nice grey backdrop for them
		color[0] = color[1] = color[2] = 0.15f;
		CG_FillRect( SB_LEFT_X, y, (320 - SB_LEFT_X) * 2 + 4, ( (int)ceil(spec_count/2.0)) * SB_HEIGHT_INTER, color);

		for ( i = 0; i < cg.numScores; i++ ) {
			//get the current score and client
			score = &cg.scores[i];

			if ( cgs.clientinfo[ score->client ].team == TEAM_SPECTATOR ) {
				count++;
				rows = (count-1) / 2;
				if( count % 2 )
					// left column
					x = SB_LEFT_X;
				else
					// right column
					x = SB_RIGHT_X;

				JH_DrawClientScore( x, y + lineHeight * rows, score, color, fade, 1 );
			} 
		}
	}

	total_rows = rows;
	y += ceil( spec_count / 2.0 ) * lineHeight;
	
	// Draw in red specs
	if ( red_count ) {
		count = 0;
		rows  = 0;

		color[0] = 0.2f;
		color[1] = 0;
		color[2] = 0;

		CG_FillRect( SB_LEFT_X, y + 2, (320 - SB_LEFT_X) * 2 + 4, ( (int)ceil(red_count/2.0)) * SB_HEIGHT_INTER, color);

		for ( i = 0; i < red_count; i++ ) {
			count++;
			rows = (count-1) / 2;
			if( count % 2 )
				// left column
				x = SB_LEFT_X;
			else
				// right column
				x = SB_RIGHT_X;

			JH_DrawClientScore( x, (y + lineHeight * rows) + 2, &cg.scores[ observers[0][ i ] ], color, fade, 1 );
		}
	}

	total_rows += rows;
	y += ceil( red_count / 2.0 ) * lineHeight;
	
	// Draw in blue specs
	if ( blue_count ) {
		count = 0;
		rows  = 0;

		color[0] = 0;
		color[2] = 0.2f;

		CG_FillRect( SB_LEFT_X, y + 2, (320 - SB_LEFT_X) * 2 + 4, ( (int)ceil(blue_count/2.0)) * SB_HEIGHT_INTER, color);

		for ( i = 0; i < blue_count; i++ ) {
			count++;
			rows = (count-1) / 2;
			if( count % 2 )
				// left column
				x = SB_LEFT_X;
			else
				// right column
				x = SB_RIGHT_X;

			JH_DrawClientScore( x, (y + lineHeight * rows) + 2, &cg.scores[ observers[1][ i ] ], color, fade, 1 );
		}
	}

	return total_rows + rows;
} 

/*---------------------------------------------------------------------------
FUNCTION: JH_CutName

Cuts a name to the specified length taking into account color codes
---------------------------------------------------------------------------*/
static void JH_CutStr( char *name, int size )
{
	int ptr, count;

	ptr   = 0;
	count = 0;

	while ( name[ ptr ] )
	{
		if ( count == size )
		{
			name[ ptr ] = 0;
			return;
		}

		if ( name[ ptr ] == '^' )
		{
			ptr += 2;
			continue;
		} 

		count++;
		ptr++;
	}
} 


/*
================
CG_CenterGiantLine
================
*/
static void CG_CenterGiantLine( float y, const char *string ) {
    float		x;
    vec4_t		color;

    color[0] = 1;
    color[1] = 1;
    color[2] = 1;
    color[3] = 1;

    x = 0.5 * ( 640 - GIANT_WIDTH * CG_DrawStrlen( string ) );

    CG_DrawStringExt( x, y, string, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
}


/*
=================
CG_DrawTourneyScoreboard
 
Draw the oversize scoreboard for tournements
=================
*/
void CG_DrawOldTourneyScoreboard( void ) {
    const char		*s;
    vec4_t			color;
    int				min, tens, ones;
    clientInfo_t	*ci;
    int				y;
    int				i;

    // request more scores regularly
    if ( cg.scoresRequestTime + 2000 < cg.time ) {
        cg.scoresRequestTime = cg.time;
        trap_SendClientCommand( "score" );
    }

    color[0] = 1;
    color[1] = 1;
    color[2] = 1;
    color[3] = 1;

    // draw the dialog background
    color[0] = color[1] = color[2] = 0;
    color[3] = 1;
    CG_FillRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color );

    // print the mesage of the day
    s = CG_ConfigString( CS_MOTD );
    if ( !s[0] ) {
        s = "Scoreboard";
    }

    // print optional title
    CG_CenterGiantLine( 8, s );

    // print server time
    ones = cg.time / 1000;
    min = ones / 60;
    ones %= 60;
    tens = ones / 10;
    ones %= 10;
    s = va("%i:%i%i", min, tens, ones );

    CG_CenterGiantLine( 64, s );


    // print the two scores

    y = 160;
    if ( cgs.gametype >= GT_TEAM ) {
        //
        // teamplay scoreboard
        //
        CG_DrawStringExt( 8, y, "Red Team", color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
        s = va("%i", cg.teamScores[0] );
        CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );

        y += 64;

        CG_DrawStringExt( 8, y, "Blue Team", color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
        s = va("%i", cg.teamScores[1] );
        CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
    } else {
        //
        // free for all scoreboard
        //
        for ( i = 0 ; i < MAX_CLIENTS ; i++ ) {
            ci = &cgs.clientinfo[i];
            if ( !ci->infoValid ) {
                continue;
            }
            if ( ci->team != TEAM_FREE ) {
                continue;
            }

            CG_DrawStringExt( 8, y, ci->name, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
            s = va("%i", ci->score );
            CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
            y += 64;
        }
    }


}

