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