summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_buildable.c186
-rw-r--r--src/cgame/cg_draw.c1
-rw-r--r--src/cgame/cg_drawtools.c35
-rw-r--r--src/cgame/cg_local.h3
-rw-r--r--src/cgame/cg_servercmds.c1
-rw-r--r--src/cgame/cg_tutorial.c33
6 files changed, 166 insertions, 93 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index 2f1eb239..c1cac345 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -697,8 +697,8 @@ static void CG_BuildableParticleEffects( centity_t *cent )
{
entityState_t *es = &cent->currentState;
buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex );
- int health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT );
- float healthFrac = (float)health / B_HEALTH_SCALE;
+ int health = es->generic1 & B_HEALTH_MASK;
+ float healthFrac = (float)health / B_HEALTH_MASK;
if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) )
return;
@@ -736,85 +736,122 @@ static void CG_BuildableParticleEffects( centity_t *cent )
}
}
-
-#define HEALTH_BAR_WIDTH 50.0f
-#define HEALTH_BAR_HEIGHT 5.0f
+#define STATUS_FADE_TIME 200
+#define STATUS_MAX_VIEW_DIST 600.0f
/*
==================
-CG_BuildableHealthBar
+CG_BuildableStatusDisplay
==================
*/
-static void CG_BuildableHealthBar( centity_t *cent )
+static void CG_BuildableStatusDisplay( centity_t *cent )
{
- vec3_t origin, origin2, down, right, back, downLength, rightLength;
- float rimWidth = HEALTH_BAR_HEIGHT / 15.0f;
- float doneWidth, leftWidth, progress;
+ entityState_t *es = &cent->currentState;
+ vec3_t origin;
+ float healthScale;
int health;
- qhandle_t shader;
- entityState_t *es;
- vec3_t mins, maxs;
+ float x, y;
+ char s[ MAX_STRING_CHARS ] = { 0 };
+ int w;
+ vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f };
+ qboolean powered, marked;
+ trace_t tr;
+ float d;
- es = &cent->currentState;
+ CG_Trace( &tr, cent->lerpOrigin, NULL, NULL, cg.refdef.vieworg,
+ cent->currentState.number, MASK_SOLID );
+ d = Distance( cent->lerpOrigin, cg.refdef.vieworg );
- health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT );
- progress = (float)health / B_HEALTH_SCALE;
+ if( ( tr.fraction < 1.0f || d > STATUS_MAX_VIEW_DIST ) &&
+ cent->buildableStatus.visible )
+ {
+ cent->buildableStatus.visible = qfalse;
+ cent->buildableStatus.lastTime = cg.time;
+ }
+ else if( ( tr.fraction == 1.0f && d <= STATUS_MAX_VIEW_DIST ) &&
+ !cent->buildableStatus.visible )
+ {
+ cent->buildableStatus.visible = qtrue;
+ cent->buildableStatus.lastTime = cg.time;
+ }
- if( progress < 0.0f )
- progress = 0.0f;
- else if( progress > 1.0f )
- progress = 1.0f;
+ // Fade up
+ if( cent->buildableStatus.visible )
+ {
+ if( cent->buildableStatus.lastTime + STATUS_FADE_TIME > cg.time )
+ color[ 3 ] = (float)( cg.time - cent->buildableStatus.lastTime ) / STATUS_FADE_TIME;
+ }
- if( progress < 0.33f )
- shader = cgs.media.redBuildShader;
- else
- shader = cgs.media.greenBuildShader;
+ // Fade down
+ if( !cent->buildableStatus.visible )
+ {
+ if( cent->buildableStatus.lastTime + STATUS_FADE_TIME > cg.time )
+ color[ 3 ] = 1.0f - (float)( cg.time - cent->buildableStatus.lastTime ) / STATUS_FADE_TIME;
+ else
+ return;
+ }
+
+ health = es->generic1 & B_HEALTH_MASK;
+ healthScale = (float)health / B_HEALTH_MASK;
- doneWidth = ( HEALTH_BAR_WIDTH - 2 * rimWidth ) * progress;
- leftWidth = ( HEALTH_BAR_WIDTH - 2 * rimWidth ) - doneWidth;
+ if( healthScale < 0.0f )
+ healthScale = 0.0f;
+ else if( healthScale > 1.0f )
+ healthScale = 1.0f;
- VectorCopy( cg.refdef.viewaxis[ 2 ], down );
- VectorInverse( down );
- VectorCopy( cg.refdef.viewaxis[ 1 ], right );
- VectorInverse( right );
- VectorSubtract( cg.refdef.vieworg, cent->lerpOrigin, back );
- VectorNormalize( back );
VectorCopy( cent->lerpOrigin, origin );
- BG_FindBBoxForBuildable( es->modelindex, mins, maxs );
- VectorMA( origin, 48.0f, es->origin2, origin );
- VectorMA( origin, -HEALTH_BAR_WIDTH / 2.0f, right, origin );
- VectorMA( origin, maxs[ 0 ] + 8.0f, back, origin );
-
- VectorCopy( origin, origin2 );
- VectorScale( right, rimWidth + doneWidth, rightLength );
- VectorScale( down, HEALTH_BAR_HEIGHT, downLength );
- CG_DrawPlane( origin2, downLength, rightLength, shader );
-
- VectorMA( origin, rimWidth + doneWidth, right, origin2 );
- VectorScale( right, leftWidth, rightLength );
- VectorScale( down, rimWidth, downLength );
- CG_DrawPlane( origin2, downLength, rightLength, shader );
-
- VectorMA( origin, rimWidth + doneWidth, right, origin2 );
- VectorMA( origin2, HEALTH_BAR_HEIGHT - rimWidth, down, origin2 );
- VectorScale( right, leftWidth, rightLength );
- VectorScale( down, rimWidth, downLength );
- CG_DrawPlane( origin2, downLength, rightLength, shader );
-
- VectorMA( origin, HEALTH_BAR_WIDTH - rimWidth, right, origin2 );
- VectorScale( right, rimWidth, rightLength );
- VectorScale( down, HEALTH_BAR_HEIGHT, downLength );
- CG_DrawPlane( origin2, downLength, rightLength, shader );
-
- if( !( es->generic1 & B_POWERED_TOGGLEBIT ) &&
- BG_FindTeamForBuildable( es->modelindex ) == BIT_HUMANS )
+ if( CG_WorldToScreen( origin, &x, &y ) )
+ {
+ powered = es->generic1 & B_POWERED_TOGGLEBIT;
+ marked = es->generic1 & B_MARKED_TOGGLEBIT;
+
+ //FIXME: crappy mock-up for the time being...
+ Com_sprintf( s, MAX_STRING_CHARS, "%d%%", (int)(healthScale * 100) );
+
+ if( BG_FindTeamForBuildable( es->modelindex ) == BIT_HUMANS && !powered )
+ Q_strcat( s, MAX_STRING_CHARS, " P" );
+
+ if( marked )
+ Q_strcat( s, MAX_STRING_CHARS, " X" );
+
+ w = CG_Text_Width( s, 0.5f, 0 );
+
+ CG_Text_Paint( x - w / 2, y, 0.5f, color, s, 0, 0, ITEM_TEXTSTYLE_NORMAL );
+ }
+}
+
+/*
+==================
+CG_DrawBuildableStatus
+==================
+*/
+void CG_DrawBuildableStatus( void )
+{
+ int i;
+ centity_t *cent;
+ entityState_t *es;
+
+ switch( cg.predictedPlayerState.weapon )
{
- VectorMA( origin, 15.0f, right, origin2 );
- VectorMA( origin2, HEALTH_BAR_HEIGHT + 5.0f, down, origin2 );
- VectorScale( right, HEALTH_BAR_WIDTH / 2.0f - 5.0f, rightLength );
- VectorScale( down, HEALTH_BAR_WIDTH / 2.0f - 5.0f, downLength );
- CG_DrawPlane( origin2, downLength, rightLength, cgs.media.noPowerShader );
+ case WP_ABUILD:
+ case WP_ABUILD2:
+ case WP_HBUILD:
+ case WP_HBUILD2:
+ for( i = 0; i < cg.snap->numEntities; i++ )
+ {
+ cent = &cg_entities[ cg.snap->entities[ i ].number ];
+ es = &cent->currentState;
+
+ if( es->eType == ET_BUILDABLE &&
+ BG_FindTeamForBuildable( es->modelindex ) ==
+ BG_FindTeamForWeapon( cg.predictedPlayerState.weapon ) )
+ CG_BuildableStatusDisplay( cent );
+ }
+ break;
+
+ default:
+ break;
}
}
@@ -993,21 +1030,6 @@ void CG_Buildable( centity_t *cent )
trap_R_AddRefEntityToScene( &turretTop );
}
- switch( cg.predictedPlayerState.weapon )
- {
- case WP_ABUILD:
- case WP_ABUILD2:
- case WP_HBUILD:
- case WP_HBUILD2:
- if( BG_FindTeamForBuildable( es->modelindex ) ==
- BG_FindTeamForWeapon( cg.predictedPlayerState.weapon ) )
- CG_BuildableHealthBar( cent );
- break;
-
- default:
- break;
- }
-
//weapon effects for turrets
if( es->eFlags & EF_FIRING )
{
@@ -1036,8 +1058,8 @@ void CG_Buildable( centity_t *cent )
trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound );
}
- health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT );
- healthScale = (float)health / B_HEALTH_SCALE;
+ health = es->generic1 & B_HEALTH_MASK;
+ healthScale = (float)health / B_HEALTH_MASK;
if( healthScale < cent->lastBuildableHealthScale && ( es->generic1 & B_SPAWNED_TOGGLEBIT ) )
{
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 4bcec5b3..43f5e0fc 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -3345,6 +3345,7 @@ static void CG_Draw2D( void )
Menu_Paint( menu, qtrue );
CG_DrawCrosshair( );
+ CG_DrawBuildableStatus( );
}
else if( cg_drawStatus.integer )
Menu_Paint( defaultMenu, qtrue );
diff --git a/src/cgame/cg_drawtools.c b/src/cgame/cg_drawtools.c
index a1b99a5f..3151f66f 100644
--- a/src/cgame/cg_drawtools.c
+++ b/src/cgame/cg_drawtools.c
@@ -285,8 +285,6 @@ void CG_TileClear( void )
CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader );
}
-
-
/*
================
CG_FadeColor
@@ -315,3 +313,36 @@ float *CG_FadeColor( int startMsec, int totalMsec )
return color;
}
+
+/*
+================
+CG_WorldToScreen
+================
+*/
+qboolean CG_WorldToScreen( vec3_t point, float *x, float *y )
+{
+ vec3_t trans;
+ float xc, yc;
+ float px, py;
+ float z;
+
+ px = tan( cg.refdef.fov_x * M_PI / 360.0 );
+ py = tan( cg.refdef.fov_y * M_PI / 360.0 );
+
+ VectorSubtract( point, cg.refdef.vieworg, trans );
+
+ xc = 640.0f / 2.0f;
+ yc = 480.0f / 2.0f;
+
+ z = DotProduct( trans, cg.refdef.viewaxis[ 0 ] );
+ if( z <= 0.001f )
+ return qfalse;
+
+ if( x )
+ *x = xc - DotProduct( trans, cg.refdef.viewaxis[ 1 ] ) * xc / ( z * px );
+
+ if( y )
+ *y = yc - DotProduct( trans, cg.refdef.viewaxis[ 2 ] ) * yc / ( z * py );
+
+ return qtrue;
+}
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 2f61e4a4..613dc98a 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1291,11 +1291,10 @@ typedef struct
qboolean localServer; // detected on startup by checking sv_running
// parsed from serverinfo
- int dmflags;
- int teamflags;
int timelimit;
int maxclients;
char mapname[ MAX_QPATH ];
+ qboolean markDeconstruct; // Whether or not buildables are marked
int voteTime;
int voteYes;
diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c
index bb0daabb..ed677779 100644
--- a/src/cgame/cg_servercmds.c
+++ b/src/cgame/cg_servercmds.c
@@ -115,6 +115,7 @@ void CG_ParseServerinfo( void )
info = CG_ConfigString( CS_SERVERINFO );
cgs.timelimit = atoi( Info_ValueForKey( info, "timelimit" ) );
cgs.maxclients = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
+ cgs.markDeconstruct = atoi( Info_ValueForKey( info, "g_markDeconstruct" ) );
mapname = Info_ValueForKey( info, "mapname" );
Com_sprintf( cgs.mapname, sizeof( cgs.mapname ), "maps/%s.bsp", mapname );
}
diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c
index 350d3156..ddc4cbcb 100644
--- a/src/cgame/cg_tutorial.c
+++ b/src/cgame/cg_tutorial.c
@@ -157,8 +157,8 @@ static entityState_t *CG_BuildableInRange( playerState_t *ps, float *healthFract
if( healthFraction )
{
- health = es->generic1 & ~( B_POWERED_TOGGLEBIT | B_DCCED_TOGGLEBIT | B_SPAWNED_TOGGLEBIT );
- *healthFraction = (float)health / B_HEALTH_SCALE;
+ health = es->generic1 & B_HEALTH_MASK;
+ *healthFraction = (float)health / B_HEALTH_MASK;
}
if( es->eType == ET_BUILDABLE &&
@@ -175,7 +175,8 @@ CG_AlienBuilderText
*/
static void CG_AlienBuilderText( char *text, playerState_t *ps )
{
- buildable_t buildable = ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT;
+ buildable_t buildable = ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT;
+ entityState_t *es;
if( buildable > BA_NONE )
{
@@ -195,11 +196,29 @@ static void CG_AlienBuilderText( char *text, playerState_t *ps )
va( "Press %s to build a structure\n",
CG_KeyNameForCommand( "+attack" ) ) );
- if( CG_BuildableInRange( ps, NULL ) )
+ if( ( es = CG_BuildableInRange( ps, NULL ) ) )
{
- Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to destroy this structure\n",
- CG_KeyNameForCommand( "deconstruct" ) ) );
+ if( cgs.markDeconstruct )
+ {
+ if( es->generic1 & B_MARKED_TOGGLEBIT )
+ {
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to unmark this structure\n",
+ CG_KeyNameForCommand( "deconstruct" ) ) );
+ }
+ else
+ {
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to mark this structure\n",
+ CG_KeyNameForCommand( "deconstruct" ) ) );
+ }
+ }
+ else
+ {
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to destroy this structure\n",
+ CG_KeyNameForCommand( "deconstruct" ) ) );
+ }
}
}