Code3Arena

PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 24 | Next >>

menu

  • Home/News
  • ModSource
  • Compiling
  • Help!!!
  • Submission
  • Contributors
  • Staff
  • Downloads

    Tutorials
    < Index >
    1. Mod making 101
    2. Up 'n running
    3. Hello, QWorld!
    4. Infinite Haste
    5. Armor Piercing Rails
    6. Bouncing Rockets
    7. Cloaking
    8. Ladders
    9. Favourite Server
    10. Flame Thrower
    11. Vortex Grenades
    12. Grapple
    13. Lightning Discharge
    14. Locational Damage
    15. Leg Shots
    16. Weapon Switching
    17. Scoreboard frag-rate
    18. Vortex Grenades II
    19. Vulnerable Missiles
    20. Creating Classes
    21. Scrolling Credits
    22. Weapon Dropping
    23. Anti-Gravity Boots
    24. HUD scoreboard
    25. Flashlight and laser
    26. Weapon Positioning
    27. Weapon Reloading
    28. Progressive Zooming
    29. Rotating Doors
    30. Beheading (headshot!)
    31. Alt Weapon Fire
    32. Popup Menus I
    33. Popup Menus II
    34. Cluster Grenades
    35. Homing Rockets
    36. Spreadfire Powerup
    37. Instagib gameplay
    38. Accelerating rockets
    39. Server only Instagib
    40. Advanced Grapple Hook
    41. Unlagging your mod


    Articles
    < Index >
    1. Entities
    2. Vectors
    3. Good Coding
    4. Compilers I
    5. Compilers II
    6. UI Menu Primer I
    7. UI Menu Primer II
    8. UI Menu Primer III
    9. QVM Communication, Cvars, commands
    10. Metrowerks CodeWarrior
    11. 1.27g code, bugs, batch


    Links

  • Quake3 Files
  • Quake3 Forums
  • Q3A Editing Message Board
  • Quake3 Editing


    Feedback

  • SumFuka
  • Calrathan
  • HypoThermia
  • WarZone





    Site Design by:
    ICEmosis Design


  •  
    TUTORIAL 24 - Hud scoreboard
    by HeffX

    Ok, so Quake 3 Arena has a nice detailed scoreboard. But what if you just need your score and your place on the scoreboard? It's a bit irritating to break from the action to check them, so that's why I had this idea. This tutorial will let you add a mini scoreboard right in your hud.

    First, we need to know where we want it, I thought it would be a good idea to place it under that little score display in the lower right corner of the screen. However, this display is a little low so we'll place this display higher. So, let's find that piece of code. Set cgame as your active configuration and open up cg_draw.c. We want it in the lower right corner, that code starts somewhere at line 796.

    Ok! Let's start coding.

    1. Adding the new function(s)

    First, let's place the code, that places the mini scoreboard on the screen, above of CG_DrawScores:

    /*
    =================
    CG_DrawMiniScore
    
    Draw the small scoreboard display
    =================
    */
    void CG_DrawMiniScore( int y, score_t *score, qboolean smallfont ) {
    	char	string[1024];
    	float	hcolor[4];
    	float	color[4];
    	clientInfo_t	*ci;
    	int		x;
    	int		w;
    	int		sw;
    	int		sh;
    	const char *s;
    
    	ci = &cgs.clientinfo[score->client];
    
    	// draw the score line
    	// Use S_COLOR_WHITE so colored names don't change score color.
    	Com_sprintf(string, sizeof(string),
    		"%s "S_COLOR_WHITE" %3i", ci->name, score->score);
    
    	// colorize line
    	if ( ci->team == TEAM_BLUE ) {
    		hcolor[0] = 0;
    		hcolor[1] = 0;
    		hcolor[2] = 1;
    	} else if ( ci->team == TEAM_RED ) {
    		hcolor[0] = 1;
    		hcolor[1] = 0;
    		hcolor[2] = 0;
    	} else {
    		hcolor[0] = 0.7;
    		hcolor[1] = 0.7;
    		hcolor[2] = 0.7;
    	}
    
    	hcolor[3] = 0.33;
    
    	if(smallfont)
    	{
    		sw = TINYCHAR_WIDTH;
    		sh = TINYCHAR_HEIGHT;
    	}
    	else
    	{
    		sw = SMALLCHAR_WIDTH;
    		sh = SMALLCHAR_HEIGHT;
    	}
    
    	x = 640;
    	s = va( "%s", string );
    	w = CG_DrawStrlen( s ) * sw + 8;
    	x -= w;
    
    	CG_FillRect( x+1, y, w, sh+1, hcolor );
    
    	if(smallfont)
    	{
    		color[0] = color[1] = color[2] = color[3] = 1.0;
    		CG_DrawStringExt( x, y, string, color, qtrue, qfalse, TINYCHAR_WIDTH, TINYCHAR_HEIGHT, 0 );
    	}
    	else
    	{
    		CG_DrawSmallString( x, y, string, 1.0 );
    	}
    }
    
    int CG_MakeMiniScoreboard( int y)
    {
    	int		i;
    	score_t	*score;
    	int		count;
    	int players;
    	clientInfo_t	*ci;
    	qboolean smallfont;
    	int lineHeight;
    
    	players = 0;
    	count = 0;
    
    	for ( i = 0 ; i < cg.numScores ; i++ )
    	{
    		score = &cg.scores[i];
    		ci = &cgs.clientinfo[ score->client ];
    
    		if ( score->client < 0 || score->client >= cgs.maxclients ) {
    			Com_Printf( "Bad score->client: %i\n", score->client );
    			return 0;
    		}
    
    		// Don't show connecting people or spectators
    		if ( score->ping == -1 || ci->team == TEAM_SPECTATOR ) {
    			continue;
    		}
    
    		players++;
    	}
    
    	if (!players)
    		return 0;
    
    	if(players > 7) {
    		lineHeight = (TINYCHAR_HEIGHT - 4)*2+1;
    		smallfont = qtrue;
    	}
    	else {
    		lineHeight = (SMALLCHAR_HEIGHT - 8)*2+1;
    		smallfont = qfalse;
    	}	
    
    	// draw (at most) the top 11 players
    	for ( i = 0 ; i < cg.numScores && count < 11 ; i++ )
    	{
    		score = &cg.scores[i];
    		ci = &cgs.clientinfo[ score->client ];
    		if ( score->ping == -1 || ci->team == TEAM_SPECTATOR ) {
    			continue;
    		}
    
    		CG_DrawMiniScore( y + lineHeight * count, score, smallfont);
    		count++;
    	}
    
    	return count;
    }
    
    /*
    =================
    CG_DrawScores
    
    Draw the small two score display
    =================
    */
    static float CG_DrawScores( float y )
    {
    

    Now, let's break it down:

    CG_DrawMiniScore : Places it on the screen. If teamplay is on it make the lines team colored, else just white.

    CG_MakeMiniScoreboard : Set's everything up. As you can see from the comments, it doesn't show connecting and spectating people. It calls CG_DrawMiniScore to write every client's score down.

    2. Calling the function

    So! Now we have the code to place it on the screen, now we need to call it somewhere, but first, place the display higher so the scoreboard fits under.

    static float CG_DrawScores( float y )
    {
    	const char	*s;
    	int			s1, s2, score;
    	int			x, w;
    	int			v;
    	vec4_t		color;
    	float		y1;
    	gitem_t		*item;
    
    	s1 = cgs.scores1;
    	s2 = cgs.scores2;
    
    	y -=  BIGCHAR_HEIGHT + 8;
    	y -=  BIGCHAR_HEIGHT * 14;
    
    	y1 = y;
    

    Now for the call: Go to the bottom of CG_DrawScores and place this code:

                if ( cgs.fraglimit ) {
                      s = va( "%2i", cgs.fraglimit );
                      w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8;
                      x -= w;
                      CG_DrawBigString( x + 4, y, s, 1.0F);
                }
          }
    
          if ( cg.scoresRequestTime + 5000 < cg.time )
          {
                // the scores are more than five seconds out of date,
    			// so request new ones
    			cg.scoresRequestTime = cg.time;
    			trap_SendClientCommand( "score" );
    	  }
    	  CG_MakeMiniScoreboard( y + ((BIGCHAR_HEIGHT - 8)*2)+8 );
    
          return y1 - 8;
    }
    

    The first part of this piece of code, updates the scores (every 5 sec.). Then it does the call. If you want the scores to be updated faster, I think 2 seconds is the minimum.

    3. Compile...

    Now compile and run! Remember, it's client side, so you can use it on any server that has pure server off.

    I made the mini scoreboard for my own mod (P.U.F.F), just wanted to mention that.

    This tuturial is (c) Mike "HeffX" Willems.

    PlanetQuake | Code3Arena | Tutorials | << Prev | Tutorial 24 | Next >>