示例#1
0
// maxX param is initially an X limit, but is also used as feedback. 0 = text was clipped to fit within, else maxX = next pos
void CG_Text_Paint_Limit( float *maxX, float x, float y, float scale, const vector4 *color, const char *text, float adjust,
	int limit, int iMenuFont ) {
	qboolean bIsTrailingPunctuation;

	// this is kinda dirty, but...
	qhandle_t iFontIndex = MenuFontToHandle( iMenuFont );

	//float fMax = *maxX;
	float iPixelLen = trap->R_Font_StrLenPixels( text, iFontIndex, scale );
	if ( x + iPixelLen > *maxX ) {
		// whole text won't fit, so we need to print just the amount that does...
		//  Ok, this is slow and tacky, but only called occasionally, and it works...
		char sTemp[4096] = { 0 };	// lazy assumption
		const char *psText = text;
		char *psOut = &sTemp[0];
		char *psOutLastGood = psOut;
		unsigned int uiLetter;

		while ( *psText && (x + trap->R_Font_StrLenPixels( sTemp, iFontIndex, scale ) <= *maxX)
			&& psOut < &sTemp[sizeof(sTemp)-1] ) {
			int iAdvanceCount;
			psOutLastGood = psOut;

			uiLetter = trap->R_AnyLanguage_ReadCharFromString( psText, &iAdvanceCount, &bIsTrailingPunctuation );
			psText += iAdvanceCount;

			if ( uiLetter > 255 ) {
				*psOut++ = uiLetter >> 8;
				*psOut++ = uiLetter & 0xFF;
			}
			else
示例#2
0
static void DrawPlayerCount_Free( float fade ) {
	const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPLARGE );
	const float fontScale = 0.5f, width = SCREEN_WIDTH / 2.0f, lineHeight = 14.0f;
	float y = 108.0f;
	const char *tmp = NULL;
	vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f };
	int i, freeCount = 0, specCount = 0, botCount = 0;

	colour.a = fade;

	for ( i = 0; i < cg.numScores; i++ ) {
		clientInfo_t *ci = &cgs.clientinfo[cg.scores[i].client];
		if ( ci->team == TEAM_FREE )
			freeCount++;
		else if ( ci->team == TEAM_SPECTATOR )
			specCount++;
		if ( ci->botSkill != -1 )
			botCount++;
	}

	// player count
	if ( botCount )
		tmp = va( "%i players / %i bots", freeCount - botCount, botCount );
	else
		tmp = va( "%i players", freeCount );
	trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp, &colour,
		fontHandle, -1, fontScale );

	// spectator count
	tmp = va( "%2i spectators", specCount );
	trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y + lineHeight * 20,
		tmp, &colour, fontHandle, -1, fontScale );
}
示例#3
0
文件: cg_newdraw.c 项目: Razish/QtZ
void CG_DrawFlagCarrierName( void ) {
	int fontHandle = MenuFontToHandle( FONT_Q3PLARGE );
	float fontScale = 0.137f;
	vector4 color = { 1.0f, 1.0f, 1.0f, 1.0f };
	vector3 worldPos = { 0.0f, 0.0f, 0.0f };
	vector2 screenPos = { 0.0f, 0.0f };
	char text[] = "FLAG CARRIER";

	if ( (cgs.gametype < GT_FLAGS || !cg_drawFlagCarrier.boolean || cg.q3p.flagCarrierEntityNum == ENTITYNUM_NONE) && !cg_debugHUD->integer )
		return;

	VectorCopy( cg_entities[cg.q3p.flagCarrierEntityNum].lerpOrigin, worldPos );
	worldPos[2] += 64.0f;

	//FIXME: skews position on non 4:3 ratios
	// fix is in modbase/ja++
	CG_WorldCoordToScreenCoordFloat( worldPos, &screenPos[0], &screenPos[1] );

	trap->R_Font_DrawString( screenPos[0] - trap->R_Font_StrLenPixels( text, fontHandle, fontScale )/2.0f, screenPos[1], text, color, fontHandle|STYLE_DROPSHADOW, -1, fontScale );

	//already drawn it this frame, reset ent num so we can scan again next frame
	cg.q3p.flagCarrierEntityNum = ENTITYNUM_NONE;

	trap->R_SetColor( NULL );
}
示例#4
0
// shows current date and JA++ version
static void DrawClientInfo( float fade ) {
	struct tm *timeinfo;
	time_t tm;
	char buf[256];
	const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPMONO );
	const float fontScale = 0.5f;
	const float lineHeight = trap->R_Font_HeightPixels( fontHandle, fontScale );
	float y = SCREEN_HEIGHT - lineHeight - 4.0f;
	vector4 colour;

	VectorCopy4( &g_color_table[ColorIndex( COLOR_ORANGE )], &colour );
	colour.a = fade;

#ifdef REVISION
	// JA++ version
	trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( REVISION, fontHandle, fontScale ) - 21.0f, y,
		REVISION, &colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale );
	y -= lineHeight;
#endif

	// date
	time( &tm );
	timeinfo = localtime( &tm );

	Com_sprintf( buf, sizeof(buf), "%s %i%s %04i, %02i:%02i:%02i", months[timeinfo->tm_mon], timeinfo->tm_mday,
		GetDateSuffix( timeinfo->tm_mday ), 1900 + timeinfo->tm_year, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec );

	trap->R_Font_DrawString( SCREEN_WIDTH - trap->R_Font_StrLenPixels( buf, fontHandle, fontScale ) - 12.0f, y, buf,
		&colour, fontHandle | STYLE_DROPSHADOW, -1, fontScale );
}
void JKG_Slice_DrawGridSummary(int slot, float x, float y, float w, float h) {
	static const vec4_t topcol = {.2, 1, .2, 0.2f};
	static const vec4_t botcol = {1, 0.2, 0.2, 0.2f};

	int orientation = (slot >> 3) & 1;		// 0 = Columns, 1 = Rows
	int index = slot & 7;

	vec4_t color;

	const char *text;

	float w2;

	if ((orientation == 0 && index >= sliceData.width) || (orientation == 1 && index >= sliceData.height) ) {
		UI_DrawRect(x, y, w, h, disabled);
		return;
	} else {
		UI_FillRect(x, y, w, h/2, topcol);
		UI_FillRect(x, y + (0.5f * h), w, h/2, botcol);
		if (sliceData.inputState == INPUTSTATE_AWAITINGLINE) {
			float phase = 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f;
			MAKERGBA(color, phase, phase, phase, 1.0f);
			UI_DrawRect(x, y, w, h, color);
		} else {
			UI_DrawRect(x, y, w, h, black);
		}
	}


	if (sliceData.summariesKnown) {
		text = va("%i", sliceData.summaries[slot].value);
		w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
		DC->drawText(x + (w/2) - (w2/2), y-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 );

		text = va("%i", sliceData.summaries[slot].alarms);
		w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
		DC->drawText(x + (w/2) - (w2/2), y+(h*0.5f)-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 );
	} else {
		text = "?";
		w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
		DC->drawText(x + (w/2) - (w2/2), y-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 );

		w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
		DC->drawText(x + (w/2) - (w2/2), y+(h*0.5f)-1, 0.4f, const_cast<float *>(white), text, 0, 0, 0, 0 );
	}

}
void JKG_Slice_DrawDialog(int line, float x, float y, float w, float h) {
	float width;
	const char *text;

	if (!sliceData.dlgActive) {
		return;
	}
	if (line == 1) {
		text = sliceData.dlgText1;
	} else if (line == 2) {
		text = sliceData.dlgText2;
	} else {
		text = sliceData.dlgText3;
	}

	width = (float)trap->R_Font_StrLenPixels(text, MenuFontToHandle(1), 1) * 0.5f;

	x = x + ((w / 2) - (width / 2));
	trap->R_Font_DrawString(	x, y, text, colorWhite, MenuFontToHandle(1) | 0x80000000 , -1, 0.5f);
}
示例#7
0
static void DrawPlayers_Free( float fade ) {
	const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() );
	const float fontScale = 0.45f, lineHeight = 14.0f;
	float x = 0, y = 128.0f;
	const int playerCount = PlayerCount( TEAM_FREE );

	// dirty hack, 7 players means 4 on left, so +1 then /2 (8/2==4) will give a good number (4 left, 3 right)
	//	similarly, 8 players means 4 on left, so +1 then /2 (9/2==4) will give a good number (4 left, 4 right)
	ListPlayers_Free( fade, x, y, fontScale, fontHandle, lineHeight, 0, (playerCount + 1) / 2 );
	ListPlayers_Free( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, (playerCount + 1) / 2, playerCount / 2 );

	DrawSpectators( fade );
}
示例#8
0
void JKG_PartyMngt_DrawDialog(int line, float x, float y, float w, float h) {
	float width;
	const char *text;
	//vec4_t shadow;

	if (!PDlgData.InUse) {
		return;
	}
	if (line == 1) {
		text = PDlgData.line1;
	} else if (line == 2) {
		text = PDlgData.line2;
	} else {
		text = PDlgData.line3;
	}

	width = (float)trap->R_Font_StrLenPixels(text, MenuFontToHandle(1), 1) * 0.5f;

	x = x + ((w / 2) - (width / 2));
	//MAKERGBA(shadow,0,0,0,0.2f);
	//trap->R_Font_DrawString(	x+1, y+1, text, shadow, MenuFontToHandle(1), -1, 0.5f);
	trap->R_Font_DrawString(	x, y, text, colorWhite, MenuFontToHandle(1) | 0x80000000 , -1, 0.5f);
}
示例#9
0
void DrawPlayerCount_Team( float fade ) {
	const qhandle_t fontHandle = MenuFontToHandle( FONT_JAPPLARGE );
	const float fontScale = 0.5f, width = SCREEN_WIDTH / 2.0f, lineHeight = 14.0f;
	float y = 108.0f;
	const char *tmp = NULL;
	vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f };
	int i, redCount = 0, blueCount = 0, specCount = 0, pingAccumRed = 0, pingAvgRed = 0, pingAccumBlue = 0, pingAvgBlue = 0;
	colour.a = fade;

	for ( i = 0; i < cg.numScores; i++ ) {
		if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_RED ) {
			pingAccumRed += cg.scores[i].ping;
			redCount++;
		}
		else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_BLUE ) {
			blueCount++;
			pingAccumBlue += cg.scores[i].ping;
		}
		else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR )
			specCount++;
	}

	if ( redCount )
		pingAvgRed = ceilf( pingAccumRed / redCount );
	if ( blueCount )
		pingAvgBlue = ceilf( pingAccumBlue / blueCount );

	if ( cgs.scores1 >= cgs.scores2 ) {
		// red team
		tmp = va( S_COLOR_RED "%i players " S_COLOR_WHITE "(%3i avg ping)", redCount, pingAvgRed );
		trap->R_Font_DrawString( width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp,
			&colour, fontHandle, -1, fontScale );
		// blue team
		tmp = va( S_COLOR_CYAN "%i players " S_COLOR_WHITE "(%3i avg ping)", blueCount, pingAvgBlue );
		trap->R_Font_DrawString( width + width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp,
			&colour, fontHandle, -1, fontScale );
	}
	else {
		tmp = va( S_COLOR_CYAN "%i players " S_COLOR_WHITE "(%i avg ping)", blueCount, pingAvgBlue );
		trap->R_Font_DrawString( width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp,
			&colour, fontHandle, -1, fontScale );
		tmp = va( S_COLOR_RED "%i players " S_COLOR_WHITE "(%i avg ping)", redCount, pingAvgRed );
		trap->R_Font_DrawString( width + width / 2.0f - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y, tmp,
			&colour, fontHandle, -1, fontScale );
	}

	tmp = va( "%2i spectators", specCount );
	trap->R_Font_DrawString( width - trap->R_Font_StrLenPixels( tmp, fontHandle, fontScale ) / 2.0f, y + lineHeight * 20,
		tmp, &colour, fontHandle, -1, fontScale );
}
示例#10
0
static void DrawPlayers_Team( float fade ) {
	const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() );
	const float fontScale = 0.5f, lineHeight = 14.0f;
	float x = 0, y = 128.0f;

	if ( cgs.scores1 >= cgs.scores2 ) {
		ListPlayers_Team( fade, x, y, fontScale, fontHandle, lineHeight, TEAM_RED );
		ListPlayers_Team( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, TEAM_BLUE );
	}
	else {
		ListPlayers_Team( fade, x, y, fontScale, fontHandle, lineHeight, TEAM_BLUE );
		ListPlayers_Team( fade, x + SCREEN_WIDTH / 2.0f, y, fontScale, fontHandle, lineHeight, TEAM_RED );
	}

	DrawSpectators( fade );
}
示例#11
0
static void DrawSpectators( float fade ) {
	const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() );
	const float fontScale = 0.5f, lineHeight = 14.0f;
	float y = 128.0f;
	vector4 white = { 1.0f, 1.0f, 1.0f, 1.0f };
	white.a = fade;

	CG_BuildSpectatorString();
	cg.scoreboard.spectatorWidth = CG_Text_Width( cg.scoreboard.spectatorList, fontScale, fontHandle );

	if ( cg.scoreboard.spectatorLen ) {
		const float dt = (cg.time - cg.scoreboard.spectatorResetTime)*0.0625f;
		cg.scoreboard.spectatorX = SCREEN_WIDTH - (1.0f)*dt;

		if ( cg.scoreboard.spectatorX < 0 - cg.scoreboard.spectatorWidth ) {
			cg.scoreboard.spectatorX = SCREEN_WIDTH;
			cg.scoreboard.spectatorResetTime = cg.time;
		}
		CG_Text_Paint( cg.scoreboard.spectatorX, (y + lineHeight * 20) - 3, fontScale, &white, cg.scoreboard.spectatorList,
			0, 0, ITEM_TEXTSTYLE_SHADOWED, fontHandle );
	}
}
void JKG_Slice_DrawSecurityClearance(int slot, float x, float y, float w, float h) {

	const char *text;

	float w2;

	if (slot >= sliceData.securityLevels) {
		UI_DrawRect(x, y, w, h, disabled);
		return;
	} else {
		switch (sliceData.securityState[slot])
		{
			case 0:
				UI_FillRect(x, y, w, h, red);
				break;
			case 1:
				UI_FillRect(x, y, w, h, orange);
				break;
			case 2:
				UI_FillRect(x, y, w, h, yellow);
				break;
			case 3:
				UI_FillRect(x, y, w, h, green);
				break;
		}

		UI_DrawRect(x, y, w, h, black);
	}


	text = va("%i", slot + 1);
	
	w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.5f;
	DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.5f, const_cast<float *>(white), text, 0, 0, 0, 0 );

}
示例#13
0
文件: cg_newdraw.c 项目: Razish/QtZ
void CG_DrawObituary( void ) {
	linkedList_t *node = NULL;
	float x = SCREEN_WIDTH/2.0f, y = 0.0f;
	float lineHeight = 20.0f;
	float iconSize = lineHeight*2.0f;
	int fontHandle = MenuFontToHandle( FONT_Q3PSMALL );
	float fontScale = 0.8f;//0.2175f;

	if ( !cg_newObituary->integer )
		return;

	trap->R_SetColor( NULL );

	if ( cg_debugHUD.boolean )
	{
		char *attackerName = "AttackerName";
		char *targetName = "TargetName";
		float attackerWidth = trap->R_Font_StrLenPixels( attackerName, fontHandle, fontScale );
		float iconWidth = 2.0f + iconSize + 2.0f;
		float victimWidth = trap->R_Font_StrLenPixels( targetName, fontHandle, fontScale );
		float totalWidth = attackerWidth + iconWidth + victimWidth;
		float startX = x - totalWidth/2.0f;

		trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );												startX += attackerWidth;
		CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_QUANTIZER] ].weaponIcon );		startX += iconWidth;
		trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );													startX += victimWidth;
		startX = x - totalWidth/2.0f;
		y += lineHeight;

		trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );												startX += attackerWidth;
		CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_MORTAR] ].weaponIcon );		startX += iconWidth;
		trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );													startX += victimWidth;
		startX = x - totalWidth/2.0f;
		y += lineHeight;

		trap->R_Font_DrawString( startX, y, attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );												startX += attackerWidth;
		CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[MOD_DIVERGENCE] ].weaponIcon );	startX += iconWidth;
		trap->R_Font_DrawString( startX, y, targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );													startX += victimWidth;
		startX = x - totalWidth/2.0f;
		y += lineHeight;
	}
	else
	{
		for ( node=cg.q3p.obituaryRoot; node; node=LinkedList_Traverse( node ) )
		{
			obituary_t *obituary = (obituary_t*)node->data;
			if ( obituary->deathTime < cg.time - cg_obituaryTime->integer )
			{//Free this object
				free( obituary );
				LinkedList_RemoveObject( &cg.q3p.obituaryRoot, node );
				node = cg.q3p.obituaryRoot;//HACK: Return to start of list
				continue;
			}
			else
			{
				float attackerWidth = trap->R_Font_StrLenPixels( obituary->attackerName, fontHandle, fontScale );
				float iconWidth = 2.0f + iconSize + 2.0f;
				float victimWidth = trap->R_Font_StrLenPixels( obituary->targetName, fontHandle, fontScale );
				float totalWidth = attackerWidth + iconWidth + victimWidth;
				float startX = x - totalWidth/2.0f;
				trap->R_Font_DrawString( startX, y, obituary->attackerName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );						startX += attackerWidth;
				CG_DrawPic( startX, y-(iconSize/2.0f)+lineHeight/2.0f, iconSize, iconSize, cg_weapons[ weaponFromMOD[obituary->mod] ].weaponIcon );		startX += iconWidth;
				trap->R_Font_DrawString( startX, y, obituary->targetName, g_color_table[ColorIndex(COLOR_WHITE)], fontHandle, -1, fontScale );						startX += victimWidth;
				y += lineHeight;
			}
		}
	}
}
示例#14
0
static void DrawServerInfo( float fade ) {
	const qhandle_t fontLarge = MenuFontToHandle( FONT_JAPPLARGE ), fontSmall = MenuFontToHandle( FONT_JAPPMONO );
	const float fontScale = 0.5f, lineHeightBig = 14.0f,
		lineHeightSmall = trap->R_Font_HeightPixels( fontSmall, fontScale );
	const char *tmp = NULL;
	float y = SCREEN_HEIGHT - lineHeightSmall - 4.0f;
	vector4 colour = { 1.0f, 1.0f, 1.0f, 1.0f };
	colour.a = fade;

	// map name
	tmp = va( "%s (%s)", (char *)CG_ConfigString( CS_MESSAGE ), cgs.mapname );
	trap->R_Font_DrawString( 0.0f, y, tmp, &colour, fontSmall | STYLE_DROPSHADOW, -1, fontScale );
	y -= lineHeightSmall;

	// server name
	trap->R_Font_DrawString( 0.0f, y, cgs.japp.serverName, &colour, fontSmall | STYLE_DROPSHADOW, -1, fontScale );
	y -= lineHeightSmall;

	y = 42.0f;

	// gametype
	tmp = BG_GetGametypeString( cgs.gametype );
	trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
		tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
	y += lineHeightBig;

	switch ( cgs.gametype ) {
	case GT_FFA:
		if ( cgs.timelimit && cgs.fraglimit ) {
			tmp = va( "Until " S_COLOR_YELLOW "%i " S_COLOR_WHITE "frags or " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/"
				S_COLOR_YELLOW "%i minutes", cgs.fraglimit, (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit );
		}
		else if ( cgs.timelimit ) {
			tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "minutes",
				(cg.time - cgs.levelStartTime) / 60000, cgs.timelimit );
		}
		else if ( cgs.fraglimit )
			tmp = va( "Until " S_COLOR_YELLOW "%i " S_COLOR_WHITE "frags", cgs.fraglimit );
		else
			tmp = "Playing forever!";

		trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
			tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
		break;

	case GT_CTF:
	case GT_CTY:
		if ( cgs.timelimit && cgs.capturelimit ) {
			tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "captures or "
				S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i minutes", max( cgs.scores1, cgs.scores2 ),
				cgs.capturelimit, (cg.time - cgs.levelStartTime) / 60000, cgs.timelimit );
		}
		else if ( cgs.timelimit ) {
			tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "minutes",
				(cg.time - cgs.levelStartTime) / 60000, cgs.timelimit );
		}
		else if ( cgs.capturelimit ) {
			tmp = va( "Until " S_COLOR_YELLOW "%i" S_COLOR_WHITE "/" S_COLOR_YELLOW "%i " S_COLOR_WHITE "captures",
				max( cgs.scores1, cgs.scores2 ), cgs.capturelimit );
		}
		else
			tmp = "Playing forever!";

		trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
			tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
		y += lineHeightBig * 2;
		//FALL THROUGH TO GENERIC TEAM GAME INFO!

	case GT_TEAM:
		if ( cgs.scores1 == cgs.scores2 ) {
			tmp = S_COLOR_YELLOW"Teams are tied";
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
				tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
			y += lineHeightBig;
			tmp = va( S_COLOR_RED"%i "S_COLOR_WHITE"/ "S_COLOR_CYAN"%i", cgs.scores1, cgs.scores2 );
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f,
				y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
		}
		else if ( cgs.scores1 > cgs.scores2 ) {
			tmp = S_COLOR_RED"Red "S_COLOR_WHITE"leads";
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f,
				y, tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
			y += lineHeightBig;
			tmp = va( S_COLOR_RED"%i "S_COLOR_WHITE"/ "S_COLOR_CYAN"%i", cgs.scores1, cgs.scores2 );
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
				tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
		}
		else {
			tmp = S_COLOR_CYAN"Blue "S_COLOR_WHITE"leads";
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
				tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
			y += lineHeightBig;
			tmp = va( S_COLOR_CYAN"%i "S_COLOR_WHITE"/ "S_COLOR_RED"%i", cgs.scores2, cgs.scores1 );
			trap->R_Font_DrawString( SCREEN_WIDTH / 2.0f - trap->R_Font_StrLenPixels( tmp, fontLarge, fontScale ) / 2.0f, y,
				tmp, &colour, fontLarge | STYLE_DROPSHADOW, -1, fontScale );
		}
		//TODO: playing until x/y
		break;

	default:
		break;
	}
}
void JKG_Slice_DrawGridSlot(int slot, float x, float y, float w, float h)
{
	vec4_t color;
	vec4_t color2;

	int row = slot >> 3;
	int col = slot & 7;

	const char *text = NULL;
	float w2;

	if (row >= sliceData.height || col >= sliceData.width) {
		UI_DrawRect(x, y, w, h, disabled);
	} else {
		if (sliceData.grid[row][col].active) {
			// Determine the color to show
			switch (sliceData.grid[row][col].type) {
				case 0:	// Alarm node
					VectorCopy4M(red, color2);
					text = NULL;
					break;
				case 1:	// Relay node
					VectorCopy4M(orange, color2);
					text = NULL;
					break;
				case 2: // Reset node
					VectorCopy4M(yellow, color2);
					text = "R";
					break;
				case 3: // Access level 1
				case 4:	// Access level 2
				case 5:	// Access level 3
				case 6:	// Access level 4
				case 7: // Access level 5
					VectorCopy4M(green, color2);
					text = va("%i", sliceData.grid[row][col].type - 2);
					break;
			}

			if (sliceData.grid[row][col].revealTime) {
				float phase = (float)(trap->Milliseconds() - sliceData.grid[row][col].revealTime) / 250.0f;
				if (phase > 1.0f) phase = 1.0f;

				if (trap->Milliseconds() > sliceData.grid[row][col].revealTime + 250) {
					sliceData.grid[row][col].revealTime = 0;
				}

				LerpColor((float *)white, color2, color, phase);
				UI_FillRect(x, y, w, h, color);
				
				if (text) {
					color[0] = color[1] = color[2] = 1.0f;
					color[3] = phase;
					w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
					DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.4f, color, text, 0, 0, 0, 0 );
				}
			} else {
				UI_FillRect(x, y, w, h, color2);
				if (text) {
					w2 = trap->R_Font_StrLenPixels(text, MenuFontToHandle(0), 1.0f) * 0.4f;
					DC->drawText(x + (w/2) - (w2/2), y+(h*0.2f), 0.4f, (float *)(white), text, 0, 0, 0, 0 );
				}
			}
		} else {
			if (sliceData.grid[row][col].blinkTime) {
				int delta = trap->Milliseconds() - sliceData.grid[row][col].blinkTime;
				float phase;
				if (delta > 2350) {	 // ~(7.5 * PI)*100, so the node blinks 4 times and stops when faded out
					sliceData.grid[row][col].blinkTime = 0;
				}

				phase = 0.5f + (sin((float)delta / 100.0f) * 0.5);

				if (sliceData.grid[row][col].blinkColor) {
					LerpColor((float *)offcolor, (float *)green, color, phase);
				} else {
					LerpColor((float *)offcolor, (float *)red, color, phase);
				}

				UI_FillRect(x, y, w, h, color);
			} else {
				if (sliceData.grid[row][col].marked) {
					if (sliceData.grid[row][col].marked == 1) {
						MAKERGBA(color, 0.3f, 0.3f, 1.0f, 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f);
					} else {
						MAKERGBA(color, 1.0f, 0.3f, .3f, 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f);
					}
					UI_FillRect(x, y, w, h, color);
				} else {
					UI_FillRect(x, y, w, h, offcolor);
				}
			}
		}

		if (sliceData.inputState == INPUTSTATE_AWAITINGNODE || (sliceData.inputState == INPUTSTATE_AWAITINGINACTIVENODE && !sliceData.grid[row][col].active)) {
			float phase = 0.7f + sin((float)trap->Milliseconds() / 150.0f) * 0.1f;
			MAKERGBA(color, phase, phase, phase, 1.0f);
			UI_DrawRect(x, y, w, h, color);
		} else {
			UI_DrawRect(x, y, w, h, black);
		}
	}
}