q3rally/engine/code/cgame/cg_newdraw.c

1868 lines
49 KiB
C
Raw Normal View History

2011-02-18 14:31:32 +00:00
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2002-2015 Q3Rally Team (Per Thormann - q3rally@gmail.com)
2011-02-18 14:31:32 +00:00
This file is part of q3rally source code.
q3rally source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
q3rally source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with q3rally; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef MISSIONPACK
2011-02-18 14:31:32 +00:00
#error This file not be used for classic Q3A.
#endif
#include "cg_local.h"
#include "../ui/ui_shared.h"
extern displayContextDef_t cgDC;
// set in CG_ParseTeamInfo
//static int sortedTeamPlayers[TEAM_MAXOVERLAY];
//static int numSortedTeamPlayers;
int drawTeamOverlayModificationCount = -1;
//static char systemChat[256];
//static char teamChat1[256];
//static char teamChat2[256];
void CG_InitTeamChat(void) {
2011-02-18 14:31:32 +00:00
memset(teamChat1, 0, sizeof(teamChat1));
memset(teamChat2, 0, sizeof(teamChat2));
memset(systemChat, 0, sizeof(systemChat));
}
void CG_SetPrintString(int type, const char *p) {
if (type == SYSTEM_PRINT) {
strcpy(systemChat, p);
} else {
strcpy(teamChat2, teamChat1);
strcpy(teamChat1, p);
}
}
void CG_CheckOrderPending(void) {
2011-02-18 14:31:32 +00:00
if (cgs.gametype < GT_CTF) {
return;
}
if (cgs.orderPending) {
//clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
const char *p1, *p2, *b;
p1 = p2 = b = NULL;
switch (cgs.currentOrder) {
case TEAMTASK_OFFENSE:
p1 = VOICECHAT_ONOFFENSE;
p2 = VOICECHAT_OFFENSE;
b = "+button7; wait; -button7";
break;
case TEAMTASK_DEFENSE:
p1 = VOICECHAT_ONDEFENSE;
p2 = VOICECHAT_DEFEND;
b = "+button8; wait; -button8";
break;
case TEAMTASK_PATROL:
p1 = VOICECHAT_ONPATROL;
p2 = VOICECHAT_PATROL;
b = "+button9; wait; -button9";
break;
case TEAMTASK_FOLLOW:
p1 = VOICECHAT_ONFOLLOW;
p2 = VOICECHAT_FOLLOWME;
b = "+button10; wait; -button10";
break;
case TEAMTASK_CAMP:
p1 = VOICECHAT_ONCAMPING;
p2 = VOICECHAT_CAMP;
break;
case TEAMTASK_RETRIEVE:
p1 = VOICECHAT_ONGETFLAG;
p2 = VOICECHAT_RETURNFLAG;
break;
case TEAMTASK_ESCORT:
p1 = VOICECHAT_ONFOLLOWCARRIER;
p2 = VOICECHAT_FOLLOWFLAGCARRIER;
break;
}
if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
// to everyone
trap_SendConsoleCommand(va("cmd vsay_team %s\n", p2));
} else {
// for the player self
if (sortedTeamPlayers[cg_currentSelectedPlayer.integer] == cg.snap->ps.clientNum && p1) {
trap_SendConsoleCommand(va("teamtask %i\n", cgs.currentOrder));
//trap_SendConsoleCommand(va("cmd say_team %s\n", p2));
trap_SendConsoleCommand(va("cmd vsay_team %s\n", p1));
} else if (p2) {
//trap_SendConsoleCommand(va("cmd say_team %s, %s\n", ci->name,p));
trap_SendConsoleCommand(va("cmd vtell %d %s\n", sortedTeamPlayers[cg_currentSelectedPlayer.integer], p2));
}
}
if (b) {
trap_SendConsoleCommand(b);
}
cgs.orderPending = qfalse;
}
}
static void CG_SetSelectedPlayerName( void ) {
2011-02-18 14:31:32 +00:00
if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
if (ci) {
trap_Cvar_Set("cg_selectedPlayerName", ci->name);
trap_Cvar_Set("cg_selectedPlayer", va("%d", sortedTeamPlayers[cg_currentSelectedPlayer.integer]));
cgs.currentOrder = ci->teamTask;
}
} else {
trap_Cvar_Set("cg_selectedPlayerName", "Everyone");
}
}
int CG_GetSelectedPlayer( void ) {
2011-02-18 14:31:32 +00:00
if (cg_currentSelectedPlayer.integer < 0 || cg_currentSelectedPlayer.integer >= numSortedTeamPlayers) {
cg_currentSelectedPlayer.integer = 0;
}
return cg_currentSelectedPlayer.integer;
}
void CG_SelectNextPlayer( void ) {
2011-02-18 14:31:32 +00:00
CG_CheckOrderPending();
if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
cg_currentSelectedPlayer.integer++;
} else {
cg_currentSelectedPlayer.integer = 0;
}
CG_SetSelectedPlayerName();
}
void CG_SelectPrevPlayer( void ) {
2011-02-18 14:31:32 +00:00
CG_CheckOrderPending();
if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer <= numSortedTeamPlayers) {
2011-02-18 14:31:32 +00:00
cg_currentSelectedPlayer.integer--;
} else {
cg_currentSelectedPlayer.integer = numSortedTeamPlayers;
}
CG_SetSelectedPlayerName();
}
static void CG_DrawPlayerArmorIcon( rectDef_t *rect, qboolean draw2D ) {
vec3_t angles;
vec3_t origin;
if ( cg_drawStatus.integer == 0 ) {
2011-02-18 14:31:32 +00:00
return;
}
if ( draw2D || ( !cg_draw3dIcons.integer && cg_drawIcons.integer) ) {
2011-02-18 14:31:32 +00:00
CG_DrawPic( rect->x, rect->y + rect->h/2 + 1, rect->w, rect->h, cgs.media.armorIcon );
} else if (cg_draw3dIcons.integer) {
VectorClear( angles );
origin[0] = 90;
origin[1] = 0;
origin[2] = -10;
angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0f;
CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cgs.media.armorModel, 0, origin, angles );
}
2011-02-18 14:31:32 +00:00
}
static void CG_DrawPlayerArmorValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
char num[16];
int value;
2011-02-18 14:31:32 +00:00
playerState_t *ps;
ps = &cg.snap->ps;
value = ps->stats[STAT_ARMOR];
if (shader) {
trap_R_SetColor( color );
2011-02-18 14:31:32 +00:00
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
2011-02-18 14:31:32 +00:00
} else {
Com_sprintf (num, sizeof(num), "%i", value);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
2011-02-18 14:31:32 +00:00
}
}
static void CG_DrawPlayerAmmoIcon( rectDef_t *rect, qboolean draw2D ) {
centity_t *cent;
vec3_t angles;
vec3_t origin;
cent = &cg_entities[cg.snap->ps.clientNum];
if ( draw2D || (!cg_draw3dIcons.integer && cg_drawIcons.integer) ) {
qhandle_t icon;
icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon;
2011-02-18 14:31:32 +00:00
if ( icon ) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, icon );
2011-02-18 14:31:32 +00:00
}
} else if (cg_draw3dIcons.integer) {
if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) {
VectorClear( angles );
origin[0] = 70;
origin[1] = 0;
origin[2] = 0;
angles[YAW] = 90 + 20 * sin( cg.time / 1000.0 );
CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, origin, angles );
}
}
2011-02-18 14:31:32 +00:00
}
static void CG_DrawPlayerAmmoValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
char num[16];
int value;
centity_t *cent;
playerState_t *ps;
cent = &cg_entities[cg.snap->ps.clientNum];
ps = &cg.snap->ps;
if ( cent->currentState.weapon ) {
value = ps->ammo[cent->currentState.weapon];
if ( value > -1 ) {
if (shader) {
trap_R_SetColor( color );
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
} else {
Com_sprintf (num, sizeof(num), "%i", value);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
}
}
}
static void CG_DrawPlayerHead(rectDef_t *rect, qboolean draw2D) {
vec3_t angles;
float size, stretch;
float frac;
float x = rect->x;
VectorClear( angles );
if ( cg.damageTime && cg.time - cg.damageTime < DAMAGE_TIME ) {
frac = (float)(cg.time - cg.damageTime ) / DAMAGE_TIME;
size = rect->w * 1.25 * ( 1.5 - frac * 0.5 );
stretch = size - rect->w * 1.25;
// kick in the direction of damage
x -= stretch * 0.5 + cg.damageX * stretch * 0.5;
cg.headStartYaw = 180 + cg.damageX * 45;
cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
cg.headEndPitch = 5 * cos( crandom()*M_PI );
cg.headStartTime = cg.time;
cg.headEndTime = cg.time + 100 + random() * 2000;
} else {
if ( cg.time >= cg.headEndTime ) {
// select a new head angle
cg.headStartYaw = cg.headEndYaw;
cg.headStartPitch = cg.headEndPitch;
cg.headStartTime = cg.headEndTime;
cg.headEndTime = cg.time + 100 + random() * 2000;
cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
cg.headEndPitch = 5 * cos( crandom()*M_PI );
}
}
// if the server was frozen for a while we may have a bad head start time
if ( cg.headStartTime > cg.time ) {
cg.headStartTime = cg.time;
}
frac = ( cg.time - cg.headStartTime ) / (float)( cg.headEndTime - cg.headStartTime );
frac = frac * frac * ( 3 - 2 * frac );
angles[YAW] = cg.headStartYaw + ( cg.headEndYaw - cg.headStartYaw ) * frac;
angles[PITCH] = cg.headStartPitch + ( cg.headEndPitch - cg.headStartPitch ) * frac;
// Q3Rally Code (removed function)
// CG_DrawHead( x, rect->y, rect->w, rect->h, cg.snap->ps.clientNum, angles );
// Q3Rally Code END
}
static void CG_DrawSelectedPlayerHealth( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
clientInfo_t *ci;
int value;
char num[16];
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
if (shader) {
trap_R_SetColor( color );
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
} else {
Com_sprintf (num, sizeof(num), "%i", ci->health);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
}
}
static void CG_DrawSelectedPlayerArmor( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
clientInfo_t *ci;
int value;
char num[16];
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
if (ci->armor > 0) {
if (shader) {
trap_R_SetColor( color );
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
} else {
Com_sprintf (num, sizeof(num), "%i", ci->armor);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
}
}
}
qhandle_t CG_StatusHandle(int task) {
qhandle_t h;
2011-02-18 14:31:32 +00:00
switch (task) {
case TEAMTASK_OFFENSE :
h = cgs.media.assaultShader;
break;
case TEAMTASK_DEFENSE :
h = cgs.media.defendShader;
break;
case TEAMTASK_PATROL :
h = cgs.media.patrolShader;
break;
case TEAMTASK_FOLLOW :
h = cgs.media.followShader;
break;
case TEAMTASK_CAMP :
h = cgs.media.campShader;
break;
case TEAMTASK_RETRIEVE :
h = cgs.media.retrieveShader;
break;
case TEAMTASK_ESCORT :
h = cgs.media.escortShader;
break;
default :
h = cgs.media.assaultShader;
break;
}
return h;
}
static void CG_DrawSelectedPlayerStatus( rectDef_t *rect ) {
clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
qhandle_t h;
if (cgs.orderPending) {
// blink the icon
if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
return;
}
h = CG_StatusHandle(cgs.currentOrder);
} else {
h = CG_StatusHandle(ci->teamTask);
}
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h );
}
}
static void CG_DrawPlayerStatus( rectDef_t *rect ) {
clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
if (ci) {
qhandle_t h = CG_StatusHandle(ci->teamTask);
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h);
}
}
static void CG_DrawSelectedPlayerName( rectDef_t *rect, float scale, vec4_t color, qboolean voice, int textStyle) {
clientInfo_t *ci;
ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
if (ci) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, ci->name, 0, 0, textStyle);
}
}
static void CG_DrawSelectedPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
clientInfo_t *ci;
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
if (!p || !*p) {
p = "unknown";
}
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
}
}
static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
if (ci) {
const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
if (!p || !*p) {
p = "unknown";
}
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
}
}
static void CG_DrawSelectedPlayerWeapon( rectDef_t *rect ) {
clientInfo_t *ci;
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
if ( cg_weapons[ci->curWeapon].weaponIcon ) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ci->curWeapon].weaponIcon );
} else {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader);
}
}
}
static void CG_DrawPlayerScore( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
char num[16];
int value = cg.snap->ps.persistant[PERS_SCORE];
if (shader) {
trap_R_SetColor( color );
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
} else {
Com_sprintf (num, sizeof(num), "%i", value);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
}
static void CG_DrawPlayerItem( rectDef_t *rect, float scale, qboolean draw2D) {
int value;
vec3_t origin, angles;
value = cg.snap->ps.stats[STAT_HOLDABLE_ITEM];
if ( value ) {
CG_RegisterItemVisuals( value );
if (qtrue) {
CG_RegisterItemVisuals( value );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
} else {
VectorClear( angles );
origin[0] = 90;
origin[1] = 0;
origin[2] = -10;
angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
CG_Draw3DModel(rect->x, rect->y, rect->w, rect->h, cg_items[ value ].models[0], 0, origin, angles );
}
}
}
static void CG_DrawSelectedPlayerPowerup( rectDef_t *rect, qboolean draw2D ) {
clientInfo_t *ci;
int j;
float x, y;
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
if (ci) {
x = rect->x;
y = rect->y;
for (j = 0; j < PW_NUM_POWERUPS; j++) {
if (ci->powerups & (1 << j)) {
gitem_t *item;
item = BG_FindItemForPowerup( j );
if (item) {
CG_DrawPic( x, y, rect->w, rect->h, trap_R_RegisterShader( item->icon ) );
return;
}
}
}
}
}
static void CG_DrawSelectedPlayerHead( rectDef_t *rect, qboolean draw2D, qboolean voice ) {
clipHandle_t cm;
clientInfo_t *ci;
float len;
vec3_t origin;
vec3_t mins, maxs, angles;
ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
if (ci) {
if ( cg_draw3dIcons.integer ) {
cm = ci->headModel;
if ( !cm ) {
return;
}
// offset the origin y and z to center the head
trap_R_ModelBounds( cm, mins, maxs );
origin[2] = -0.5 * ( mins[2] + maxs[2] );
origin[1] = 0.5 * ( mins[1] + maxs[1] );
// calculate distance so the head nearly fills the box
// assume heads are taller than wide
len = 0.7 * ( maxs[2] - mins[2] );
origin[0] = len / 0.268; // len / tan( fov/2 )
// allow per-model tweaking
VectorAdd( origin, ci->headOffset, origin );
angles[PITCH] = 0;
angles[YAW] = 180;
angles[ROLL] = 0;
CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, ci->headModel, ci->headSkin, origin, angles );
} else if ( cg_drawIcons.integer ) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, ci->modelIcon );
}
// if they are deferred, draw a cross out
if ( ci->deferred ) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader );
}
}
}
static void CG_DrawPlayerHealth(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
playerState_t *ps;
int value;
char num[16];
ps = &cg.snap->ps;
value = ps->stats[STAT_HEALTH];
if (shader) {
trap_R_SetColor( color );
CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
trap_R_SetColor( NULL );
} else {
Com_sprintf (num, sizeof(num), "%i", value);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
}
static void CG_DrawRedScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
int value;
char num[16];
if ( cgs.scores1 == SCORE_NOT_PRESENT ) {
Com_sprintf (num, sizeof(num), "-");
}
else {
Com_sprintf (num, sizeof(num), "%i", cgs.scores1);
}
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
static void CG_DrawBlueScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
int value;
char num[16];
if ( cgs.scores2 == SCORE_NOT_PRESENT ) {
Com_sprintf (num, sizeof(num), "-");
}
else {
Com_sprintf (num, sizeof(num), "%i", cgs.scores2);
}
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
}
// FIXME: team name support
static void CG_DrawRedName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_redTeamName.string , 0, 0, textStyle);
}
static void CG_DrawBlueName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_blueTeamName.string, 0, 0, textStyle);
}
static void CG_DrawBlueFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
int i;
for ( i = 0 ; i < cgs.maxclients ; i++ ) {
if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
return;
}
}
}
static void CG_DrawBlueFlagStatus(rectDef_t *rect, qhandle_t shader) {
if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
if (cgs.gametype == GT_HARVESTER) {
vec4_t color = {0, 0, 1, 1};
trap_R_SetColor(color);
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.blueCubeIcon );
trap_R_SetColor(NULL);
}
return;
}
if (shader) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
} else {
gitem_t *item = BG_FindItemForPowerup( PW_BLUEFLAG );
if (item) {
vec4_t color = {0, 0, 1, 1};
trap_R_SetColor(color);
if( cgs.blueflag >= 0 && cgs.blueflag <= 2 ) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.blueflag] );
} else {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
}
trap_R_SetColor(NULL);
}
}
}
static void CG_DrawBlueFlagHead(rectDef_t *rect) {
int i;
for ( i = 0 ; i < cgs.maxclients ; i++ ) {
if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
vec3_t angles;
VectorClear( angles );
angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
// Q3Rally Code (removed function)
// CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
// Q3Rally Code END
return;
}
}
}
static void CG_DrawRedFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
int i;
for ( i = 0 ; i < cgs.maxclients ; i++ ) {
if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
return;
}
}
}
static void CG_DrawRedFlagStatus(rectDef_t *rect, qhandle_t shader) {
if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
if (cgs.gametype == GT_HARVESTER) {
vec4_t color = {1, 0, 0, 1};
trap_R_SetColor(color);
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.redCubeIcon );
trap_R_SetColor(NULL);
}
return;
}
if (shader) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
} else {
gitem_t *item = BG_FindItemForPowerup( PW_REDFLAG );
if (item) {
vec4_t color = {1, 0, 0, 1};
trap_R_SetColor(color);
if( cgs.redflag >= 0 && cgs.redflag <= 2) {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.redflag] );
} else {
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
}
trap_R_SetColor(NULL);
}
}
}
static void CG_DrawRedFlagHead(rectDef_t *rect) {
int i;
for ( i = 0 ; i < cgs.maxclients ; i++ ) {
if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
vec3_t angles;
VectorClear( angles );
angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
// Q3Rally Code (removed function)
// CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
// Q3Rally Code END
return;
}
}
}
static void CG_HarvesterSkulls(rectDef_t *rect, float scale, vec4_t color, qboolean force2D, int textStyle ) {
char num[16];
vec3_t origin, angles;
qhandle_t handle;
int value = cg.snap->ps.generic1;
if (cgs.gametype != GT_HARVESTER) {
return;
}
if( value > 99 ) {
value = 99;
}
Com_sprintf (num, sizeof(num), "%i", value);
value = CG_Text_Width(num, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value), rect->y + rect->h, scale, color, num, 0, 0, textStyle);
if (cg_drawIcons.integer) {
if (!force2D && cg_draw3dIcons.integer) {
VectorClear(angles);
origin[0] = 90;
origin[1] = 0;
origin[2] = -10;
angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
handle = cgs.media.redCubeModel;
} else {
handle = cgs.media.blueCubeModel;
}
CG_Draw3DModel( rect->x, rect->y, 35, 35, handle, 0, origin, angles );
} else {
if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
handle = cgs.media.redCubeIcon;
} else {
handle = cgs.media.blueCubeIcon;
}
CG_DrawPic( rect->x + 3, rect->y + 16, 20, 20, handle );
}
}
}
static void CG_OneFlagStatus(rectDef_t *rect) {
if (cgs.gametype != GT_1FCTF) {
return;
} else {
gitem_t *item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
if (item) {
if( cgs.flagStatus >= 0 && cgs.flagStatus <= 4 ) {
vec4_t color = {1, 1, 1, 1};
int index = 0;
if (cgs.flagStatus == FLAG_TAKEN_RED) {
color[1] = color[2] = 0;
index = 1;
} else if (cgs.flagStatus == FLAG_TAKEN_BLUE) {
color[0] = color[1] = 0;
index = 1;
} else if (cgs.flagStatus == FLAG_DROPPED) {
index = 2;
}
trap_R_SetColor(color);
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[index] );
}
}
}
}
static void CG_DrawCTFPowerUp(rectDef_t *rect) {
int value;
if (cgs.gametype < GT_CTF) {
return;
}
2011-02-18 14:31:32 +00:00
value = cg.snap->ps.stats[STAT_PERSISTANT_POWERUP];
if ( value ) {
CG_RegisterItemVisuals( value );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
}
}
static void CG_DrawTeamColor(rectDef_t *rect, vec4_t color) {
CG_DrawTeamBackground(rect->x, rect->y, rect->w, rect->h, color[3], cg.snap->ps.persistant[PERS_TEAM]);
}
static void CG_DrawAreaPowerUp(rectDef_t *rect, int align, float special, float scale, vec4_t color) {
char num[16];
int sorted[MAX_POWERUPS];
int sortedTime[MAX_POWERUPS];
int i, j, k;
int active;
playerState_t *ps;
int t;
gitem_t *item;
float f;
rectDef_t r2;
float *inc;
r2.x = rect->x;
r2.y = rect->y;
r2.w = rect->w;
r2.h = rect->h;
inc = (align == HUD_VERTICAL) ? &r2.y : &r2.x;
ps = &cg.snap->ps;
if ( ps->stats[STAT_HEALTH] <= 0 ) {
return;
}
// sort the list by time remaining
active = 0;
for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
if ( !ps->powerups[ i ] ) {
continue;
}
// ZOID--don't draw if the power up has unlimited time
2011-02-18 14:31:32 +00:00
// This is true of the CTF flags
if ( ps->powerups[ i ] == INT_MAX ) {
continue;
}
t = ps->powerups[ i ] - cg.time;
if ( t <= 0 ) {
2011-02-18 14:31:32 +00:00
continue;
}
// insert into the list
for ( j = 0 ; j < active ; j++ ) {
if ( sortedTime[j] >= t ) {
for ( k = active - 1 ; k >= j ; k-- ) {
sorted[k+1] = sorted[k];
sortedTime[k+1] = sortedTime[k];
}
break;
}
}
sorted[j] = i;
sortedTime[j] = t;
active++;
}
// draw the icons and timers
for ( i = 0 ; i < active ; i++ ) {
item = BG_FindItemForPowerup( sorted[i] );
if (item) {
t = ps->powerups[ sorted[i] ];
if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
trap_R_SetColor( NULL );
} else {
vec4_t modulate;
f = (float)( t - cg.time ) / POWERUP_BLINK_TIME;
f -= (int)f;
modulate[0] = modulate[1] = modulate[2] = modulate[3] = f;
trap_R_SetColor( modulate );
}
CG_DrawPic( r2.x, r2.y, r2.w * .75, r2.h, trap_R_RegisterShader( item->icon ) );
Com_sprintf (num, sizeof(num), "%i", sortedTime[i] / 1000);
CG_Text_Paint(r2.x + (r2.w * .75) + 3 , r2.y + r2.h, scale, color, num, 0, 0, 0);
*inc += r2.w + special;
}
}
trap_R_SetColor( NULL );
}
float CG_GetValue(int ownerDraw) {
centity_t *cent;
clientInfo_t *ci;
playerState_t *ps;
cent = &cg_entities[cg.snap->ps.clientNum];
ps = &cg.snap->ps;
switch (ownerDraw) {
case CG_SELECTEDPLAYER_ARMOR:
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
return ci->armor;
break;
case CG_SELECTEDPLAYER_HEALTH:
ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
return ci->health;
break;
case CG_PLAYER_ARMOR_VALUE:
return ps->stats[STAT_ARMOR];
break;
case CG_PLAYER_AMMO_VALUE:
if ( cent->currentState.weapon ) {
return ps->ammo[cent->currentState.weapon];
}
break;
case CG_PLAYER_SCORE:
return cg.snap->ps.persistant[PERS_SCORE];
break;
case CG_PLAYER_HEALTH:
return ps->stats[STAT_HEALTH];
break;
case CG_RED_SCORE:
return cgs.scores1;
break;
case CG_BLUE_SCORE:
return cgs.scores2;
break;
default:
break;
}
return -1;
}
qboolean CG_OtherTeamHasFlag(void) {
2011-02-18 14:31:32 +00:00
if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
int team = cg.snap->ps.persistant[PERS_TEAM];
if (cgs.gametype == GT_1FCTF) {
if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_BLUE) {
return qtrue;
} else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_RED) {
return qtrue;
} else {
return qfalse;
}
} else {
if (team == TEAM_RED && cgs.redflag == FLAG_TAKEN) {
return qtrue;
} else if (team == TEAM_BLUE && cgs.blueflag == FLAG_TAKEN) {
return qtrue;
} else {
return qfalse;
}
}
}
return qfalse;
}
qboolean CG_YourTeamHasFlag(void) {
2011-02-18 14:31:32 +00:00
if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
int team = cg.snap->ps.persistant[PERS_TEAM];
if (cgs.gametype == GT_1FCTF) {
if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_RED) {
return qtrue;
} else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_BLUE) {
return qtrue;
} else {
return qfalse;
}
} else {
if (team == TEAM_RED && cgs.blueflag == FLAG_TAKEN) {
return qtrue;
} else if (team == TEAM_BLUE && cgs.redflag == FLAG_TAKEN) {
return qtrue;
} else {
return qfalse;
}
}
}
return qfalse;
}
// THINKABOUTME: should these be exclusive or inclusive..
//
qboolean CG_OwnerDrawVisible(int flags) {
if (flags & CG_SHOW_TEAMINFO) {
return (cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
}
if (flags & CG_SHOW_NOTEAMINFO) {
return !(cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
}
if (flags & CG_SHOW_OTHERTEAMHASFLAG) {
return CG_OtherTeamHasFlag();
}
if (flags & CG_SHOW_YOURTEAMHASENEMYFLAG) {
return CG_YourTeamHasFlag();
}
if (flags & (CG_SHOW_BLUE_TEAM_HAS_REDFLAG | CG_SHOW_RED_TEAM_HAS_BLUEFLAG)) {
if (flags & CG_SHOW_BLUE_TEAM_HAS_REDFLAG && (cgs.redflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_RED)) {
return qtrue;
} else if (flags & CG_SHOW_RED_TEAM_HAS_BLUEFLAG && (cgs.blueflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_BLUE)) {
return qtrue;
}
return qfalse;
}
if (flags & CG_SHOW_ANYTEAMGAME) {
if( cgs.gametype >= GT_TEAM) {
return qtrue;
}
}
if (flags & CG_SHOW_ANYNONTEAMGAME) {
if( cgs.gametype < GT_TEAM) {
return qtrue;
}
}
if (flags & CG_SHOW_HARVESTER) {
if( cgs.gametype == GT_HARVESTER ) {
return qtrue;
} else {
return qfalse;
}
}
if (flags & CG_SHOW_ONEFLAG) {
if( cgs.gametype == GT_1FCTF ) {
return qtrue;
} else {
return qfalse;
}
}
if (flags & CG_SHOW_CTF) {
if( cgs.gametype == GT_CTF ) {
return qtrue;
}
}
if (flags & CG_SHOW_OBELISK) {
if( cgs.gametype == GT_OBELISK ) {
return qtrue;
} else {
return qfalse;
}
}
if (flags & CG_SHOW_HEALTHCRITICAL) {
if (cg.snap->ps.stats[STAT_HEALTH] < 25) {
return qtrue;
}
}
if (flags & CG_SHOW_HEALTHOK) {
if (cg.snap->ps.stats[STAT_HEALTH] >= 25) {
2011-02-18 14:31:32 +00:00
return qtrue;
}
}
if (flags & CG_SHOW_SINGLEPLAYER) {
if( cgs.gametype == GT_SINGLE_PLAYER ) {
return qtrue;
}
}
if (flags & CG_SHOW_TOURNAMENT) {
if( cgs.gametype == GT_TOURNAMENT ) {
return qtrue;
}
}
if (flags & CG_SHOW_DURINGINCOMINGVOICE) {
}
if (flags & CG_SHOW_IF_PLAYER_HAS_FLAG) {
if (cg.snap->ps.powerups[PW_REDFLAG] || cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) {
return qtrue;
}
}
return qfalse;
}
static void CG_DrawPlayerHasFlag(rectDef_t *rect, qboolean force2D) {
int adj = (force2D) ? 0 : 2;
if( cg.predictedPlayerState.powerups[PW_REDFLAG] ) {
CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_RED, force2D);
} else if( cg.predictedPlayerState.powerups[PW_BLUEFLAG] ) {
CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_BLUE, force2D);
} else if( cg.predictedPlayerState.powerups[PW_NEUTRALFLAG] ) {
CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_FREE, force2D);
}
}
static void CG_DrawAreaSystemChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, systemChat, 0, 0, 0);
}
static void CG_DrawAreaTeamChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color,teamChat1, 0, 0, 0);
}
static void CG_DrawAreaChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, teamChat2, 0, 0, 0);
}
const char *CG_GetKillerText(void) {
2011-02-18 14:31:32 +00:00
const char *s = "";
if ( cg.killerName[0] ) {
s = va("Fragged by %s", cg.killerName );
}
return s;
}
static void CG_DrawKiller(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
// fragged by ... line
if ( cg.killerName[0] ) {
int x = rect->x + rect->w / 2;
CG_Text_Paint(x - CG_Text_Width(CG_GetKillerText(), scale, 0) / 2, rect->y + rect->h, scale, color, CG_GetKillerText(), 0, 0, textStyle);
}
}
static void CG_DrawCapFragLimit(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
int limit = (cgs.gametype >= GT_CTF) ? cgs.capturelimit : cgs.fraglimit;
CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", limit),0, 0, textStyle);
}
static void CG_Draw1stPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
if (cgs.scores1 != SCORE_NOT_PRESENT) {
CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores1),0, 0, textStyle);
}
}
static void CG_Draw2ndPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
if (cgs.scores2 != SCORE_NOT_PRESENT) {
CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores2),0, 0, textStyle);
}
}
const char *CG_GetGameStatusText(void) {
2011-02-18 14:31:32 +00:00
const char *s = "";
if ( cgs.gametype < GT_TEAM) {
if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
s = va("%s place with %i",CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ),cg.snap->ps.persistant[PERS_SCORE] );
}
} else {
// Q3Rally Code Start
/*
if ( cg.teamScores[0] == cg.teamScores[1] ) {
s = va("Teams are tied at %i", cg.teamScores[0] );
} else if ( cg.teamScores[0] >= cg.teamScores[1] ) {
s = va("Red leads Blue, %i to %i", cg.teamScores[0], cg.teamScores[1] );
} else {
s = va("Blue leads Red, %i to %i", cg.teamScores[1], cg.teamScores[0] );
}
*/
int team = GetTeamAtRank(1);
if ( TiedWinner() ) {
s = va("Winners are tied at %i", cg.teamScores[team-TEAM_RED] );
}
else {
switch(team){
case TEAM_RED:
teamName = "Red";
break;
case TEAM_BLUE:
teamName = "Blue";
break;
case TEAM_GREEN:
teamName = "Green";
break;
case TEAM_YELLOW:
teamName = "Yellow";
break;
}
s = va("%s leads with %i", teamName, cg.teamScores[team-TEAM_RED] );
}
// Q3Rally Code END
}
return s;
}
static void CG_DrawGameStatus(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GetGameStatusText(), 0, 0, textStyle);
}
const char *CG_GameTypeString(void) {
2011-02-18 14:31:32 +00:00
if ( cgs.gametype == GT_FFA ) {
return "Free For All";
} else if ( cgs.gametype == GT_TEAM ) {
return "Team Deathmatch";
} else if ( cgs.gametype == GT_CTF ) {
return "Capture the Flag";
} else if ( cgs.gametype == GT_1FCTF ) {
return "One Flag CTF";
} else if ( cgs.gametype == GT_OBELISK ) {
return "Overload";
} else if ( cgs.gametype == GT_HARVESTER ) {
return "Harvester";
}
return "";
}
static void CG_DrawGameType(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GameTypeString(), 0, 0, textStyle);
}
static void CG_Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
int len, count;
vec4_t newColor;
glyphInfo_t *glyph;
if (text) {
const char *s = text;
2011-02-18 14:31:32 +00:00
float max = *maxX;
float useScale;
fontInfo_t *font = &cgDC.Assets.textFont;
if (scale <= cg_smallFont.value) {
font = &cgDC.Assets.smallFont;
} else if (scale > cg_bigFont.value) {
font = &cgDC.Assets.bigFont;
}
useScale = scale * font->glyphScale;
trap_R_SetColor( color );
len = strlen(text);
if (limit > 0 && len > limit) {
len = limit;
}
count = 0;
while (s && *s && count < len) {
glyph = &font->glyphs[*s & 255];
2011-02-18 14:31:32 +00:00
if ( Q_IsColorString( s ) ) {
memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
newColor[3] = color[3];
trap_R_SetColor( newColor );
s += 2;
continue;
} else {
float yadj = useScale * glyph->top;
if (CG_Text_Width(s, scale, 1) + x > max) {
2011-02-18 14:31:32 +00:00
*maxX = 0;
break;
}
CG_Text_PaintChar(x, y - yadj,
glyph->imageWidth,
glyph->imageHeight,
useScale,
glyph->s,
glyph->t,
glyph->s2,
glyph->t2,
glyph->glyph);
x += (glyph->xSkip * useScale) + adjust;
*maxX = x;
count++;
s++;
}
}
trap_R_SetColor( NULL );
}
}
#define PIC_WIDTH 12
void CG_DrawNewTeamInfo(rectDef_t *rect, float text_x, float text_y, float scale, vec4_t color, qhandle_t shader) {
int xx;
float y;
int i, j, len, count;
const char *p;
vec4_t hcolor;
float pwidth, lwidth, maxx, leftOver;
clientInfo_t *ci;
gitem_t *item;
qhandle_t h;
// max player name width
pwidth = 0;
count = (numSortedTeamPlayers > 8) ? 8 : numSortedTeamPlayers;
for (i = 0; i < count; i++) {
ci = cgs.clientinfo + sortedTeamPlayers[i];
if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
len = CG_Text_Width( ci->name, scale, 0);
if (len > pwidth)
pwidth = len;
}
}
// max location name width
lwidth = 0;
for (i = 1; i < MAX_LOCATIONS; i++) {
p = CG_ConfigString(CS_LOCATIONS + i);
if (p && *p) {
len = CG_Text_Width(p, scale, 0);
if (len > lwidth)
lwidth = len;
}
}
y = rect->y;
for (i = 0; i < count; i++) {
ci = cgs.clientinfo + sortedTeamPlayers[i];
if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
xx = rect->x + 1;
for (j = 0; j <= PW_NUM_POWERUPS; j++) {
if (ci->powerups & (1 << j)) {
item = BG_FindItemForPowerup( j );
if (item) {
CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, trap_R_RegisterShader( item->icon ) );
xx += PIC_WIDTH;
}
}
}
// FIXME: max of 3 powerups shown properly
xx = rect->x + (PIC_WIDTH * 3) + 2;
CG_GetColorForHealth( ci->health, ci->armor, hcolor );
trap_R_SetColor(hcolor);
CG_DrawPic( xx, y + 1, PIC_WIDTH - 2, PIC_WIDTH - 2, cgs.media.heartShader );
//Com_sprintf (st, sizeof(st), "%3i %3i", ci->health, ci->armor);
//CG_Text_Paint(xx, y + text_y, scale, hcolor, st, 0, 0);
// draw weapon icon
xx += PIC_WIDTH + 1;
// weapon used is not that useful, use the space for task
#if 0
if ( cg_weapons[ci->curWeapon].weaponIcon ) {
CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cg_weapons[ci->curWeapon].weaponIcon );
} else {
CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cgs.media.deferShader );
}
#endif
trap_R_SetColor(NULL);
if (cgs.orderPending) {
// blink the icon
if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
h = 0;
} else {
h = CG_StatusHandle(cgs.currentOrder);
}
} else {
h = CG_StatusHandle(ci->teamTask);
}
if (h) {
CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, h);
}
xx += PIC_WIDTH + 1;
leftOver = rect->w - xx;
maxx = xx + leftOver / 3;
CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, ci->name, 0, 0);
p = CG_ConfigString(CS_LOCATIONS + ci->location);
if (!p || !*p) {
p = "unknown";
}
xx += leftOver / 3 + 2;
maxx = rect->w - 4;
CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, p, 0, 0);
y += text_y + 2;
if ( y + text_y + 2 > rect->y + rect->h ) {
break;
}
}
}
}
void CG_DrawTeamSpectators(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
if (cg.spectatorLen) {
float maxX;
if (cg.spectatorWidth == -1) {
cg.spectatorWidth = 0;
cg.spectatorPaintX = rect->x + 1;
cg.spectatorPaintX2 = -1;
}
if (cg.spectatorOffset > cg.spectatorLen) {
cg.spectatorOffset = 0;
cg.spectatorPaintX = rect->x + 1;
cg.spectatorPaintX2 = -1;
}
if (cg.time > cg.spectatorTime) {
cg.spectatorTime = cg.time + 10;
if (cg.spectatorPaintX <= rect->x + 2) {
if (cg.spectatorOffset < cg.spectatorLen) {
cg.spectatorPaintX += CG_Text_Width(&cg.spectatorList[cg.spectatorOffset], scale, 1) - 1;
cg.spectatorOffset++;
} else {
cg.spectatorOffset = 0;
if (cg.spectatorPaintX2 >= 0) {
cg.spectatorPaintX = cg.spectatorPaintX2;
} else {
cg.spectatorPaintX = rect->x + rect->w - 2;
}
cg.spectatorPaintX2 = -1;
}
} else {
cg.spectatorPaintX--;
if (cg.spectatorPaintX2 >= 0) {
cg.spectatorPaintX2--;
}
}
}
maxX = rect->x + rect->w - 2;
CG_Text_Paint_Limit(&maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, &cg.spectatorList[cg.spectatorOffset], 0, 0);
if (cg.spectatorPaintX2 >= 0) {
float maxX2 = rect->x + rect->w - 2;
CG_Text_Paint_Limit(&maxX2, cg.spectatorPaintX2, rect->y + rect->h - 3, scale, color, cg.spectatorList, 0, cg.spectatorOffset);
}
if (cg.spectatorOffset && maxX > 0) {
// if we have an offset ( we are skipping the first part of the string ) and we fit the string
if (cg.spectatorPaintX2 == -1) {
cg.spectatorPaintX2 = rect->x + rect->w - 2;
}
} else {
cg.spectatorPaintX2 = -1;
}
}
}
void CG_DrawMedal(int ownerDraw, rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
score_t *score = &cg.scores[cg.selectedScore];
float value = 0;
char *text = NULL;
color[3] = 0.25;
switch (ownerDraw) {
case CG_ACCURACY:
value = score->accuracy;
break;
case CG_ASSISTS:
value = score->assistCount;
break;
case CG_DEFEND:
value = score->defendCount;
break;
case CG_EXCELLENT:
value = score->excellentCount;
break;
case CG_IMPRESSIVE:
value = score->impressiveCount;
break;
case CG_PERFECT:
value = score->perfect;
break;
case CG_GAUNTLET:
value = score->guantletCount;
break;
case CG_CAPTURES:
value = score->captures;
break;
}
if (value > 0) {
if (ownerDraw != CG_PERFECT) {
if (ownerDraw == CG_ACCURACY) {
text = va("%i%%", (int)value);
if (value > 50) {
color[3] = 1.0;
}
} else {
text = va("%i", (int)value);
color[3] = 1.0;
}
} else {
if (value) {
color[3] = 1.0;
}
text = "Wow";
}
}
trap_R_SetColor(color);
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
if (text) {
color[3] = 1.0;
value = CG_Text_Width(text, scale, 0);
CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h + 10 , scale, color, text, 0, 0, 0);
}
trap_R_SetColor(NULL);
}
//
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) {
rectDef_t rect;
if ( cg_drawStatus.integer == 0 ) {
return;
}
//if (ownerDrawFlags != 0 && !CG_OwnerDrawVisible(ownerDrawFlags)) {
// return;
//}
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
switch (ownerDraw) {
case CG_PLAYER_ARMOR_ICON:
CG_DrawPlayerArmorIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
break;
case CG_PLAYER_ARMOR_ICON2D:
CG_DrawPlayerArmorIcon(&rect, qtrue);
break;
case CG_PLAYER_ARMOR_VALUE:
CG_DrawPlayerArmorValue(&rect, scale, color, shader, textStyle);
break;
case CG_PLAYER_AMMO_ICON:
CG_DrawPlayerAmmoIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
break;
case CG_PLAYER_AMMO_ICON2D:
CG_DrawPlayerAmmoIcon(&rect, qtrue);
break;
case CG_PLAYER_AMMO_VALUE:
CG_DrawPlayerAmmoValue(&rect, scale, color, shader, textStyle);
break;
case CG_SELECTEDPLAYER_HEAD:
CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qfalse);
break;
case CG_VOICE_HEAD:
CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qtrue);
break;
case CG_VOICE_NAME:
CG_DrawSelectedPlayerName(&rect, scale, color, qtrue, textStyle);
break;
case CG_SELECTEDPLAYER_STATUS:
CG_DrawSelectedPlayerStatus(&rect);
break;
case CG_SELECTEDPLAYER_ARMOR:
CG_DrawSelectedPlayerArmor(&rect, scale, color, shader, textStyle);
break;
case CG_SELECTEDPLAYER_HEALTH:
CG_DrawSelectedPlayerHealth(&rect, scale, color, shader, textStyle);
break;
case CG_SELECTEDPLAYER_NAME:
CG_DrawSelectedPlayerName(&rect, scale, color, qfalse, textStyle);
break;
case CG_SELECTEDPLAYER_LOCATION:
CG_DrawSelectedPlayerLocation(&rect, scale, color, textStyle);
break;
case CG_SELECTEDPLAYER_WEAPON:
CG_DrawSelectedPlayerWeapon(&rect);
break;
case CG_SELECTEDPLAYER_POWERUP:
CG_DrawSelectedPlayerPowerup(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
break;
case CG_PLAYER_HEAD:
CG_DrawPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
break;
case CG_PLAYER_ITEM:
CG_DrawPlayerItem(&rect, scale, ownerDrawFlags & CG_SHOW_2DONLY);
break;
case CG_PLAYER_SCORE:
CG_DrawPlayerScore(&rect, scale, color, shader, textStyle);
break;
case CG_PLAYER_HEALTH:
CG_DrawPlayerHealth(&rect, scale, color, shader, textStyle);
break;
case CG_RED_SCORE:
CG_DrawRedScore(&rect, scale, color, shader, textStyle);
break;
case CG_BLUE_SCORE:
CG_DrawBlueScore(&rect, scale, color, shader, textStyle);
break;
case CG_RED_NAME:
CG_DrawRedName(&rect, scale, color, textStyle);
break;
case CG_BLUE_NAME:
CG_DrawBlueName(&rect, scale, color, textStyle);
break;
case CG_BLUE_FLAGHEAD:
CG_DrawBlueFlagHead(&rect);
break;
case CG_BLUE_FLAGSTATUS:
CG_DrawBlueFlagStatus(&rect, shader);
break;
case CG_BLUE_FLAGNAME:
CG_DrawBlueFlagName(&rect, scale, color, textStyle);
break;
case CG_RED_FLAGHEAD:
CG_DrawRedFlagHead(&rect);
break;
case CG_RED_FLAGSTATUS:
CG_DrawRedFlagStatus(&rect, shader);
break;
case CG_RED_FLAGNAME:
CG_DrawRedFlagName(&rect, scale, color, textStyle);
break;
case CG_HARVESTER_SKULLS:
CG_HarvesterSkulls(&rect, scale, color, qfalse, textStyle);
break;
case CG_HARVESTER_SKULLS2D:
CG_HarvesterSkulls(&rect, scale, color, qtrue, textStyle);
break;
case CG_ONEFLAG_STATUS:
CG_OneFlagStatus(&rect);
break;
case CG_PLAYER_LOCATION:
CG_DrawPlayerLocation(&rect, scale, color, textStyle);
break;
case CG_TEAM_COLOR:
CG_DrawTeamColor(&rect, color);
break;
case CG_CTF_POWERUP:
CG_DrawCTFPowerUp(&rect);
break;
case CG_AREA_POWERUP:
CG_DrawAreaPowerUp(&rect, align, special, scale, color);
break;
case CG_PLAYER_STATUS:
CG_DrawPlayerStatus(&rect);
break;
case CG_PLAYER_HASFLAG:
CG_DrawPlayerHasFlag(&rect, qfalse);
break;
case CG_PLAYER_HASFLAG2D:
CG_DrawPlayerHasFlag(&rect, qtrue);
break;
case CG_AREA_SYSTEMCHAT:
CG_DrawAreaSystemChat(&rect, scale, color, shader);
break;
case CG_AREA_TEAMCHAT:
CG_DrawAreaTeamChat(&rect, scale, color, shader);
break;
case CG_AREA_CHAT:
CG_DrawAreaChat(&rect, scale, color, shader);
break;
case CG_GAME_TYPE:
CG_DrawGameType(&rect, scale, color, shader, textStyle);
break;
case CG_GAME_STATUS:
CG_DrawGameStatus(&rect, scale, color, shader, textStyle);
break;
case CG_KILLER:
CG_DrawKiller(&rect, scale, color, shader, textStyle);
break;
case CG_ACCURACY:
case CG_ASSISTS:
case CG_DEFEND:
case CG_EXCELLENT:
case CG_IMPRESSIVE:
case CG_PERFECT:
case CG_GAUNTLET:
case CG_CAPTURES:
CG_DrawMedal(ownerDraw, &rect, scale, color, shader);
break;
case CG_SPECTATORS:
CG_DrawTeamSpectators(&rect, scale, color, shader);
break;
case CG_TEAMINFO:
if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
CG_DrawNewTeamInfo(&rect, text_x, text_y, scale, color, shader);
}
break;
case CG_CAPFRAGLIMIT:
CG_DrawCapFragLimit(&rect, scale, color, shader, textStyle);
break;
case CG_1STPLACE:
CG_Draw1stPlace(&rect, scale, color, shader, textStyle);
break;
case CG_2NDPLACE:
CG_Draw2ndPlace(&rect, scale, color, shader, textStyle);
break;
default:
break;
}
}
void CG_MouseEvent(int x, int y) {
int n;
if ( (cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR) && cg.showScores == qfalse) {
trap_Key_SetCatcher(0);
return;
}
cgs.cursorX+= x;
if (cgs.cursorX < 0)
cgs.cursorX = 0;
else if (cgs.cursorX > 640)
cgs.cursorX = 640;
cgs.cursorY += y;
if (cgs.cursorY < 0)
cgs.cursorY = 0;
else if (cgs.cursorY > 480)
cgs.cursorY = 480;
n = Display_CursorType(cgs.cursorX, cgs.cursorY);
cgs.activeCursor = 0;
if (n == CURSOR_ARROW) {
cgs.activeCursor = cgs.media.selectCursor;
} else if (n == CURSOR_SIZER) {
cgs.activeCursor = cgs.media.sizeCursor;
}
if (cgs.capturedItem) {
Display_MouseMove(cgs.capturedItem, x, y);
} else {
Display_MouseMove(NULL, cgs.cursorX, cgs.cursorY);
}
}
/*
==================
CG_HideTeamMenus
==================
*/
void CG_HideTeamMenu( void ) {
2011-02-18 14:31:32 +00:00
Menus_CloseByName("teamMenu");
Menus_CloseByName("getMenu");
}
/*
==================
CG_ShowTeamMenus
==================
*/
void CG_ShowTeamMenu( void ) {
2011-02-18 14:31:32 +00:00
Menus_OpenByName("teamMenu");
}
/*
==================
CG_EventHandling
==================
type 0 - no event handling
1 - team menu
2 - hud editor
*/
void CG_EventHandling(int type) {
cgs.eventHandling = type;
if (type == CGAME_EVENT_NONE) {
CG_HideTeamMenu();
} else if (type == CGAME_EVENT_TEAMMENU) {
//CG_ShowTeamMenu();
} else if (type == CGAME_EVENT_SCOREBOARD) {
}
}
void CG_KeyEvent(int key, qboolean down) {
if (!down) {
return;
}
if ( cg.predictedPlayerState.pm_type == PM_NORMAL || (cg.predictedPlayerState.pm_type == PM_SPECTATOR && cg.showScores == qfalse)) {
CG_EventHandling(CGAME_EVENT_NONE);
trap_Key_SetCatcher(0);
return;
}
//if (key == trap_Key_GetKey("teamMenu") || !Display_CaptureItem(cgs.cursorX, cgs.cursorY)) {
// if we see this then we should always be visible
// CG_EventHandling(CGAME_EVENT_NONE);
// trap_Key_SetCatcher(0);
//}
Display_HandleKey(key, down, cgs.cursorX, cgs.cursorY);
if (cgs.capturedItem) {
cgs.capturedItem = NULL;
} else {
if (key == K_MOUSE2 && down) {
cgs.capturedItem = Display_CaptureItem(cgs.cursorX, cgs.cursorY);
}
}
}
int CG_ClientNumFromName(const char *p) {
int i;
for (i = 0; i < cgs.maxclients; i++) {
if (cgs.clientinfo[i].infoValid && Q_stricmp(cgs.clientinfo[i].name, p) == 0) {
return i;
}
}
return -1;
}
void CG_ShowResponseHead(void) {
ioquake3 resync to revision 3511 from 3444. This updates from SDL 2.0.4 to SDL 2.0.8. Fix nullptr dereference in front of nullptr check in FS_CheckPak0 Fix undefined behaviour due to shifting signed in snd_mem.c Fix shifting bits out of byte in tr_font.c Fix shift into sign in cl_cin.c Fix signed bit operations in MSG_ReadBits Add missing address operator in cm_polylib.c OpenGL1: Decay float[8] to float * in tr_marks.c Avoid srcList[-1] in snd_openal.c Fix the behaviour of CVAR_LATCH|CVAR_CHEAT cvars Maximize cURL buffer size Fix mouse grab after toggling fullscreen Fix q3history buffer not cleared between mods and OOB-access Revert "Removed "Color Depth" from q3_ui system settings, it didn't control anything." Fix displayed color/depth/stencil bits values Restore setting r_colorbits in q3_ui Make setting r_stencilbits more consistent in Team Arena UI Fix map list in Team Arena start server menu after entering SP menu Support SDL audio devices that require float32 samples. sdl_snd.c should just initialize SDL audio without checking SDL_WasInit(). There's no need to SDL_PauseAudio(1) before calling SDL_CloseAudio(). Added audio capture support to SDL backend. Use the SDL2 audio device interface instead of the legacy 1.2 API. Disable SDL audio capture until prebuilt SDL libraries are updated to 2.0.8. Update SDL2 to 2.0.8 Add SDL 2.0.1 headers for macOS PPC Make macOS Universal Bundle target 10.6 for x86 and x86_64 Fix possible bot goal state NULL pointer dereference Fix uninitialized bot_goal_t fields Remove unnecessary NULL pointer check in Cmd_RemoveCommand Make UI_DrawProportionalString handle NULL string Fix compiling against macOS system OpenAL and SDL2 frameworks Fix array index in CanDamage() function - discovered by MARTY Fix compiling Makefile (broke in macOS frameworks commit) Fix clearing keys for control in Team Arena UI Make s_useOpenAL be CVAR_LATCH Improvements for dedicated camera followers (team follow1/2) Fix not closing description.txt and fix path seperator Fix duplicate bots displayed in Team Arena ingame add bot menu OpenGL2: Fix parsing specularScale in shaders Don't allow SDL audio capture using pulseaudio Isolate the Altivec code so non-Altivec PPC targets can use the same binary. Limit -maltivec to specific source files on OpenBSD too (untested) Use SDL 2.0.1 headers for macOS ppc64 Fix console offset while Team Arena voiceMenu is open OpenGL2: Readd r_deluxeSpecular. Fix client kicked as unpure when missing the latest cgame/ui pk3s Don't create multiple windows when GL context creation fails Require OpenGL 1.2 for GL_CLAMP_TO_EDGE Fix Linux uninstaller requiring Bash Fix Linux uninstaller redirecting stderr to stdout in preuninstall.sh Reported by @illwieckz. Fix in_restart causing fatal error while video is shutdown Allow pkg-config binary to be overridden with PKG_CONFIG Make testgun command without argument disable test gun model Remove unused renderer_buffer variable Don't upload 8 bit grayscale images as 16 bit luminance OpenGL1: Use RE_UploadCinematic() instead of duplicate code Don't load non-core GL functions for OpenGL 3.2 core context Load OpenGL ES 2.0 function procs Don't check fixed function GL extensions when using shader pipeline OpenGL2: Fix world VAO cache drawing when glIndex_t is unsigned short OpenGL2: Misc fixes and cleanup Fix IQM root joint backlerp when joint number is more than 0 Improve IQM loading Improve IQM CPU vertex skinning performance OpenGL2: Add GPU vertex skinning for IQM models
2018-07-30 11:35:12 +00:00
float x, y, w, h;
x = 72;
y = w = h = 0;
CG_AdjustFrom640( &x, &y, &w, &h );
Menus_OpenByName("voiceMenu");
trap_Cvar_Set("cl_conXOffset", va("%d", (int)x));
2011-02-18 14:31:32 +00:00
cg.voiceTime = cg.time;
}
void CG_RunMenuScript(char **args) {
}
void CG_GetTeamColor(vec4_t *color) {
if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
(*color)[0] = 1.0f;
(*color)[3] = 0.25f;
(*color)[1] = (*color)[2] = 0.0f;
2011-02-18 14:31:32 +00:00
} else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
(*color)[0] = (*color)[1] = 0.0f;
(*color)[2] = 1.0f;
(*color)[3] = 0.25f;
2011-02-18 14:31:32 +00:00
} else {
(*color)[0] = (*color)[2] = 0.0f;
(*color)[1] = 0.17f;
(*color)[3] = 0.25f;
2011-02-18 14:31:32 +00:00
}
}