Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

cg_newdraw.c (50495B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #ifndef MISSIONPACK // bk001204
     24 #error This file not be used for classic Q3A.
     25 #endif
     26 
     27 #include "cg_local.h"
     28 #include "../ui/ui_shared.h"
     29 
     30 extern displayContextDef_t cgDC;
     31 
     32 
     33 // set in CG_ParseTeamInfo
     34 
     35 //static int sortedTeamPlayers[TEAM_MAXOVERLAY];
     36 //static int numSortedTeamPlayers;
     37 int drawTeamOverlayModificationCount = -1;
     38 
     39 //static char systemChat[256];
     40 //static char teamChat1[256];
     41 //static char teamChat2[256];
     42 
     43 void CG_InitTeamChat() {
     44   memset(teamChat1, 0, sizeof(teamChat1));
     45   memset(teamChat2, 0, sizeof(teamChat2));
     46   memset(systemChat, 0, sizeof(systemChat));
     47 }
     48 
     49 void CG_SetPrintString(int type, const char *p) {
     50   if (type == SYSTEM_PRINT) {
     51     strcpy(systemChat, p);
     52   } else {
     53     strcpy(teamChat2, teamChat1);
     54     strcpy(teamChat1, p);
     55   }
     56 }
     57 
     58 void CG_CheckOrderPending() {
     59 	if (cgs.gametype < GT_CTF) {
     60 		return;
     61 	}
     62 	if (cgs.orderPending) {
     63 		//clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
     64 		const char *p1, *p2, *b;
     65 		p1 = p2 = b = NULL;
     66 		switch (cgs.currentOrder) {
     67 			case TEAMTASK_OFFENSE:
     68 				p1 = VOICECHAT_ONOFFENSE;
     69 				p2 = VOICECHAT_OFFENSE;
     70 				b = "+button7; wait; -button7";
     71 			break;
     72 			case TEAMTASK_DEFENSE:
     73 				p1 = VOICECHAT_ONDEFENSE;
     74 				p2 = VOICECHAT_DEFEND;
     75 				b = "+button8; wait; -button8";
     76 			break;					
     77 			case TEAMTASK_PATROL:
     78 				p1 = VOICECHAT_ONPATROL;
     79 				p2 = VOICECHAT_PATROL;
     80 				b = "+button9; wait; -button9";
     81 			break;
     82 			case TEAMTASK_FOLLOW: 
     83 				p1 = VOICECHAT_ONFOLLOW;
     84 				p2 = VOICECHAT_FOLLOWME;
     85 				b = "+button10; wait; -button10";
     86 			break;
     87 			case TEAMTASK_CAMP:
     88 				p1 = VOICECHAT_ONCAMPING;
     89 				p2 = VOICECHAT_CAMP;
     90 			break;
     91 			case TEAMTASK_RETRIEVE:
     92 				p1 = VOICECHAT_ONGETFLAG;
     93 				p2 = VOICECHAT_RETURNFLAG;
     94 			break;
     95 			case TEAMTASK_ESCORT:
     96 				p1 = VOICECHAT_ONFOLLOWCARRIER;
     97 				p2 = VOICECHAT_FOLLOWFLAGCARRIER;
     98 			break;
     99 		}
    100 
    101 		if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
    102 			// to everyone
    103 			trap_SendConsoleCommand(va("cmd vsay_team %s\n", p2));
    104 		} else {
    105 			// for the player self
    106 			if (sortedTeamPlayers[cg_currentSelectedPlayer.integer] == cg.snap->ps.clientNum && p1) {
    107 				trap_SendConsoleCommand(va("teamtask %i\n", cgs.currentOrder));
    108 				//trap_SendConsoleCommand(va("cmd say_team %s\n", p2));
    109 				trap_SendConsoleCommand(va("cmd vsay_team %s\n", p1));
    110 			} else if (p2) {
    111 				//trap_SendConsoleCommand(va("cmd say_team %s, %s\n", ci->name,p));
    112 				trap_SendConsoleCommand(va("cmd vtell %d %s\n", sortedTeamPlayers[cg_currentSelectedPlayer.integer], p2));
    113 			}
    114 		}
    115 		if (b) {
    116 			trap_SendConsoleCommand(b);
    117 		}
    118 		cgs.orderPending = qfalse;
    119 	}
    120 }
    121 
    122 static void CG_SetSelectedPlayerName() {
    123   if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
    124 		clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
    125 	  if (ci) {
    126 			trap_Cvar_Set("cg_selectedPlayerName", ci->name);
    127 			trap_Cvar_Set("cg_selectedPlayer", va("%d", sortedTeamPlayers[cg_currentSelectedPlayer.integer]));
    128 			cgs.currentOrder = ci->teamTask;
    129 	  }
    130 	} else {
    131 		trap_Cvar_Set("cg_selectedPlayerName", "Everyone");
    132 	}
    133 }
    134 int CG_GetSelectedPlayer() {
    135 	if (cg_currentSelectedPlayer.integer < 0 || cg_currentSelectedPlayer.integer >= numSortedTeamPlayers) {
    136 		cg_currentSelectedPlayer.integer = 0;
    137 	}
    138 	return cg_currentSelectedPlayer.integer;
    139 }
    140 
    141 void CG_SelectNextPlayer() {
    142 	CG_CheckOrderPending();
    143 	if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
    144 		cg_currentSelectedPlayer.integer++;
    145 	} else {
    146 		cg_currentSelectedPlayer.integer = 0;
    147 	}
    148 	CG_SetSelectedPlayerName();
    149 }
    150 
    151 void CG_SelectPrevPlayer() {
    152 	CG_CheckOrderPending();
    153 	if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
    154 		cg_currentSelectedPlayer.integer--;
    155 	} else {
    156 		cg_currentSelectedPlayer.integer = numSortedTeamPlayers;
    157 	}
    158 	CG_SetSelectedPlayerName();
    159 }
    160 
    161 
    162 static void CG_DrawPlayerArmorIcon( rectDef_t *rect, qboolean draw2D ) {
    163 	centity_t	*cent;
    164 	playerState_t	*ps;
    165 	vec3_t		angles;
    166 	vec3_t		origin;
    167 
    168   if ( cg_drawStatus.integer == 0 ) {
    169 		return;
    170 	}
    171 
    172 	cent = &cg_entities[cg.snap->ps.clientNum];
    173 	ps = &cg.snap->ps;
    174 
    175 	if ( draw2D || ( !cg_draw3dIcons.integer && cg_drawIcons.integer) ) { // bk001206 - parentheses
    176 		CG_DrawPic( rect->x, rect->y + rect->h/2 + 1, rect->w, rect->h, cgs.media.armorIcon );
    177   } else if (cg_draw3dIcons.integer) {
    178 	  VectorClear( angles );
    179     origin[0] = 90;
    180   	origin[1] = 0;
    181   	origin[2] = -10;
    182   	angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
    183   
    184     CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cgs.media.armorModel, 0, origin, angles );
    185   }
    186 
    187 }
    188 
    189 static void CG_DrawPlayerArmorValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
    190 	char	num[16];
    191   int value;
    192 	centity_t	*cent;
    193 	playerState_t	*ps;
    194 
    195   cent = &cg_entities[cg.snap->ps.clientNum];
    196 	ps = &cg.snap->ps;
    197 
    198 	value = ps->stats[STAT_ARMOR];
    199   
    200 
    201 	if (shader) {
    202     trap_R_SetColor( color );
    203 		CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    204 	  trap_R_SetColor( NULL );
    205 	} else {
    206 		Com_sprintf (num, sizeof(num), "%i", value);
    207 		value = CG_Text_Width(num, scale, 0);
    208 	  CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    209 	}
    210 }
    211 
    212 #ifndef MISSIONPACK // bk001206 
    213 static float healthColors[4][4] = { 
    214 //		{ 0.2, 1.0, 0.2, 1.0 } , { 1.0, 0.2, 0.2, 1.0 }, {0.5, 0.5, 0.5, 1} };
    215   // bk0101016 - float const
    216   { 1.0f, 0.69f, 0.0f, 1.0f } ,		// normal
    217   { 1.0f, 0.2f, 0.2f, 1.0f },		// low health
    218   { 0.5f, 0.5f, 0.5f, 1.0f},		// weapon firing
    219   { 1.0f, 1.0f, 1.0f, 1.0f } };		// health > 100
    220 #endif
    221 
    222 static void CG_DrawPlayerAmmoIcon( rectDef_t *rect, qboolean draw2D ) {
    223 	centity_t	*cent;
    224 	playerState_t	*ps;
    225 	vec3_t		angles;
    226 	vec3_t		origin;
    227 
    228 	cent = &cg_entities[cg.snap->ps.clientNum];
    229 	ps = &cg.snap->ps;
    230 
    231 	if ( draw2D || (!cg_draw3dIcons.integer && cg_drawIcons.integer) ) { // bk001206 - parentheses
    232 	  qhandle_t	icon;
    233     icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon;
    234 		if ( icon ) {
    235 		  CG_DrawPic( rect->x, rect->y, rect->w, rect->h, icon );
    236 		}
    237   } else if (cg_draw3dIcons.integer) {
    238   	if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) {
    239 	    VectorClear( angles );
    240 	  	origin[0] = 70;
    241   		origin[1] = 0;
    242   		origin[2] = 0;
    243   		angles[YAW] = 90 + 20 * sin( cg.time / 1000.0 );
    244   		CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, origin, angles );
    245   	}
    246   }
    247 }
    248 
    249 static void CG_DrawPlayerAmmoValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
    250 	char	num[16];
    251 	int value;
    252 	centity_t	*cent;
    253 	playerState_t	*ps;
    254 
    255 	cent = &cg_entities[cg.snap->ps.clientNum];
    256 	ps = &cg.snap->ps;
    257 
    258 	if ( cent->currentState.weapon ) {
    259 		value = ps->ammo[cent->currentState.weapon];
    260 		if ( value > -1 ) {
    261 			if (shader) {
    262 		    trap_R_SetColor( color );
    263 				CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    264 			  trap_R_SetColor( NULL );
    265 			} else {
    266 				Com_sprintf (num, sizeof(num), "%i", value);
    267 				value = CG_Text_Width(num, scale, 0);
    268 				CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    269 			}
    270 		}
    271 	}
    272 
    273 }
    274 
    275 
    276 
    277 static void CG_DrawPlayerHead(rectDef_t *rect, qboolean draw2D) {
    278 	vec3_t		angles;
    279 	float		size, stretch;
    280 	float		frac;
    281 	float		x = rect->x;
    282 
    283 	VectorClear( angles );
    284 
    285 	if ( cg.damageTime && cg.time - cg.damageTime < DAMAGE_TIME ) {
    286 		frac = (float)(cg.time - cg.damageTime ) / DAMAGE_TIME;
    287 		size = rect->w * 1.25 * ( 1.5 - frac * 0.5 );
    288 
    289 		stretch = size - rect->w * 1.25;
    290 		// kick in the direction of damage
    291 		x -= stretch * 0.5 + cg.damageX * stretch * 0.5;
    292 
    293 		cg.headStartYaw = 180 + cg.damageX * 45;
    294 
    295 		cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
    296 		cg.headEndPitch = 5 * cos( crandom()*M_PI );
    297 
    298 		cg.headStartTime = cg.time;
    299 		cg.headEndTime = cg.time + 100 + random() * 2000;
    300 	} else {
    301 		if ( cg.time >= cg.headEndTime ) {
    302 			// select a new head angle
    303 			cg.headStartYaw = cg.headEndYaw;
    304 			cg.headStartPitch = cg.headEndPitch;
    305 			cg.headStartTime = cg.headEndTime;
    306 			cg.headEndTime = cg.time + 100 + random() * 2000;
    307 
    308 			cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
    309 			cg.headEndPitch = 5 * cos( crandom()*M_PI );
    310 		}
    311 
    312 		size = rect->w * 1.25;
    313 	}
    314 
    315 	// if the server was frozen for a while we may have a bad head start time
    316 	if ( cg.headStartTime > cg.time ) {
    317 		cg.headStartTime = cg.time;
    318 	}
    319 
    320 	frac = ( cg.time - cg.headStartTime ) / (float)( cg.headEndTime - cg.headStartTime );
    321 	frac = frac * frac * ( 3 - 2 * frac );
    322 	angles[YAW] = cg.headStartYaw + ( cg.headEndYaw - cg.headStartYaw ) * frac;
    323 	angles[PITCH] = cg.headStartPitch + ( cg.headEndPitch - cg.headStartPitch ) * frac;
    324 
    325 	CG_DrawHead( x, rect->y, rect->w, rect->h, cg.snap->ps.clientNum, angles );
    326 }
    327 
    328 static void CG_DrawSelectedPlayerHealth( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    329 	clientInfo_t *ci;
    330 	int value;
    331 	char num[16];
    332 
    333   ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    334   if (ci) {
    335 		if (shader) {
    336 			trap_R_SetColor( color );
    337 			CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    338 			trap_R_SetColor( NULL );
    339 		} else {
    340 			Com_sprintf (num, sizeof(num), "%i", ci->health);
    341 		  value = CG_Text_Width(num, scale, 0);
    342 		  CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    343 		}
    344 	}
    345 }
    346 
    347 static void CG_DrawSelectedPlayerArmor( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    348 	clientInfo_t *ci;
    349 	int value;
    350 	char num[16];
    351   ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    352   if (ci) {
    353     if (ci->armor > 0) {
    354 			if (shader) {
    355 				trap_R_SetColor( color );
    356 				CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    357 				trap_R_SetColor( NULL );
    358 			} else {
    359 				Com_sprintf (num, sizeof(num), "%i", ci->armor);
    360 				value = CG_Text_Width(num, scale, 0);
    361 				CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    362 			}
    363 		}
    364  	}
    365 }
    366 
    367 qhandle_t CG_StatusHandle(int task) {
    368 	qhandle_t h = cgs.media.assaultShader;
    369 	switch (task) {
    370 		case TEAMTASK_OFFENSE :
    371 			h = cgs.media.assaultShader;
    372 			break;
    373 		case TEAMTASK_DEFENSE :
    374 			h = cgs.media.defendShader;
    375 			break;
    376 		case TEAMTASK_PATROL :
    377 			h = cgs.media.patrolShader;
    378 			break;
    379 		case TEAMTASK_FOLLOW :
    380 			h = cgs.media.followShader;
    381 			break;
    382 		case TEAMTASK_CAMP :
    383 			h = cgs.media.campShader;
    384 			break;
    385 		case TEAMTASK_RETRIEVE :
    386 			h = cgs.media.retrieveShader; 
    387 			break;
    388 		case TEAMTASK_ESCORT :
    389 			h = cgs.media.escortShader; 
    390 			break;
    391 		default : 
    392 			h = cgs.media.assaultShader;
    393 			break;
    394 	}
    395 	return h;
    396 }
    397 
    398 static void CG_DrawSelectedPlayerStatus( rectDef_t *rect ) {
    399 	clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    400 	if (ci) {
    401 		qhandle_t h;
    402 		if (cgs.orderPending) {
    403 			// blink the icon
    404 			if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
    405 				return;
    406 			}
    407 			h = CG_StatusHandle(cgs.currentOrder);
    408 		}	else {
    409 			h = CG_StatusHandle(ci->teamTask);
    410 		}
    411 		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h );
    412 	}
    413 }
    414 
    415 
    416 static void CG_DrawPlayerStatus( rectDef_t *rect ) {
    417 	clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
    418 	if (ci) {
    419 		qhandle_t h = CG_StatusHandle(ci->teamTask);
    420 		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h);
    421 	}
    422 }
    423 
    424 
    425 static void CG_DrawSelectedPlayerName( rectDef_t *rect, float scale, vec4_t color, qboolean voice, int textStyle) {
    426 	clientInfo_t *ci;
    427   ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
    428   if (ci) {
    429     CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, ci->name, 0, 0, textStyle);
    430   }
    431 }
    432 
    433 static void CG_DrawSelectedPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
    434 	clientInfo_t *ci;
    435   ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    436   if (ci) {
    437 		const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
    438 		if (!p || !*p) {
    439 			p = "unknown";
    440 		}
    441     CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
    442   }
    443 }
    444 
    445 static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle  ) {
    446 	clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
    447   if (ci) {
    448 		const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
    449 		if (!p || !*p) {
    450 			p = "unknown";
    451 		}
    452     CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
    453   }
    454 }
    455 
    456 
    457 
    458 static void CG_DrawSelectedPlayerWeapon( rectDef_t *rect ) {
    459 	clientInfo_t *ci;
    460 
    461   ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    462   if (ci) {
    463 	  if ( cg_weapons[ci->curWeapon].weaponIcon ) {
    464 	    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ci->curWeapon].weaponIcon );
    465 		} else {
    466   	  CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader);
    467     }
    468   }
    469 }
    470 
    471 static void CG_DrawPlayerScore( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    472   char num[16];
    473   int value = cg.snap->ps.persistant[PERS_SCORE];
    474 
    475 	if (shader) {
    476 		trap_R_SetColor( color );
    477 		CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    478 		trap_R_SetColor( NULL );
    479 	} else {
    480 		Com_sprintf (num, sizeof(num), "%i", value);
    481 		value = CG_Text_Width(num, scale, 0);
    482 	  CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    483 	}
    484 }
    485 
    486 static void CG_DrawPlayerItem( rectDef_t *rect, float scale, qboolean draw2D) {
    487 	int		value;
    488   vec3_t origin, angles;
    489 
    490 	value = cg.snap->ps.stats[STAT_HOLDABLE_ITEM];
    491 	if ( value ) {
    492 		CG_RegisterItemVisuals( value );
    493 
    494 		if (qtrue) {
    495 		  CG_RegisterItemVisuals( value );
    496 		  CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
    497 		} else {
    498  			VectorClear( angles );
    499 			origin[0] = 90;
    500   		origin[1] = 0;
    501    		origin[2] = -10;
    502   		angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
    503 			CG_Draw3DModel(rect->x, rect->y, rect->w, rect->h, cg_items[ value ].models[0], 0, origin, angles );
    504 		}
    505 	}
    506 
    507 }
    508 
    509 
    510 static void CG_DrawSelectedPlayerPowerup( rectDef_t *rect, qboolean draw2D ) {
    511 	clientInfo_t *ci;
    512   int j;
    513   float x, y;
    514 
    515   ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    516   if (ci) {
    517     x = rect->x;
    518     y = rect->y;
    519 
    520 		for (j = 0; j < PW_NUM_POWERUPS; j++) {
    521 			if (ci->powerups & (1 << j)) {
    522 				gitem_t	*item;
    523 				item = BG_FindItemForPowerup( j );
    524 				if (item) {
    525 				  CG_DrawPic( x, y, rect->w, rect->h, trap_R_RegisterShader( item->icon ) );
    526 					x += 3;
    527 					y += 3;
    528           return;
    529 				}
    530 			}
    531 		}
    532 
    533   }
    534 }
    535 
    536 
    537 static void CG_DrawSelectedPlayerHead( rectDef_t *rect, qboolean draw2D, qboolean voice ) {
    538 	clipHandle_t	cm;
    539 	clientInfo_t	*ci;
    540 	float			len;
    541 	vec3_t			origin;
    542 	vec3_t			mins, maxs, angles;
    543 
    544 
    545   ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
    546 
    547   if (ci) {
    548   	if ( cg_draw3dIcons.integer ) {
    549 	  	cm = ci->headModel;
    550   		if ( !cm ) {
    551   			return;
    552 	  	}
    553 
    554   		// offset the origin y and z to center the head
    555   		trap_R_ModelBounds( cm, mins, maxs );
    556 
    557 	  	origin[2] = -0.5 * ( mins[2] + maxs[2] );
    558   		origin[1] = 0.5 * ( mins[1] + maxs[1] );
    559 
    560 	  	// calculate distance so the head nearly fills the box
    561   		// assume heads are taller than wide
    562   		len = 0.7 * ( maxs[2] - mins[2] );		
    563   		origin[0] = len / 0.268;	// len / tan( fov/2 )
    564 
    565   		// allow per-model tweaking
    566   		VectorAdd( origin, ci->headOffset, origin );
    567 
    568     	angles[PITCH] = 0;
    569     	angles[YAW] = 180;
    570     	angles[ROLL] = 0;
    571   	
    572       CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, ci->headModel, ci->headSkin, origin, angles );
    573   	} else if ( cg_drawIcons.integer ) {
    574 	  	CG_DrawPic( rect->x, rect->y, rect->w, rect->h, ci->modelIcon );
    575   	}
    576 
    577   	// if they are deferred, draw a cross out
    578   	if ( ci->deferred ) {
    579   		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader );
    580   	}
    581   }
    582 
    583 }
    584 
    585 
    586 static void CG_DrawPlayerHealth(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    587 	playerState_t	*ps;
    588   int value;
    589 	char	num[16];
    590 
    591 	ps = &cg.snap->ps;
    592 
    593 	value = ps->stats[STAT_HEALTH];
    594 
    595 	if (shader) {
    596 		trap_R_SetColor( color );
    597 		CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
    598 		trap_R_SetColor( NULL );
    599 	} else {
    600 		Com_sprintf (num, sizeof(num), "%i", value);
    601 	  value = CG_Text_Width(num, scale, 0);
    602 	  CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    603 	}
    604 }
    605 
    606 
    607 static void CG_DrawRedScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    608 	int value;
    609 	char num[16];
    610 	if ( cgs.scores1 == SCORE_NOT_PRESENT ) {
    611 		Com_sprintf (num, sizeof(num), "-");
    612 	}
    613 	else {
    614 		Com_sprintf (num, sizeof(num), "%i", cgs.scores1);
    615 	}
    616 	value = CG_Text_Width(num, scale, 0);
    617 	CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    618 }
    619 
    620 static void CG_DrawBlueScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
    621 	int value;
    622 	char num[16];
    623 
    624 	if ( cgs.scores2 == SCORE_NOT_PRESENT ) {
    625 		Com_sprintf (num, sizeof(num), "-");
    626 	}
    627 	else {
    628 		Com_sprintf (num, sizeof(num), "%i", cgs.scores2);
    629 	}
    630 	value = CG_Text_Width(num, scale, 0);
    631 	CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    632 }
    633 
    634 // FIXME: team name support
    635 static void CG_DrawRedName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
    636   CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_redTeamName.string , 0, 0, textStyle);
    637 }
    638 
    639 static void CG_DrawBlueName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
    640   CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_blueTeamName.string, 0, 0, textStyle);
    641 }
    642 
    643 static void CG_DrawBlueFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
    644   int i;
    645   for ( i = 0 ; i < cgs.maxclients ; i++ ) {
    646 	  if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED  && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
    647       CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
    648       return;
    649     }
    650   }
    651 }
    652 
    653 static void CG_DrawBlueFlagStatus(rectDef_t *rect, qhandle_t shader) {
    654 	if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
    655 		if (cgs.gametype == GT_HARVESTER) {
    656 		  vec4_t color = {0, 0, 1, 1};
    657 		  trap_R_SetColor(color);
    658 	    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.blueCubeIcon );
    659 		  trap_R_SetColor(NULL);
    660 		}
    661 		return;
    662 	}
    663   if (shader) {
    664 		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
    665   } else {
    666 	  gitem_t *item = BG_FindItemForPowerup( PW_BLUEFLAG );
    667     if (item) {
    668 		  vec4_t color = {0, 0, 1, 1};
    669 		  trap_R_SetColor(color);
    670 	    if( cgs.blueflag >= 0 && cgs.blueflag <= 2 ) {
    671 		    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.blueflag] );
    672 			} else {
    673 		    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
    674 			}
    675 		  trap_R_SetColor(NULL);
    676 	  }
    677   }
    678 }
    679 
    680 static void CG_DrawBlueFlagHead(rectDef_t *rect) {
    681   int i;
    682   for ( i = 0 ; i < cgs.maxclients ; i++ ) {
    683 	  if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED  && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
    684       vec3_t angles;
    685       VectorClear( angles );
    686  		  angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
    687       CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
    688       return;
    689     }
    690   }
    691 }
    692 
    693 static void CG_DrawRedFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
    694   int i;
    695   for ( i = 0 ; i < cgs.maxclients ; i++ ) {
    696 	  if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE  && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
    697       CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
    698       return;
    699     }
    700   }
    701 }
    702 
    703 static void CG_DrawRedFlagStatus(rectDef_t *rect, qhandle_t shader) {
    704 	if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
    705 		if (cgs.gametype == GT_HARVESTER) {
    706 		  vec4_t color = {1, 0, 0, 1};
    707 		  trap_R_SetColor(color);
    708 	    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.redCubeIcon );
    709 		  trap_R_SetColor(NULL);
    710 		}
    711 		return;
    712 	}
    713   if (shader) {
    714 		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
    715   } else {
    716 	  gitem_t *item = BG_FindItemForPowerup( PW_REDFLAG );
    717     if (item) {
    718 		  vec4_t color = {1, 0, 0, 1};
    719 		  trap_R_SetColor(color);
    720 	    if( cgs.redflag >= 0 && cgs.redflag <= 2) {
    721 		    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.redflag] );
    722 			} else {
    723 		    CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
    724 			}
    725 		  trap_R_SetColor(NULL);
    726 	  }
    727   }
    728 }
    729 
    730 static void CG_DrawRedFlagHead(rectDef_t *rect) {
    731   int i;
    732   for ( i = 0 ; i < cgs.maxclients ; i++ ) {
    733 	  if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE  && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
    734       vec3_t angles;
    735       VectorClear( angles );
    736  		  angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
    737       CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
    738       return;
    739     }
    740   }
    741 }
    742 
    743 static void CG_HarvesterSkulls(rectDef_t *rect, float scale, vec4_t color, qboolean force2D, int textStyle ) {
    744 	char num[16];
    745 	vec3_t origin, angles;
    746 	qhandle_t handle;
    747 	int value = cg.snap->ps.generic1;
    748 
    749 	if (cgs.gametype != GT_HARVESTER) {
    750 		return;
    751 	}
    752 
    753 	if( value > 99 ) {
    754 		value = 99;
    755 	}
    756 
    757 	Com_sprintf (num, sizeof(num), "%i", value);
    758 	value = CG_Text_Width(num, scale, 0);
    759 	CG_Text_Paint(rect->x + (rect->w - value), rect->y + rect->h, scale, color, num, 0, 0, textStyle);
    760 
    761 	if (cg_drawIcons.integer) {
    762 		if (!force2D && cg_draw3dIcons.integer) {
    763 			VectorClear(angles);
    764 			origin[0] = 90;
    765 			origin[1] = 0;
    766 			origin[2] = -10;
    767 			angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
    768 			if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
    769 				handle = cgs.media.redCubeModel;
    770 			} else {
    771 				handle = cgs.media.blueCubeModel;
    772 			}
    773 			CG_Draw3DModel( rect->x, rect->y, 35, 35, handle, 0, origin, angles );
    774 		} else {
    775 			if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
    776 				handle = cgs.media.redCubeIcon;
    777 			} else {
    778 				handle = cgs.media.blueCubeIcon;
    779 			}
    780 			CG_DrawPic( rect->x + 3, rect->y + 16, 20, 20, handle );
    781 		}
    782 	}
    783 }
    784 
    785 static void CG_OneFlagStatus(rectDef_t *rect) {
    786 	if (cgs.gametype != GT_1FCTF) {
    787 		return;
    788 	} else {
    789 		gitem_t *item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
    790 		if (item) {
    791 			if( cgs.flagStatus >= 0 && cgs.flagStatus <= 4 ) {
    792 				vec4_t color = {1, 1, 1, 1};
    793 				int index = 0;
    794 				if (cgs.flagStatus == FLAG_TAKEN_RED) {
    795 					color[1] = color[2] = 0;
    796 					index = 1;
    797 				} else if (cgs.flagStatus == FLAG_TAKEN_BLUE) {
    798 					color[0] = color[1] = 0;
    799 					index = 1;
    800 				} else if (cgs.flagStatus == FLAG_DROPPED) {
    801 					index = 2;
    802 				}
    803 			  trap_R_SetColor(color);
    804 				CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[index] );
    805 			}
    806 		}
    807 	}
    808 }
    809 
    810 
    811 static void CG_DrawCTFPowerUp(rectDef_t *rect) {
    812 	int		value;
    813 
    814 	if (cgs.gametype < GT_CTF) {
    815 		return;
    816 	}
    817 	value = cg.snap->ps.stats[STAT_PERSISTANT_POWERUP];
    818 	if ( value ) {
    819 		CG_RegisterItemVisuals( value );
    820 		CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
    821 	}
    822 }
    823 
    824 
    825 
    826 static void CG_DrawTeamColor(rectDef_t *rect, vec4_t color) {
    827 	CG_DrawTeamBackground(rect->x, rect->y, rect->w, rect->h, color[3], cg.snap->ps.persistant[PERS_TEAM]);
    828 }
    829 
    830 static void CG_DrawAreaPowerUp(rectDef_t *rect, int align, float special, float scale, vec4_t color) {
    831 	char num[16];
    832 	int		sorted[MAX_POWERUPS];
    833 	int		sortedTime[MAX_POWERUPS];
    834 	int		i, j, k;
    835 	int		active;
    836 	playerState_t	*ps;
    837 	int		t;
    838 	gitem_t	*item;
    839 	float	f;
    840 	rectDef_t r2;
    841 	float *inc;
    842 	r2.x = rect->x;
    843 	r2.y = rect->y;
    844 	r2.w = rect->w;
    845 	r2.h = rect->h;
    846 
    847 	inc = (align == HUD_VERTICAL) ? &r2.y : &r2.x;
    848 
    849 	ps = &cg.snap->ps;
    850 
    851 	if ( ps->stats[STAT_HEALTH] <= 0 ) {
    852 		return;
    853 	}
    854 
    855 	// sort the list by time remaining
    856 	active = 0;
    857 	for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
    858 		if ( !ps->powerups[ i ] ) {
    859 			continue;
    860 		}
    861 		t = ps->powerups[ i ] - cg.time;
    862 		// ZOID--don't draw if the power up has unlimited time (999 seconds)
    863 		// This is true of the CTF flags
    864 		if ( t <= 0 || t >= 999000) {
    865 			continue;
    866 		}
    867 
    868 		// insert into the list
    869 		for ( j = 0 ; j < active ; j++ ) {
    870 			if ( sortedTime[j] >= t ) {
    871 				for ( k = active - 1 ; k >= j ; k-- ) {
    872 					sorted[k+1] = sorted[k];
    873 					sortedTime[k+1] = sortedTime[k];
    874 				}
    875 				break;
    876 			}
    877 		}
    878 		sorted[j] = i;
    879 		sortedTime[j] = t;
    880 		active++;
    881 	}
    882 
    883 	// draw the icons and timers
    884 	for ( i = 0 ; i < active ; i++ ) {
    885 		item = BG_FindItemForPowerup( sorted[i] );
    886 
    887 		if (item) {
    888 			t = ps->powerups[ sorted[i] ];
    889 			if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
    890 				trap_R_SetColor( NULL );
    891 			} else {
    892 				vec4_t	modulate;
    893 
    894 				f = (float)( t - cg.time ) / POWERUP_BLINK_TIME;
    895 				f -= (int)f;
    896 				modulate[0] = modulate[1] = modulate[2] = modulate[3] = f;
    897 				trap_R_SetColor( modulate );
    898 			}
    899 
    900 			CG_DrawPic( r2.x, r2.y, r2.w * .75, r2.h, trap_R_RegisterShader( item->icon ) );
    901 
    902 			Com_sprintf (num, sizeof(num), "%i", sortedTime[i] / 1000);
    903 			CG_Text_Paint(r2.x + (r2.w * .75) + 3 , r2.y + r2.h, scale, color, num, 0, 0, 0);
    904 			*inc += r2.w + special;
    905 		}
    906 
    907 	}
    908 	trap_R_SetColor( NULL );
    909 
    910 }
    911 
    912 float CG_GetValue(int ownerDraw) {
    913 	centity_t	*cent;
    914  	clientInfo_t *ci;
    915 	playerState_t	*ps;
    916 
    917   cent = &cg_entities[cg.snap->ps.clientNum];
    918 	ps = &cg.snap->ps;
    919 
    920   switch (ownerDraw) {
    921   case CG_SELECTEDPLAYER_ARMOR:
    922     ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    923     return ci->armor;
    924     break;
    925   case CG_SELECTEDPLAYER_HEALTH:
    926     ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
    927     return ci->health;
    928     break;
    929   case CG_PLAYER_ARMOR_VALUE:
    930 		return ps->stats[STAT_ARMOR];
    931     break;
    932   case CG_PLAYER_AMMO_VALUE:
    933 		if ( cent->currentState.weapon ) {
    934 		  return ps->ammo[cent->currentState.weapon];
    935 		}
    936     break;
    937   case CG_PLAYER_SCORE:
    938 	  return cg.snap->ps.persistant[PERS_SCORE];
    939     break;
    940   case CG_PLAYER_HEALTH:
    941 		return ps->stats[STAT_HEALTH];
    942     break;
    943   case CG_RED_SCORE:
    944 		return cgs.scores1;
    945     break;
    946   case CG_BLUE_SCORE:
    947 		return cgs.scores2;
    948     break;
    949   default:
    950     break;
    951   }
    952 	return -1;
    953 }
    954 
    955 qboolean CG_OtherTeamHasFlag() {
    956 	if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
    957 		int team = cg.snap->ps.persistant[PERS_TEAM];
    958 		if (cgs.gametype == GT_1FCTF) {
    959 			if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_BLUE) {
    960 				return qtrue;
    961 			} else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_RED) {
    962 				return qtrue;
    963 			} else {
    964 				return qfalse;
    965 			}
    966 		} else {
    967 			if (team == TEAM_RED && cgs.redflag == FLAG_TAKEN) {
    968 				return qtrue;
    969 			} else if (team == TEAM_BLUE && cgs.blueflag == FLAG_TAKEN) {
    970 				return qtrue;
    971 			} else {
    972 				return qfalse;
    973 			}
    974 		}
    975 	}
    976 	return qfalse;
    977 }
    978 
    979 qboolean CG_YourTeamHasFlag() {
    980 	if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
    981 		int team = cg.snap->ps.persistant[PERS_TEAM];
    982 		if (cgs.gametype == GT_1FCTF) {
    983 			if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_RED) {
    984 				return qtrue;
    985 			} else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_BLUE) {
    986 				return qtrue;
    987 			} else {
    988 				return qfalse;
    989 			}
    990 		} else {
    991 			if (team == TEAM_RED && cgs.blueflag == FLAG_TAKEN) {
    992 				return qtrue;
    993 			} else if (team == TEAM_BLUE && cgs.redflag == FLAG_TAKEN) {
    994 				return qtrue;
    995 			} else {
    996 				return qfalse;
    997 			}
    998 		}
    999 	}
   1000 	return qfalse;
   1001 }
   1002 
   1003 // THINKABOUTME: should these be exclusive or inclusive.. 
   1004 // 
   1005 qboolean CG_OwnerDrawVisible(int flags) {
   1006 
   1007 	if (flags & CG_SHOW_TEAMINFO) {
   1008 		return (cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
   1009 	}
   1010 
   1011 	if (flags & CG_SHOW_NOTEAMINFO) {
   1012 		return !(cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
   1013 	}
   1014 
   1015 	if (flags & CG_SHOW_OTHERTEAMHASFLAG) {
   1016 		return CG_OtherTeamHasFlag();
   1017 	}
   1018 
   1019 	if (flags & CG_SHOW_YOURTEAMHASENEMYFLAG) {
   1020 		return CG_YourTeamHasFlag();
   1021 	}
   1022 
   1023 	if (flags & (CG_SHOW_BLUE_TEAM_HAS_REDFLAG | CG_SHOW_RED_TEAM_HAS_BLUEFLAG)) {
   1024 		if (flags & CG_SHOW_BLUE_TEAM_HAS_REDFLAG && (cgs.redflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_RED)) {
   1025 			return qtrue;
   1026 		} else if (flags & CG_SHOW_RED_TEAM_HAS_BLUEFLAG && (cgs.blueflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_BLUE)) {
   1027 			return qtrue;
   1028 		}
   1029 		return qfalse;
   1030 	}
   1031 
   1032 	if (flags & CG_SHOW_ANYTEAMGAME) {
   1033 		if( cgs.gametype >= GT_TEAM) {
   1034 			return qtrue;
   1035 		}
   1036 	}
   1037 
   1038 	if (flags & CG_SHOW_ANYNONTEAMGAME) {
   1039 		if( cgs.gametype < GT_TEAM) {
   1040 			return qtrue;
   1041 		}
   1042 	}
   1043 
   1044 	if (flags & CG_SHOW_HARVESTER) {
   1045 		if( cgs.gametype == GT_HARVESTER ) {
   1046 			return qtrue;
   1047     } else {
   1048       return qfalse;
   1049     }
   1050 	}
   1051 
   1052 	if (flags & CG_SHOW_ONEFLAG) {
   1053 		if( cgs.gametype == GT_1FCTF ) {
   1054 			return qtrue;
   1055     } else {
   1056       return qfalse;
   1057     }
   1058 	}
   1059 
   1060 	if (flags & CG_SHOW_CTF) {
   1061 		if( cgs.gametype == GT_CTF ) {
   1062 			return qtrue;
   1063 		}
   1064 	}
   1065 
   1066 	if (flags & CG_SHOW_OBELISK) {
   1067 		if( cgs.gametype == GT_OBELISK ) {
   1068 			return qtrue;
   1069     } else {
   1070       return qfalse;
   1071     }
   1072 	}
   1073 
   1074 	if (flags & CG_SHOW_HEALTHCRITICAL) {
   1075 		if (cg.snap->ps.stats[STAT_HEALTH] < 25) {
   1076 			return qtrue;
   1077 		}
   1078 	}
   1079 
   1080 	if (flags & CG_SHOW_HEALTHOK) {
   1081 		if (cg.snap->ps.stats[STAT_HEALTH] >= 25) {
   1082 			return qtrue;
   1083 		}
   1084 	}
   1085 
   1086 	if (flags & CG_SHOW_SINGLEPLAYER) {
   1087 		if( cgs.gametype == GT_SINGLE_PLAYER ) {
   1088 			return qtrue;
   1089 		}
   1090 	}
   1091 
   1092 	if (flags & CG_SHOW_TOURNAMENT) {
   1093 		if( cgs.gametype == GT_TOURNAMENT ) {
   1094 			return qtrue;
   1095 		}
   1096 	}
   1097 
   1098 	if (flags & CG_SHOW_DURINGINCOMINGVOICE) {
   1099 	}
   1100 
   1101 	if (flags & CG_SHOW_IF_PLAYER_HAS_FLAG) {
   1102 		if (cg.snap->ps.powerups[PW_REDFLAG] || cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) {
   1103 			return qtrue;
   1104 		}
   1105 	}
   1106 	return qfalse;
   1107 }
   1108 
   1109 
   1110 
   1111 static void CG_DrawPlayerHasFlag(rectDef_t *rect, qboolean force2D) {
   1112 	int adj = (force2D) ? 0 : 2;
   1113 	if( cg.predictedPlayerState.powerups[PW_REDFLAG] ) {
   1114   	CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_RED, force2D);
   1115 	} else if( cg.predictedPlayerState.powerups[PW_BLUEFLAG] ) {
   1116   	CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_BLUE, force2D);
   1117 	} else if( cg.predictedPlayerState.powerups[PW_NEUTRALFLAG] ) {
   1118   	CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_FREE, force2D);
   1119 	}
   1120 }
   1121 
   1122 static void CG_DrawAreaSystemChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
   1123   CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, systemChat, 0, 0, 0);
   1124 }
   1125 
   1126 static void CG_DrawAreaTeamChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
   1127   CG_Text_Paint(rect->x, rect->y + rect->h, scale, color,teamChat1, 0, 0, 0);
   1128 }
   1129 
   1130 static void CG_DrawAreaChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
   1131   CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, teamChat2, 0, 0, 0);
   1132 }
   1133 
   1134 const char *CG_GetKillerText() {
   1135 	const char *s = "";
   1136 	if ( cg.killerName[0] ) {
   1137 		s = va("Fragged by %s", cg.killerName );
   1138 	}
   1139 	return s;
   1140 }
   1141 
   1142 
   1143 static void CG_DrawKiller(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
   1144 	// fragged by ... line
   1145 	if ( cg.killerName[0] ) {
   1146 		int x = rect->x + rect->w / 2;
   1147 	  CG_Text_Paint(x - CG_Text_Width(CG_GetKillerText(), scale, 0) / 2, rect->y + rect->h, scale, color, CG_GetKillerText(), 0, 0, textStyle);
   1148 	}
   1149 	
   1150 }
   1151 
   1152 
   1153 static void CG_DrawCapFragLimit(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
   1154 	int limit = (cgs.gametype >= GT_CTF) ? cgs.capturelimit : cgs.fraglimit;
   1155 	CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", limit),0, 0, textStyle); 
   1156 }
   1157 
   1158 static void CG_Draw1stPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
   1159 	if (cgs.scores1 != SCORE_NOT_PRESENT) {
   1160 		CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores1),0, 0, textStyle); 
   1161 	}
   1162 }
   1163 
   1164 static void CG_Draw2ndPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
   1165 	if (cgs.scores2 != SCORE_NOT_PRESENT) {
   1166 		CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores2),0, 0, textStyle); 
   1167 	}
   1168 }
   1169 
   1170 const char *CG_GetGameStatusText() {
   1171 	const char *s = "";
   1172 	if ( cgs.gametype < GT_TEAM) {
   1173 		if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
   1174 			s = va("%s place with %i",CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ),cg.snap->ps.persistant[PERS_SCORE] );
   1175 		}
   1176 	} else {
   1177 		if ( cg.teamScores[0] == cg.teamScores[1] ) {
   1178 			s = va("Teams are tied at %i", cg.teamScores[0] );
   1179 		} else if ( cg.teamScores[0] >= cg.teamScores[1] ) {
   1180 			s = va("Red leads Blue, %i to %i", cg.teamScores[0], cg.teamScores[1] );
   1181 		} else {
   1182 			s = va("Blue leads Red, %i to %i", cg.teamScores[1], cg.teamScores[0] );
   1183 		}
   1184 	}
   1185 	return s;
   1186 }
   1187 	
   1188 static void CG_DrawGameStatus(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
   1189 	CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GetGameStatusText(), 0, 0, textStyle);
   1190 }
   1191 
   1192 const char *CG_GameTypeString() {
   1193 	if ( cgs.gametype == GT_FFA ) {
   1194 		return "Free For All";
   1195 	} else if ( cgs.gametype == GT_TEAM ) {
   1196 		return "Team Deathmatch";
   1197 	} else if ( cgs.gametype == GT_CTF ) {
   1198 		return "Capture the Flag";
   1199 	} else if ( cgs.gametype == GT_1FCTF ) {
   1200 		return "One Flag CTF";
   1201 	} else if ( cgs.gametype == GT_OBELISK ) {
   1202 		return "Overload";
   1203 	} else if ( cgs.gametype == GT_HARVESTER ) {
   1204 		return "Harvester";
   1205 	}
   1206 	return "";
   1207 }
   1208 static void CG_DrawGameType(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
   1209 	CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GameTypeString(), 0, 0, textStyle);
   1210 }
   1211 
   1212 static void CG_Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
   1213   int len, count;
   1214 	vec4_t newColor;
   1215 	glyphInfo_t *glyph;
   1216   if (text) {
   1217 // TTimo: FIXME
   1218 //    const unsigned char *s = text; // bk001206 - unsigned
   1219     const char *s = text;
   1220 		float max = *maxX;
   1221 		float useScale;
   1222 		fontInfo_t *font = &cgDC.Assets.textFont;
   1223 		if (scale <= cg_smallFont.value) {
   1224 			font = &cgDC.Assets.smallFont;
   1225 		} else if (scale > cg_bigFont.value) {
   1226 			font = &cgDC.Assets.bigFont;
   1227 		}
   1228 		useScale = scale * font->glyphScale;
   1229 		trap_R_SetColor( color );
   1230     len = strlen(text);					 
   1231 		if (limit > 0 && len > limit) {
   1232 			len = limit;
   1233 		}
   1234 		count = 0;
   1235 		while (s && *s && count < len) {
   1236 			glyph = &font->glyphs[(int)*s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build
   1237 			if ( Q_IsColorString( s ) ) {
   1238 				memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
   1239 				newColor[3] = color[3];
   1240 				trap_R_SetColor( newColor );
   1241 				s += 2;
   1242 				continue;
   1243 			} else {
   1244 	      float yadj = useScale * glyph->top;
   1245 				if (CG_Text_Width(s, useScale, 1) + x > max) {
   1246 					*maxX = 0;
   1247 					break;
   1248 				}
   1249 		    CG_Text_PaintChar(x, y - yadj, 
   1250 			                    glyph->imageWidth,
   1251 				                  glyph->imageHeight,
   1252 					                useScale, 
   1253 						              glyph->s,
   1254 							            glyph->t,
   1255 								          glyph->s2,
   1256 									        glyph->t2,
   1257 										      glyph->glyph);
   1258 	      x += (glyph->xSkip * useScale) + adjust;
   1259 				*maxX = x;
   1260 				count++;
   1261 				s++;
   1262 	    }
   1263 		}
   1264 	  trap_R_SetColor( NULL );
   1265   }
   1266 
   1267 }
   1268 
   1269 
   1270 
   1271 #define PIC_WIDTH 12
   1272 
   1273 void CG_DrawNewTeamInfo(rectDef_t *rect, float text_x, float text_y, float scale, vec4_t color, qhandle_t shader) {
   1274 	int xx;
   1275 	float y;
   1276 	int i, j, len, count;
   1277 	const char *p;
   1278 	vec4_t		hcolor;
   1279 	float pwidth, lwidth, maxx, leftOver;
   1280 	clientInfo_t *ci;
   1281 	gitem_t	*item;
   1282 	qhandle_t h;
   1283 
   1284 	// max player name width
   1285 	pwidth = 0;
   1286 	count = (numSortedTeamPlayers > 8) ? 8 : numSortedTeamPlayers;
   1287 	for (i = 0; i < count; i++) {
   1288 		ci = cgs.clientinfo + sortedTeamPlayers[i];
   1289 		if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
   1290 			len = CG_Text_Width( ci->name, scale, 0);
   1291 			if (len > pwidth)
   1292 				pwidth = len;
   1293 		}
   1294 	}
   1295 
   1296 	// max location name width
   1297 	lwidth = 0;
   1298 	for (i = 1; i < MAX_LOCATIONS; i++) {
   1299 		p = CG_ConfigString(CS_LOCATIONS + i);
   1300 		if (p && *p) {
   1301 			len = CG_Text_Width(p, scale, 0);
   1302 			if (len > lwidth)
   1303 				lwidth = len;
   1304 		}
   1305 	}
   1306 
   1307 	y = rect->y;
   1308 
   1309 	for (i = 0; i < count; i++) {
   1310 		ci = cgs.clientinfo + sortedTeamPlayers[i];
   1311 		if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
   1312 
   1313 			xx = rect->x + 1;
   1314 			for (j = 0; j <= PW_NUM_POWERUPS; j++) {
   1315 				if (ci->powerups & (1 << j)) {
   1316 
   1317 					item = BG_FindItemForPowerup( j );
   1318 
   1319 					if (item) {
   1320 						CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, trap_R_RegisterShader( item->icon ) );
   1321 						xx += PIC_WIDTH;
   1322 					}
   1323 				}
   1324 			}
   1325 
   1326 			// FIXME: max of 3 powerups shown properly
   1327 			xx = rect->x + (PIC_WIDTH * 3) + 2;
   1328 
   1329 			CG_GetColorForHealth( ci->health, ci->armor, hcolor );
   1330 			trap_R_SetColor(hcolor);
   1331 			CG_DrawPic( xx, y + 1, PIC_WIDTH - 2, PIC_WIDTH - 2, cgs.media.heartShader );
   1332 
   1333 			//Com_sprintf (st, sizeof(st), "%3i %3i", ci->health,	ci->armor);
   1334 			//CG_Text_Paint(xx, y + text_y, scale, hcolor, st, 0, 0); 
   1335 
   1336 			// draw weapon icon
   1337 			xx += PIC_WIDTH + 1;
   1338 
   1339 // weapon used is not that useful, use the space for task
   1340 #if 0
   1341 			if ( cg_weapons[ci->curWeapon].weaponIcon ) {
   1342 				CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cg_weapons[ci->curWeapon].weaponIcon );
   1343 			} else {
   1344 				CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cgs.media.deferShader );
   1345 			}
   1346 #endif
   1347 
   1348 			trap_R_SetColor(NULL);
   1349 			if (cgs.orderPending) {
   1350 				// blink the icon
   1351 				if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
   1352 					h = 0;
   1353 				} else {
   1354 					h = CG_StatusHandle(cgs.currentOrder);
   1355 				}
   1356 			}	else {
   1357 				h = CG_StatusHandle(ci->teamTask);
   1358 			}
   1359 
   1360 			if (h) {
   1361 				CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, h);
   1362 			}
   1363 
   1364 			xx += PIC_WIDTH + 1;
   1365 
   1366 			leftOver = rect->w - xx;
   1367 			maxx = xx + leftOver / 3;
   1368 
   1369 
   1370 
   1371 			CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, ci->name, 0, 0); 
   1372 
   1373 			p = CG_ConfigString(CS_LOCATIONS + ci->location);
   1374 			if (!p || !*p) {
   1375 				p = "unknown";
   1376 			}
   1377 
   1378 			xx += leftOver / 3 + 2;
   1379 			maxx = rect->w - 4;
   1380 
   1381 			CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, p, 0, 0); 
   1382 			y += text_y + 2;
   1383 			if ( y + text_y + 2 > rect->y + rect->h ) {
   1384 				break;
   1385 			}
   1386 
   1387 		}
   1388 	}
   1389 }
   1390 
   1391 
   1392 void CG_DrawTeamSpectators(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
   1393 	if (cg.spectatorLen) {
   1394 		float maxX;
   1395 
   1396 		if (cg.spectatorWidth == -1) {
   1397 			cg.spectatorWidth = 0;
   1398 			cg.spectatorPaintX = rect->x + 1;
   1399 			cg.spectatorPaintX2 = -1;
   1400 		}
   1401 
   1402 		if (cg.spectatorOffset > cg.spectatorLen) {
   1403 			cg.spectatorOffset = 0;
   1404 			cg.spectatorPaintX = rect->x + 1;
   1405 			cg.spectatorPaintX2 = -1;
   1406 		}
   1407 
   1408 		if (cg.time > cg.spectatorTime) {
   1409 			cg.spectatorTime = cg.time + 10;
   1410 			if (cg.spectatorPaintX <= rect->x + 2) {
   1411 				if (cg.spectatorOffset < cg.spectatorLen) {
   1412 					cg.spectatorPaintX += CG_Text_Width(&cg.spectatorList[cg.spectatorOffset], scale, 1) - 1;
   1413 					cg.spectatorOffset++;
   1414 				} else {
   1415 					cg.spectatorOffset = 0;
   1416 					if (cg.spectatorPaintX2 >= 0) {
   1417 						cg.spectatorPaintX = cg.spectatorPaintX2;
   1418 					} else {
   1419 						cg.spectatorPaintX = rect->x + rect->w - 2;
   1420 					}
   1421 					cg.spectatorPaintX2 = -1;
   1422 				}
   1423 			} else {
   1424 				cg.spectatorPaintX--;
   1425 				if (cg.spectatorPaintX2 >= 0) {
   1426 					cg.spectatorPaintX2--;
   1427 				}
   1428 			}
   1429 		}
   1430 
   1431 		maxX = rect->x + rect->w - 2;
   1432 		CG_Text_Paint_Limit(&maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, &cg.spectatorList[cg.spectatorOffset], 0, 0); 
   1433 		if (cg.spectatorPaintX2 >= 0) {
   1434 			float maxX2 = rect->x + rect->w - 2;
   1435 			CG_Text_Paint_Limit(&maxX2, cg.spectatorPaintX2, rect->y + rect->h - 3, scale, color, cg.spectatorList, 0, cg.spectatorOffset); 
   1436 		}
   1437 		if (cg.spectatorOffset && maxX > 0) {
   1438 			// if we have an offset ( we are skipping the first part of the string ) and we fit the string
   1439 			if (cg.spectatorPaintX2 == -1) {
   1440 						cg.spectatorPaintX2 = rect->x + rect->w - 2;
   1441 			}
   1442 		} else {
   1443 			cg.spectatorPaintX2 = -1;
   1444 		}
   1445 
   1446 	}
   1447 }
   1448 
   1449 
   1450 
   1451 void CG_DrawMedal(int ownerDraw, rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
   1452 	score_t *score = &cg.scores[cg.selectedScore];
   1453 	float value = 0;
   1454 	char *text = NULL;
   1455 	color[3] = 0.25;
   1456 
   1457 	switch (ownerDraw) {
   1458 		case CG_ACCURACY:
   1459 			value = score->accuracy;
   1460 			break;
   1461 		case CG_ASSISTS:
   1462 			value = score->assistCount;
   1463 			break;
   1464 		case CG_DEFEND:
   1465 			value = score->defendCount;
   1466 			break;
   1467 		case CG_EXCELLENT:
   1468 			value = score->excellentCount;
   1469 			break;
   1470 		case CG_IMPRESSIVE:
   1471 			value = score->impressiveCount;
   1472 			break;
   1473 		case CG_PERFECT:
   1474 			value = score->perfect;
   1475 			break;
   1476 		case CG_GAUNTLET:
   1477 			value = score->guantletCount;
   1478 			break;
   1479 		case CG_CAPTURES:
   1480 			value = score->captures;
   1481 			break;
   1482 	}
   1483 
   1484 	if (value > 0) {
   1485 		if (ownerDraw != CG_PERFECT) {
   1486 			if (ownerDraw == CG_ACCURACY) {
   1487 				text = va("%i%%", (int)value);
   1488 				if (value > 50) {
   1489 					color[3] = 1.0;
   1490 				}
   1491 			} else {
   1492 				text = va("%i", (int)value);
   1493 				color[3] = 1.0;
   1494 			}
   1495 		} else {
   1496 			if (value) {
   1497 				color[3] = 1.0;
   1498 			}
   1499 			text = "Wow";
   1500 		}
   1501 	}
   1502 
   1503 	trap_R_SetColor(color);
   1504 	CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
   1505 
   1506 	if (text) {
   1507 		color[3] = 1.0;
   1508 		value = CG_Text_Width(text, scale, 0);
   1509 		CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h + 10 , scale, color, text, 0, 0, 0);
   1510 	}
   1511 	trap_R_SetColor(NULL);
   1512 
   1513 }
   1514 
   1515 	
   1516 //
   1517 void CG_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle) {
   1518 	rectDef_t rect;
   1519 
   1520   if ( cg_drawStatus.integer == 0 ) {
   1521 		return;
   1522 	}
   1523 
   1524 	//if (ownerDrawFlags != 0 && !CG_OwnerDrawVisible(ownerDrawFlags)) {
   1525 	//	return;
   1526 	//}
   1527 
   1528   rect.x = x;
   1529   rect.y = y;
   1530   rect.w = w;
   1531   rect.h = h;
   1532 
   1533   switch (ownerDraw) {
   1534   case CG_PLAYER_ARMOR_ICON:
   1535     CG_DrawPlayerArmorIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
   1536     break;
   1537   case CG_PLAYER_ARMOR_ICON2D:
   1538     CG_DrawPlayerArmorIcon(&rect, qtrue);
   1539     break;
   1540   case CG_PLAYER_ARMOR_VALUE:
   1541     CG_DrawPlayerArmorValue(&rect, scale, color, shader, textStyle);
   1542     break;
   1543   case CG_PLAYER_AMMO_ICON:
   1544     CG_DrawPlayerAmmoIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
   1545     break;
   1546   case CG_PLAYER_AMMO_ICON2D:
   1547     CG_DrawPlayerAmmoIcon(&rect, qtrue);
   1548     break;
   1549   case CG_PLAYER_AMMO_VALUE:
   1550     CG_DrawPlayerAmmoValue(&rect, scale, color, shader, textStyle);
   1551     break;
   1552   case CG_SELECTEDPLAYER_HEAD:
   1553     CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qfalse);
   1554     break;
   1555   case CG_VOICE_HEAD:
   1556     CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qtrue);
   1557     break;
   1558   case CG_VOICE_NAME:
   1559     CG_DrawSelectedPlayerName(&rect, scale, color, qtrue, textStyle);
   1560     break;
   1561   case CG_SELECTEDPLAYER_STATUS:
   1562     CG_DrawSelectedPlayerStatus(&rect);
   1563     break;
   1564   case CG_SELECTEDPLAYER_ARMOR:
   1565     CG_DrawSelectedPlayerArmor(&rect, scale, color, shader, textStyle);
   1566     break;
   1567   case CG_SELECTEDPLAYER_HEALTH:
   1568     CG_DrawSelectedPlayerHealth(&rect, scale, color, shader, textStyle);
   1569     break;
   1570   case CG_SELECTEDPLAYER_NAME:
   1571     CG_DrawSelectedPlayerName(&rect, scale, color, qfalse, textStyle);
   1572     break;
   1573   case CG_SELECTEDPLAYER_LOCATION:
   1574     CG_DrawSelectedPlayerLocation(&rect, scale, color, textStyle);
   1575     break;
   1576   case CG_SELECTEDPLAYER_WEAPON:
   1577     CG_DrawSelectedPlayerWeapon(&rect);
   1578     break;
   1579   case CG_SELECTEDPLAYER_POWERUP:
   1580     CG_DrawSelectedPlayerPowerup(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
   1581     break;
   1582   case CG_PLAYER_HEAD:
   1583     CG_DrawPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
   1584     break;
   1585   case CG_PLAYER_ITEM:
   1586     CG_DrawPlayerItem(&rect, scale, ownerDrawFlags & CG_SHOW_2DONLY);
   1587     break;
   1588   case CG_PLAYER_SCORE:
   1589     CG_DrawPlayerScore(&rect, scale, color, shader, textStyle);
   1590     break;
   1591   case CG_PLAYER_HEALTH:
   1592     CG_DrawPlayerHealth(&rect, scale, color, shader, textStyle);
   1593     break;
   1594   case CG_RED_SCORE:
   1595     CG_DrawRedScore(&rect, scale, color, shader, textStyle);
   1596     break;
   1597   case CG_BLUE_SCORE:
   1598     CG_DrawBlueScore(&rect, scale, color, shader, textStyle);
   1599     break;
   1600   case CG_RED_NAME:
   1601     CG_DrawRedName(&rect, scale, color, textStyle);
   1602     break;
   1603   case CG_BLUE_NAME:
   1604     CG_DrawBlueName(&rect, scale, color, textStyle);
   1605     break;
   1606   case CG_BLUE_FLAGHEAD:
   1607     CG_DrawBlueFlagHead(&rect);
   1608     break;
   1609   case CG_BLUE_FLAGSTATUS:
   1610     CG_DrawBlueFlagStatus(&rect, shader);
   1611     break;
   1612   case CG_BLUE_FLAGNAME:
   1613     CG_DrawBlueFlagName(&rect, scale, color, textStyle);
   1614     break;
   1615   case CG_RED_FLAGHEAD:
   1616     CG_DrawRedFlagHead(&rect);
   1617     break;
   1618   case CG_RED_FLAGSTATUS:
   1619     CG_DrawRedFlagStatus(&rect, shader);
   1620     break;
   1621   case CG_RED_FLAGNAME:
   1622     CG_DrawRedFlagName(&rect, scale, color, textStyle);
   1623     break;
   1624   case CG_HARVESTER_SKULLS:
   1625     CG_HarvesterSkulls(&rect, scale, color, qfalse, textStyle);
   1626     break;
   1627   case CG_HARVESTER_SKULLS2D:
   1628     CG_HarvesterSkulls(&rect, scale, color, qtrue, textStyle);
   1629     break;
   1630   case CG_ONEFLAG_STATUS:
   1631     CG_OneFlagStatus(&rect);
   1632     break;
   1633   case CG_PLAYER_LOCATION:
   1634     CG_DrawPlayerLocation(&rect, scale, color, textStyle);
   1635     break;
   1636   case CG_TEAM_COLOR:
   1637     CG_DrawTeamColor(&rect, color);
   1638     break;
   1639   case CG_CTF_POWERUP:
   1640     CG_DrawCTFPowerUp(&rect);
   1641     break;
   1642   case CG_AREA_POWERUP:
   1643 		CG_DrawAreaPowerUp(&rect, align, special, scale, color);
   1644     break;
   1645   case CG_PLAYER_STATUS:
   1646     CG_DrawPlayerStatus(&rect);
   1647     break;
   1648   case CG_PLAYER_HASFLAG:
   1649     CG_DrawPlayerHasFlag(&rect, qfalse);
   1650     break;
   1651   case CG_PLAYER_HASFLAG2D:
   1652     CG_DrawPlayerHasFlag(&rect, qtrue);
   1653     break;
   1654   case CG_AREA_SYSTEMCHAT:
   1655     CG_DrawAreaSystemChat(&rect, scale, color, shader);
   1656     break;
   1657   case CG_AREA_TEAMCHAT:
   1658     CG_DrawAreaTeamChat(&rect, scale, color, shader);
   1659     break;
   1660   case CG_AREA_CHAT:
   1661     CG_DrawAreaChat(&rect, scale, color, shader);
   1662     break;
   1663   case CG_GAME_TYPE:
   1664     CG_DrawGameType(&rect, scale, color, shader, textStyle);
   1665     break;
   1666   case CG_GAME_STATUS:
   1667     CG_DrawGameStatus(&rect, scale, color, shader, textStyle);
   1668 		break;
   1669   case CG_KILLER:
   1670     CG_DrawKiller(&rect, scale, color, shader, textStyle);
   1671 		break;
   1672 	case CG_ACCURACY:
   1673 	case CG_ASSISTS:
   1674 	case CG_DEFEND:
   1675 	case CG_EXCELLENT:
   1676 	case CG_IMPRESSIVE:
   1677 	case CG_PERFECT:
   1678 	case CG_GAUNTLET:
   1679 	case CG_CAPTURES:
   1680 		CG_DrawMedal(ownerDraw, &rect, scale, color, shader);
   1681 		break;
   1682   case CG_SPECTATORS:
   1683 		CG_DrawTeamSpectators(&rect, scale, color, shader);
   1684 		break;
   1685   case CG_TEAMINFO:
   1686 		if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
   1687 			CG_DrawNewTeamInfo(&rect, text_x, text_y, scale, color, shader);
   1688 		}
   1689 		break;
   1690   case CG_CAPFRAGLIMIT:
   1691     CG_DrawCapFragLimit(&rect, scale, color, shader, textStyle);
   1692 		break;
   1693   case CG_1STPLACE:
   1694     CG_Draw1stPlace(&rect, scale, color, shader, textStyle);
   1695 		break;
   1696   case CG_2NDPLACE:
   1697     CG_Draw2ndPlace(&rect, scale, color, shader, textStyle);
   1698 		break;
   1699   default:
   1700     break;
   1701   }
   1702 }
   1703 
   1704 void CG_MouseEvent(int x, int y) {
   1705 	int n;
   1706 
   1707 	if ( (cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR) && cg.showScores == qfalse) {
   1708     trap_Key_SetCatcher(0);
   1709 		return;
   1710 	}
   1711 
   1712 	cgs.cursorX+= x;
   1713 	if (cgs.cursorX < 0)
   1714 		cgs.cursorX = 0;
   1715 	else if (cgs.cursorX > 640)
   1716 		cgs.cursorX = 640;
   1717 
   1718 	cgs.cursorY += y;
   1719 	if (cgs.cursorY < 0)
   1720 		cgs.cursorY = 0;
   1721 	else if (cgs.cursorY > 480)
   1722 		cgs.cursorY = 480;
   1723 
   1724 	n = Display_CursorType(cgs.cursorX, cgs.cursorY);
   1725 	cgs.activeCursor = 0;
   1726 	if (n == CURSOR_ARROW) {
   1727 		cgs.activeCursor = cgs.media.selectCursor;
   1728 	} else if (n == CURSOR_SIZER) {
   1729 		cgs.activeCursor = cgs.media.sizeCursor;
   1730 	}
   1731 
   1732   if (cgs.capturedItem) {
   1733 	  Display_MouseMove(cgs.capturedItem, x, y);
   1734   } else {
   1735 	  Display_MouseMove(NULL, cgs.cursorX, cgs.cursorY);
   1736   }
   1737 
   1738 }
   1739 
   1740 /*
   1741 ==================
   1742 CG_HideTeamMenus
   1743 ==================
   1744 
   1745 */
   1746 void CG_HideTeamMenu() {
   1747   Menus_CloseByName("teamMenu");
   1748   Menus_CloseByName("getMenu");
   1749 }
   1750 
   1751 /*
   1752 ==================
   1753 CG_ShowTeamMenus
   1754 ==================
   1755 
   1756 */
   1757 void CG_ShowTeamMenu() {
   1758   Menus_OpenByName("teamMenu");
   1759 }
   1760 
   1761 
   1762 
   1763 
   1764 /*
   1765 ==================
   1766 CG_EventHandling
   1767 ==================
   1768  type 0 - no event handling
   1769       1 - team menu
   1770       2 - hud editor
   1771 
   1772 */
   1773 void CG_EventHandling(int type) {
   1774 	cgs.eventHandling = type;
   1775   if (type == CGAME_EVENT_NONE) {
   1776     CG_HideTeamMenu();
   1777   } else if (type == CGAME_EVENT_TEAMMENU) {
   1778     //CG_ShowTeamMenu();
   1779   } else if (type == CGAME_EVENT_SCOREBOARD) {
   1780   }
   1781 
   1782 }
   1783 
   1784 
   1785 
   1786 void CG_KeyEvent(int key, qboolean down) {
   1787 
   1788 	if (!down) {
   1789 		return;
   1790 	}
   1791 
   1792 	if ( cg.predictedPlayerState.pm_type == PM_NORMAL || (cg.predictedPlayerState.pm_type == PM_SPECTATOR && cg.showScores == qfalse)) {
   1793 		CG_EventHandling(CGAME_EVENT_NONE);
   1794     trap_Key_SetCatcher(0);
   1795 		return;
   1796 	}
   1797 
   1798   //if (key == trap_Key_GetKey("teamMenu") || !Display_CaptureItem(cgs.cursorX, cgs.cursorY)) {
   1799     // if we see this then we should always be visible
   1800   //  CG_EventHandling(CGAME_EVENT_NONE);
   1801   //  trap_Key_SetCatcher(0);
   1802   //}
   1803 
   1804 
   1805 
   1806   Display_HandleKey(key, down, cgs.cursorX, cgs.cursorY);
   1807 
   1808 	if (cgs.capturedItem) {
   1809 		cgs.capturedItem = NULL;
   1810 	}	else {
   1811 		if (key == K_MOUSE2 && down) {
   1812 			cgs.capturedItem = Display_CaptureItem(cgs.cursorX, cgs.cursorY);
   1813 		}
   1814 	}
   1815 }
   1816 
   1817 int CG_ClientNumFromName(const char *p) {
   1818   int i;
   1819   for (i = 0; i < cgs.maxclients; i++) {
   1820     if (cgs.clientinfo[i].infoValid && Q_stricmp(cgs.clientinfo[i].name, p) == 0) {
   1821       return i;
   1822     }
   1823   }
   1824   return -1;
   1825 }
   1826 
   1827 void CG_ShowResponseHead() {
   1828   Menus_OpenByName("voiceMenu");
   1829 	trap_Cvar_Set("cl_conXOffset", "72");
   1830 	cg.voiceTime = cg.time;
   1831 }
   1832 
   1833 void CG_RunMenuScript(char **args) {
   1834 }
   1835 
   1836 
   1837 void CG_GetTeamColor(vec4_t *color) {
   1838   if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
   1839     (*color)[0] = 1.0f;
   1840     (*color)[3] = 0.25f;
   1841     (*color)[1] = (*color)[2] = 0.0f;
   1842   } else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
   1843     (*color)[0] = (*color)[1] = 0.0f;
   1844     (*color)[2] = 1.0f;
   1845     (*color)[3] = 0.25f;
   1846   } else {
   1847     (*color)[0] = (*color)[2] = 0.0f;
   1848     (*color)[1] = 0.17f;
   1849     (*color)[3] = 0.25f;
   1850 	}
   1851 }
   1852