#include "g_local.h"

void PunkBot_Go(edict_t *ent);
void DogBot_Go (edict_t *ent);

void ClientBeginDeathmatch (edict_t *ent);
void DeathmatchScoreboard (edict_t *ent);
void removedogs(edict_t *ent);
int	 vote_set[9];        // stores votes for next map

char admincode[16];		 // the admincode
char default_map[32];    // default settings
char default_teamplay[16];
char default_dmflags[16];
char default_password[16];
char default_timelimit[16];
char default_cashlimit[16];
char default_fraglimit[16];
char default_dm_realmode[16];
char custom_map_filename[32];  // stores where various files can be found
char ban_name_filename[32];
char ban_ip_filename[32];
int allow_map_voting;
int disable_admin_voting;
int scoreboard_first;
int fph_scoreboard;
int total_rank;          // used in calculating maps picks based on weight
int num_custom_maps;
int num_netnames;
int num_ips;

int fixed_gametype;
int enable_password;
char rconx_file[32];
int num_rconx_pass;
int keep_admin_status;
int default_random_map;
int disable_anon_text;
int specrate;

MOTD_t	MOTD[20];

player_t playerlist[64];

ban_t	netname[100];
ban_t	ip[100];

ban_t	rconx_pass[100];


//==============================================================
//
// Papa - This file contains all the functions that control the 
//        modes a server may be in.
//
//===============================================================

void PublicSetup (edict_t *ent)  // returns the server into ffa mode and resets all the cvars (settings)
{
	edict_t		*self;
	int			i;



	level.modeset = FREEFORALL;
	gi.cvar_set ("dmflags",default_dmflags);
	gi.cvar_set ("teamplay",default_teamplay);
	gi.cvar_set ("password",default_password);
	gi.cvar_set ("timelimit",default_timelimit);
	gi.cvar_set ("fraglimit",default_fraglimit);
	gi.cvar_set ("cashlimit",default_cashlimit);
	gi.cvar_set ("dm_realmode",default_dm_realmode);
    level.startframe = level.framenum;
	
	for_each_player (self,i)
	{

		if (self->client->pers.spectator) 
			UPDATERATE(self)

		self->flags &= ~FL_GODMODE;
		self->health = 0;
		meansOfDeath = MOD_RESTART;
		player_die (self, self, self, 1, vec3_origin, 0, 0);

		ClientBeginDeathmatch( self );	
	}
	
	safe_bprintf(PRINT_HIGH,"The server is once again public.\n");
}


void MatchSetup (edict_t *ent) // Places the server in prematch mode
{
	edict_t		*self;
	int			i;

	level.modeset = MATCHSETUP;
	level.startframe = level.framenum;

	for_each_player (self,i)
	{

		if (self->client->pers.spectator) 
			UPDATERATE(self)

/*		self->movetype = MOVETYPE_NOCLIP;
		self->solid = SOLID_NOT;
		self->svflags |= SVF_NOCLIENT;
		self->client->pers.weapon = NULL;*/
		if (self->client->pers.spectator == SPECTATING)
			continue;
		meansOfDeath = MOD_RESTART;
		self->client->pers.spectator = SPECTATING;
		self->flags &= ~FL_GODMODE;
		self->health = 0;
		player_die (self, self, self, 1, vec3_origin, 0, 0);
		ClientBeginDeathmatch( self );	
	}

	safe_bprintf(PRINT_HIGH,"The server is now ready to setup a match.\n");
	safe_bprintf(PRINT_HIGH,"Players need to join the correct teams.\n");
	
}

void ResetServer (edict_t *ent) // completely resets the server including map
{
	char command[64];
    
	gi.cvar_set ("dmflags",default_dmflags);
	gi.cvar_set ("teamplay",default_teamplay);
	gi.cvar_set ("password",default_password);
	gi.cvar_set ("timelimit",default_timelimit);
	gi.cvar_set ("fraglimit",default_fraglimit);
	gi.cvar_set ("cashlimit",default_cashlimit);
	gi.cvar_set ("dm_realmode",default_dm_realmode);
	gi.cvar_set ("cheats","0");

	if (default_random_map && num_custom_maps)
		Com_sprintf (command, sizeof(command), "map \"%s\"\n", custom_list[rand()%num_custom_maps].custom_map);
	else
		Com_sprintf (command, sizeof(command), "map \"%s\"\n", default_map);
	gi.AddCommandString (command);
}

int team_startcash[2]={0,0};

void MatchStart(edict_t *ent)  // start the match
{
	int			i;
	edict_t		*self;
		
	
	level.player_num=0;
	level.modeset = FINALCOUNT;
	level.startframe = level.framenum;
	safe_bprintf (PRINT_HIGH,"FINAL COUNTDOWN STARTED.  15 SECONDS TO MATCH.\n");
	team_cash[1]=team_startcash[0]; team_startcash[0]=0;
	team_cash[2]=team_startcash[1]; team_startcash[1]=0;
	UPDATESCORE

	for_each_player (self,i)
	{
		
		if (self->client->pers.spectator) 
			UPDATERATE(self)
		self->client->pers.bagcash = 0;
		self->client->resp.deposited = 0;
		self->client->resp.score = 0;
		self->client->pers.currentcash = 0;
		self->client->resp.acchit = self->client->resp.accshot = 0;
		memset(self->client->resp.fav,0,15*sizeof(int));
		self->client->resp.botkills = 0;
	}

	gi.WriteByte( svc_stufftext );
	gi.WriteString( va("play world/hmcypress%i.wav", 2+(rand()%4)) );
	gi.multicast (vec3_origin, MULTICAST_ALL);
}


void SpawnPlayer (edict_t *ent) // Here I spawn players - 1 per server frame in hopes of reducing overflows
{
	edict_t		*self;
	int			i;
	int			team1=false;

	for (i=0 ; i<maxclients->value; i++)
	{
		self = g_edicts + 1 + i;
		if (!self->inuse)
			continue;
		if (!self->client->resp.is_spawn)
		{
            gi.dprintf("spawned player %d\n",i+1);
			self->flags &= ~FL_GODMODE;
			self->health = 0;
			team1 = true;
			self->client->pers.spectator = PLAYING;
//			player_die (self, self, self, 1, vec3_origin, 0, 0);
			ClientBeginDeathmatch( self );	
			self->client->resp.is_spawn = true;
			break;
		}
	}
	if (!team1)
		level.is_spawn = true;

//gi.dprintf("done.\n");
}



void SpawnPlayers (edict_t *ent)  // Same idea but 1 player per team
{
	edict_t		*self;
	int			i;
	int			team1,team2;

	team1 = false;
	team2 = false;


	for (i=0 ; i<maxclients->value && (!team1 || !team2); i++)
	{
		self = g_edicts + 1 + i;
		
		if (!self->inuse)
			continue;
		
		if ((self->client->pers.team == 1) && (!team1) && (!self->client->resp.is_spawn))
		{
			self->flags &= ~FL_GODMODE;
			self->health = 0;
			team1 = true;
			self->client->pers.spectator = PLAYING;
//			player_die (self, self, self, 1, vec3_origin, 0, 0);
			ClientBeginDeathmatch( self );	
			self->client->resp.is_spawn = true;
		}
		if ((self->client->pers.team == 2) && (!team2) && (!self->client->resp.is_spawn))
		{
			self->flags &= ~FL_GODMODE;
			self->health = 0;
			meansOfDeath = MOD_RESTART;
			team2 = true;
			self->client->pers.spectator = PLAYING;
//			player_die (self, self, self, 1, vec3_origin, 0, 0);
			ClientBeginDeathmatch( self );	
			self->client->resp.is_spawn = true;
		}
	}
	if ((!team1) && (!team2))
		level.is_spawn = true;
}

void Start_Match (edict_t *ent) // Starts the match
{
	edict_t		*self;
	int			i;


	level.startframe = level.framenum;
	level.modeset = STARTINGMATCH;
	level.is_spawn = false;
	for_each_player(self,i)
	{
		if (self->client->pers.spectator) 
			UPDATERATE(self)
		safe_centerprintf(self,"The Match has begun.\n");
		self->client->resp.is_spawn = false;
		self->client->resp.enterframe = level.framenum;
	}

	gi.WriteByte( svc_stufftext );
	gi.WriteString("play world/pawnbuzz_out.wav");
	gi.multicast (vec3_origin, MULTICAST_ALL);

//	level.modeset = MATCH;
}


void Start_Pub (edict_t *ent) // Starts a pub
{
	edict_t		*self;

	int			i;


	level.startframe = level.framenum;
	level.modeset = STARTINGPUB;
	level.is_spawn = false;

	for_each_player(self,i)
	{
		if (self->client->pers.spectator) 
			UPDATERATE(self)
//		safe_centerprintf(self,"Type 'HELPME' in console for bind info!\n");
		self->client->resp.is_spawn = false;
		self->client->resp.enterframe = level.framenum;
	
	}




	gi.WriteByte( svc_stufftext );
	gi.WriteString("play weapons/xpld_wat.wav");
    gi.multicast (vec3_origin, MULTICAST_ALL);


}

void SetupMapVote (edict_t *ent) // at the end of a level - starts the vote for the next map
{
	edict_t *self;
	int		found;
	int		i,j,k;
	int		unique;
	int		selection;
	
	
	level.modeset = ENDMATCHVOTING;
	level.startframe = level.framenum;

	for_each_player (self,i)
	{
		
		
		if (self->client->pers.spectator) 
			UPDATERATE(self)

//GHOSTZOID - START HOOK
		KPQ2PlayerResetGrapple(self); //added by ghost
//GHOSTZOID - END HOOK		

		self->movetype = MOVETYPE_NOCLIP;
		self->solid = SOLID_NOT;
		self->svflags |= SVF_NOCLIENT;
		self->client->pers.weapon = NULL;
		self->client->pers.spectator = SPECTATING;
	}
	gi.WriteByte( svc_stufftext );
	gi.WriteString( va("play world/hmcypress%i.wav", 2+(rand()%4)) );
	gi.multicast (vec3_origin, MULTICAST_ALL);

	i = 0;
	found = false;
	while ((!found) && (i < (num_custom_maps - 1) )) 
	{	
		if (Q_stricmp (custom_list[i].custom_map,level.mapname) == 0)
		{
			vote_set[1] = i+1;
			found = true;
		}
		i++;
	}
	if (!found)
		vote_set[1] = 0;

	if (num_custom_maps < 9) // less than 9 maps found, just display them all
	{
		i = vote_set[1];
		for (j=2; j< (num_custom_maps+2); j++)
		{
			i++;
			if (i == num_custom_maps)
				i=0;
			vote_set[j] = i;
		}
		return;
	}
	// first map is always the next in the rotations
	srand((unsigned int)time((time_t *)NULL));

	for (i=2; i < 6; i++) // 2-5 are weighted by rank
	{
		unique = false;
		while (!unique)
		{		
			selection = rand() % total_rank;
			j=0;
			while (selection >= 0)
			{
				selection -= custom_list[j].rank;
				j++;
			}
			vote_set[i] = (j-1);
			unique = true;
			for (k=0; k < i; k++)
				if (vote_set[i] == vote_set[k])
					unique = false;
		}
	}

	for (i=6; i < 9; i++) // 6-8 are just picked at random
	{
		unique = false;
		while (!unique)
		{		
			selection = rand() % num_custom_maps;
			vote_set[i] = selection;
			unique = true;
			for (k=0; k < i; k++)
				if (vote_set[i] == vote_set[k])
					unique = false;
		}
	}
}

void MatchEnd (edict_t *ent) // end of the match
{
	edict_t *self;
	int i;

	
	level.modeset = MATCHSETUP;
	level.startframe = level.framenum;
	for_each_player(self,i)
	{
		
		if (self->client->pers.spectator) 
			UPDATERATE(self)
		safe_centerprintf(self,"The Match has ended!");
		self->flags &= ~FL_GODMODE;
		self->health = 0;
		meansOfDeath = MOD_RESTART;
		player_die (self, self, self, 1, vec3_origin, 0, 0);    
		ClientBeginDeathmatch( self );
	}
	gi.WriteByte( svc_stufftext );
	gi.WriteString( va("play world/hmcypress%i.wav", 2+(rand()%4)) );
	gi.multicast (vec3_origin, MULTICAST_ALL);

}


void CheckAllPlayersSpawned (edict_t *ent) // when starting a match this function is called until all the players are in the game
{

	if (teamplay->value)
		SpawnPlayers (ent);
	else
		SpawnPlayer (ent);
		
	if ((level.is_spawn) && (level.modeset == STARTINGMATCH))
		level.modeset = MATCH;
	
	if ((level.is_spawn) && (level.modeset == STARTINGPUB))
		level.modeset = TEAMPLAY;

		
}


void CheckIdleMatchSetup (edict_t *ent) // restart the server if its empty in matchsetup mode
{
	int		count=0;
	int		i;
	edict_t	*doot;

	for_each_player (doot,i)
		count++;
	if (count == 0)
		ResetServer (ent);
}


void CheckStartMatch (edict_t *ent) // 15 countdown before matches
{
	if (level.framenum >= level.startframe + 145)
	{
		Start_Match (ent);
		return;
	}

	if ((level.framenum % 10 == 0 ) && (level.framenum > level.startframe + 49))
		safe_bprintf(PRINT_HIGH,"The Match will start in %d seconds!\n", (140 - (level.framenum - level.startframe)) / 10);
}



/*
void CheckStartPub (edict_t *ent) // 35 second countdown before server starts
{
	if (level.framenum >= 345)
	{
		
    
   Start_Pub (ent);
		return;
	}

	if ((level.framenum % 10 == 0 ) && (level.framenum > 299))
		safe_bprintf(PRINT_HIGH,"The Server will start in %d seconds!\n", (340 - (level.framenum )) / 10);
}
*/

void CheckStartPub (edict_t *ent) // 35 second countdown before server starts
{


	static char current_map[55];
	
	if (level.framenum >= 345)
	{
		
	strcpy(current_map,level.mapname);

	ACEND_InitNodes();
	ACEND_LoadNodes();
	ACESP_LoadBots();


	Start_Pub (ent);
	return;

	}

	if ((level.framenum % 10 == 0 ) && (level.framenum > 299))
		safe_bprintf(PRINT_HIGH,"The Server will start in %d seconds!\n", (340 - (level.framenum )) / 10);
}


void PunkBot_Go(edict_t *ent);
void PunkBot_Go_rl(edict_t *ent);
void PunkBot_Go_fg(edict_t *ent);
void PunkBot_Go_gl(edict_t *ent);
void PunkBot_Go_hmg(edict_t *ent);
void PunkBot_Go_tg(edict_t *ent);
void BitchBot_Go(edict_t *ent);
void DogBot_Go(edict_t *ent);
//void Dog2Bot_Go(edict_t *ent);
void RuntBot_Go(edict_t *ent);
void ShortyBot_Go(edict_t *ent);
void ThugBot_Go(edict_t *ent);


//botload
void CheckStartPubold (edict_t *ent) // 35 second countdown before server starts
{
	
	
	int z;
	

	if (level.framenum >= 345)
	{
		Start_Pub (ent);
		return;
	}


		if ((level.framenum % 10 == 0 ) && (level.framenum > 219)){

	if (strstr (level.mapname, "dai_")){

	
	//z = rand()%11;
	
		z = (340 - (level.framenum )) / 10;
	
		switch (z)
	{
	case 0:
		break;
	case 1:
		break;
	case 2:
		break;
	case 3:
		break;
	case 4:
		break;
	case 5:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload2.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 8\n");
		DogBot_Go(ent);
		break;
	case 6:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload1.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 7\n");
		DogBot_Go(ent);
		break;
	case 7:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload2.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 6\n");
		DogBot_Go(ent);
		break;
	case 8:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload2.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 5\n");
		DogBot_Go(ent);
		break;
	case 9:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload1.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 4\n");
		DogBot_Go(ent);
		break;
	case 10:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload2.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 3\n");
		DogBot_Go(ent);
		break;
	case 11:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload2.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 2\n");
		DogBot_Go(ent);
		break;
	case 12:
		gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_AUTO, gi.soundindex("misc/botload1.wav"), 1, ATTN_NONE, 0); 
		safe_bprintf(PRINT_HIGH,"Loading dog 1\n");
		DogBot_Go(ent);
		break;
	
	}	

		}
}
	

}









void CheckEndMatch (edict_t *ent) // check if time,frag,cash limits have been reached in a match
{
	int			i;
	gclient_t	*cl;
	int		count=0;
	edict_t	*doot;



	for_each_player (doot,i)
		count++;
	if (count == 0)
		ResetServer (ent);

	if (level.framenum > (level.startframe + ((int)timelimit->value) * 600 - 1))
	{
		safe_bprintf (PRINT_HIGH, "Timelimit hit.\n");

//GHOSTZOID - START HOOK
		KPQ2PlayerResetGrapple(ent); //added by ghost
//GHOSTZOID - END HOOK		
        removedogs(ent);
		MatchEnd(ent);
		return;
	}
	if ((int)fraglimit->value)
	{
		for (i=0 ; i<maxclients->value ; i++)
		{
			cl = game.clients + i;
			if (!g_edicts[i+1].inuse)
				continue;

			if (cl->resp.score >= (int)fraglimit->value)
			{

				safe_bprintf (PRINT_HIGH, "Fraglimit hit.\n");

//GHOSTZOID - START HOOK
		        KPQ2PlayerResetGrapple(ent); //added by ghost
//GHOSTZOID - END HOOK
                removedogs(ent);				
				MatchEnd (ent);
				return;
			}
		}
	}

	if ((int)cashlimit->value)
	{
		if ((team_cash[1] >= (int)cashlimit->value) || (team_cash[2] >= (int)cashlimit->value))
		{
			safe_bprintf (PRINT_HIGH, "Cashlimit hit.\n");

//GHOSTZOID - START HOOK
		    KPQ2PlayerResetGrapple(ent); //added by ghost
//GHOSTZOID - END HOOK
            removedogs(ent);			
			MatchEnd (ent);
			return;
		}
	}

	if (((level.framenum - level.startframe ) % 10 == 0 ) && (level.framenum > (level.startframe + (((int)timelimit->value  * 600) - 155))))  
	{
		safe_bprintf(PRINT_HIGH,"The Match will end in  %d seconds\n", (((int)timelimit->value * 600) + level.startframe - level.framenum ) / 10);
		return;
	}

	if (((level.framenum - level.startframe ) % 600 == 0 ) && (level.framenum > (level.startframe + (((int)timelimit->value * 600) - 3000))))  
	{
		safe_bprintf(PRINT_HIGH,"The Match will end in  %d minutes\n", (((int)timelimit->value * 600) + level.startframe - level.framenum ) / 600);
		return;
	}

	if ((level.framenum - level.startframe ) % 3000 == 0 )
		safe_bprintf(PRINT_HIGH,"The Match will end in  %d minutes\n", (((int)timelimit->value * 600) + level.startframe - level.framenum ) / 600);

	

}

void CheckEndVoteTime (edict_t *ent) // check the timelimit for voting next level/start next map
{
	int		i,count[9];
	edict_t *player;
	char	command[64];
	int		wining_map;

	if (level.framenum == (level.startframe + 10))
	{
		for_each_player (player,i)
		{
			if (scoreboard_first)
				player->client->showscores = SCOREBOARD;
			else
				player->client->showscores = SCORE_MAP_VOTE;
			DeathmatchScoreboard (player);
		}
	}

	if (level.framenum > (level.startframe + 300))
	{
		memset (&count, 0, sizeof(count));
		for_each_player(player,i)
		{
			count[player->vote]++;
		}
		wining_map = 1;
		for (i = 2;i < 9 ; i++)
		{
			custom_list[vote_set[i]].rank += count[i];
			if (count[i] > count[wining_map])
				wining_map = i;
		}
		i = write_map_file();
		if (i != OK)
			gi.dprintf("Error writing custom map file!\n");

		Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", custom_list[vote_set[wining_map]].custom_map);
		gi.AddCommandString (command);
	}
}

void CheckVote(edict_t *ent) // check the timelimit for an admin vote
{
	
	if (level.framenum > (level.voteframe + 1200))
	{
		switch (level.voteset)
		{
			case VOTE_ON_ADMIN:
				safe_bprintf(PRINT_HIGH,"The request for admin has failed!\n");
				break;
		}
		level.voteset = NO_VOTES;
	}
}



int	CheckPlayerBan (edict_t *ent, char *userinfo) 
{
	char	*value;
	int		i,j;
	int		isSame;

	value = Info_ValueForKey (userinfo, "name");
	for (i=0;i<num_netnames;i++) {
		if (Q_strcasecmp (netname[i].value, value) == 0)
			return true;
	}

	value = Info_ValueForKey (userinfo, "ip");
	for (i=0;i<num_ips;i++) {
		isSame = true;
		j = 0;
		while ((isSame) && (value[j] != '\0') && (value[j] != ':'))
		{		
			if (ip[i].value[j] != value[j])
				isSame = false;
			j++;
		}
		if (isSame)
			return true;
	}

	return false;
}











