/*
   Copyright (C) 1997-2001 Id Software, Inc.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

   See the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 */

#include "g_local.h"
#include "g_gametypes.h"
#include "g_gametype_da.h"

#ifdef DUEL_ARENA
qboolean G_Gametype_DA_Match_Tied( void )
{
	int maxscore = 0;
	int count = 0;
	edict_t	*e;
	for( e = game.edicts+1; PLAYERNUM( e ) < game.maxclients; e++ )
	{
		if( !e->r.inuse )
			continue;
		if( maxscore < match.scores[PLAYERNUM( e )].score )
			maxscore =  match.scores[PLAYERNUM( e )].score;
	}
	for( e = game.edicts+1; PLAYERNUM( e ) < game.maxclients; e++ )
	{
		if( !e->r.inuse )
			continue;
		if( maxscore == match.scores[PLAYERNUM( e )].score )
			count++;
		if( count > 1 )
			return qtrue;
	}
	return qfalse;
}
void G_Gametype_DA_SetUpEndMatch( void )
{
	edict_t *ent;

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < game.maxclients; ent++ )
	{
		if( ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
			G_ClearPlayerStateEvents( ent->r.client );
	}

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS,
	                  qtrue );
	match.pickableItemsMask = 0; // disallow item pickup

	G_GameType_BeginPostMatch();
}
void G_Gametype_DA_ScoreboardMessage_AddSpectators( void )
{
	char entry[MAX_TOKEN_CHARS];
	int i, clstate;
	edict_t	*e;
	size_t len;

	len = strlen( scoreboardString );
	if( !len )
		return;

	e = G_Teams_BestInChallengersQueue( 0, NULL );
	while( e )
	{
		//spectator tab entry
		if( e->r.client->pers.connecting == qtrue || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED )
		{

		}
		else
		{
			*entry = 0;
			Q_snprintfz( entry, sizeof( entry ), "&w %i %i %i %i ",
			             PLAYERNUM( e ),
			             match.scores[PLAYERNUM( e )].score,
			             e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping,
			             match.ready[PLAYERNUM( e )]
			             );

			if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
			{
				Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
				len = strlen( scoreboardString );
			}
		}

		e = G_Teams_BestInChallengersQueue( e->r.client->pers.queueTimeStamp, e );
	}

	//add spectator team
	for( i = 0; teamlist[TEAM_SPECTATOR].playerIndices[i] != -1; i++ )
	{
		e = game.edicts + teamlist[TEAM_SPECTATOR].playerIndices[i];
		if( e->r.client->pers.connecting == qtrue || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED )
			continue;

		//spectator tab entry
		*entry = 0;
		if( !e->r.client->pers.queueTimeStamp )
		{ // not in challenger queue
			Q_snprintfz( entry, sizeof( entry ), "&s %i %i ",
			             PLAYERNUM( e ),
			             e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping );
		}

		if( *entry )
		{
			if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
			{
				Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
				len = strlen( scoreboardString );
			}
		}
	}

	//add connecting spectators
	for( i = 0; teamlist[TEAM_SPECTATOR].playerIndices[i] != -1; i++ )
	{
		e = game.edicts + teamlist[TEAM_SPECTATOR].playerIndices[i];

		//spectator tab entry
		*entry = 0;
		clstate = trap_GetClientState( PLAYERNUM( e ) );
		if( e->r.client->pers.connecting == qtrue || ( clstate >= CS_CONNECTED && clstate < CS_SPAWNED ) )
			Q_snprintfz( entry, sizeof( entry ), "&c %i", PLAYERNUM( e ) );
		if( *entry )
		{
			if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
			{
				Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
				len = strlen( scoreboardString );
			}
		}
	}
}

char *G_Gametype_DA_ScoreboardMessage( void )
{
	char entry[MAX_TOKEN_CHARS];
	size_t len;
	int i, team;
	edict_t	*e;

	//fixed layout scheme id
	Q_snprintfz( scoreboardString, sizeof( scoreboardString ), "scb \"&das " );
	len = strlen( scoreboardString );
	*entry = 0; // wsw : aiwa : fix unitialized value heisenbug

	//it's not sending the player in score order (yet)
	for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
	{
		for( i = 0; teamlist[team].playerIndices[i] != -1; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];

			//player tab entry
			*entry = 0;
			Q_snprintfz( entry, sizeof( entry ), "&p %i %i %i %i %i %i %i ",
			             e->s.team,
			             PLAYERNUM( e ),
			             match.scores[PLAYERNUM( e )].score,
			             match.scores[PLAYERNUM( e )].kills,
			             match.scores[PLAYERNUM( e )].deaths,
			             match.scores[PLAYERNUM( e )].suicides,
			             e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping );

			if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
			{
				Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
				len = strlen( scoreboardString );
			}
		}
	}

	G_Gametype_DA_ScoreboardMessage_AddSpectators();

	// add player stats (all weapon weak/strong 0..99) to scoreboard message
	//	G_ScoreboardMessage_AddPlayerStats( ent );

	// add closing quote
	if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
	{
		Q_strncatz( scoreboardString, "\"", sizeof( scoreboardString ) );
		len = strlen( scoreboardString );
	}
	return scoreboardString;
}

static qboolean G_Match_DA_CountDownAnnounces( void )
{
	static int lastsecond;
	static float remainingtime;
	static int remainingseconds;

	if( match.roundstate >= MATCH_STATE_POSTMATCH )
		return qfalse;

	if( !match.roundendtime )
		return qfalse;

	remainingtime = (float)( match.roundendtime - level.time ) * 0.001f;
	remainingseconds = (int)remainingtime;

	//do the next operations only once per second
	if( lastsecond == remainingseconds )
		return qfalse;

	lastsecond = remainingseconds;

	//print some countdowns
	if( match.roundstate == MATCH_STATE_COUNTDOWN )
	{
		if( 1 + remainingseconds <= g_countdown_time->integer )
		{
			char *names[2];
			int num = 0;
			int team;
			edict_t *e;

			for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
			{
				int i;
				if( !teamlist[team].numplayers )
					continue;
				for( i = 0; teamlist[team].playerIndices[i] != -1; i++ )
				{
					e = game.edicts + teamlist[team].playerIndices[i];
					if( !e->r.inuse )
						continue;
					if( e->r.client->is_coach )  // ignore coachs
						continue;
					if( num >= 2 )
						break;
					names[num] = e->r.client->pers.netname;
					num++;
				}
			}

			//countdown sound
			if( 1 + remainingseconds < 4 )
				G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2,
				                                             1 + remainingseconds, 1 ) ), GS_MAX_TEAMS, qfalse ); // todo: use random countdown set for all three numbers
			if( num == 2 )
				G_CenterPrintMsg( NULL, "%s " S_COLOR_WHITE "vs " S_COLOR_WHITE "%s" S_COLOR_WHITE "\n%i\n", names[0], names[1], 1 + remainingseconds );
		}
	}
	else if( match.roundstate == MATCH_STATE_PLAYTIME )
	{
		if( ( 1 + remainingseconds <= g_countdown_time->integer ) && g_timelimit->integer )
		{
			G_CenterPrintMsg( NULL, "%i\n", 1 + remainingseconds );
		}
	}

	return qtrue;
}

qboolean G_Gametype_DA_ClientRespawn( edict_t *self )
{
	int index, i;
	edict_t *spawnpoint;
	vec3_t spawn_origin, spawn_angles;
	gclient_t *client;
	client_respawn_t resp;
	client_teamchange_t teamchange;
	client_persistant_t pers;
	char userinfo[MAX_INFO_STRING];
	weapon_info_t *weaponinfo;
	int ammocount, weakammocount;

	self->r.svflags &= ~SVF_NOCLIENT;

	//if invalid be spectator
	if( self->s.team < 0 || self->s.team >= GS_MAX_TEAMS )
		self->s.team = TEAM_SPECTATOR;

	GClip_UnlinkEntity( self );

	index = self-game.edicts-1;
	client = self->r.client;

	// deathmatch wipes most client data every spawn
	resp = client->resp;
	teamchange = client->teamchange;
	pers = client->pers;
	memcpy( userinfo, client->pers.userinfo, sizeof( userinfo ) );
	memset( client, 0, sizeof( *client ) );
	client->resp = resp;
	client->teamchange = teamchange;
	client->pers = pers;

	self->deadflag = DEAD_NO;
	ClientUserinfoChanged( self, userinfo );

	// clear entity values
	memset( &self->snap, 0, sizeof( self->snap ) );
	self->groundentity = NULL;
	self->r.client = &game.clients[index];
	self->takedamage = DAMAGE_AIM;
	self->movetype = MOVETYPE_PLAYER;
	self->think = player_think;
	self->pain = player_pain;
	self->die = player_die;
	self->viewheight = playerbox_stand_viewheight;
	self->r.inuse = qtrue;
	self->mass = 200;
	self->r.solid = SOLID_BBOX;
	self->air_finished = level.time + ( 12*1000 );
	self->r.clipmask = MASK_PLAYERSOLID;
	self->waterlevel = 0;
	self->watertype = 0;
	self->flags &= ~FL_NO_KNOCKBACK;
	self->r.svflags &= ~SVF_CORPSE;
	//MbotGame[start]

	self->enemy = NULL;
	self->r.owner = NULL;

	if( self->ai.type == AI_ISBOT )
	{
		self->think = AI_Think;
		self->classname = "bot";
	}
	else if( self->r.svflags & SVF_FAKECLIENT )
	{
		self->classname = "fakeclient"; //[end]
	}
	else
	{
		self->classname = "player";
	}

	VectorCopy( playerbox_stand_mins, self->r.mins );
	VectorCopy( playerbox_stand_maxs, self->r.maxs );
	VectorClear( self->velocity );
	VectorClear( self->avelocity );

	// clear playerstate values
	memset( &self->r.client->ps, 0, sizeof( client->ps ) );

	client->ps.POVnum = ENTNUM( self );

	// clear entity state values
	self->s.type = ET_PLAYER;
	self->s.effects = 0;
	self->s.light = 0;

	// modelindex and skinnum are set at calling to update userinfo
	self->s.frame = 0;
	self->s.weapon = 0;

	self->fall_fatal = qfalse;

	SelectSpawnPoint( self, &spawnpoint, spawn_origin, spawn_angles, 400 );
	VectorCopy( spawn_origin, client->ps.pmove.origin );
	client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
	VectorCopy( spawn_origin, self->s.origin );
	VectorCopy( self->s.origin, self->s.old_origin );

	// set angles
	self->s.angles[PITCH] = 0;
	self->s.angles[YAW] = spawn_angles[YAW];
	self->s.angles[ROLL] = 0;
	VectorCopy( self->s.angles, client->ps.viewangles );

	// set the delta angle
	for( i = 0; i < 3; i++ )
		client->ps.pmove.delta_angles[i] = ANGLE2SHORT( self->s.angles[i] ) - client->pers.cmd_angles[i];

	//if invalid join spectator
	if( self->s.team < 0 || self->s.team >= GS_MAX_TEAMS )
		self->s.team = TEAM_SPECTATOR;

	//don't put spectators in the game
	if( self->s.team == TEAM_SPECTATOR )
	{
		self->movetype = MOVETYPE_NOCLIP;
		self->r.solid = SOLID_NOT;
		self->r.svflags |= SVF_NOCLIENT;
	}
	else
	{
		if( KillBox( self ) )
		{       // telefragged someone?
		}

		// add a teleportation effect
		G_SpawnTeleportEffect( self );
	}

	self->s.teleported = qtrue;

	// hold in place briefly
	self->r.client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
	self->r.client->ps.pmove.pm_time = 14;

	BOT_Respawn( self ); //MbotGame

	// wsw: pb set default max health
	self->max_health = 100;
	self->health = self->max_health;

	self->r.client->buttons = 0;

	// resetting award stats
	memset( &self->r.client->awardInfo, 0, sizeof( award_info_t ) );

	//give default items
	memset( &self->r.client->inventory, 0, sizeof( self->r.client->inventory ) );
	if( self->s.team == TEAM_SPECTATOR )
	{
		G_UseTargets( spawnpoint, self );
	}
	else
	{
		if( g_instagib->integer )
		{
			self->r.client->inventory[WEAP_INSTAGUN] = 1;
			self->r.client->inventory[AMMO_INSTAS] = 1;
			self->r.client->inventory[AMMO_WEAK_INSTAS] = 1;
		}
		else
		{
			self->r.client->inventory[WEAP_GUNBLADE] = 1;
			self->r.client->inventory[AMMO_WEAK_GUNBLADE] = DA_AMMO_WEAK_GUNBLADE;

			self->r.client->inventory[WEAP_RIOTGUN] = 1;
			self->r.client->inventory[AMMO_WEAK_SHELLS] = DA_AMMO_WEAK_SHELLS;

			self->r.client->inventory[WEAP_GRENADELAUNCHER] = 1;
			self->r.client->inventory[AMMO_WEAK_GRENADES] = DA_AMMO_WEAK_GRENADES;

			self->r.client->inventory[WEAP_ROCKETLAUNCHER] = 1;
			self->r.client->inventory[AMMO_WEAK_ROCKETS] = DA_AMMO_WEAK_ROCKETS;

			self->r.client->inventory[WEAP_PLASMAGUN] = 1;
			self->r.client->inventory[AMMO_WEAK_PLASMA] = DA_AMMO_WEAK_PLASMA;

			self->r.client->inventory[WEAP_LASERGUN] = 1;
			self->r.client->inventory[AMMO_WEAK_LASERS] = DA_AMMO_WEAK_LASERS;

			self->r.client->inventory[WEAP_ELECTROBOLT] = 1;
			self->r.client->inventory[AMMO_WEAK_BOLTS] = DA_AMMO_WEAK_BOLTS;

			self->r.client->inventory[WEAP_GUNBLADE] = 1;
			self->r.client->inventory[AMMO_CELLS] = DA_AMMO_CELLS;

			self->r.client->inventory[WEAP_RIOTGUN] = 1;
			self->r.client->inventory[AMMO_SHELLS] = DA_AMMO_SHELLS;

			self->r.client->inventory[WEAP_GRENADELAUNCHER] = 1;
			self->r.client->inventory[AMMO_GRENADES] = DA_AMMO_GRENADES;

			self->r.client->inventory[WEAP_ROCKETLAUNCHER] = 1;
			self->r.client->inventory[AMMO_ROCKETS] = DA_AMMO_ROCKETS;

			self->r.client->inventory[WEAP_PLASMAGUN] = 1;
			self->r.client->inventory[AMMO_PLASMA] = DA_AMMO_PLASMA;

			self->r.client->inventory[WEAP_LASERGUN] = 1;
			self->r.client->inventory[AMMO_LASERS] = DA_AMMO_LASERS;

			self->r.client->inventory[WEAP_ELECTROBOLT] = 1;
			self->r.client->inventory[AMMO_BOLTS] = DA_AMMO_BOLTS;

			self->max_health = g_ca_health->integer;
			self->health = self->max_health;
			self->r.client->armortag = ARMOR_RA;
			self->r.client->armor = g_ca_armor->integer;
		}

		G_UseTargets( spawnpoint, self );

		for( i = WEAP_TOTAL - 1; i >= WEAP_GUNBLADE; i-- )
		{
			if( i == WEAP_SHOCKWAVE )  // FIXME!!!
				continue;

			if( !self->r.client->inventory[i] )
				continue;

			if( g_select_empty->integer )
				break;

			weaponinfo = &gs_weaponInfos[i];

			if( weaponinfo->firedef->usage_count && weaponinfo->firedef->ammo_id )
				ammocount = self->r.client->inventory[weaponinfo->firedef->ammo_id];
			else
				ammocount = weaponinfo->firedef->usage_count;

			if( weaponinfo->firedef_weak->usage_count && weaponinfo->firedef_weak->ammo_id )
				weakammocount = self->r.client->inventory[weaponinfo->firedef_weak->ammo_id];
			else
				weakammocount = weaponinfo->firedef_weak->usage_count;

			if( ammocount >= weaponinfo->firedef->usage_count || weakammocount >= weaponinfo->firedef_weak->usage_count )
				break;
		}
		self->r.client->latched_weapon = i;

		// FIXME: forcing RL to be used if available
		if( self->r.client->inventory[WEAP_ROCKETLAUNCHER] )
		{
			if( g_select_empty->integer )
				self->r.client->latched_weapon = WEAP_ROCKETLAUNCHER;

			weaponinfo = &gs_weaponInfos[WEAP_ROCKETLAUNCHER];

			if( weaponinfo->firedef->usage_count && weaponinfo->firedef->ammo_id )
				ammocount = self->r.client->inventory[weaponinfo->firedef->ammo_id];
			else
				ammocount = weaponinfo->firedef->usage_count;

			if( weaponinfo->firedef_weak->usage_count && weaponinfo->firedef_weak->ammo_id )
				weakammocount = self->r.client->inventory[weaponinfo->firedef_weak->ammo_id];
			else
				weakammocount = weaponinfo->firedef_weak->usage_count;

			if( ammocount >= weaponinfo->firedef->usage_count || weakammocount >= weaponinfo->firedef_weak->usage_count )
				self->r.client->latched_weapon = WEAP_ROCKETLAUNCHER;
		}

		ChangeWeapon( self );
		self->r.client->weaponstate.status = WEAPON_ACTIVATING;
		self->r.client->weaponstate.nexttime = WEAPON_RESPAWN_DELAY;
	}

	GClip_LinkEntity( self );
	return qtrue;
}

void G_Gametype_DA_FragBonuses( edict_t *targ, edict_t *inflictor, edict_t *attacker, int mod )
{
	if( targ->s.team < TEAM_ALPHA || targ->s.team >= GS_MAX_TEAMS )
		return; // whoever died isn't on a team

	// add frag to scores

	if( !attacker->r.client ) // killed by the world
	{
		if( attacker == world && targ->r.client )
		{
			if( mod == MOD_FALLING )  //should have cratereds++
				match.scores[PLAYERNUM( targ )].suicides++;

			match.scores[PLAYERNUM( targ )].deaths++;
			match.scores[PLAYERNUM( targ )].score--;
		}
		return;
	}

	//selffrag or teamfrag
	if( targ->s.team == attacker->s.team )
	{
		match.scores[PLAYERNUM( attacker )].score--;
		if( targ == attacker )
			match.scores[PLAYERNUM( attacker )].suicides++;
		else
			match.scores[PLAYERNUM( attacker )].teamfrags++;
	}
	else
	{
		match.scores[PLAYERNUM( attacker )].score++;
		match.scores[PLAYERNUM( attacker )].kills++;
	}

	if( !targ->r.client )  //can't count deaths on non-clients
		return;

	match.scores[PLAYERNUM( targ )].deaths++;

	if( targ->s.team != attacker->s.team )
	{
		G_PrintMsg( targ, "You were killed by %s %s(health: %i, armor: %i)\n", attacker->r.client->pers.netname, S_COLOR_WHITE, HEALTH_TO_INT( attacker->health ), ARMOR_TO_INT( attacker->r.client->armor ) );
	}
}

void G_Gametype_DA_NextPlayer( void )
{
	edict_t	*e;
	int team;
	char userinfo[MAX_INFO_STRING];
	for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
	{
		int i;
		if( teamlist[team].numplayers == 0 )
		{
			client_scores_t score;
			client_respawn_t resp;
			e = G_Teams_BestInChallengersQueue( 0, NULL );
			score = match.scores[PLAYERNUM( e )];
			resp = e->r.client->resp;
			G_Teams_JoinAnyTeam( e, qtrue );
			match.scores[PLAYERNUM( e )] = score;
			e->r.client->resp = resp;
			memcpy( userinfo, e->r.client->pers.userinfo, sizeof( userinfo ) );
			ClientUserinfoChanged( e, userinfo );
			break;
		}
		for( i = 0; teamlist[team].playerIndices[i] != -1; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			if( !e->r.inuse )
				continue;
			if( e->r.client->is_coach )  // ignore coachs
				continue;
			if( e->r.solid == SOLID_NOT )
			{
				client_scores_t score;
				client_respawn_t resp;
				score = match.scores[PLAYERNUM( e )];
				resp = e->r.client->resp;
				G_Teams_SetTeam( e, TEAM_SPECTATOR );
				e->r.client->pers.queueTimeStamp = 0;
				match.scores[PLAYERNUM( e )] = score;
				e->r.client->resp = resp;
				G_Teams_JoinChallengersQueue( e );

				e = G_Teams_BestInChallengersQueue( 0, NULL );
				score = match.scores[PLAYERNUM( e )];
				resp = e->r.client->resp;
				G_Teams_JoinAnyTeam( e, qtrue );
				match.scores[PLAYERNUM( e )] = score;
				e->r.client->resp = resp;
				memcpy( userinfo, e->r.client->pers.userinfo, sizeof( userinfo ) );
				ClientUserinfoChanged( e, userinfo );
			}
		}
	}
	G_Match_RespawnAllClients();
}

int G_Gametype_DA_GetAlivePlayerCount( void )
{
	edict_t	*e;
	int team;
	int alive = 0;
	qboolean is_all_dead[GS_MAX_TEAMS] = { qtrue };

	// update is_all_dead[] and alive_team.
	for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
	{
		int i;
		is_all_dead[team] = qtrue;
		if( !teamlist[team].numplayers )
			continue;
		for( i = 0; teamlist[team].playerIndices[i] != -1; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			if( !e->r.inuse )
				continue;
			if( e->r.client->is_coach )  // ignore coachs
				continue;
			if( !G_IsDead( e ) )
				is_all_dead[team] = qfalse;
		}
		if( !is_all_dead[team] )
			alive++;
	}
	return alive;
}
void G_Gametype_DA_UpdatHudScores( void )
{
	edict_t	*e;
	int team;

	for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
	{
		int i;
		if( !teamlist[team].numplayers )
			continue;
		for( i = 0; teamlist[team].playerIndices[i] != -1; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			teamlist[e->s.team].teamplayerscores = match.scores[PLAYERNUM( e )].score;
			teamlist[e->s.team].teamscore = match.scores[PLAYERNUM( e )].score;
		}
	}
}


qboolean G_Gametype_DA_PlayersInChallengersQueue( void )
{
	if( G_Teams_BestInChallengersQueue( 0, NULL ) != NULL )
		return qtrue;
	return qfalse;
}

int G_Gametype_DA_GetPlayersCount( void )
{
	int team;
	int playercount = 0;
	for( team = TEAM_ALPHA; team < TEAM_ALPHA + g_maxteams->integer; team++ )
	{
		if( teamlist[team].numplayers )
			playercount++;
	}
	return playercount;
}

int G_Gametype_DA_GetPlayersInChallengersQueueCount( void )
{
	edict_t	*e;
	int playercount = 0;
	e = G_Teams_BestInChallengersQueue( 0, NULL );
	while( e )
	{
		playercount++;
		e = G_Teams_BestInChallengersQueue( e->r.client->pers.queueTimeStamp, e );
	}
	return playercount;
}

qboolean G_Gametype_DA_ScorelimitHit( void )
{
	edict_t	*e;

	if( g_scorelimit->integer )
	{
		for( e = game.edicts+1; PLAYERNUM( e ) < game.maxclients; e++ )
		{
			if( !e->r.inuse )
				continue;

			if( match.scores[PLAYERNUM( e )].score >= g_scorelimit->integer )
				return qtrue;
		}
	}

	return qfalse;
}

void G_Gametype_DA_RemoveAllClient( void )
{
	edict_t	*e;
	for( e = game.edicts+1; PLAYERNUM( e ) < game.maxclients; e++ )
	{
		if( !e->r.inuse )
			continue;
		G_Teams_JoinTeam( e, TEAM_SPECTATOR );
		G_Teams_LeaveChallengersQueue( e );
	}
}

void G_Gametype_DA_CheckRoundRules( void )
{
	if( match.roundstate == MATCH_STATE_PLAYTIME )
	{                                         // Round is running
		int alive_players = G_Gametype_DA_GetAlivePlayerCount();
		if( alive_players <= 1 )
		{
			int playercount = G_Gametype_DA_GetPlayersCount();
			if( playercount >= 2 )
			{
				match.roundstate = MATCH_STATE_POSTMATCH;
				match.roundstarttime = level.time;
				match.roundendtime = level.time + fabs( G_POSTMATCH_TIMELIMIT );
				G_Match_RemoveAllClientLasers();
				G_Gametype_DA_UpdatHudScores();
			}
			else
			{
				match.roundstate = MATCH_STATE_NONE;
			}
		}
	}
	else if( match.roundstate == MATCH_STATE_POSTMATCH )
	{                                                 // Round is done
		if( !match.roundendtime || level.time < match.roundendtime )
		{
			if( G_Gametype_DA_ScorelimitHit() )
			{
				//G_Gametype_DA_RemoveAllClient();
				G_Match_SetUpNextState();
				return;
			}
			if( G_Gametype_DA_GetAlivePlayerCount == 0 )
			{
				G_CenterPrintMsg( NULL, "DRAW!\n" );
			}
		}
		else
		{
			int playercount = G_Gametype_DA_GetPlayersInChallengersQueueCount();
			if( G_Gametype_DA_GetAlivePlayerCount == 0 )
			{
				G_Match_RespawnAllClients();
			}
			else
			{
				if( playercount <= 0 )
				{
					playercount = G_Gametype_DA_GetPlayersCount();
					if( playercount == 2 )
						G_Match_RespawnAllClients();
					else
						match.roundstate = MATCH_STATE_NONE;
				}
				else
				{
					G_Gametype_DA_NextPlayer();
				}
			}
			G_Gametype_DA_UpdatHudScores();
			match.roundstate = MATCH_STATE_COUNTDOWN;
			match.roundstarttime = level.time;
			match.roundendtime = level.time + (int)( fabs( g_countdown_time->value )*1000 );
			G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, qtrue );
		}
	}
	else if( match.roundstate == MATCH_STATE_COUNTDOWN )
	{                                                 // Round statring
		if( !match.roundendtime || level.time < match.roundendtime )
		{
			if( G_Gametype_DA_GetPlayersCount() != 2 )
				match.roundstate = MATCH_STATE_NONE;
		}
		else
		{
			match.roundstate = MATCH_STATE_PLAYTIME;
			match.roundstarttime = level.time;
			match.roundendtime = match.endtime;
			G_Match_RemoveAllClientLasers();
			G_Match_RemoveAllProjectiles();
			trap_GameCmd( NULL, "autr altstart");
			G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, qtrue );
			G_CenterPrintMsg( NULL, "FIGHT!\n" );
			G_UpdatePlayersMatchMsgs();
		}
	}
	else
	{
		// match.roundstate == MATCH_STATE_NONE
		//match.state = MATCH_STATE_WARMUP;
		int playercount = G_Gametype_DA_GetPlayersCount();
		int challengercount = G_Gametype_DA_PlayersInChallengersQueue();
		
		if( ( playercount + challengercount ) >= 2)
		{
			G_Gametype_DA_NextPlayer();
			G_Match_RespawnAllClients();
			match.roundstate = MATCH_STATE_COUNTDOWN;
			match.roundstarttime = level.time;
			match.roundendtime = level.time + (int)( fabs( g_countdown_time->value )*1000 );
			G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, qtrue );
		}
		else
		{
			G_Match_SetUpNextState();
		}
	}
}

void G_Gametype_DA_CheckRules( void )
{
	if( match.state >= MATCH_STATE_POSTMATCH )
		return;

	if( game.gametype != GAMETYPE_DA )
		return;

	if( G_Match_DA_CountDownAnnounces() )
	{
	}

	if( match.state == MATCH_STATE_WARMUP )
	{
		int playercount = G_Gametype_DA_GetPlayersCount();
		G_CenterPrintMsg( NULL, "Waiting for Players!\n" );
		if( G_Gametype_DA_PlayersInChallengersQueue() )
			G_Teams_ExecuteChallengersQueue();
		if( playercount >= 2 )
		{
			G_Match_RespawnAllClients();
			G_UpdatePlayersMatchMsgs();
			match.starttime = level.time;
			if( g_timelimit->value )
				match.endtime = level.time + (int)( fabs( 60 * g_timelimit->value )*1000 );
			else
				match.endtime = 0;
			G_Match_Autorecord_Start();
			match.state = MATCH_STATE_PLAYTIME;
			match.roundstate = MATCH_STATE_COUNTDOWN;
			match.roundstarttime = level.time;
			match.roundendtime = level.time + (int)( fabs( g_countdown_time->value )*1000 );
			G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_GET_READY_TO_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, qtrue );
			G_UpdatePlayersMatchMsgs();
		}
	}

	if( match.state != MATCH_STATE_PLAYTIME )
		return;

	G_Gametype_DA_CheckRoundRules();
}

#endif
