Advertisement
Schneider1988

Keep Your Lane - V2 - Lite Version

Dec 23rd, 2014
467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 16.40 KB | None | 0 0
  1. #include <a_samp>
  2. #include <sscanf2>
  3. #include <streamer>
  4.  
  5. //#define ALLOW_DRIVING_ON_TRAIN_TRACK    //While this define is diabled (commented) players are NOT allowed to drive on traintracks. Remove the // to allow players to drive on the tracks.
  6.  
  7.  
  8.  
  9. #define MAX_ROADPOINTS_PER_ZONE 500  // This value will define the size of the array in which the RoadPoints in each zone will be stored.
  10.                                      // If this value is too small (there are more RoadPoints in a zone than this value) this system will be terminated.
  11.                                      // On the other hand, if this value is too large your server will be less efficient. Keep an eye on the serverlog...
  12.                                      // ...it will show you the ideal value based on the number of RoadPoints found.
  13.  
  14.  
  15. #define ANGLE_TOLERANCE 25   // Example: if this value is set at 25 degrees and a given RoadPoint has an original angle of 150 degrees, the script will...
  16.                              //          ...trigger OnPlayerWrongLane when a player passes this point with an angle between 125 and 175 degrees.
  17.  
  18.  
  19. #define ROADPOINT_CHECK_INTERVAL 100   // This the interval in milliseconds of which the script will check each player if it's driving on the wrong side of the road.
  20.                              // The lower this value the more precice this system will work, but with many players or having a large script it might slow it down.
  21.  
  22.  
  23. #define BUILD "2.1.1"
  24.  
  25. #if defined ALLOW_DRIVING_ON_TRAIN_TRACK
  26.     new bool:AllowTrainTrackDriving = true;
  27. #else
  28.     new bool:AllowTrainTrackDriving = false;
  29. #endif
  30.  
  31. //New Variables:
  32. new TRP;  //Will store the total amout of RoadPoints created.  (wont get lowered when RoadPoints gets removed until restart. Used to give new Roadpoints an unique ID).
  33.  
  34. //Roadpoint Enum
  35. enum rpinfo
  36. {
  37.     ID,      //Holds the unique ID of each RoadPoint
  38.     Float:X,  // Holds the X coordinate of each RoadPoint
  39.     Float:Y,  // Holds the Y coordinate of each RoadPoint
  40.     Float:Z,  // Holds the Z coordinate of each RoadPoint
  41.     Float:A,  // Holds the angle of each roadpoint (Note: this value should be the angle the players are supposed to drive!)
  42.     Float:D,  // Holds the maximum distance a player has to be from this RoadPoint before it's triggered.
  43. }
  44.  
  45. enum tpinfo
  46. {
  47.     Float:tpX,  // Holds the X coordinate of each RoadPoint
  48.     Float:tpY,  // Holds the Y coordinate of each RoadPoint
  49.     Float:tpZ,  // Holds the Z coordinate of each RoadPoint
  50.     Float:tpD,  // Holds the maximum distance a player has to be from this RoadPoint before it's triggered.
  51. }
  52.  
  53. //This is the main array that stores all info about each RoadPoint.
  54. //The first dimention (37) is the number of zones (36 zones as described above + 1 extra zone in case players have custom roads build on the oceans around the map.
  55. //Each zone has (MAX_ROADPOINTS_PER_ZONE) slots available.
  56. new RP[145][MAX_ROADPOINTS_PER_ZONE][rpinfo];
  57. new RPInZone[145];
  58. new TP[145][90][tpinfo];
  59. new TPInZone[145];
  60.  
  61. new CZ[MAX_PLAYERS];
  62.  
  63. //Publics
  64. public OnFilterScriptInit()
  65. {
  66.     ResetRoadPointInfo(); //Will destroy and reset all values and pickups.
  67.     new Float:minX, Float:maxX, Float:minY, Float:maxY;
  68.     maxY = 3000.0;
  69.     minY = 2500.0;
  70.     for(new i; i<12; i++)
  71.     {
  72.         minX = -3000.0;
  73.         maxX = -2500;
  74.         for(new j; j<12; j++)
  75.         {
  76.             CreateDynamicRectangle(minX, minY, maxX, maxY);
  77.             minX = floatadd(minX, 500.0);
  78.             maxX = floatadd(maxX, 500.0);
  79.         }
  80.         maxY = floatsub(maxY, 500.0);
  81.         minY = floatsub(minY, 500.0);
  82.     }
  83.     print("\n--------------------------------------------");
  84.     printf(" [FS]Keep Your Lane - Lite - Build %s", BUILD);
  85.     print("            by Schneider 2014");
  86.     print("---------------------------------------------\n");
  87.    
  88.     //This timer will trigger a function that will calculate the optimal value of MAX_ROADPOINTS_PER_ZONE...
  89.     SetTimer("CheckEfficiency", 3000, 0);
  90.     //SetTimer("SpeedTest", 4000, 0);
  91.     SetTimer("CheckRoadPoints", ROADPOINT_CHECK_INTERVAL, 1);   //Start the main timer that checks each players position on the road.
  92.  
  93.     ReadRoadPoints(); // This function will read and load all RoadPoints from the KYLRoadPoints.txt file.
  94.  
  95.     if(AllowTrainTrackDriving == false)
  96.     {
  97.         ReadTrainPoints();
  98.     }
  99.     return 1;
  100. }
  101.  
  102. public OnPlayerEnterDynamicArea(playerid, areaid)
  103. {
  104.     CZ[playerid] = (areaid-1);
  105.     return 1;
  106. }
  107.  
  108. public OnPlayerLeaveDynamicArea(playerid, areaid)
  109. {
  110.     if(CZ[playerid] == (areaid-1))
  111.     {
  112.         CZ[playerid] = 144;
  113.     }
  114.     return 1;
  115. }
  116.  
  117. stock GetZone(Float:vX, Float:vY)  // This function returns the zone-number based on given X- and Y-coord.
  118. {
  119.     for(new i=1; i<145; i++)
  120.     {
  121.         if(IsPointInDynamicArea(i, vX, vY, 0.0)) return (i-1); //Return the zone (0-143)
  122.     }
  123.     return 144; // Return oceanzone (144)
  124. }
  125.  
  126. stock ResetRoadPointInfo()  // This Function will reset all RoadPoint-related variables and destroys the pickups.
  127. {
  128.     for(new zone; zone<145; zone++) // Loop through all 37 zones.
  129.     {
  130.         for(new slot; slot<MAX_ROADPOINTS_PER_ZONE; slot++)  // Loop through each slot in current zone
  131.         {
  132.             RP[zone][slot][X] = 0.0;  //Reset X Coordinate
  133.             RP[zone][slot][Y] = 0.0;  //Reset Y Coordinate
  134.             RP[zone][slot][Z] = 0.0;  //Reset Z Coordinate
  135.             RP[zone][slot][A] = 0.0;  //Reset Angle
  136.             RP[zone][slot][D] = 0;  //Reset Max Distance
  137.             RP[zone][slot][ID] = -1;  //Reset ID
  138.         }
  139.     }
  140.     return 1;
  141. }
  142.  
  143. stock ReadRoadPoints() //  This function will read and load all RoadPoints from the KYLRoadPoints.txt file
  144. {
  145.     new File:file;
  146.     if (!fexist("KYLRoadPoints.txt"))
  147.     {
  148.         file = fopen("KYLRoadPoints.txt",io_write);
  149.         fclose(file);
  150.     }
  151.     file=fopen("KYLRoadPoints.txt", io_read);
  152.     new str[64], zone, slot;  // Create new variables to store the string, zone and slot
  153.     new Float:rX, Float:rY, Float:rZ, Float:rA, Float:rType; // Create new temprorarily variables to store the coordinates, angle and distance
  154.     while(fread(file, str))  // Loop through each line in the file
  155.     {
  156.         sscanf(str, "fffff", rX, rY, rZ, rA, rType);  // Retrieve all values from the line and store them in the temporarily variables
  157.         {
  158.             zone = GetZone(rX, rY);  // Get the zone ID based on the X and Y coordinate
  159.             slot = GetFreeSlot(zone);  // Get the ID of the first free slot in this zone
  160.             if(slot != -1)   // If there is an empty slot found
  161.             {
  162.                 RP[zone][slot][X] = rX;  // Store the temporarily X value in the global array
  163.                 RP[zone][slot][Y] = rY;  // Store the temporarily Y value in the global array
  164.                 RP[zone][slot][Z] = rZ;  // Store the temporarily Z value in the global array
  165.                 RP[zone][slot][A] = rA;  // Store the temporarily angle in the global array
  166.                 RP[zone][slot][D] = rType;  // Store the temporarily distance in the global array
  167.                 RP[zone][slot][ID] = TRP; // Give the new RoadPoint an unique ID (based on total amount of created RoadPoints)
  168.                 TRP++;  // Increae number of total created RoadPoints by 1
  169.                 RPInZone[zone]++;
  170.             }
  171.             else  // if no empty slot is found in the current zone:
  172.             {
  173.                 //Send error message to the ServerLog
  174.                 print("------------------------------------------------------------------");
  175.                 printf("FATAL ERROR: Too many RoadPoints in Zone #%02d (Limit: %d)", zone, MAX_ROADPOINTS_PER_ZONE);
  176.                 print("Loading of the RoadPoints has failed");
  177.                 print("Increase the value of MAX_ROADPOINTS_PER_ZONE");
  178.                 print("at the top of the filterscript and reload");
  179.                 print("------------------------------------------------------------------");
  180.                 ResetRoadPointInfo(); // Reset all RoadPoints related info.
  181.                 fclose(file); // Close the fille
  182.                 return 0; // Abort the function
  183.             }
  184.         }
  185.     }
  186.     fclose(file);  // Close the file
  187.     printf("%d roadpoints loaded", TRP); // Show in ServerLog the total amound of created RoadPoints.
  188.     return 1;
  189. }
  190.  
  191. stock ReadTrainPoints() //  This function will read and load all RoadPoints from the KYLRoadPoints.txt file
  192. {
  193.     new File:file;
  194.     if (!fexist("KYLTrainRoadPoints.txt"))
  195.     {
  196.         file = fopen("KYLTrainRoadPoints.txt",io_write);
  197.         fclose(file);
  198.     }
  199.     file=fopen("KYLTrainRoadPoints.txt", io_read);
  200.     new str[64], zone, slot;  // Create new variables to store the string, zone and slot
  201.     new Float:rX, Float:rY, Float:rZ, Float:rD; // Create new temprorarily variables to store the coordinates, angle and distance
  202.     while(fread(file, str))  // Loop through each line in the file
  203.     {
  204.         sscanf(str, "ffff", rX, rY, rZ, rD);  // Retrieve all values from the line and store them in the temporarily variables
  205.         {
  206.             zone = GetZone(rX, rY);  // Get the zone ID based on the X and Y coordinate
  207.             slot = TPInZone[zone];
  208.             if(slot != 90)   // If there is an empty slot found
  209.             {
  210.                 TP[zone][slot][tpX] = rX;  // Store the temporarily X value in the global array
  211.                 TP[zone][slot][tpY] = rY;  // Store the temporarily Y value in the global array
  212.                 TP[zone][slot][tpZ] = rZ;  // Store the temporarily Z value in the global array
  213.                 TP[zone][slot][tpD] = rD-1.0;  // Store the temporarily distance in the global array
  214.                 TPInZone[zone]++;
  215.             }
  216.         }
  217.     }
  218.     fclose(file);  // Close the file
  219.     return 1;
  220. }
  221.  
  222. forward CheckRoadPoints();
  223. public CheckRoadPoints()   // This is the main function that checks the players position and sees if he's driving on the wrong side of the road:
  224. {
  225.     new zone, slot, rtrn; // Create some variables to temporarily store values.
  226.     for(new i; i<MAX_PLAYERS; i++) // Loop through all players
  227.     {
  228.         if(IsPlayerConnected(i))
  229.         {
  230.             if(GetPlayerState(i) == PLAYER_STATE_DRIVER) // Check if the player is driving a vehicle
  231.             {
  232.                 // My original plan was to only scan the players current zone for RoadPoints and check if the player is near any of them, but it caused problems when...
  233.                 //... because RoadPoints near its zone-border wont get triggered if the player is within reach, but on the other side of the border (in an different zone)...
  234.                 //... To solve this problem this script will not only scan the players current zone, but also the 4 surrounding zones for RoadPoints (if none have been found already).
  235.  
  236.                 // I created the funtion 'IsPlayerOnWrongWay' to check if the player is near a Roadpoint and, if so, check if the player is driving the right or wrong direction.
  237.                 // It will return '-1' if the player is not near any roadpoint in the given zone. Return '0' if the player is near a RoadPoint, but driving the right direction...
  238.                 //..and it will return '1' if the player is near a RoadPoint AND driving the wrong direction.
  239.                 //... this function also returns the slot of the found RoadPoint.
  240.  
  241.                 rtrn = IsPlayerOnWrongWay(i, CZ[i], slot);   // Check if the player is near any RoadPoint in his current zone.
  242.                 //// If the player is Ghost Driving, the remote callback 'OnPlayerGhostDriving' will be called (in your gamemode), it passes the playerid, zone, XYZ-coords and angle of the RoadPoint
  243.                 if(rtrn == 1) CallRemoteFunction("OnPlayerGhostDriving", "ddffff", i, zone, RP[CZ[i]][slot][X], RP[CZ[i]][slot][Y], RP[CZ[i]][slot][Z], RP[CZ[i]][slot][A]);
  244.                 else if(rtrn == -1)  // If no close RoadPoint is found... scan the next surrounding zone and repeat if for all 4 surrounding zones (unless a point is found.
  245.                 {
  246.                     zone = CZ[i]+1;
  247.                     rtrn = IsPlayerOnWrongWay(i, zone, slot);
  248.                     if(rtrn == 1) CallRemoteFunction("OnPlayerGhostDriving", "ddffff", i, zone, RP[zone][slot][X], RP[zone][slot][Y], RP[zone][slot][Z], RP[zone][slot][A]);
  249.                     else if(rtrn == -1)
  250.                     {
  251.                         zone = CZ[i]-1;
  252.                         rtrn = IsPlayerOnWrongWay(i, zone, slot);
  253.                         if(rtrn == 1) CallRemoteFunction("OnPlayerGhostDriving", "ddffff", i, zone, RP[zone][slot][X], RP[zone][slot][Y], RP[zone][slot][Z], RP[zone][slot][A]);
  254.                         else if(rtrn == -1)
  255.                         {
  256.                             zone = CZ[i]+12;
  257.                             rtrn = IsPlayerOnWrongWay(i, zone, slot);
  258.                             if(rtrn == 1) CallRemoteFunction("OnPlayerGhostDriving", "ddffff", i, zone, RP[zone][slot][X], RP[zone][slot][Y], RP[zone][slot][Z], RP[zone][slot][A]);
  259.                             else if(rtrn == -1)
  260.                             {
  261.                                 zone = CZ[i]-12;
  262.                                 rtrn = IsPlayerOnWrongWay(i, zone, slot);
  263.                                 if(rtrn == 1) CallRemoteFunction("OnPlayerGhostDriving", "ddffff", i, zone, RP[zone][slot][X], RP[zone][slot][Y], RP[zone][slot][Z], RP[zone][slot][A]);
  264.                             }
  265.                         }
  266.                     }
  267.                 }
  268.                 if(AllowTrainTrackDriving == false)
  269.                 {
  270.                     new model = GetVehicleModel(GetPlayerVehicleID(i));
  271.                     if((model != 537) && (model !=538))
  272.                     {
  273.                         for(slot = 0; slot<90; slot++)  // Loop through all RoadPoints in the given zone
  274.                         {
  275.                             if(IsPlayerInRangeOfPoint(i, TP[CZ[i]][slot][tpD], TP[CZ[i]][slot][tpX], TP[CZ[i]][slot][tpY], TP[CZ[i]][slot][tpZ])) // Check if player is in range of the RoadPoint
  276.                             {
  277.                                 CallRemoteFunction("OnPlayerDrivingOnTrainTrack", "ddfff", i, CZ[i], TP[CZ[i]][slot][tpX], TP[CZ[i]][slot][tpY], TP[CZ[i]][slot][tpZ]);
  278.                             }
  279.                         }
  280.                     }
  281.                 }
  282.             }
  283.         }
  284.     }
  285.     return 1;
  286. }
  287.  
  288. // This function will scan the given zone for RoadPoints and check if the given player is near them and driving in the right or wrong direction...
  289. //.. it will return the slot of the Roadpoint in that zone and will return -1, 0, or 1, depending on if any points are found.
  290. IsPlayerOnWrongWay(playerid, zone, &slot)
  291. {
  292.     new Float:cA, Float:MinAngle, Float:MaxAngle;
  293.     new isfound = -1;  // On default no RoadPoint is found near the player
  294.     for(slot = 0; slot<MAX_ROADPOINTS_PER_ZONE; slot++)  // Loop through all RoadPoints in the given zone
  295.     {
  296.         if(IsPlayerInRangeOfPoint(playerid, RP[zone][slot][D], RP[zone][slot][X], RP[zone][slot][Y], RP[zone][slot][Z])) // Check if player is in range of the RoadPoint
  297.         {
  298.             isfound = 0; // Set the variable to '0', this means the player is near a RoadPoint, now we should check if the player is driving the right/wrong direction:
  299.             GetVehicleZAngle(GetPlayerVehicleID(playerid), cA);  // Get the current driving direction of the player
  300.             cA = floatsub(cA, 180);  // Invert the direction by subtracting 180 degrees.
  301.             if(cA < 0)  // check if the angle is below '0'
  302.             {
  303.                 cA = floatadd(cA, 360.0);  // add 360 to get it above 0 degrees again.
  304.             }
  305.             MinAngle = floatsub(RP[zone][slot][A], ANGLE_TOLERANCE); // Calculate the minimum angle by subtracting the angle tolerance (defined at top of this script)
  306.             MaxAngle = floatadd(RP[zone][slot][A], ANGLE_TOLERANCE); // Calculate the maximum angle by adding the angle tolerance (defined at top of this script)
  307.             if((cA > MinAngle) && (cA < MaxAngle))  // Check if the players driving direction is between the mininmum and maximum angle (if yes, he's driving in the wrong direction)
  308.             {
  309.                 isfound = 1; // If the player is indeed Ghost Driving, set the varible to '1'.
  310.             }
  311.             break; // stop the loop.
  312.         }
  313.     }
  314.     return isfound; // Return the result
  315. }
  316.  
  317. stock GetFreeSlot(zone) // This funtion returns the ID of the first empty slot in the given zone. (Returns -1 if no empty slot is found in this zone).
  318. {
  319.     new freeslot = -1;
  320.     for(new slot; slot<MAX_ROADPOINTS_PER_ZONE; slot++)
  321.     {
  322.         if(RP[zone][slot][ID] == -1)
  323.         {
  324.             freeslot = slot;
  325.             break;
  326.         }
  327.     }
  328.     return freeslot;
  329. }
  330.  
  331. stock GetLargestZone() // This function returns the zone ID which holds the most RoadPoints. (Used in the CheckEfficiency function).
  332. {
  333.     new largestzone = -1;
  334.     new highestvalue = -1, tmp;
  335.     for(new zone; zone<145; zone++)
  336.     {
  337.         tmp = GetFreeSlot(zone);
  338.         if(tmp == -1)  //Zone is full
  339.         {
  340.             largestzone = zone;
  341.             highestvalue = MAX_ROADPOINTS_PER_ZONE;
  342.         }
  343.         if(tmp > highestvalue)
  344.         {
  345.             largestzone = zone;
  346.             highestvalue = tmp;
  347.         }
  348.     }
  349.     return largestzone;
  350. }
  351.  
  352. forward CheckEfficiency();
  353. public CheckEfficiency() // This function will check if the defined value of MAX_ROADPOINTS_PER_ZONE is optimal
  354. {
  355.     new zone = GetLargestZone();  // Retreive the zone which holds the most RoadPoints
  356.     new amount = GetFreeSlot(zone);  // Get the amount of RoadPoints in that zone.
  357.     if((amount <= MAX_ROADPOINTS_PER_ZONE) && (amount > 1))  // Check if this amount is lower than the defined MAX_ROADPOINTS_PER_ZONE
  358.     {
  359.         // If so, send a message to the serverlog suggesting the optimal value:
  360.         print("------------------------------------------------------------------");
  361.         print("[TIP]: If you are done with creating new RoadPoints you can");
  362.         print("increase your server's performance by lowering the value");
  363.         printf("of 'MAX_ROADPOINTS_PER_ZONE' to %d at the top of the Filterscript", amount);
  364.         print("-------------------------------------------------------------------");
  365.     }
  366.     return 1;
  367. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement