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; } }