#include "g_local.h"

int TeamNumber (team_t *team);
IniFile ini_file;  //ini file to load team defs

void LoadTeam (int team, char *section)
{
	char p[12];
	int i;

	teams[team] = gi.TagMalloc (sizeof(team_t), TAG_GAME);
	strcpy(teams[team]->name, Ini_GetValue(&ini_file, section, "name"));
	
	teams[team]->icon = Ini_GetValue(&ini_file, section, "icon");

	teams[team]->laser = atoi(Ini_GetValue(&ini_file, section, "laser"));
	teams[team]->since_last_base = 0;

	for (i=0; i<= BD_MAX_TEAM_SKINS; i++) 
	{
		Com_sprintf(p, sizeof(p), "skin%i", i);
		teams[team]->skins[i] = Ini_GetValue(&ini_file, section, p);
	}

	teams[team]->banner = Ini_GetValue(&ini_file, section, "banner");
	teams[team]->banner_skin = atoi(Ini_GetValue(&ini_file, section, "banner skin"));
}

void Ini_LoadFile ()
{
	char *p, *q;
	int i;
	
	for (i=0; i <= BD_MAX_TEAM; i++) 
	{
		p = q = NULL;

		switch (i) 
		{
		case TEAM1:
			q = "Team one";
			break;
		case TEAM2:
			q = "Team two";
			break;
		case TEAM3:
			q = "Team three";
			break;
		case TEAM4:
			q = "Team four";
			break;
		default:
			continue;
		}

		p = Ini_GetValue(&ini_file, q, "name");
		if (p != NULL)
			LoadTeam (i, q);		
	}

	//BD_IN_BASE_BONUS				= 1  
	p = Ini_GetValue(&ini_file, "Bonuses", "in base bonus");
	if (p != NULL)
		bonus[0] = 	atoi(p);
	else 
		bonus[0] =  1;

	//BD_HEALER_PROTECT_BONUS		= 1  
	p = Ini_GetValue(&ini_file, "Bonuses", "healer protect");
	if (p != NULL)
		bonus[1] = 	atoi(p);
	else 
		bonus[1] =  1;

	//BD_WALL_PROTECT				= 2
	p = Ini_GetValue(&ini_file, "Bonuses", "wall protect");
	if (p != NULL)
		bonus[2] = 	atoi(p);
	else 
		bonus[2] =  2;
	
	//BD_HARDCORE_BONUS				= 1
	p = Ini_GetValue(&ini_file, "Bonuses", "hardcore kill");
	if (p != NULL)
		bonus[3] = 	atoi(p);
	else 
		bonus[3] =  1;

	//BD_HEALER_KILL				= 1
	p = Ini_GetValue(&ini_file, "Bonuses", "healer kill");
	if (p != NULL)
		bonus[4] = 	atoi(p);
	else 
		bonus[4] =  1;

	//BD_BUTTON_PROTECT				= 4
	p = Ini_GetValue(&ini_file, "Bonuses", "button protect");
	if (p != NULL)
		bonus[5] = 	atoi(p);
	else 
		bonus[5] =  4;

	//BD_PRIORITY_BONUS				= 2
	p = Ini_GetValue(&ini_file, "Bonuses", "priority kill");
	if (p != NULL)
		bonus[6] = 	atoi(p);
	else 
		bonus[6] =  2;
	
	//BD_WALL_BONUS					= 3
	p = Ini_GetValue(&ini_file, "Bonuses", "wall bonus");
	if (p != NULL)
		bonus[7] = 	atoi(p);
	else 
		bonus[7] =  3;
	
	//CHANGEOVER_BONUS				= 10
	p = Ini_GetValue(&ini_file, "Bonuses", "changeover");
	if (p != NULL)
		bonus[8] = 	atoi(p);
	else 
		bonus[8] =  10;

}


void InitTeams ()
{
	gi.dprintf ("Initiate teams\n");

	teams[TEAM1] = gi.TagMalloc (sizeof(team_t), TAG_GAME);
	strcpy(teams[TEAM1]->name, "Red");
	teams[TEAM1]->icon = "teams/redteam";

	teams[TEAM1]->skins[0] = "male/m-team3";
	teams[TEAM1]->skins[1] = "female/f-team3";
	teams[TEAM1]->skins[2] = "cyborg/c-team3";

	teams[TEAM1]->laser = 0xf2f2f0f0;
	teams[TEAM1]->banner = "models/objects/banner/tris.md2";
	teams[TEAM1]->banner_skin = 3;

	teams[TEAM2] = gi.TagMalloc (sizeof(team_t), TAG_GAME);
	strcpy(teams[TEAM2]->name, "Blue");
	teams[TEAM2]->icon = "teams/blueteam";

	teams[TEAM2]->skins[0] = "male/m-team2";
	teams[TEAM2]->skins[1] = "female/f-team2";
	teams[TEAM2]->skins[2] = "cyborg/c-team2";

	teams[TEAM2]->laser = 0xf3f3f1f1;
	teams[TEAM2]->banner = "models/objects/banner/tris.md2";
	teams[TEAM2]->banner_skin = 2;

	// Lab Rat, Something is going hidiously wrong with the team pointer
	// method, till I figure it out gona use teamoffset as a backup to the pointer.
	// Ah hell just use the int.

}

qboolean OnSameTeam (edict_t *targ, edict_t *attacker)
{
	if (targ->client && attacker->client)
		if (targ->client->pers.team == attacker->client->pers.team &&
			targ != attacker)
			return true;

	return false;
}

qboolean CheckTeamDamage (edict_t *targ, edict_t *attacker)
{
	if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
		return false;

	if ((int)dmflags->value & DF_NO_FRIENDLY_FIRE)
		if (targ->client && attacker->client)
			if (targ->client->pers.team == attacker->client->pers.team &&
				targ != attacker)
				return true;

	return false;
}





/*-----------------------------------------------------------------------*/

void JoinTeam(edict_t *ent, int desired_team)
{
	char *s;

	PMenu_Close(ent);

	ent->svflags &= ~SVF_NOCLIENT;
	ent->client->pers.team = desired_team;
	//ent->client->resp.ctf_state = CTF_STATE_START;
	s = Info_ValueForKey (ent->client->pers.userinfo, "skin");
	AssignSkin(ent, s);
	
	PutClientInServer (ent);
	// add a teleportation effect
	ent->s.event = EV_PLAYER_TELEPORT;
	// hold in place briefly
	ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
	ent->client->ps.pmove.pm_time = 14;
		

	gi.bprintf(PRINT_HIGH, "%s joined the %s team.\n",
		ent->client->pers.netname, teams[ent->client->pers.team]->name);
}

//This seems a little ugly, gona have to stick with it for now though.
void JoinTeam1(edict_t *ent, pmenu_t *p)
{
	JoinTeam(ent, TEAM1);
}

void JoinTeam2(edict_t *ent, pmenu_t *p)
{
	JoinTeam(ent, TEAM2);
}

void JoinTeam3(edict_t *ent, pmenu_t *p)
{
	JoinTeam(ent, TEAM3);
}

void JoinTeam4(edict_t *ent, pmenu_t *p)
{
	JoinTeam(ent, TEAM4);
}


void ChaseCam(edict_t *ent, pmenu_t *p)
{
	int i;
	edict_t *e;

	if (ent->client->chase_target) 
	{
		ent->client->chase_target = NULL;
		PMenu_Close(ent);
		return;
	}

	for (i = 1; i <= maxclients->value; i++) 
	{
		e = g_edicts + i;
		if (e->inuse && e->solid != SOLID_NOT) 
		{
			ent->client->chase_target = e;
			PMenu_Close(ent);
			ent->client->update_chase = true;
			break;
		}
	}
}


void ReturnToMain(edict_t *ent, pmenu_t *p)
{
	PMenu_Close(ent);
	OpenJoinMenu(ent);
}

void Credits(edict_t *ent, pmenu_t *p);

void DeathmatchScoreboard (edict_t *ent);

/*void ShowScores(edict_t *ent, pmenu_t *p)
{
	PMenu_Close(ent);

	ent->client->showscores = true;
	ent->client->showinventory = false;
	DeathmatchScoreboard (ent);
}*/

pmenu_t creditsmenu[] = {
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,								PMENU_ALIGN_CENTER, NULL, NULL },
	{ "Return to Main Menu",			PMENU_ALIGN_LEFT, NULL, ReturnToMain }
};

pmenu_t joinmenu[] = {
	{ NULL,						PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,						PMENU_ALIGN_CENTER, NULL, NULL },
	{ "Join Red Team",			PMENU_ALIGN_LEFT, NULL, JoinTeam1 },
	{ NULL,						PMENU_ALIGN_LEFT, NULL, NULL },
	{ "Join Blue Team",			PMENU_ALIGN_LEFT, NULL, JoinTeam2 },
	{ NULL,						PMENU_ALIGN_LEFT, NULL, NULL },
	{ "Join Green Team",		PMENU_ALIGN_LEFT, NULL, JoinTeam3 },
	{ NULL,						PMENU_ALIGN_LEFT, NULL, NULL },
	{ "Join Yellow Team",		PMENU_ALIGN_LEFT, NULL, JoinTeam4 },
	{ NULL,						PMENU_ALIGN_CENTER, NULL, NULL },
	{ NULL,						PMENU_ALIGN_CENTER, NULL, NULL },
	{ "Chase Camera",			PMENU_ALIGN_LEFT, NULL, ChaseCam },
	//{ "Credits",				PMENU_ALIGN_LEFT, NULL, Credits },
	{ NULL,						PMENU_ALIGN_LEFT, NULL, NULL },
	{ NULL,						PMENU_ALIGN_LEFT, NULL, NULL },
	{ "Use [ and ] to move cursor",		PMENU_ALIGN_LEFT, NULL, NULL },
	{ "ENTER to select",				PMENU_ALIGN_LEFT, NULL, NULL },
	{ "ESC to Exit Menu",				PMENU_ALIGN_LEFT, NULL, NULL },
	{ "(TAB to Return)",				PMENU_ALIGN_LEFT, NULL, NULL },
	{ "v" BD_STRING_VERSION,	PMENU_ALIGN_RIGHT, NULL, NULL },
};

int UpdateJoinMenu(edict_t *ent)
{
	static char levelname[32];
	static char team1players[32];
	static char team2players[32];
	static char team3players[32];
	static char team4players[32];
	static char team1name[32];
	static char team2name[32];
	static char team3name[32];
	static char team4name[32];
	int i, t, num1, num2, num3, num4;

	sprintf(team1name, "Join %s Team", teams[TEAM1]->name);
	joinmenu[2].text = team1name;
	joinmenu[2].SelectFunc = JoinTeam1;
	
	sprintf(team2name, "Join %s Team", teams[TEAM2]->name);
	joinmenu[4].text = team2name;
	joinmenu[4].SelectFunc = JoinTeam2;

	if (teams[TEAM3]) {
		sprintf(team3name, "Join %s Team", teams[TEAM3]->name);
		joinmenu[6].text = team3name;
		joinmenu[6].SelectFunc = JoinTeam3;
	} else {
		joinmenu[6].text = NULL;
		joinmenu[6].SelectFunc = NULL;
	}

	if (teams[TEAM4]) {
		sprintf(team4name, "Join %s Team", teams[TEAM4]->name);
		joinmenu[8].text = team4name;
		joinmenu[8].SelectFunc = JoinTeam4;
	} else {
		joinmenu[8].text = NULL;
		joinmenu[8].SelectFunc = NULL;
	}


	/*
	if (forcejoin->string && *ctf_forcejoin->string) {
		if (stricmp(ctf_forcejoin->string, "red") == 0) {
			joinmenu[6].text = NULL;
			joinmenu[6].SelectFunc = NULL;
		} else if (stricmp(ctf_forcejoin->string, "blue") == 0) {
			joinmenu[4].text = NULL;
			joinmenu[4].SelectFunc = NULL;
		}
	}
	*/

	
	if (ent->client->chase_target)
		joinmenu[11].text = "Leave Chase Camera";
	else
		joinmenu[11].text = "Chase Camera";
	

	levelname[0] = '*';
	if (g_edicts[0].message)
		strncpy(levelname+1, g_edicts[0].message, sizeof(levelname) - 2);
	else
		strncpy(levelname+1, level.mapname, sizeof(levelname) - 2);
	levelname[sizeof(levelname) - 1] = 0;

	//players[1] = players[2] = players[3] = players[4] = 0;
	num1 = 0;
	num2 = 0;
	num3 = 0;
	num4 = 0;
	for (i = 0; i < maxclients->value; i++) {
		if (!(g_edicts[i+1].inuse))
			continue;
		if (game.clients[i].pers.team == NOTEAM)
			continue;
		if (game.clients[i].pers.team == TEAM1)
			num1++;
		else if (game.clients[i].pers.team == TEAM2)
			num2++;
		else if (game.clients[i].pers.team == TEAM3)
			num3++;
		else if (game.clients[i].pers.team == TEAM4)
			num4++;
		//players[game.clients[i].pers.team]++;
	}

	sprintf(team1players, "  (%d players)", num1);
	sprintf(team2players, "  (%d players)", num2);
	sprintf(team3players, "  (%d players)", num3);
	sprintf(team4players, "  (%d players)", num4);
	//That seems like a waste of time.
	//Just figured out why it isn't, if you try and do it more efficently
	//you end up with either the same string repeated or a bunch of funky
	//higher ascii junk.

	joinmenu[0].text = levelname;

	if (joinmenu[2].text)
		joinmenu[3].text = team1players;
	else
		joinmenu[3].text = NULL;

	if (joinmenu[4].text)
		joinmenu[5].text = team2players;
	else
		joinmenu[5].text = NULL;

	if (joinmenu[6].text)
		joinmenu[7].text = team3players;
	else
		joinmenu[7].text = NULL;

	if (joinmenu[8].text)
		joinmenu[9].text = team4players;
	else
		joinmenu[9].text = NULL;


	t = TEAM1;
	i = num1;
	if ( (num2 < i) || ((num2 == i) && (rand() & 1)) )
	{
		t = TEAM2;
		i = num2;
	}
	if (teams[TEAM3])
	{
		if	((num3 < i) ||  ((num3 == i) && (rand() & 1)) )
		{
			t = TEAM3;
			i = num3;
		}
	}
	if (teams[TEAM4]) 
	{
		if ((num4 < i) ||	((num4 == i) && (rand() & 1) )  )  
		{
			t = TEAM4;
		}
	}
	return t;
	//Lab Rat, what, I should be shot for coding that like that!
	//And why cant this function seem to take arrays properly?
	//And I dont like team1's chance of getting picked in the event of
	//even players on each team. .5 * .5 * .5  ie FIXME
}

void OpenJoinMenu(edict_t *ent)
{
	int team;

	team = UpdateJoinMenu(ent);
	if (ent->client->chase_target)
		team = 13;
	else /*switch (team) 
	{
	case TEAM1:
		team = 4;
		break;
	case TEAM2:
		team = 6;
		break;
	case TEAM3:
		team = 8;
		break;
	case TEAM4:
		team = 10;
		break;
	}*/
	{
		team += 1;
		team *= 2;
	}

	PMenu_Open(ent, joinmenu, team, sizeof(joinmenu) / sizeof(pmenu_t));
}

void Credits(edict_t *ent, pmenu_t *p)
{
	PMenu_Close(ent);
	PMenu_Open(ent, creditsmenu, -1, sizeof(creditsmenu) / sizeof(pmenu_t));
}

qboolean StartClient(edict_t *ent)
{
	if (ent->client->pers.team != NOTEAM)
		return false;

	if (! ( (int) dmflags->value & DF_FORCEJOIN) ) 
	{
		// start as 'observer'
		ent->movetype = MOVETYPE_NOCLIP;
		ent->solid = SOLID_NOT;
		ent->svflags |= SVF_NOCLIENT;
		ent->client->pers.team = NOTEAM;
		ent->client->ps.gunindex = 0;
		gi.linkentity (ent);

		OpenJoinMenu(ent);
		return true;
	}
	return false;
}

/*
qboolean CTFCheckRules(void)
{
	if (capturelimit->value && 
		(ctfgame.team1 >= capturelimit->value ||
		ctfgame.team2 >= capturelimit->value)) {
		gi.bprintf (PRINT_HIGH, "Capturelimit hit.\n");
		return true;
	}
	return false;
}
*/

void AssignTeam(gclient_t *who)
{
	edict_t		*player;
	int i, t;
	int playercount[4];

	if (!((int)dmflags->value & DF_FORCEJOIN)) 
	{
		who->pers.team = NOTEAM;
		return;
	}

	for (i = 1; i <= maxclients->value; i++) 
	{
		player = &g_edicts[i];

		if (!player->inuse || player->client == who)
			continue;

		playercount[player->client->pers.team]++;
	}

	t = TEAM1;
	i = playercount[t];
	if ((playercount[TEAM2] < i) || ((playercount[TEAM2] == i) && (rand() & 1))) 
	{
		t = TEAM2;
		i = playercount[t];
	}
	if (teams[TEAM3]  && ( (playercount[TEAM3] < i) || ( (playercount[TEAM3] == i) && (rand() & 1) ) ) ) 
	{
		t = TEAM3;
		i = playercount[t];
	}
	if (teams[TEAM4]  && ( (playercount[TEAM3] < i) || ( (playercount[TEAM3] == i) && (rand() & 1) ) ) ) 
	{
		t = TEAM4;
	}

	who->pers.team = t;
}

/* ------------------------------------------ */

void Cmd_Team_f (edict_t *ent)
{
	char *s, *t;
	int desired_team, i;

	t = gi.args();
	if (!*t) {
		gi.cprintf(ent, PRINT_HIGH, "You are on the %s team.\n",
			teams[ent->client->pers.team]->name);
		return;
	}

	desired_team = NOTEAM;
	for (i = 0; i <= BD_MAX_TEAM; i++) {
		if (teams[i] == NULL)
			continue;
		if (Q_stricmp(t, teams[i]->name) == 0)
			desired_team = i;
	}
	if (desired_team == NOTEAM) {
		gi.cprintf(ent, PRINT_HIGH, "Unknown team %s.\n", t);
		return;
	}


	if (ent->client->pers.team == desired_team) {
		gi.cprintf(ent, PRINT_HIGH, "You are already on the %s team.\n",
			teams[ent->client->pers.team]->name);
		return;
	}

////

	ent->svflags = 0;
	ent->flags &= ~FL_GODMODE;
	ent->client->pers.team = desired_team;
	//ent->client->pers.ctf_state = CTF_STATE_START;
	s = Info_ValueForKey (ent->client->pers.userinfo, "skin");
	AssignSkin(ent, s);

	if (ent->solid == SOLID_NOT) { // spectator
		PutClientInServer (ent);
		// add a teleportation effect
		ent->s.event = EV_PLAYER_TELEPORT;
		// hold in place briefly
		ent->client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
		ent->client->ps.pmove.pm_time = 14;
		gi.bprintf(PRINT_HIGH, "%s joined the %s team.\n",
			ent->client->pers.netname, teams[ent->client->pers.team]->name);
		return;
	}


	ent->health = 0;
	player_die (ent, ent, ent, 100000, vec3_origin);
	// don't even bother waiting for death frames
	ent->deadflag = DEAD_DEAD;
	respawn (ent);

	ent->client->resp.score = 0;

	gi.bprintf(PRINT_HIGH, "%s changed to the %s team.\n",
		ent->client->pers.netname, teams[ent->client->pers.team]->name);
}


qboolean AssignSkin(edict_t *ent, char *s)
{
	int playernum = ent-g_edicts-1, i;
	char *p, *q;
	char t[32], r[32];
	team_t *myteam;

	if (ent->client->pers.team == NOTEAM)
		return false;
	myteam = teams[ent->client->pers.team];

	//First check to see that we dont already have an alowed skin.
	for (i = 0; i < 2; i++) {
		if (myteam->skins[0] == NULL)
			continue;
		if (Q_stricmp(s, myteam->skins[i]) == 0)
			return false; //ie we haven't changed it
	}

	Com_sprintf(t, sizeof(t), "%s", s);

	//Find out what model we want to be
	if ((p = strrchr(t, '/')) != NULL)
		p[1] = 0;
	else
	//Default to male/
		strcpy(t, "male/");
	
	//Now find the first skin with matching model
	for (i = 0; i <= BD_MAX_TEAM_SKINS; i++) {
		if (myteam->skins[i] == NULL)
			continue;
		Com_sprintf(r, sizeof(r), "%s", myteam->skins[i]);
		if((q = strrchr(r, '/')) != NULL)
			q[1] = 0;

		if (Q_stricmp(t, r) == 0) {
			gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s", 
				ent->client->pers.netname, myteam->skins[i]) );

			return true; //we have changed it
		}
	}

	//If we've got this far somethings gone wrong
	//find 1st team skin & model and use it.
	for (i = 0; i <= BD_MAX_TEAM_SKINS; i++) {
		if (myteam->skins[i] == NULL)
			continue;
		gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s", 
			ent->client->pers.netname, myteam->skins[i]) );

		return true; //we have changed it
	}
	
	return false;
}


/*
==================
TeamplayScoreboardMessage

==================
*/
void TeamplayScoreboardMessage (edict_t *ent, edict_t *killer)
{
	char	entry[1024];
	char	string[1400];
	char	msg[3][256];
	int		stringlength;
	int		i, j, k;
	team_t	*sorted[BD_MAX_TEAM];
	int		pings[BD_MAX_TEAM + 1];
	int		players[BD_MAX_TEAM + 1];
	int		score, total;
	int		teamnum, scorenum;
	int		x, y;

	players[0] = players[1] = players[2] = players[3] = players[4] = 0;
	pings[0] = pings[1] = pings[2] = pings[3] = pings[4] = 0;

	for (i=0 ; i<game.maxclients ; i++)
	{
		if (!(g_edicts[i+1].inuse))
			continue;
		//if (!(teams[g_edicts[i+1].client->pers.team]))
		//	continue;
		players[g_edicts[i+1].client->pers.team]++;
		pings[g_edicts[i+1].client->pers.team] += g_edicts[i+1].client->ping;
	}

	// sort the teams by score
	total = 0;
	for (i=0 ; i<=BD_MAX_TEAM ; i++)
	{
		if (!(teams[i]))
			continue;
		score = teams[i]->total_score;
		for (j=0 ; j<total ; j++)
		{
			if (score > sorted[j]->total_score)
				break;
		}
		for (k=total ; k>j ; k--)
		{
			sorted[k] = sorted[k-1];
		}
		sorted[j] = teams[i];
		total++;
	}

	// print level name and exit rules
	string[0] = 0;
	stringlength = strlen(string);

	// add the teams in sorted order
	if (total > 12)
		total = 12;

	for (i=0 ; i<total ; i++)
	{
		if (!sorted[i])
			continue;

		x = 60; //(i>=6) ? 160 : 0;
		y = 32 + 26 * (i%6);

		// add a dogtag

		/*if (cl_ent == ent)
			tag = "tag1";
		else if (cl_ent == killer)
			tag = "tag2";
		else
			tag = NULL;
		if (tag)
		{
			Com_sprintf (entry, sizeof(entry),
				"xv %i yv %i picn %s ",x+32, y, tag);
			j = strlen(entry);
			if (stringlength + j > 1024)
				break;
			strcpy (string + stringlength, entry);
			stringlength += j;
		}*/


		teamnum = TeamNumber(sorted[i]);
		scorenum = 15 + teamnum;

		Com_sprintf(msg[0], sizeof(msg[0]), "Team: %s\n",
			sorted[i]->name);
		if (players[teamnum] > 0)
			Com_sprintf(msg[1], sizeof(msg[1]), "Ave. Ping: %i\n",
				pings[teamnum]/players[teamnum]);
		else 
			strcpy(msg[1], "Ave. Ping: 0\n");
		Com_sprintf(msg[2], sizeof(msg[2]), "Players:   %i\n",
			players[teamnum]);

		// send the layout
		Com_sprintf (entry, sizeof(entry),
			"xv %i yv %i picn \"%s\" "
			"xv %i yv %i string2 \"%s\" "
			"xv %i yv %i string \"%s\" "
			"xv %i yv %i string \"%s\" "
			"xv %i yv %i num 3 %i ",
			x,			y,		sorted[i]->icon, 
			x + 26,		y,		msg[0], 
			x + 26,		y+8,	msg[1], 
			x + 26,		y+16,	msg[2], 
			x + 160,	y,		scorenum);
		j = strlen(entry);
		if (stringlength + j > 1024)
		{
			gi.dprintf ("Overrun string length in teamplay scoreboard\n");
			break;
		}
		strcpy (string + stringlength, entry);
		stringlength += j;
	}

	gi.WriteByte (svc_layout);
	gi.WriteString (string);
}


/*
==================
TeamplayScoreboard

Draw instead of help message.
Note that it isn't that hard to overflow the 1400 byte message limit!
==================
*/
void TeamplayScoreboard (edict_t *ent)
{
	TeamplayScoreboardMessage (ent, ent->enemy);
	gi.unicast (ent, true);
}

//Lab Rat - Uck, a hack, could be a better way round it later. (ie FIXME)
int TeamNumber (team_t *team)
{
	int i;
	for (i=0; i <= BD_MAX_TEAM; i++) {
		if (!teams[i])
			continue;
		if (teams[i] == team)
			return i;
	}
}

/*
==================
TeamScores

Calculates the actual score that each team has got.
This is because team scores are adjusted on-the-fly whenever a players score is 
changed.  This saves processor cycles during the teamscoreborad functions, and eases
plenty of headaches.  However, it can't catch events like players dropping, so every
now and again we ought to work out the real team score fom the players scores.
==================
*/
void TeamScores ()
{
	int i;

	// zero all the teamscores, saves having a temp array
	// and i doubt anything will need the scores half-way through this function.
	for (i=0; i <= BD_MAX_TEAM; i++) 
	{
		if (!teams[i])
			continue;
		teams[i]->total_score = 0;
	}

	// loop through the players adding on their scores to the team total
	for (i=0; i<game.maxclients; i++)
	{
		if (!(g_edicts[i+1].inuse))
			continue;
		if (!(teams[g_edicts[i+1].client->pers.team]))
			continue;
		teams[g_edicts[i+1].client->pers.team]->total_score += g_edicts[i+1].client->resp.score;
	}
}

/*
==================
TeamScoreReport

Give a text update to all players about the teams scores
Maybe later.
==================
*/
void TeamScoreReport ()
{
	//team_sort *current;
	level.next_score_time = level.time + (SCORE_TIME * 60);

	//Check the latest scores
	TeamScores ();
}

