/* ================ CG_FadeColor ================ */ Color::Color CG_FadeColor( int startMsec, int totalMsec ) { int t; if ( startMsec == 0 ) { return Color::White; } t = cg.time - startMsec; if ( t >= totalMsec ) { return Color::White; } Color::Color color = Color::White; // fade out if ( totalMsec - t < FADE_TIME ) { color.SetAlpha( ( totalMsec - t ) * 1.0 / FADE_TIME ); } return color; }
/* =============== CG_PainBlend =============== */ static void CG_PainBlend() { int damage; float damageAsFracOfMax; qhandle_t shader = cgs.media.viewBloodShader; float x, y, w, h; float s1, t1, s2, t2; if ( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT || cg.intermissionStarted ) { return; } damage = cg.lastHealth - cg.snap->ps.stats[ STAT_HEALTH ]; if ( damage < 0 ) { damage = 0; } damageAsFracOfMax = ( float ) damage / cg.snap->ps.stats[ STAT_MAX_HEALTH ]; cg.lastHealth = cg.snap->ps.stats[ STAT_HEALTH ]; cg.painBlendValue += damageAsFracOfMax * cg_painBlendScale.value; if ( cg.painBlendValue > 0.0f ) { cg.painBlendValue -= ( cg.frametime / 1000.0f ) * cg_painBlendDownRate.value; } if ( cg.painBlendValue > 1.0f ) { cg.painBlendValue = 1.0f; } else if ( cg.painBlendValue <= 0.0f ) { cg.painBlendValue = 0.0f; return; } Color::Color color; if ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_ALIENS ) { color = { 0.43f, 0.8f, 0.37f }; } else if ( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_HUMANS ) { color = { 0.8f, 0.0f, 0.0f }; } if ( cg.painBlendValue > cg.painBlendTarget ) { cg.painBlendTarget += ( cg.frametime / 1000.0f ) * cg_painBlendUpRate.value; } else if ( cg.painBlendValue < cg.painBlendTarget ) { cg.painBlendTarget = cg.painBlendValue; } if ( cg.painBlendTarget > cg_painBlendMax.value ) { cg.painBlendTarget = cg_painBlendMax.value; } color.SetAlpha( cg.painBlendTarget ); trap_R_SetColor( color ); //left x = 0.0f; y = 0.0f; w = PAINBLEND_BORDER * 640.0f; h = 480.0f; CG_AdjustFrom640( &x, &y, &w, &h ); s1 = 0.0f; t1 = 0.0f; s2 = PAINBLEND_BORDER; t2 = 1.0f; CG_ScalePainBlendTCs( &s1, &t1, &s2, &t2 ); trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, shader ); //right x = 640.0f - ( PAINBLEND_BORDER * 640.0f ); y = 0.0f; w = PAINBLEND_BORDER * 640.0f; h = 480.0f; CG_AdjustFrom640( &x, &y, &w, &h ); s1 = 1.0f - PAINBLEND_BORDER; t1 = 0.0f; s2 = 1.0f; t2 = 1.0f; CG_ScalePainBlendTCs( &s1, &t1, &s2, &t2 ); trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, shader ); //top x = PAINBLEND_BORDER * 640.0f; y = 0.0f; w = 640.0f - ( 2 * PAINBLEND_BORDER * 640.0f ); h = PAINBLEND_BORDER * 480.0f; CG_AdjustFrom640( &x, &y, &w, &h ); s1 = PAINBLEND_BORDER; t1 = 0.0f; s2 = 1.0f - PAINBLEND_BORDER; t2 = PAINBLEND_BORDER; CG_ScalePainBlendTCs( &s1, &t1, &s2, &t2 ); trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, shader ); //bottom x = PAINBLEND_BORDER * 640.0f; y = 480.0f - ( PAINBLEND_BORDER * 480.0f ); w = 640.0f - ( 2 * PAINBLEND_BORDER * 640.0f ); h = PAINBLEND_BORDER * 480.0f; CG_AdjustFrom640( &x, &y, &w, &h ); s1 = PAINBLEND_BORDER; t1 = 1.0f - PAINBLEND_BORDER; s2 = 1.0f - PAINBLEND_BORDER; t2 = 1.0f; CG_ScalePainBlendTCs( &s1, &t1, &s2, &t2 ); trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, shader ); trap_R_ClearColor(); }
static void CG_DrawBeacon( cbeacon_t *b ) { float angle; // Don't draw clamped beacons for tags, except for enemy players. if( b->type == BCT_TAG && b->clamped && !( ( b->flags & EF_BC_ENEMY ) && ( b->flags & EF_BC_TAG_PLAYER ) ) ) return; Color::Color color = b->color; if( !( BG_Beacon( b->type )->flags & BCF_IMPORTANT ) ) color.SetAlpha( color.Alpha() * cgs.bc.hudAlpha ); else color.SetAlpha( color.Alpha() * cgs.bc.hudAlphaImportant ); trap_R_SetColor( color ); trap_R_DrawStretchPic( b->pos[ 0 ] - b->size/2, b->pos[ 1 ] - b->size/2, b->size, b->size, 0, 0, 1, 1, CG_BeaconIcon( b ) ); if( b->flags & EF_BC_DYING ) trap_R_DrawStretchPic( b->pos[ 0 ] - b->size/2 * 1.3, b->pos[ 1 ] - b->size/2 * 1.3, b->size * 1.3, b->size * 1.3, 0, 0, 1, 1, cgs.media.beaconNoTarget ); if ( b->clamped ) trap_R_DrawRotatedPic( b->pos[ 0 ] - b->size/2 * 1.5, b->pos[ 1 ] - b->size/2 * 1.5, b->size * 1.5, b->size * 1.5, 0, 0, 1, 1, cgs.media.beaconIconArrow, 270.0 - ( angle = atan2( b->clamp_dir[ 1 ], b->clamp_dir[ 0 ] ) ) * 180 / M_PI ); if( b->type == BCT_TIMER ) { int num; num = ( BEACON_TIMER_TIME + b->ctime - cg.time ) / 100; if( num > 0 ) { float h, tw; const char *p; vec2_t pos, dir, rect[ 2 ]; int i, l, frame; h = b->size * 0.4; p = va( "%d", num ); l = strlen( p ); tw = h * l; if( !b->clamped ) { pos[ 0 ] = b->pos[ 0 ]; pos[ 1 ] = b->pos[ 1 ] + b->size/2 + h/2; } else { rect[ 0 ][ 0 ] = b->pos[ 0 ] - b->size/2 - tw/2; rect[ 1 ][ 0 ] = b->pos[ 0 ] + b->size/2 + tw/2; rect[ 0 ][ 1 ] = b->pos[ 1 ] - b->size/2 - h/2; rect[ 1 ][ 1 ] = b->pos[ 1 ] + b->size/2 + h/2; for( i = 0; i < 2; i++ ) dir[ i ] = - b->clamp_dir[ i ]; ProjectPointOntoRectangleOutwards( pos, b->pos, dir, (const vec2_t*)rect ); } pos[ 0 ] -= tw/2; pos[ 1 ] -= h/2; for( i = 0; i < l; i++ ) { if( p[ i ] >= '0' && p[ i ] <= '9' ) frame = p[ i ] - '0'; else if( p[ i ] == '-' ) frame = STAT_MINUS; else frame = -1; if( frame != -1 ) trap_R_DrawStretchPic( pos[ 0 ], pos[ 1 ], h, h, 0, 0, 1, 1, cgs.media.numberShaders[ frame ] ); pos[ 0 ] += h; } } } trap_R_ClearColor(); }
/* ================ CG_DrawRangeMarker ================ */ void CG_DrawRangeMarker( rangeMarker_t rmType, const vec3_t origin, float range, const vec3_t angles, Color::Color rgba ) { if ( cg_rangeMarkerDrawSurface.integer ) { qhandle_t pcsh; pcsh = cgs.media.plainColorShader; rgba.SetAlpha( rgba.Alpha() * Com_Clamp( 0.0f, 1.0f, cg_rangeMarkerSurfaceOpacity.value ) ); switch( rmType ) { case RM_SPHERE: CG_DrawSphere( origin, range, pcsh, rgba ); break; case RM_SPHERICAL_CONE_64: CG_DrawSphericalCone( origin, angles, range, false, pcsh, rgba ); break; case RM_SPHERICAL_CONE_240: CG_DrawSphericalCone( origin, angles, range, true, pcsh, rgba ); break; } } if ( cg_rangeMarkerDrawIntersection.integer || cg_rangeMarkerDrawFrontline.integer ) { float lineOpacity, lineThickness; const cgMediaBinaryShader_t *mbsh; cgBinaryShaderSetting_t *bshs; if ( cg.numBinaryShadersUsed >= NUM_BINARY_SHADERS ) { return; } lineOpacity = Com_Clamp( 0.0f, 1.0f, cg_rangeMarkerLineOpacity.value ); lineThickness = cg_rangeMarkerLineThickness.value; if ( lineThickness < 0.0f ) lineThickness = 0.0f; mbsh = &cgs.media.binaryShaders[ cg.numBinaryShadersUsed ]; if ( rmType == RM_SPHERE ) { if ( range > lineThickness / 2 ) { if ( cg_rangeMarkerDrawIntersection.integer ) { CG_DrawSphere( origin, range - lineThickness / 2, mbsh->b1, Color::White ); } CG_DrawSphere( origin, range - lineThickness / 2, mbsh->f2, Color::White ); } if ( cg_rangeMarkerDrawIntersection.integer ) { CG_DrawSphere( origin, range + lineThickness / 2, mbsh->b2, Color::White ); } CG_DrawSphere( origin, range + lineThickness / 2, mbsh->f1, Color::White ); } else { bool t2; float f, r; vec3_t forward, tip; t2 = ( rmType == RM_SPHERICAL_CONE_240 ); f = lineThickness * ( t2 ? 0.26f : 0.8f ); r = f + lineThickness * ( t2 ? 0.23f : 0.43f ); AngleVectors( angles, forward, nullptr, nullptr ); if ( range > r ) { VectorMA( origin, f, forward, tip ); if ( cg_rangeMarkerDrawIntersection.integer ) { CG_DrawSphericalCone( tip, angles, range - r, t2, mbsh->b1, Color::White ); } CG_DrawSphericalCone( tip, angles, range - r, t2, mbsh->f2, Color::White ); } VectorMA( origin, -f, forward, tip ); if ( cg_rangeMarkerDrawIntersection.integer ) { CG_DrawSphericalCone( tip, angles, range + r, t2, mbsh->b2, Color::White ); } CG_DrawSphericalCone( tip, angles, range + r, t2, mbsh->f1, Color::White ); } bshs = &cg.binaryShaderSettings[ cg.numBinaryShadersUsed ]; bshs->color = rgba * lineOpacity; bshs->drawIntersection = !!cg_rangeMarkerDrawIntersection.integer; bshs->drawFrontline = !!cg_rangeMarkerDrawFrontline.integer; ++cg.numBinaryShadersUsed; } }