Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <a_samp> //I'm pretty sure we all know what this line does. It adds the sa-mp natives :).
- #include <zcmd> //Could be y_cmd or something else. It's not hard to adapt the code but most people currently use ZCMD.
- #define MAX_RACES 25 //Maximum races will be 50, the lower the better due to array sizes - Change this higher if you need to
- #define MAX_CHECKPOINTS 150 //Maximum checkpoints will be 100, the lower the better due to array sizes - Change this higher if you need to
- #define WAIT_RACE 15 //The time in seconds between the opening of the race to the time that it starts
- enum rInfo
- {
- //This enum is for anything related to the races themselves.
- racetimeout,
- //The above varible is the timeout in seconds before a race stops. We
- //use this so the lovely people that decide to just sit in a race don't
- //cause it to run forever.
- Float:checkpointx[MAX_CHECKPOINTS],
- Float:checkpointy[MAX_CHECKPOINTS],
- Float:checkpointz[MAX_CHECKPOINTS],
- //These will be the float positions of the checkpoints in a race.
- //All checkpoint positions will load into these arrays on startup.
- racename[100 char],
- //We use char to lower the array size to make the script more efficient
- //and use less memory that the sa-mp server could use for doing other things
- //We can use chars on strings because their values do not exceed 255.
- //For more information on char visit:
- //For example if racename[0] = 'a' then racename[0] would actually
- //be racename[0] = 97. This will reduce our array size by 4x. If you are
- //going to have race names over 100 characters then you should change
- //the 100 to a higher value.
- cpnum,
- //We need to know how many slots are currently being used in
- //the checkpoints array. We could use a loop everytime we
- //wanted to add more checkpoints to the array but this would
- //be very time wasting and pointless. the cpnum variable
- //gives us the amount of checkpoints in a race and the next
- //free cell in the checkpoints variable
- racevehicle,
- //The racevehicle variable isn't really needed but we will add it anyway.
- //This variable allows us to specify a specific vehicle for the race
- //such as an NRG or a specific boat if you're in a boat race. Later on
- //we will make it so that if the variable is 0 then there is no specific
- //vehicle needed.
- bool:racerunning,
- //The above is just a boolean that is true if the race is currently
- //running and false if it's not. We set it to true on race start and
- //false when the race is stopped.
- bool:racejoinable,
- //This variable is different to the one above because this is used if the
- //race is open but hasn't started yet. If the race hasn't started, this would
- //be true and racerunning would be false but if the race had started it would
- //be the oppisite.
- racetimer,
- //This is the timer id for the timeout for the race. This will be dynamic
- //and will change whenever the race is given a timer and set to start.
- //We need this variable so that we can cancel the timer if there is no
- //players before the timeout of the race.
- racecount,
- //This variable is to show the amount of players that are currently
- //in the race so when it hits 0 we can end the race if it hasn't
- //already timed out.
- originalcount,
- //This variable is static from the start to the end of the race because
- //it gives us the amount of people in the race when it started. This is used
- //for positioning in the race combined with the racecount. It wouldn't be a
- //race if we didn't have the race positions at the end :).
- racetime
- //This variable is just used to determine how long the race has been running
- //for and it will allow us to use the timeout timer as a double for the
- //time people have spent in the race. The race timer will run at 100ms and
- //give us our race time accurate to .1 of a second. When the race timer reaches
- //the timeout (if it does) then it will exit. It will be easier to understand
- //the code when you see it :P.
- };
- new RaceInfo[MAX_RACES][rInfo];
- //The lovely variable that holds all race information required
- //For operating the races.
- new currentraceslot;
- //The above variable tells us how many races we have loaded and the
- //next avalible slot that we can use in the array. This is very useful
- //so we don't have to create a loop to find this information.
- new VehicleNames[212][] =
- {
- "Landstalker", "Bravura", "Buffalo", "Linerunner", "Perennial", "Sentinel",
- "Dumper", "Firetruck" , "Trashmaster" , "Stretch", "Manana", "Infernus",
- "Voodoo", "Pony", "Mule", "Cheetah", "Ambulance", "Leviathan", "Moonbeam",
- "Esperanto", "Taxi", "Washington", "Bobcat", "Mr Whoopee", "BF Injection",
- "Hunter", "Premier", "Enforcer", "Securicar", "Banshee", "Predator", "Bus",
- "Rhino", "Barracks", "Hotknife", "Trailer", "Previon", "Coach", "Cabbie",
- "Stallion", "Rumpo", "RC Bandit", "Romero", "Packer", "Monster", "Admiral",
- "Squalo", "Seasparrow", "Pizzaboy", "Tram", "Trailer", "Turismo", "Speeder",
- "Reefer", "Tropic", "Flatbed","Yankee", "Caddy", "Solair","Berkley's RC Van",
- "Skimmer", "PCJ-600", "Faggio", "Freeway", "RC Baron","RC Raider","Glendale",
- "Oceanic", "Sanchez", "Sparrow", "Patriot", "Quad", "Coastguard", "Dinghy",
- "Hermes", "Sabre", "Rustler", "ZR-350", "Walton", "Regina", "Comet", "BMX",
- "Burrito", "Camper", "Marquis", "Baggage", "Dozer","Maverick","News Chopper",
- "Rancher", "FBI Rancher", "Virgo", "Greenwood","Jetmax","Hotring","Sandking",
- "Blista Compact", "Police Maverick", "Boxville", "Benson","Mesa","RC Goblin",
- "Hotring Racer", "Hotring Racer", "Bloodring Banger", "Rancher", "Super GT",
- "Elegant", "Journey", "Bike", "Mountain Bike", "Beagle", "Cropdust", "Stunt",
- "Tanker", "RoadTrain", "Nebula", "Majestic", "Buccaneer", "Shamal", "Hydra",
- "FCR-900","NRG-500","HPV1000","Cement Truck","Tow Truck","Fortune","Cadrona",
- "FBI Truck", "Willard", "Forklift","Tractor","Combine","Feltzer","Remington",
- "Slamvan", "Blade", "Freight", "Streak","Vortex","Vincent","Bullet","Clover",
- "Sadler", "Firetruck", "Hustler", "Intruder", "Primo", "Cargobob", "Tampa",
- "Sunrise", "Merit", "Utility Truck", "Nevada", "Yosemite", "Windsor", "Monster",
- "Monster","Uranus","Jester","Sultan","Stratum","Elegy","Raindance","RCTiger",
- "Flash","Tahoma","Savanna", "Bandito", "Freight", "Trailer", "Kart", "Mower",
- "Dune", "Sweeper", "Broadway", "Tornado", "AT-400", "DFT-30", "Huntley",
- "Stafford", "BF-400", "Newsvan","Tug","Trailer","Emperor","Wayfarer","Euros",
- "Hotdog", "Club", "Trailer", "Trailer","Andromada","Dodo","RC Cam", "Launch",
- "Police Car LSPD", "Police Car SFPD","Police Car LVPD","Police Ranger",
- "Picador", "S.W.A.T. Van", "Alpha", "Phoenix", "Glendale", "Sadler",
- "Luggage Trailer","Luggage Trailer","Stair Trailer", "Boxville", "Farm Plow",
- "Utility Trailer"
- };
- //A lovely array of all vehicle names by ?. This allows us to tell a person what
- //vehicle a race requires if it requires one.
- new RaceCheckpoint[MAX_PLAYERS];
- //This variable tells us what race checkpoint that the player is currently
- //in so that we can send him to the next checkpoint in the array.
- new InRace[MAX_PLAYERS];
- //The above will be either "true" or "false" whether the player is
- //currently racing or not. This variable is useful also because you
- //can integrate it into your script in other ways.
- stock CreateRace(RaceName[], RaceTimeout, RaceVehicle = -1)
- {
- //This is the function that we will use to load our race information
- //into the variables themselves. We know that our variable currentraceslot
- //will give us the next slot that we can use freely. So lets load the
- //information that we have used in the function into our variables
- //I have put RaceVehicle = -1 so it's the default value which means that
- //we don't even need to specify it when creating a race, it's like an extra
- //thing like the draw distance of an object. You could just do the following
- //CreateRace("DEATH RACE :)", 300) to create a race with a timeout of 5 minutes
- //with any vehicle or CreateRace("DEATH RACE :)", 300, 411) for a race with
- //a specified vehicle. This will be shown more later on.
- format(RaceInfo[currentraceslot][racename], 100, "%s", RaceName);
- //We are inserting the function information of RaceName into our array
- //RaceInfo with the next avalible race slot. format just transfers one
- //string to another with ease. I was having issues with strcat for
- //some reason with char.
- RaceInfo[currentraceslot][racetimeout] = RaceTimeout;
- //The above is pretty much the same as I explained for the name.
- //We put the function information into the array. In this case
- //it's the timeout information into the timeout variable in the array
- RaceInfo[currentraceslot][racevehicle] = RaceVehicle;
- //Same as above. Loading the vehicle information into the array.
- RaceInfo[currentraceslot][racerunning] = false;
- //Sets the race running variable to false
- RaceInfo[currentraceslot][racejoinable] = false;
- //Sets the race joinable variable to false
- return currentraceslot, currentraceslot ++;
- //We return the array ID so we can use it to add checkpoints later.
- //It's the exact same thing you do with a pickup, you assign a variable
- //to the ID of the pickup so that you can identify it later. For example
- //new deathrace = CreateRace("DEATH RACE :)", 300); and we will be able to
- //add checkpoints using the variable deathrace. currentraceslot++ is just
- //adding 1 to the variable because we have used that slot.
- }
- stock AddCheckpointToRace(RaceID, Float:CheckPointX, Float:CheckPointY, Float:CheckPointZ)
- {
- //This function adds information into the designated array using the race
- //id that was returned from the CreateRace function. We just add information
- //to the arrays using this function rather than doing it manually because it's far
- //easier this way. An example how this would look would be
- //new deathrace = CreateRace("Death Race", 300);
- //AddCheckpointToRace(deathrace, 1432.13, 312.311, 12.1);
- //Pretty straight forward and easy to understand.
- new nextcheckpointfree = RaceInfo[RaceID][cpnum];
- //The above variable just makes it look cleaner because it gets
- //the next free checkpoint slot in the array.
- RaceInfo[RaceID][checkpointx][nextcheckpointfree] = CheckPointX;
- RaceInfo[RaceID][checkpointy][nextcheckpointfree] = CheckPointY;
- RaceInfo[RaceID][checkpointz][nextcheckpointfree] = CheckPointZ;
- //Just putting the checkpoint locations from the function
- //into the correct race array and into the correct checkpoint array.
- //The variables go into the race ID defined and the next free checkpoint
- //id in that specific race. It's like inception but less confusing :).
- RaceInfo[RaceID][cpnum] ++;
- //We add one so that the script knows that we have used that checkpoint
- //slot up and to use the next one avalible.
- return 1;
- //We don't need to return a specific value unless you plan on editing
- //the checkpoints location later so we just return 1 :).
- }
- public OnPlayerSpawn(playerid)
- {
- //This code just resets our player variables (InRace and RaceCheckpoint)
- InRace[playerid] = -1;
- //InRace is -1 if the player is not in any race or it will be a value > -1
- //if the player is actually in a race. This is also quite useful because
- //We could return the name of the race a player is in as well by using
- //RaceInfo[InRace[playerid]][racename] in a string :).
- RaceCheckpoint[playerid] = -1;
- //We use RaceCheckpoint = -1 to show no checkpoint at all. We cannot
- //have it at zero because in the array the first checkpoint is at 0 on
- //the start. When the player is actually in the starting checkpoint
- //and heading to the first checkpoint then this can be set to 0. The starting
- //checkpoint is #0 and the second one is #1. It will be easier to understand
- //when you see the code.
- return 1;
- }
- //Before I start the next 6 functions I'll just go into a quick overview of what
- //they are in the first place so it's easier for you to understand what I'm trying
- //to do here. OpenRace is the first function which opens a race to allow players
- //to join to it. This will tell players they have WAIT_RACE amount of time to get
- //to the start checkpoint of the race. Start race is when the racing begins and
- //the timer starts counting down to the end of the race. OpenRace calls start
- //race with a WAIT_RACE seconds on the timer. So the race will start on StartRace
- //and end on the StopRace function. However if people drop out of the race by
- //death or other means then it will also call the StopRace function. The JoinRace
- //function is called when a player requests to join a race. LeaveRace is called
- //when a player dies, quits the game, quits the race or teleports if your server
- //allows it. The RaceTime timer goes at 100ms so that it can be used to show how
- //long the race has been running and also double as the timeout timer. It allows
- //us to use 1 timer instead of one for the race time and 1 for the timeout time.
- stock OpenRace(raceid)
- {
- new RaceStr[128];
- //We create this string to format the string that will be sent to all
- //players when the race is joinable.
- if(RaceInfo[raceid][racevehicle] == -1) format(RaceStr, sizeof(RaceStr), "[RACE] The Race '%s' will start in %d seconds. Type /joinrace %d to join!", RaceInfo[raceid][racename], WAIT_RACE, raceid);
- if(RaceInfo[raceid][racevehicle] > 0) format(RaceStr, sizeof(RaceStr), "[RACE] The Race '%s' will start in %d seconds. Type /joinrace %d to join! A %s is required for this race.", RaceInfo[raceid][racename], WAIT_RACE, raceid, VehicleNames[RaceInfo[raceid][racevehicle]-400]);
- if(RaceInfo[raceid][racevehicle] == 0) format(RaceStr, sizeof(RaceStr), "[RACE] The Race '%s' will start in %d seconds. Type /joinrace %d to join! This is a onfoot race only.", RaceInfo[raceid][racename], WAIT_RACE, raceid);
- //We all probably know what format is and the above formats the message to
- //send a message that the race can be joined by typing /joinrace [raceid]
- //an example message would be something like the following:
- //[RACE]The Race 'Death Race' will start in 60 seconds. Type /joinrace 1 to join
- //Or if it requires a specific vehicle then it will add that on the end too.
- SendClientMessageToAll(0xFF00AA, RaceStr);
- //Sends the formatted message in yellow. You can easily change that colour =].
- RaceInfo[raceid][racejoinable] = true;
- //The above allows players to join the race. This will be set to false
- //when the race starts.
- SetTimerEx("StartRace", WAIT_RACE*1000, false, "d", raceid);
- //The above sets the timer for the start race function. There will be 60 seconds
- //before this function is actually called. StartRace is the function name,
- //we have WAIT_RACE*1000 because WAIT_RACE is in seconds and the timers work
- //in milliseconds (1 second = 1000 milliseconds).
- //We also pass the raceid to the function 60 seconds later.
- return 1;
- }
- stock Float:AngleToPoint(Float:x2, Float:y2, Float:X, Float:Y)
- {
- //This function by ? is used so that we can face the vehicle in the correct angle
- //when we teleport the player to a race. This isn't a real biggie but it looks more
- //awesome. Explaining this will be a bit tricky but I'll try to a basic overview.
- //If you have ever done basic trig in class you will know that with two lengths
- //we can find out an angle of a triangle
- // /|
- // H / | A (Lets pretend that's a triangle)
- // ----
- // O
- //
- //using tan ( O / A) we can find the angle that we are meant to be facing at
- //The rest of the function just calculates the angles because we are not just
- //in a triangle, we have a circle around us. If you don't understand then it
- //is really no big issue. We use this function below.
- new Float:DX, Float:DY;
- new Float:angle;
- DX = floatabs(floatsub(x2,X));
- //Get the positive value of x2 - x (finding the length we need for the
- //'O' side or the oppisite side to the angle
- DY = floatabs(floatsub(y2,Y));
- //Get the positive value of y2 - y (finding the length we need for the
- //'A' side or the adjasent side to the angle
- if (DY == 0.0 || DX == 0.0)
- //If for some reason one length is zero then we do not need trig to complete
- //the function and we can just find the angle by determining what value is
- //the non-zero value. Pretty self explanitory.
- {
- if(DY == 0 && DX > 0) angle = 0.0;
- else if(DY == 0 && DX < 0) angle = 180.0;
- else if(DY > 0 && DX == 0) angle = 90.0;
- else if(DY < 0 && DX == 0) angle = 270.0;
- else if(DY == 0 && DX == 0) angle = 0.0;
- }
- else
- {
- angle = atan(DX/DY);
- //If we have both values (no zeros) then we have to use the TOA
- //tan(oppisite / adjacent) to find the angle required. We also have
- //to add to it to find the actual angle as if we where in a circle.
- //Sadly I cant fully explain it because it's hard to create a circle
- //but think of it as a triangle in a circle and we need to find the
- //full angle rather than just the angle of a specific segment.
- if(X > x2 && Y <= y2) angle += 90.0;
- else if(X <= x2 && Y < y2) angle = floatsub(90.0, angle);
- else if(X < x2 && Y >= y2) angle -= 90.0;
- else if(X >= x2 && Y > y2) angle = floatsub(270.0, angle);
- }
- return floatadd(angle, 90.0);
- }
- stock JoinRace(playerid, raceid)
- {
- if(RaceInfo[raceid][racejoinable] == false) return SendClientMessage(playerid, 0xAA3333AA, "Race is currently not joinable!");
- //If the race isn't joinable then we send a message to the player that the
- //race cannot be joined right now and we stop them there.
- if(InRace[playerid] != -1) return SendClientMessage(playerid, 0xAA3333AA, "You are currently in a race! /leaverace before joining a new one!");
- //If the player is already in a race and trying to join another one it's
- //also a bit silly. The player has to first leave his current race before
- //going into another one. As you see, /leaverace will be our command
- //to leave the race :)
- if(GetVehicleModel(GetPlayerVehicleID(playerid)) != RaceInfo[raceid][racevehicle] && RaceInfo[raceid][racevehicle] != -1)
- {
- if(RaceInfo[raceid][racevehicle] == 0) return SendClientMessage(playerid, 0xAA3333AA, "You are not allowed vehicles in a foot race!");
- //If it's a foot race then it will send the player an error and stop here
- new RaceStr[75];
- //creates the string array
- format(RaceStr, sizeof(RaceStr), "You need to be in a %s to join this race!", VehicleNames[RaceInfo[raceid][racevehicle]-400]);
- //formats the string
- return SendClientMessage(playerid, 0xAA3333AA, RaceStr);
- //Or here you could always get rid of the return 1; and give the player
- //that specific vehicle that is required or for a running race, take
- //the players vehicle away from him/her. It's really up to you on
- //what you want to do here. What I have done is just denied enterance
- //to the race if the player is not in the required vehicle.
- }
- if(RaceInfo[raceid][racevehicle] == 0 && IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, 0xAA3333AA, "You are not allowed vehicles in this race!");
- //I just made this clause for running races or swimming races, whatever
- //floats your boat. Handy little addition and it's easy to add on. Just
- //CreateRace("Runnin' Race", 300, 0) to make a running race :).
- RaceCheckpoint[playerid] = 0;
- //Checkpoint set to 0 - First checkpoint
- InRace[playerid] = raceid;
- //Players race is set to the race he/she chose to join.
- if(IsPlayerInAnyVehicle(playerid))
- //We are going to check if the player is in any vehicle so that we can
- //then teleport that vehicle to the correct location + world. We do not
- //use world 0 as the race world as people would just ram people for the fun
- //of it.
- {
- new vehicleid = GetPlayerVehicleID(playerid);
- //We fetch the players vehicle ID
- SetVehicleVirtualWorld(vehicleid, 1050005 + raceid);
- //We set the vehicle to a virtual world with 1050005 + the raceid like
- //we are going to do with the player too. I used 1050005 so it doesn't
- //overlap any worlds used by your script (hopefully). E.g. Race 20 would
- //be in world ID 10050025 etc...
- SetPlayerVirtualWorld(playerid, 1050005 + raceid);
- //Sets the player to the same virtual world as above
- PutPlayerInVehicle(playerid, vehicleid, 0);
- //We put the player in the vehicle just in case
- SetVehiclePos(vehicleid, RaceInfo[raceid][checkpointx][0], RaceInfo[raceid][checkpointy][0], RaceInfo[raceid][checkpointz][0]);
- //We set the vehicles position in the first checkpoint waiting for the race to start
- SetVehicleZAngle(vehicleid, AngleToPoint(RaceInfo[raceid][checkpointx][0], RaceInfo[raceid][checkpointy][0], RaceInfo[raceid][checkpointx][1], RaceInfo[raceid][checkpointy][1]));
- //The code above sets the angle of the vehicle towards the second checkpoint.
- }
- else
- {
- SetPlayerVirtualWorld(playerid, 1050005 + raceid);
- SetPlayerFacingAngle(playerid, AngleToPoint(RaceInfo[raceid][checkpointx][0], RaceInfo[raceid][checkpointy][0], RaceInfo[raceid][checkpointx][1], RaceInfo[raceid][checkpointy][1]));
- SetPlayerPos(playerid, RaceInfo[raceid][checkpointx][0], RaceInfo[raceid][checkpointy][0], RaceInfo[raceid][checkpointz][0]);
- //Same as above with the cars. The angle of the player is set to the next
- //checkpoint so that they are not facing backwards when the race starts.
- //Actually, that would be pretty funny :P.
- }
- new RaceInfoString[75];
- format(RaceInfoString, sizeof(RaceInfoString), "~y~Joined the race! ~b~Please wait %d seconds for the race to start!", WAIT_RACE);
- //We have to format the amount of seconds before the race starts because it's
- //most likely going to change from 60 seconds that have been set.
- GameTextForPlayer(playerid, RaceInfoString, 3000, 3);
- //We send the player a nice on screen message telling them
- //that they have joined the race :).
- SetPlayerRaceCheckpoint(playerid, 0, RaceInfo[raceid][checkpointx][0], RaceInfo[raceid][checkpointy][0], RaceInfo[raceid][checkpointz][0], RaceInfo[raceid][checkpointx][1], RaceInfo[raceid][checkpointy][1], RaceInfo[raceid][checkpointz][1], 6);
- //This sets the starting checkpoint and it points to the direction that the
- //next checkpoint will be in. The player has to be in this checkpoint when
- //the race starts or they won't racing :P. Remember that our array ids start
- //at 0 rather than one.
- return 1;
- }
- forward StartRace(raceid);
- public StartRace(raceid)
- {
- RaceInfo[raceid][racejoinable] = false;
- //We now make it so the race is no longer joinable by anyone else.
- for(new i; i<MAX_PLAYERS; i++)
- //if you have foreach then foreach (new i : Player) or make your own
- //illiterator for players in races. Just loops through everyone currently
- //that has tried to join the race
- {
- if(InRace[i] != raceid) continue;
- //skips anyone that isn't in the race that we are looking into.
- //continue just skips a certain id. For example if ID 5 wasn't in
- //our race so InRace[playerid] = -1 it would skip his ID and not check
- //any further.
- if(IsPlayerInRaceCheckpoint(i) && (GetVehicleModel(GetPlayerVehicleID(i)) == RaceInfo[raceid][racevehicle] || RaceInfo[raceid][racevehicle] == -1 ))
- //If the player is in the race we are looking at + the player is in
- //the checkpoint + the vehicle model is correct if there is one.
- {
- SetPlayerRaceCheckpoint(i, 0, RaceInfo[raceid][checkpointx][1], RaceInfo[raceid][checkpointy][1], RaceInfo[raceid][checkpointz][1], RaceInfo[raceid][checkpointx][2], RaceInfo[raceid][checkpointy][2], RaceInfo[raceid][checkpointz][2], 6);
- //The above line sets the players checkpoint from the start point
- //to the second checkpoint in the race. It also points to the direction
- //Of the third checkpoint RaceInfo[raceid][checkpoint[x][y][z]][2].
- //Remember that the first and starting checkpoint was used in the
- //Joinrace function with the index of 0. 0 is the first number in
- //our array rather than 1.
- RaceCheckpoint[i] = 2;
- //The players race checkpoint is set to checkpoint #1. As we see
- //above the race checkpoint is being set in the array as 1.
- RaceInfo[raceid][originalcount] ++;
- //We add to the originalcount so that we get the players in the race
- //This count does not change throughout the race and will be reset
- //at the end of the race on StopRace
- RaceInfo[raceid][racecount] ++;
- //This racecount variable will change whenever someone leaves the
- //race or finishes it. It helps us determine when to stop the race
- //and what position someone finishes in a certain race. This variable
- //will be changed over the course of the race.
- GameTextForPlayer(i, "~r~GO!!!!", 3000, 3);
- //We send the player a nice on screen text that tells them that
- //the race has started and they better get going :).
- }
- else
- //The above code is if we find that the player isn't even in the checkpoint
- //when the race has started or the vehicle ID specified isn't the one that
- //the race allows.
- {
- RaceCheckpoint[i] = -1;
- //Race checkpoint reset
- InRace[i] = -1;
- //Player is put out of the race
- DisablePlayerRaceCheckpoint(i);
- //Players checkpoint is disabled.
- if(IsPlayerInAnyVehicle(i))
- //If the player was in a car
- {
- new vehicleid = GetPlayerVehicleID(i);
- //We fetch the players vehicle ID
- SetVehicleVirtualWorld(vehicleid, 0);
- //We reset the vehicles virtual world to 0
- SetPlayerVirtualWorld(i, 0);
- //Sets the player to virtual world 0 too
- PutPlayerInVehicle(i, vehicleid, 0);
- //We put the player in the vehicle just in case
- }
- else
- {
- SetPlayerVirtualWorld(i, 0);
- //If the player was on foot we just put him back to virtual
- //world 0.
- }
- }
- }
- if(RaceInfo[raceid][originalcount] == 0) return 1;
- //The above code is executed if it's time for the race to start but we seem
- //to have nobody in the race checkpoint with the specified rules. This will
- //just stop the function and the race will not be started and that will be
- //the end of it.
- RaceInfo[raceid][racetimer] = SetTimerEx("RaceTime", 100, true, "d", raceid);
- //We set the 100ms timer that acts as our timeout timer and gives us the
- //amount of time that the race has gone on for. Some people would use the
- //function GetTickCount although if you're server has a long uptime then
- //the script would just break itself. The timer is set at 100ms and the raceid
- //is carried onto the RaceTime function.
- RaceInfo[raceid][racerunning] = true;
- //We set the variable of racerunning to true to show that the race is actually
- //running so it cant be started.
- return 1;
- }
- forward RaceTime(raceid);
- public RaceTime(raceid)
- {
- RaceInfo[raceid][racetime] ++;
- //The racetime variable holds the current race time in 100ms increments
- //This allows us to give accurate race times to players at the end of the
- //race to .1 of a second.
- if(floatround((RaceInfo[raceid][racetime] / 10), floatround_floor) >= RaceInfo[raceid][racetimeout]) StopRace(raceid);
- //The above code does seem slightly confusing but it isn't. The racetimeout
- //time is in seconds and the racetime is in 0.1 of a second. We just divide
- //the race time by 10 so that we get the total race time in seconds and we
- //use the function Floatround to round downwards so we have no chance to get
- //errors when we try compare a float like this.
- return 1;
- }
- stock StopRace(raceid)
- {
- KillTimer(RaceInfo[raceid][racetimer]);
- //We kill that timer that is going at 100ms/s acting as our timeout timer
- //and the race time timer
- RaceInfo[raceid][racetime] = 0;
- //Race time is reset to 0 for the race.
- RaceInfo[raceid][racerunning] = false;
- //Race running is set to false for the race
- RaceInfo[raceid][originalcount] = 0;
- //The originalcount is set to 0 for the race.
- if(RaceInfo[raceid][racecount] != 0)
- {
- //The only case that this would happen is a race timeout. This is if we
- //try to stop a race when there is players still in it.
- for(new i; i<MAX_PLAYERS; i++)
- //if you have foreach then foreach (new i : Player) or make your own
- //illiterator for players in races.
- {
- if(InRace[i] != raceid) continue;
- //skips anyone that isn't in the race that we are looking into.
- //continue just skips a certain id. For example if ID 5 wasn't in
- //our race so InRace[playerid] = -1 it would skip his ID and not check
- //any further.
- GameTextForPlayer(i, "~r~You have run out of time for this race!", 3000, 3);
- //Send the player a message telling them they have ran out of time for
- //the race.
- LeaveRace(i, raceid);
- //Calls LeaveRace for any player that is still in the race.
- }
- RaceInfo[raceid][racecount] = 0;
- //The racecount can now be reset as all the players have been kicked
- //from the race if they didn't make it.
- }
- return 1;
- }
- stock LeaveRace(playerid, raceid)
- {
- RaceCheckpoint[playerid] = -1;
- //Race checkpoint reset
- InRace[playerid] = -1;
- //Player is put out of the race
- DisablePlayerRaceCheckpoint(playerid);
- //Players checkpoint is disabled.
- if(IsPlayerInAnyVehicle(playerid))
- //If the player was in a car
- {
- new vehicleid = GetPlayerVehicleID(playerid);
- //We fetch the players vehicle ID
- SetVehicleVirtualWorld(vehicleid, 0);
- //We reset the vehicles virtual world to 0
- SetPlayerVirtualWorld(playerid, 0);
- //Sets the player to virtual world 0 too
- PutPlayerInVehicle(playerid, vehicleid, 0);
- //We put the player in the vehicle just in case
- }
- else
- {
- SetPlayerVirtualWorld(playerid, 0);
- //If the player was on foot we just put him back to virtual
- //world 0.
- }
- if(RaceInfo[raceid][racerunning] == true)
- //If the race has actually started rather than just a player waiting for the
- //race to start leaving the race.
- {
- RaceInfo[raceid][racecount] --;
- //removes a player from the racecount.
- if(RaceInfo[raceid][racecount] == 0) StopRace(raceid);
- //If there is nobody in the race after this person leaves then we have to
- //stop the race from running.
- }
- return 1;
- }
- //Now you're thinking sweeeeeeeeeeeet done with that part but you're wrong >:).
- //We still have to advance each checkpoint and determine what happens when a
- //player wins a race or finishes one. We need the callback OnPlayerEnterRaceCheckpoint.
- public OnPlayerEnterRaceCheckpoint(playerid)
- {
- if(InRace[playerid] != -1)
- //This just makes sure the player is actually in a race. You may be using
- //race checkpoints for something else as well as this race system.
- {
- if(RaceCheckpoint[playerid] > 0)
- //RaceCheckpoint[playerid] = 0 is if the player is in a race but at
- //the starting checkpoint rather than actually racing. We check if the
- //player is at a checkpoint further than CP 1.
- {
- new raceid = InRace[playerid], checkpoint = RaceCheckpoint[playerid];
- //Above variables just makes it easier for us to use and understand
- //the code. We put the raceid that the player is in into the raceid
- //variable... YAY :). We also put the checkpoint id into the
- //checkpoint variable ;).
- if(checkpoint == RaceInfo[raceid][cpnum])
- //If we have the same checkpoint value as the race checkpoints before
- //we add one to our race checkpoint variable then we have gone through
- //the finishing checkpoint which means we should initiate the finish
- //race code and stop it there with a return 1;
- {
- //Player leaves the race.
- new str[128], playername[24];
- //creates the variables for the string we will format and the
- //variable to hold the players name.
- format(str, sizeof(str), "~w~Finished the race~n~~g~Position %d/%d - ~b~Time: %s", (RaceInfo[raceid][originalcount] - (RaceInfo[raceid][racecount] - 1)), RaceInfo[raceid][originalcount], ReturnTime(RaceInfo[raceid][racetime]));
- //Formats the string that will be sent to the player in a gametext.
- //(RaceInfo[raceid][originalcount] - (RaceInfo[raceid][racecount] - 1))
- //Starts at the original count minus the players in the race
- //minus the player himself (-1).
- GameTextForPlayer(playerid, str, 3000, 3);
- //Sends the player an on screen text of that formatted text above
- GetPlayerName(playerid, playername, sizeof(playername));
- //Gets the players name for the message that will be sent to everyone
- format(str, sizeof(str), "[RACE RESULTS] %s(%d) finished race %s(ID:%d) in %s in the position %d/%d", playername, playerid, RaceInfo[raceid][racename], raceid, ReturnTime(RaceInfo[raceid][racetime]), (RaceInfo[raceid][originalcount] - (RaceInfo[raceid][racecount]-1)), RaceInfo[raceid][originalcount]);
- //Formats a message for everyone with the players race results
- //which include his name, id, race name, raceid, time, and
- //position.
- SendClientMessageToAll(0xFF00AA, str);
- //sends everyone the formatted string.
- LeaveRace(playerid, InRace[playerid]);
- return 1;
- }
- RaceCheckpoint[playerid] ++;
- //Adds one to the players current race checkpoint.
- if(checkpoint != RaceInfo[raceid][cpnum]) SetPlayerRaceCheckpoint(playerid, 0, RaceInfo[raceid][checkpointx][checkpoint], RaceInfo[raceid][checkpointy][checkpoint], RaceInfo[raceid][checkpointz][checkpoint], RaceInfo[raceid][checkpointx][checkpoint+1], RaceInfo[raceid][checkpointy][checkpoint+1], RaceInfo[raceid][checkpointz][checkpoint+1], 6);
- //Sets the players race checkpoint and the arrow to the next
- //race checkpoint. RaceInfo[raceid][checkpointx][checkpoint+1] is the
- //next x position of the next checkpoint which is what the current
- //checkpoint will point at. if(checkpoint != RaceInfo[raceid][cpnum]
- //means that we are not at the last checkpoint yet. The cpnum variable
- //was used to show us the last array used for our checkpoints back
- //when we were adding checkpoints and it will tell us the last checkpoint.
- if(checkpoint+1 == RaceInfo[raceid][cpnum]) SetPlayerRaceCheckpoint(playerid, 1, RaceInfo[raceid][checkpointx][checkpoint], RaceInfo[raceid][checkpointy][checkpoint], RaceInfo[raceid][checkpointz][checkpoint], 0.0, 0.0, 0.0, 6);
- //The above is different from the last time we used
- //if(checkpoint == RaceInfo[raceid][cpnum]) because this time it's
- //after we added 1 to the race checkpoint variable. This now means
- //that we are setting the last checkpoint and the call above will
- //be called when we enter that checkpoint that we are just setting now.
- new RaceInfoString[80];
- format(RaceInfoString, sizeof(RaceInfoString), "~b~%d/%d ~n~~g~%s", RaceCheckpoint[playerid]-2, RaceInfo[raceid][cpnum] - 1, ReturnTime(RaceInfo[raceid][racetime]));
- //This returns a formatted string with the checkpoint number and the
- //current time that they have taken on this course. I have created
- //the function ReturnTime because I used the exact same code when
- //the player had finished the race as well. We have the cpnum minus
- //one because we don't count the starting checkpoint as an actual
- //checkpoint that the player goes through. RaceCheckpint[playerid]-2
- //is there because of the reason above (we don't count the first
- //checkpoint and it shows one before what we actually have so
- //that the second to last checkpoint shows 12/13 rather than 13/13
- GameTextForPlayer(playerid, RaceInfoString, 3000, 3);
- //Sends the gametext that tells the player their checkpoint number
- //and the current time it has taken them. You could always add a
- //loop here comparing with the checkpoint number to find the players
- //position in the race. You could also make a Textdraw that tells
- //the player their time and checkpoint rather than having it show
- //as a gametext.
- }
- }
- return 1;
- }
- stock ReturnTime(timevariable)
- //Used in the OnPlayerEnterRaceCheckpoint code.
- {
- new milliseconds = timevariable, seconds, minutes, string[20];
- while(milliseconds > 9)
- //While we still have 10 or more 100x milliseconds left
- {
- seconds ++;
- //Add to the seconds variable
- milliseconds = milliseconds - 10;
- //Take away 10 from the ms variable
- }
- while(seconds > 59)
- //while we have 60 or more seconds on the timer
- {
- minutes ++;
- //We add to the minutes variable
- seconds = seconds - 60;
- //And take the 60 seconds from the seconds variable.
- }
- format(string, sizeof(string), "%d:%02d.%03d
- ", minutes, seconds, milliseconds);
- //format the return string the 0 before the first %d makes it so the
- //seconds are correct and the zeros after the last %d make it so the
- //milliseconds show correctly.
- return string;
- //return the end result.
- }
- //Now time for the commands. Most of it has already been done in the functions
- //so that we can easily just check if the raceid is valid and then Join the
- //race. LeaveRace is just straight forward, if you're not in a race, you cant leave
- //one. If you're in a race, you will leave it.
- CMD:joinrace(playerid, params[])
- //The joinrace command using ZCMD
- {
- if(!strlen(params)) return SendClientMessage(playerid, 0xFF0000, "Please enter a race id to join or type /races");
- new raceid = strval(params);
- if(raceid > currentraceslot-1) return SendClientMessage(playerid, 0xFF0000, "The race ID you have entered is invalid");
- //Just basic tests to see if there is a race in the array / the number is
- //not too big for the array.
- if(RaceInfo[raceid][racejoinable] == false && RaceInfo[raceid][racerunning] == false && InRace[playerid] == -1) OpenRace(raceid);
- //If the race is not running or is joinable it is opened and the player
- //isn't in a race then it will start the race. If you don't want players
- //to be able to start races like this then remove the line and add an admin
- //command or a timer that choses a random race every x amount of seconds.
- JoinRace(playerid, raceid);
- //The above line will just join the player to the race.
- return 1;
- }
- CMD:leaverace(playerid, params[])
- //The leaverace command using zcmd
- {
- if(InRace[playerid] == -1) return SendClientMessage(playerid, 0xFF0000, "You are not in a race");
- //Checks if a player is in a race or not and errors him if he isn't and
- //the code stops there with a return.
- LeaveRace(playerid, InRace[playerid]);
- //player leaves the race.
- GameTextForPlayer(playerid, "~b~You have left the race", 3000, 3);
- //On screen text telling them they have left the race
- return 1;
- }
- public OnPlayerDeath(playerid, killerid, reason)
- {
- if(InRace[playerid] != -1) LeaveRace(playerid, InRace[playerid]);
- //Checks if the player is in a race and removes him / her from it on death
- return 1;
- }
- public OnPlayerDisconnect(playerid, reason)
- {
- if(InRace[playerid] != -1) LeaveRace(playerid, InRace[playerid]);
- //Checks if the player is in a race and removes him from it on disconnect if
- //(s)he is in a race.
- return 1;
- }
- //The following is just cool to have. It's just a command /races that will
- //just popup a dialog that gives you a list of all the races and whether you can
- //join the races or not. You don't need it but how else are people going to know
- //what ID the races are :P?
- CMD:races(playerid, params[])
- {
- new RaceInfoString[600];
- //Creates the large string for formatting all of this information. If you
- //are going to have like 30+ races then you may need to make the string
- //slightly larger.
- for(new x; x<currentraceslot; x++)
- //We are looping through all races up to the last slot used (currentraceslot)
- {
- if(RaceInfo[x][racejoinable] == true) format(RaceInfoString, sizeof(RaceInfoString), "%s%s(ID:%d) {00FF00}[RACE JOINABLE]{FFFFFF}\n", RaceInfoString, RaceInfo[x][racename], x);
- //If the race is currently joinable (still not started) then it will add
- //a line to that string that shows the race information with the tag
- //[RACE JOINABLE] on the end.
- else if(RaceInfo[x][racerunning] == true) format(RaceInfoString, sizeof(RaceInfoString), "%s%s(ID:%d) {FF0000}[RACE RUNNING]{FFFFFF}\n", RaceInfoString, RaceInfo[x][racename], x);
- //If the race is not currently joinable it will show the race name + id
- //with [RACE RUNNING] tag on it.
- else format(RaceInfoString, sizeof(RaceInfoString), "%s%s(ID:%d) \n", RaceInfoString, RaceInfo[x][racename], x);
- //If the race is not running or being started at all then it will just
- //be added with the race name and id.
- }
- ShowPlayerDialog(playerid, 13337, DIALOG_STYLE_LIST, "Races", RaceInfoString, "Join", "Cancel");
- //Sends the player a dialog which allows them to join races straight off
- //that list if they are avalible. The list also shows all races that have
- //currently been started and are currently running.
- return 1;
- }
- public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
- {
- if(dialogid == 13337 && response != 0)
- //If our dialog is chosen and the player has pressed the join button
- //we initiate further code.
- {
- if(currentraceslot < listitem) return SendClientMessage(playerid, 0xFF0000, "Race ID is not valid");
- //Just to prevent the server crashing due to array out of bounds
- //if someone manages to manipulate the dialog we just make it so that
- //the listitem has a higher value than the array.
- if(!strlen(RaceInfo[listitem][racename])) return SendClientMessage(playerid, 0xFF0000, "Race ID is not valid");
- //Same as above but it just prevents players from attempting to join
- //races that are not being used by checking if they have a name or not.
- //Remember the return stops the code there.
- if(RaceInfo[listitem][racejoinable] == false && RaceInfo[listitem][racerunning] == false && InRace[playerid] == -1) OpenRace(listitem);
- //Same as in the /joinrace command. Starts the race if possible. If you
- //don't want players to have this kind of permission then just take it
- //off.
- JoinRace(playerid, listitem);
- //We join the race to the listitem specified. The listitem will be the
- //number on the list chosen which will also match up with our RaceInfo
- //array.
- }
- return 0;
- }
- //Here are just a few test races that I made up :). You don't need to use
- //them it's just for a bit of fun.
- public OnFilterScriptInit()
- {
- new myfirstrace = CreateRace("Drag race", 300);
- AddCheckpointToRace(myfirstrace, 2378.034423, -1256.948120, 23.392478);
- AddCheckpointToRace(myfirstrace, 2424.435058, -1256.951904, 23.392736);
- AddCheckpointToRace(myfirstrace, 2483.459228, -1256.290039, 29.515676);
- AddCheckpointToRace(myfirstrace, 2544.722656, -1255.574829, 40.808807);
- AddCheckpointToRace(myfirstrace, 2623.192871, -1256.035888, 48.688129);
- AddCheckpointToRace(myfirstrace, 2640.677734, -1299.083984, 43.465404);
- AddCheckpointToRace(myfirstrace, 2641.805908, -1384.888916, 29.915727);
- AddCheckpointToRace(myfirstrace, 2642.633056, -1510.337402, 28.740942);
- AddCheckpointToRace(myfirstrace, 2642.414306, -1609.575195, 10.076794);
- AddCheckpointToRace(myfirstrace, 2642.405029, -1748.507324, 10.287642);
- AddCheckpointToRace(myfirstrace, 2642.405029, -1812.125122, 10.375592);
- new race1 = CreateRace("DRAG LOL", 180);
- AddCheckpointToRace(race1, 2829.936523, -1794.952880, 10.647988);
- AddCheckpointToRace(race1, 2844.200927, -1714.927368, 10.654101);
- AddCheckpointToRace(race1, 2882.619628, -1575.671142, 10.650041);
- AddCheckpointToRace(race1, 2903.586425, -1443.250488, 10.646242);
- AddCheckpointToRace(race1, 2889.312988, -1309.945068, 10.654065);
- AddCheckpointToRace(race1, 2871.154785, -1043.372802, 10.646505);
- AddCheckpointToRace(race1, 2874.849609, -857.698730, 10.646862);
- AddCheckpointToRace(race1, 2884.896484, -675.723999, 10.607203);
- AddCheckpointToRace(race1, 2898.247802, -742.455566, 10.612231);
- AddCheckpointToRace(race1, 2892.632080, -896.031188, 10.646240);
- AddCheckpointToRace(race1, 2889.872314, -1064.333740, 10.646269);
- AddCheckpointToRace(race1, 2897.653076, -1222.954711, 10.646265);
- AddCheckpointToRace(race1, 2916.691650, -1346.928466, 10.646243);
- AddCheckpointToRace(race1, 2916.200683, -1513.697265, 10.649989);
- AddCheckpointToRace(race1, 2874.615478, -1659.650390, 10.646264);
- new race2 = CreateRace("lolrace", 50, 0);
- AddCheckpointToRace(race2, 2915.456787, -1622.428466, 12.435916);
- AddCheckpointToRace(race2, 2910.672363, -1637.185913, 12.395952);
- AddCheckpointToRace(race2, 2903.093994, -1660.151611, 12.430374);
- AddCheckpointToRace(race2, 2898.300048, -1675.741333, 12.457112);
- AddCheckpointToRace(race2, 2890.918457, -1702.602905, 12.493884);
- new race3 = CreateRace("circles", 300, 422);
- AddCheckpointToRace(race3, 2743.795654, -1824.129760, 37.350173);
- AddCheckpointToRace(race3, 2785.624511, -1798.400634, 38.007194);
- AddCheckpointToRace(race3, 2789.515625, -1730.653320, 38.372951);
- AddCheckpointToRace(race3, 2738.261718, -1703.567260, 39.003555);
- AddCheckpointToRace(race3, 2684.301513, -1735.715698, 38.545482);
- AddCheckpointToRace(race3, 2696.835693, -1801.783691, 38.632278);
- AddCheckpointToRace(race3, 2760.039550, -1815.870971, 38.270313);
- AddCheckpointToRace(race3, 2798.526611, -1765.682006, 38.073280);
- AddCheckpointToRace(race3, 2788.305908, -1731.470947, 38.702461);
- AddCheckpointToRace(race3, 2751.104736, -1710.066772, 40.082180);
- AddCheckpointToRace(race3, 2685.113037, -1726.660766, 37.719898);
- AddCheckpointToRace(race3, 2681.699951, -1785.690185, 37.916439);
- AddCheckpointToRace(race3, 2732.258544, -1823.472167, 37.502525);
- AddCheckpointToRace(race3, 2787.974121, -1795.875976, 37.903495);
- AddCheckpointToRace(race3, 2789.651855, -1734.030151, 38.703849);
- AddCheckpointToRace(race3, 2699.944824, -1717.708496, 38.976169);
- AddCheckpointToRace(race3, 2682.354736, -1756.922851, 39.295875);
- new race4 = CreateRace("DatLongRace", 300);
- AddCheckpointToRace(race4, 2633.364990, -1734.128051, 10.525354);
- AddCheckpointToRace(race4, 2545.920654, -1733.396240, 13.154250);
- AddCheckpointToRace(race4, 2442.343750, -1733.484252, 13.355755);
- AddCheckpointToRace(race4, 2431.615478, -1675.185058, 23.190317);
- AddCheckpointToRace(race4, 2432.491699, -1583.581542, 24.303165);
- AddCheckpointToRace(race4, 2426.228027, -1528.688842, 23.610731);
- AddCheckpointToRace(race4, 2358.857177, -1524.946044, 23.599382);
- AddCheckpointToRace(race4, 2343.114013, -1438.596801, 23.599653);
- AddCheckpointToRace(race4, 2332.898925, -1387.123657, 23.665111);
- AddCheckpointToRace(race4, 2267.898437, -1374.233398, 23.599349);
- AddCheckpointToRace(race4, 2266.498535, -1303.596435, 23.602481);
- AddCheckpointToRace(race4, 2143.897705, -1302.048583, 23.591621);
- AddCheckpointToRace(race4, 2076.627197, -1295.328979, 23.590627);
- AddCheckpointToRace(race4, 2054.959472, -1258.147949, 23.591150);
- AddCheckpointToRace(race4, 1923.316406, -1260.406738, 16.012174);
- AddCheckpointToRace(race4, 1817.992553, -1264.200195, 13.243765);
- AddCheckpointToRace(race4, 1714.354370, -1297.821655, 13.160857);
- AddCheckpointToRace(race4, 1607.921142, -1299.956787, 17.046354);
- AddCheckpointToRace(race4, 1467.686523, -1303.289916, 13.193289);
- AddCheckpointToRace(race4, 1453.888427, -1381.708862, 13.154219);
- AddCheckpointToRace(race4, 1449.449584, -1436.579956, 13.154660);
- AddCheckpointToRace(race4, 1405.544921, -1420.086425, 13.945821);
- AddCheckpointToRace(race4, 1315.515258, -1405.038818, 13.063317);
- AddCheckpointToRace(race4, 1205.709960, -1404.587158, 13.066181);
- AddCheckpointToRace(race4, 1041.687133, -1403.934204, 13.045770);
- AddCheckpointToRace(race4, 946.428405, -1401.756591, 13.036564);
- AddCheckpointToRace(race4, 918.143981, -1382.413818, 13.005650);
- AddCheckpointToRace(race4, 916.576599, -1334.884765, 13.273034);
- AddCheckpointToRace(race4, 822.389953, -1334.648559, 13.323395);
- AddCheckpointToRace(race4, 837.015991, -1343.594848, 7.064631);
- AddCheckpointToRace(race4, 830.920715, -1355.182861, 1.802645);
- AddCheckpointToRace(race4, 824.963378, -1381.297363, -1.784867);
- AddCheckpointToRace(race4, 897.291625, -1450.401733, -1.967725);
- AddCheckpointToRace(race4, 968.884155, -1525.094238, -2.687804);
- AddCheckpointToRace(race4, 1118.831665, -1692.697875, -4.506172);
- AddCheckpointToRace(race4, 1205.780883, -1793.990234, -4.416773);
- AddCheckpointToRace(race4, 1327.433471, -1920.372924, 1.110849);
- AddCheckpointToRace(race4, 1425.327758, -1953.886962, 12.610272);
- AddCheckpointToRace(race4, 1560.160888, -1956.531127, 13.320227);
- AddCheckpointToRace(race4, 1714.534423, -1957.219116, 13.322772);
- AddCheckpointToRace(race4, 1827.264770, -1956.456542, 13.326131);
- AddCheckpointToRace(race4, 1935.426879, -1966.828613, 14.527605);
- AddCheckpointToRace(race4, 1984.612304, -1963.229858, 17.639959);
- AddCheckpointToRace(race4, 2116.238037, -1956.358520, 13.328435);
- AddCheckpointToRace(race4, 2198.640625, -1911.479736, 13.332157);
- AddCheckpointToRace(race4, 2218.488037, -1849.738159, 13.029332);
- AddCheckpointToRace(race4, 2223.098632, -1751.567504, 13.153687);
- AddCheckpointToRace(race4, 2324.993896, -1749.899047, 13.151140);
- AddCheckpointToRace(race4, 2405.868164, -1753.348999, 13.153372);
- AddCheckpointToRace(race4, 2412.497558, -1804.233764, 13.154181);
- AddCheckpointToRace(race4, 2412.224609, -1882.934814, 13.154174);
- AddCheckpointToRace(race4, 2412.380615, -1999.624389, 13.132261);
- AddCheckpointToRace(race4, 2412.784912, -2109.244384, 13.141799);
- AddCheckpointToRace(race4, 2413.450195, -2160.048828, 13.220868);
- AddCheckpointToRace(race4, 2324.239990, -2235.036132, 13.146298);
- AddCheckpointToRace(race4, 2287.443115, -2302.291992, 13.150836);
- AddCheckpointToRace(race4, 2359.932861, -2374.427246, 13.151649);
- AddCheckpointToRace(race4, 2429.166992, -2442.671386, 13.238473);
- AddCheckpointToRace(race4, 2520.102294, -2380.220703, 13.224400);
- AddCheckpointToRace(race4, 2628.054931, -2402.248291, 13.233164);
- AddCheckpointToRace(race4, 2736.581298, -2409.763183, 13.258348);
- AddCheckpointToRace(race4, 2797.283447, -2416.207763, 13.402585);
- new lsrace = CreateRace("LsRace", 300);
- AddCheckpointToRace(lsrace, 1706.426391, -611.859863, 38.901790);
- AddCheckpointToRace(lsrace, 1692.569946, -723.126037, 48.900508);
- AddCheckpointToRace(lsrace, 1652.880004, -817.668334, 57.524845);
- AddCheckpointToRace(lsrace, 1605.353881, -881.411804, 53.732391);
- AddCheckpointToRace(lsrace, 1539.825439, -922.278015, 43.056083);
- AddCheckpointToRace(lsrace, 1461.724975, -940.698120, 35.791889);
- AddCheckpointToRace(lsrace, 1403.331054, -941.417907, 34.747589);
- AddCheckpointToRace(lsrace, 1392.661621, -882.348999, 39.213245);
- AddCheckpointToRace(lsrace, 1465.932739, -865.940429, 55.070766);
- AddCheckpointToRace(lsrace, 1512.892944, -797.726623, 73.608940);
- AddCheckpointToRace(lsrace, 1476.592773, -764.863769, 91.092216);
- AddCheckpointToRace(lsrace, 1457.034545, -720.671813, 91.886367);
- AddCheckpointToRace(lsrace, 1338.306518, -698.574401, 91.680290);
- AddCheckpointToRace(lsrace, 1155.694335, -762.598022, 107.170852);
- AddCheckpointToRace(lsrace, 1037.425781, -782.354858, 103.803581);
- AddCheckpointToRace(lsrace, 944.082031, -823.647094, 95.165565);
- AddCheckpointToRace(lsrace, 838.899108, -870.125427, 68.854980);
- AddCheckpointToRace(lsrace, 782.362426, -907.054016, 56.233585);
- AddCheckpointToRace(lsrace, 676.304748, -1057.787963, 49.234329);
- AddCheckpointToRace(lsrace, 546.687988, -1158.329833, 54.421894);
- AddCheckpointToRace(lsrace, 442.335571, -1189.781250, 67.419334);
- AddCheckpointToRace(lsrace, 399.630310, -1174.796752, 78.225868);
- AddCheckpointToRace(lsrace, 287.595764, -1227.318481, 74.894096);
- AddCheckpointToRace(lsrace, 230.168182, -1276.778564, 64.179939);
- AddCheckpointToRace(lsrace, 243.446228, -1327.960083, 52.253746);
- AddCheckpointToRace(lsrace, 212.957321, -1365.910888, 49.981910);
- AddCheckpointToRace(lsrace, 156.897445, -1428.196655, 39.155746);
- AddCheckpointToRace(lsrace, 112.251525, -1485.543457, 14.808308);
- AddCheckpointToRace(lsrace, 167.971176, -1530.873657, 11.934063);
- AddCheckpointToRace(lsrace, 230.456497, -1443.309692, 12.917514);
- AddCheckpointToRace(lsrace, 338.681091, -1381.437988, 13.922136);
- AddCheckpointToRace(lsrace, 471.116241, -1298.085449, 15.019657);
- AddCheckpointToRace(lsrace, 539.320739, -1241.989990, 16.362131);
- AddCheckpointToRace(lsrace, 634.960266, -1259.193481, 16.687885);
- AddCheckpointToRace(lsrace, 635.698059, -1334.740722, 13.114221);
- AddCheckpointToRace(lsrace, 633.734802, -1491.675170, 14.342875);
- AddCheckpointToRace(lsrace, 635.601684, -1616.577270, 15.354584);
- AddCheckpointToRace(lsrace, 632.403259, -1718.967895, 13.681066);
- AddCheckpointToRace(lsrace, 759.028747, -1766.696166, 12.587768);
- AddCheckpointToRace(lsrace, 881.049072, -1770.948730, 13.109845);
- AddCheckpointToRace(lsrace, 1008.124572, -1795.744262, 13.775837);
- AddCheckpointToRace(lsrace, 1156.595825, -1852.637329, 13.121710);
- AddCheckpointToRace(lsrace, 1312.552978, -1831.018432, 13.109981);
- AddCheckpointToRace(lsrace, 1311.227416, -1670.582519, 13.109985);
- AddCheckpointToRace(lsrace, 1337.795532, -1493.360961, 13.108355);
- AddCheckpointToRace(lsrace, 1356.297363, -1256.863037, 13.106974);
- AddCheckpointToRace(lsrace, 1363.745239, -1076.934936, 24.951122);
- AddCheckpointToRace(lsrace, 1473.232055, -1031.099243, 23.383405);
- AddCheckpointToRace(lsrace, 1658.844116, -1026.858276, 23.625595);
- AddCheckpointToRace(lsrace, 1894.228637, -1044.847290, 23.408243);
- AddCheckpointToRace(lsrace, 2039.885620, -1074.727416, 24.357799);
- AddCheckpointToRace(lsrace, 2176.282226, -1143.813720, 24.630598);
- AddCheckpointToRace(lsrace, 2168.373535, -1290.851318, 23.547401);
- AddCheckpointToRace(lsrace, 2271.814941, -1299.705200, 23.553785);
- AddCheckpointToRace(lsrace, 2331.828125, -1299.506225, 23.808448);
- AddCheckpointToRace(lsrace, 2371.086181, -1352.059692, 23.562322);
- AddCheckpointToRace(lsrace, 2343.587890, -1409.425415, 23.545507);
- AddCheckpointToRace(lsrace, 2342.461669, -1513.188110, 23.564939);
- AddCheckpointToRace(lsrace, 2300.728759, -1565.118164, 14.730288);
- AddCheckpointToRace(lsrace, 2164.391357, -1532.709472, 2.032401);
- AddCheckpointToRace(lsrace, 2042.412719, -1503.038574, 3.047770);
- AddCheckpointToRace(lsrace, 1948.191284, -1518.647460, 3.063310);
- AddCheckpointToRace(lsrace, 1851.070434, -1551.060546, 12.822020);
- AddCheckpointToRace(lsrace, 1818.930175, -1665.781372, 13.110196);
- AddCheckpointToRace(lsrace, 1907.059204, -1754.055419, 13.109704);
- AddCheckpointToRace(lsrace, 2023.382446, -1753.830566, 13.109979);
- AddCheckpointToRace(lsrace, 2189.188476, -1699.546752, 13.243209);
- AddCheckpointToRace(lsrace, 2245.878662, -1653.323486, 15.011875);
- AddCheckpointToRace(lsrace, 2381.359863, -1660.972656, 13.109755);
- return 1;
- }
Add Comment
Please, Sign In to add comment