Beispiel #1
0
//
// Draw Weapon Menu
//
int CHudAmmo::DrawWList( float flTime )
{
	int r, g, b, a;
	int x, y, i;

	if( !gpActiveSel )
		return 0;

	int iActiveSlot;

	if( gpActiveSel == (WEAPON *)1 )
		iActiveSlot = -1;	// current slot has no weapons
	else 
		iActiveSlot = gpActiveSel->iSlot;

	x = 10; //!!!
	y = 10; //!!!

	// Ensure that there are available choices in the active slot
	if( iActiveSlot > 0 )
	{
		if( !gWR.GetFirstPos( iActiveSlot ))
		{
			gpActiveSel = (WEAPON *)1;
			iActiveSlot = -1;
		}
	}
		
	// Draw top line
	for( i = 0; i < MAX_WEAPON_SLOTS; i++ )
	{
		int iWidth;

		UnpackRGB( r, g, b, gHUD.m_iHUDColor );
	
		if( iActiveSlot == i )
			a = 255;
		else
			a = 192;

		ScaleColors( r, g, b, 255 );
		SPR_Set( gHUD.GetSprite( m_HUD_bucket0 + i ), r, g, b );

		// make active slot wide enough to accomodate gun pictures
		if( i == iActiveSlot )
		{
			WEAPON *p = gWR.GetFirstPos(iActiveSlot);

			if( p )
				iWidth = p->rcActive.right - p->rcActive.left;
			else
				iWidth = giBucketWidth;
		}
		else
			iWidth = giBucketWidth;

		SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_bucket0 + i ));
		
		x += iWidth + 5;
	}

	a = 128; //!!!
	x = 10;

	// Draw all of the buckets
	for( i = 0; i < MAX_WEAPON_SLOTS; i++ )
	{
		y = giBucketHeight + 10;

		// If this is the active slot, draw the bigger pictures,
		// otherwise just draw boxes
		if( i == iActiveSlot )
		{
			WEAPON *p = gWR.GetFirstPos( i );
			int iWidth = giBucketWidth;

			if( p )
				iWidth = p->rcActive.right - p->rcActive.left;

			for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
			{
				p = gWR.GetWeaponSlot( i, iPos );

				if( !p || !p->iId )
					continue;

				UnpackRGB( r, g, b, gHUD.m_iHUDColor );
			
				// if active, then we must have ammo.
				if( gpActiveSel == p )
				{
					SPR_Set( p->hActive, r, g, b );
					SPR_DrawAdditive( 0, x, y, &p->rcActive );

					SPR_Set( gHUD.GetSprite( m_HUD_selection ), r, g, b );
					SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_selection ));
				}
				else
				{
					// Draw Weapon if Red if no ammo
					if( gWR.HasAmmo( p ))
					{
						ScaleColors( r, g, b, 192 );
					}
					else
					{
						UnpackRGB( r, g, b, RGB_REDISH );
						ScaleColors( r, g, b, 128 );
					}

					SPR_Set( p->hInactive, r, g, b );
					SPR_DrawAdditive( 0, x, y, &p->rcInactive );
				}

				// Draw Ammo Bar
				DrawAmmoBar( p, x + giABWidth / 2, y, giABWidth, giABHeight );
				y += p->rcActive.bottom - p->rcActive.top + 5;
			}

			x += iWidth + 5;

		}
		else
		{
			// Draw Row of weapons.
			UnpackRGB( r, g, b, gHUD.m_iHUDColor );

			for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
			{
				WEAPON *p = gWR.GetWeaponSlot( i, iPos );
				
				if( !p || !p->iId )
					continue;

				if( gWR.HasAmmo( p ))
				{
					UnpackRGB( r, g, b, gHUD.m_iHUDColor );
					a = 128;
				}
				else
				{
					UnpackRGB( r, g, b, RGB_REDISH );
					a = 96;
				}

				FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a );
				y += giBucketHeight + 5;
			}
			x += giBucketWidth + 5;
		}
	}	

	return 1;

}
Beispiel #2
0
//-------------------------------------------------------------------------
// Drawing code
//-------------------------------------------------------------------------
int CHudAmmo::Draw( float flTime )
{
	int a, x, y, r, g, b;
	int AmmoWidth;

	if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
		return 1;

	if(( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )))
		return 1;

	// Draw Weapon Menu
	DrawWList( flTime );

	// Draw ammo pickup history
	gHR.DrawAmmoHistory( flTime );

	if( !( m_iFlags & HUD_ACTIVE ))
		return 0;

	if( !m_pWeapon )
	{
		return 0;
	}

	WEAPON *pw = m_pWeapon; // shorthand

	// SPR_Draw Ammo
	if(( pw->iAmmoType < 0 ) && ( pw->iAmmo2Type < 0 ))
		return 0;


	int iFlags = DHN_DRAWZERO; // draw 0 values

	AmmoWidth = gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).right - gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).left;

	a = (int)max( MIN_ALPHA, m_fFade );

	if( m_fFade > 0 )
		m_fFade -= (gHUD.m_flTimeDelta * 20);

	UnpackRGB( r, g, b, gHUD.m_iHUDColor );

	ScaleColors( r, g, b, a );

	// Does this weapon have a clip?
	y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;

	// Does weapon have any ammo at all?
	if( m_pWeapon->iAmmoType > 0 )
	{
		int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left;
		
		if( pw->iClip >= 0 )
		{
			// room for the number and the '|' and the current ammo
			x = ScreenWidth - ( 8 * AmmoWidth ) - iIconWidth;
			x = gHUD.DrawHudNumber( x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b );

			wrect_t rc;
			rc.top = 0;
			rc.left = 0;
			rc.right = AmmoWidth;
			rc.bottom = 100;

			int iBarWidth =  AmmoWidth / 10;

			x += AmmoWidth / 2;

			UnpackRGB( r, g, b, gHUD.m_iHUDColor );

			// draw the | bar
			FillRGBA( x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a );

			x += iBarWidth + AmmoWidth / 2;

			// GL Seems to need this
			ScaleColors( r, g, b, a );
			x = gHUD.DrawHudNumber( x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo( pw->iAmmoType ), r, g, b );		


		}
		else
		{
			// SPR_Draw a bullets only line
			x = ScreenWidth - 4 * AmmoWidth - iIconWidth;
			x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo( pw->iAmmoType ), r, g, b );
		}

		// Draw the ammo Icon
		int iOffset = ( m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top ) / 8;
		SPR_Set( m_pWeapon->hAmmo, r, g, b );
		SPR_DrawAdditive( 0, x, y - iOffset, &m_pWeapon->rcAmmo );
	}

	// Does weapon have seconday ammo?
	if( pw->iAmmo2Type > 0 ) 
	{
		int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left;

		// Do we have secondary ammo?
		if(( pw->iAmmo2Type != 0 ) && ( gWR.CountAmmo(pw->iAmmo2Type ) > 0))
		{
			y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight / 4;
			x = ScreenWidth - 4 * AmmoWidth - iIconWidth;
			x = gHUD.DrawHudNumber( x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo( pw->iAmmo2Type ), r, g, b );

			// Draw the ammo Icon
			SPR_Set( m_pWeapon->hAmmo2, r, g, b );
			int iOffset = ( m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top ) / 8;
			SPR_DrawAdditive( 0, x, y - iOffset, &m_pWeapon->rcAmmo2 );
		}
	}
	return 1;
}
Beispiel #3
0
int CHudHealth::Draw(float flTime)
{
	int r, g, b;
	int a = 0, x, y;
	int HealthWidth;

	if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() )
		return 1;

	if ( !m_hSprite )
		m_hSprite = LoadSprite(PAIN_NAME);
	
	// Has health changed? Flash the health #
	if (m_fFade)
	{
		m_fFade -= (gHUD.m_flTimeDelta * 20);
		if (m_fFade <= 0)
		{
			a = MIN_ALPHA;
			m_fFade = 0;
		}

		// Fade the health number back to dim

		a = MIN_ALPHA +  (m_fFade/FADE_TIME) * 128;

	}
	else
		a = MIN_ALPHA;

	// If health is getting low, make it bright red
	if (m_iHealth <= 15)
		a = 255;
		
	GetPainColor( r, g, b );
	ScaleColors(r, g, b, a );

	// Only draw health if we have the suit.
	if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)))
	{
		HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
		int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left;

		y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
		x = CrossWidth /2;

		SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b);
		SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross));

		x = CrossWidth + HealthWidth / 2;

		x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b);

		x += HealthWidth/2;

		int iHeight = gHUD.m_iFontHeight;
		int iWidth = HealthWidth/10;
		FillRGBA(x, y, iWidth, iHeight, 255, 160, 0, a);
	}

	DrawDamage(flTime);
	return DrawPain(flTime);
}
Beispiel #4
0
/*
=================
UI_Crosshair_Ownerdraw
=================
*/
static void UI_Crosshair_Ownerdraw( void *self )
{
	menuBitmap_s *item = (menuBitmap_s*)self;

	UI_DrawPic(item->generic.x, item->generic.y, item->generic.width, item->generic.height, 0x00FFFFFF, "gfx/vgui/crosshair" );


	int l;
	switch( (int)uiPlayerSetup.crosshairSize.curValue )
	{
	case 1:
		l = 10;
		break;
	case 2:
		l = 20;
		break;
	case 3:
		l = 30;
		break;
	case 0:
		if( ScreenWidth < 640 )
			l = 30;
		else if( ScreenWidth < 1024 )
			l = 20;
		else l = 10;
	}

	l *= ScreenHeight / 768.0f;

	int x = item->generic.x, // xpos
		y = item->generic.y, // ypos
		w = item->generic.width, // width
		h = item->generic.height, // height
		// delta distance
		d = (item->generic.width / 2 - l) * 0.5,
		// alpha
		a = 180,
		// red
		r = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][0],
		// green
		g = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][1],
		// blue
		b = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][2];

	if( uiPlayerSetup.crosshairTranslucent.enabled )
	{
		// verical
		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawTrans(x + w / 2, y + d,         1, l );

		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawTrans(x + w / 2, y + h / 2 + d, 1, l );

		// horizontal
		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawTrans(x + d,         y + h / 2, l, 1 );

		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawTrans(x + w / 2 + d, y + h / 2, l, 1 );
	}
	else
	{
		// verical
		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawAdditive(x + w / 2, y + d,         1, l );

		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawAdditive(x + w / 2, y + h / 2 + d, 1, l );

		// horizontal
		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawAdditive(x + d,         y + h / 2, l, 1 );

		PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a);
		PIC_DrawAdditive(x + w / 2 + d, y + h / 2, l, 1 );
	}

#if 0
	// verical
	FillRGBA(x + w / 2, y + d,         1, l, r, g, b, a);
	FillRGBA(x + w / 2, y + h / 2 + d, 1, l, r, g, b, a);

	// horizontal
	FillRGBA(x + d,         y + h / 2, l, 1, r, g, b, a);
	FillRGBA(x + w / 2 + d, y + h / 2, l, 1, r, g, b, a);
#endif
}
// returns the ypos where it finishes drawing
int CHudScoreboard::DrawPlayers(int xpos_rel, float list_slot, int nameoffset, char *team)
{
	int can_show_packetloss = 0;
	int FAR_RIGHT;

	//  Packetloss removed on Kelly 'shipping nazi' Bailey's orders
	if(cl_showpacketloss && cl_showpacketloss->value && (ScreenWidth >= 400))
	{
		can_show_packetloss = 1;
		SCOREBOARD_WIDTH    = 400;
	}
	else
	{
		SCOREBOARD_WIDTH = 320;
	}

	FAR_RIGHT = can_show_packetloss ? PL_RANGE_MAX : PING_RANGE_MAX;
	FAR_RIGHT += 5;

	// draw the players, in order,  and restricted to team if set
	while(1)
	{
		// Find the top ranking player
		int highest_frags = -99999;
		int lowest_deaths = 99999;
		int best_player   = 0;

		for(int i = 1; i < MAX_PLAYERS; i++)
		{
			if(g_PlayerInfoList[i].name && g_PlayerExtraInfo[i].frags >= highest_frags)
			{
				if(!(team && stricmp(g_PlayerExtraInfo[i].teamname, team))) // make sure it is the specified team
				{
					extra_player_info_t *pl_info = &g_PlayerExtraInfo[i];
					if(pl_info->frags > highest_frags || pl_info->deaths < lowest_deaths)
					{
						best_player   = i;
						lowest_deaths = pl_info->deaths;
						highest_frags = pl_info->frags;
					}
				}
			}
		}

		if(!best_player)
			break;

		// draw out the best player
		hud_player_info_t *pl_info = &g_PlayerInfoList[best_player];

		int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);

		// check we haven't drawn too far down
		if(ypos > ROW_RANGE_MAX) // don't draw to close to the lower border
			break;

		int xpos = NAME_RANGE_MIN + xpos_rel;
		int r = 255, g = 255, b = 255;
		if(best_player == m_iLastKilledBy && m_fLastKillTime && m_fLastKillTime > gHUD.m_flTime)
		{
			if(pl_info->thisplayer)
			{ // green is the suicide color? i wish this could do grey...
				FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 80, 155, 0, 70);
			}
			else
			{ // Highlight the killers name - overlay the background in red,  then draw the score text over it
				FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 255, 0, 0, ((float)15 * (float)(m_fLastKillTime - gHUD.m_flTime)));
			}
		}
		else if(pl_info->thisplayer) // if it is their name, draw it a different color
		{
			// overlay the background in blue,  then draw the score text over it
			FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 0, 0, 255, 70);
		}

		// draw their name (left to right)
		gHUD.DrawHudString(xpos + nameoffset, ypos, NAME_RANGE_MAX + xpos_rel, pl_info->name, r, g, b);

		// draw kills (right to left)
		xpos = KILLS_RANGE_MAX + xpos_rel;
		gHUD.DrawHudNumberString(xpos, ypos, KILLS_RANGE_MIN + xpos_rel, g_PlayerExtraInfo[best_player].frags, r, g, b);

		// draw divider
		xpos = DIVIDER_POS + xpos_rel;
		gHUD.DrawHudString(xpos, ypos, xpos + 20, "/", r, g, b);

		// draw deaths
		xpos = DEATHS_RANGE_MAX + xpos_rel;
		gHUD.DrawHudNumberString(xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, g_PlayerExtraInfo[best_player].deaths, r, g, b);

		// draw ping & packetloss
		static char buf[64];
		sprintf(buf, "%d", g_PlayerInfoList[best_player].ping);
		xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25;
		gHUD.DrawHudStringReverse(xpos, ypos, xpos - 50, buf, r, g, b);

		//  Packetloss removed on Kelly 'shipping nazi' Bailey's orders
		if(can_show_packetloss)
		{
			if(g_PlayerInfoList[best_player].packetloss >= 63)
			{
				UnpackRGB(r, g, b, RGB_REDISH);
				sprintf(buf, " !!!!");
			}
			else
			{
				sprintf(buf, "  %d", g_PlayerInfoList[best_player].packetloss);
			}

			xpos = ((PL_RANGE_MAX - PL_RANGE_MIN) / 2) + PL_RANGE_MIN + xpos_rel + 25;

			gHUD.DrawHudString(xpos, ypos, xpos + 50, buf, r, g, b);
		}

		pl_info->name = NULL; // set the name to be NULL, so this client won't get drawn again
		list_slot++;
	}

	return list_slot;
}
int CHudScoreboard::Draw(float fTime)
{
	int can_show_packetloss = 0;
	int FAR_RIGHT;

	if(!m_iShowscoresHeld && gHUD.m_Health.m_iHealth > 0 && !gHUD.m_iIntermission)
		return 1;

	GetAllPlayersInfo();

	//  Packetloss removed on Kelly 'shipping nazi' Bailey's orders
	if(cl_showpacketloss && cl_showpacketloss->value && (ScreenWidth >= 400))
	{
		can_show_packetloss = 1;
		SCOREBOARD_WIDTH    = 400;
	}
	else
	{
		SCOREBOARD_WIDTH = 320;
	}

	// just sort the list on the fly
	// list is sorted first by frags, then by deaths
	float list_slot = 0;
	int   xpos_rel  = (ScreenWidth - SCOREBOARD_WIDTH) / 2;

	// print the heading line
	int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
	int xpos = NAME_RANGE_MIN + xpos_rel;

	if(!gHUD.m_Teamplay)
		gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Player", 255, 140, 0);
	else
		gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Teams", 255, 140, 0);

	gHUD.DrawHudStringReverse(KILLS_RANGE_MAX + xpos_rel, ypos, 0, "kills", 255, 140, 0);
	gHUD.DrawHudString(DIVIDER_POS + xpos_rel, ypos, ScreenWidth, "/", 255, 140, 0);
	gHUD.DrawHudString(DEATHS_RANGE_MIN + xpos_rel + 5, ypos, ScreenWidth, "deaths", 255, 140, 0);
	gHUD.DrawHudString(PING_RANGE_MAX + xpos_rel - 35, ypos, ScreenWidth, "latency", 255, 140, 0);

	if(can_show_packetloss)
	{
		gHUD.DrawHudString(PL_RANGE_MAX + xpos_rel - 35, ypos, ScreenWidth, "pkt loss", 255, 140, 0);
	}

	FAR_RIGHT = can_show_packetloss ? PL_RANGE_MAX : PING_RANGE_MAX;
	FAR_RIGHT += 5;

	list_slot += 1.2;
	ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
	xpos = NAME_RANGE_MIN + xpos_rel;
	FillRGBA(xpos - 5, ypos, FAR_RIGHT, 1, 255, 140, 0, 255); // draw the seperator line

	list_slot += 0.8;

	if(!gHUD.m_Teamplay)
	{
		// it's not teamplay,  so just draw a simple player list
		DrawPlayers(xpos_rel, list_slot);
		return 1;
	}

	// clear out team scores
	for(int i = 1; i <= m_iNumTeams; i++)
	{
		if(!g_TeamInfo[i].scores_overriden)
			g_TeamInfo[i].frags = g_TeamInfo[i].deaths = 0;
		g_TeamInfo[i].ping = g_TeamInfo[i].packetloss = 0;
	}

	// recalc the team scores, then draw them
	for(i = 1; i < MAX_PLAYERS; i++)
	{
		if(g_PlayerInfoList[i].name == NULL)
			continue; // empty player slot, skip

		if(g_PlayerExtraInfo[i].teamname[0] == 0)
			continue; // skip over players who are not in a team

		// find what team this player is in
		for(int j = 1; j <= m_iNumTeams; j++)
		{
			if(!stricmp(g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name))
				break;
		}
		if(j > m_iNumTeams) // player is not in a team, skip to the next guy
			continue;

		if(!g_TeamInfo[j].scores_overriden)
		{
			g_TeamInfo[j].frags += g_PlayerExtraInfo[i].frags;
			g_TeamInfo[j].deaths += g_PlayerExtraInfo[i].deaths;
		}

		g_TeamInfo[j].ping += g_PlayerInfoList[i].ping;
		g_TeamInfo[j].packetloss += g_PlayerInfoList[i].packetloss;

		if(g_PlayerInfoList[i].thisplayer)
			g_TeamInfo[j].ownteam = TRUE;
		else
			g_TeamInfo[j].ownteam = FALSE;
	}

	// find team ping/packetloss averages
	for(i = 1; i <= m_iNumTeams; i++)
	{
		g_TeamInfo[i].already_drawn = FALSE;

		if(g_TeamInfo[i].players > 0)
		{
			g_TeamInfo[i].ping /= g_TeamInfo[i].players;       // use the average ping of all the players in the team as the teams ping
			g_TeamInfo[i].packetloss /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping
		}
	}

	// Draw the teams
	while(1)
	{
		int highest_frags = -99999;
		int lowest_deaths = 99999;
		int best_team     = 0;

		for(i = 1; i <= m_iNumTeams; i++)
		{
			if(g_TeamInfo[i].players < 0)
				continue;

			if(!g_TeamInfo[i].already_drawn && g_TeamInfo[i].frags >= highest_frags)
			{
				if(g_TeamInfo[i].frags > highest_frags || g_TeamInfo[i].deaths < lowest_deaths)
				{
					best_team     = i;
					lowest_deaths = g_TeamInfo[i].deaths;
					highest_frags = g_TeamInfo[i].frags;
				}
			}
		}

		// draw the best team on the scoreboard
		if(!best_team)
			break;

		// draw out the best team
		team_info_t *team_info = &g_TeamInfo[best_team];

		ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);

		// check we haven't drawn too far down
		if(ypos > ROW_RANGE_MAX) // don't draw to close to the lower border
			break;

		xpos  = NAME_RANGE_MIN + xpos_rel;
		int r = 255, g = 225, b = 55; // draw the stuff kinda yellowish

		if(team_info->ownteam) // if it is their team, draw the background different color
		{
			// overlay the background in blue,  then draw the score text over it
			FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 0, 0, 255, 70);
		}

		// draw their name (left to right)
		gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, team_info->name, r, g, b);

		// draw kills (right to left)
		xpos = KILLS_RANGE_MAX + xpos_rel;
		gHUD.DrawHudNumberString(xpos, ypos, KILLS_RANGE_MIN + xpos_rel, team_info->frags, r, g, b);

		// draw divider
		xpos = DIVIDER_POS + xpos_rel;
		gHUD.DrawHudString(xpos, ypos, xpos + 20, "/", r, g, b);

		// draw deaths
		xpos = DEATHS_RANGE_MAX + xpos_rel;
		gHUD.DrawHudNumberString(xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, team_info->deaths, r, g, b);

		// draw ping
		// draw ping & packetloss
		static char buf[64];
		sprintf(buf, "%d", team_info->ping);
		xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25;
		UnpackRGB(r, g, b, RGB_YELLOWISH);
		gHUD.DrawHudStringReverse(xpos, ypos, xpos - 50, buf, r, g, b);

		//  Packetloss removed on Kelly 'shipping nazi' Bailey's orders
		if(can_show_packetloss)
		{
			xpos = ((PL_RANGE_MAX - PL_RANGE_MIN) / 2) + PL_RANGE_MIN + xpos_rel + 25;

			sprintf(buf, "  %d", team_info->packetloss);
			gHUD.DrawHudString(xpos, ypos, xpos + 50, buf, r, g, b);
		}

		team_info->already_drawn = TRUE; // set the already_drawn to be TRUE, so this team won't get drawn again
		list_slot++;

		// draw all the players that belong to this team, indented slightly
		list_slot = DrawPlayers(xpos_rel, list_slot, 10, team_info->name);
	}

	// draw all the players who are not in a team
	list_slot += 0.5;
	DrawPlayers(xpos_rel, list_slot, 0, "");

	return 1;
}