[Tutorial] How to create a vehicle system using Y_INI and Y_CMD
#1

Introduction:
In this tutorial, I will be showing you how to create an advance vehicle system using YINI and YCMD.






Prerequisites:
Y_INI => HERE
Y_COMMANDS => HERE





Step 1: The System

In this step, we will be doing the system. A system is the group of logics behind the function which can be reused.
pawn Код:
enum vInfo // The name of the enum. For naming convention use the system's first letter in lowercase.
{
    vID, // The vehicle id used on the SA-MP to represent the vehicle.
    vModel, // The vehicle model of the vehicle.
    Float:vLoc[4], // The array which contains position and the rotation of the vehicle in 4 cells. So, basically {X = 0, Y = 1, Z = 2, R = 3}
    vColor1, // The primary color of the vehicle.
    vColor2, // The secondary color of the vehicle.
    vRespawn, // The vehicle respawn time.
    vOwner[MAX_PLAYER_NAME], // The vehicle's owner name. Remember string is a group of literal characters and the cells you provide should be the maximum length for that string.
    bool:vLocked // Bool representing if the vehicle is locked or not. (0 = False, 1 = True)
}
new VehicleInfo[MAX_VEHICLES][vInfo]; // We are now making use of our ENUM by declaring an array which will hold all of the dynamic vehicle's information.
// The first cell is going to be the vehicle id based on our system(Not SA-MP). It's use to reference the dynamic vehicle for later usage.
// The second cell is the ENUM we made it. ENUMs are bunch of constant variables stacked up with each other.
// Imagine the array when the system will be ready. VehicleInfo[0][vID] or VehicleInfo[1][vID].

new bool:vCreated[MAX_VEHICLES]; // This will account the vehicles which has been created for later usage. The reason why we use this is to save/load
// the vehicle only if the vehicle is created. Otherwise not.

stock VehiclePath(vehicleID) // Creating a function which will get the vehicle path dynamically based on the vehicle id of the system.
{
    new strPath[64]; // Declaring the variable which will hold and return the vehicle path by vehicle id.
    format(strPath, sizeof(strPath), "/vehicle/%d.ini"); // We are formatting the string so that it holds the file path based on the vehicle id. '%d' means it will be a whole number.
   
    return strPath; // Return the file path so that it can be manipulate later on.
}  
stock VehicleGetFreeSlot() // This function is used to get the free slot available to be used on the vehicle. It will be the vehicle id.
{
    for(new i = 0; i < MAX_VEHICLES; i++) // Loop through all of the vehicles on the sa-mp world and increments the variable 'i' by 1.
    {
        if(!vCreated[i]) return i; // If that 'i' isn't being used on any of our system's vehicle then return this vehicle id and make use of it.
    }
   
    return -1; // Return -1 because 0 is a valid vehicle id for our system as we are left with -1.
}
stock VehicleCreate(vehicleModel, Float:vehicleLoc[4], vehicleColor1, vehicleColor2, vehicleRespawn, vehicleOwner[], bool:vehicleLocked)
// This is our most important function. This will create the vehicle with the valid information provided on the arguments.
{
    new vehicleid = VehicleGetFreeSlot(); // Get the free slot and store it on the vehicleid variable.
    //Now, we will basically put the information from the arguments to our newly created vehicle's array.
    VehicleInfo[vehicleid][vModel] = vehicleModel; // Assign our vehicle's model id to the model id provided.
    VehicleInfo[vehicleid][vLoc] = vehicleLoc; // Assign our vehicle's position/rotation to the position/rotation provided.
    VehicleInfo[vehicleid][vColor1] = vehicleColor1; // Assign our vehicle's primary color to the primary color provided.
    VehicleInfo[vehicleid][vColor2] = vehicleColor2; // Assign our vehicle's secondary color to the secondary color provided.
    VehicleInfo[vehicleid][vRespawn] = vehicleRespawn; // Assign our vehicle's respawn time to the respawn time provided.
    format(VehicleInfo[vehicleid][vOwner], MAX_PLAYER_NAME, vehicleOwner); // Assign our vehicle's owner name to the owner name provided.
    VehicleInfo[vehicleid][vLocked] = vehicleLocked; // Assign our vehicle's lock data to the lock data provided.
    VehicleInfo[vehicleid][vID] = CreateVehicle(vehicleModel, vehicleLoc[0], vehicleLoc[1], vehicleLoc[2], vehicleLoc[3], vehicleColor1, vehicleColor2,
    vehicleRespawn); // Now we are doing two things. We are creating our vehicle on the sa-mp world based on the data provided as well as assigning the
    // sa-mp vehicle id to our system's vehicle id so that we can alter it later.
    vCreated[vehicleid] = true; // Tell our vehicle management variable that this vehicle creation has been done and it's now on the system.
    VehicleLock(vehicleid, VehicleInfo[vehicleid][vLocked]); // Toggle our vehicle's door based on the parameter.
   
    return vehicleid; // Return the newly created vehicle's system id.
}
stock VehicleGet(vehicleID)
// Get the current sa-mp vehicle information for the provided vehicle id
{
    GetVehiclePos(VehicleInfo[vehicleID][vID], VehicleInfo[vehicleID][vLoc][0], VehicleInfo[vehicleID][vLoc][1], VehicleInfo[vehicleID][vLoc][2]);
    // Get the current position of that vehicle and assign it to our system's vehicle information.
    GetVehicleZAngle(VehicleInfo[vehicleID][vID], VehicleInfo[vehicleID][vLoc][3]);
    // Get the current rotation of that vehicle and assign it to our system's vehicle information.
}
stock VehicleLoad(vehicleID, file[])
// This function will load the vehicle provided by the id when the server starts.
{
    INI_ParseFile(file, "LoadVehicleData", .bExtra = true, .extra = vehicleID); // Parse the vehicle data from the INI file.
    VehicleCreate(VehicleInfo[vehicleID][vModel],
    VehicleInfo[vehicleID][vLoc], VehicleInfo[vehicleID][vColor1], VehicleInfo[vehicleID][vColor2], VehicleInfo[vehicleID][vRespawn],
    VehicleInfo[vehicleID][vOwner], VehicleInfo[vehicleID][vLocked]); // Creates the vehicle from the information we loaded and parsed. Pretty self-explanatory.
}
forward public LoadVehicleData(vehicleID, name[], value[]);
public LoadVehicleData(vehicleID, name[], value[]) // This a callback with the parameter of the vehicleID send from our VehicleLoad function. This function will pretty much parse the data from the file.
{
    new strLoc[8]; // Will hold the location key name dynamically.
    // The first argument is the key and the second argument is the data which will hold the value of that key.
    INI_Int("model", VehicleInfo[vehicleID][vModel]);
    for(new i = 0; i < 4; i++) format(strLoc, sizeof(strLoc), "Loc%d", i), INI_Float(strLoc, VehicleInfo[vehicleID][vLoc][i]);
    // Looping through our location data and retrive it. Loc0 = LocX, Loc1 = LocY, Loc2 = LocZ, Loc3 = LocA.
    INI_Int("color1", VehicleInfo[vehicleID][vColor1]); // You should've guessed it by now.
    INI_Int("color2", VehicleInfo[vehicleID][vColor2]);
    INI_Int("respawn", VehicleInfo[vehicleID][vRespawn]);
    INI_String("owner", VehicleInfo[vehicleID][vOwner], MAX_PLAYER_NAME);
    VehicleInfo[vehicleID][vLocked] = INI_Int("locked") == 1 ? true : false;
    //Converting the locked data from int(whole number) to bool(true/false) and assign it.

    return 1;
}
stock VehicleSave(vehicleID) // This function will save our vehicle on the INI file and will create it if it doesn't exist.
{
    new INI:dFile = INI_Open(VehiclePath(vehicleID)); // Open/Create the file for our vehicle.
    new strLoc[8]; // Will hold the location key name dynamically.
    // The first argument is the file to write the second is the key and the third argument is the value it will write.
    INI_WriteInt(dFile, "model", VehicleInfo[vehicleID][vModel]);
    for(new i = 0; i < 4; i++) format(strLoc, sizeof(strLoc), "Loc%d", i), INI_Float(dFile, strLoc, VehicleInfo[vehicleID][vLoc][i]);
    // Looping through our location data and write it. Loc0 = LocX, Loc1 = LocY, Loc2 = LocZ, Loc3 = LocA.
    INI_WriteInt(dFile, "color1", VehicleInfo[vehicleID][vColor1]); // You should've guessed it by now.
    INI_WriteInt(dFile, "color2", VehicleInfo[vehicleID][vColor2]);
    INI_WriteInt(dFile, "respawn", VehicleInfo[vehicleID][vRespawn]);
    INI_WriteString(dFile, "owner", VehicleInfo[vehicleID][vOwner]);
    INI_WriteInt(dFile, "locked", VehicleInfo[vehicleID][vLocked] ? 1 : 0);
    //Converting the locked data from bool(true/false) to int(whole number) and write it.
    INI_Close(dFile);
}
stock VehicleLoadAll() // This function will load all of the system vehicles created and saved.
{
    new index = 0; // We need this variable to keep track of the id or the index of the file. Start it with 0 as the id.

    while(fexist(VehiclePath(index))) // If any system vehicle has been created before with that 0 id
    {
        VehicleLoad(index, VehiclePath(index)); // Then load that vehicle.
        index++; // And move on to another system vehicle id.
    }
   
    printf("Vehicles Loaded: %d", index); // Print out how many vehicles has been loaded.
}
stock VehicleSaveAll()
{
    new index = 0; // We need this variable to keep track of the id or the index of the file. Start it with 0 as the id.

    for(new i = 0; i < MAX_VEHICLES; i++) // Loop through the maximum amount of vehicles allowed by sa-mp.
    {
        if(vCreated[i]) // If that is our system's vehicle and if it has been created
        {
            VehicleGet(index); // Get that vehicle's current data.
            VehicleSave(index); // Save that vehicle's data on the file.
            index++; // Move on to next vehicle.
        }
    }
   
    printf("Vehicles Saved: %d", index); // Print out how many vehicles has been saved.
}




Step 2: Implementing it on the gamemode
In this step, we will be implementing the vehicle system on the gamemode.
pawn Код:
public OnGameModeInit()
{
    VehicleLoadAll(); // Load all vehicles when the main script starts.

    return 1;
}

public OnGameModeExit()
{
    VehicleSaveAll(); // Save all vehicles when the main script stops/ends.
   
    return 1;
}




Step 3: Creating the commands.
In this step, we will be creating the commands to be able to use for our vehicle system.
pawn Код:
stock VehicleValid(vehicleID) //Get's the system's vehicle id from sa-mp's vehicle id.
{
    for(new i = 0; i < MAX_VEHICLES; i++) // For every vehicles till the maximum amount
    {
        if((vCreated[i]) && (VehicleInfo[i][vID] == vehicleID)) return i; // Is this vehicle created and it's the same sa-mp id as the argument provided? Return the system's id then.
    }
   
    return -1; // Return invalid system's vehicle id if it was not found.
}
stock VehicleEngine(vehicleID, bool:toggle) // Toggles the vehicle engine with the first parameter being the system's vehicle id not sa-mp's
{
    new vehicleid = VehicleInfo[vehicleID][vID]; // Get's the sa-mp's vehicle id.
    new engine, lights, alarm, doors, bonnet, boot, objective; // The variables to hold the current vehicle state.
    GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective); // Get's the current variable state and reference it to the variables.
    SetVehicleParamsEx(vehicleid, toggle, lights, alarm, doors, bonnet, boot, objective); // Set's the current vehicle state to be the same as before with just the engine being controlled by the bool:toggle parameter.
}
stock VehicleLock(vehicleID, bool:toggle) // Toggles the vehicle doors with the first parameter being the system's vehicle id not sa-mp's
{
    new vehicleid = VehicleInfo[vehicleID][vID]; // Get's the sa-mp's vehicle id.
    new engine, lights, alarm, doors, bonnet, boot, objective; // The variables to hold the current vehicle state.
    GetVehicleParamsEx(vehicleid, engine, lights, alarm, doors, bonnet, boot, objective); // Get's the current variable state and reference it to the variables.
    SetVehicleParamsEx(vehicleid, engine, lights, alarm, toggle, bonnet, boot, objective); // Set's the current vehicle state to be the same as before with just the door being controlled by the bool:toggle parameter.
}

new bool:engine; // This will check if we should turn on/turn off the engine. (TRUE/FALSE)
YCMD:engine(playerid, params[], help) // The base YCMD command structure with the command name being /engine which will toggle the engine.
{
    if(help) return SendClientMessage(playerid, -1, "Allows to toggle the vehicle engine."); // Shows him the help messages. Check out Y_CMD for more info.

    new vehicleid = VehicleID(GetPlayerVehicleID(playerid)); // Get's our system vehicle id from our sa-mp's vehicle id.
   
    if((IsPlayerInAnyVehicle(playerid)) && (vehicleid != -1)) // If they are on a vehicle and if that vehicle is the system's vehicle.
    {
        engine = !engine; // Inverse our boolean. So, if it's false it should be true and if it's true it should be false.
        VehicleEngine(vehicleid, engine); // Call the function we have just created.
    }
   
    return 1;
}
YCMD:createvehicle(playerid, params[], help) // The base YCMD command structure with the command name being /createvehicle which will create a system's vehicle.
{
    if(help) return SendClientMessage(playerid, -1, "Allows to create a dynamic vehicle."); // Shows him the help messages. Check out Y_CMD for more info.

    new vehModel, vehColor1, vehColor2, vehRespawnTime; // This variables will have the arguments value stored in it which will be parsed from sscanf.
   
    if(sscanf(params, "iiii", vehModel, vehColor1, vehColor2, vehRespawnTime)) // If they don't meet our arguments.
        return SendClientMessage(playerid, -1, "USAGE: /createvehicle [Vehicle Model] [Color 1] [Color 2] [Respawn Time]"); // Return a message to convey them the correct order/format.
   
    new Float:pLoc[4]; // This will hold our player's position and rotation data.
    new strPlayerName[MAX_PLAYER_NAME]; // This will hold our player's name.
    new vehicleid; // This will hold our newly created sa-mp vehicle id.
    GetPlayerPos(playerid, pLoc[0], pLoc[1], pLoc[2]); // Get's our player's position and store it in the variable.
    GetPlayerFacingAngle(playerid, pLoc[3]); // Get's our player's rotation and store it in the variable.
    GetPlayerName(playerid, strPlayerName, MAX_PLAYER_NAME); // Get's our player's name and store it in the variable.
    vehicleid = VehicleCreate(vehModel, pLoc, vehColor1, vehColor2, vehRespawnTime, strPlayerName, false);
    //Set's the model based on the argument, the position based on the player's position, the two color's based on the argument, the respawn time
    //based on the argument, the owner name based on the player's name and the vehicle lock to be false.
    PutPlayerInVehicle(playerid, vehicleid, 0); // Put the player in our vehicle.
   
    return 1;
}
//Updating...
Reply
#2

Really nice, can't wait for the commands to be made.
Reply
#3

Very interesting and helpful tutorial ,congratz
Reply
#4

Nicce
Reply
#5

Good job
Reply
#6

UPDATED: Added vehicle lock on VehicleCreate and the Step 3.
Reply
#7

Good tutorial. But you forgot to add a link to sscanf.
Reply
#8

nice tut as always. Too bad you left sa-mp
Reply
#9

dood Ycmd suks use zcmd
Reply
#10

I just wonder something.

What does Respawn Time do? I know, it does respawn the vehicle but.. Is this the time that the vehicle takes to respawn when the GM has been restarted?

Anyways, Nice tutorial.
Reply
#11

Quote:
Originally Posted by [CG]Milito
View Post
I just wonder something.

What does Respawn Time do? I know, it does respawn the vehicle but.. Is this the time that the vehicle takes to respawn when the GM has been restarted?

Anyways, Nice tutorial.
It's used to respawn the vehicle back to the location it were created. Use -1 if you don't want it.
Reply
#12

I have an error on this line
pawn Code:
VehicleCreate(VehicleInfo[vehicleID][vModel],
    VehicleInfo[vehicleID][vLoc], VehicleInfo[vehicleID][vColor1], VehicleInfo[vehicleID][vColor2], VehicleInfo[vehicleID][vRespawn],
    VehicleInfo[vehicleID][vOwner], VehicleInfo[vehicleID][vLocked]);
ERROR:
Code:
array sizes do not match, or destination array is too small
Any idea or solution? Thanks! .. its for the vLoc array
Reply
#13

Try to make the array bigger.
Reply
#14

Nice but I am gonna use it for my rp server but it has tones of errors on 3.x
Reply
#15

Quote:
Originally Posted by Ryan_Obeles
View Post
Nice but I am gonna use it for my rp server but it has tones of errors on 3.x
You clearly aren't using it right as it worked fine on my script.
Reply
#16

No i have fixed it already i am just waiting for cmds
Reply
#17

Quote:
Originally Posted by Ryan_Obeles
View Post
No i have fixed it already i am just waiting for cmds
Which command?
Reply
#18

why do i get all this errors and warnings ?
pawn Code:
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(28) : warning 201: redefinition of constant/macro (symbol "strcpy(%0,%1,%2)")
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(145) : warning 203: symbol is never used: "vehicleID"
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(193) : error 047: array sizes do not match, or destination array is too small
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(203) : error 029: invalid expression, assumed zero
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(203) : error 001: expected token: ";", but found "return"
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(203) : error 017: undefined symbol "i"
C:\Users\user\Desktop\Roleplay\Roleplay\gamemodes\rp.pwn(203) : fatal error 107: too many error messages on one line
Reply
#19

I love this tutorial it's awesome! But I'm having a problem that I hope I can get answered quickly pleaseee s:

So basically I'm creating a house system following this tutorial but I dont know what to do with this line:

stock HouseGet(houseid)
{}

I need something to get the coordinates of the Pickup that I created in the :

Quote:

stock HouseCreate(name, Float:houseLoc[3], interior, owner[], price, locked)
{
new houseid = HouseGetFreeSlot();
HouseInfo[houseid][hName] = houseName;
HouseInfo[houseid][hLoc] = houseLoc;
HouseInfo[houseid][hInt] = houseInt;
format(HouseInfo[houseid][hOwner], MAX_PLAYER_NAME, houseOwner);
HouseInfo[houseid][hPrice] = housePrice;
HouseInfo[houseid][hLocked] = houseLocked;
HouseInfo[houseid][hID] = CreatePickup(1273, 1, houseLoc[0], houseLoc[1], houseLoc[2], -1); <----------------------------------
hCreated[houseid] = true;
HouseLock(houseid, HouseInfo[houseid][hLocked]);
return houseid;
}

Please some help is really mutch appreciated! Thanks (:
Reply
#20

GetPlayerPos ^
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)