summaryrefslogtreecommitdiff
path: root/src/cgame/cg_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame/cg_draw.c')
-rw-r--r--src/cgame/cg_draw.c2941
1 files changed, 1618 insertions, 1323 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 1a3ecae..38c9578 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -1,13 +1,14 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
-Copyright (C) 2000-2006 Tim Angus
+Copyright (C) 2000-2013 Darklegion Development
+Copyright (C) 2015-2019 GrangerHub
This file is part of Tremulous.
Tremulous 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,
+published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
Tremulous is distributed in the hope that it will be
@@ -16,284 +17,84 @@ 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 Tremulous; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+along with Tremulous; if not, see <https://www.gnu.org/licenses/>
+
===========================================================================
*/
// cg_draw.c -- draw all of the graphical elements during
// active (after loading) gameplay
-
#include "cg_local.h"
-#include "../ui/ui_shared.h"
+#include "ui/ui_shared.h"
-// used for scoreboard
-extern displayContextDef_t cgDC;
menuDef_t *menuScoreboard = NULL;
-int drawTeamOverlayModificationCount = -1;
-
-int sortedTeamPlayers[ TEAM_MAXOVERLAY ];
-int numSortedTeamPlayers;
-
-//TA UI
-int CG_Text_Width( const char *text, float scale, int limit )
+static void CG_AlignText( rectDef_t *rect, const char *text, float scale,
+ float w, float h,
+ int align, int valign,
+ float *x, float *y )
{
- int count,len;
- float out;
- glyphInfo_t *glyph;
- float useScale;
-// FIXME: see ui_main.c, same problem
-// const unsigned char *s = text;
- const char *s = text;
- fontInfo_t *font = &cgDC.Assets.textFont;
+ float tx, ty;
- if( scale <= cg_smallFont.value )
- font = &cgDC.Assets.smallFont;
- else if( scale > cg_bigFont.value )
- font = &cgDC.Assets.bigFont;
-
- useScale = scale * font->glyphScale;
- out = 0;
-
- if( text )
+ if( scale > 0.0f )
{
- len = strlen( text );
- if( limit > 0 && len > limit )
- len = limit;
-
- count = 0;
- while( s && *s && count < len )
- {
- if( Q_IsColorString( s ) )
- {
- s += 2;
- continue;
- }
- else
- {
- glyph = &font->glyphs[ (int)*s ];
- //TTimo: FIXME: getting nasty warnings without the cast,
- //hopefully this doesn't break the VM build
- out += glyph->xSkip;
- s++;
- count++;
- }
- }
+ w = UI_Text_Width( text, scale );
+ h = UI_Text_Height( text, scale );
}
- return out * useScale;
-}
-
-int CG_Text_Height( const char *text, float scale, int limit )
-{
- int len, count;
- float max;
- glyphInfo_t *glyph;
- float useScale;
-// TTimo: FIXME
-// const unsigned char *s = text;
- const char *s = text;
- 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;
- max = 0;
-
- if( text )
+ switch( align )
{
- len = strlen( text );
- if( limit > 0 && len > limit )
- len = limit;
-
- count = 0;
- while( s && *s && count < len )
- {
- if( Q_IsColorString( s ) )
- {
- s += 2;
- continue;
- }
- else
- {
- glyph = &font->glyphs[ (int)*s ];
- //TTimo: FIXME: getting nasty warnings without the cast,
- //hopefully this doesn't break the VM build
- if( max < glyph->height )
- max = glyph->height;
-
- s++;
- count++;
- }
- }
- }
-
- return max * useScale;
-}
+ default:
+ case ALIGN_LEFT:
+ tx = 0.0f;
+ break;
-void CG_Text_PaintChar( float x, float y, float width, float height, float scale,
- float s, float t, float s2, float t2, qhandle_t hShader )
-{
- float w, h;
- w = width * scale;
- h = height * scale;
- CG_AdjustFrom640( &x, &y, &w, &h );
- trap_R_DrawStretchPic( x, y, w, h, s, t, s2, t2, hShader );
-}
+ case ALIGN_RIGHT:
+ tx = rect->w - w;
+ break;
-void CG_Text_Paint( float x, float y, float scale, vec4_t color, const char *text,
- float adjust, int limit, int style )
-{
- int len, count;
- vec4_t newColor;
- glyphInfo_t *glyph;
- float useScale;
- fontInfo_t *font = &cgDC.Assets.textFont;
+ case ALIGN_CENTER:
+ tx = ( rect->w - w ) / 2.0f;
+ break;
- if( scale <= cg_smallFont.value )
- font = &cgDC.Assets.smallFont;
- else if( scale > cg_bigFont.value )
- font = &cgDC.Assets.bigFont;
+ case ALIGN_NONE:
+ tx = 0;
+ break;
+ }
- useScale = scale * font->glyphScale;
- if( text )
+ switch( valign )
{
-// TTimo: FIXME
-// const unsigned char *s = text;
- const char *s = text;
-
- trap_R_SetColor( color );
- memcpy( &newColor[ 0 ], &color[ 0 ], sizeof( vec4_t ) );
- len = strlen( text );
-
- if( limit > 0 && len > limit )
- len = limit;
-
- count = 0;
- while( s && *s && count < len )
- {
- glyph = &font->glyphs[ (int)*s ];
- //TTimo: FIXME: getting nasty warnings without the cast,
- //hopefully this doesn't break the VM build
+ default:
+ case VALIGN_BOTTOM:
+ ty = rect->h;
+ break;
- 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( style == ITEM_TEXTSTYLE_SHADOWED ||
- style == ITEM_TEXTSTYLE_SHADOWEDMORE )
- {
- int ofs = style == ITEM_TEXTSTYLE_SHADOWED ? 1 : 2;
- colorBlack[ 3 ] = newColor[ 3 ];
- trap_R_SetColor( colorBlack );
- CG_Text_PaintChar( x + ofs, y - yadj + ofs,
- glyph->imageWidth,
- glyph->imageHeight,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- colorBlack[ 3 ] = 1.0;
- trap_R_SetColor( newColor );
- }
- else if( style == ITEM_TEXTSTYLE_NEON )
- {
- vec4_t glow, outer, inner, white;
-
- glow[ 0 ] = newColor[ 0 ] * 0.5;
- glow[ 1 ] = newColor[ 1 ] * 0.5;
- glow[ 2 ] = newColor[ 2 ] * 0.5;
- glow[ 3 ] = newColor[ 3 ] * 0.2;
-
- outer[ 0 ] = newColor[ 0 ];
- outer[ 1 ] = newColor[ 1 ];
- outer[ 2 ] = newColor[ 2 ];
- outer[ 3 ] = newColor[ 3 ];
-
- inner[ 0 ] = newColor[ 0 ] * 1.5 > 1.0f ? 1.0f : newColor[ 0 ] * 1.5;
- inner[ 1 ] = newColor[ 1 ] * 1.5 > 1.0f ? 1.0f : newColor[ 1 ] * 1.5;
- inner[ 2 ] = newColor[ 2 ] * 1.5 > 1.0f ? 1.0f : newColor[ 2 ] * 1.5;
- inner[ 3 ] = newColor[ 3 ];
-
- white[ 0 ] = white[ 1 ] = white[ 2 ] = white[ 3 ] = 1.0f;
-
- trap_R_SetColor( glow );
- CG_Text_PaintChar( x - 3, y - yadj - 3,
- glyph->imageWidth + 6,
- glyph->imageHeight + 6,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( outer );
- CG_Text_PaintChar( x - 1, y - yadj - 1,
- glyph->imageWidth + 2,
- glyph->imageHeight + 2,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( inner );
- CG_Text_PaintChar( x - 0.5, y - yadj - 0.5,
- glyph->imageWidth + 1,
- glyph->imageHeight + 1,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
-
- trap_R_SetColor( white );
- }
+ case VALIGN_TOP:
+ ty = h;
+ break;
+ case VALIGN_CENTER:
+ ty = h + ( ( rect->h - h ) / 2.0f );
+ break;
- CG_Text_PaintChar( x, y - yadj,
- glyph->imageWidth,
- glyph->imageHeight,
- useScale,
- glyph->s,
- glyph->t,
- glyph->s2,
- glyph->t2,
- glyph->glyph );
+ case VALIGN_NONE:
+ ty = 0;
+ break;
+ }
- x += ( glyph->xSkip * useScale ) + adjust;
- s++;
- count++;
- }
- }
+ if( x )
+ *x = rect->x + tx;
- trap_R_SetColor( NULL );
- }
+ if( y )
+ *y = rect->y + ty;
}
/*
==============
CG_DrawFieldPadded
-Draws large numbers for status bar and powerups
+Draws large numbers for status bar
==============
*/
static void CG_DrawFieldPadded( int x, int y, int width, int cw, int ch, int value )
@@ -307,7 +108,7 @@ static void CG_DrawFieldPadded( int x, int y, int width, int cw, int ch, int val
charWidth = CHAR_WIDTH;
if( !( charHeight = ch ) )
- charWidth = CHAR_HEIGHT;
+ charHeight = CHAR_HEIGHT;
if( width < 1 )
return;
@@ -344,7 +145,7 @@ static void CG_DrawFieldPadded( int x, int y, int width, int cw, int ch, int val
orgL = l;
- x += 2;
+ x += ( 2.0f * cgDC.aspectScale );
ptr = num;
while( *ptr && l )
@@ -373,7 +174,7 @@ static void CG_DrawFieldPadded( int x, int y, int width, int cw, int ch, int val
==============
CG_DrawField
-Draws large numbers for status bar and powerups
+Draws large numbers for status bar
==============
*/
void CG_DrawField( float x, float y, int width, float cw, float ch, int value )
@@ -387,7 +188,7 @@ void CG_DrawField( float x, float y, int width, float cw, float ch, int value )
charWidth = CHAR_WIDTH;
if( !( charHeight = ch ) )
- charWidth = CHAR_HEIGHT;
+ charHeight = CHAR_HEIGHT;
if( width < 1 )
return;
@@ -422,7 +223,7 @@ void CG_DrawField( float x, float y, int width, float cw, float ch, int value )
if( l > width )
l = width;
- x += 2 + charWidth * ( width - l );
+ x += ( 2.0f * cgDC.aspectScale ) + charWidth * ( width - l );
ptr = num;
while( *ptr && l )
@@ -440,18 +241,22 @@ void CG_DrawField( float x, float y, int width, float cw, float ch, int value )
}
static void CG_DrawProgressBar( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special, float progress )
+ int align, int textalign, int textStyle,
+ float borderSize, float progress )
{
- float rimWidth = rect->h / 20.0f;
+ float rimWidth;
float doneWidth, leftWidth;
- float tx, ty, tw, th;
+ float tx, ty;
char textBuffer[ 8 ];
- if( rimWidth < 0.6f )
- rimWidth = 0.6f;
-
- if( special >= 0.0f )
- rimWidth = special;
+ if( borderSize >= 0.0f )
+ rimWidth = borderSize;
+ else
+ {
+ rimWidth = rect->h / 20.0f;
+ if( rimWidth < 0.6f )
+ rimWidth = 0.6f;
+ }
if( progress < 0.0f )
progress = 0.0f;
@@ -464,7 +269,7 @@ static void CG_DrawProgressBar( rectDef_t *rect, vec4_t color, float scale,
trap_R_SetColor( color );
//draw rim and bar
- if( align == ITEM_ALIGN_RIGHT )
+ if( align == ALIGN_RIGHT )
{
CG_DrawPic( rect->x, rect->y, rimWidth, rect->h, cgs.media.whiteShader );
CG_DrawPic( rect->x + rimWidth, rect->y,
@@ -490,31 +295,9 @@ static void CG_DrawProgressBar( rectDef_t *rect, vec4_t color, float scale,
if( scale > 0.0 )
{
Com_sprintf( textBuffer, sizeof( textBuffer ), "%d%%", (int)( progress * 100 ) );
- tw = CG_Text_Width( textBuffer, scale, 0 );
- th = scale * 40.0f;
-
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x + ( rect->w / 10.0f );
- ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f );
- break;
-
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - ( rect->w / 10.0f ) - tw;
- ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f );
- break;
-
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f );
- ty = rect->y + ( rect->h / 2.0f ) + ( th / 2.0f );
- break;
+ CG_AlignText( rect, textBuffer, scale, 0.0f, 0.0f, textalign, VALIGN_CENTER, &tx, &ty );
- default:
- tx = ty = 0.0f;
- }
-
- CG_Text_Paint( tx, ty, scale, color, textBuffer, 0, 0, textStyle );
+ UI_Text_Paint( tx, ty, scale, color, textBuffer, 0, 0, textStyle );
}
}
@@ -539,14 +322,17 @@ static void CG_DrawPlayerCreditsValue( rectDef_t *rect, vec4_t color, qboolean p
value = ps->persistant[ PERS_CREDIT ];
if( value > -1 )
{
- if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS &&
- !CG_AtHighestClass( ) )
+ if( cg.predictedPlayerState.stats[ STAT_TEAM ] == TEAM_ALIENS )
{
- if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME )
+ if( !BG_AlienCanEvolve( cg.predictedPlayerState.stats[ STAT_CLASS ],
+ value, cgs.alienStage ) &&
+ cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME &&
+ ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) & 1 )
{
- if( ( ( cg.time - cg.lastEvolveAttempt ) / 300 ) % 2 )
- color[ 3 ] = 0.0f;
+ color[ 3 ] = 0.0f;
}
+
+ value /= ALIEN_CREDITS_PER_KILL;
}
trap_R_SetColor( color );
@@ -560,135 +346,66 @@ static void CG_DrawPlayerCreditsValue( rectDef_t *rect, vec4_t color, qboolean p
}
}
-static void CG_DrawPlayerBankValue( rectDef_t *rect, vec4_t color, qboolean padding )
+static void CG_DrawPlayerCreditsFraction( rectDef_t *rect, vec4_t color, qhandle_t shader )
{
- int value;
- playerState_t *ps;
-
- ps = &cg.snap->ps;
-
- value = ps->persistant[ PERS_BANK ];
- if( value > -1 )
- {
- trap_R_SetColor( color );
-
- if( padding )
- CG_DrawFieldPadded( rect->x, rect->y, 4, rect->w / 4, rect->h, value );
- else
- CG_DrawField( rect->x, rect->y, 1, rect->w, rect->h, value );
-
- trap_R_SetColor( NULL );
- }
-}
-
-#define HH_MIN_ALPHA 0.2f
-#define HH_MAX_ALPHA 0.8f
-#define HH_ALPHA_DIFF (HH_MAX_ALPHA-HH_MIN_ALPHA)
+ float fraction;
+ float height;
-#define AH_MIN_ALPHA 0.2f
-#define AH_MAX_ALPHA 0.8f
-#define AH_ALPHA_DIFF (AH_MAX_ALPHA-AH_MIN_ALPHA)
-
-/*
-==============
-CG_DrawPlayerStamina1
-==============
-*/
-static void CG_DrawPlayerStamina1( rectDef_t *rect, vec4_t color, qhandle_t shader )
-{
- playerState_t *ps = &cg.snap->ps;
- float stamina = ps->stats[ STAT_STAMINA ];
- float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f;
- float progress;
+ if( cg.predictedPlayerState.stats[ STAT_TEAM ] != TEAM_ALIENS )
+ return;
- stamina -= ( 2 * (int)maxStaminaBy3 );
- progress = stamina / maxStaminaBy3;
+ fraction = ((float)(cg.predictedPlayerState.persistant[ PERS_CREDIT ] %
+ ALIEN_CREDITS_PER_KILL)) / ALIEN_CREDITS_PER_KILL;
- if( progress > 1.0f )
- progress = 1.0f;
- else if( progress < 0.0f )
- progress = 0.0f;
-
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
+ CG_AdjustFrom640( &rect->x, &rect->y, &rect->w, &rect->h );
+ height = rect->h * fraction;
trap_R_SetColor( color );
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ trap_R_DrawStretchPic( rect->x, rect->y - height + rect->h, rect->w,
+ height, 0.0f, 1.0f - fraction, 1.0f, 1.0f, shader );
trap_R_SetColor( NULL );
}
-/*
-==============
-CG_DrawPlayerStamina2
-==============
-*/
-static void CG_DrawPlayerStamina2( rectDef_t *rect, vec4_t color, qhandle_t shader )
-{
- playerState_t *ps = &cg.snap->ps;
- float stamina = ps->stats[ STAT_STAMINA ];
- float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f;
- float progress;
-
- stamina -= (int)maxStaminaBy3;
- progress = stamina / maxStaminaBy3;
-
- if( progress > 1.0f )
- progress = 1.0f;
- else if( progress < 0.0f )
- progress = 0.0f;
-
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
-
- trap_R_SetColor( color );
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
- trap_R_SetColor( NULL );
-}
/*
==============
-CG_DrawPlayerStamina3
+CG_DrawPlayerStamina
==============
*/
-static void CG_DrawPlayerStamina3( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerStamina( int ownerDraw, rectDef_t *rect,
+ vec4_t backColor, vec4_t foreColor,
+ qhandle_t shader )
{
playerState_t *ps = &cg.snap->ps;
float stamina = ps->stats[ STAT_STAMINA ];
- float maxStaminaBy3 = (float)MAX_STAMINA / 3.0f;
+ float maxStaminaBy3 = (float)STAMINA_MAX / 3.0f;
float progress;
+ vec4_t color;
+ switch( ownerDraw )
+ {
+ case CG_PLAYER_STAMINA_1:
+ progress = ( stamina - 2 * (int)maxStaminaBy3 ) / maxStaminaBy3;
+ break;
+ case CG_PLAYER_STAMINA_2:
+ progress = ( stamina - (int)maxStaminaBy3 ) / maxStaminaBy3;
+ break;
+ case CG_PLAYER_STAMINA_3:
progress = stamina / maxStaminaBy3;
+ break;
+ case CG_PLAYER_STAMINA_4:
+ progress = ( stamina + STAMINA_MAX ) / STAMINA_MAX;
+ break;
+ default:
+ return;
+ }
if( progress > 1.0f )
progress = 1.0f;
else if( progress < 0.0f )
progress = 0.0f;
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
-
- trap_R_SetColor( color );
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
- trap_R_SetColor( NULL );
-}
-
-/*
-==============
-CG_DrawPlayerStamina4
-==============
-*/
-static void CG_DrawPlayerStamina4( rectDef_t *rect, vec4_t color, qhandle_t shader )
-{
- playerState_t *ps = &cg.snap->ps;
- float stamina = ps->stats[ STAT_STAMINA ];
- float progress;
-
- stamina += (float)MAX_STAMINA;
- progress = stamina / (float)MAX_STAMINA;
-
- if( progress > 1.0f )
- progress = 1.0f;
- else if( progress < 0.0f )
- progress = 0.0f;
-
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
+ Vector4Lerp( progress, backColor, foreColor, color );
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
@@ -700,15 +417,28 @@ static void CG_DrawPlayerStamina4( rectDef_t *rect, vec4_t color, qhandle_t shad
CG_DrawPlayerStaminaBolt
==============
*/
-static void CG_DrawPlayerStaminaBolt( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerStaminaBolt( rectDef_t *rect, vec4_t backColor,
+ vec4_t foreColor, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- float stamina = ps->stats[ STAT_STAMINA ];
+ float stamina = cg.snap->ps.stats[ STAT_STAMINA ];
+ vec4_t color;
- if( stamina < 0 )
- color[ 3 ] = HH_MIN_ALPHA;
+ if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_SPEEDBOOST )
+ {
+ if( stamina >= 0 )
+ Vector4Lerp( ( sin( cg.time / 150.0f ) + 1 ) / 2,
+ backColor, foreColor, color );
+ else
+ Vector4Lerp( ( sin( cg.time / 2000.0f ) + 1 ) / 2,
+ backColor, foreColor, color );
+ }
else
- color[ 3 ] = HH_MAX_ALPHA;
+ {
+ if( stamina < 0 )
+ Vector4Copy( backColor, color );
+ else
+ Vector4Copy( foreColor, color );
+ }
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
@@ -720,40 +450,42 @@ static void CG_DrawPlayerStaminaBolt( rectDef_t *rect, vec4_t color, qhandle_t s
CG_DrawPlayerClipsRing
==============
*/
-static void CG_DrawPlayerClipsRing( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerClipsRing( rectDef_t *rect, vec4_t backColor,
+ vec4_t foreColor, qhandle_t shader )
{
playerState_t *ps = &cg.snap->ps;
centity_t *cent;
float buildTime = ps->stats[ STAT_MISC ];
float progress;
float maxDelay;
+ weapon_t weapon;
+ vec4_t color;
cent = &cg_entities[ cg.snap->ps.clientNum ];
+ weapon = BG_GetPlayerWeapon( ps );
- switch( cent->currentState.weapon )
+ switch( weapon )
{
case WP_ABUILD:
case WP_ABUILD2:
case WP_HBUILD:
- case WP_HBUILD2:
- maxDelay = (float)BG_FindBuildDelayForWeapon( cent->currentState.weapon );
-
- if( buildTime > maxDelay )
- buildTime = maxDelay;
+ if( buildTime > MAXIMUM_BUILD_TIME )
+ buildTime = MAXIMUM_BUILD_TIME;
+ progress = ( MAXIMUM_BUILD_TIME - buildTime ) / MAXIMUM_BUILD_TIME;
- progress = ( maxDelay - buildTime ) / maxDelay;
-
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
+ Vector4Lerp( progress, backColor, foreColor, color );
break;
default:
if( ps->weaponstate == WEAPON_RELOADING )
{
- maxDelay = (float)BG_FindReloadTimeForWeapon( cent->currentState.weapon );
+ maxDelay = (float)BG_Weapon( cent->currentState.weapon )->reloadTime;
progress = ( maxDelay - (float)ps->weaponTime ) / maxDelay;
- color[ 3 ] = HH_MIN_ALPHA + ( progress * HH_ALPHA_DIFF );
+ Vector4Lerp( progress, backColor, foreColor, color );
}
+ else
+ Com_Memcpy( color, foreColor, sizeof( color ) );
break;
}
@@ -767,24 +499,20 @@ static void CG_DrawPlayerClipsRing( rectDef_t *rect, vec4_t color, qhandle_t sha
CG_DrawPlayerBuildTimerRing
==============
*/
-static void CG_DrawPlayerBuildTimerRing( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerBuildTimerRing( rectDef_t *rect, vec4_t backColor,
+ vec4_t foreColor, qhandle_t shader )
{
playerState_t *ps = &cg.snap->ps;
- centity_t *cent;
float buildTime = ps->stats[ STAT_MISC ];
float progress;
- float maxDelay;
-
- cent = &cg_entities[ cg.snap->ps.clientNum ];
+ vec4_t color;
- maxDelay = (float)BG_FindBuildDelayForWeapon( cent->currentState.weapon );
+ if( buildTime > MAXIMUM_BUILD_TIME )
+ buildTime = MAXIMUM_BUILD_TIME;
- if( buildTime > maxDelay )
- buildTime = maxDelay;
+ progress = ( MAXIMUM_BUILD_TIME - buildTime ) / MAXIMUM_BUILD_TIME;
- progress = ( maxDelay - buildTime ) / maxDelay;
-
- color[ 3 ] = AH_MIN_ALPHA + ( progress * AH_ALPHA_DIFF );
+ Vector4Lerp( progress, backColor, foreColor, color );
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
@@ -796,17 +524,14 @@ static void CG_DrawPlayerBuildTimerRing( rectDef_t *rect, vec4_t color, qhandle_
CG_DrawPlayerBoosted
==============
*/
-static void CG_DrawPlayerBoosted( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerBoosted( rectDef_t *rect, vec4_t backColor,
+ vec4_t foreColor, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- qboolean boosted = ps->stats[ STAT_STATE ] & SS_BOOSTED;
-
- if( boosted )
- color[ 3 ] = AH_MAX_ALPHA;
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_BOOSTED )
+ trap_R_SetColor( foreColor );
else
- color[ 3 ] = AH_MIN_ALPHA;
+ trap_R_SetColor( backColor );
- trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
}
@@ -816,26 +541,20 @@ static void CG_DrawPlayerBoosted( rectDef_t *rect, vec4_t color, qhandle_t shade
CG_DrawPlayerBoosterBolt
==============
*/
-static void CG_DrawPlayerBoosterBolt( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerBoosterBolt( rectDef_t *rect, vec4_t backColor,
+ vec4_t foreColor, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- qboolean boosted = ps->stats[ STAT_STATE ] & SS_BOOSTED;
- vec4_t localColor;
-
- Vector4Copy( color, localColor );
-
- if( boosted )
- {
- if( ps->stats[ STAT_BOOSTTIME ] > BOOST_TIME - 3000 )
- {
- qboolean flash = ( ps->stats[ STAT_BOOSTTIME ] / 500 ) % 2;
+ vec4_t color;
- if( flash )
- localColor[ 3 ] = 1.0f;
- }
- }
+ // Flash bolts when the boost is almost out
+ if( ( cg.snap->ps.stats[ STAT_STATE ] & SS_BOOSTED ) &&
+ ( cg.snap->ps.stats[ STAT_STATE ] & SS_BOOSTEDWARNING ) )
+ Vector4Lerp( ( sin( cg.time / 100.0f ) + 1 ) / 2,
+ backColor, foreColor, color );
+ else
+ Vector4Copy( foreColor, color );
- trap_R_SetColor( localColor );
+ trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
}
@@ -847,38 +566,49 @@ CG_DrawPlayerPoisonBarbs
*/
static void CG_DrawPlayerPoisonBarbs( rectDef_t *rect, vec4_t color, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- int x = rect->x;
- int y = rect->y;
- int width = rect->w;
- int height = rect->h;
- qboolean vertical;
- int iconsize, numBarbs, i;
+ qboolean vertical;
+ float x = rect->x, y = rect->y;
+ float width = rect->w, height = rect->h;
+ float diff;
+ int iconsize, numBarbs, maxBarbs;
- numBarbs = ps->ammo;
+ maxBarbs = BG_Weapon( cg.snap->ps.weapon )->maxAmmo;
+ numBarbs = cg.snap->ps.ammo;
+ if( maxBarbs <= 0 || numBarbs <= 0 )
+ return;
+
+ // adjust these first to ensure the aspect ratio of the barb image is
+ // preserved
+ CG_AdjustFrom640( &x, &y, &width, &height );
if( height > width )
{
vertical = qtrue;
iconsize = width;
+ if( maxBarbs != 1 ) // avoid division by zero
+ diff = ( height - iconsize ) / (float)( maxBarbs - 1 );
+ else
+ diff = 0; // doesn't matter, won't be used
}
- else if( height <= width )
+ else
{
vertical = qfalse;
iconsize = height;
+ if( maxBarbs != 1 )
+ diff = ( width - iconsize ) / (float)( maxBarbs - 1 );
+ else
+ diff = 0;
}
- if( color[ 3 ] != 0.0 )
- trap_R_SetColor( color );
+ trap_R_SetColor( color );
- for( i = 0; i < numBarbs; i ++ )
+ for( ; numBarbs > 0; numBarbs-- )
{
+ trap_R_DrawStretchPic( x, y, iconsize, iconsize, 0, 0, 1, 1, shader );
if( vertical )
- y += iconsize;
+ y += diff;
else
- x += iconsize;
-
- CG_DrawPic( x, y, iconsize, iconsize, shader );
+ x += diff;
}
trap_R_SetColor( NULL );
@@ -889,70 +619,83 @@ static void CG_DrawPlayerPoisonBarbs( rectDef_t *rect, vec4_t color, qhandle_t s
CG_DrawPlayerWallclimbing
==============
*/
-static void CG_DrawPlayerWallclimbing( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerWallclimbing( rectDef_t *rect, vec4_t backColor, vec4_t foreColor, qhandle_t shader )
{
- playerState_t *ps = &cg.snap->ps;
- qboolean ww = ps->stats[ STAT_STATE ] & SS_WALLCLIMBING;
-
- if( ww )
- color[ 3 ] = AH_MAX_ALPHA;
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING )
+ trap_R_SetColor( foreColor );
else
- color[ 3 ] = AH_MIN_ALPHA;
+ trap_R_SetColor( backColor );
- trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
}
-static void CG_DrawPlayerStamina( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
-{
- playerState_t *ps = &cg.snap->ps;
- int stamina = ps->stats[ STAT_STAMINA ];
- float progress = ( (float)stamina + (float)MAX_STAMINA ) / ( (float)MAX_STAMINA * 2.0f );
-
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, progress );
-}
-
static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color )
{
- int value;
- centity_t *cent;
- playerState_t *ps;
-
- cent = &cg_entities[ cg.snap->ps.clientNum ];
- ps = &cg.snap->ps;
+ int value;
+ int valueMarked = -1;
+ qboolean bp = qfalse;
- if( cent->currentState.weapon )
+ switch( cg.snap->ps.stats[ STAT_WEAPON ] )
{
- switch( cent->currentState.weapon )
- {
- case WP_ABUILD:
- case WP_ABUILD2:
- //percentage of BP remaining
- value = cgs.alienBuildPoints;
- break;
+ case WP_NONE:
+ case WP_BLASTER:
+ return;
- case WP_HBUILD:
- case WP_HBUILD2:
- //percentage of BP remaining
- value = cgs.humanBuildPoints;
- break;
+ case WP_ABUILD:
+ case WP_ABUILD2:
+ case WP_HBUILD:
+ value = cg.snap->ps.persistant[ PERS_BP ];
+ valueMarked = cg.snap->ps.persistant[ PERS_MARKEDBP ];
+ bp = qtrue;
+ break;
- default:
- value = ps->ammo;
- break;
- }
+ default:
+ value = cg.snap->ps.ammo;
+ break;
+ }
+
+ if( value > 999 )
+ value = 999;
+ if( valueMarked > 999 )
+ valueMarked = 999;
- if( value > 999 )
- value = 999;
+ if( value > -1 )
+ {
+ float tx, ty;
+ const char *text;
+ float scale;
+ int len;
- if( value > -1 )
+ trap_R_SetColor( color );
+ if( !bp )
{
- trap_R_SetColor( color );
- CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value );
+ CG_DrawField( rect->x - 5, rect->y, 4, rect->w / 4, rect->h, value );
trap_R_SetColor( NULL );
+ return;
}
+
+ if( valueMarked > 0 )
+ text = va( "%d+(%d)", value, valueMarked );
+ else
+ text = va( "%d", value );
+
+ len = strlen( text );
+
+ if( len <= 4 )
+ scale = 0.50;
+ else if( len <= 6 )
+ scale = 0.43;
+ else if( len == 7 )
+ scale = 0.36;
+ else if( len == 8 )
+ scale = 0.33;
+ else
+ scale = 0.31;
+
+ CG_AlignText( rect, text, scale, 0.0f, 0.0f, ALIGN_RIGHT, VALIGN_CENTER, &tx, &ty );
+ UI_Text_Paint( tx + 1, ty, scale, color, text, 0, 0, ITEM_TEXTSTYLE_NORMAL );
+ trap_R_SetColor( NULL );
}
}
@@ -964,7 +707,7 @@ CG_DrawAlienSense
*/
static void CG_DrawAlienSense( rectDef_t *rect )
{
- if( BG_ClassHasAbility( cg.snap->ps.stats[ STAT_PCLASS ], SCA_ALIENSENSE ) )
+ if( BG_ClassHasAbility( cg.snap->ps.stats[ STAT_CLASS ], SCA_ALIENSENSE ) )
CG_AlienSense( rect );
}
@@ -999,19 +742,25 @@ static void CG_DrawUsableBuildable( rectDef_t *rect, qhandle_t shader, vec4_t co
es = &cg_entities[ trace.entityNum ].currentState;
- if( es->eType == ET_BUILDABLE && BG_FindUsableForBuildable( es->modelindex ) &&
- cg.predictedPlayerState.stats[ STAT_PTEAM ] == BG_FindTeamForBuildable( es->modelindex ) )
+ if( es->eType == ET_BUILDABLE && BG_Buildable( es->modelindex )->usable &&
+ cg.predictedPlayerState.stats[ STAT_TEAM ] == BG_Buildable( es->modelindex )->team )
{
//hack to prevent showing the usable buildable when you aren't carrying an energy weapon
if( ( es->modelindex == BA_H_REACTOR || es->modelindex == BA_H_REPEATER ) &&
- ( !BG_FindUsesEnergyForWeapon( cg.snap->ps.weapon ) ||
- BG_FindInfinteAmmoForWeapon( cg.snap->ps.weapon ) ) )
+ ( !BG_Weapon( cg.snap->ps.weapon )->usesEnergy ||
+ BG_Weapon( cg.snap->ps.weapon )->infiniteAmmo ) )
+ {
+ cg.nearUsableBuildable = BA_NONE;
return;
+ }
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
+ cg.nearUsableBuildable = es->modelindex;
}
+ else
+ cg.nearUsableBuildable = BA_NONE;
}
@@ -1019,221 +768,381 @@ static void CG_DrawUsableBuildable( rectDef_t *rect, qhandle_t shader, vec4_t co
static void CG_DrawPlayerBuildTimer( rectDef_t *rect, vec4_t color )
{
- float progress;
int index;
- centity_t *cent;
playerState_t *ps;
- cent = &cg_entities[ cg.snap->ps.clientNum ];
ps = &cg.snap->ps;
- if( cent->currentState.weapon )
- {
- switch( cent->currentState.weapon )
- {
- case WP_ABUILD:
- progress = (float)ps->stats[ STAT_MISC ] / (float)ABUILDER_BASE_DELAY;
- break;
-
- case WP_ABUILD2:
- progress = (float)ps->stats[ STAT_MISC ] / (float)ABUILDER_ADV_DELAY;
- break;
-
- case WP_HBUILD:
- progress = (float)ps->stats[ STAT_MISC ] / (float)HBUILD_DELAY;
- break;
-
- case WP_HBUILD2:
- progress = (float)ps->stats[ STAT_MISC ] / (float)HBUILD2_DELAY;
- break;
+ if( ps->stats[ STAT_MISC ] <= 0 )
+ return;
- default:
- return;
- break;
- }
+ switch( ps->stats[ STAT_WEAPON ] )
+ {
+ case WP_ABUILD:
+ case WP_ABUILD2:
+ case WP_HBUILD:
+ break;
- if( !ps->stats[ STAT_MISC ] )
+ default:
return;
+ }
- index = (int)( progress * 8.0f );
-
- if( index > 7 )
- index = 7;
- else if( index < 0 )
- index = 0;
-
- if( cg.time - cg.lastBuildAttempt <= BUILD_DELAY_TIME )
- {
- if( ( ( cg.time - cg.lastBuildAttempt ) / 300 ) % 2 )
- {
- color[ 0 ] = 1.0f;
- color[ 1 ] = color[ 2 ] = 0.0f;
- color[ 3 ] = 1.0f;
- }
- }
+ index = 8 * ( ps->stats[ STAT_MISC ] - 1 ) / MAXIMUM_BUILD_TIME;
+ if( index > 7 )
+ index = 7;
+ else if( index < 0 )
+ index = 0;
- trap_R_SetColor( color );
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h,
- cgs.media.buildWeaponTimerPie[ index ] );
- trap_R_SetColor( NULL );
+ if( cg.time - cg.lastBuildAttempt <= BUILD_DELAY_TIME &&
+ ( ( cg.time - cg.lastBuildAttempt ) / 300 ) % 2 )
+ {
+ color[ 0 ] = 1.0f;
+ color[ 1 ] = color[ 2 ] = 0.0f;
+ color[ 3 ] = 1.0f;
}
+
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h,
+ cgs.media.buildWeaponTimerPie[ index ] );
+ trap_R_SetColor( NULL );
}
static void CG_DrawPlayerClipsValue( rectDef_t *rect, vec4_t color )
{
int value;
- centity_t *cent;
- playerState_t *ps;
-
- cent = &cg_entities[ cg.snap->ps.clientNum ];
- ps = &cg.snap->ps;
+ playerState_t *ps = &cg.snap->ps;
- if( cent->currentState.weapon )
+ switch( ps->stats[ STAT_WEAPON ] )
{
- switch( cent->currentState.weapon )
- {
- case WP_ABUILD:
- case WP_ABUILD2:
- case WP_HBUILD:
- case WP_HBUILD2:
- break;
+ case WP_NONE:
+ case WP_BLASTER:
+ case WP_ABUILD:
+ case WP_ABUILD2:
+ case WP_HBUILD:
+ return;
- default:
- value = ps->clips;
+ default:
+ value = ps->clips;
- if( value > -1 )
- {
- trap_R_SetColor( color );
- CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value );
- trap_R_SetColor( NULL );
- }
- break;
- }
+ if( value > -1 )
+ {
+ trap_R_SetColor( color );
+ CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value );
+ trap_R_SetColor( NULL );
+ }
+ break;
}
}
static void CG_DrawPlayerHealthValue( rectDef_t *rect, vec4_t color )
{
- playerState_t *ps;
- int value;
-
- ps = &cg.snap->ps;
-
- value = ps->stats[ STAT_HEALTH ];
-
trap_R_SetColor( color );
- CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h, value );
+ CG_DrawField( rect->x, rect->y, 4, rect->w / 4, rect->h,
+ cg.snap->ps.stats[ STAT_HEALTH ] );
trap_R_SetColor( NULL );
}
-static void CG_DrawPlayerHealthBar( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
-{
- playerState_t *ps;
- float total;
-
- ps = &cg.snap->ps;
-
- total = ( (float)ps->stats[ STAT_HEALTH ] / (float)ps->stats[ STAT_MAX_HEALTH ] );
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, total );
-}
-
/*
==============
CG_DrawPlayerHealthCross
==============
*/
-static void CG_DrawPlayerHealthCross( rectDef_t *rect, vec4_t color, qhandle_t shader )
+static void CG_DrawPlayerHealthCross( rectDef_t *rect, vec4_t ref_color )
{
- playerState_t *ps = &cg.snap->ps;
- int health = ps->stats[ STAT_HEALTH ];
+ qhandle_t shader;
+ vec4_t color;
+ float ref_alpha;
+
+ // Pick the current icon
+ shader = cgs.media.healthCross;
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_3X )
+ shader = cgs.media.healthCross3X;
+ else if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_2X )
+ {
+ if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
+ shader = cgs.media.healthCross2X;
+ else
+ shader = cgs.media.healthCrossMedkit;
+ }
+ else if( cg.snap->ps.stats[ STAT_STATE ] & SS_POISONED )
+ shader = cgs.media.healthCrossPoisoned;
- if( health < 10 )
+ // Pick the alpha value
+ Vector4Copy( ref_color, color );
+ if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS &&
+ cg.snap->ps.stats[ STAT_HEALTH ] < 10 )
{
color[ 0 ] = 1.0f;
color[ 1 ] = color[ 2 ] = 0.0f;
}
+ ref_alpha = ref_color[ 3 ];
+ if( cg.snap->ps.stats[ STAT_STATE ] & SS_HEALING_ACTIVE )
+ ref_alpha = 1.0f;
+
+ // Don't fade from nothing
+ if( !cg.lastHealthCross )
+ cg.lastHealthCross = shader;
+
+ // Fade the icon during transition
+ if( cg.lastHealthCross != shader )
+ {
+ cg.healthCrossFade += cg.frametime / 500.0f;
+ if( cg.healthCrossFade > 1.0f )
+ {
+ cg.healthCrossFade = 0.0f;
+ cg.lastHealthCross = shader;
+ }
+ else
+ {
+ // Fading between two icons
+ color[ 3 ] = ref_alpha * cg.healthCrossFade;
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ color[ 3 ] = ref_alpha * ( 1.0f - cg.healthCrossFade );
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg.lastHealthCross );
+ trap_R_SetColor( NULL );
+ return;
+ }
+ }
+ // Not fading, draw a single icon
+ color[ 3 ] = ref_alpha;
trap_R_SetColor( color );
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
trap_R_SetColor( NULL );
}
-static void CG_DrawProgressLabel( rectDef_t *rect, float text_x, float text_y, vec4_t color,
- float scale, int align, const char *s, float fraction )
+static float CG_ChargeProgress( void )
{
- vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f };
- float tx, tw = CG_Text_Width( s, scale, 0 );
+ float progress;
+ int min = 0, max = 0;
- switch( align )
+ if( cg.snap->ps.weapon == WP_ALEVEL3 )
{
- case ITEM_ALIGN_LEFT:
- tx = 0.0f;
- break;
+ min = LEVEL3_POUNCE_TIME_MIN;
+ max = LEVEL3_POUNCE_TIME;
+ }
+ else if( cg.snap->ps.weapon == WP_ALEVEL3_UPG )
+ {
+ min = LEVEL3_POUNCE_TIME_MIN;
+ max = LEVEL3_POUNCE_TIME_UPG;
+ }
+ else if( cg.snap->ps.weapon == WP_ALEVEL4 )
+ {
+ if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_CHARGING )
+ {
+ min = 0;
+ max = LEVEL4_TRAMPLE_DURATION;
+ }
+ else
+ {
+ min = LEVEL4_TRAMPLE_CHARGE_MIN;
+ max = LEVEL4_TRAMPLE_CHARGE_MAX;
+ }
+ }
+ else if( cg.snap->ps.weapon == WP_LUCIFER_CANNON )
+ {
+ min = LCANNON_CHARGE_TIME_MIN;
+ max = LCANNON_CHARGE_TIME_MAX;
+ }
- case ITEM_ALIGN_RIGHT:
- tx = rect->w - tw;
- break;
+ if( max - min <= 0.0f )
+ return 0.0f;
- case ITEM_ALIGN_CENTER:
- tx = ( rect->w / 2.0f ) - ( tw / 2.0f );
- break;
+ progress = ( (float)cg.predictedPlayerState.stats[ STAT_MISC ] - min ) /
+ ( max - min );
- default:
- tx = 0.0f;
+ if( progress > 1.0f )
+ return 1.0f;
+
+ if( progress < 0.0f )
+ return 0.0f;
+
+ return progress;
+}
+
+#define CHARGE_BAR_FADE_RATE 0.002f
+
+static void CG_DrawPlayerChargeBarBG( rectDef_t *rect, vec4_t ref_color,
+ qhandle_t shader )
+{
+ vec4_t color;
+
+ if( !cg_drawChargeBar.integer || cg.chargeMeterAlpha <= 0.0f )
+ return;
+
+ color[ 0 ] = ref_color[ 0 ];
+ color[ 1 ] = ref_color[ 1 ];
+ color[ 2 ] = ref_color[ 2 ];
+ color[ 3 ] = ref_color[ 3 ] * cg.chargeMeterAlpha;
+
+ // Draw meter background
+ trap_R_SetColor( color );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
+ trap_R_SetColor( NULL );
+}
+
+// FIXME: This should come from the element info
+#define CHARGE_BAR_CAP_SIZE 3
+
+static void CG_DrawPlayerChargeBar( rectDef_t *rect, vec4_t ref_color,
+ qhandle_t shader )
+{
+ vec4_t color;
+ float x, y, width, height, cap_size, progress;
+
+ if( !cg_drawChargeBar.integer )
+ return;
+
+ // Get progress proportion and pump fade
+ progress = CG_ChargeProgress();
+ if( progress <= 0.0f )
+ {
+ cg.chargeMeterAlpha -= CHARGE_BAR_FADE_RATE * cg.frametime;
+ if( cg.chargeMeterAlpha <= 0.0f )
+ {
+ cg.chargeMeterAlpha = 0.0f;
+ return;
+ }
+ }
+ else
+ {
+ cg.chargeMeterValue = progress;
+ cg.chargeMeterAlpha += CHARGE_BAR_FADE_RATE * cg.frametime;
+ if( cg.chargeMeterAlpha > 1.0f )
+ cg.chargeMeterAlpha = 1.0f;
+ }
+
+ color[ 0 ] = ref_color[ 0 ];
+ color[ 1 ] = ref_color[ 1 ];
+ color[ 2 ] = ref_color[ 2 ];
+ color[ 3 ] = ref_color[ 3 ] * cg.chargeMeterAlpha;
+
+ // Flash red for Lucifer Cannon warning
+ if( cg.snap->ps.weapon == WP_LUCIFER_CANNON &&
+ cg.snap->ps.stats[ STAT_MISC ] >= LCANNON_CHARGE_TIME_WARN &&
+ ( cg.time & 128 ) )
+ {
+ color[ 0 ] = 1.0f;
+ color[ 1 ] = 0.0f;
+ color[ 2 ] = 0.0f;
+ }
+
+ x = rect->x;
+ y = rect->y;
+
+ // Horizontal charge bar
+ if( rect->w >= rect->h )
+ {
+ width = ( rect->w - CHARGE_BAR_CAP_SIZE * 2 ) * cg.chargeMeterValue;
+ height = rect->h;
+ CG_AdjustFrom640( &x, &y, &width, &height );
+ cap_size = CHARGE_BAR_CAP_SIZE * cgs.screenXScale;
+
+ // Draw the meter
+ trap_R_SetColor( color );
+ trap_R_DrawStretchPic( x, y, cap_size, height, 0, 0, 1, 1, shader );
+ trap_R_DrawStretchPic( x + width + cap_size, y, cap_size, height,
+ 1, 0, 0, 1, shader );
+ trap_R_DrawStretchPic( x + cap_size, y, width, height, 1, 0, 1, 1, shader );
+ trap_R_SetColor( NULL );
}
+ // Vertical charge bar
+ else
+ {
+ y += rect->h;
+ width = rect->w;
+ height = ( rect->h - CHARGE_BAR_CAP_SIZE * 2 ) * cg.chargeMeterValue;
+ CG_AdjustFrom640( &x, &y, &width, &height );
+ cap_size = CHARGE_BAR_CAP_SIZE * cgs.screenYScale;
+
+ // Draw the meter
+ trap_R_SetColor( color );
+ trap_R_DrawStretchPic( x, y - cap_size, width, cap_size,
+ 0, 1, 1, 0, shader );
+ trap_R_DrawStretchPic( x, y - height - cap_size * 2, width,
+ cap_size, 0, 0, 1, 1, shader );
+ trap_R_DrawStretchPic( x, y - height - cap_size, width, height,
+ 0, 1, 1, 1, shader );
+ trap_R_SetColor( NULL );
+ }
+}
+
+static void CG_DrawProgressLabel( rectDef_t *rect, float text_x, float text_y, vec4_t color,
+ float scale, int textalign, int textvalign,
+ const char *s, float fraction )
+{
+ vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f };
+ float tx, ty;
+
+ CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty );
+
if( fraction < 1.0f )
- CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, white,
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, white,
s, 0, 0, ITEM_TEXTSTYLE_NORMAL );
else
- CG_Text_Paint( rect->x + text_x + tx, rect->y + text_y, scale, color,
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, color,
s, 0, 0, ITEM_TEXTSTYLE_NEON );
}
static void CG_DrawMediaProgress( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
+ int align, int textalign, int textStyle,
+ float borderSize )
{
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.mediaFraction );
+ CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle,
+ borderSize, cg.mediaFraction );
}
static void CG_DrawMediaProgressLabel( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align )
+ vec4_t color, float scale, int textalign, int textvalign )
{
- CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Map and Textures", cg.mediaFraction );
+ CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign,
+ "Map and Textures", cg.mediaFraction );
}
-static void CG_DrawBuildablesProgress( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
+static void CG_DrawBuildablesProgress( rectDef_t *rect, vec4_t color,
+ float scale, int align, int textalign,
+ int textStyle, float borderSize )
{
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.buildablesFraction );
+ CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle,
+ borderSize, cg.buildablesFraction );
}
static void CG_DrawBuildablesProgressLabel( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align )
+ vec4_t color, float scale, int textalign, int textvalign )
{
- CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Buildable Models", cg.buildablesFraction );
+ CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign,
+ "Buildable Models", cg.buildablesFraction );
}
-static void CG_DrawCharModelProgress( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
+static void CG_DrawCharModelProgress( rectDef_t *rect, vec4_t color,
+ float scale, int align, int textalign,
+ int textStyle, float borderSize )
{
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, cg.charModelFraction );
+ CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle,
+ borderSize, cg.charModelFraction );
}
static void CG_DrawCharModelProgressLabel( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align )
+ vec4_t color, float scale, int textalign, int textvalign )
{
- CG_DrawProgressLabel( rect, text_x, text_y, color, scale, align, "Character Models", cg.charModelFraction );
+ CG_DrawProgressLabel( rect, text_x, text_y, color, scale, textalign, textvalign,
+ "Character Models", cg.charModelFraction );
}
static void CG_DrawOverallProgress( rectDef_t *rect, vec4_t color, float scale,
- int align, int textStyle, int special )
+ int align, int textalign, int textStyle,
+ float borderSize )
{
float total;
- total = ( cg.charModelFraction + cg.buildablesFraction + cg.mediaFraction ) / 3.0f;
- CG_DrawProgressBar( rect, color, scale, align, textStyle, special, total );
+ total = cg.charModelFraction + cg.buildablesFraction + cg.mediaFraction;
+ total /= 3.0f;
+
+ CG_DrawProgressBar( rect, color, scale, align, textalign, textStyle,
+ borderSize, total );
}
static void CG_DrawLevelShot( rectDef_t *rect )
@@ -1258,97 +1167,44 @@ static void CG_DrawLevelShot( rectDef_t *rect )
CG_DrawPic( rect->x, rect->y, rect->w, rect->h, detail );
}
-static void CG_DrawLoadingString( rectDef_t *rect, float text_x, float text_y, vec4_t color,
- float scale, int align, int textStyle, const char *s )
-{
- float tw, th, tx;
- int pos, i;
- char buffer[ 1024 ];
- char *end;
-
- if( !s[ 0 ] )
- return;
-
- strcpy( buffer, s );
- tw = CG_Text_Width( s, scale, 0 );
- th = scale * 40.0f;
-
- pos = i = 0;
-
- while( pos < strlen( s ) )
- {
- strcpy( buffer, &s[ pos ] );
- tw = CG_Text_Width( buffer, scale, 0 );
-
- while( tw > rect->w )
- {
- end = strrchr( buffer, ' ' );
-
- if( end == NULL )
- break;
-
- *end = '\0';
- tw = CG_Text_Width( buffer, scale, 0 );
- }
-
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
-
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - tw;
- break;
-
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( tw / 2.0f );
- break;
-
- default:
- tx = 0.0f;
- }
-
- CG_Text_Paint( tx + text_x, rect->y + text_y + i * ( th + 3 ), scale, color,
- buffer, 0, 0, textStyle );
-
- pos += strlen( buffer ) + 1;
- i++;
- }
-}
-
static void CG_DrawLevelName( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align, int textStyle )
+ vec4_t color, float scale,
+ int textalign, int textvalign, int textStyle )
{
const char *s;
s = CG_ConfigString( CS_MESSAGE );
- CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, s );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, s );
}
static void CG_DrawMOTD( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align, int textStyle )
+ vec4_t color, float scale,
+ int textalign, int textvalign, int textStyle )
{
const char *s;
+ char parsed[ MAX_STRING_CHARS ];
s = CG_ConfigString( CS_MOTD );
- CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, s );
+ Q_ParseNewlines( parsed, s, sizeof( parsed ) );
+
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, parsed );
}
static void CG_DrawHostname( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align, int textStyle )
+ vec4_t color, float scale,
+ int textalign, int textvalign, int textStyle )
{
char buffer[ 1024 ];
const char *info;
info = CG_ConfigString( CS_SERVERINFO );
- Q_strncpyz( buffer, Info_ValueForKey( info, "sv_hostname" ), 1024 );
+ UI_EscapeEmoticons( buffer, Info_ValueForKey( info, "sv_hostname" ), sizeof( buffer ) );
Q_CleanStr( buffer );
- CG_DrawLoadingString( rect, text_x, text_y, color, scale, align, textStyle, buffer );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, buffer );
}
/*
@@ -1409,30 +1265,29 @@ Draw all the status / pacifier stuff during level loading
*/
void CG_DrawLoadingScreen( void )
{
- Menu_Paint( Menus_FindByName( "Loading" ), qtrue );
+ menuDef_t *menu = Menus_FindByName( "Loading" );
+
+ Menu_Update( menu );
+ Menu_Paint( menu, qtrue );
}
float CG_GetValue( int ownerDraw )
{
- centity_t *cent;
playerState_t *ps;
+ weapon_t weapon;
- cent = &cg_entities[ cg.snap->ps.clientNum ];
ps = &cg.snap->ps;
+ weapon = BG_GetPlayerWeapon( ps );
switch( ownerDraw )
{
case CG_PLAYER_AMMO_VALUE:
- if( cent->currentState.weapon )
- {
+ if( weapon )
return ps->ammo;
- }
break;
case CG_PLAYER_CLIPS_VALUE:
- if( cent->currentState.weapon )
- {
+ if( weapon )
return ps->clips;
- }
break;
case CG_PLAYER_HEALTH:
return ps->stats[ STAT_HEALTH ];
@@ -1461,165 +1316,131 @@ static void CG_DrawKiller( rectDef_t *rect, float scale, vec4_t color,
if( cg.killerName[ 0 ] )
{
int x = rect->x + rect->w / 2;
- CG_Text_Paint( x - CG_Text_Width( CG_GetKillerText( ), scale, 0 ) / 2,
+ UI_Text_Paint( x - UI_Text_Width( CG_GetKillerText( ), scale ) / 2,
rect->y + rect->h, scale, color, CG_GetKillerText( ), 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;
+#define SPECTATORS_PIXELS_PER_SECOND 30.0f
- if( text )
- {
-// TTimo: FIXME
-// const unsigned char *s = text; // bk001206 - unsigned
- const char *s = text;
- float max = *maxX;
- float useScale;
- fontInfo_t *font = &cgDC.Assets.textFont;
+/*
+==================
+CG_DrawTeamSpectators
+==================
+*/
+static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, int textvalign, vec4_t color, qhandle_t shader )
+{
+ float y;
+ char *text = cg.spectatorList;
+ float textWidth = UI_Text_Width( text, scale );
- if( scale <= cg_smallFont.value )
- font = &cgDC.Assets.smallFont;
- else if( scale > cg_bigFont.value )
- font = &cgDC.Assets.bigFont;
+ CG_AlignText( rect, text, scale, 0.0f, 0.0f, ALIGN_LEFT, textvalign, NULL, &y );
- useScale = scale * font->glyphScale;
- trap_R_SetColor( color );
- len = strlen( text );
+ if( textWidth > rect->w )
+ {
+ // The text is too wide to fit, so scroll it
+ int now = trap_Milliseconds( );
+ int delta = now - cg.spectatorTime;
- if( limit > 0 && len > limit )
- len = limit;
+ CG_SetClipRegion( rect->x, rect->y, rect->w, rect->h );
- count = 0;
+ UI_Text_Paint( rect->x - cg.spectatorOffset, y, scale, color, text, 0, 0, 0 );
+ UI_Text_Paint( rect->x + textWidth - cg.spectatorOffset, y, scale, color, text, 0, 0, 0 );
- while( s && *s && count < len )
- {
- glyph = &font->glyphs[ (int)*s ];
- //TTimo: FIXME: getting nasty warnings without the cast,
- //hopefully this doesn't break the VM build
+ CG_ClearClipRegion( );
- 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;
+ cg.spectatorOffset += ( delta / 1000.0f ) * SPECTATORS_PIXELS_PER_SECOND;
- if( CG_Text_Width( s, useScale, 1 ) + x > max )
- {
- *maxX = 0;
- break;
- }
+ while( cg.spectatorOffset > textWidth )
+ cg.spectatorOffset -= textWidth;
- 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 );
+ cg.spectatorTime = now;
+ }
+ else
+ {
+ UI_Text_Paint( rect->x, y, scale, color, text, 0, 0, 0 );
}
}
-static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader )
+#define FOLLOWING_STRING "following "
+#define CHASING_STRING "chasing "
+
+/*
+==================
+CG_DrawFollow
+==================
+*/
+static void CG_DrawFollow( rectDef_t *rect, float text_x, float text_y,
+ vec4_t color, float scale, int textalign, int textvalign, int textStyle )
{
- if( cg.spectatorLen )
- {
- float maxX;
+ float tx, ty;
- if( cg.spectatorWidth == -1 )
- {
- cg.spectatorWidth = 0;
- cg.spectatorPaintX = rect->x + 1;
- cg.spectatorPaintX2 = -1;
- }
+ if( cg.snap && cg.snap->ps.pm_flags & PMF_FOLLOW )
+ {
+ char buffer[ MAX_STRING_CHARS ];
- if( cg.spectatorOffset > cg.spectatorLen )
- {
- cg.spectatorOffset = 0;
- cg.spectatorPaintX = rect->x + 1;
- cg.spectatorPaintX2 = -1;
- }
+ if( !cg.chaseFollow )
+ strcpy( buffer, FOLLOWING_STRING );
+ else
+ strcpy( buffer, CHASING_STRING );
- if( cg.time > cg.spectatorTime )
- {
- cg.spectatorTime = cg.time + 10;
+ strcat( buffer, cgs.clientinfo[ cg.snap->ps.clientNum ].name );
- if( cg.spectatorPaintX <= rect->x + 2 )
- {
- if( cg.spectatorOffset < cg.spectatorLen )
- {
- //TA: skip colour directives
- if( Q_IsColorString( &cg.spectatorList[ cg.spectatorOffset ] ) )
- cg.spectatorOffset += 2;
- else
- {
- cg.spectatorPaintX += CG_Text_Width( &cg.spectatorList[ cg.spectatorOffset ], scale, 1 ) - 1;
- cg.spectatorOffset++;
- }
- }
- else
- {
- cg.spectatorOffset = 0;
+ CG_AlignText( rect, buffer, scale, 0, 0, textalign, textvalign, &tx, &ty );
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, color, buffer, 0, 0,
+ textStyle );
+ }
+}
- if( cg.spectatorPaintX2 >= 0 )
- cg.spectatorPaintX = cg.spectatorPaintX2;
- else
- cg.spectatorPaintX = rect->x + rect->w - 2;
+/*
+==================
+CG_DrawTeamLabel
+==================
+*/
+static void CG_DrawTeamLabel( rectDef_t *rect, team_t team, float text_x, float text_y,
+ vec4_t color, float scale, int textalign, int textvalign, int textStyle )
+{
+ char *t;
+ char stage[ MAX_TOKEN_CHARS ];
+ const char *s;
+ float tx, ty;
- cg.spectatorPaintX2 = -1;
- }
- }
- else
- {
- cg.spectatorPaintX--;
+ stage[ 0 ] = '\0';
- if( cg.spectatorPaintX2 >= 0 )
- cg.spectatorPaintX2--;
- }
- }
+ switch( team )
+ {
+ case TEAM_ALIENS:
+ t = "Aliens";
+ if( cg.intermissionStarted )
+ Com_sprintf( stage, MAX_TOKEN_CHARS, "(Stage %d)", cgs.alienStage + 1 );
+ break;
- maxX = rect->x + rect->w - 2;
+ case TEAM_HUMANS:
+ t = "Humans";
+ if( cg.intermissionStarted )
+ Com_sprintf( stage, MAX_TOKEN_CHARS, "(Stage %d)", cgs.humanStage + 1 );
+ break;
- CG_Text_Paint_Limit( &maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color,
- &cg.spectatorList[ cg.spectatorOffset ], 0, 0 );
+ default:
+ t = "";
+ break;
+ }
- 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 );
- }
+ switch( textalign )
+ {
+ default:
+ case ALIGN_LEFT:
+ s = va( "%s %s", t, stage );
+ break;
- 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;
+ case ALIGN_RIGHT:
+ s = va( "%s %s", stage, t );
+ break;
}
+
+ CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty );
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle );
}
/*
@@ -1628,70 +1449,52 @@ CG_DrawStageReport
==================
*/
static void CG_DrawStageReport( rectDef_t *rect, float text_x, float text_y,
- vec4_t color, float scale, int align, int textStyle )
+ vec4_t color, float scale, int textalign, int textvalign, int textStyle )
{
char s[ MAX_TOKEN_CHARS ];
- int tx, w, kills;
+ float tx, ty;
- if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_NONE && !cg.intermissionStarted )
+ if( cg.intermissionStarted )
return;
- if( cg.intermissionStarted )
- {
- Com_sprintf( s, MAX_TOKEN_CHARS,
- "Stage %d" //PH34R MY MAD-LEET CODING SKILLZ
- " "
- "Stage %d",
- cgs.alienStage + 1, cgs.humanStage + 1 );
- }
- else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_NONE )
+ return;
+
+ if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
{
- kills = cgs.alienNextStageThreshold - cgs.alienKills;
+ int kills = ceil( (float)(cgs.alienNextStageThreshold - cgs.alienCredits) / ALIEN_CREDITS_PER_KILL );
+ if( kills < 0 )
+ kills = 0;
if( cgs.alienNextStageThreshold < 0 )
Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d", cgs.alienStage + 1 );
else if( kills == 1 )
- Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kill for next stage",
- cgs.alienStage + 1, kills );
+ Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, 1 frag for next stage",
+ cgs.alienStage + 1 );
else
- Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kills for next stage",
+ Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d frags for next stage",
cgs.alienStage + 1, kills );
}
- else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ else if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
{
- kills = cgs.humanNextStageThreshold - cgs.humanKills;
+ int credits = cgs.humanNextStageThreshold - cgs.humanCredits;
+
+ if( credits < 0 )
+ credits = 0;
if( cgs.humanNextStageThreshold < 0 )
Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d", cgs.humanStage + 1 );
- else if( kills == 1 )
- Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kill for next stage",
- cgs.humanStage + 1, kills );
+ else if( credits == 1 )
+ Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, 1 credit for next stage",
+ cgs.humanStage + 1 );
else
- Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d kills for next stage",
- cgs.humanStage + 1, kills );
+ Com_sprintf( s, MAX_TOKEN_CHARS, "Stage %d, %d credits for next stage",
+ cgs.humanStage + 1, credits );
}
- w = CG_Text_Width( s, scale, 0 );
-
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
-
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - w;
- break;
-
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f );
- break;
-
- default:
- tx = 0.0f;
- }
+ CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty );
- CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle );
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle );
}
/*
@@ -1699,15 +1502,17 @@ static void CG_DrawStageReport( rectDef_t *rect, float text_x, float text_y,
CG_DrawFPS
==================
*/
-//TA: personally i think this should be longer - it should really be a cvar
#define FPS_FRAMES 20
#define FPS_STRING "fps"
static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y,
- float scale, vec4_t color, int align, int textStyle,
+ float scale, vec4_t color,
+ int textalign, int textvalign, int textStyle,
qboolean scalableText )
{
- char *s;
- int tx, w, totalWidth, strLength;
+ const char *s;
+ float tx, ty;
+ float w, h, totalWidth;
+ int strLength;
static int previousTimes[ FPS_FRAMES ];
static int index;
int i, total;
@@ -1741,27 +1546,12 @@ static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y,
fps = 1000 * FPS_FRAMES / total;
s = va( "%d", fps );
- w = CG_Text_Width( "0", scale, 0 );
+ w = UI_Text_Width( "0", scale );
+ h = UI_Text_Height( "0", scale );
strLength = CG_DrawStrlen( s );
- totalWidth = CG_Text_Width( FPS_STRING, scale, 0 ) + w * strLength;
+ totalWidth = UI_Text_Width( FPS_STRING, scale ) + w * strLength;
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
-
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - totalWidth;
- break;
-
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f );
- break;
-
- default:
- tx = 0.0f;
- }
+ CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty );
if( scalableText )
{
@@ -1772,8 +1562,10 @@ static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y,
c[ 0 ] = s[ i ];
c[ 1 ] = '\0';
- CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );
+ UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle );
}
+
+ UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, FPS_STRING, 0, 0, textStyle );
}
else
{
@@ -1781,9 +1573,6 @@ static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y,
CG_DrawField( rect->x, rect->y, 3, rect->w / 3, rect->h, fps );
trap_R_SetColor( NULL );
}
-
- if( scalableText )
- CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, FPS_STRING, 0, 0, textStyle );
}
}
@@ -1844,10 +1633,13 @@ CG_DrawTimer
=================
*/
static void CG_DrawTimer( rectDef_t *rect, float text_x, float text_y,
- float scale, vec4_t color, int align, int textStyle )
+ float scale, vec4_t color,
+ int textalign, int textvalign, int textStyle )
{
- char *s;
- int i, tx, w, totalWidth, strLength;
+ const char *s;
+ float tx, ty;
+ int i, strLength;
+ float w, h, totalWidth;
int mins, seconds, tens;
int msec;
@@ -1863,36 +1655,255 @@ static void CG_DrawTimer( rectDef_t *rect, float text_x, float text_y,
seconds -= tens * 10;
s = va( "%d:%d%d", mins, tens, seconds );
- w = CG_Text_Width( "0", scale, 0 );
+ w = UI_Text_Width( "0", scale );
+ h = UI_Text_Height( "0", scale );
strLength = CG_DrawStrlen( s );
totalWidth = w * strLength;
- switch( align )
+ CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty );
+
+ for( i = 0; i < strLength; i++ )
{
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
+ char c[ 2 ];
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - totalWidth;
- break;
+ c[ 0 ] = s[ i ];
+ c[ 1 ] = '\0';
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f );
- break;
+ UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle );
+ }
+}
- default:
- tx = 0.0f;
+/*
+=================
+CG_DrawTeamOverlay
+=================
+*/
+
+typedef enum
+{
+ TEAMOVERLAY_OFF,
+ TEAMOVERLAY_ALL,
+ TEAMOVERLAY_SUPPORT,
+ TEAMOVERLAY_NEARBY,
+} teamOverlayMode_t;
+
+typedef enum
+{
+ TEAMOVERLAY_SORT_NONE,
+ TEAMOVERLAY_SORT_SCORE,
+ TEAMOVERLAY_SORT_WEAPONCLASS,
+} teamOverlaySort_t;
+
+static int QDECL SortScore( const void *a, const void *b )
+{
+ int na = *(int *)a;
+ int nb = *(int *)b;
+
+ return( cgs.clientinfo[ nb ].score - cgs.clientinfo[ na ].score );
+}
+
+static int QDECL SortWeaponClass( const void *a, const void *b )
+{
+ int out;
+ clientInfo_t *ca = cgs.clientinfo + *(int *)a;
+ clientInfo_t *cb = cgs.clientinfo + *(int *)b;
+
+ out = cb->curWeaponClass - ca->curWeaponClass;
+
+ // We want grangers on top. ckits are already on top without the special case.
+ if( ca->team == TEAM_ALIENS )
+ {
+ if( ca->curWeaponClass == PCL_ALIEN_BUILDER0_UPG ||
+ cb->curWeaponClass == PCL_ALIEN_BUILDER0_UPG ||
+ ca->curWeaponClass == PCL_ALIEN_BUILDER0 ||
+ cb->curWeaponClass == PCL_ALIEN_BUILDER0 )
+ {
+ out = -out;
+ }
}
- for( i = 0; i < strLength; i++ )
+ return( out );
+}
+
+static void CG_DrawTeamOverlay( rectDef_t *rect, float scale, vec4_t color )
+{
+ const char *s;
+ int i;
+ float x = rect->x;
+ float y;
+ clientInfo_t *ci, *pci;
+ vec4_t tcolor;
+ float iconSize = rect->h / 8.0f;
+ float leftMargin = 4.0f;
+ float iconTopMargin = 2.0f;
+ float midSep = 2.0f;
+ float backgroundWidth = rect->w;
+ float fontScale = 0.30f;
+ float vPad = 0.0f;
+ float nameWidth = 0.5f * rect->w;
+ char name[ MAX_NAME_LENGTH + 2 ];
+ int maxDisplayCount = 0;
+ int displayCount = 0;
+ float nameMaxX, nameMaxXCp;
+ float maxX = rect->x + rect->w;
+ float maxXCp = maxX;
+ weapon_t curWeapon = WP_NONE;
+ teamOverlayMode_t mode = cg_drawTeamOverlay.integer;
+ teamOverlaySort_t sort = cg_teamOverlaySortMode.integer;
+ int displayClients[ MAX_CLIENTS ];
+
+ if( cg.predictedPlayerState.pm_type == PM_SPECTATOR )
+ return;
+
+ if( mode == TEAMOVERLAY_OFF || !cg_teamOverlayMaxPlayers.integer )
+ return;
+
+ if( !cgs.teaminfoReceievedTime )
+ return;
+
+ if( cg.showScores ||
+ cg.predictedPlayerState.pm_type == PM_INTERMISSION )
+ return;
+
+ pci = cgs.clientinfo + cg.snap->ps.clientNum;
+
+ if( mode == TEAMOVERLAY_ALL || mode == TEAMOVERLAY_SUPPORT )
{
- char c[ 2 ];
+ for( i = 0; i < MAX_CLIENTS; i++ )
+ {
+ ci = cgs.clientinfo + i;
+ if( ci->infoValid && pci != ci && ci->team == pci->team )
+ {
+ if( mode == TEAMOVERLAY_ALL )
+ displayClients[ maxDisplayCount++ ] = i;
+ else
+ {
+ if( ci->curWeaponClass == PCL_ALIEN_BUILDER0 ||
+ ci->curWeaponClass == PCL_ALIEN_BUILDER0_UPG ||
+ ci->curWeaponClass == PCL_ALIEN_LEVEL1 ||
+ ci->curWeaponClass == PCL_ALIEN_LEVEL1_UPG ||
+ ci->curWeaponClass == WP_HBUILD )
+ {
+ displayClients[ maxDisplayCount++ ] = i;
+ }
+ }
+ }
+ }
+ }
+ else // find nearby
+ {
+ for( i = 0; i < cg.snap->numEntities; i++ )
+ {
+ centity_t *cent = &cg_entities[ cg.snap->entities[ i ].number ];
+ vec3_t relOrigin = { 0.0f, 0.0f, 0.0f };
+ int team = cent->currentState.misc & 0x00FF;
- c[ 0 ] = s[ i ];
- c[ 1 ] = '\0';
+ if( cent->currentState.eType != ET_PLAYER ||
+ team != pci->team ||
+ cent->currentState.eFlags & EF_DEAD )
+ {
+ continue;
+ }
+
+ VectorSubtract( cent->lerpOrigin, cg.predictedPlayerState.origin, relOrigin );
+
+ if( VectorLength( relOrigin ) < HELMET_RANGE )
+ displayClients[ maxDisplayCount++ ] = cg.snap->entities[ i ].number;
+ }
+ }
- CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );
+ // Sort
+ if( sort == TEAMOVERLAY_SORT_SCORE )
+ {
+ qsort( displayClients, maxDisplayCount,
+ sizeof( displayClients[ 0 ] ), SortScore );
+ }
+ else if( sort == TEAMOVERLAY_SORT_WEAPONCLASS )
+ {
+ qsort( displayClients, maxDisplayCount,
+ sizeof( displayClients[ 0 ] ), SortWeaponClass );
+ }
+
+ if( maxDisplayCount > cg_teamOverlayMaxPlayers.integer )
+ maxDisplayCount = cg_teamOverlayMaxPlayers.integer;
+
+ iconSize *= scale;
+ leftMargin *= scale;
+ iconTopMargin *= scale;
+ midSep *= scale;
+ backgroundWidth *= scale;
+ fontScale *= scale;
+ nameWidth *= scale;
+
+ vPad = ( rect->h - ( (float) maxDisplayCount * iconSize ) ) / 2.0f;
+ y = rect->y + vPad;
+
+ tcolor[ 0 ] = 1.0f;
+ tcolor[ 1 ] = 1.0f;
+ tcolor[ 2 ] = 1.0f;
+ tcolor[ 3 ] = color[ 3 ];
+
+ for( i = 0; i < MAX_CLIENTS && displayCount < maxDisplayCount; i++ )
+ {
+ ci = cgs.clientinfo + displayClients[ i ];
+
+ if( !ci->infoValid || pci == ci || ci->team != pci->team )
+ continue;
+
+ Com_sprintf( name, sizeof( name ), "%s^7", ci->name );
+
+ trap_R_SetColor( color );
+ CG_DrawPic( x, y, backgroundWidth,
+ iconSize, cgs.media.teamOverlayShader );
+ trap_R_SetColor( tcolor );
+ if( ci->health <= 0 || !ci->curWeaponClass )
+ s = "";
+ else
+ {
+ if( ci->team == TEAM_HUMANS )
+ curWeapon = ci->curWeaponClass;
+ else if( ci->team == TEAM_ALIENS )
+ curWeapon = BG_Class( ci->curWeaponClass )->startWeapon;
+
+ CG_DrawPic( x + leftMargin, y, iconSize, iconSize,
+ cg_weapons[ curWeapon ].weaponIcon );
+ if( cg.predictedPlayerState.stats[ STAT_TEAM ] == TEAM_HUMANS )
+ {
+ if( ci->upgrade != UP_NONE )
+ {
+ CG_DrawPic( x + iconSize + leftMargin, y, iconSize,
+ iconSize, cg_upgrades[ ci->upgrade ].upgradeIcon );
+ }
+ }
+ else
+ {
+ if( curWeapon == WP_ABUILD2 || curWeapon == WP_ALEVEL1_UPG ||
+ curWeapon == WP_ALEVEL2_UPG || curWeapon == WP_ALEVEL3_UPG )
+ {
+ CG_DrawPic( x + iconSize + leftMargin, y, iconSize,
+ iconSize, cgs.media.upgradeClassIconShader );
+ }
+ }
+
+ s = va( " [^%c%3d^7] ^7%s",
+ CG_GetColorCharForHealth( displayClients[ i ] ),
+ ci->health,
+ CG_ConfigString( CS_LOCATIONS + ci->location ) );
+ }
+
+ trap_R_SetColor( NULL );
+ nameMaxX = nameMaxXCp = x + 2.0f * iconSize +
+ leftMargin + midSep + nameWidth;
+ UI_Text_Paint_Limit( &nameMaxXCp, x + 2.0f * iconSize + leftMargin + midSep,
+ y + iconSize - iconTopMargin, fontScale, tcolor, name,
+ 0, 0 );
+
+ maxXCp = maxX;
+
+ UI_Text_Paint_Limit( &maxXCp, nameMaxX, y + iconSize - iconTopMargin,
+ fontScale, tcolor, s, 0, 0 );
+ y += iconSize;
+ displayCount++;
}
}
@@ -1902,17 +1913,19 @@ CG_DrawClock
=================
*/
static void CG_DrawClock( rectDef_t *rect, float text_x, float text_y,
- float scale, vec4_t color, int align, int textStyle )
+ float scale, vec4_t color,
+ int textalign, int textvalign, int textStyle )
{
- char *s;
- int i, tx, w, totalWidth, strLength;
+ const char *s;
+ float tx, ty;
+ int i, strLength;
+ float w, h, totalWidth;
qtime_t qt;
- int t;
if( !cg_drawClock.integer )
return;
- t = trap_RealTime( &qt );
+ trap_RealTime( &qt );
if( cg_drawClock.integer == 2 )
{
@@ -1936,27 +1949,12 @@ static void CG_DrawClock( rectDef_t *rect, float text_x, float text_y,
s = va( "%d%s%02d%s", h, ( qt.tm_sec % 2 ) ? ":" : " ", qt.tm_min, pm );
}
- w = CG_Text_Width( "0", scale, 0 );
+ w = UI_Text_Width( "0", scale );
+ h = UI_Text_Height( "0", scale );
strLength = CG_DrawStrlen( s );
totalWidth = w * strLength;
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
-
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - totalWidth;
- break;
-
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f );
- break;
-
- default:
- tx = 0.0f;
- }
+ CG_AlignText( rect, s, 0.0f, totalWidth, h, textalign, textvalign, &tx, &ty );
for( i = 0; i < strLength; i++ )
{
@@ -1965,7 +1963,7 @@ static void CG_DrawClock( rectDef_t *rect, float text_x, float text_y,
c[ 0 ] = s[ i ];
c[ 1 ] = '\0';
- CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle );
+ UI_Text_Paint( text_x + tx + i * w, text_y + ty, scale, color, c, 0, 0, textStyle );
}
}
@@ -1975,39 +1973,90 @@ CG_DrawSnapshot
==================
*/
static void CG_DrawSnapshot( rectDef_t *rect, float text_x, float text_y,
- float scale, vec4_t color, int align, int textStyle )
+ float scale, vec4_t color,
+ int textalign, int textvalign, int textStyle )
{
- char *s;
- int w, tx;
+ const char *s;
+ float tx, ty;
if( !cg_drawSnapshot.integer )
return;
s = va( "time:%d snap:%d cmd:%d", cg.snap->serverTime,
cg.latestSnapshotNum, cgs.serverCommandSequence );
- w = CG_Text_Width( s, scale, 0 );
- switch( align )
- {
- case ITEM_ALIGN_LEFT:
- tx = rect->x;
- break;
+ CG_AlignText( rect, s, scale, 0.0f, 0.0f, textalign, textvalign, &tx, &ty );
- case ITEM_ALIGN_RIGHT:
- tx = rect->x + rect->w - w;
- break;
+ UI_Text_Paint( text_x + tx, text_y + ty, scale, color, s, 0, 0, textStyle );
+}
- case ITEM_ALIGN_CENTER:
- tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f );
- break;
+/*
+===============================================================================
- default:
- tx = 0.0f;
- }
+KILLL MESSAGE
- CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle );
+===============================================================================
+*/
+
+/*
+==================
+CG_DrawKillMsg
+==================
+*/
+static void CG_DrawKillMsg( rectDef_t *rect, float text_x, float text_y,
+ float scale, vec4_t color,
+ int textalign, int textvalign, int textStyle )
+{
+ int i;
+ vec4_t hcolor;
+ int chatHeight;
+
+ if (cg_killMsgHeight.integer < TEAMCHAT_HEIGHT)
+ chatHeight = cg_killMsgHeight.integer;
+ else
+ chatHeight = TEAMCHAT_HEIGHT;
+
+ if (chatHeight <= 0)
+ return; // disabled
+
+ if (cgs.killMsgLastPos != cgs.killMsgPos)
+ {
+ if (cg.time - cgs.killMsgMsgTimes[cgs.killMsgLastPos % chatHeight] > cg_killMsgTime.integer)
+ cgs.killMsgLastPos++;
+
+ hcolor[0] = hcolor[1] = hcolor[2] = hcolor[3] = 1.0f;
+
+ for ( i = cgs.killMsgPos - 1; i >= cgs.killMsgLastPos; i-- )
+ {
+ int x = 0, w;
+ int j = i % chatHeight;
+
+ w = UI_Text_Width( cgs.killMsgKillers[j], scale );
+ UI_Text_Paint( rect->x + TINYCHAR_WIDTH,
+ rect->y - (cgs.killMsgPos - i)*20,
+ scale, color, cgs.killMsgKillers[j],
+ 0, 0, textStyle );
+ x += w + 3;
+
+ if ( cg_weapons[cgs.killMsgWeapons[j]].weaponIcon != WP_NONE )
+ {
+ CG_DrawPic( rect->x + TINYCHAR_WIDTH + x,
+ rect->y - (cgs.killMsgPos - i)*20-15,
+ 16, 16,
+ cg_weapons[cgs.killMsgWeapons[j]].weaponIcon );
+ x += 16 + 2;
+
+ w = UI_Text_Width( cgs.killMsgVictims[j], scale );
+ UI_Text_Paint( rect->x + TINYCHAR_WIDTH + x,
+ rect->y - (cgs.killMsgPos - i)*20,
+ scale, color, cgs.killMsgVictims[j],
+ 0, 0, textStyle );
+ }
+ }
+ }
}
+
/*
===============================================================================
@@ -2080,7 +2129,7 @@ void CG_AddLagometerSnapshotInfo( snapshot_t *snap )
{
previousPings[ index++ ] = cg.snap->ping;
index = index % PING_FRAMES;
-
+
for( i = 0; i < PING_FRAMES; i++ )
{
cg.ping += previousPings[ i ];
@@ -2116,8 +2165,8 @@ static void CG_DrawDisconnect( void )
// also add text in center of screen
s = "Connection Interrupted";
- w = CG_Text_Width( s, 0.7f, 0 );
- CG_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+ w = UI_Text_Width( s, 0.7f );
+ UI_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
// blink the icon
if( ( cg.time >> 9 ) & 1 )
@@ -2147,7 +2196,7 @@ static void CG_DrawLagometer( rectDef_t *rect, float text_x, float text_y,
int color;
vec4_t adjustedColor;
float vscale;
- vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f };
+ const char *ping;
if( cg.snap->ps.pm_type == PM_INTERMISSION )
return;
@@ -2270,81 +2319,194 @@ static void CG_DrawLagometer( rectDef_t *rect, float text_x, float text_y,
trap_R_SetColor( NULL );
if( cg_nopredict.integer || cg_synchronousClients.integer )
- CG_Text_Paint( ax, ay, 0.5, white, "snc", 0, 0, ITEM_TEXTSTYLE_NORMAL );
+ ping = "snc";
else
- {
- char *s;
-
- s = va( "%d", cg.ping );
- ax = rect->x + ( rect->w / 2.0f ) - ( CG_Text_Width( s, scale, 0 ) / 2.0f ) + text_x;
- ay = rect->y + ( rect->h / 2.0f ) + ( CG_Text_Height( s, scale, 0 ) / 2.0f ) + text_y;
+ ping = va( "%d", cg.ping );
+ ax = rect->x + ( rect->w / 2.0f ) -
+ ( UI_Text_Width( ping, scale ) / 2.0f ) + text_x;
+ ay = rect->y + ( rect->h / 2.0f ) +
+ ( UI_Text_Height( ping, scale ) / 2.0f ) + text_y;
- Vector4Copy( textColor, adjustedColor );
- adjustedColor[ 3 ] = 0.5f;
- CG_Text_Paint( ax, ay, scale, adjustedColor, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );
- }
+ Vector4Copy( textColor, adjustedColor );
+ adjustedColor[ 3 ] = 0.5f;
+ UI_Text_Paint( ax, ay, scale, adjustedColor, ping, 0, 0,
+ ITEM_TEXTSTYLE_NORMAL );
CG_DrawDisconnect( );
}
+#define SPEEDOMETER_NUM_SAMPLES 4096
+#define SPEEDOMETER_NUM_DISPLAYED_SAMPLES 160
+#define SPEEDOMETER_DRAW_TEXT 0x1
+#define SPEEDOMETER_DRAW_GRAPH 0x2
+#define SPEEDOMETER_IGNORE_Z 0x4
+float speedSamples[ SPEEDOMETER_NUM_SAMPLES ];
+int speedSampleTimes[ SPEEDOMETER_NUM_SAMPLES ];
+// array indices
+int oldestSpeedSample = 0;
+int maxSpeedSample = 0;
+int maxSpeedSampleInWindow = 0;
+
/*
-==============
-CG_DrawTextBlock
-==============
+===================
+CG_AddSpeed
+
+append a speed to the sample history
+===================
*/
-static void CG_DrawTextBlock( rectDef_t *rect, float text_x, float text_y, vec4_t color,
- float scale, int align, int textStyle, const char *text,
- menuDef_t *parent, itemDef_t *textItem )
+void CG_AddSpeed( void )
{
- float x, y, w, h;
+ float speed;
+ vec3_t vel;
+ int windowTime;
+ qboolean newSpeedGteMaxSpeed, newSpeedGteMaxSpeedInWindow;
- //offset the text
- x = rect->x;
- y = rect->y;
- w = rect->w - ( 16 + ( 2 * text_x ) ); //16 to ensure text within frame
- h = rect->h;
+ VectorCopy( cg.snap->ps.velocity, vel );
- textItem->text = text;
+ if( cg_drawSpeed.integer & SPEEDOMETER_IGNORE_Z )
+ vel[ 2 ] = 0;
- textItem->parent = parent;
- memcpy( textItem->window.foreColor, color, sizeof( vec4_t ) );
- textItem->window.flags = 0;
+ speed = VectorLength( vel );
- switch( align )
+ windowTime = cg_maxSpeedTimeWindow.integer;
+ if( windowTime < 0 )
+ windowTime = 0;
+ else if( windowTime > SPEEDOMETER_NUM_SAMPLES * 1000 )
+ windowTime = SPEEDOMETER_NUM_SAMPLES * 1000;
+
+ if( ( newSpeedGteMaxSpeed = ( speed >= speedSamples[ maxSpeedSample ] ) ) )
+ maxSpeedSample = oldestSpeedSample;
+
+ if( ( newSpeedGteMaxSpeedInWindow = ( speed >= speedSamples[ maxSpeedSampleInWindow ] ) ) )
+ maxSpeedSampleInWindow = oldestSpeedSample;
+
+ speedSamples[ oldestSpeedSample ] = speed;
+ speedSampleTimes[ oldestSpeedSample ] = cg.time;
+
+ if( !newSpeedGteMaxSpeed && maxSpeedSample == oldestSpeedSample )
{
- case ITEM_ALIGN_LEFT:
- textItem->window.rect.x = x;
- break;
+ // if old max was overwritten find a new one
+ int i;
+ for( maxSpeedSample = 0, i = 1; i < SPEEDOMETER_NUM_SAMPLES; i++ )
+ {
+ if( speedSamples[ i ] > speedSamples[ maxSpeedSample ] )
+ maxSpeedSample = i;
+ }
+ }
- case ITEM_ALIGN_RIGHT:
- textItem->window.rect.x = x + w;
- break;
+ if( !newSpeedGteMaxSpeedInWindow && ( maxSpeedSampleInWindow == oldestSpeedSample ||
+ cg.time - speedSampleTimes[ maxSpeedSampleInWindow ] > windowTime ) )
+ {
+ int i;
+ do {
+ maxSpeedSampleInWindow = ( maxSpeedSampleInWindow + 1 ) % SPEEDOMETER_NUM_SAMPLES;
+ } while( cg.time - speedSampleTimes[ maxSpeedSampleInWindow ] > windowTime );
+ for( i = maxSpeedSampleInWindow; ; i = ( i + 1 ) % SPEEDOMETER_NUM_SAMPLES )
+ {
+ if( speedSamples[ i ] > speedSamples[ maxSpeedSampleInWindow ] )
+ maxSpeedSampleInWindow = i;
+ if( i == oldestSpeedSample )
+ break;
+ }
+ }
- case ITEM_ALIGN_CENTER:
- textItem->window.rect.x = x + ( w / 2 );
- break;
+ oldestSpeedSample = ( oldestSpeedSample + 1 ) % SPEEDOMETER_NUM_SAMPLES;
+}
- default:
- textItem->window.rect.x = x;
- break;
+#define SPEEDOMETER_MIN_RANGE 900
+#define SPEED_MED 1000.f
+#define SPEED_FAST 1600.f
+
+/*
+===================
+CG_DrawSpeedGraph
+===================
+*/
+static void CG_DrawSpeedGraph( rectDef_t *rect, vec4_t foreColor,
+ vec4_t backColor )
+{
+ int i;
+ float val, max, top;
+ // colour of graph is interpolated between these values
+ const vec3_t slow = { 0.0, 0.0, 1.0 };
+ const vec3_t medium = { 0.0, 1.0, 0.0 };
+ const vec3_t fast = { 1.0, 0.0, 0.0 };
+ vec4_t color;
+
+ max = speedSamples[ maxSpeedSample ];
+ if( max < SPEEDOMETER_MIN_RANGE )
+ max = SPEEDOMETER_MIN_RANGE;
+
+ trap_R_SetColor( backColor );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.whiteShader );
+
+ Vector4Copy( foreColor, color );
+
+ for( i = 1; i < SPEEDOMETER_NUM_DISPLAYED_SAMPLES; i++ )
+ {
+ val = speedSamples[ ( oldestSpeedSample + i + SPEEDOMETER_NUM_SAMPLES -
+ SPEEDOMETER_NUM_DISPLAYED_SAMPLES ) % SPEEDOMETER_NUM_SAMPLES ];
+ if( val < SPEED_MED )
+ VectorLerp2( val / SPEED_MED, slow, medium, color );
+ else if( val < SPEED_FAST )
+ VectorLerp2( ( val - SPEED_MED ) / ( SPEED_FAST - SPEED_MED ),
+ medium, fast, color );
+ else
+ VectorCopy( fast, color );
+ trap_R_SetColor( color );
+ top = rect->y + ( 1 - val / max ) * rect->h;
+ CG_DrawPic( rect->x + ( i / (float)SPEEDOMETER_NUM_DISPLAYED_SAMPLES ) * rect->w, top,
+ rect->w / (float)SPEEDOMETER_NUM_DISPLAYED_SAMPLES, val * rect->h / max,
+ cgs.media.whiteShader );
+ }
+ trap_R_SetColor( NULL );
+}
+
+/*
+===================
+CG_DrawSpeedText
+===================
+*/
+static void CG_DrawSpeedText( rectDef_t *rect, float text_x, float text_y,
+ float scale, vec4_t foreColor )
+{
+ char speedstr[ 16 ];
+ float val;
+ vec4_t color;
+
+ VectorCopy( foreColor, color );
+ color[ 3 ] = 1;
+ if( cg.predictedPlayerState.clientNum == cg.clientNum )
+ {
+ vec3_t vel;
+ VectorCopy( cg.predictedPlayerState.velocity, vel );
+ if( cg_drawSpeed.integer & SPEEDOMETER_IGNORE_Z )
+ vel[ 2 ] = 0;
+ val = VectorLength( vel );
}
+ else
+ val = speedSamples[ ( oldestSpeedSample - 1 + SPEEDOMETER_NUM_SAMPLES ) % SPEEDOMETER_NUM_SAMPLES ];
- textItem->window.rect.y = y;
- textItem->window.rect.w = w;
- textItem->window.rect.h = h;
- textItem->window.borderSize = 0;
- textItem->textRect.x = 0;
- textItem->textRect.y = 0;
- textItem->textRect.w = 0;
- textItem->textRect.h = 0;
- textItem->textalignment = align;
- textItem->textalignx = text_x;
- textItem->textaligny = text_y;
- textItem->textscale = scale;
- textItem->textStyle = textStyle;
+ Com_sprintf( speedstr, sizeof( speedstr ), "%d / %d", (int)val, (int)speedSamples[ maxSpeedSampleInWindow ] );
- //hack to utilise existing autowrap code
- Item_Text_AutoWrapped_Paint( textItem );
+ UI_Text_Paint(
+ rect->x + ( rect->w - UI_Text_Width( speedstr, scale ) ) / 2.0f,
+ rect->y + ( rect->h + UI_Text_Height( speedstr, scale ) ) / 2.0f,
+ scale, color, speedstr, 0, 0, ITEM_TEXTSTYLE_NORMAL );
+}
+
+/*
+===================
+CG_DrawSpeed
+===================
+*/
+static void CG_DrawSpeed( rectDef_t *rect, float text_x, float text_y,
+ float scale, vec4_t foreColor, vec4_t backColor )
+{
+ if( cg_drawSpeed.integer & SPEEDOMETER_DRAW_GRAPH )
+ CG_DrawSpeedGraph( rect, foreColor, backColor );
+ if( cg_drawSpeed.integer & SPEEDOMETER_DRAW_TEXT )
+ CG_DrawSpeedText( rect, text_x, text_y, scale, foreColor );
}
/*
@@ -2353,13 +2515,9 @@ CG_DrawConsole
===================
*/
static void CG_DrawConsole( rectDef_t *rect, float text_x, float text_y, vec4_t color,
- float scale, int align, int textStyle )
+ float scale, int textalign, int textvalign, int textStyle )
{
- static menuDef_t dummyParent;
- static itemDef_t textItem;
-
- CG_DrawTextBlock( rect, text_x, text_y, color, scale, align, textStyle,
- cg.consoleText, &dummyParent, &textItem );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, cg.consoleText );
}
/*
@@ -2368,16 +2526,12 @@ CG_DrawTutorial
===================
*/
static void CG_DrawTutorial( rectDef_t *rect, float text_x, float text_y, vec4_t color,
- float scale, int align, int textStyle )
+ float scale, int textalign, int textvalign, int textStyle )
{
- static menuDef_t dummyParent;
- static itemDef_t textItem;
-
if( !cg_tutorial.integer )
return;
- CG_DrawTextBlock( rect, text_x, text_y, color, scale, align, textStyle,
- CG_TutorialText( ), &dummyParent, &textItem );
+ UI_DrawTextBlock( rect, text_x, text_y, color, scale, textalign, textvalign, textStyle, CG_TutorialText( ) );
}
/*
@@ -2387,29 +2541,34 @@ CG_DrawWeaponIcon
*/
void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color )
{
- int ammo, clips, maxAmmo;
- centity_t *cent;
+ int maxAmmo;
playerState_t *ps;
+ weapon_t weapon;
- cent = &cg_entities[ cg.snap->ps.clientNum ];
ps = &cg.snap->ps;
+ weapon = BG_GetPlayerWeapon( ps );
- ammo = ps->ammo;
- clips = ps->clips;
- BG_FindAmmoForWeapon( cent->currentState.weapon, &maxAmmo, NULL );
+ maxAmmo = BG_Weapon( weapon )->maxAmmo;
// don't display if dead
if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 )
return;
- if( cent->currentState.weapon == 0 )
+ if( weapon <= WP_NONE || weapon >= WP_NUM_WEAPONS )
+ {
return;
+ }
- CG_RegisterWeapon( cent->currentState.weapon );
+ if( !cg_weapons[ weapon ].registered )
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: CG_DrawWeaponIcon: weapon %d (%s) "
+ "is not registered\n", weapon, BG_Weapon( weapon )->name );
+ return;
+ }
- if( clips == 0 && !BG_FindInfinteAmmoForWeapon( cent->currentState.weapon ) )
+ if( ps->clips == 0 && !BG_Weapon( weapon )->infiniteAmmo )
{
- float ammoPercent = (float)ammo / (float)maxAmmo;
+ float ammoPercent = (float)ps->ammo / (float)maxAmmo;
if( ammoPercent < 0.33f )
{
@@ -2418,7 +2577,9 @@ void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color )
}
}
- if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS && CG_AtHighestClass( ) )
+ if( cg.predictedPlayerState.stats[ STAT_TEAM ] == TEAM_ALIENS &&
+ !BG_AlienCanEvolve( cg.predictedPlayerState.stats[ STAT_CLASS ],
+ ps->persistant[ PERS_CREDIT ], cgs.alienStage ) )
{
if( cg.time - cg.lastEvolveAttempt <= NO_CREDITS_TIME )
{
@@ -2428,7 +2589,8 @@ void CG_DrawWeaponIcon( rectDef_t *rect, vec4_t color )
}
trap_R_SetColor( color );
- CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].weaponIcon );
+ CG_DrawPic( rect->x, rect->y, rect->w, rect->h,
+ cg_weapons[ weapon ].weaponIcon );
trap_R_SetColor( NULL );
}
@@ -2443,50 +2605,65 @@ CROSSHAIR
*/
+
/*
=================
CG_DrawCrosshair
=================
*/
-static void CG_DrawCrosshair( void )
+static void CG_DrawCrosshair( rectDef_t *rect, vec4_t color )
{
float w, h;
qhandle_t hShader;
float x, y;
weaponInfo_t *wi;
+ weapon_t weapon;
+
+ weapon = BG_GetPlayerWeapon( &cg.snap->ps );
if( cg_drawCrosshair.integer == CROSSHAIR_ALWAYSOFF )
return;
if( cg_drawCrosshair.integer == CROSSHAIR_RANGEDONLY &&
- !BG_FindLongRangedForWeapon( cg.snap->ps.weapon ) )
- {
+ !BG_Weapon( weapon )->longRanged )
return;
- }
- if( ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR ) ||
- ( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) ||
- ( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) )
+ if( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT )
return;
if( cg.renderingThirdPerson )
return;
- wi = &cg_weapons[ cg.snap->ps.weapon ];
+ if( cg.snap->ps.pm_type == PM_INTERMISSION )
+ return;
- w = h = wi->crossHairSize;
+ wi = &cg_weapons[ weapon ];
- x = cg_crosshairX.integer;
- y = cg_crosshairY.integer;
- CG_AdjustFrom640( &x, &y, &w, &h );
+ w = h = wi->crossHairSize * cg_crosshairSize.value;
+ w *= cgDC.aspectScale;
+
+ //FIXME: this still ignores the width/height of the rect, but at least it's
+ //neater than cg_crosshairX/cg_crosshairY
+ x = rect->x + ( rect->w / 2 ) - ( w / 2 );
+ y = rect->y + ( rect->h / 2 ) - ( h / 2 );
hShader = wi->crossHair;
+ //aiming at a friendly player/buildable, dim the crosshair
+ if( cg.time == cg.crosshairClientTime || cg.crosshairBuildable >= 0 )
+ {
+ int i;
+ for( i = 0; i < 3; i++ )
+ color[i] *= .5f;
+
+ }
+
if( hShader != 0 )
{
- trap_R_DrawStretchPic( x + cg.refdef.x + 0.5 * ( cg.refdef.width - w ),
- y + cg.refdef.y + 0.5 * ( cg.refdef.height - h ),
- w, h, 0, 0, 1, 1, hShader );
+
+ trap_R_SetColor( color );
+ CG_DrawPic( x, y, w, h, hShader );
+ trap_R_SetColor( NULL );
}
}
@@ -2502,7 +2679,7 @@ static void CG_ScanForCrosshairEntity( void )
trace_t trace;
vec3_t start, end;
int content;
- pTeam_t team;
+ team_t team;
VectorCopy( cg.refdef.vieworg, start );
VectorMA( start, 131072, cg.refdef.viewaxis[ 0 ], end );
@@ -2510,20 +2687,29 @@ static void CG_ScanForCrosshairEntity( void )
CG_Trace( &trace, start, vec3_origin, vec3_origin, end,
cg.snap->ps.clientNum, CONTENTS_SOLID|CONTENTS_BODY );
- if( trace.entityNum >= MAX_CLIENTS )
- return;
-
// if the player is in fog, don't show it
content = trap_CM_PointContents( trace.endpos, 0 );
if( content & CONTENTS_FOG )
return;
+ if( trace.entityNum >= MAX_CLIENTS )
+ {
+ entityState_t *s = &cg_entities[ trace.entityNum ].currentState;
+ if( s->eType == ET_BUILDABLE && BG_Buildable( s->modelindex )->team ==
+ cg.snap->ps.stats[ STAT_TEAM ] )
+ cg.crosshairBuildable = trace.entityNum;
+ else
+ cg.crosshairBuildable = -1;
+
+ return;
+ }
+
team = cgs.clientinfo[ trace.entityNum ].team;
- if( cg.snap->ps.persistant[ PERS_TEAM ] != TEAM_SPECTATOR )
+ if( cg.snap->ps.stats[ STAT_TEAM ] != TEAM_NONE )
{
//only display team names of those on the same team as this player
- if( team != cg.snap->ps.stats[ STAT_PTEAM ] )
+ if( team != cg.snap->ps.stats[ STAT_TEAM ] )
return;
}
@@ -2535,13 +2721,51 @@ static void CG_ScanForCrosshairEntity( void )
/*
=====================
+CG_DrawLocation
+=====================
+*/
+static void CG_DrawLocation( rectDef_t *rect, float scale, int textalign, vec4_t color )
+{
+ const char *location;
+ centity_t *locent;
+ float maxX;
+ float tx = rect->x, ty = rect->y;
+
+ if( cg.intermissionStarted )
+ return;
+
+ maxX = rect->x + rect->w;
+
+ locent = CG_GetPlayerLocation( );
+ if( locent )
+ location = CG_ConfigString( CS_LOCATIONS + locent->currentState.generic1 );
+ else
+ location = CG_ConfigString( CS_LOCATIONS );
+
+ // need to skip horiz. align if it's too long, but valign must be run either way
+ if( UI_Text_Width( location, scale ) < rect->w )
+ {
+ CG_AlignText( rect, location, scale, 0.0f, 0.0f, textalign, VALIGN_CENTER, &tx, &ty );
+ UI_Text_Paint( tx, ty, scale, color, location, 0, 0, ITEM_TEXTSTYLE_NORMAL );
+ }
+ else
+ {
+ CG_AlignText( rect, location, scale, 0.0f, 0.0f, ALIGN_NONE, VALIGN_CENTER, &tx, &ty );
+ UI_Text_Paint_Limit( &maxX, tx, ty, scale, color, location, 0, 0 );
+ }
+
+ trap_R_SetColor( NULL );
+}
+
+/*
+=====================
CG_DrawCrosshairNames
=====================
*/
static void CG_DrawCrosshairNames( rectDef_t *rect, float scale, int textStyle )
{
float *color;
- char *name;
+ const char *name;
float w, x;
if( !cg_drawCrosshairNames.integer )
@@ -2554,21 +2778,31 @@ static void CG_DrawCrosshairNames( rectDef_t *rect, float scale, int textStyle )
CG_ScanForCrosshairEntity( );
// draw the name of the player being looked at
- color = CG_FadeColor( cg.crosshairClientTime, 1000 );
+ color = CG_FadeColor( cg.crosshairClientTime, CROSSHAIR_CLIENT_TIMEOUT );
if( !color )
{
trap_R_SetColor( NULL );
return;
}
+ // add health from overlay info to the crosshair client name
name = cgs.clientinfo[ cg.crosshairClientNum ].name;
- w = CG_Text_Width( name, scale, 0 );
- x = rect->x + rect->w / 2;
- CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );
+ if( cg_teamOverlayUserinfo.integer &&
+ cg.snap->ps.stats[ STAT_TEAM ] != TEAM_NONE &&
+ cgs.teaminfoReceievedTime &&
+ cgs.clientinfo[ cg.crosshairClientNum ].health > 0 )
+ {
+ name = va( "%s ^7[^%c%d^7]", name,
+ CG_GetColorCharForHealth( cg.crosshairClientNum ),
+ cgs.clientinfo[ cg.crosshairClientNum ].health );
+ }
+
+ w = UI_Text_Width( name, scale );
+ x = rect->x + rect->w / 2.0f;
+ UI_Text_Paint( x - w / 2.0f, rect->y + rect->h, scale, color, name, 0, 0, textStyle );
trap_R_SetColor( NULL );
}
-
/*
===============
CG_OwnerDraw
@@ -2578,14 +2812,12 @@ Draw an owner drawn item
*/
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,
+ int align, int textalign, int textvalign, float borderSize,
+ float scale, vec4_t foreColor, vec4_t backColor,
qhandle_t shader, int textStyle )
{
rectDef_t rect;
- if( cg_drawStatus.integer == 0 )
- return;
-
rect.x = x;
rect.y = y;
rect.w = w;
@@ -2594,100 +2826,107 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
switch( ownerDraw )
{
case CG_PLAYER_CREDITS_VALUE:
- CG_DrawPlayerCreditsValue( &rect, color, qtrue );
+ CG_DrawPlayerCreditsValue( &rect, foreColor, qtrue );
break;
- case CG_PLAYER_BANK_VALUE:
- CG_DrawPlayerBankValue( &rect, color, qtrue );
+ case CG_PLAYER_CREDITS_FRACTION:
+ CG_DrawPlayerCreditsFraction( &rect, foreColor, shader );
break;
case CG_PLAYER_CREDITS_VALUE_NOPAD:
- CG_DrawPlayerCreditsValue( &rect, color, qfalse );
- break;
- case CG_PLAYER_BANK_VALUE_NOPAD:
- CG_DrawPlayerBankValue( &rect, color, qfalse );
- break;
- case CG_PLAYER_STAMINA:
- CG_DrawPlayerStamina( &rect, color, scale, align, textStyle, special );
+ CG_DrawPlayerCreditsValue( &rect, foreColor, qfalse );
break;
case CG_PLAYER_STAMINA_1:
- CG_DrawPlayerStamina1( &rect, color, shader );
- break;
case CG_PLAYER_STAMINA_2:
- CG_DrawPlayerStamina2( &rect, color, shader );
- break;
case CG_PLAYER_STAMINA_3:
- CG_DrawPlayerStamina3( &rect, color, shader );
- break;
case CG_PLAYER_STAMINA_4:
- CG_DrawPlayerStamina4( &rect, color, shader );
+ CG_DrawPlayerStamina( ownerDraw, &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_STAMINA_BOLT:
- CG_DrawPlayerStaminaBolt( &rect, color, shader );
+ CG_DrawPlayerStaminaBolt( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_AMMO_VALUE:
- CG_DrawPlayerAmmoValue( &rect, color );
+ CG_DrawPlayerAmmoValue( &rect, foreColor );
break;
case CG_PLAYER_CLIPS_VALUE:
- CG_DrawPlayerClipsValue( &rect, color );
+ CG_DrawPlayerClipsValue( &rect, foreColor );
break;
case CG_PLAYER_BUILD_TIMER:
- CG_DrawPlayerBuildTimer( &rect, color );
+ CG_DrawPlayerBuildTimer( &rect, foreColor );
break;
case CG_PLAYER_HEALTH:
- CG_DrawPlayerHealthValue( &rect, color );
- break;
- case CG_PLAYER_HEALTH_BAR:
- CG_DrawPlayerHealthBar( &rect, color, scale, align, textStyle, special );
+ CG_DrawPlayerHealthValue( &rect, foreColor );
break;
case CG_PLAYER_HEALTH_CROSS:
- CG_DrawPlayerHealthCross( &rect, color, shader );
+ CG_DrawPlayerHealthCross( &rect, foreColor );
+ break;
+ case CG_PLAYER_CHARGE_BAR_BG:
+ CG_DrawPlayerChargeBarBG( &rect, foreColor, shader );
+ break;
+ case CG_PLAYER_CHARGE_BAR:
+ CG_DrawPlayerChargeBar( &rect, foreColor, shader );
break;
case CG_PLAYER_CLIPS_RING:
- CG_DrawPlayerClipsRing( &rect, color, shader );
+ CG_DrawPlayerClipsRing( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_BUILD_TIMER_RING:
- CG_DrawPlayerBuildTimerRing( &rect, color, shader );
+ CG_DrawPlayerBuildTimerRing( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_WALLCLIMBING:
- CG_DrawPlayerWallclimbing( &rect, color, shader );
+ CG_DrawPlayerWallclimbing( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_BOOSTED:
- CG_DrawPlayerBoosted( &rect, color, shader );
+ CG_DrawPlayerBoosted( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_BOOST_BOLT:
- CG_DrawPlayerBoosterBolt( &rect, color, shader );
+ CG_DrawPlayerBoosterBolt( &rect, backColor, foreColor, shader );
break;
case CG_PLAYER_POISON_BARBS:
- CG_DrawPlayerPoisonBarbs( &rect, color, shader );
+ CG_DrawPlayerPoisonBarbs( &rect, foreColor, shader );
break;
case CG_PLAYER_ALIEN_SENSE:
CG_DrawAlienSense( &rect );
break;
case CG_PLAYER_HUMAN_SCANNER:
- CG_DrawHumanScanner( &rect, shader, color );
+ CG_DrawHumanScanner( &rect, shader, foreColor );
break;
case CG_PLAYER_USABLE_BUILDABLE:
- CG_DrawUsableBuildable( &rect, shader, color );
+ CG_DrawUsableBuildable( &rect, shader, foreColor );
break;
case CG_KILLER:
- CG_DrawKiller( &rect, scale, color, shader, textStyle );
+ CG_DrawKiller( &rect, scale, foreColor, shader, textStyle );
break;
case CG_PLAYER_SELECT:
- CG_DrawItemSelect( &rect, color );
+ CG_DrawItemSelect( &rect, foreColor );
break;
case CG_PLAYER_WEAPONICON:
- CG_DrawWeaponIcon( &rect, color );
+ CG_DrawWeaponIcon( &rect, foreColor );
break;
case CG_PLAYER_SELECTTEXT:
CG_DrawItemSelectText( &rect, scale, textStyle );
break;
case CG_SPECTATORS:
- CG_DrawTeamSpectators( &rect, scale, color, shader );
+ CG_DrawTeamSpectators( &rect, scale, textvalign, foreColor, shader );
+ break;
+ case CG_PLAYER_LOCATION:
+ CG_DrawLocation( &rect, scale, textalign, foreColor );
+ break;
+ case CG_FOLLOW:
+ CG_DrawFollow( &rect, text_x, text_y, foreColor, scale,
+ textalign, textvalign, textStyle );
break;
case CG_PLAYER_CROSSHAIRNAMES:
CG_DrawCrosshairNames( &rect, scale, textStyle );
break;
+ case CG_PLAYER_CROSSHAIR:
+ CG_DrawCrosshair( &rect, foreColor );
+ break;
case CG_STAGE_REPORT_TEXT:
- CG_DrawStageReport( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawStageReport( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
+ break;
+ case CG_ALIENS_SCORE_LABEL:
+ CG_DrawTeamLabel( &rect, TEAM_ALIENS, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
+ break;
+ case CG_HUMANS_SCORE_LABEL:
+ CG_DrawTeamLabel( &rect, TEAM_HUMANS, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
break;
//loading screen
@@ -2695,74 +2934,92 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
CG_DrawLevelShot( &rect );
break;
case CG_LOAD_MEDIA:
- CG_DrawMediaProgress( &rect, color, scale, align, textStyle, special );
+ CG_DrawMediaProgress( &rect, foreColor, scale, align, textalign, textStyle,
+ borderSize );
break;
case CG_LOAD_MEDIA_LABEL:
- CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, align );
+ CG_DrawMediaProgressLabel( &rect, text_x, text_y, foreColor, scale, textalign, textvalign );
break;
case CG_LOAD_BUILDABLES:
- CG_DrawBuildablesProgress( &rect, color, scale, align, textStyle, special );
+ CG_DrawBuildablesProgress( &rect, foreColor, scale, align, textalign,
+ textStyle, borderSize );
break;
case CG_LOAD_BUILDABLES_LABEL:
- CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, align );
+ CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, foreColor, scale, textalign, textvalign );
break;
case CG_LOAD_CHARMODEL:
- CG_DrawCharModelProgress( &rect, color, scale, align, textStyle, special );
+ CG_DrawCharModelProgress( &rect, foreColor, scale, align, textalign,
+ textStyle, borderSize );
break;
case CG_LOAD_CHARMODEL_LABEL:
- CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, align );
+ CG_DrawCharModelProgressLabel( &rect, text_x, text_y, foreColor, scale, textalign, textvalign );
break;
case CG_LOAD_OVERALL:
- CG_DrawOverallProgress( &rect, color, scale, align, textStyle, special );
+ CG_DrawOverallProgress( &rect, foreColor, scale, align, textalign, textStyle,
+ borderSize );
break;
case CG_LOAD_LEVELNAME:
- CG_DrawLevelName( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawLevelName( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
break;
case CG_LOAD_MOTD:
- CG_DrawMOTD( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawMOTD( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
break;
case CG_LOAD_HOSTNAME:
- CG_DrawHostname( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawHostname( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
break;
case CG_FPS:
- CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qtrue );
+ CG_DrawFPS( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle, qtrue );
break;
case CG_FPS_FIXED:
- CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle, qfalse );
+ CG_DrawFPS( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle, qfalse );
break;
case CG_TIMER:
- CG_DrawTimer( &rect, text_x, text_y, scale, color, align, textStyle );
+ CG_DrawTimer( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle );
break;
case CG_CLOCK:
- CG_DrawClock( &rect, text_x, text_y, scale, color, align, textStyle );
+ CG_DrawClock( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle );
break;
case CG_TIMER_MINS:
- CG_DrawTimerMins( &rect, color );
+ CG_DrawTimerMins( &rect, foreColor );
break;
case CG_TIMER_SECS:
- CG_DrawTimerSecs( &rect, color );
+ CG_DrawTimerSecs( &rect, foreColor );
break;
case CG_SNAPSHOT:
- CG_DrawSnapshot( &rect, text_x, text_y, scale, color, align, textStyle );
+ CG_DrawSnapshot( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle );
break;
case CG_LAGOMETER:
- CG_DrawLagometer( &rect, text_x, text_y, scale, color );
+ CG_DrawLagometer( &rect, text_x, text_y, scale, foreColor );
+ break;
+ case CG_TEAMOVERLAY:
+ CG_DrawTeamOverlay( &rect, scale, foreColor );
+ break;
+ case CG_SPEEDOMETER:
+ CG_DrawSpeed( &rect, text_x, text_y, scale, foreColor, backColor );
break;
case CG_DEMO_PLAYBACK:
- CG_DrawDemoPlayback( &rect, color, shader );
+ CG_DrawDemoPlayback( &rect, foreColor, shader );
break;
case CG_DEMO_RECORDING:
- CG_DrawDemoRecording( &rect, color, shader );
+ CG_DrawDemoRecording( &rect, foreColor, shader );
break;
case CG_CONSOLE:
- CG_DrawConsole( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawConsole( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
break;
case CG_TUTORIAL:
- CG_DrawTutorial( &rect, text_x, text_y, color, scale, align, textStyle );
+ CG_DrawTutorial( &rect, text_x, text_y, foreColor, scale, textalign, textvalign, textStyle );
+ break;
+
+ case CG_KILLFEED:
+ CG_DrawKillMsg( &rect, text_x, text_y, scale, foreColor, textalign, textvalign, textStyle );
+ break;
+
+ case CG_PLAYER_THZ_SCANNER:
+ THZ_DrawScanner( &rect );
break;
default:
@@ -2827,17 +3084,17 @@ CG_ShowTeamMenus
*/
void CG_ShowTeamMenu( void )
{
- Menus_OpenByName( "teamMenu" );
+ Menus_ActivateByName( "teamMenu" );
}
/*
==================
CG_EventHandling
-==================
- type 0 - no event handling
- 1 - team menu
- 2 - hud editor
+type 0 - no event handling
+ 1 - team menu
+ 2 - hud editor
+==================
*/
void CG_EventHandling( int type )
{
@@ -2891,14 +3148,6 @@ int CG_ClientNumFromName( const char *p )
void CG_RunMenuScript( char **args )
{
}
-
-
-void CG_GetTeamColor( vec4_t *color )
-{
- (*color)[ 0 ] = (*color)[ 2 ] = 0.0f;
- (*color)[ 1 ] = 0.17f;
- (*color)[ 3 ] = 0.25f;
-}
//END TA UI
@@ -2910,13 +3159,9 @@ CG_DrawLighting
*/
static void CG_DrawLighting( void )
{
- centity_t *cent;
-
- cent = &cg_entities[ cg.snap->ps.clientNum ];
-
//fade to black if stamina is low
- if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) &&
- ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) )
+ if( ( cg.snap->ps.stats[ STAT_STAMINA ] < STAMINA_BLACKOUT_LEVEL ) &&
+ ( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS ) )
{
vec4_t black = { 0, 0, 0, 0 };
black[ 3 ] = 1.0 - ( (float)( cg.snap->ps.stats[ STAT_STAMINA ] + 1000 ) / 200.0f );
@@ -2946,8 +3191,15 @@ for a few moments
void CG_CenterPrint( const char *str, int y, int charWidth )
{
char *s;
+ char newlineParsed[ MAX_STRING_CHARS ];
+ const char *wrapped;
+ static int maxWidth = (int)( ( 2.0f / 3.0f ) * (float)SCREEN_WIDTH );
+
+ Q_ParseNewlines( newlineParsed, str, sizeof( newlineParsed ) );
- Q_strncpyz( cg.centerPrint, str, sizeof( cg.centerPrint ) );
+ wrapped = Item_Text_Wrap( newlineParsed, 0.5f, maxWidth );
+
+ Q_strncpyz( cg.centerPrint, wrapped, sizeof( cg.centerPrint ) );
cg.centerPrintTime = cg.time;
cg.centerPrintY = y;
@@ -2994,9 +3246,9 @@ static void CG_DrawCenterString( void )
while( 1 )
{
- char linebuffer[ 1024 ];
+ char linebuffer[ MAX_STRING_CHARS ];
- for( l = 0; l < 50; l++ )
+ for( l = 0; l < sizeof(linebuffer) - 1; l++ )
{
if( !start[ l ] || start[ l ] == '\n' )
break;
@@ -3006,10 +3258,10 @@ static void CG_DrawCenterString( void )
linebuffer[ l ] = 0;
- w = CG_Text_Width( linebuffer, 0.5, 0 );
- h = CG_Text_Height( linebuffer, 0.5, 0 );
+ w = UI_Text_Width( linebuffer, 0.5 );
+ h = UI_Text_Height( linebuffer, 0.5 );
x = ( SCREEN_WIDTH - w ) / 2;
- CG_Text_Paint( x, y + h, 0.5, color, linebuffer, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE );
+ UI_Text_Paint( x, y + h, 0.5, color, linebuffer, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE );
y += h + 6;
while( *start && ( *start != '\n' ) )
@@ -3037,83 +3289,62 @@ static void CG_DrawCenterString( void )
CG_DrawVote
=================
*/
-static void CG_DrawVote( void )
+static void CG_DrawVote( team_t team )
{
- char *s;
+ const char *s;
int sec;
+ int offset = 0;
vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f };
- char yeskey[ 32 ], nokey[ 32 ];
+ char yeskey[ 32 ] = "", nokey[ 32 ] = "";
- if( !cgs.voteTime )
+ if( !cgs.voteTime[ team ] )
return;
// play a talk beep whenever it is modified
- if( cgs.voteModified )
+ if( cgs.voteModified[ team ] )
{
- cgs.voteModified = qfalse;
+ cgs.voteModified[ team ] = qfalse;
trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
}
- sec = ( VOTE_TIME - ( cg.time - cgs.voteTime ) ) / 1000;
+ sec = ( VOTE_TIME - ( cg.time - cgs.voteTime[ team ] ) ) / 1000;
if( sec < 0 )
sec = 0;
- Q_strncpyz( yeskey, CG_KeyBinding( "vote yes" ), sizeof( yeskey ) );
- Q_strncpyz( nokey, CG_KeyBinding( "vote no" ), sizeof( nokey ) );
- s = va( "VOTE(%i): \"%s\" [%s]Yes:%i [%s]No:%i", sec, cgs.voteString,
- yeskey, cgs.voteYes, nokey, cgs.voteNo );
- CG_Text_Paint( 8, 340, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );
-}
-/*
-=================
-CG_DrawTeamVote
-=================
-*/
-static void CG_DrawTeamVote( void )
-{
- char *s;
- int sec, cs_offset;
- vec4_t white = { 1.0f, 1.0f, 1.0f, 1.0f };
- char yeskey[ 32 ], nokey[ 32 ];
+ if( cg_tutorial.integer )
+ {
+ Com_sprintf( yeskey, sizeof( yeskey ), "[%s]",
+ CG_KeyBinding( va( "%svote yes", team == TEAM_NONE ? "" : "team" ) ) );
+ Com_sprintf( nokey, sizeof( nokey ), "[%s]",
+ CG_KeyBinding( va( "%svote no", team == TEAM_NONE ? "" : "team" ) ) );
+ }
- if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS )
- cs_offset = 0;
- else if( cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_ALIENS )
- cs_offset = 1;
- else
- return;
+ if( team != TEAM_NONE )
+ offset = 80;
- if( !cgs.teamVoteTime[ cs_offset ] )
- return;
+ s = va( "%sVOTE(%i): %s",
+ team == TEAM_NONE ? "" : "TEAM", sec, cgs.voteString[ team ] );
- // play a talk beep whenever it is modified
- if ( cgs.teamVoteModified[ cs_offset ] )
- {
- cgs.teamVoteModified[ cs_offset ] = qfalse;
- trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
- }
+ UI_Text_Paint( 8, 300 + offset, 0.3f, white, s, 0, 0,
+ ITEM_TEXTSTYLE_NORMAL );
- sec = ( VOTE_TIME - ( cg.time - cgs.teamVoteTime[ cs_offset ] ) ) / 1000;
+ s = va( " Called by: \"%s\"", cgs.voteCaller[ team ] );
- if( sec < 0 )
- sec = 0;
+ UI_Text_Paint( 8, 320 + offset, 0.3f, white, s, 0, 0,
+ ITEM_TEXTSTYLE_NORMAL );
- Q_strncpyz( yeskey, CG_KeyBinding( "teamvote yes" ), sizeof( yeskey ) );
- Q_strncpyz( nokey, CG_KeyBinding( "teamvote no" ), sizeof( nokey ) );
- s = va( "TEAMVOTE(%i): \"%s\" [%s]Yes:%i [%s]No:%i", sec,
- cgs.teamVoteString[ cs_offset ],
- yeskey, cgs.teamVoteYes[cs_offset],
- nokey, cgs.teamVoteNo[ cs_offset ] );
+ s = va( " %sYes:%i %sNo:%i",
+ yeskey, cgs.voteYes[ team ], nokey, cgs.voteNo[ team ] );
- CG_Text_Paint( 8, 360, 0.3f, white, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );
+ UI_Text_Paint( 8, 340 + offset, 0.3f, white, s, 0, 0,
+ ITEM_TEXTSTYLE_NORMAL );
}
static qboolean CG_DrawScoreboard( void )
{
static qboolean firstTime = qtrue;
- float fade, *fadeColor;
if( menuScoreboard )
menuScoreboard->window.flags &= ~WINDOW_FORCED;
@@ -3125,13 +3356,8 @@ static qboolean CG_DrawScoreboard( void )
return qfalse;
}
- if( cg.showScores ||
- cg.predictedPlayerState.pm_type == PM_INTERMISSION )
- {
- fade = 1.0;
- fadeColor = colorWhite;
- }
- else
+ if( !cg.showScores &&
+ cg.predictedPlayerState.pm_type != PM_INTERMISSION )
{
cg.deferredPlayerLoading = 0;
cg.killerName[ 0 ] = 0;
@@ -3139,6 +3365,7 @@ static qboolean CG_DrawScoreboard( void )
return qfalse;
}
+ CG_RequestScores( );
if( menuScoreboard == NULL )
menuScoreboard = Menus_FindByName( "teamscore_menu" );
@@ -3147,10 +3374,12 @@ static qboolean CG_DrawScoreboard( void )
{
if( firstTime )
{
+ cg.spectatorTime = trap_Milliseconds();
CG_SetScoreSelection( menuScoreboard );
firstTime = qfalse;
}
+ Menu_Update( menuScoreboard );
Menu_Paint( menuScoreboard, qtrue );
}
@@ -3164,27 +3393,28 @@ CG_DrawIntermission
*/
static void CG_DrawIntermission( void )
{
- if( cg_drawStatus.integer )
- Menu_Paint( Menus_FindByName( "default_hud" ), qtrue );
+ menuDef_t *menu = Menus_FindByName( "default_hud" );
+
+ Menu_Update( menu );
+ Menu_Paint( menu, qtrue );
cg.scoreFadeTime = cg.time;
cg.scoreBoardShowing = CG_DrawScoreboard( );
}
-#define FOLLOWING_STRING "following "
-
/*
=================
-CG_DrawFollow
+CG_DrawQueue
=================
*/
-static qboolean CG_DrawFollow( void )
+static qboolean CG_DrawQueue( void )
{
float w;
vec4_t color;
- char buffer[ MAX_STRING_CHARS ];
+ int position;
+ char *ordinal, buffer[ MAX_STRING_CHARS ];
- if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) )
+ if( !( cg.snap->ps.pm_flags & PMF_QUEUED ) )
return qfalse;
color[ 0 ] = 1;
@@ -3192,66 +3422,82 @@ static qboolean CG_DrawFollow( void )
color[ 2 ] = 1;
color[ 3 ] = 1;
- strcpy( buffer, FOLLOWING_STRING );
- strcat( buffer, cgs.clientinfo[ cg.snap->ps.clientNum ].name );
+ position = cg.snap->ps.persistant[ PERS_QUEUEPOS ] + 1;
+ if( position < 1 )
+ return qfalse;
- w = CG_Text_Width( buffer, 0.7f, 0 );
- CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+ switch( position % 100 )
+ {
+ case 11:
+ case 12:
+ case 13:
+ ordinal = "th";
+ break;
+ default:
+ switch( position % 10 )
+ {
+ case 1: ordinal = "st"; break;
+ case 2: ordinal = "nd"; break;
+ case 3: ordinal = "rd"; break;
+ default: ordinal = "th"; break;
+ }
+ break;
+ }
+
+ Com_sprintf( buffer, MAX_STRING_CHARS, "You are %d%s in the spawn queue",
+ position, ordinal );
+
+ w = UI_Text_Width( buffer, 0.7f );
+ UI_Text_Paint( 320 - w / 2, 360, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+
+ if( cg.snap->ps.persistant[ PERS_SPAWNS ] == 0 )
+ Com_sprintf( buffer, MAX_STRING_CHARS, "There are no spawns remaining" );
+ else if( cg.snap->ps.persistant[ PERS_SPAWNS ] == 1 )
+ Com_sprintf( buffer, MAX_STRING_CHARS, "There is 1 spawn remaining" );
+ else
+ Com_sprintf( buffer, MAX_STRING_CHARS, "There are %d spawns remaining",
+ cg.snap->ps.persistant[ PERS_SPAWNS ] );
+
+ w = UI_Text_Width( buffer, 0.7f );
+ UI_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
return qtrue;
}
+
/*
=================
-CG_DrawQueue
+CG_DrawWarmup
=================
*/
-static qboolean CG_DrawQueue( void )
+static void CG_DrawWarmup( void )
{
- float w;
- vec4_t color;
- char buffer[ MAX_STRING_CHARS ];
+ int sec = 0;
+ int w;
+ int h;
+ float size = 0.5f;
+ char text[ MAX_STRING_CHARS ] = "Warmup Time:";
- if( !( cg.snap->ps.pm_flags & PMF_QUEUED ) )
- return qfalse;
-
- color[ 0 ] = 1;
- color[ 1 ] = 1;
- color[ 2 ] = 1;
- color[ 3 ] = 1;
+ if( !cg.warmupTime )
+ return;
- Com_sprintf( buffer, MAX_STRING_CHARS, "You are in position %d of the spawn queue.",
- cg.snap->ps.persistant[ PERS_QUEUEPOS ] + 1 );
+ sec = ( cg.warmupTime - cg.time ) / 1000;
- w = CG_Text_Width( buffer, 0.7f, 0 );
- CG_Text_Paint( 320 - w / 2, 360, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+ if( sec < 0 )
+ return;
- if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
- {
- if( cgs.numAlienSpawns == 1 )
- Com_sprintf( buffer, MAX_STRING_CHARS, "There is 1 spawn remaining." );
- else
- Com_sprintf( buffer, MAX_STRING_CHARS, "There are %d spawns remaining.",
- cgs.numAlienSpawns );
- }
- else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
- {
- if( cgs.numHumanSpawns == 1 )
- Com_sprintf( buffer, MAX_STRING_CHARS, "There is 1 spawn remaining." );
- else
- Com_sprintf( buffer, MAX_STRING_CHARS, "There are %d spawns remaining.",
- cgs.numHumanSpawns );
- }
+ w = UI_Text_Width( text, size );
+ h = UI_Text_Height( text, size );
+ UI_Text_Paint( 320 - w / 2, 200, size, colorWhite, text, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
- w = CG_Text_Width( buffer, 0.7f, 0 );
- CG_Text_Paint( 320 - w / 2, 400, 0.7f, color, buffer, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+ Com_sprintf( text, sizeof( text ), "%s", sec ? va( "%d", sec ) : "FIGHT!" );
- return qtrue;
+ w = UI_Text_Width( text, size );
+ UI_Text_Paint( 320 - w / 2, 200 + 1.5f * h, size, colorWhite, text, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
}
//==================================================================================
-#define SPECTATOR_STRING "SPECTATOR"
/*
=================
CG_Draw2D
@@ -3259,15 +3505,11 @@ CG_Draw2D
*/
static void CG_Draw2D( void )
{
- vec4_t color;
- float w;
- menuDef_t *menu = NULL, *defaultMenu;
+ menuDef_t *menu = NULL;
- color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 1.0f;
-
- // if we are taking a levelshot for the menu, don't draw anything
- if( cg.levelShot )
- return;
+ // fading to black if stamina runs out
+ // (only 2D that can't be disabled)
+ CG_DrawLighting( );
if( cg_draw2D.integer == 0 )
return;
@@ -3278,36 +3520,30 @@ static void CG_Draw2D( void )
return;
}
- //TA: draw the lighting effects e.g. nvg
- CG_DrawLighting( );
-
-
- defaultMenu = Menus_FindByName( "default_hud" );
-
- if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
+ if ( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_NONE
+ || (cg.snap->ps.persistant[ PERS_SPECSTATE ] == SPECTATOR_NOT
+ && cg.snap->ps.stats[ STAT_HEALTH ] > 0 ))
{
- w = CG_Text_Width( SPECTATOR_STRING, 0.7f, 0 );
- CG_Text_Paint( 320 - w / 2, 440, 0.7f, color, SPECTATOR_STRING, 0, 0, ITEM_TEXTSTYLE_SHADOWED );
+ menu = Menus_FindByName( BG_ClassConfig(
+ cg.predictedPlayerState.stats[ STAT_CLASS ] )->hudName );
+
+ CG_DrawBuildableStatus( );
}
- else
- menu = Menus_FindByName( BG_FindHudNameForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ) );
- if( !( cg.snap->ps.stats[ STAT_STATE ] & SS_INFESTING ) &&
- !( cg.snap->ps.stats[ STAT_STATE ] & SS_HOVELING ) && menu &&
- ( cg.snap->ps.stats[ STAT_HEALTH ] > 0 ) )
+ if( !menu )
{
- CG_DrawBuildableStatus( );
- if( cg_drawStatus.integer )
- Menu_Paint( menu, qtrue );
+ menu = Menus_FindByName( "default_hud" );
- CG_DrawCrosshair( );
+ if( !menu ) // still couldn't find it
+ CG_Error( "Default HUD could not be found" );
}
- else if( cg_drawStatus.integer )
- Menu_Paint( defaultMenu, qtrue );
- CG_DrawVote( );
- CG_DrawTeamVote( );
- CG_DrawFollow( );
+ Menu_Update( menu );
+ Menu_Paint( menu, qtrue );
+
+ CG_DrawVote( TEAM_NONE );
+ CG_DrawVote( cg.predictedPlayerState.stats[ STAT_TEAM ] );
+ CG_DrawWarmup( );
CG_DrawQueue( );
// don't draw center string if scoreboard is up
@@ -3356,7 +3592,7 @@ static void CG_PainBlend( void )
float x, y, w, h;
float s1, t1, s2, t2;
- if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR || cg.intermissionStarted )
+ if( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT || cg.intermissionStarted )
return;
damage = cg.lastHealth - cg.snap->ps.stats[ STAT_HEALTH ];
@@ -3383,9 +3619,9 @@ static void CG_PainBlend( void )
return;
}
- if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_ALIENS )
+ if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
VectorSet( color, 0.43f, 0.8f, 0.37f );
- else if( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS )
+ else if( cg.snap->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
VectorSet( color, 0.8f, 0.0f, 0.0f );
if( cg.painBlendValue > cg.painBlendTarget )
@@ -3455,6 +3691,66 @@ void CG_ResetPainBlend( void )
}
/*
+================
+CG_DrawBinaryShadersFinalPhases
+================
+*/
+static void CG_DrawBinaryShadersFinalPhases( void )
+{
+ float ss, f, l, u;
+ polyVert_t verts[ 4 ] = {
+ { { 0, 0, 0 }, { 0, 0 }, { 255, 255, 255, 255 } },
+ { { 0, 0, 0 }, { 1, 0 }, { 255, 255, 255, 255 } },
+ { { 0, 0, 0 }, { 1, 1 }, { 255, 255, 255, 255 } },
+ { { 0, 0, 0 }, { 0, 1 }, { 255, 255, 255, 255 } }
+ };
+ int i, j, k;
+
+ if( !cg.numBinaryShadersUsed )
+ return;
+
+ ss = cg_binaryShaderScreenScale.value;
+ if( ss <= 0.0f )
+ {
+ cg.numBinaryShadersUsed = 0;
+ return;
+ }
+ else if( ss > 1.0f )
+ ss = 1.0f;
+
+ ss = sqrt( ss );
+
+ f = 1.01f; // FIXME: is this a good choice to avoid near-clipping?
+ l = f * tan( DEG2RAD( cg.refdef.fov_x / 2 ) ) * ss;
+ u = f * tan( DEG2RAD( cg.refdef.fov_y / 2 ) ) * ss;
+
+ VectorMA( cg.refdef.vieworg, f, cg.refdef.viewaxis[ 0 ], verts[ 0 ].xyz );
+ VectorMA( verts[ 0 ].xyz, l, cg.refdef.viewaxis[ 1 ], verts[ 0 ].xyz );
+ VectorMA( verts[ 0 ].xyz, u, cg.refdef.viewaxis[ 2 ], verts[ 0 ].xyz );
+ VectorMA( verts[ 0 ].xyz, -2*l, cg.refdef.viewaxis[ 1 ], verts[ 1 ].xyz );
+ VectorMA( verts[ 1 ].xyz, -2*u, cg.refdef.viewaxis[ 2 ], verts[ 2 ].xyz );
+ VectorMA( verts[ 0 ].xyz, -2*u, cg.refdef.viewaxis[ 2 ], verts[ 3 ].xyz );
+
+ trap_R_AddPolyToScene( cgs.media.binaryAlpha1Shader, 4, verts );
+
+ for( i = 0; i < cg.numBinaryShadersUsed; ++i )
+ {
+ for( j = 0; j < 4; ++j )
+ {
+ for( k = 0; k < 3; ++k )
+ verts[ j ].modulate[ k ] = cg.binaryShaderSettings[ i ].color[ k ];
+ }
+
+ if( cg.binaryShaderSettings[ i ].drawFrontline )
+ trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].f3, 4, verts );
+ if( cg.binaryShaderSettings[ i ].drawIntersection )
+ trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].b3, 4, verts );
+ }
+
+ cg.numBinaryShadersUsed = 0;
+}
+
+/*
=====================
CG_DrawActive
@@ -3496,6 +3792,8 @@ void CG_DrawActive( stereoFrame_t stereoView )
VectorMA( cg.refdef.vieworg, -separation, cg.refdef.viewaxis[ 1 ],
cg.refdef.vieworg );
+ CG_DrawBinaryShadersFinalPhases( );
+
// draw 3D view
trap_R_RenderScene( &cg.refdef );
@@ -3510,6 +3808,3 @@ void CG_DrawActive( stereoFrame_t stereoView )
// draw status bar and other floating elements
CG_Draw2D( );
}
-
-
-