diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2015-04-03 03:50:41 +0200 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2015-04-03 03:50:41 +0200 |
commit | 0d5460522ba3651da1ed5630f7f8a784c5eb6514 (patch) | |
tree | 143e3cae332ef6a31957d222fb9b9ed8e27e9f06 /src | |
parent | e6735d21e17ecbbe03607046ded443516b65c3a7 (diff) |
Initial implementation of health bars.
Diffstat (limited to 'src')
-rw-r--r-- | src/cgame/cg_draw.c | 120 | ||||
-rw-r--r-- | src/game/g_active.c | 4 |
2 files changed, 123 insertions, 1 deletions
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index d8b411c..340a207 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -3836,7 +3836,7 @@ static void CG_DrawWarmup( void ) /* ================= -CG_DrawWarmup +Damage blobs ================= */ @@ -3968,6 +3968,123 @@ static void CG_DrawDamageBlobs( void ) trap_R_SetColor( NULL ); } +/* +================= +Health bars +================= +*/ +typedef struct +{ + vec3_t origin; + float dist; + + int value; + int max; +} healthBar_t; + +static int CompareHealthBars( const healthBar_t *a, const healthBar_t *b ) +{ + return a->dist < b->dist; +} + +static void CG_DrawHealthBars( void ) +{ + int i; + healthBar_t *bar, *bare, bars[ MAX_ENTITIES_IN_SNAPSHOT ]; + + for( bar = bars, i = 0; i < cg.snap->numEntities; i++ ) + { + int j; + centity_t *cent; + entityState_t *es; + trace_t tr; + vec3_t mins, maxs; + + cent = cg_entities + cg.snap->entities[ i ].number; + es = ¢->currentState; + + if( es->eFlags & EF_DEAD ) + continue; + + switch( es->eType ) + { + case ET_BUILDABLE: + bar->value = es->generic1; + bar->max = BG_Buildable( es->modelindex )->health; + BG_BuildableBoundingBox( es->modelindex, mins, maxs ); + break; + + case ET_PLAYER: + bar->value = es->otherEntityNum2; + bar->max = BG_Class( ( es->misc >> 8 ) & 0xFF )->health; + BG_ClassBoundingBox( ( es->misc >> 8 ) & 0xFF, mins, maxs, NULL, NULL, NULL ); + break; + + default: + continue; + } + + for( j = 0; j < 3; j++ ) + bar->origin[ j ] = cent->lerpOrigin[ j ] + ( maxs[ j ] + mins[ j ] ) / 2.0f; + + CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL, bar->origin, ENTITYNUM_NONE, MASK_SOLID ); + + if( tr.fraction < 1.0f ) + continue; + + bar->dist = Distance( bar->origin, cg.refdef.vieworg ); + + bar++; + } + + bare = bar; + qsort( bars, bare - bars, sizeof( healthBar_t ), + (int(*)(const void*,const void*))CompareHealthBars ); + +/* + TODO: figure out why qsort fails for more than 5 bars + + for( i = 0; i < bare - bars - 1; i++ ) + if( CompareHealthBars( bars + i, bars + i + 1 ) ) + { + Com_Printf( "qsort is retarded\n" ); + break; + } +*/ + + for( bar = bars; bar < bare; bar++ ) + { + float x, y, w, h, hf; + char buffer[ 64 ]; + vec4_t color; + + if( !CG_WorldToScreen( bar->origin, &x, &y ) ) + continue; + + hf = (float)bar->value / bar->max; + + h = 20 * 100 / bar->dist; + w = 4 * h * cgDC.aspectScale; + + Com_sprintf( buffer, sizeof( buffer ), "%d", bar->value ); + + color[ 3 ] = 1.0f; + + VectorSet( color, 0.1, 0.7, 0.1 ); + trap_R_SetColor( color ); + CG_DrawPic( x - w/2, y - h/2, w * hf, h, cgs.media.whiteShader ); + + VectorSet( color, 0.7, 0.1, 0.1 ); + trap_R_SetColor( color ); + CG_DrawPic( x - w/2 + w * hf, y - h/2, w * ( 1 - hf ), h, cgs.media.whiteShader ); + + VectorSet( color, 0, 0, 0 ); + trap_R_SetColor( color ); + CG_DrawNumber( x, y, h, buffer ); + } +} + + //================================================================================== /* @@ -4019,6 +4136,7 @@ static void CG_Draw2D( void ) } CG_DrawDamageBlobs( ); + CG_DrawHealthBars( ); if( !menu ) { diff --git a/src/game/g_active.c b/src/game/g_active.c index 90c47c4..2eede6b 100644 --- a/src/game/g_active.c +++ b/src/game/g_active.c @@ -2236,6 +2236,7 @@ void ClientThink( int clientNum ) void G_RunClient( gentity_t *ent ) { + // send all buffered damage blobs if( ent->client->bufferedBlobCount ) { int i; @@ -2275,6 +2276,9 @@ void G_RunClient( gentity_t *ent ) ent->client->bufferedBlobCount = 0; } + // update the public health field + ent->s.otherEntityNum2 = MAX( 0, ent->client->ps.stats[ STAT_HEALTH ] ); + // Run a client think when there are no commands for a time if( !g_synchronousClients.integer && ( g_friendlyFreeze.integer < 100 || |