#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 #include #include #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 for 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 is better than any of the ones in highscore list, and update. forward CheckBestRace(playerid,racetime); // Check if 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];i0) //Clear the old race if there is such. { for(new i=0;i 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 ' ') && ((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;i1) { 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;i1) { 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 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) { 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; }