main()
{
	// if no stats selected return
	if(!level.ex_stbdk && !level.ex_stbdd) return;

	// check that server is not empty and there are at least 2 players
	players = getentarray("player", "classname");
	if(players.size <= 1) return;

	// play music if there is no end music playing
	if(level.ex_stbdm)
	{
			mn = randomInt(10);
			musicplay("gom_music_" + mn);
	}

	// clear iprintlnbold area	
	thread [[level.ex_clearlnb]]("all",5);

	level.ex_movebar = 0;
	level.ex_stplayers = 0;
	level.ex_statsover = false;

	// set display range for stats selected
	if(level.ex_stbdk) level.ex_ststart = 1;
		else level.ex_ststart = 17;

	if(level.ex_stbdd) level.ex_stend = 34;
		else level.ex_stend = 16;

	// show prep message
	createPrepBar();

	// move the prep bar
	thread monitorPrepBar();	

	// count players not spectating, set stats for all players
	for(i = 0;i < players.size;i++)
	{
		if(isPlayer(players[i]))
		{
			if(players[i].pers["team"] != "spectator") level.ex_stplayers++;
			players[i] setPlayerUp();
		}
	}		

	// set for top x players	
	if(level.ex_stplayers > 5) level.ex_stmaxp = 5;
	else level.ex_stmaxp = level.ex_stplayers;

	// monitor for new players now
	level.ex_movebar++;
	thread monitorJoining();

	// check valid amount of stats to display
	level.ex_movebar++;
	level.ex_laststat = checkForLastStat();

	// if there are no valid stats (zero points) end stats and return	
	if(level.ex_laststat == 0)
	{
		level notify("endstats");
		removePrepBar();
		return;
	}

	// Set up time to wait
	i = 0;	

	if(level.ex_stbdtps)
	{
		level.ex_stwait = (level.ex_laststat * level.ex_stbdtps); // user defined seconds per stat

		if(level.ex_stscore)
		{
			level.ex_stwait+= level.ex_stbdtps;
			i++;
		}
		
		if(level.ex_steffiency)
		{
			level.ex_stwait+= level.ex_stbdtps;
			i++;
		}
	
		if(level.ex_stwait < (level.ex_stbdtps * i)) level.ex_stwait = level.ex_stbdtps * i;
		else if(level.ex_stwait > level.ex_stbdt) level.ex_stwait = level.ex_stbdt;
	}
	else level.ex_stwait = level.ex_stbdt;

	// if the statsboard music is on, make sure there is enough time to fade it!
	if(level.ex_stbdm && level.ex_stwait < 10) level.ex_stwait = 10;

	// Good to go!
	level.ex_movebar++;
	level.ex_statson = "true";

	// remove prepbar
	removePrepBar();

	// create background
	createStatsboard();

	// ok - show them the goods!
	thread splitforplayers();

	// wait while the time runs down
	level waittill("endstats");

	// ok - scrap it all and finish
	destroyStatsboard();
}

// monitor for new players joining
monitorJoining()
{
	while(!level.ex_statsover)
	{
		wait 0.05;

		if(!isDefined(level.ex_diff)) continue;

		players = getentarray("player", "classname");
		for(i = 0;i < players.size;i++) if(isPlayer(players[i]) && !isDefined(players[i].ex_statson)) players[i] thread joiningPlayers();
	}
}

joiningPlayers()
{
	self endon("disconnect");

	self.ex_justjoined = true;
	self initHud();
	self setPlayerUp();
	self.ex_statson = true;
	self createForPlayers();
	self endStatsboard();
}

// process stats
setPlayerUp()
{
	self endon("disconnect");
	
	if(isPlayer(self))
	{
		// spawn player as spectators
		self extreme\_ex_spawn::spawnSpectator();
		self allowspectateteam("allies", false);
		self allowSpectateTeam("axis", false);
		self allowSpectateTeam("freelook", false);
		self allowSpectateTeam("none", true);
		self setClientCvar("g_scriptmainmenu", "");
		self closeMenu();
		
		if(!isDefined(self.ex_justjoined)) self.ex_statson = true;

		ticon = undefined;
		chevron = undefined;
	
		if(isDefined(self.pers["team"]))
		{
			if(self.pers["team"] == "allies")
			{				
				switch(game["allies"])
				{
					case "american":	ticon = "objective_american";		break;
					case "british":		ticon = "objective_british";			break;
					default:					ticon = "objective_russian";			break;
				}
			}
			else if(self.pers["team"] == "axis")
			{
				switch(game["axis"])
				{
					case "german":
					ticon = "objective_german";
					break;
				}
			}
		}
		else if(self.sessionteam == "spectator")
		{
			ticon = "objpoint_radio";
		}

		if(isPlayer(self))
		{
			self.ticon = ticon;
		}
		
		for(i = level.ex_ststart;i <= level.ex_stend; i++)
		{
			stat = getStat(i);
			if(isPlayer(self) && !isDefined(self.pers[stat])) self.pers[stat] = 0;
		}

		// move the progrees bar along
		level.ex_movebar++;
	
		// set player scores (required for kill ratio too!)
		if(level.ex_stscore || level.ex_steffiency)
		{
			if(isDefined(self.score)) self.pers["score"] = self.score;
			else self.pers["score"] = 0;
		}

		if(!isDefined(self.pers["kill"])) self.pers["kill"] = 0;
			
		//calculate the kill/death ratio
		if(level.ex_steffiency)
		{
			if(self.pers["kill"] == 0 || (self.pers["kill"] - (self.pers["death"] + self.pers["suicide"])) <= 0) self.pers["effiency"] = 0;
			else self.pers["effiency"] = int((100 / self.pers["kill"]) * self.pers["kill"] - (self.pers["death"] + self.pers["suicide"]));

			if(self.pers["effiency"] > 100) self.pers["effiency"] = 0;
		}
	}
}

// setup and display preparing stats message
createPrepBar()
{
	level.ex_pmsg[0] = newhudelem();
	level.ex_pmsg[0].archived = false;
	level.ex_pmsg[0].alpha = 0.7;
	level.ex_pmsg[0].x = 160;
	level.ex_pmsg[0].y = 20;
	level.ex_pmsg[0].sort = 100;
	level.ex_pmsg[0] setshader("black", 320, 42);

	level.ex_pmsg[1] = newhudelem();
	level.ex_pmsg[1].archived = false;
	level.ex_pmsg[1].alpha = .3;
	level.ex_pmsg[1].x = 164;
	level.ex_pmsg[1].y = 22;
	level.ex_pmsg[1].sort = 101;
	level.ex_pmsg[1] setshader("white", 312, 2);

	level.ex_pmsg[2] = newhudelem();
	level.ex_pmsg[2].archived = false;
	level.ex_pmsg[2].alpha = .3;
	level.ex_pmsg[2].x = 164;
	level.ex_pmsg[2].y = 58;
	level.ex_pmsg[2].sort = 101;
	level.ex_pmsg[2] setshader("white", 312, 2);
		
	level.ex_pmsg[3] = newhudelem();
	level.ex_pmsg[3].archived = false;
	level.ex_pmsg[3].alpha = .3;
	level.ex_pmsg[3].x = 162;
	level.ex_pmsg[3].y = 22;
	level.ex_pmsg[3].sort = 101;
	level.ex_pmsg[3] setshader("white", 2, 38);

	level.ex_pmsg[4]  = newhudelem();
	level.ex_pmsg[4].archived = false;
	level.ex_pmsg[4].alpha = .3;
	level.ex_pmsg[4].x = 476;
	level.ex_pmsg[4].y = 22;
	level.ex_pmsg[4].sort = 101;
	level.ex_pmsg[4] setshader("white", 2, 38);
	
	level.ex_pmsg[5]  = newhudelem();
	level.ex_pmsg[5].archived = false;
	level.ex_pmsg[5].alpha = 1;
	level.ex_pmsg[5].alignx = "center";
	level.ex_pmsg[5].aligny = "top";
	level.ex_pmsg[5].x = 320;
	level.ex_pmsg[5].y = 24;
	level.ex_pmsg[5].sort = 102;
	level.ex_pmsg[5].fontscale = 1.5;
	level.ex_pmsg[5] settext(&"STATSBOARD_GENERATING");

	level.ex_pmsg[6]	= newhudelem();				
	level.ex_pmsg[6].alignx = "left";
	level.ex_pmsg[6].aligny = "middle";
	level.ex_pmsg[6].x = (320 - (300 / 2.0));
	level.ex_pmsg[6].y = 50;
	level.ex_pmsg[6].color = (0,1,1);
	level.ex_pmsg[6] setshader("white", 0, 8);
}

monitorPrepBar()
{
	width = 0;
	level.ex_prepbar = true;
	
	while(level.ex_prepbar)
	{
		width += level.ex_movebar * randomInt(10);

		if(width > 300)
		{
			level.ex_pmsg[6] setshader("white" , 300 , 8);
			break;
		}

		level.ex_pmsg[6] setshader("white" , width , 8);
		wait 1;
	}
}

// remove preparing stats message
removePrepBar()
{
	if(isDefined(level.ex_pmsg))
	{
		level.ex_pmsg[6] setshader("white" , 300 , 8);
		wait 0.5;

		level.ex_prepbar = false;

		for(i = 0;i < level.ex_pmsg.size; i++) level.ex_pmsg[i] destroy();
	}
}

// create statsboard
createStatsboard()
{
	// set player amount differential
	level.ex_stbdchu = level.ex_stmaxp + 14;
	level.ex_diff = 166 - ((level.ex_stmaxp - 2) * 16);
	
	// background
	level.ex_stdis[0] = newhudelem();
	level.ex_stdis[0].archived = false;
	level.ex_stdis[0].alpha = 0.7;
	level.ex_stdis[0].x = 100;
	level.ex_stdis[0].y = 37; //20;
	level.ex_stdis[0].sort = 100;
	level.ex_stdis[0] setshader("black", 440, 280-level.ex_diff);
	
	// background image
	level.ex_stdis[1] = newhudelem();
	level.ex_stdis[1].archived = false;
	level.ex_stdis[1].alpha = 0.8;
	level.ex_stdis[1].x = 104;
	level.ex_stdis[1].y = 39;
	level.ex_stdis[1].sort = 0;
//	level.ex_stdis[1] setshader("gfx/custom/extreme_statsboard_title.tga", 432, 58);

	// top line
	level.ex_stdis[2] = newhudelem();
	level.ex_stdis[2].archived = false;
	level.ex_stdis[2].alpha = .3;
	level.ex_stdis[2].x = 104;
	level.ex_stdis[2].y = 39;
	level.ex_stdis[2].sort = 101;
	level.ex_stdis[2] setshader("white", 432, 2);

	// bottom line
	level.ex_stdis[3] = newhudelem();
	level.ex_stdis[3].archived = false;
	level.ex_stdis[3].alpha = .3;
	level.ex_stdis[3].x = 104;
	level.ex_stdis[3].y = 313 - level.ex_diff;
	level.ex_stdis[3].sort = 101;
	level.ex_stdis[3] setshader("white", 432, 2);
	
	// middle line 1
	level.ex_stdis[4] = newhudelem();
	level.ex_stdis[4].archived = false;
	level.ex_stdis[4].alpha = .3;
	level.ex_stdis[4].x = 104;
	level.ex_stdis[4].y = 75;
	level.ex_stdis[4].sort = 101;
	level.ex_stdis[4] setshader("white", 432, 2);

	// middle line 2	
	level.ex_stdis[5] = newhudelem();
	level.ex_stdis[5].archived = false;
	level.ex_stdis[5].alpha = .3;
	level.ex_stdis[5].x = 104;
	level.ex_stdis[5].y = 101;
	level.ex_stdis[5].sort = 101;
	level.ex_stdis[5] setshader("white", 432, 1);

	// middle line 3
	level.ex_stdis[6] = newhudelem();
	level.ex_stdis[6].archived = false;
	level.ex_stdis[6].alpha = .3;
	level.ex_stdis[6].x = 104;
	level.ex_stdis[6].y = 297 - level.ex_diff;
	level.ex_stdis[6].sort = 101;
	level.ex_stdis[6] setshader("white", 432, 1);

	// left line 1
	level.ex_stdis[7] = newhudelem();
	level.ex_stdis[7].archived = false;
	level.ex_stdis[7].alpha = .3;
	level.ex_stdis[7].x = 102;
	level.ex_stdis[7].y = 39;
	level.ex_stdis[7].sort = 101;
	level.ex_stdis[7] setshader("white", 2, 276-level.ex_diff);

	// left line 2
	level.ex_stdis[8] = newhudelem();
	level.ex_stdis[8].archived = false;
	level.ex_stdis[8].alpha = .1;
	level.ex_stdis[8].x = 122;
	level.ex_stdis[8].y = 101;
	level.ex_stdis[8].sort = 101;
	level.ex_stdis[8] setshader("white", 1, 196-level.ex_diff);	

	// right line 1	
	level.ex_stdis[9] = newhudelem();
	level.ex_stdis[9].archived = false;
	level.ex_stdis[9].alpha = .3;
	level.ex_stdis[9].x = 536;
	level.ex_stdis[9].y = 39;
	level.ex_stdis[9].sort = 101;
	level.ex_stdis[9] setshader("white", 2, 276-level.ex_diff);
	
	// right line 2
	level.ex_stdis[10] = newhudelem();
	level.ex_stdis[10].archived = false;
	level.ex_stdis[10].alpha = .3;
	level.ex_stdis[10].x = 504;
	level.ex_stdis[10].y = 101;
	level.ex_stdis[10].sort = 101;
	level.ex_stdis[10] setshader("white", 1, 196-level.ex_diff);

	// statsboard header
	level.ex_stdis[11] = newhudelem();
	level.ex_stdis[11].archived = false;
	level.ex_stdis[11].alpha = 1;
	level.ex_stdis[11].alignx = "center";
	level.ex_stdis[11].aligny = "top";
	level.ex_stdis[11].x = 320;
	level.ex_stdis[11].y = 43;
	level.ex_stdis[11].sort = 102;
	level.ex_stdis[11].fontscale = 2.5;
	level.ex_stdis[11] settext(&"STATSBOARD_TITLE");

	// statsboard time left text
	level.ex_stdis[12] = newhudelem();
	level.ex_stdis[12].archived = false;
	level.ex_stdis[12].alpha = 1;
	level.ex_stdis[12].alignx = "center";
	level.ex_stdis[12].aligny = "middle";
	level.ex_stdis[12].x = 480;
	level.ex_stdis[12].y = 306 - level.ex_diff;
	level.ex_stdis[12].sort = 102;
	level.ex_stdis[12].fontscale = 1;
	level.ex_stdis[12] settext(&"STATSBOARD_TIME_LEFT");

	// statsboard timer		
	level.ex_stdis[13] = newhudelem();
	level.ex_stdis[13].archived = false;
	level.ex_stdis[13].alpha = 1;
	level.ex_stdis[13].alignx = "center";
	level.ex_stdis[13].aligny = "middle";
	level.ex_stdis[13].x = 520;
	level.ex_stdis[13].y = 306 - level.ex_diff;
	level.ex_stdis[13].sort = 102;
	level.ex_stdis[13].fontscale = 1;
	level.ex_stdis[13].color = (0,1,1);
	level.ex_stdis[13] settimer(level.ex_stwait);
	
	// middle lines (player seperators)
	stbd_scy = 115;
	for(li = 14; li < (level.ex_stbdchu); li++)
	{
		level.ex_stdis[li] = newhudelem();
		level.ex_stdis[li].archived = false;
		level.ex_stdis[li].alpha = .1;
		level.ex_stdis[li].x = 104;
		level.ex_stdis[li].y = stbd_scy;
		level.ex_stdis[li].sort = 101;
		level.ex_stdis[li] setshader("white", 432, 1);
		stbd_scy+=16;
	}
}

// start stats display for each player
splitforplayers()
{
	level endon("endstats");
	game["menu_team"] = "";
	
	players = getentarray("player", "classname");
	for(i = 0; i < players.size; i++) players[i] thread createForPlayers();

	endStatsboard();
}

endStatsboard()
{
	if(level.ex_stbdm)
	{
		wait level.ex_stwait - 10;
		musicstop(10); // fade music
		wait 10;
	}
	else wait level.ex_stwait;
	
	level.ex_statsover = true;	
	players = getentarray("player", "classname");	

	// stop name display routines
	for(i = 0; i < players.size; i++) players[i] notify("end_playernames");

	wait 0.5;

	thread [[level.ex_clearlnb]]("all",5);

	// fade board elements (level)
	if(level.ex_stbdf)
	{	
		for(i = 0; i < (level.ex_stdis.size); i++)
		{
			level.ex_stdis[i] fadeovertime(1);
			level.ex_stdis[i].alpha = 0;
		}

		// fade board elements (self)
		for(i = 0; i < players.size; i++) players[i] doPlayerFades();

		wait 1;
	}

	level notify("endstats");
}

// main routine (self)
createForPlayers()
{
	level endon("endstats");
	self endon("disconnect");

	if(!isDefined(self.ex_justjoined)) self initHud();

	self.sessionstate = "spectator";
	self.spectatorclient = -1;
	
	self.ex_cycle = -1;
	self.ex_stlimbo = undefined;
	self.ex_hsdone = false;
	self resetStatDisplay();
	
	while(!level.ex_statsover)
	{
		wait 0.05;

		if(isPlayer(self) && self.sessionstate != "spectator")
		{
			
			self extreme\_ex_spawn::spawnSpectator();
			self allowspectateteam("allies", false);
			self allowSpectateTeam("axis", false);
			self allowSpectateTeam("freelook", false);
			self allowSpectateTeam("none", true);
			self setClientCvar("g_scriptmainmenu", "");
			self closeMenu();
		}

		// keep looping until they press the button
		if(isPlayer(self) && !self attackButtonPressed()) continue;

		if(isPlayer(self))
		{
			// fade out existing stats
			self doPlayerFades(0,.5,1);
			self clearStat();

			// play sound on trigger
			self playLocalSound("mouse_click");

			// change status message to calculating
			self.ex_stdiself[1] settext(&"STATSBOARD_PLEASE_WAIT_CALCULATING");
			wait 0.5;
		}

		// wait till they release the button, avoid spamming the display routine
		while(isPlayer(self) && self attackButtonPressed()) wait 0.05;

		if(isPlayer(self))
		{
			// next stat please!
			self.ex_showstat++;

			// limbo check
			if(isDefined(self.ex_stlimbo)) return;

			// check for highscores, kill ratio and reset			
			if(self.ex_showstat > level.ex_laststat)
			{
				// reset?
				if(self.ex_showstat == 102 && !level.ex_steffiency) self.ex_sreset = true;
				else if(self.ex_showstat == 103) self.ex_sreset = true;
				else if(!level.ex_stscore && !level.ex_steffiency) self.ex_sreset = true;

				if(!self.ex_sreset)
				{
					// show scores if selected
					if(level.ex_stscore && self.ex_showstat != 102)
					{
						self.ex_showstat = 101;
						self.ex_skip = true;
					}

					// show kill/death ratios if selected
					if(level.ex_steffiency && !self.ex_skip && (self.ex_showstat == 102 || !level.ex_stscore))
					{
						if(!level.ex_stscore) self.ex_showstat = 102;
						self.ex_skip = true;
					}
				}
				else self.ex_skip = true;
			}

			// skip stat check?
			if(!self.ex_skip)
			{
				// check that its worth displaying
				for(;;)
				{
					if(isPlayer(self))
					{	
						if(self.ex_showstat > level.ex_stend) self.ex_showstat = level.ex_ststart;

						if(self checkValidStat(self.ex_showstat)) break;
						else self.ex_showstat++;
					}

					wait 0.05;
				}
			}

			if(isPlayer(self))
			{
				// reset the stats if true
				if(self.ex_sreset) self resetStatDisplay();
				else
				{
					// display stats
					chvr = getStat(self.ex_showstat);
					self displayStat(chvr);
				}
			}
		}
	}
}

// reset the stats and display next in line
resetStatDisplay()
{
	level endon("endstats");
	self endon("disconnect");

	// change status message to calculating	
	self.ex_stdiself[1] settext(&"STATSBOARD_PLEASE_WAIT_CALCULATING");

	self notify("end_playernames");

	self thread [[level.ex_clearlnb]]("self",5);
		
	self.ex_sdone = false;
	self.ex_rdone = false;
	self.ex_sreset = false;
	self.ex_skip = false;
	self.ex_cycle++;
	self.ex_showstat = level.ex_ststart;
		
	// find first stat to display		
	for(;;)
	{
		if(isPlayer(self))
		{
			// check that its worth displaying
			if(self checkValidStat(self.ex_showstat)) break;
			else self.ex_showstat++;

			if(self.ex_showstat > level.ex_stend) self.ex_showstat = level.ex_ststart;
		}
	}

	// display first stat
	chvr = getStat(self.ex_showstat);
	self displayStat(chvr);
}

// check the stat is worth displaying
checkValidStat(num)
{
	self endon("disconnect");

	if(!isDefined(num)) return false;
		
	valid = false;
	stat = getStat(num);
	
	players = getentarray("player", "classname");	
	for(i = 0;i < players.size;i++)
	{
		if(isPlayer(players[i]))
		{
			if(!isDefined(players[i].ex_statson)) players[i].pers[stat] = 0;
			else if(isDefined(players[i].ex_statson) && players[i].pers[stat] != 0) valid = true;

			if(valid) break;
		}
	}
			
	if(valid) return true;
	else return false;
}

// check the amount of stats that will be displayed
checkForLastStat()
{
	laststat = 0;

	players = getentarray("player", "classname");	
	for(i = 0; i < players.size; i++)
	{
		if(isPlayer(players[i])) player = players[i];
		else continue;

		tempstat = 0;

		for(j = level.ex_ststart; j <= level.ex_stend; j++)
		{
			stat = getStat(j);

			if(isPlayer(player))
			{
				if(!isDefined(player.pers[stat])) player.pers[stat] = 0;
				else if(player.pers[stat] != 0) tempstat = j;
			}
		}

		if(tempstat > laststat) laststat = tempstat;
	}

	return laststat;
}

// setup hudelems(self)
initHud()
{
	level endon("endstats");
	self endon("disconnect");

	if(isPlayer(self))
	{
		// variable header
		self.ex_stdiself[0] = newclienthudelem(self);
		self.ex_stdiself[0].archived = false;
		self.ex_stdiself[0].alpha = 1;
		self.ex_stdiself[0].alignx = "center";
		self.ex_stdiself[0].aligny = "middle";
		self.ex_stdiself[0].x = 320;
		self.ex_stdiself[0].y = 89; //70;
		self.ex_stdiself[0].sort = 102;
		self.ex_stdiself[0].fontscale = 1.6;
		
		// press fire, calculating & max cycle
		self.ex_stdiself[1] = newclienthudelem(self);
		self.ex_stdiself[1].archived = false;
		self.ex_stdiself[1].alpha = 1;
		self.ex_stdiself[1].alignx = "left";
		self.ex_stdiself[1].aligny = "middle";
		self.ex_stdiself[1].x = 108;
		self.ex_stdiself[1].y = 306 - level.ex_diff; //287-level.ex_diff;
		self.ex_stdiself[1].sort = 102;
		self.ex_stdiself[1].fontscale = 1;
	}
}

// fade in/out hudelems (self)
doPlayerFades(state,time,kpfca)
{
	self endon("disconnect");

	if(!isDefined(state)) state  = 0;
			
	if(!isDefined(time)) time = 1;

	if(isDefined(kpfca))
	{
		if(isDefined(self.ex_stdiself[0]))
		{
			self.ex_stdiself[0] fadeovertime (time);
			self.ex_stdiself[0].alpha = state;
		}
	}
	else if(isDefined(self.ex_stdiself))
	{
		for(i = 0;i < self.ex_stdiself.size;i++)
		{
			if(isDefined(self.ex_stdiself[i]))
			{
				self.ex_stdiself[i] fadeovertime (time);
				self.ex_stdiself[i].alpha = state;
			}
		}
	}
	
	if(isDefined(self.ex_stpts))
	{
		for(i = 0;i < self.ex_stpts.size;i++)
		{
			if(isDefined(self.ex_stpts[i]))
			{
				self.ex_stpts[i] fadeovertime (time);
				self.ex_stpts[i].alpha = state;
			}
		}
	}
	
	if(isDefined(self.ex_sticon))
	{
		for(i = 0;i < self.ex_sticon.size;i++)
		{
			if(isDefined(self.ex_sticon[i]))
			{
				self.ex_sticon[i] fadeovertime(time);
				self.ex_sticon[i].alpha = state;
			}
		}
	}
		
	if(isDefined(self.ex_dina))
	{
		for(i = 0;i < self.ex_dina.size;i++)
		{
			if(isDefined(self.ex_dina[i]))
			{
				self.ex_dina[i] fadeovertime (time);
				self.ex_dina[i].alpha = state;
			}
		}
	}
}

// destroy hudelems (level and self)
destroyStatsboard()
{
	// destroy level hudelems
	if(isDefined(level.ex_stdis)) for(i = 0; i < level.ex_stdis.size; i++) level.ex_stdis[i] destroy();

	// destroy player(self) hudelems	
	players = getentarray("player", "classname");

	for(i = 0; i < players.size; i++)
	{
		if(isPlayer(players[i]) && isDefined(players[i].ex_stdiself))
		{
			for(j = 0;j < players[i].ex_stdiself.size;j++)
			{
				players[i].ex_stdiself[j] destroy();
				players[i] clearStat();
			}
		}
	}
}

// clear the stats screen elems (self)
clearStat()
{
	if(isPlayer(self))
	{
		self notify("end_playernames");
		self thread [[level.ex_clearlnb]]("self",5);

		// clear player names
		if(isDefined(self.ex_dina)) for(i = 0;i < self.ex_dina.size;i++) if(isDefined(self.ex_dina[i])) self.ex_dina[i] destroy();

		// clear player team icons
		if(isDefined(self.ex_sticon)) for(i = 0;i < self.ex_sticon.size;i++) if(isDefined( self.ex_sticon[i])) self.ex_sticon[i] destroy();
		
		// clear player points	
		if(isDefined(self.ex_stpts)) for(i = 0;i < self.ex_stpts.size;i++) if(isDefined( self.ex_stpts[i])) self.ex_stpts[i] destroy();
	}
}

// display the stats for players
displayStat(var)
{
	self endon("disconnect");

	self.ex_printy = 0;
	sn = 0;
	si = 0;
	
	if(level.ex_statsover) return;

	// setup stats hudelems(self)
	if(isPlayer(self) && !level.ex_statsover)
	{
		self.ex_stdiself[0] settext(getStatTitle(self.ex_showstat)); 
	
		// check how many times stats have been reset (to avoid exceeding vars usage!)
		if(self.ex_cycle > 4)
		{
			if(isDefined(self.ex_stlimbo))
				return;

			self.ex_stlimbo = "true";
			self.ex_stdiself[0] settext(&"STATSBOARD_LIMBO_CYCLE_REACHED");
			self.ex_stdiself[1] settext(&"STATSBOARD_LIMBO_PLEASE_WAIT");
			return;
		}

		for(i = 0;i < level.ex_stmaxp;i++)
		{		
			self.ex_sticon[i] = newclienthudelem(self);
			self.ex_sticon[i].archived = false;
			self.ex_sticon[i].alpha = 1;
			self.ex_sticon[i].alignx = "center";
			self.ex_sticon[i].aligny = "middle";
			self.ex_sticon[i].x = 113;
			self.ex_sticon[i].sort = 102;
			self.ex_sticon[i].color = (1,1,1);

			self.ex_stpts[i] = newclienthudelem(self);
			self.ex_stpts[i].archived = false;
			self.ex_stpts[i].alpha = 1;
			self.ex_stpts[i].alignx = "center";
			self.ex_stpts[i].aligny = "middle";
			self.ex_stpts[i].x = 520;
			self.ex_stpts[i].fontscale = 1;
			self.ex_stpts[i].sort = 102;
			self.ex_stpts[i].color = (1,1,0);
		}
	}

	// sort the stats to display
	stbdpl = getentarray("player", "classname");	
	if(isPlayer(self) && !level.ex_statsover)
	{
		for(i= 0; i < stbdpl.size; i++)
		{
			for(j = i; j < stbdpl.size; j++)
			{
				if(isPlayer(stbdpl[i]) && isDefined(stbdpl[i].pers[var]) && isDefined(stbdpl[i].ex_statson) && isPlayer(stbdpl[j]) && isDefined(stbdpl[j].pers[var]) && isDefined(stbdpl[j].ex_statson))
				{
					if(stbdpl[i].pers[var] < stbdpl[j].pers[var])
					{
						temp = stbdpl[i];
						stbdpl[i] = stbdpl[j];
						stbdpl[j] = temp;
					}
				}
			}
		}

		emptylines = 0;

		if(isPlayer(self))
		{
			self.ex_ipname = [];

			// add player names
			for(i = 0; i < 5; i++)
			{
				if(isPlayer(self) && !level.ex_statsover)
				{
					if(isPlayer(stbdpl[i])) self.ex_ipname[i] = stbdpl[i];
					else emptylines++;
					wait 0.01;
				}
			}
		}

		if(isPlayer(self)) self thread displayNames(emptylines);

		if(isPlayer(self)) self.ex_printy = 107; //90;

		// show player stat		
		for(i = 0; i < level.ex_stmaxp; i++)
		{
			if(isPlayer(self) && isPlayer(stbdpl[sn]) && isDefined(stbdpl[sn].pers[var]) && !level.ex_statsover)
			{
				self.ex_stpts[sn].y = self.ex_printy;
				self.ex_stpts[sn] setValue(stbdpl[sn].pers[var]);
				self.ex_printy += 16;
				sn++;
			}
		}

		if(isPlayer(self)) self.ex_printy = 107; //90;

		// show player team icon		
		for(i = 0; i < level.ex_stmaxp; i++)
		{
			if(isPlayer(self) && isPlayer(stbdpl[i]) && isDefined(stbdpl[i].ticon) && !level.ex_statsover)
			{
				self.ex_sticon[si].y = self.ex_printy + 1;
				self.ex_sticon[si] setshader(stbdpl[i].ticon, 10,10);
				self.ex_printy += 16;
				si++;
			}
		}
	}

	// fade in new stats
	if(isPlayer(self)) self doPlayerFades(1,.5,1);
	
	// change status message to press fire
	if(isPlayer(self) && !level.ex_statsover) self.ex_stdiself[1] settext(&"STATSBOARD_PRESS_FIRE");	
}

displayNames(emptylines)
{
	self endon("disconnect");
	self endon("end_playernames");

	while(1)
	{
		wait 0.1;
		for(i = 0; i < self.ex_ipname.size; i++) if(isPlayer(self) && isPlayer(self.ex_ipname[i])) self iprintlnbold(self.ex_ipname[i]);
		if(emptylines >= 1) self thread [[level.ex_clearlnb]]("self", emptylines);
		wait 7.7;
	}
}

getStat(stat)
{
	switch(stat)
	{
		// kills
		case 1:   return "kill";
		case 2:   return "grenadekill";
		case 3:   return "tripwirekill";
		case 4:   return "headshotkill";
		case 5:   return "bashkill";
		case 6:   return "sniperkill";
		case 7:   return "knifekill";
		case 8:   return "mortarkill";
		case 9:   return "artillerykill";
		case 10:  return "airstrikekill";
		case 11:  return "napalmkill";
		case 12:  return "panzerkill";
		case 13:  return "spawnkill";
		case 14:  return "spamkill";
		case 15:  return "teamkill";
		case 16:  return "remotekill";

		// deaths
		case 17:  return "death";
		case 18:  return "grenadedeath";
		case 19:  return "tripwiredeath";
		case 20:  return "headshotdeath";
		case 21:  return "bashdeath";
		case 22:  return "sniperdeath";
		case 23:  return "knifedeath";
		case 24:  return "mortardeath";
		case 25:  return "artillerydeath";
		case 26:  return "airstrikedeath";
		case 27:  return "napalmdeath";
		case 28:  return "panzerdeath";
		case 29:  return "spawndeath";
		case 30:  return "planedeath";
		case 31:  return "remotedeath";
		case 32:  return "fallingdeath";
		case 33:  return "minefielddeath";
		case 34:  return "suicide";

		case 101: return "score";
		case 102: return "effiency";
	}
}

getStatTitle(stat)
{
	switch(stat)
	{
		case 1:   return &"STATSBOARD_KILL";
		case 2:   return &"STATSBOARD_GRENADE_KILL";
		case 3:   return &"STATSBOARD_TRIPWIRE_KILL";
		case 4:   return &"STATSBOARD_HEADSHOT_KILL";
		case 5:   return &"STATSBOARD_BASH_KILL";
		case 6:   return &"STATSBOARD_SNIPER_KILL";
		case 7:   return &"STATSBOARD_KNIFE_KILL";
		case 8:   return &"STATSBOARD_MORTAR_KILL";
		case 9:   return &"STATSBOARD_ARTILLERY_KILL";
		case 10:  return &"STATSBOARD_AIRSTRIKE_KILL";
		case 11:  return &"STATSBOARD_NAPALM_KILL";
		case 12:  return &"STATSBOARD_PANZER_KILL";
		case 13:  return &"STATSBOARD_SPAWN_KILL";
		case 14:  return &"STATSBOARD_SPAM_KILL";
		case 15:  return &"STATSBOARD_TEAM_KILL";
		case 16:  return &"STATSBOARD_REMOTE_KILL";

		case 17:  return &"STATSBOARD_DEATH";
		case 18:  return &"STATSBOARD_GRENADE_DEATH";
		case 19:  return &"STATSBOARD_TRIPWIRE_DEATH";
		case 20:  return &"STATSBOARD_HEADSHOT_DEATH";
		case 21:  return &"STATSBOARD_BASH_DEATH";
		case 22:  return &"STATSBOARD_SNIPER_DEATH";
		case 23:  return &"STATSBOARD_KNIFE_DEATH";
		case 24:  return &"STATSBOARD_MORTAR_DEATH";
		case 25:  return &"STATSBOARD_ARTILLERY_DEATH";
		case 26:  return &"STATSBOARD_AIRSTRIKE_DEATH";
		case 27:  return &"STATSBOARD_NAPALM_DEATH";
		case 28:  return &"STATSBOARD_PANZER_DEATH";
		case 29:  return &"STATSBOARD_SPAWN_DEATH";
		case 30:  return &"STATSBOARD_PLANE_DEATH";
		case 31:  return &"STATSBOARD_REMOTE_DEATH";
		case 32:  return &"STATSBOARD_FALLING_DEATH";
		case 33:  return &"STATSBOARD_MINEFIELD_DEATH";
		case 34:  return &"STATSBOARD_SUICIDE";

		case 101: return &"STATSBOARD_HIGH_SCORE";
		case 102: return &"STATSBOARD_EFFICIENCY";
	}
}
