All pastes #608627 Raw Edit

agu's Race Filterscript v0.2d

public text v1 · immutable
·published 2007-07-08 12:51 UTC
rendered paste body
#define dcmd(%1,%2,%3) if ((strcmp((%3)[1], #%1, true, (%2)) == 0) && ((((%3)[(%2) + 1] == 0) && (dcmd_%1(playerid, "")))||(((%3)[(%2) + 1] == 32) && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1
#include <a_samp>
#include <float>
#include <file>

#define FILTERSCRIPT
#define MAX_RACECHECKPOINTS 64
#define RACEFILE_VERSION 1 // !!! DO NOT CHANGE !!!
// #define BUILDADMIN     //Require admin access for build commands, uncomment to enable
// #define RACEADMIN      //Require admin access for raceload & racestart, uncomment to enable

#define COLOR_GREEN 0x33AA33AA
#define COLOR_RED 0xAA3333AA
#define COLOR_YELLOW 0xFFFF00AA
#define COLOR_WHITE 0xFFFFFFAA

forward SaveScores();   				// After race, if new best times have been made, saves them.
forward GetRaceTick(playerid);			// Gets amount of ticks the player was racing
forward GetLapTick(playerid); 		 	// Gets amount of ticks the player spend on the lap
forward ReadyRefresh();      	  		// Check the /ready status of players and start the race when ready
forward RaceSound(playerid,sound);      // Plays <sound> for <playerid>
forward BActiveCP(playerid,sele);       // Gives the player selected checkpoint
forward endrace();                      // Ends the race, whether it ended normally or by /endrace. Cleans the variables.
forward countdown();                    // Handles the countdown
forward strtok(const string[],&index);
forward SetNextCheckpoint(playerid);    // Gives the next checkpoint for the player during race
forward CheckBestLap(playerid, laptime);	// Check if <laptime> is better than any of the ones in highscore list, and update.
forward CheckBestRace(playerid,racetime);   // Check if <racetime> is better than any of the ones in highscore list, and update.
forward ChangeLap(playerid);            // Change player's lap, print out time and stuff.
forward SetRaceCheckpoint(playerid,target,next);

new Prize=15000;                                    //Money for winning the race.
new Countdown;                                      //Countdown timer
new cd;                                             //Countdown time
new Ranking;                                        //Finishing order for prizes
new RaceActive;                                     //Is a race active?
new RaceStart;                                      //Has race started?
new BCurrentCheckpoints[MAX_PLAYERS];               //Buildrace array pointers
new BSelectedCheckpoint[MAX_PLAYERS];               //Selected checkpoint during building
new RaceBuilders[MAX_PLAYERS];                      //Who is building a race?
new Float:BRaceCheckpoints[MAX_PLAYERS][MAX_RACECHECKPOINTS][3]; //Buildrace CP array
new Float:RaceCheckpoints[MAX_RACECHECKPOINTS][3];  //Current race CP array
new LCurrentCheckpoint;                             //Current race array pointer
new CurrentCheckpoint[MAX_PLAYERS];                 //Current race array pointer array :V
new CurrentLap[MAX_PLAYERS];                        //Current lap array
new RaceParticipant[MAX_PLAYERS];                   //Has the player /joined the race
  // \_values: 0 - not in race, 1 - joined, 2 - arrived to start CP, 3 - /ready locked, 4 - racing, 5 - Last CP
new Participants;                                   //Amount of participants
new PlayerVehicles[MAX_PLAYERS];                    //For slapping the player back in their vehicle.
new Bracemode[MAX_PLAYERS];
new Blaps[MAX_PLAYERS];
new CBuilder[MAX_PLAYER_NAME], CFile[64], CRaceName[128];        //Creator of the race and the filename, for score changing purposes.
new ORacelaps, ORacemode;   //Saves the laps/mode from file in case they are changed
new Racelaps, Racemode;		//If mode/laps has been changed, the new scores won't be saved.
new ScoreChange;            //Flag for new best times, so they are saved.
new RaceTick;               //Startime of the race
new LastLapTick[MAX_PLAYERS];       //Array that stores the times when players started the lap
new TopRacers[6][MAX_PLAYER_NAME]; // Stores 5 top scores, 6th isn't
new TopRacerTimes[6];              // saved to file, used to simplify
new TopLappers[6][MAX_PLAYER_NAME];// for() loops on CheckBestLap and
new TopLapTimes[6];                // CheckBestRace.

public OnFilterScriptInit()
{
	print("\n+--------------------------------+");
	print("| Yagu's Race Filterscript v0.2d |");
	print("+------------LOADED--------------+\n");
	RaceActive=0;
	Ranking=1;
	LCurrentCheckpoint=0;
	Participants=0;
	return 1;
}

public OnFilterScriptExit()
{
	print("\n+--------------------------------+");
	print("| Yagu's Race Filterscript v0.2d |");
	print("+-----------UNLOADED-------------+\n");
	return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
	dcmd(racehelp,8,cmdtext);	// Racehelp - there's a lot of commands!
	dcmd(buildhelp,9,cmdtext);	// Buildhelp - there's a lot of commands!
	dcmd(buildrace,9,cmdtext);	// Buildrace - Start building a new race (suprising!)
	dcmd(cp,2,cmdtext);		  	// cp - Add a checkpoint
	dcmd(scp,3,cmdtext);		// scp - Select a checkpoint
	dcmd(rcp,3,cmdtext);		// rcp - Replace the current checkpoint with a new one
	dcmd(mcp,3,cmdtext);		// mcp - Move the selected checkpoint
	dcmd(dcp,3,cmdtext);       	// dcp - Delete the selected waypoint
	dcmd(clearrace,9,cmdtext);	// clearrace - Clear the current (new) race.
	dcmd(editrace,8,cmdtext);	// editrace - Load an existing race into the builder
	dcmd(saverace,8,cmdtext);	// saverace - Save the current checkpoints to a file
	dcmd(setlaps,7,cmdtext);	// setlaps - Set amount of laps to drive
	dcmd(racemode,8,cmdtext);	// racemode - Set the current racemode
	dcmd(loadrace,8,cmdtext);	// loadrace - Load a race from file and start it
	dcmd(join,4,cmdtext);		// join - Join the announced race.
	dcmd(leave,5,cmdtext);		// leave - leave the current race.
	dcmd(endrace,7,cmdtext);	// endrace - Complete the current race, clear tables & variables, stop the timer.
	dcmd(ready,5,cmdtext);		// ready - Player is ready to start, lock the controls, prepare for CD.
	dcmd(bestlap,7,cmdtext);	// bestlap - Display the best lap times for the current race
	dcmd(bestrace,8,cmdtext);	// bestrace - Display the best race times for the current race
	return 0;
}

dcmd_racehelp(playerid, params[])
{
    #pragma unused params
	SendClientMessage(playerid, COLOR_GREEN, "Yagu's race script racing help:");
	SendClientMessage(playerid, COLOR_WHITE, "/loadrace [name] to load a track & start it. Use /join to jo in,");
	SendClientMessage(playerid, COLOR_WHITE, "and /ready once at start to begin the race once others are ready");
	SendClientMessage(playerid, COLOR_WHITE, "as well. /leave to leave the race./endrace to aborts the race.");
	SendClientMessage(playerid, COLOR_WHITE, "/bestlap shows best laps for the race, /bestrace for the whole");
	SendClientMessage(playerid, COLOR_WHITE, "race. For info on building races, see /buildhelp");
	return 1;
}

dcmd_buildhelp(playerid, params[])
{
    #pragma unused params
	SendClientMessage(playerid, COLOR_GREEN, "Yagu's race script building help:");
	SendClientMessage(playerid, COLOR_WHITE, "/buildrace to start a new track, /cp to place a checkpoint");
	SendClientMessage(playerid, COLOR_WHITE, "/scp to choose an old checkpoint, /dcp to delete it, /mcp to move it.");
	SendClientMessage(playerid, COLOR_WHITE, "/rcp to replace the current checkpoint, /editrace to load a race to editor.");
	SendClientMessage(playerid, COLOR_WHITE, "/saverace [name] to save the race, and /clearrace to clear the race.");
	SendClientMessage(playerid, COLOR_WHITE, "/racemode [0/1/2] to change racemode, /setlaps [amount] to set amount of laps.");
	SendClientMessage(playerid, COLOR_WHITE, "For info on racing itself, see /racehelp");
	return 1;
}

dcmd_buildrace(playerid, params[])
{
    #pragma unused params
	#if defined BUILDADMIN
    if (!IsPlayerAdmin(playerid))
	{
	    SendClientMessage(playerid, COLOR_RED, "You need to be an admin to use this command!");
	    return 1;
    }
	#endif
	if(RaceBuilders[playerid] == 1)
	{
		SendClientMessage(playerid, COLOR_YELLOW, "You are already building a race, dork.");
	}
	else if(RaceParticipant[playerid]>0)
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "You are participating in a race, can't build a race.");
	}
	else
	{
		SendClientMessage(playerid, COLOR_GREEN, "You are now building a race.");
		RaceBuilders[playerid]=1;
		BCurrentCheckpoints[playerid]=0;
		Bracemode[playerid]=0;
		Blaps[playerid]=0;
	}
	return 1;
}

dcmd_cp(playerid, params[])
{
	#pragma unused params
	if(RaceBuilders[playerid] == 1 && BCurrentCheckpoints[playerid] < MAX_RACECHECKPOINTS)
	{
		new Float:x, Float:y, Float:z;
		GetPlayerPos(playerid,x,y,z);
		SetPlayerRaceCheckpoint(playerid,1,x,y,z,0.0,0.0,0.0,8.0);
		new string[128];
		format(string,128,"Checkpoint %d created: %f,%f,%f.",BCurrentCheckpoints[playerid],x,y,z);
		SendClientMessage(playerid, COLOR_GREEN, string);
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][0]=x;
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][1]=y;
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][2]=z;
		BSelectedCheckpoint[playerid]=BCurrentCheckpoints[playerid];
		BCurrentCheckpoints[playerid]++;
	}
	else if(RaceBuilders[playerid] == 1 && BCurrentCheckpoints[playerid] == MAX_RACECHECKPOINTS)
	{
		new string[128];
		format(string,128,"Sorry, maximum amount of checkpoints reached (%d).",MAX_RACECHECKPOINTS);
		SendClientMessage(playerid, COLOR_YELLOW, string);
	}
	else
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
	}
	return 1;
}

dcmd_scp(playerid, params[])
{
	new sele, tmp[256], idx;
    tmp = strtok(params, idx);
    if(!strlen(tmp)) {
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /scp [checkpoint]");
		return 1;
    }
    sele = strval(tmp);
	if(RaceBuilders[playerid] == 1)
	{
		if(sele>BCurrentCheckpoints[playerid]-1 || BCurrentCheckpoints[playerid] < 1 || sele < 0)
		{
			SendClientMessage(playerid, COLOR_YELLOW, "Invalid checkpoint!");
			return 1;
		}
		new string[128];
		format(string,128,"Selected checkpoint %d.",sele);
		SendClientMessage(playerid, COLOR_GREEN, string);
		BActiveCP(playerid,sele);
		BSelectedCheckpoint[playerid]=sele;
	}
	else
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
	}
	return 1;
}

dcmd_rcp(playerid, params[])
{
	#pragma unused params
	if(RaceBuilders[playerid] != 1)
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
		return 1;
	}
	else if(BCurrentCheckpoints[playerid] < 1)
	{
		SendClientMessage(playerid, COLOR_YELLOW, "No checkpoint to replace!");
		return 1;
	}
	new Float:x,Float:y,Float:z;
	GetPlayerPos(playerid,x,y,z);
	SetPlayerRaceCheckpoint(playerid,1,x,y,z,0.0,0.0,0.0,8.0);
	new string[128];
	format(string,128,"Checkpoint %d replaced: %f,%f,%f.",BSelectedCheckpoint[playerid],x,y,z);
	SendClientMessage(playerid, COLOR_GREEN, string);
	BRaceCheckpoints[playerid][BSelectedCheckpoint[playerid]][0]=x;
	BRaceCheckpoints[playerid][BSelectedCheckpoint[playerid]][1]=y;
	BRaceCheckpoints[playerid][BSelectedCheckpoint[playerid]][2]=z;
	BActiveCP(playerid,BSelectedCheckpoint[playerid]);
    return 1;
}

dcmd_mcp(playerid, params[])
{
	if(RaceBuilders[playerid] != 1)
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
		return 1;
	}
	else if(BCurrentCheckpoints[playerid] < 1)
	{
		SendClientMessage(playerid, COLOR_YELLOW, "No checkpoint to move!");
		return 1;
	}
	new idx, direction, dir[32];
	dir=strtok(params, idx);
	new Float:amount=floatstr(strtok(params,idx));
	if(amount == 0.0 || (dir[0] != 'x' && dir[0]!='y' && dir[0]!='z'))
	{
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /mcp [x,y or z] [amount]");
		return 1;
	}
    if(dir[0] == 'x') direction=0;
    else if (dir[0] == 'y') direction=1;
    else if (dir[0] == 'z') direction=2;
    BRaceCheckpoints[playerid][BSelectedCheckpoint[playerid]][direction]=BRaceCheckpoints[playerid][BSelectedCheckpoint[playerid]][direction]+amount;
	BActiveCP(playerid,BSelectedCheckpoint[playerid]);
	return 1;
}

dcmd_dcp(playerid, params[])
{
	#pragma unused params
	if(RaceBuilders[playerid] != 1)
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
		return 1;
	}
	else if(BCurrentCheckpoints[playerid] < 1)
	{
		SendClientMessage(playerid, COLOR_YELLOW, "No checkpoint to delete!");
		return 1;
	}
	for(new i=BSelectedCheckpoint[playerid];i<BCurrentCheckpoints[playerid];i++)
	{
		BRaceCheckpoints[playerid][i][0]=BRaceCheckpoints[playerid][i+1][0];
		BRaceCheckpoints[playerid][i][1]=BRaceCheckpoints[playerid][i+1][1];
		BRaceCheckpoints[playerid][i][2]=BRaceCheckpoints[playerid][i+1][2];
	}
	BCurrentCheckpoints[playerid]--;
	BSelectedCheckpoint[playerid]--;
	if(BCurrentCheckpoints[playerid] < 1)
	{
	    DisablePlayerRaceCheckpoint(playerid);
	    BSelectedCheckpoint[playerid]=0;
		return 1;
	}
	else if(BSelectedCheckpoint[playerid] < 0)
	{
	    BSelectedCheckpoint[playerid]=0;
	}
	BActiveCP(playerid,BSelectedCheckpoint[playerid]);
	return 1;
}

dcmd_clearrace(playerid,params[])
{
	#pragma unused params
	if(RaceBuilders[playerid] == 1)
	{
		RaceBuilders[playerid]=0;
		for(new i=0;i<BCurrentCheckpoints[playerid];i++)
		{
			BRaceCheckpoints[playerid][i][0]=0.0;
			BRaceCheckpoints[playerid][i][1]=0.0;
			BRaceCheckpoints[playerid][i][2]=0.0;
		}
		BCurrentCheckpoints[playerid]=0;
		DisablePlayerRaceCheckpoint(playerid);
		SendClientMessage(playerid, COLOR_GREEN, "Your race has been cleared! Use /buildrace to start a new one.");
	}
	else
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
	}
	return 1;
}

dcmd_editrace(playerid,params[])
{
	if(RaceBuilders[playerid] != 1)
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
		return 1;
	}
	if(BCurrentCheckpoints[playerid]>0) //Clear the old race if there is such.
	{
		for(new i=0;i<BCurrentCheckpoints[playerid];i++)
		{
			BRaceCheckpoints[playerid][i][0]=0.0;
			BRaceCheckpoints[playerid][i][1]=0.0;
			BRaceCheckpoints[playerid][i][2]=0.0;
		}
		BCurrentCheckpoints[playerid]=0;
	}
	new tmp[256],idx;
    tmp = strtok(params, idx);
    if(!strlen(tmp))
	{
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /editrace [name]");
		return 1;
    }
	new race_name[32],templine[42];
	format(race_name,sizeof(race_name), "%s.yr",tmp);
	if(!fexist(race_name))
	{
		new string[64];
		format(string,sizeof(string), "The race \"%s\" doesn't exist.",tmp);
		SendClientMessage(playerid, COLOR_RED, string);
		return 1;
	}
    BCurrentCheckpoints[playerid]=-1;
	new File:f, i;
	f = fopen(race_name, io_read);
	new string[128];
	fread(f,templine,sizeof(templine));
	if(templine[0] == 'Y') //Checking if the racefile is v0.2+
	{
		new fileversion;
	    strtok(templine,i); // read off YRACE
		fileversion = strval(strtok(templine,i)); // read off the file version
		if(fileversion > RACEFILE_VERSION) // Check if the race is made with a newer version of the racefile format
		{
		    format(string,128,"Race \'%s\' is created with a newer version of YRACE, unable to load.",tmp);
		    SendClientMessage(playerid,COLOR_RED,string);
		    return 1;
		}
		strtok(templine,i); // read off RACEBUILDER
		Bracemode[playerid] = strval(strtok(templine,i)); // read off racemode
		Blaps[playerid] = strval(strtok(templine,i)); // read off amount of laps
		fread(f,templine,sizeof(templine)); // read off best race times, not saved due to editing the track
		fread(f,templine,sizeof(templine)); // read off best lap times,          -||-
	}
	else //Otherwise add the lines as checkpoints, the file is made with v0.1 (or older) version of the script.
	{
		BCurrentCheckpoints[playerid]++;
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][0] = floatstr(strtok(templine,i));
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][1] = floatstr(strtok(templine,i));
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][2] = floatstr(strtok(templine,i));
	}
	while(fread(f,templine,sizeof(templine),false))
	{
		BCurrentCheckpoints[playerid]++;
		i=0;
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][0] = floatstr(strtok(templine,i));
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][1] = floatstr(strtok(templine,i));
		BRaceCheckpoints[playerid][BCurrentCheckpoints[playerid]][2] = floatstr(strtok(templine,i));
	}
	fclose(f);
	BCurrentCheckpoints[playerid]++; // # of next CP to be created
	format(string,128,"Race \"%s\" has been loaded for editing. (%d checkpoints)",tmp,BCurrentCheckpoints[playerid]);
	SendClientMessage(playerid, COLOR_GREEN, string);
    return 1;
}
dcmd_saverace(playerid, params[])
{
	if(RaceBuilders[playerid] == 1)
	{
		new tmp[256], idx;
	    tmp = strtok(params, idx);
	    if(!strlen(tmp))
		{
			SendClientMessage(playerid, COLOR_WHITE, "USAGE: /saverace [name]");
			return 1;
	    }
	    if(BCurrentCheckpoints[playerid] < 2)
	    {
	        SendClientMessage(playerid, COLOR_YELLOW, "You need atleast 2 checkpoints to save!");
	        return 1;
	    }
		new race_name[32],templine[42];
		format(race_name, 32, "%s.yr",tmp);
		if(fexist(race_name))
		{
			new string[64];
			format(string,sizeof(string), "Race \"%s\" already exists.",tmp);
			SendClientMessage(playerid, COLOR_RED, string);
			return 1;
		}
		new File:f,Float:x,Float:y,Float:z, Bcreator[MAX_PLAYER_NAME];
		GetPlayerName(playerid, Bcreator, MAX_PLAYER_NAME);
		f = fopen(race_name,io_write);
		format(templine,sizeof(templine),"YRACE %d %s %d %d\n", RACEFILE_VERSION, Bcreator, Bracemode, Blaps);
		fwrite(f,templine);
		format(templine,sizeof(templine),"A 0 A 0 A 0 A 0 A 0\n"); //Best complete race times
		fwrite(f,templine);
		format(templine,sizeof(templine),"A 0 A 0 A 0 A 0 A 0\n"); //Best lap times
		fwrite(f,templine);
		for(new i = 0; i < BCurrentCheckpoints[playerid];i++)
		{
			x=BRaceCheckpoints[playerid][i][0];
			y=BRaceCheckpoints[playerid][i][1];
			z=BRaceCheckpoints[playerid][i][2];
			format(templine,sizeof(templine),"%f %f %f\n",x,y,z);
			fwrite(f,templine);
		}
		fclose(f);
		new string[128];
		format(string,128,"Your race \"%s\" has been saved.",tmp);
   		SendClientMessage(playerid, COLOR_GREEN, string);
	}
	else
	{
		SendClientMessage(playerid, COLOR_RED, "You are not building a race!");
	}
	return 1;
}

dcmd_setlaps(playerid,params[])
{
	new tmp[256], idx;
    tmp = strtok(params, idx);
    if(!strlen(tmp))
	{
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /setlaps [amount of laps]");
		return 1;
   	}
	if(RaceBuilders[playerid] == 1)
    {
		Blaps[playerid] = strval(tmp);
		format(tmp,sizeof(tmp),"Amount of laps set to %d.", Blaps[playerid]);
		SendClientMessage(playerid, COLOR_GREEN, tmp);
        return 1;
    }
	#if defined RACEADMIN
    if (!IsPlayerAdmin(playerid))
	{
	    SendClientMessage(playerid, COLOR_RED, "You need to be an admin to use this command!");
	    return 1;
    }
    #endif
	if(RaceActive == 0 || RaceStart == 1)
	{
	    SendClientMessage(playerid, COLOR_RED, "No race active!");
	}
	else
	{
	    Racelaps=strval(tmp);
		format(tmp,sizeof(tmp),"Amount of laps set to %d for current race.", Racelaps);
		SendClientMessage(playerid, COLOR_GREEN, tmp);
	}
	return 1;
}

dcmd_racemode(playerid,params[])
{
	new tmp[256], idx;
    tmp = strtok(params, idx);
    if(!strlen(tmp))
	{
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /racemode [0/1/2]");
		return 1;
   	}
   	else if (0 < strval(tmp) > 2)
   	{
   	    SendClientMessage(playerid, COLOR_YELLOW, "Invalid racemode!");
		return 1;
   	}
	if(RaceBuilders[playerid] == 1)
    {
		if(strval(tmp) == 2 && BCurrentCheckpoints[playerid] < 3)
		{
		    SendClientMessage(playerid, COLOR_YELLOW, "Can't set racemode 2 on races with only 2 CPs. Changing to mode 1 instead.");
		    Bracemode[playerid] = 1;
		    return 1;
		}
		Bracemode[playerid] = strval(tmp);
		format(tmp,sizeof(tmp),"Racemode set to %d.", Bracemode[playerid]);
		SendClientMessage(playerid, COLOR_GREEN, tmp);
        return 1;
    }
	#if defined RACEADMIN
	    if (!IsPlayerAdmin(playerid))
		{
		    SendClientMessage(playerid, COLOR_RED, "You need to be an admin to use this command!");
		    return 1;
	    }
	#endif
	if(RaceActive == 0 || RaceStart == 1)
	{
	    SendClientMessage(playerid, COLOR_RED, "No race active!");
	}
	else
	{
		if(strval(tmp) == 2 && LCurrentCheckpoint < 2)
		{
		    SendClientMessage(playerid, COLOR_YELLOW, "Can't set racemode 2 on races with only 2 CPs. Changing to mode 1 instead.");
		    Racemode = 1;
		    return 1;
		}
	    Racemode=strval(tmp);
		format(tmp,sizeof(tmp),"Racemode set to %d.", Racemode);
		SendClientMessage(playerid, COLOR_GREEN, tmp);
	}
	return 1;
}

dcmd_loadrace(playerid, params[])
{
	#if defined RACEADMIN
    if (!IsPlayerAdmin(playerid))
	{
	    SendClientMessage(playerid, COLOR_RED, "You need to be an admin to use this command!");
	    return 1;
    }
	#endif
	Racemode = 0; Racelaps = 1;
	new tmp[128], idx;
    tmp = strtok(params, idx);
    if(!strlen(tmp))
	{
		SendClientMessage(playerid, COLOR_WHITE, "USAGE: /loadrace [name]");
		return 1;
    }
    if(RaceActive == 1)
    {
		SendClientMessage(playerid, COLOR_RED, "A race is already active!");
		return 1;
    }
	new race_name[32],templine[512];
	CRaceName=tmp;
	format(race_name,sizeof(race_name), "%s.yr",tmp);
	if(!fexist(race_name))
	{
		new string[64];
		format(string,sizeof(string), "The race \"%s\" doesn't exist.",tmp);
		SendClientMessage(playerid, COLOR_RED, string);
		return 1;
	}
	CFile=race_name;
	if(fexist(race_name))
	{
		new string[128];
        LCurrentCheckpoint=-1;
		new File:f, i;
		f = fopen(race_name, io_read);
		fread(f,templine,sizeof(templine));
		if(templine[0] == 'Y') //Checking if the racefile is v0.2+
		{
			new fileversion;
		    strtok(templine,i); // read off YRACE
			fileversion = strval(strtok(templine,i)); // read off the file version
			if(fileversion > RACEFILE_VERSION) // Check if the race is made with a newer version of the racefile format
			{
			    format(string,128,"Race \'%s\' is created with a newer version of YRACE, unable to load.",tmp);
			    SendClientMessage(playerid,COLOR_RED,string);
			    return 1;
			}
			CBuilder=strtok(templine,i); // read off RACEBUILDER
			ORacemode = strval(strtok(templine,i)); // read off racemode
			ORacelaps = strval(strtok(templine,i)); // read off amount of laps
			Racemode=ORacemode; Racelaps=ORacelaps; //Allows changing the modes, but disables highscores if they've been changed.
			fread(f,templine,sizeof(templine)); // read off best race times
			i=0;
			for(new j=0;j<5;j++)
			{
			    TopRacers[j]=strtok(templine,i);
			    TopRacerTimes[j]=strval(strtok(templine,i));
			}
			fread(f,templine,sizeof(templine)); // read off best lap times
			i=0;
			for(new j=0;j<5;j++)
			{
			    TopLappers[j]=strtok(templine,i);
			    TopLapTimes[j]=strval(strtok(templine,i));
			}
		}
		else //Otherwise add the lines as checkpoints, the file is made with v0.1 (or older) version of the script.
		{
			LCurrentCheckpoint++;
			RaceCheckpoints[LCurrentCheckpoint][0] = floatstr(strtok(templine,i));
			RaceCheckpoints[LCurrentCheckpoint][1] = floatstr(strtok(templine,i));
			RaceCheckpoints[LCurrentCheckpoint][2] = floatstr(strtok(templine,i));
			Racemode=0; ORacemode=0; Racelaps=0; ORacelaps=0;   //Enables converting old files to new versions
			CBuilder="UNKNOWN";
			for(new j;j<5;j++)
			{
			    TopLappers[j]="A"; TopLapTimes[j]=0; TopRacers[j]="A"; TopRacerTimes[j]=0;
			}
		}
		while(fread(f,templine,sizeof(templine),false))
		{
			LCurrentCheckpoint++;
			i=0;
			RaceCheckpoints[LCurrentCheckpoint][0] = floatstr(strtok(templine,i));
			RaceCheckpoints[LCurrentCheckpoint][1] = floatstr(strtok(templine,i));
			RaceCheckpoints[LCurrentCheckpoint][2] = floatstr(strtok(templine,i));
		}
		fclose(f);
		if(LCurrentCheckpoint<2 && Racemode == 2)
		{
		    Racemode = 1; // Racemode 2 doesn't work well with only 2CPs, and mode 1 is just the same when playing with 2 CPs.
		}                 // Setting racemode 2 is prevented from racebuilder so this shouldn't happen anyways.
		format(string,128,"Race \'%s\' is about to start, type /join to join!",tmp);
		SendClientMessageToAll(COLOR_GREEN,string);
		RaceStart=0;
		RaceActive=1;
		ScoreChange=0;
		Ranking=1;
	}
	return 1;
}

dcmd_join(playerid,params[])
{
	#pragma unused params
	if(RaceBuilders[playerid] == 1)
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "You are currently building a race, can't join. Use /clearrace to exit build mode.");
	    return 1;
	}
	if(RaceParticipant[playerid]>0)
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "You've already joined the race!");
	}
	else if(RaceActive==1 && RaceStart==0)
	{
		CurrentCheckpoint[playerid]=0;
		SetRaceCheckpoint(playerid,0,1);
		RaceParticipant[playerid]=1;
		CurrentLap[playerid]=0;
		SendClientMessage(playerid, COLOR_GREEN, "You have joined the race, go to the start!");
		Participants++;
	}
	else if(RaceActive==1 && RaceStart==1)
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "The race has already started, can't join.");
	}
	else
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "There is no race you can join.");
	}
	return 1;
}

dcmd_leave(playerid,params[])
{
	#pragma unused params
	if(RaceParticipant[playerid] > 0)
	{
       	if(RaceParticipant[playerid]==3) //Player was still /ready-locked, unlocking.
		{
			TogglePlayerControllable(playerid,1);
	        if(PlayerVehicles[playerid] != 0)
	        {
	            PutPlayerInVehicle(playerid,PlayerVehicles[playerid],0);
	            PlayerVehicles[playerid]=0;
	        }
		}
		DisablePlayerRaceCheckpoint(playerid);
		RaceParticipant[playerid]=0;
		Participants--;
		SendClientMessage(playerid,COLOR_YELLOW,"You have left the race.");
        if(Participants == 0)
        {
            endrace();
        }
        ReadyRefresh();
	}
	else
	{
	    SendClientMessage(playerid, COLOR_YELLOW, "You aren't in a race.");
	}
    return 1;
}

dcmd_endrace(playerid, params[])
{
	#pragma unused params
	#if defined RACEADMIN
    if (!IsPlayerAdmin(playerid))
	{
	    SendClientMessage(playerid, COLOR_RED, "You need to be an admin to use this command!");
	    return 1;
    }
	#endif
    if(RaceActive==0)
    {
        SendClientMessage(playerid, COLOR_YELLOW, "There is no race active.");
		return 1;
    }
    endrace();
	return 1;
}

dcmd_ready(playerid, params[])
{
	#pragma unused params
	new PState=GetPlayerState(playerid);
	if(RaceParticipant[playerid]==2 && IsPlayerInRaceCheckpoint(playerid) && PState != PLAYER_STATE_PASSENGER)
	{
		SendClientMessage(playerid,COLOR_GREEN,"You are now ready. Type /ready again to cancel.");
		TogglePlayerControllable(playerid,0);
		if(IsPlayerInAnyVehicle(playerid))
		{
		    PlayerVehicles[playerid]=GetPlayerVehicleID(playerid);
		}
		else
		{
			PlayerVehicles[playerid]=0;
		}
		RaceParticipant[playerid]=3;
		ReadyRefresh();
	}
	else if (RaceParticipant[playerid]==3 && RaceStart==0)
	{
	    SendClientMessage(playerid,COLOR_YELLOW,"You are now not ready. Type /ready when you are.");
		TogglePlayerControllable(playerid,1);
	    RaceParticipant[playerid]=2;
	    if(PlayerVehicles[playerid] != 0)
	    {
	        PutPlayerInVehicle(playerid,PlayerVehicles[playerid],0);
	    	PlayerVehicles[playerid]=0;
	    }
	}
	else if (PState == PLAYER_STATE_PASSENGER)
	{
	    SendClientMessage(playerid,COLOR_YELLOW,"You need to be driving for yourself!");
	}
	else if(RaceParticipant[playerid]>0 && !IsPlayerInRaceCheckpoint(playerid))
	{
	    SendClientMessage(playerid,COLOR_YELLOW,"You need to be in the starting checkpoint to /ready");
	}
	else
	{
		SendClientMessage(playerid,COLOR_YELLOW,"You have not participated in a race.");
	}
    return 1;
}

dcmd_bestlap(playerid,params[])
{
	#pragma unused params
	if(RaceActive == 0)
	{
	    SendClientMessage(playerid,COLOR_YELLOW,"No race active!");
		return 1;
	}
	new string[128];
	format(string,sizeof(string),"%s by %s - Best Laps:",CRaceName,CBuilder);
	SendClientMessage(playerid,COLOR_GREEN,string);
	for(new i;i<5;i++)
	{
		if(TopLapTimes[i] == 0)
		{
		    format(string,sizeof(string),"%d. None yet",i+1);
			i=6;
		}
		else
		{
	 	   format(string,sizeof(string),"%d. %s - %s",i+1,BeHuman(TopLapTimes[i]),TopLappers[i]);
	    }
	    SendClientMessage(playerid,COLOR_GREEN,string);
	}
    return 1;
}

dcmd_bestrace(playerid,params[])
{
	#pragma unused params
	if(RaceActive == 0)
	{
	    SendClientMessage(playerid,COLOR_YELLOW,"No race active!");
		return 1;
	}
	new string[128];
	format(string,sizeof(string),"%s by %s - Best Race times:",CRaceName,CBuilder);
	SendClientMessage(playerid,COLOR_GREEN,string);
	for(new i;i<5;i++)
	{
		if(TopRacerTimes[i] == 0)
		{
		    format(string,sizeof(string),"%d. None yet",i+1);
			i=6;
		}
		else
		{
	 	   format(string,sizeof(string),"%d. %s - %s",i+1,BeHuman(TopRacerTimes[i]),TopRacers[i]);
	    }
	    SendClientMessage(playerid,COLOR_GREEN,string);
	}
    return 1;
}

public OnPlayerDisconnect(playerid,reason)
{
	if(RaceParticipant[playerid]>=1)
	{
		if(Participants==1) //Last participant leaving, ending race.
		{
			endrace();
		}
		if(RaceParticipant[playerid] < 3 && RaceStart == 0) //Doing readycheck since someone left
		{
		    ReadyRefresh();
		}
	    Participants--;
	    RaceParticipant[playerid]=0;
	    DisablePlayerRaceCheckpoint(playerid);
	}
	if(RaceBuilders[playerid]==1)
	{
   	    DisablePlayerRaceCheckpoint(playerid);
	    for(new i;i<BCurrentCheckpoints[playerid];i++)
	    {
	        BRaceCheckpoints[playerid][i][0]=0.0;
   	        BRaceCheckpoints[playerid][i][1]=0.0;
	        BRaceCheckpoints[playerid][i][2]=0.0;
		}
	} 
	return 1;
}

strtok(const string[], &index)
{
	new length = strlen(string);
	while ((index < length) && (string[index] <= ' '))
	{
		index++;
	}

	new offset = index;
	new result[20];
	while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
	{
		result[index - offset] = string[index];
		index++;
	}
	result[index - offset] = EOS;
	return result;
}

public countdown() {
	RaceStart=1;
	if(cd>0)
	{
       	new string[32];
		format(string, 32, "%d...",cd);
		for(new i=0;i<MAX_PLAYERS;i++)
		{
			if(RaceParticipant[i]>1)
			{
				RaceSound(i,1056);
			    GameTextForPlayer(i,string,1000,3);
		    }
	    }
	}
	else if(cd == 0)
	{
       	new string[32];
		format(string, 32, "GO!",cd);
	    KillTimer(Countdown);
		for(new i=0;i<MAX_PLAYERS;i++)
		{
			if(RaceParticipant[i]>1)
			{
				RaceSound(i,1057);
			    GameTextForPlayer(i,string,3000,3);
				TogglePlayerControllable(i,1);
				RaceParticipant[i]=4;
				CurrentLap[i]=1;
		        if(PlayerVehicles[i] != 0)
		        {
		            PutPlayerInVehicle(i,PlayerVehicles[i],0);
		            PlayerVehicles[i]=0;
		        }
				SetNextCheckpoint(i);
				RaceTick=tickcount();
		    }
	    }
	}
	cd--;
}
public SetNextCheckpoint(playerid)
{
	if(Racemode == 0)
	{
		CurrentCheckpoint[playerid]++;
		if(CurrentCheckpoint[playerid] == LCurrentCheckpoint)
		{
			SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],-1);
			RaceParticipant[playerid]=6;
		}
		else SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]+1);
	}
	else if(Racemode == 1)
	{
		CurrentCheckpoint[playerid]++;
		if(CurrentCheckpoint[playerid] == LCurrentCheckpoint+1 && CurrentLap[playerid] == Racelaps)
		{
			SetRaceCheckpoint(playerid,0,-1);
			RaceParticipant[playerid]=6;
		}
		else if (CurrentCheckpoint[playerid] == LCurrentCheckpoint+1 && CurrentLap[playerid] != Racelaps)
		{
			CurrentCheckpoint[playerid]=0;
			SetRaceCheckpoint(playerid,0,1);
			RaceParticipant[playerid]=5;
		}
		else if(CurrentCheckpoint[playerid] == 1 && RaceParticipant[playerid]==5)
		{
			ChangeLap(playerid);
			if(LCurrentCheckpoint==1)
			{
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],0);
			}
			else
			{
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],2);
            }
  		    RaceParticipant[playerid]=4;
		}
		else
		{
			if(LCurrentCheckpoint==1 || CurrentCheckpoint[playerid] == LCurrentCheckpoint) SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],0);
			else SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]+1);
		}
	}
	else if(Racemode == 2)
	{
		if(RaceParticipant[playerid]==4)
		{
			if(CurrentCheckpoint[playerid] == LCurrentCheckpoint) // @ Last CP, trigger last-1
			{
			    RaceParticipant[playerid]=5;
				CurrentCheckpoint[playerid]=LCurrentCheckpoint-1;
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]-1);
			}
			else if(CurrentCheckpoint[playerid] == LCurrentCheckpoint-1) // Second last CP, set next accordingly
			{
				CurrentCheckpoint[playerid]++;
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]-1);
			}
			else
			{
				CurrentCheckpoint[playerid]++;
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]+1);
			}
		}
		else if(RaceParticipant[playerid]==5)
		{
			if(CurrentCheckpoint[playerid] == 1 && CurrentLap[playerid] == Racelaps) //Set the finish line
			{
				SetRaceCheckpoint(playerid,0,-1);
				RaceParticipant[playerid]=6;
			}
			else if(CurrentCheckpoint[playerid] == 0) //At finish line, change lap.
			{
				ChangeLap(playerid);
				if(LCurrentCheckpoint==1)
				{
					SetRaceCheckpoint(playerid,1,0);
				}
				else
				{
					SetRaceCheckpoint(playerid,1,2);
	            }
	  		    RaceParticipant[playerid]=4;
			}
			else if(CurrentCheckpoint[playerid] == 1)
			{
				CurrentCheckpoint[playerid]--;
				SetRaceCheckpoint(playerid,0,1);
			}
			else
			{
				CurrentCheckpoint[playerid]--;
				SetRaceCheckpoint(playerid,CurrentCheckpoint[playerid],CurrentCheckpoint[playerid]-1);
			}
		}
	}
}

public SetRaceCheckpoint(playerid,target,next)
{
	if(next == -1) SetPlayerRaceCheckpoint(playerid,1,RaceCheckpoints[target][0],RaceCheckpoints[target][1],RaceCheckpoints[target][2],0.0,0.0,0.0,8.0);
	else SetPlayerRaceCheckpoint(playerid,0,RaceCheckpoints[target][0],RaceCheckpoints[target][1],RaceCheckpoints[target][2],RaceCheckpoints[next][0],RaceCheckpoints[next][1],RaceCheckpoints[next][2],8.0);
}

public GetLapTick(playerid)
{
	new tick, lap;
	tick=tickcount();
	if(CurrentLap[playerid]==1)
	{
		lap=tick-RaceTick;
		LastLapTick[playerid]=tick;
	}
	else
	{
		lap=tick-LastLapTick[playerid];
		LastLapTick[playerid]=tick;
	}
	return lap;
}

public GetRaceTick(playerid)
{
	new tick, race;
	tick=tickcount();
	race=tick-RaceTick;
	return race;
}

public OnPlayerEnterRaceCheckpoint(playerid)
{
	if(RaceParticipant[playerid]>=1) // See if the player is participating in a race, allows race builders to do their stuff in peace.
	{
		if(RaceParticipant[playerid] == 6) // Player reaches the checkered flag.
	    {
			new string[128], name[MAX_PLAYER_NAME], LapTime, RaceTime;
			LapTime=GetLapTick(playerid);
			RaceTime=GetRaceTick(playerid);
			GetPlayerName(playerid, name, MAX_PLAYER_NAME);
			RaceParticipant[playerid]=0;
			RaceSound(playerid,1139);
			format(string,128,"%s has finished the race, position: %d",name,Ranking);
			SendClientMessageToAll(COLOR_GREEN,string);
			if(Racemode == ORacemode && ORacelaps == Racelaps)
			{
				new	LapString[10],RaceString[10], laprank, racerank;
				LapString=BeHuman(LapTime);
				RaceString=BeHuman(RaceTime);
				format(string,128,"~w~Racetime: %s",LapString,RaceString);
				laprank=CheckBestLap(playerid,LapTime);
				if(laprank == 1)
				{
				    format(string,128,"%s~n~~y~LAP RECORD!",string);
				}
				racerank=CheckBestRace(playerid,RaceTime);
				if(racerank == 1)
				{
				    format(string,128,"%s~n~~y~TRACK RECORD!",string);
				}
			    GameTextForPlayer(playerid,string,10000,3);
		    }
			if(Ranking<4)
			{
				GivePlayerMoney(playerid,Prize/Ranking);
				format(string,128,"You have earned $%d from the race!",Prize/Ranking);
				SendClientMessage(playerid,COLOR_GREEN,string);
			}
			Ranking++;
			Participants--;
			printf("Participants: %d",Participants);
	        DisablePlayerRaceCheckpoint(playerid);
	        if(Participants == 0)
	        {
	            endrace();
	        }
	    }
	    else if (CurrentCheckpoint[playerid]==0 && RaceStart == 0 && RaceParticipant[playerid]==1) // Player arrives to the start CP for 1st time
	    {
			SendClientMessage(playerid,COLOR_YELLOW,"Type /ready when you are ready to start.");
			SendClientMessage(playerid,COLOR_YELLOW,"NOTE: Your controls will be locked.");
			RaceParticipant[playerid]=2;
	    }
	    else if (RaceStart==1) // Otherwise switch to the next race CP.
	    {
			RaceSound(playerid,1138);
			SetNextCheckpoint(playerid);
	    }
	}
	return 1;
}

public endrace()
{
    SaveScores(); //If the race had already started, and mode & laps are as originally, save the lapscores and racescores.
	for(new i=0;i<LCurrentCheckpoint;i++)
	{
	    RaceCheckpoints[i][0]=0.0;
	    RaceCheckpoints[i][1]=0.0;
	    RaceCheckpoints[i][2]=0.0;
	}
	LCurrentCheckpoint=0;
    for(new i=0;i<MAX_PLAYERS;i++)
    {
		LastLapTick[i]=0;
        DisablePlayerRaceCheckpoint(i);
		if(RaceParticipant[i]==3) //Player was still /ready-locked, unlocking.
		{
				TogglePlayerControllable(i,1);
		        if(PlayerVehicles[i] != 0)
		        {
		            PutPlayerInVehicle(i,PlayerVehicles[i],0);
		            PlayerVehicles[i]=0;
		        }
		}
        RaceParticipant[i]=0;
    }
	RaceActive=0;
	RaceStart=0;
	Participants=0;
    SendClientMessageToAll(COLOR_YELLOW, "The current race has been finished.");
}

public BActiveCP(playerid,sele)
{
	new Float:x,Float:y,Float:z, Float:nx, Float:ny, Float:nz;
	x=BRaceCheckpoints[playerid][sele][0];
	y=BRaceCheckpoints[playerid][sele][1];
	z=BRaceCheckpoints[playerid][sele][2];
	if(BCurrentCheckpoints[playerid]-1 == sele)
	{

		SetPlayerRaceCheckpoint(playerid,1,x,y,z,0.0,0.0,0.0,8.0);
	}
	else
	{
		nx=BRaceCheckpoints[playerid][sele+1][0];
		ny=BRaceCheckpoints[playerid][sele+1][1];
		nz=BRaceCheckpoints[playerid][sele+1][2];
		SetPlayerRaceCheckpoint(playerid,0,x,y,z,nx,ny,nz,8.0);
	}
}

public RaceSound(playerid,sound)
{
	new Float:x,Float:y,Float:z;
	GetPlayerPos(playerid,x,y,z);
	PlayerPlaySound(playerid,sound,x,y,z);
}

public ReadyRefresh()
{
	if(RaceActive==1) //No countdown if no race is active (could occur with /leave)
	{
		new Waiting=0;
		for(new i=0;i<MAX_PLAYERS;i++)
		{
			if(RaceParticipant[i] == 1 || RaceParticipant[i] == 2)
			{
			    Waiting++;
			}
		}
		if(Waiting==0)
		{
			SendClientMessageToAll(COLOR_GREEN,"Everyone is ready, the race begins!");
			cd=5;
			Countdown = SetTimer("countdown",1000,1);
		}
	}
}

public CheckBestLap(playerid,laptime)
{
	if(TopLapTimes[4]<laptime && TopLapTimes[4] != 0)
	{
		return 0;  // If the laptime is more than the previous 5th on the top list, skip to end
	}
	for(new i;i<5;i++)
	{
	    if(TopLapTimes[i] == 0)
	    {
			new playername[MAX_PLAYER_NAME];
	        GetPlayerName(playerid,playername,MAX_PLAYER_NAME);
	        TopLappers[i]=playername;
	        TopLapTimes[i]=laptime;
			ScoreChange=1;
			return i+1;
	    }
		else if(TopLapTimes[i] > laptime)
		{
		    for(new j=4;j>=i;j--)
		    {
		        TopLapTimes[j+1]=TopLapTimes[j];
		        TopLappers[j+1]=TopLappers[j];
		    }
			new playername[MAX_PLAYER_NAME];
	        GetPlayerName(playerid,playername,MAX_PLAYER_NAME);
		    TopLapTimes[i]=laptime;
			TopLappers[i]=playername;
			ScoreChange=1;
			return i+1;
		}
	}
	return -1;
}
public CheckBestRace(playerid,racetime)
{
	if(TopRacerTimes[4]<racetime && TopRacerTimes[4] != 0)
	{
		return 0;  // If the racetime is more than the previous 5th on the top list, exit quick
	}
	for(new i;i<5;i++)
	{
	    if(TopRacerTimes[i] == 0)
	    {
			new playername[MAX_PLAYER_NAME];
	        GetPlayerName(playerid,playername,MAX_PLAYER_NAME);
	        TopRacers[i]=playername;
	        TopRacerTimes[i]=racetime;
			ScoreChange=1;
			return i+1;
	    }
		else if(TopRacerTimes[i] > racetime)
		{
		    for(new j=4;j>=i;j--)
		    {
		        TopRacerTimes[j+1]=TopRacerTimes[j];
		        TopRacers[j+1]=TopRacers[j];
		    }
			new playername[MAX_PLAYER_NAME];
	        GetPlayerName(playerid,playername,MAX_PLAYER_NAME);
		    TopRacerTimes[i]=racetime;
			TopRacers[i]=playername;
			ScoreChange=1;
			return i+1;
		}
	}
	return -1; //Shouldn't get here.
}

public SaveScores()
{
	if(ScoreChange == 1)
	{
		fremove(CFile);
		new File:f,Float:x,Float:y,Float:z, templine[512];
		f = fopen(CFile,io_write);
		format(templine,sizeof(templine),"YRACE %d %s %d %d\n", RACEFILE_VERSION, CBuilder, ORacemode, ORacelaps);
		fwrite(f,templine);
		format(templine,sizeof(templine),"%s %d %s %d %s %d %s %d %s %d\n",
				TopRacers[0],TopRacerTimes[0],TopRacers[1], TopRacerTimes[1], TopRacers[2],TopRacerTimes[2],
	 			TopRacers[3],TopRacerTimes[3],TopRacers[4], TopRacerTimes[4]);
		fwrite(f,templine);
		format(templine,sizeof(templine),"%s %d %s %d %s %d %s %d %s %d\n",
				TopLappers[0],TopLapTimes[0],TopLappers[1], TopLapTimes[1], TopLappers[2],TopLapTimes[2],
	 			TopLappers[3],TopLapTimes[3],TopLappers[4], TopLapTimes[4]);
		fwrite(f,templine);
		for(new i = 0; i < LCurrentCheckpoint+1;i++)
		{
			x=RaceCheckpoints[i][0];
			y=RaceCheckpoints[i][1];
			z=RaceCheckpoints[i][2];
			format(templine,sizeof(templine),"%f %f %f\n",x,y,z);
			fwrite(f,templine);
		}
		fclose(f);
	}
	ScoreChange=0;
}
public ChangeLap(playerid)
{
			new string[128], LapTime, TimeString[10], checklap;
            LapTime=GetLapTick(playerid);
            TimeString=BeHuman(LapTime);
			format(string,sizeof(string),"~w~Lap %d/%d - time: %s", CurrentLap[playerid], Racelaps, TimeString);
			if(Racemode == ORacemode && ORacelaps == Racelaps)
			{
				checklap=CheckBestLap(playerid,LapTime);
				if(checklap==1)
				{
				format(string,sizeof(string),"%s~n~~y~LAP RECORD!",string);
				}
			}
		    CurrentLap[playerid]++;
			if(CurrentLap[playerid] == Racelaps)
			{
			    format(string,sizeof(string),"%s~n~~g~Final lap!",string);
			}
			GameTextForPlayer(playerid,string,6000,3);
}

BeHuman(ticks)
{
	new HumanTime[10], minutes, seconds;
	minutes=ticks/60000;
	ticks=ticks-(minutes*60000);
	seconds=ticks/1000;
	ticks=ticks-(seconds*1000);
	format(HumanTime,sizeof(HumanTime),"%d:%2d.%2d",minutes,seconds,ticks);
	return HumanTime;
}