[Tutorial] [TUT]Making personal spawn-vehicles
#1

Hi all!
I decided to make a little simple tutorial, on how to make vehicles which players can spawn for themselves.

First off, start by making a global variable which stores the vehicleid for each player:
pawn Код:
new
    gPersonalVehicle[ MAX_PLAYERS ], //used to store the player's personal vehicleID
    gPersonalModel[ MAX_PLAYERS ]; //used to store the player's personal modelID
Just in case, set these variables to 0 on connect and disconnect (you have to do it inside atleast one of them callbacks)

pawn Код:
public OnPlayerConnect(playerid)
{
    gPersonalVehicle[ playerid ] = 0;
    gPersonalModel[ playerid ] = 0;
    return true;
}

public OnPlayerDisconnect(playerid, reason)
{
    gPersonalVehicle[ playerid ] = 0;
    gPersonalModel[ playerid ] = 0;
    return true;
}
This will prevent players who connect with a ID which already has been used, and get their personal vehicle.
You don't want that.

Now for the commands.
UPDATE: Added STRTOK version below
I'm going to use DCMD and sscanf in this tutorial, since I'm more comfortable with it.
I'll add comments in the code box, so please pay attention to them:


DCMD&Sscanf

pawn Код:
dcmd_spawnveh(playerid, params[])
{
    new
        iModel, //the variable we will use for the parameter in this command
        Float:x,
        Float:y,  //x, y, z is the floats we will use to store the player's position.
        Float:z,
        str[ 76 ];  //a string variable with 76 cells

    if( sscanf( params, "%d", iModel )) //checks if the parameter is an integer, or even typed in
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Usage: \"/spawnveh <modelid>\"" );
        //send a message to 'playerid' with color RED, saying this string ^
    if( IsPlayerInAnyVehicle( playerid )) //checks if the player is inside any vehicle, and tell him/her to exit the vehicle before spawning a personal one
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Please exit your current vehicle before using this command" );
    if( GetPlayerInterior( playerid ) != 0 ) //checks if player is not in the interior 0 (outdoors)
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Only usable outdoors (interior 0)" );
    if( iModel < 400 || iModel > 611 ) //checks if the modelid parameter is less than 400 or more than 611. Lowest modelid is 400 and highest is 611
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Invalid modelID" );
    if( gPersonalVehicle[ playerid ] != 0 ) //checks if gPersonalVehicle is more than -1, if it is, this player already got a personal vehicle, and we have to do something
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You already have a personal vehicle! Use the /getveh command to teleport the vehicle to you, or /changeveh to change your personal vehicle." );
    GetPlayerPos( playerid, x, y, z ); //stores the player's position coordinates into the variables; x, y and z
    gPersonalVehicle[ playerid ] = CreateVehicle( iModel, x, y, z, 0, -1, -1, 10*60*1000 );
    //creates a vehicle (stored within the variable gPersonalVehicle) with the decided model, at the exact same position as the player is standing, with random colors and a respawn time at 10 minutes.
    gPersonalModel[ playerid ] = iModel; //sets the variable gPersonalModel equal to iModel
    PutPlayerInVehicle( playerid, gPersonalVehicle[ playerid ], 0 ); //puts the player in his/her personal vehicle as the driver. This is why we checked if the player already were inside a vehicle or not.
    format( str, sizeof( str ), "[SUCCESS]Successfully spawned your very own personal vehicle! (ModelID: %d)", iModel ); //just a simple format message to include the chosen model id in the message.
    SendClientMessage( playerid, 0x00FF00FF, str ); //sends the formatted string
    return true; //returns the command
}
That was the /spawnveh command *phew*
Now for the /getveh command

pawn Код:
dcmd_getveh(playerid, params[])
{
    #pragma unused params //this line hides the warning that "params" is unused, since we don't use it in this command
    new
        Float:x,
        Float:y,  //x, y, z is the floats we will use to store the player's position.
        Float:z;

    if( gPersonalVehicle[ playerid ] == 0 ) //checks if the player doesn't already have a personal vehicle
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You haven't spawned a personal vehicle yet! Use /spawnveh to spawn one." );
    if( IsPlayerInAnyVehicle( playerid )) //checks if the player is inside any vehicle, and tell him/her to exit the vehicle before teleporting his/her personal one
    if( GetPlayerInterior( playerid ) != 0 ) //checks if player is not in the interior 0 (outdoors)
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Only usable outdoors (interior 0)" );
    GetPlayerPos( playerid, x, y, z );//again, this stores the player's position coordinates into the variables; x, y and z
    DestroyVehicle( gPersonalVehicle[ playerid ] ); //destroys the players personal vehicle, before we spawn it again
    gPersonalVehicle[ playerid ] = CreateVehicle( gPersonalModel[ playerid ], x, y, z, 0, -1, -1, 10*60*1000 );
    //same as last time, we create a vehicle assigned to the variable 'gPersonalVehicle'
    PutPlayerInVehicle( playerid, gPersonalVehicle[ playerid ], 0 ); //puts the player in his/her personal vehicle as the driver. This is why we checked if the player already were inside a vehicle or not.
    SendClientMessage( playerid, 0x00FF00FF, "[SUCCESS]Personal vehicle teleported to your location" );
    return true; //return the command
}
Now lastly, the /changeveh command:

pawn Код:
dcmd_changeveh(playerid, params[])
{
    if( gPersonalVehicle[ playerid ] == 0 ) //checks if the player doesn't already have a personal vehicle
        return dcmd_spawnveh(playerid, params); //"redirect" the player to the spawn command
    new
        iNewModel, //the variable we will use for the parameter in this command
        str[ 50 ];  //a string variable with 50 cells

    if( sscanf( params, "%d", iNewModel )) //checks if the parameter is an integer, or even typed in
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Usage: \"/changeveh <modelid>\"" );
        //send a message to 'playerid' with color RED, saying this string ^
    if( iNewModel < 400 || iNewModel > 611 ) //checks if the modelid parameter is less than 400 or more than 611. Lowest modelid is 400 and highest is 611
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Invalid modelID" );
    if( IsPlayerInVehicle( playerid, gPersonalVehicle[ playerid ] )) //if the player is inside his/her personal vehicle
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You must exit your personal vehicle for this command to work!" );
    gPersonalModel[ playerid ] = iNewModel; //sets the players personal vehicle modelid, to the newly wanted one.
    DestroyVehicle( gPersonalVehicle[ playerid ] ); //destroys the players personal vehicle
    format( str, sizeof( str ), "[SUCCESS]Personal vehicle changed to modelid %d!", iNewModel ); //again we format a message (string) for the player to recieve
    SendClientMessage( playerid, 0x00FF00FF, str ); //here we send the message with the formatted string.
    return true; //lastly we return the command
}
Now we are done with our commands *finally, lol*
Remember that with dcmd you have to call them inside OnPlayerCommandText, so add these lines:
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
    dcmd(spawnveh, 8, cmdtext); //call the command 'spawnveh' which has 8 characters
    dcmd(getveh, 6, cmdtext); //call the command 'getveh' which has 6 characters
    dcmd(changeveh, 9, cmdtext); //call the command 'changeveh' which has 9 characters
    return false; //remember that OnPlayerCommandText should return false.
}
Oh, and you'll have to include the DCMD define line, and the sscanf function to your script.

pawn Код:
//DCMD
#define dcmd(%1,%2,%3) \
if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) \
return 1
Sscanf (code too large to post here, lol:P): https://sampwiki.blast.hk/wiki/Sscanf_code


STRTOK

Put this inside your OnPlayerCommandText:

pawn Код:
new
    cmd[ 128 ],
    idx;

    cmd = strtok(cmdtext, idx);
These commands is added normally (inside OnPlayerCommandText)

pawn Код:
if( !strcmp( cmd, "/spawnveh", true )) //Checks if the player types /spawnveh
{
    new
        iModel, //the variable we will use for the parameter in this command
        Float:x,
        Float:y,  //x, y, z is the floats we will use to store the player's position.
        Float:z,
        str[ 76 ],  //a string variable with 76 cells
        tmp[ 128 ]; //the variable we use for strtok

    tmp = strtok(cmdtext, idx);
    if( !strlen( tmp )) //checks if the parameter is typed in
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Usage: \"/spawnveh <modelid>\"" );
        //send a message to 'playerid' with color RED, saying this string ^
    iModel = strval( tmp ); //iModel stores the parameter
    if( IsPlayerInAnyVehicle( playerid )) //checks if the player is inside any vehicle, and tell him/her to exit the vehicle before spawning a personal one
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Please exit your current vehicle before using this command" );
    if( GetPlayerInterior( playerid ) != 0 ) //checks if player is not in the interior 0 (outdoors)
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Only usable outdoors (interior 0)" );
    if( iModel < 400 || iModel > 611 ) //checks if the modelid parameter is less than 400 or more than 611. Lowest modelid is 400 and highest is 611
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Invalid modelID" );
    if( gPersonalVehicle[ playerid ] != 0 ) //checks if gPersonalVehicle is more than -1, if it is, this player already got a personal vehicle, and we have to do something
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You already have a personal vehicle! Use the /getveh command to teleport the vehicle to you, or /changeveh to change your personal vehicle." );
    GetPlayerPos( playerid, x, y, z ); //stores the player's position coordinates into the variables; x, y and z
    gPersonalVehicle[ playerid ] = CreateVehicle( iModel, x, y, z, 0, -1, -1, 10*60*1000 );
    //creates a vehicle (stored within the variable gPersonalVehicle) with the decided model, at the exact same position as the player is standing, with random colors and a respawn time at 10 minutes.
    gPersonalModel[ playerid ] = iModel; //sets the variable gPersonalModel equal to iModel
    PutPlayerInVehicle( playerid, gPersonalVehicle[ playerid ], 0 ); //puts the player in his/her personal vehicle as the driver. This is why we checked if the player already were inside a vehicle or not.
    format( str, sizeof( str ), "[SUCCESS]Successfully spawned your very own personal vehicle! (ModelID: %d)", iModel ); //just a simple format message to include the chosen model id in the message.
    SendClientMessage( playerid, 0x00FF00FF, str ); //sends the formatted string
    return true; //returns the command
}
That was the /spawnveh command *phew*
Now for the /getveh command

pawn Код:
if( !strcmp( cmdtext, "/getveh", true ))
{
    new
        Float:x,
        Float:y,  //x, y, z is the floats we will use to store the player's position.
        Float:z;

    if( gPersonalVehicle[ playerid ] == 0 ) //checks if the player doesn't already have a personal vehicle
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You haven't spawned a personal vehicle yet! Use /spawnveh to spawn one." );
    if( IsPlayerInAnyVehicle( playerid )) //checks if the player is inside any vehicle, and tell him/her to exit the vehicle before teleporting his/her personal one
    if( GetPlayerInterior( playerid ) != 0 ) //checks if player is not in the interior 0 (outdoors)
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Only usable outdoors (interior 0)" );
    GetPlayerPos( playerid, x, y, z );//again, this stores the player's position coordinates into the variables; x, y and z
    DestroyVehicle( gPersonalVehicle[ playerid ] ); //destroys the players personal vehicle, before we spawn it again
    gPersonalVehicle[ playerid ] = CreateVehicle( gPersonalModel[ playerid ], x, y, z, 0, -1, -1, 10*60*1000 );
    //same as last time, we create a vehicle assigned to the variable 'gPersonalVehicle'
    PutPlayerInVehicle( playerid, gPersonalVehicle[ playerid ], 0 ); //puts the player in his/her personal vehicle as the driver. This is why we checked if the player already were inside a vehicle or not.
    SendClientMessage( playerid, 0x00FF00FF, "[SUCCESS]Personal vehicle teleported to your location" );
    return true; //return the command
}
Now lastly, the /changeveh command:

pawn Код:
if( !strcmp( cmd, "/changeveh", true ))
{
    if( gPersonalVehicle[ playerid ] == 0 ) //checks if the player doesn't already have a personal vehicle
        return OnPlayerCommandText(playerid, "/spawnveh"); //"redirect" the player to the spawn command
    new
        iNewModel, //the variable we will use for the parameter in this command
        str[ 50 ],  //a string variable with 50 cells
        tmp[ 128 ];

    tmp = strtok(cmdtext, idx);
    if( !strlen( tmp )) //checks if the parameter is typed in
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Usage: \"/changeveh <modelid>\"" );
        //send a message to 'playerid' with color RED, saying this string ^
    iNewModel = strval( tmp );
    if( iNewModel < 400 || iNewModel > 611 ) //checks if the modelid parameter is less than 400 or more than 611. Lowest modelid is 400 and highest is 611
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]Invalid modelID" );
    if( IsPlayerInVehicle( playerid, gPersonalVehicle[ playerid ] )) //if the player is inside his/her personal vehicle
        return SendClientMessage( playerid, 0xFF0000FF, "[ERROR]You must exit your personal vehicle for this command to work!" );
    gPersonalModel[ playerid ] = iNewModel; //sets the players personal vehicle modelid, to the newly wanted one.
    DestroyVehicle( gPersonalVehicle[ playerid ] ); //destroys the players personal vehicle
    format( str, sizeof( str ), "[SUCCESS]Personal vehicle changed to modelid %d!", iNewModel ); //again we format a message (string) for the player to recieve
    SendClientMessage( playerid, 0x00FF00FF, str ); //here we send the message with the formatted string.
    return true; //lastly we return the command
}
Lastly you need the strtok function:

pawn Код:
strtok(const string[], &index)
{
    new length = strlen(string);
    while ((index < length) && (string[index] <= ' '))
    {
        index++;
    }
 
    new offset = index;
    new result[20];
    while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
    {
        result[index - offset] = string[index];
        index++;
    }
    result[index - offset] = EOS;
    return result;
}
Well that's it, now you have a simple personal vehicle system (incredibly simple).
This is NOT tested at ALL, only compiled.
This should work out, but if there's something wrong about my tutorial, please help me fix my faults.

Enjoy!
Reply
#2

Awesome.
Detailed.
Newbie friendly.


Maybe include non DCMD parts?
Reply
#3

good tutorial!
Reply
#4

Good job.
Reply
#5

Ty guys:]

FIRST POST UPDATED WITH STRTOK VERSION
(as requested/suggested by 'www.******.com')
Reply
#6

FIRST POST FIXED
Code should be working great now :]

NOTE!: Still not tested, only compiled!
Reply
#7

Very nicly done LarzI!
Good job mate
Reply
#8

Thanks
Reply
#9

Nice 1
Reply
#10

Your /getveh command is still written as /spawnveh.
Reply
#11

Omg, I thought I fixed that already, lol.
Ty for seeing it :'p
Reply
#12

Got some questions about this lately, so I'm bumping my old topic, lol.

*B*U*M*P*
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)