/* * SCR_DrawChallengers */ static int SCR_DrawChallengers( const char **ptrptr, int x, int y, int panelWidth, struct qfontface_s *font, int pass ) { const char *token; char string[MAX_STRING_CHARS]; int yoffset = 0, xoffset = 0; int playerNum, ping; int height; assert( ptrptr && *ptrptr ); height = trap_SCR_FontHeight( font ); // draw title yoffset = height; if( pass ) { trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, CG_TranslateString( "Challengers" ), font, colorCyan ); } yoffset += height; // draw challengers while( *ptrptr ) { if( !SCR_ParseToken( ptrptr, &token ) ) break; // first token is played id playerNum = atoi( token ); if( playerNum < 0 || playerNum >= gs.maxclients ) break; // get a second token if( !SCR_ParseToken( ptrptr, &token ) ) break; // second token is ping ping = atoi( token ); // draw the challenger if( ping < 0 ) Q_snprintfz( string, sizeof( string ), "%s%s ...", cgs.clientInfo[playerNum].name, S_COLOR_WHITE ); else Q_snprintfz( string, sizeof( string ), "%s%s %i", cgs.clientInfo[playerNum].name, S_COLOR_WHITE, ping ); if( pass ) { trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, string, font, colorWhite ); } yoffset += height; } yoffset += height; return yoffset; }
/* * CG_DrawEntityNumbers */ static void CG_DrawEntityNumbers( void ) { float zfar = 2048; int i, entnum; centity_t *cent; vec2_t coords; vec3_t dir; float dist; trace_t trace; vec3_t eorigin; int shadowOffset = max( 1, cgs.vidHeight / 600 ); for( i = 0; i < cg.frame.numEntities; i++ ) { entnum = cg.frame.parsedEntities[i & ( MAX_PARSE_ENTITIES - 1 )].number; if( entnum < 1 || entnum >= MAX_EDICTS ) { continue; } cent = &cg_entities[entnum]; if( cent->serverFrame != cg.frame.serverFrame ) { continue; } if( !cent->current.modelindex ) { continue; } // Kill if behind the view VectorLerp( cent->prev.origin, cg.lerpfrac, cent->current.origin, eorigin ); VectorSubtract( eorigin, cam_origin, dir ); dist = VectorNormalize2( dir, dir ) * cg.view.fracDistFOV; if( dist > zfar ) { continue; } if( DotProduct( dir, &cg.view.axis[AXIS_FORWARD] ) < 0 ) { continue; } CG_Trace( &trace, cam_origin, vec3_origin, vec3_origin, eorigin, cent->current.number, MASK_OPAQUE ); if( trace.fraction == 1.0f ) { // find the 3d point in 2d screen trap_R_TransformVectorToScreen( &cg.view.refdef, eorigin, coords ); if( ( coords[0] < 0 || coords[0] > cgs.vidWidth ) || ( coords[1] < 0 || coords[1] > cgs.vidHeight ) ) { return; } trap_SCR_DrawString( coords[0] + shadowOffset, coords[1] + shadowOffset, ALIGN_LEFT_MIDDLE, va( "%i", cent->current.number ), cgs.fontSystemSmall, colorBlack ); trap_SCR_DrawString( coords[0], coords[1], ALIGN_LEFT_MIDDLE, va( "%i", cent->current.number ), cgs.fontSystemSmall, colorWhite ); } } }
/* * CG_DrawScoreboard */ void CG_DrawScoreboard( void ) { int pass; const char *ptr, *token, *layout; char title[MAX_CONFIGSTRING_CHARS], type; int team = TEAM_PLAYERS; int xpos; int ypos, yoffset, maxyoffset; struct qfontface_s *font; struct qfontface_s *monofont; struct qfontface_s *titlefont; int width, panelWidth; vec4_t whiteTransparent = { 1.0f, 1.0f, 1.0f, 0.5f }; // no layout defined if( !cgs.configStrings[CS_SCB_PLAYERTAB_LAYOUT][0] ) return; if( scoreboardString[0] != '&' ) // nothing to draw return; font = CG_ScoreboardFont( cg_scoreboardFontFamily, cg_scoreboardFontSize ); monofont = CG_ScoreboardFont( cg_scoreboardMonoFontFamily, cg_scoreboardFontSize ); titlefont = CG_ScoreboardFont( cg_scoreboardTitleFontFamily, cg_scoreboardTitleFontSize ); xpos = (int)( cgs.vidWidth * 0.5 ); ypos = (int)( cgs.vidHeight * 0.2 ) - 24 * cgs.vidHeight / 600; // draw title Q_strncpyz( title, cgs.configStrings[CS_GAMETYPETITLE], sizeof( title ) ); if( !title[0] ) Q_strncpyz( title, gs.gametypeName, sizeof( title ) ); Q_strupr( title ); trap_SCR_DrawString( xpos, ypos, ALIGN_CENTER_TOP, title, titlefont, whiteTransparent ); ypos += trap_SCR_FontHeight( titlefont ); trap_SCR_DrawStringWidth( xpos, ypos, ALIGN_CENTER_TOP, cgs.configStrings[CS_HOSTNAME], cgs.vidWidth*0.75, font, whiteTransparent ); ypos += trap_SCR_FontHeight( font ); // calculate the panel width from the layout panelWidth = 0; layout = cgs.configStrings[CS_SCB_PLAYERTAB_LAYOUT]; while( SCR_GetNextColumnLayout( &layout, NULL, &type, &width, font ) != NULL ) { if( !SCR_SkipColumn( type ) ) panelWidth += width; } // parse and draw the scoreboard message for ( pass = 0; pass < 2; pass++ ) { yoffset = 0; maxyoffset = 0; scr_numplayericons = 0; ptr = scoreboardString; while ( ptr ) { token = COM_ParseExt( &ptr, true ); if ( token[0] != '&' ) break; if ( !Q_stricmp( token, "&t" ) ) // team tab { yoffset = 0; yoffset += SCR_DrawTeamTab( &ptr, &team, xpos, ypos + yoffset, panelWidth, font, titlefont, pass ); } else if ( !Q_stricmp( token, "&p" ) ) // player tab { yoffset += SCR_DrawPlayerTab( &ptr, team, xpos, ypos + yoffset, panelWidth, font, pass ); } else if ( !Q_stricmp( token, "&w" ) ) // list of challengers { if ( yoffset < maxyoffset ) yoffset = maxyoffset; maxyoffset += SCR_DrawChallengers( &ptr, xpos, ypos + yoffset, panelWidth, font, pass ); } else if ( !Q_stricmp( token, "&s" ) ) // list of spectators { if ( yoffset < maxyoffset ) yoffset = maxyoffset; maxyoffset += SCR_DrawSpectators( &ptr, xpos, ypos + yoffset, panelWidth, font, true, "Spectators", colorYellow, pass ); } else if( !Q_stricmp( token, "&y" ) ) // list of chasers { if( yoffset < maxyoffset ) yoffset = maxyoffset; if( cg_showChasers->integer ) maxyoffset += SCR_DrawSpectators( &ptr, xpos, ypos + yoffset, panelWidth, font, false, "Chasers", colorOrange, pass ); else SCR_IgnoreSpectators( &ptr, false ); } if ( yoffset > maxyoffset ) maxyoffset = yoffset; } if( !pass ) SCR_DrawPlayerIcons( font ); } // add the player stats yoffset = maxyoffset + trap_SCR_FontHeight( font ); yoffset += SCB_DrawPlayerStats( xpos, ypos + yoffset, monofont ); }
/* * SCR_DrawSpectators */ static int SCR_DrawSpectators( const char **ptrptr, int x, int y, int panelWidth, struct qfontface_s *font, bool havePing, const char *title, vec4_t titleColor, int pass ) { const char *token; char string[MAX_STRING_CHARS]; int yoffset = 0, xoffset = 0; int playerNum, ping; int aligns[3], offsets[3]; int colwidth, fullwidth, count = 0, height; bool titleDrawn = false; fullwidth = panelWidth * 1.5; if( fullwidth > cgs.vidWidth * 0.7 ) fullwidth = cgs.vidWidth * 0.7; colwidth = fullwidth / 3; aligns[0] = ALIGN_CENTER_TOP; aligns[1] = ALIGN_LEFT_TOP; aligns[2] = ALIGN_RIGHT_TOP; offsets[0] = 0; offsets[1] = -fullwidth * 0.5; offsets[2] = fullwidth * 0.5; assert( ptrptr && *ptrptr ); height = trap_SCR_FontHeight( font ); yoffset = height; // draw spectators while( *ptrptr ) { if( !SCR_ParseToken( ptrptr, &token ) ) break; // first token is played id playerNum = atoi( token ); if( playerNum < 0 || playerNum >= gs.maxclients ) break; if( havePing ) { // get a second token if( !SCR_ParseToken( ptrptr, &token ) ) break; // second token is ping ping = atoi( token ); // draw the spectator if( ping < 0 ) Q_snprintfz( string, sizeof( string ), "%s%s ...", cgs.clientInfo[playerNum].name, S_COLOR_WHITE ); else Q_snprintfz( string, sizeof( string ), "%s%s %i", cgs.clientInfo[playerNum].name, S_COLOR_WHITE, ping ); } else { Q_snprintfz( string, sizeof( string ), "%s%s", cgs.clientInfo[playerNum].name, S_COLOR_WHITE ); } // draw title if there are any spectators if( !titleDrawn ) { titleDrawn = true; if( pass ) { trap_SCR_DrawString( x, y + yoffset, ALIGN_CENTER_TOP, CG_TranslateString( title ), font, titleColor ); } yoffset += height; } xoffset = offsets[count] + CG_HorizontalAlignForWidth( 0, aligns[count], trap_SCR_strWidth( string, font, 0 ) ); if ( pass ) { // fixme: the boxes aren't actually correctly aligned trap_SCR_DrawClampString( x + xoffset, y + yoffset, string, x + xoffset, y + yoffset, x + xoffset + colwidth, y + yoffset + height, font, colorWhite ); } count++; if( count > 2 ) { count = 0; yoffset += height; } } if( count ) yoffset += height; return yoffset; }
//================ //CG_DrawMiniMap //================ void CG_DrawMiniMap( int x, int y, int iw, int ih, qboolean draw_playernames, qboolean draw_itemnames, int align, vec4_t color ) { int i, entnum; centity_t *cent; vec3_t coords; vec4_t tmp_col, tmp_white_alpha, tmp_yellow_alpha; // background color of the map vec3_t mins, maxs, extend; int map_w, map_h, map_z; int x_lefttop, y_lefttop, z_lefttop; // the negative y coordinate (bottom of the map) float map_div_w, map_div_h; qboolean isSelf; if( !cg_showminimap->integer ) return; // if inside a team if( cg.predictedPlayerState.stats[STAT_REALTEAM] >= TEAM_PLAYERS && cg.predictedPlayerState.stats[STAT_REALTEAM] < GS_MAX_TEAMS ) { if( !GS_CanShowMinimap() || !( cg_showminimap->integer & 1 ) ) return; } else if( !( cg_showminimap->integer & 2 ) ) { // allow only when chasing a player and the player is allowed to see it if( !GS_CanShowMinimap() || !( cg_showminimap->integer & 1 ) || cg.predictedPlayerState.stats[STAT_REALTEAM] == cg.predictedPlayerState.stats[STAT_TEAM] ) return; } if( !cgs.shaderMiniMap ) return; x = CG_HorizontalAlignForWidth( x, align, iw ); y = CG_VerticalAlignForHeight( y, align, ih ); Vector4Copy( color, tmp_col ); Vector4Copy( colorWhite, tmp_white_alpha ); Vector4Copy( colorYellow, tmp_yellow_alpha ); tmp_white_alpha[3] = color[3]; tmp_yellow_alpha[3] = color[3]; // Get Worldmodel bounds... trap_R_ModelBounds( NULL, mins, maxs ); // NULL for world model... // make it a square bounding box VectorSubtract( maxs, mins, extend ); if( extend[1] > extend[0] ) { mins[0] -= ( extend[1] - extend[0] ) * 0.5; maxs[0] += ( extend[1] - extend[0] ) * 0.5; } else { mins[1] -= ( extend[0] - extend[1] ) * 0.5; maxs[1] += ( extend[0] - extend[1] ) * 0.5; } map_w = maxs[0] - mins[0]; // map width (in game units) map_h = maxs[1] - mins[1]; map_z = maxs[2] - mins[2]; x_lefttop = -mins[0]; // the negative x coordinate ( left of the map ) y_lefttop = -mins[1]; // the negative y coordinate (bottom of the map) z_lefttop = -mins[2]; // the negative y coordinate (bottom of the map) map_div_w = (float)map_w / (float)iw; map_div_h = (float)map_h / (float)ih; CG_DrawHUDRect( x, y, ALIGN_LEFT_TOP, iw, ih, 1, 1, tmp_col, cgs.shaderMiniMap ); //alignment test, to display green dot at 0,0 //CG_DrawHUDRect( x + x_lefttop/map_div_w -1, y + y_lefttop/map_div_h -1,ALIGN_LEFT_TOP,3,3,1,1, colorGreen, CG_MediaShader( cgs.media.shaderMiniMap ) ); for( i = 0; i < cg.frame.numEntities; i++ ) { entnum = cg.frame.parsedEntities[i&( MAX_PARSE_ENTITIES-1 )].number; // filter invalid ents if( entnum < 1 || entnum >= MAX_EDICTS ) continue; // retrieve the centity_t cent = &cg_entities[entnum]; isSelf = ( (unsigned)entnum == cg.predictedPlayerState.POVnum ); if( ( cent->current.type != ET_PLAYER ) && ( cent->current.type != ET_MINIMAP_ICON ) && !( cent->item ) ) continue; if( isSelf ) VectorCopy( cg.predictedPlayerState.pmove.origin, coords ); else VectorCopy( cent->current.origin, coords ); coords[0] = ( coords[0] + x_lefttop ) / map_div_w; coords[1] = ih - ( coords[1] + y_lefttop ) / map_div_h; coords[2] = ( coords[2] + (float)z_lefttop ) / (float)map_z; // is it a player? if( ( cent->current.type == ET_PLAYER ) ) { int box_size = (int)( 3.0 + coords[2] * 10.0 ); // check if we're allowed to see team members only (coaches, CA) if( cg.predictedPlayerState.stats[STAT_LAYOUTS] & STAT_LAYOUT_SPECTEAMONLY || (cg.predictedPlayerState.stats[STAT_REALTEAM] != TEAM_SPECTATOR && GS_TeamOnlyMinimap()) ) { if( cg.predictedPlayerState.stats[STAT_REALTEAM] != cent->current.team ) continue; } if( cent->current.team == TEAM_SPECTATOR ) { if( entnum != cg.view.POVent ) continue; VectorSet( tmp_col, 1, 1, 1 ); } else { CG_TeamColor( cent->current.team, tmp_col ); } // get color tmp_col[3] = bound( 0, color[3] + 0.3f, 1 ); CG_DrawHUDRect( x + (int)coords[0] -box_size/2, y + (int)coords[1] -box_size/2, ALIGN_LEFT_TOP, box_size, box_size, box_size, box_size, tmp_col, NULL ); // differentiate ourselves with an arrow if( isSelf ) { int thisX, thisY, thisSize; thisSize = max( box_size, 8 ); thisX = CG_VerticalAlignForHeight( x + (int)coords[0], ALIGN_CENTER_MIDDLE, thisSize ); thisY = CG_VerticalAlignForHeight( y + (int)coords[1] - thisSize, ALIGN_CENTER_MIDDLE, thisSize ); trap_R_DrawStretchPic( thisX, thisY, thisSize, thisSize, 0, 0, 1, 1, tmp_yellow_alpha, CG_MediaShader( cgs.media.shaderDownArrow ) ); } // do we want names too? if( draw_playernames == qtrue ) trap_SCR_DrawString( x + (int)coords[0] + 8, y + (int)coords[1] - 4, ALIGN_LEFT_TOP, COM_RemoveColorTokensExt( cgs.clientInfo[cent->current.number-1].name, qtrue ), cgs.fontSystemSmall, tmp_yellow_alpha ); } else if( cent->current.type == ET_MINIMAP_ICON ) { if( cent->ent.customShader ) { vec4_t tmp_this_color; int thisX, thisY, thisSize; thisSize = (float)cent->prev.frame + (float)( cent->current.frame - cent->prev.frame ) * cg.lerpfrac; if( thisSize <= 0 ) thisSize = 18; tmp_this_color[0] = (float)cent->ent.shaderRGBA[0] / 255.0f; tmp_this_color[1] = (float)cent->ent.shaderRGBA[1] / 255.0f; tmp_this_color[2] = (float)cent->ent.shaderRGBA[2] / 255.0f; tmp_this_color[3] = 1.0f; thisX = CG_VerticalAlignForHeight( x + coords[0], ALIGN_CENTER_MIDDLE, thisSize ); thisY = CG_VerticalAlignForHeight( y + coords[1], ALIGN_CENTER_MIDDLE, thisSize ); trap_R_DrawStretchPic( thisX, thisY, thisSize, thisSize, 0, 0, 1, 1, tmp_this_color, cent->ent.customShader ); } } else if( cent->item && cent->item->icon ) { // if ALIGN_CENTER_MIDDLE or something is used, images are f****d // so thats why they are set manually at the correct pos with -n CG_DrawHUDRect( x+(int)coords[0]-8, y+(int)coords[1]-8, ALIGN_LEFT_TOP, 15, 15, 1, 1, tmp_white_alpha, trap_R_RegisterPic( cent->item->icon ) ); if( draw_itemnames == qtrue ) trap_SCR_DrawString( x + (int)coords[0] + 16, y + (int)coords[1] - 8, ALIGN_LEFT_TOP, cent->item->shortname, cgs.fontSystemSmall, tmp_yellow_alpha ); } } }
/* * CG_DrawDemocam2D */ void CG_DrawDemocam2D( void ) { int xpos, ypos; const char *cam_type_name; int64_t cam_timestamp; char sfov[8], strack[8]; cg_subtitle_t *sub; if( !cgs.demoPlaying ) { return; } if( ( sub = CG_Democam_FindCurrentSubtitle() ) != NULL ) { if( sub->text && sub->text[0] ) { int y; if( sub->highprint ) { y = cgs.vidHeight * 0.30f; } else { y = cgs.vidHeight - ( cgs.vidHeight * 0.30f ); } CG_Democam_DrawCenterSubtitle( y, cgs.vidWidth * 0.75, cgs.fontSystemBig, sub->text ); } } if( democam_editing_mode ) { // draw the numbers of every entity in the view CG_DrawEntityNumbers(); // draw the cams info xpos = 8 * cgs.vidHeight / 600; ypos = 100 * cgs.vidHeight / 600; if( *cgs.demoName ) { trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Demo: %s", cgs.demoName ), cgs.fontSystemSmall, colorWhite ); ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); } trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Play mode: %s%s%s", S_COLOR_ORANGE, CamIsFree ? "Free Fly" : "Preview", S_COLOR_WHITE ), cgs.fontSystemSmall, colorWhite ); ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Time: %" PRIi64, demo_time ), cgs.fontSystemSmall, colorWhite ); ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); cam_type_name = "none"; cam_timestamp = 0; if( currentcam ) { cam_type_name = cam_TypeNames[currentcam->type]; cam_timestamp = currentcam->timeStamp; Q_snprintfz( strack, sizeof( strack ), "%i", currentcam->trackEnt ); Q_snprintfz( sfov, sizeof( sfov ), "%i", currentcam->fov ); } else { Q_strncpyz( strack, "NO", sizeof( strack ) ); Q_strncpyz( sfov, "NO", sizeof( sfov ) ); } trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Current cam: " S_COLOR_ORANGE "%s" S_COLOR_WHITE " Fov " S_COLOR_ORANGE "%s" S_COLOR_WHITE " Start %" PRIi64 " Tracking " S_COLOR_ORANGE "%s" S_COLOR_WHITE, cam_type_name, sfov, cam_timestamp, strack ), cgs.fontSystemSmall, colorWhite ); ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); if( currentcam ) { trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Pitch: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE " Yaw: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE " Roll: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE, currentcam->angles[PITCH], currentcam->angles[YAW], currentcam->angles[ROLL] ), cgs.fontSystemSmall, colorWhite ); } ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); cam_type_name = "none"; cam_timestamp = 0; Q_strncpyz( sfov, "NO", sizeof( sfov ) ); if( nextcam ) { cam_type_name = cam_TypeNames[nextcam->type]; cam_timestamp = nextcam->timeStamp; Q_snprintfz( strack, sizeof( strack ), "%i", nextcam->trackEnt ); Q_snprintfz( sfov, sizeof( sfov ), "%i", nextcam->fov ); } else { Q_strncpyz( strack, "NO", sizeof( strack ) ); Q_strncpyz( sfov, "NO", sizeof( sfov ) ); } trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Next cam: " S_COLOR_ORANGE "%s" S_COLOR_WHITE " Fov " S_COLOR_ORANGE "%s" S_COLOR_WHITE " Start %" PRIi64 " Tracking " S_COLOR_ORANGE "%s" S_COLOR_WHITE, cam_type_name, sfov, cam_timestamp, strack ), cgs.fontSystemSmall, colorWhite ); ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); if( nextcam ) { trap_SCR_DrawString( xpos, ypos, ALIGN_LEFT_TOP, va( "Pitch: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE " Yaw: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE " Roll: " S_COLOR_ORANGE "%.2f" S_COLOR_WHITE, nextcam->angles[PITCH], nextcam->angles[YAW], nextcam->angles[ROLL] ), cgs.fontSystemSmall, colorWhite ); } ypos += trap_SCR_FontHeight( cgs.fontSystemSmall ); } }
/* * SCR_DrawChallengers */ static int SCR_DrawChallengers( const char **ptrptr, int x, int y, int panelWidth, struct qfontface_s *font, int pass ) { char *token; const char *oldptr; char string[MAX_STRING_CHARS]; int yoffset = 0, xoffset = 0; int playerNum, ping; int height; assert( ptrptr && *ptrptr ); height = trap_SCR_FontHeight( font ); // draw title yoffset = height; if( pass ) { trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, CG_TranslateString( "Spectating you" ), font, colorCyan ); // racesow } yoffset += height; // draw challengers while( *ptrptr ) { oldptr = *ptrptr; token = COM_ParseExt( ptrptr, true ); if( !token[0] ) break; if( token[0] == '&' ) // it's a different command than 'challengers', so step back and return { *ptrptr = oldptr; break; } // first token is played id playerNum = atoi( token ); if( playerNum < 0 || playerNum >= gs.maxclients ) break; // get a second token oldptr = *ptrptr; token = COM_ParseExt( ptrptr, true ); if( !token[0] ) break; if( token[0] == '&' ) // it's a different command than 'challengers', so step back and return { *ptrptr = oldptr; break; } // second token is ping ping = atoi( token ); // draw the challenger if( ping < 0 ) Q_snprintfz( string, sizeof( string ), "%s%s ...", cgs.clientInfo[playerNum].name, S_COLOR_WHITE ); else Q_snprintfz( string, sizeof( string ), "%s%s %i", cgs.clientInfo[playerNum].name, S_COLOR_WHITE, ping ); if( pass ) { trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_CENTER_TOP, string, font, colorWhite ); } yoffset += height; } yoffset += height; return yoffset; }
/* * UI_DrawConnectScreen */ void UI_DrawConnectScreen( const char *serverName, const char *rejectmessage, int downloadType, const char *downloadFilename, float downloadPercent, int downloadSpeed, int connectCount, qboolean demoplaying, qboolean backGround ) { qboolean localhost, design = qfalse; char str[MAX_QPATH]; int x, y, xoffset, yoffset, width, height; unsigned int maxwidth; qboolean downloadFromWeb; char hostName[MAX_CONFIGSTRING_CHARS], mapname[MAX_CONFIGSTRING_CHARS], mapmessage[MAX_CONFIGSTRING_CHARS], gametype[MAX_CONFIGSTRING_CHARS], gametypeTitle[MAX_CONFIGSTRING_CHARS], gametypeVersion[MAX_CONFIGSTRING_CHARS], gametypeAuthor[MAX_CONFIGSTRING_CHARS], matchName[MAX_CONFIGSTRING_CHARS]; uis.demoplaying = demoplaying; //trap_S_StopBackgroundTrack(); localhost = (qboolean)( !serverName || !serverName[0] || !Q_stricmp( serverName, "localhost" ) ); trap_GetConfigString( CS_MAPNAME, mapname, sizeof( mapname ) ); trap_GetConfigString( CS_MESSAGE, mapmessage, sizeof( mapmessage ) ); if( backGround ) { Q_snprintfz( str, sizeof( str ), UI_SHADER_BACKGROUND, uis.backgroundNum ); trap_R_DrawStretchPic( 0, 0, uis.vidWidth, uis.vidHeight, 0, 0, 1, 1, colorWhite, trap_R_RegisterPic( str ) ); } // // not yet connected // x = 64; y = 64; xoffset = yoffset = 0; if( demoplaying ) Q_snprintfz( str, sizeof( str ), "Loading demo: %s", serverName ); else if( localhost ) Q_strncpyz( str, "Loading...", sizeof( str ) ); else if( mapname[0] ) Q_snprintfz( str, sizeof( str ), "Connecting to %s", serverName ); else Q_snprintfz( str, sizeof( str ), "Awaiting connection... %i", connectCount ); trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, uis.fontSystemBig, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemBig ); if( design && !rejectmessage ) rejectmessage = "Connection was interrupted because the weather sux :P"; if( rejectmessage ) { x = uis.vidWidth / 2; y = uis.vidHeight / 3; height = trap_SCR_strHeight( uis.fontSystemMedium ) * 4; Q_strncpyz( str, "Refused: ", sizeof( str ) ); width = max( trap_SCR_strWidth( str, uis.fontSystemMedium, 0 ), trap_SCR_strWidth( rejectmessage, uis.fontSystemSmall, 0 ) ); width += 32 * 2; xoffset = UISCR_HorizontalAlignOffset( ALIGN_CENTER_MIDDLE, width ); yoffset = UISCR_VerticalAlignOffset( ALIGN_CENTER_MIDDLE, height ); UI_DrawBox( x + xoffset, y + yoffset, width, height, colorWarsowOrange, colorWhite, NULL, colorDkGrey ); yoffset += trap_SCR_strHeight( uis.fontSystemMedium ); xoffset += 32; trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, uis.fontSystemMedium, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemMedium ); trap_SCR_DrawString( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, rejectmessage, uis.fontSystemSmall, colorBlack ); return; } if( mapname[0] ) { char levelshot[MAX_QPATH]; struct shader_s *levelshotShader; qboolean isDefaultlevelshot = qtrue; // // connected // x = 64; y = uis.vidHeight - 300; xoffset = yoffset = 0; width = uis.vidWidth; height = 200; UI_DrawBox( x + xoffset, y + yoffset, width, height, colorWarsowPurple, colorWhite, NULL, colorDkGrey ); xoffset += 16; yoffset += 16 + 4; maxwidth = uis.vidWidth - ( x + xoffset ); trap_GetConfigString( CS_HOSTNAME, hostName, sizeof( hostName ) ); trap_GetConfigString( CS_GAMETYPENAME, gametype, sizeof( gametype ) ); trap_GetConfigString( CS_GAMETYPETITLE, gametypeTitle, sizeof( gametypeTitle ) ); trap_GetConfigString( CS_GAMETYPEVERSION, gametypeVersion, sizeof( gametypeVersion ) ); trap_GetConfigString( CS_GAMETYPEAUTHOR, gametypeAuthor, sizeof( gametypeAuthor ) ); trap_GetConfigString( CS_MATCHNAME, matchName, sizeof( matchName ) ); Q_snprintfz( levelshot, sizeof( levelshot ), "levelshots/%s.jpg", mapname ); levelshotShader = trap_R_RegisterLevelshot( levelshot, uis.whiteShader, &isDefaultlevelshot ); if( !isDefaultlevelshot ) { int lw, lh, lx, ly; lh = height - 8; lw = lh * ( 4.0f/3.0f ); lx = uis.vidWidth - lw; ly = y + 4; trap_R_DrawStretchPic( lx, ly, lw, lh, 0, 0, 1, 1, colorWhite, levelshotShader ); } if( !localhost && !demoplaying ) { Q_snprintfz( str, sizeof( str ), "Server: %s", hostName ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; } if( mapmessage[0] && Q_stricmp( mapname, mapmessage ) ) { Q_snprintfz( str, sizeof( str ), "Level: "S_COLOR_ORANGE"%s", COM_RemoveColorTokens( mapmessage ) ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; } Q_snprintfz( str, sizeof( str ), "Map: %s", mapname ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; if( matchName[0] ) { Q_snprintfz( str, sizeof( str ), "Match: %s", matchName ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; } yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; Q_snprintfz( str, sizeof( str ), "Gametype: "S_COLOR_ORANGE"%s", COM_RemoveColorTokens( gametypeTitle ) ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; Q_snprintfz( str, sizeof( str ), "Version: %s", COM_RemoveColorTokens( gametypeVersion ) ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; Q_snprintfz( str, sizeof( str ), "Author: %s", gametypeAuthor ); trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ) + 8; } // downloading if( design && !downloadFilename ) { downloadFilename = "http://www.warsow.net/autoupdate/basewsw/map_wdm9a.pk3"; downloadType = 2; downloadPercent = 65.8; downloadSpeed = 325; } if( downloadType && downloadFilename ) { size_t len; const char *s; downloadFromWeb = ( downloadType == 2 ); x = uis.vidWidth / 2; y = uis.vidHeight / 3; width = 400; height = 128 - trap_SCR_strHeight( uis.fontSystemSmall ); if( uis.vidWidth <= width ) width = uis.vidWidth - 64; maxwidth = width - 48; xoffset = UISCR_HorizontalAlignOffset( ALIGN_CENTER_MIDDLE, width ); yoffset = UISCR_VerticalAlignOffset( ALIGN_CENTER_MIDDLE, height ); // adjust the box size for the extra number of lines needed to draw the file path s = downloadFilename; while( ( len = trap_SCR_StrlenForWidth( s, uis.fontSystemSmall, maxwidth ) ) > 0 ) { s += len; height += trap_SCR_strHeight( uis.fontSystemSmall ); } UI_DrawBox( x + xoffset, y + yoffset, width, height, colorWarsowPurple, colorWhite, NULL, colorDkGrey ); xoffset += 24; yoffset += 24; trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, downloadFromWeb ? "Downloading from web" : "Downloading from server", maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += trap_SCR_strHeight( uis.fontSystemSmall ); s = downloadFilename; while( ( len = trap_SCR_DrawStringWidth( x + xoffset, y + yoffset, ALIGN_LEFT_TOP, s, maxwidth, uis.fontSystemSmall, colorWhite ) ) > 0 ) { s += len; yoffset += trap_SCR_strHeight( uis.fontSystemSmall ); } yoffset += 16; UI_DrawPicBar( x + xoffset, y + yoffset, maxwidth, 24, ALIGN_LEFT_TOP, downloadPercent, trap_R_RegisterPic( "gfx/ui/progressbar" ),colorDkGrey, colorOrange ); Q_snprintfz( str, sizeof( str ), "%3.1f%c", downloadPercent, '%' ); trap_SCR_DrawStringWidth( x + xoffset + 12, y + yoffset + 12, ALIGN_LEFT_MIDDLE, str, maxwidth, uis.fontSystemSmall, colorWhite ); Q_snprintfz( str, sizeof( str ), "%ik/s", downloadSpeed ); trap_SCR_DrawStringWidth( x + xoffset + maxwidth - 12, y + yoffset + 12, ALIGN_RIGHT_MIDDLE, str, maxwidth, uis.fontSystemSmall, colorWhite ); yoffset += 24 + 8; } }