00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef MISSIONPACK // bk001204
00024 #error This file not be used for classic Q3A.
00025 #endif
00026
00027 #include "cg_local.h"
00028 #include "../ui/ui_shared.h"
00029
00030 extern displayContextDef_t cgDC;
00031
00032
00033
00034
00035
00036
00037 int drawTeamOverlayModificationCount = -1;
00038
00039
00040
00041
00042
00043 void CG_InitTeamChat() {
00044 memset(teamChat1, 0, sizeof(teamChat1));
00045 memset(teamChat2, 0, sizeof(teamChat2));
00046 memset(systemChat, 0, sizeof(systemChat));
00047 }
00048
00049 void CG_SetPrintString(int type, const char *p) {
00050 if (type == SYSTEM_PRINT) {
00051 strcpy(systemChat, p);
00052 } else {
00053 strcpy(teamChat2, teamChat1);
00054 strcpy(teamChat1, p);
00055 }
00056 }
00057
00058 void CG_CheckOrderPending() {
00059 if (cgs.gametype < GT_CTF) {
00060 return;
00061 }
00062 if (cgs.orderPending) {
00063
00064 const char *p1, *p2, *b;
00065 p1 = p2 = b = NULL;
00066 switch (cgs.currentOrder) {
00067 case TEAMTASK_OFFENSE:
00068 p1 = VOICECHAT_ONOFFENSE;
00069 p2 = VOICECHAT_OFFENSE;
00070 b = "+button7; wait; -button7";
00071 break;
00072 case TEAMTASK_DEFENSE:
00073 p1 = VOICECHAT_ONDEFENSE;
00074 p2 = VOICECHAT_DEFEND;
00075 b = "+button8; wait; -button8";
00076 break;
00077 case TEAMTASK_PATROL:
00078 p1 = VOICECHAT_ONPATROL;
00079 p2 = VOICECHAT_PATROL;
00080 b = "+button9; wait; -button9";
00081 break;
00082 case TEAMTASK_FOLLOW:
00083 p1 = VOICECHAT_ONFOLLOW;
00084 p2 = VOICECHAT_FOLLOWME;
00085 b = "+button10; wait; -button10";
00086 break;
00087 case TEAMTASK_CAMP:
00088 p1 = VOICECHAT_ONCAMPING;
00089 p2 = VOICECHAT_CAMP;
00090 break;
00091 case TEAMTASK_RETRIEVE:
00092 p1 = VOICECHAT_ONGETFLAG;
00093 p2 = VOICECHAT_RETURNFLAG;
00094 break;
00095 case TEAMTASK_ESCORT:
00096 p1 = VOICECHAT_ONFOLLOWCARRIER;
00097 p2 = VOICECHAT_FOLLOWFLAGCARRIER;
00098 break;
00099 }
00100
00101 if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
00102
00103 trap_SendConsoleCommand(va("cmd vsay_team %s\n", p2));
00104 } else {
00105
00106 if (sortedTeamPlayers[cg_currentSelectedPlayer.integer] == cg.snap->ps.clientNum && p1) {
00107 trap_SendConsoleCommand(va("teamtask %i\n", cgs.currentOrder));
00108
00109 trap_SendConsoleCommand(va("cmd vsay_team %s\n", p1));
00110 } else if (p2) {
00111
00112 trap_SendConsoleCommand(va("cmd vtell %d %s\n", sortedTeamPlayers[cg_currentSelectedPlayer.integer], p2));
00113 }
00114 }
00115 if (b) {
00116 trap_SendConsoleCommand(b);
00117 }
00118 cgs.orderPending = qfalse;
00119 }
00120 }
00121
00122 static void CG_SetSelectedPlayerName() {
00123 if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
00124 clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
00125 if (ci) {
00126 trap_Cvar_Set("cg_selectedPlayerName", ci->name);
00127 trap_Cvar_Set("cg_selectedPlayer", va("%d", sortedTeamPlayers[cg_currentSelectedPlayer.integer]));
00128 cgs.currentOrder = ci->teamTask;
00129 }
00130 } else {
00131 trap_Cvar_Set("cg_selectedPlayerName", "Everyone");
00132 }
00133 }
00134 int CG_GetSelectedPlayer() {
00135 if (cg_currentSelectedPlayer.integer < 0 || cg_currentSelectedPlayer.integer >= numSortedTeamPlayers) {
00136 cg_currentSelectedPlayer.integer = 0;
00137 }
00138 return cg_currentSelectedPlayer.integer;
00139 }
00140
00141 void CG_SelectNextPlayer() {
00142 CG_CheckOrderPending();
00143 if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
00144 cg_currentSelectedPlayer.integer++;
00145 } else {
00146 cg_currentSelectedPlayer.integer = 0;
00147 }
00148 CG_SetSelectedPlayerName();
00149 }
00150
00151 void CG_SelectPrevPlayer() {
00152 CG_CheckOrderPending();
00153 if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
00154 cg_currentSelectedPlayer.integer--;
00155 } else {
00156 cg_currentSelectedPlayer.integer = numSortedTeamPlayers;
00157 }
00158 CG_SetSelectedPlayerName();
00159 }
00160
00161
00162 static void CG_DrawPlayerArmorIcon( rectDef_t *rect, qboolean draw2D ) {
00163 centity_t *cent;
00164 playerState_t *ps;
00165 vec3_t angles;
00166 vec3_t origin;
00167
00168 if ( cg_drawStatus.integer == 0 ) {
00169 return;
00170 }
00171
00172 cent = &cg_entities[cg.snap->ps.clientNum];
00173 ps = &cg.snap->ps;
00174
00175 if ( draw2D || ( !cg_draw3dIcons.integer && cg_drawIcons.integer) ) {
00176 CG_DrawPic( rect->x, rect->y + rect->h/2 + 1, rect->w, rect->h, cgs.media.armorIcon );
00177 } else if (cg_draw3dIcons.integer) {
00178 VectorClear( angles );
00179 origin[0] = 90;
00180 origin[1] = 0;
00181 origin[2] = -10;
00182 angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
00183
00184 CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cgs.media.armorModel, 0, origin, angles );
00185 }
00186
00187 }
00188
00189 static void CG_DrawPlayerArmorValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
00190 char num[16];
00191 int value;
00192 centity_t *cent;
00193 playerState_t *ps;
00194
00195 cent = &cg_entities[cg.snap->ps.clientNum];
00196 ps = &cg.snap->ps;
00197
00198 value = ps->stats[STAT_ARMOR];
00199
00200
00201 if (shader) {
00202 trap_R_SetColor( color );
00203 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00204 trap_R_SetColor( NULL );
00205 } else {
00206 Com_sprintf (num, sizeof(num), "%i", value);
00207 value = CG_Text_Width(num, scale, 0);
00208 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00209 }
00210 }
00211
00212 #ifndef MISSIONPACK // bk001206
00213 static float healthColors[4][4] = {
00214
00215
00216 { 1.0f, 0.69f, 0.0f, 1.0f } ,
00217 { 1.0f, 0.2f, 0.2f, 1.0f },
00218 { 0.5f, 0.5f, 0.5f, 1.0f},
00219 { 1.0f, 1.0f, 1.0f, 1.0f } };
00220 #endif
00221
00222 static void CG_DrawPlayerAmmoIcon( rectDef_t *rect, qboolean draw2D ) {
00223 centity_t *cent;
00224 playerState_t *ps;
00225 vec3_t angles;
00226 vec3_t origin;
00227
00228 cent = &cg_entities[cg.snap->ps.clientNum];
00229 ps = &cg.snap->ps;
00230
00231 if ( draw2D || (!cg_draw3dIcons.integer && cg_drawIcons.integer) ) {
00232 qhandle_t icon;
00233 icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon;
00234 if ( icon ) {
00235 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, icon );
00236 }
00237 } else if (cg_draw3dIcons.integer) {
00238 if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) {
00239 VectorClear( angles );
00240 origin[0] = 70;
00241 origin[1] = 0;
00242 origin[2] = 0;
00243 angles[YAW] = 90 + 20 * sin( cg.time / 1000.0 );
00244 CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, origin, angles );
00245 }
00246 }
00247 }
00248
00249 static void CG_DrawPlayerAmmoValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
00250 char num[16];
00251 int value;
00252 centity_t *cent;
00253 playerState_t *ps;
00254
00255 cent = &cg_entities[cg.snap->ps.clientNum];
00256 ps = &cg.snap->ps;
00257
00258 if ( cent->currentState.weapon ) {
00259 value = ps->ammo[cent->currentState.weapon];
00260 if ( value > -1 ) {
00261 if (shader) {
00262 trap_R_SetColor( color );
00263 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00264 trap_R_SetColor( NULL );
00265 } else {
00266 Com_sprintf (num, sizeof(num), "%i", value);
00267 value = CG_Text_Width(num, scale, 0);
00268 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00269 }
00270 }
00271 }
00272
00273 }
00274
00275
00276
00277 static void CG_DrawPlayerHead(rectDef_t *rect, qboolean draw2D) {
00278 vec3_t angles;
00279 float size, stretch;
00280 float frac;
00281 float x = rect->x;
00282
00283 VectorClear( angles );
00284
00285 if ( cg.damageTime && cg.time - cg.damageTime < DAMAGE_TIME ) {
00286 frac = (float)(cg.time - cg.damageTime ) / DAMAGE_TIME;
00287 size = rect->w * 1.25 * ( 1.5 - frac * 0.5 );
00288
00289 stretch = size - rect->w * 1.25;
00290
00291 x -= stretch * 0.5 + cg.damageX * stretch * 0.5;
00292
00293 cg.headStartYaw = 180 + cg.damageX * 45;
00294
00295 cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
00296 cg.headEndPitch = 5 * cos( crandom()*M_PI );
00297
00298 cg.headStartTime = cg.time;
00299 cg.headEndTime = cg.time + 100 + random() * 2000;
00300 } else {
00301 if ( cg.time >= cg.headEndTime ) {
00302
00303 cg.headStartYaw = cg.headEndYaw;
00304 cg.headStartPitch = cg.headEndPitch;
00305 cg.headStartTime = cg.headEndTime;
00306 cg.headEndTime = cg.time + 100 + random() * 2000;
00307
00308 cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
00309 cg.headEndPitch = 5 * cos( crandom()*M_PI );
00310 }
00311
00312 size = rect->w * 1.25;
00313 }
00314
00315
00316 if ( cg.headStartTime > cg.time ) {
00317 cg.headStartTime = cg.time;
00318 }
00319
00320 frac = ( cg.time - cg.headStartTime ) / (float)( cg.headEndTime - cg.headStartTime );
00321 frac = frac * frac * ( 3 - 2 * frac );
00322 angles[YAW] = cg.headStartYaw + ( cg.headEndYaw - cg.headStartYaw ) * frac;
00323 angles[PITCH] = cg.headStartPitch + ( cg.headEndPitch - cg.headStartPitch ) * frac;
00324
00325 CG_DrawHead( x, rect->y, rect->w, rect->h, cg.snap->ps.clientNum, angles );
00326 }
00327
00328 static void CG_DrawSelectedPlayerHealth( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00329 clientInfo_t *ci;
00330 int value;
00331 char num[16];
00332
00333 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00334 if (ci) {
00335 if (shader) {
00336 trap_R_SetColor( color );
00337 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00338 trap_R_SetColor( NULL );
00339 } else {
00340 Com_sprintf (num, sizeof(num), "%i", ci->health);
00341 value = CG_Text_Width(num, scale, 0);
00342 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00343 }
00344 }
00345 }
00346
00347 static void CG_DrawSelectedPlayerArmor( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00348 clientInfo_t *ci;
00349 int value;
00350 char num[16];
00351 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00352 if (ci) {
00353 if (ci->armor > 0) {
00354 if (shader) {
00355 trap_R_SetColor( color );
00356 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00357 trap_R_SetColor( NULL );
00358 } else {
00359 Com_sprintf (num, sizeof(num), "%i", ci->armor);
00360 value = CG_Text_Width(num, scale, 0);
00361 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00362 }
00363 }
00364 }
00365 }
00366
00367 qhandle_t CG_StatusHandle(int task) {
00368 qhandle_t h = cgs.media.assaultShader;
00369 switch (task) {
00370 case TEAMTASK_OFFENSE :
00371 h = cgs.media.assaultShader;
00372 break;
00373 case TEAMTASK_DEFENSE :
00374 h = cgs.media.defendShader;
00375 break;
00376 case TEAMTASK_PATROL :
00377 h = cgs.media.patrolShader;
00378 break;
00379 case TEAMTASK_FOLLOW :
00380 h = cgs.media.followShader;
00381 break;
00382 case TEAMTASK_CAMP :
00383 h = cgs.media.campShader;
00384 break;
00385 case TEAMTASK_RETRIEVE :
00386 h = cgs.media.retrieveShader;
00387 break;
00388 case TEAMTASK_ESCORT :
00389 h = cgs.media.escortShader;
00390 break;
00391 default :
00392 h = cgs.media.assaultShader;
00393 break;
00394 }
00395 return h;
00396 }
00397
00398 static void CG_DrawSelectedPlayerStatus( rectDef_t *rect ) {
00399 clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00400 if (ci) {
00401 qhandle_t h;
00402 if (cgs.orderPending) {
00403
00404 if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
00405 return;
00406 }
00407 h = CG_StatusHandle(cgs.currentOrder);
00408 } else {
00409 h = CG_StatusHandle(ci->teamTask);
00410 }
00411 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h );
00412 }
00413 }
00414
00415
00416 static void CG_DrawPlayerStatus( rectDef_t *rect ) {
00417 clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
00418 if (ci) {
00419 qhandle_t h = CG_StatusHandle(ci->teamTask);
00420 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h);
00421 }
00422 }
00423
00424
00425 static void CG_DrawSelectedPlayerName( rectDef_t *rect, float scale, vec4_t color, qboolean voice, int textStyle) {
00426 clientInfo_t *ci;
00427 ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
00428 if (ci) {
00429 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, ci->name, 0, 0, textStyle);
00430 }
00431 }
00432
00433 static void CG_DrawSelectedPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00434 clientInfo_t *ci;
00435 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00436 if (ci) {
00437 const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
00438 if (!p || !*p) {
00439 p = "unknown";
00440 }
00441 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
00442 }
00443 }
00444
00445 static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00446 clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
00447 if (ci) {
00448 const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
00449 if (!p || !*p) {
00450 p = "unknown";
00451 }
00452 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
00453 }
00454 }
00455
00456
00457
00458 static void CG_DrawSelectedPlayerWeapon( rectDef_t *rect ) {
00459 clientInfo_t *ci;
00460
00461 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00462 if (ci) {
00463 if ( cg_weapons[ci->curWeapon].weaponIcon ) {
00464 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ci->curWeapon].weaponIcon );
00465 } else {
00466 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader);
00467 }
00468 }
00469 }
00470
00471 static void CG_DrawPlayerScore( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00472 char num[16];
00473 int value = cg.snap->ps.persistant[PERS_SCORE];
00474
00475 if (shader) {
00476 trap_R_SetColor( color );
00477 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00478 trap_R_SetColor( NULL );
00479 } else {
00480 Com_sprintf (num, sizeof(num), "%i", value);
00481 value = CG_Text_Width(num, scale, 0);
00482 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00483 }
00484 }
00485
00486 static void CG_DrawPlayerItem( rectDef_t *rect, float scale, qboolean draw2D) {
00487 int value;
00488 vec3_t origin, angles;
00489
00490 value = cg.snap->ps.stats[STAT_HOLDABLE_ITEM];
00491 if ( value ) {
00492 CG_RegisterItemVisuals( value );
00493
00494 if (qtrue) {
00495 CG_RegisterItemVisuals( value );
00496 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
00497 } else {
00498 VectorClear( angles );
00499 origin[0] = 90;
00500 origin[1] = 0;
00501 origin[2] = -10;
00502 angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
00503 CG_Draw3DModel(rect->x, rect->y, rect->w, rect->h, cg_items[ value ].models[0], 0, origin, angles );
00504 }
00505 }
00506
00507 }
00508
00509
00510 static void CG_DrawSelectedPlayerPowerup( rectDef_t *rect, qboolean draw2D ) {
00511 clientInfo_t *ci;
00512 int j;
00513 float x, y;
00514
00515 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00516 if (ci) {
00517 x = rect->x;
00518 y = rect->y;
00519
00520 for (j = 0; j < PW_NUM_POWERUPS; j++) {
00521 if (ci->powerups & (1 << j)) {
00522 gitem_t *item;
00523 item = BG_FindItemForPowerup( j );
00524 if (item) {
00525 CG_DrawPic( x, y, rect->w, rect->h, trap_R_RegisterShader( item->icon ) );
00526 x += 3;
00527 y += 3;
00528 return;
00529 }
00530 }
00531 }
00532
00533 }
00534 }
00535
00536
00537 static void CG_DrawSelectedPlayerHead( rectDef_t *rect, qboolean draw2D, qboolean voice ) {
00538 clipHandle_t cm;
00539 clientInfo_t *ci;
00540 float len;
00541 vec3_t origin;
00542 vec3_t mins, maxs, angles;
00543
00544
00545 ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
00546
00547 if (ci) {
00548 if ( cg_draw3dIcons.integer ) {
00549 cm = ci->headModel;
00550 if ( !cm ) {
00551 return;
00552 }
00553
00554
00555 trap_R_ModelBounds( cm, mins, maxs );
00556
00557 origin[2] = -0.5 * ( mins[2] + maxs[2] );
00558 origin[1] = 0.5 * ( mins[1] + maxs[1] );
00559
00560
00561
00562 len = 0.7 * ( maxs[2] - mins[2] );
00563 origin[0] = len / 0.268;
00564
00565
00566 VectorAdd( origin, ci->headOffset, origin );
00567
00568 angles[PITCH] = 0;
00569 angles[YAW] = 180;
00570 angles[ROLL] = 0;
00571
00572 CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, ci->headModel, ci->headSkin, origin, angles );
00573 } else if ( cg_drawIcons.integer ) {
00574 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, ci->modelIcon );
00575 }
00576
00577
00578 if ( ci->deferred ) {
00579 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader );
00580 }
00581 }
00582
00583 }
00584
00585
00586 static void CG_DrawPlayerHealth(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00587 playerState_t *ps;
00588 int value;
00589 char num[16];
00590
00591 ps = &cg.snap->ps;
00592
00593 value = ps->stats[STAT_HEALTH];
00594
00595 if (shader) {
00596 trap_R_SetColor( color );
00597 CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
00598 trap_R_SetColor( NULL );
00599 } else {
00600 Com_sprintf (num, sizeof(num), "%i", value);
00601 value = CG_Text_Width(num, scale, 0);
00602 CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00603 }
00604 }
00605
00606
00607 static void CG_DrawRedScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00608 int value;
00609 char num[16];
00610 if ( cgs.scores1 == SCORE_NOT_PRESENT ) {
00611 Com_sprintf (num, sizeof(num), "-");
00612 }
00613 else {
00614 Com_sprintf (num, sizeof(num), "%i", cgs.scores1);
00615 }
00616 value = CG_Text_Width(num, scale, 0);
00617 CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00618 }
00619
00620 static void CG_DrawBlueScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
00621 int value;
00622 char num[16];
00623
00624 if ( cgs.scores2 == SCORE_NOT_PRESENT ) {
00625 Com_sprintf (num, sizeof(num), "-");
00626 }
00627 else {
00628 Com_sprintf (num, sizeof(num), "%i", cgs.scores2);
00629 }
00630 value = CG_Text_Width(num, scale, 0);
00631 CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00632 }
00633
00634
00635 static void CG_DrawRedName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00636 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_redTeamName.string , 0, 0, textStyle);
00637 }
00638
00639 static void CG_DrawBlueName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00640 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_blueTeamName.string, 0, 0, textStyle);
00641 }
00642
00643 static void CG_DrawBlueFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00644 int i;
00645 for ( i = 0 ; i < cgs.maxclients ; i++ ) {
00646 if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
00647 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
00648 return;
00649 }
00650 }
00651 }
00652
00653 static void CG_DrawBlueFlagStatus(rectDef_t *rect, qhandle_t shader) {
00654 if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
00655 if (cgs.gametype == GT_HARVESTER) {
00656 vec4_t color = {0, 0, 1, 1};
00657 trap_R_SetColor(color);
00658 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.blueCubeIcon );
00659 trap_R_SetColor(NULL);
00660 }
00661 return;
00662 }
00663 if (shader) {
00664 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
00665 } else {
00666 gitem_t *item = BG_FindItemForPowerup( PW_BLUEFLAG );
00667 if (item) {
00668 vec4_t color = {0, 0, 1, 1};
00669 trap_R_SetColor(color);
00670 if( cgs.blueflag >= 0 && cgs.blueflag <= 2 ) {
00671 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.blueflag] );
00672 } else {
00673 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
00674 }
00675 trap_R_SetColor(NULL);
00676 }
00677 }
00678 }
00679
00680 static void CG_DrawBlueFlagHead(rectDef_t *rect) {
00681 int i;
00682 for ( i = 0 ; i < cgs.maxclients ; i++ ) {
00683 if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
00684 vec3_t angles;
00685 VectorClear( angles );
00686 angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
00687 CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
00688 return;
00689 }
00690 }
00691 }
00692
00693 static void CG_DrawRedFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
00694 int i;
00695 for ( i = 0 ; i < cgs.maxclients ; i++ ) {
00696 if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
00697 CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
00698 return;
00699 }
00700 }
00701 }
00702
00703 static void CG_DrawRedFlagStatus(rectDef_t *rect, qhandle_t shader) {
00704 if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
00705 if (cgs.gametype == GT_HARVESTER) {
00706 vec4_t color = {1, 0, 0, 1};
00707 trap_R_SetColor(color);
00708 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.redCubeIcon );
00709 trap_R_SetColor(NULL);
00710 }
00711 return;
00712 }
00713 if (shader) {
00714 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
00715 } else {
00716 gitem_t *item = BG_FindItemForPowerup( PW_REDFLAG );
00717 if (item) {
00718 vec4_t color = {1, 0, 0, 1};
00719 trap_R_SetColor(color);
00720 if( cgs.redflag >= 0 && cgs.redflag <= 2) {
00721 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.redflag] );
00722 } else {
00723 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
00724 }
00725 trap_R_SetColor(NULL);
00726 }
00727 }
00728 }
00729
00730 static void CG_DrawRedFlagHead(rectDef_t *rect) {
00731 int i;
00732 for ( i = 0 ; i < cgs.maxclients ; i++ ) {
00733 if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
00734 vec3_t angles;
00735 VectorClear( angles );
00736 angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
00737 CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
00738 return;
00739 }
00740 }
00741 }
00742
00743 static void CG_HarvesterSkulls(rectDef_t *rect, float scale, vec4_t color, qboolean force2D, int textStyle ) {
00744 char num[16];
00745 vec3_t origin, angles;
00746 qhandle_t handle;
00747 int value = cg.snap->ps.generic1;
00748
00749 if (cgs.gametype != GT_HARVESTER) {
00750 return;
00751 }
00752
00753 if( value > 99 ) {
00754 value = 99;
00755 }
00756
00757 Com_sprintf (num, sizeof(num), "%i", value);
00758 value = CG_Text_Width(num, scale, 0);
00759 CG_Text_Paint(rect->x + (rect->w - value), rect->y + rect->h, scale, color, num, 0, 0, textStyle);
00760
00761 if (cg_drawIcons.integer) {
00762 if (!force2D && cg_draw3dIcons.integer) {
00763 VectorClear(angles);
00764 origin[0] = 90;
00765 origin[1] = 0;
00766 origin[2] = -10;
00767 angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
00768 if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
00769 handle = cgs.media.redCubeModel;
00770 } else {
00771 handle = cgs.media.blueCubeModel;
00772 }
00773 CG_Draw3DModel( rect->x, rect->y, 35, 35, handle, 0, origin, angles );
00774 } else {
00775 if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
00776 handle = cgs.media.redCubeIcon;
00777 } else {
00778 handle = cgs.media.blueCubeIcon;
00779 }
00780 CG_DrawPic( rect->x + 3, rect->y + 16, 20, 20, handle );
00781 }
00782 }
00783 }
00784
00785 static void CG_OneFlagStatus(rectDef_t *rect) {
00786 if (cgs.gametype != GT_1FCTF) {
00787 return;
00788 } else {
00789 gitem_t *item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
00790 if (item) {
00791 if( cgs.flagStatus >= 0 && cgs.flagStatus <= 4 ) {
00792 vec4_t color = {1, 1, 1, 1};
00793 int index = 0;
00794 if (cgs.flagStatus == FLAG_TAKEN_RED) {
00795 color[1] = color[2] = 0;
00796 index = 1;
00797 } else if (cgs.flagStatus == FLAG_TAKEN_BLUE) {
00798 color[0] = color[1] = 0;
00799 index = 1;
00800 } else if (cgs.flagStatus == FLAG_DROPPED) {
00801 index = 2;
00802 }
00803 trap_R_SetColor(color);
00804 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[index] );
00805 }
00806 }
00807 }
00808 }
00809
00810
00811 static void CG_DrawCTFPowerUp(rectDef_t *rect) {
00812 int value;
00813
00814 if (cgs.gametype < GT_CTF) {
00815 return;
00816 }
00817 value = cg.snap->ps.stats[STAT_PERSISTANT_POWERUP];
00818 if ( value ) {
00819 CG_RegisterItemVisuals( value );
00820 CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
00821 }
00822 }
00823
00824
00825
00826 static void CG_DrawTeamColor(rectDef_t *rect, vec4_t color) {
00827 CG_DrawTeamBackground(rect->x, rect->y, rect->w, rect->h, color[3], cg.snap->ps.persistant[PERS_TEAM]);
00828 }
00829
00830 static void CG_DrawAreaPowerUp(rectDef_t *rect, int align, float special, float scale, vec4_t color) {
00831 char num[16];
00832 int sorted[MAX_POWERUPS];
00833 int sortedTime[MAX_POWERUPS];
00834 int i, j, k;
00835 int active;
00836 playerState_t *ps;
00837 int t;
00838 gitem_t *item;
00839 float f;
00840 rectDef_t r2;
00841 float *inc;
00842 r2.x = rect->x;
00843 r2.y = rect->y;
00844 r2.w = rect->w;
00845 r2.h = rect->h;
00846
00847 inc = (align == HUD_VERTICAL) ? &r2.y : &r2.x;
00848
00849 ps = &cg.snap->ps;
00850
00851 if ( ps->stats[STAT_HEALTH] <= 0 ) {
00852 return;
00853 }
00854
00855
00856 active = 0;
00857 for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
00858 if ( !ps->powerups[ i ] ) {
00859 continue;
00860 }
00861 t = ps->powerups[ i ] - cg.time;
00862
00863
00864 if ( t <= 0 || t >= 999000) {
00865 continue;
00866 }
00867
00868
00869 for ( j = 0 ; j < active ; j++ ) {
00870 if ( sortedTime[j] >= t ) {
00871 for ( k = active - 1 ; k >= j ; k-- ) {
00872 sorted[k+1] = sorted[k];
00873 sortedTime[k+1] = sortedTime[k];
00874 }
00875 break;
00876 }
00877 }
00878 sorted[j] = i;
00879 sortedTime[j] = t;
00880 active++;
00881 }
00882
00883
00884 for ( i = 0 ; i < active ; i++ ) {
00885 item = BG_FindItemForPowerup( sorted[i] );
00886
00887 if (item) {
00888 t = ps->powerups[ sorted[i] ];
00889 if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
00890 trap_R_SetColor( NULL );
00891 } else {
00892 vec4_t modulate;
00893
00894 f = (float)( t - cg.time ) / POWERUP_BLINK_TIME;
00895 f -= (int)f;
00896 modulate[0] = modulate[1] = modulate[2] = modulate[3] = f;
00897 trap_R_SetColor( modulate );
00898 }
00899
00900 CG_DrawPic( r2.x, r2.y, r2.w * .75, r2.h, trap_R_RegisterShader( item->icon ) );
00901
00902 Com_sprintf (num, sizeof(num), "%i", sortedTime[i] / 1000);
00903 CG_Text_Paint(r2.x + (r2.w * .75) + 3 , r2.y + r2.h, scale, color, num, 0, 0, 0);
00904 *inc += r2.w + special;
00905 }
00906
00907 }
00908 trap_R_SetColor( NULL );
00909
00910 }
00911
00912 float CG_GetValue(int ownerDraw) {
00913 centity_t *cent;
00914 clientInfo_t *ci;
00915 playerState_t *ps;
00916
00917 cent = &cg_entities[cg.snap->ps.clientNum];
00918 ps = &cg.snap->ps;
00919
00920 switch (ownerDraw) {
00921 case CG_SELECTEDPLAYER_ARMOR:
00922 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00923 return ci->armor;
00924 break;
00925 case CG_SELECTEDPLAYER_HEALTH:
00926 ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
00927 return ci->health;
00928 break;
00929 case CG_PLAYER_ARMOR_VALUE:
00930 return ps->stats[STAT_ARMOR];
00931 break;
00932 case CG_PLAYER_AMMO_VALUE:
00933 if ( cent->currentState.weapon ) {
00934 return ps->ammo[cent->currentState.weapon];
00935 }
00936 break;
00937 case CG_PLAYER_SCORE:
00938 return cg.snap->ps.persistant[PERS_SCORE];
00939 break;
00940 case CG_PLAYER_HEALTH:
00941 return ps->stats[STAT_HEALTH];
00942 break;
00943 case CG_RED_SCORE:
00944 return cgs.scores1;
00945 break;
00946 case CG_BLUE_SCORE:
00947 return cgs.scores2;
00948 break;
00949 default:
00950 break;
00951 }
00952 return -1;
00953 }
00954
00955 qboolean CG_OtherTeamHasFlag() {
00956 if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
00957 int team = cg.snap->ps.persistant[PERS_TEAM];
00958 if (cgs.gametype == GT_1FCTF) {
00959 if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_BLUE) {
00960 return qtrue;
00961 } else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_RED) {
00962 return qtrue;
00963 } else {
00964 return qfalse;
00965 }
00966 } else {
00967 if (team == TEAM_RED && cgs.redflag == FLAG_TAKEN) {
00968 return qtrue;
00969 } else if (team == TEAM_BLUE && cgs.blueflag == FLAG_TAKEN) {
00970 return qtrue;
00971 } else {
00972 return qfalse;
00973 }
00974 }
00975 }
00976 return qfalse;
00977 }
00978
00979 qboolean CG_YourTeamHasFlag() {
00980 if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
00981 int team = cg.snap->ps.persistant[PERS_TEAM];
00982 if (cgs.gametype == GT_1FCTF) {
00983 if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_RED) {
00984 return qtrue;
00985 } else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_BLUE) {
00986 return qtrue;
00987 } else {
00988 return qfalse;
00989 }
00990 } else {
00991 if (team == TEAM_RED && cgs.blueflag == FLAG_TAKEN) {
00992 return qtrue;
00993 } else if (team == TEAM_BLUE && cgs.redflag == FLAG_TAKEN) {
00994 return qtrue;
00995 } else {
00996 return qfalse;
00997 }
00998 }
00999 }
01000 return qfalse;
01001 }
01002
01003
01004
01005 qboolean CG_OwnerDrawVisible(int flags)