[Tutorial] [Basics] Making Commands with Parameters [ZMCD && Sscanf]
#1

Making Commands with Parameters!
A Tutorial by Mosslah.

A lot of people usually pop up the question here and there with how to make commands with parameters, and how to create parameters within the original parameter for that command, so here it goes.

The first thing you want to do is create your command, the command we're going to be basing this around is a simple command that may have usage in some servers, but for this tutorial, it'll just guide you through the steps.

Inside this Tutorial!
- Building the basics of a command.
- Adding parameters to a basic command.
- Adding parameters within parameters.
- Creating a simple /give money command, with parameters.
- String usage (not detailed, as there are plenty of string tutorials out there).

Building the Basics!
So, let's type our command out using sscanf and zcmd (if you don't have these, then you should download them right away as they are two of the best components for any script at the moment). We'll add the regular includes at the top, and two colours that we're going to define.

pawn Code:
#include <a_samp>
#include <zcmd>
#include <sscanf2>

#define COLOR_WHITE 0xFFFFFFAA
#define COLOR_RED 0xAA3333AA

COMMAND:give(playerid, params[])
{
    return 1;
}
So this is our basic command, and currently it does absolutely nothing. So let's start by adding the extremely important line, which will be our sscanf line.

pawn Code:
COMMAND:give(playerid, params[])
{
    new option[10];
   
    if(sscanf(params, "s[10]", option)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give [money | weapon]");
    return 1;
}
There are two methods in which you can return the uses of the actual command, you can either return the usage beneath it, or just return after the command like the example shown above.

The "new option[10];" is us adding the variable which is the 'option' part of our sscanf line. This is needed otherwise PAWNO will return an error, and also; the command will not work if it is not mentioned in the script. The [10] after the variable is the maximum amount of characters allowed in the string which follows the command, and is also added after the "s" in the sscanf line (the s stands for string, see: Sscanf). We've now got everything we need to start adding the actual functions of the command, and begin to create the parameters.

Creating the Options!
Let's begin by adding the two parameters which we want to add in to our /give command, which are "money" and "weapon". We do this by utilizing strcmp, which compares two strings to see if they are the same, and it is what we will be using for our parameters.

We're going to add our parameters, starting in the same column as our sscanf line.

pawn Code:
COMMAND:give(playerid, params[])
{
    new option[10];
   
    if(sscanf(params, "s[10]", option)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give [money | weapon]");

    if(!strcmp(option, "money", true))
    {
        return 1;
    }
   
    if(!strcmp(option, "weapon", true))
    {
        return 1;
    }
    return 1;
}
Let's break this down:

pawn Code:
if(!strcmp(option, "money", true))
Here, we are checking if the string "money" was written after typing the command /give, we're then checking if it's true and proceeding to the lines below it. "Option" comes from the variable which we added earlier, and is needed otherwise it will return errors.

Now we have the two parameters inside of our command, but again; they do nothing. However, to complicate this even further, we're now going to be adding parameters inside of our previous parameters (It's not as confusing as it seems).

Adding Parameters Within Parameters!
Giving a player money, or a weapon, cannot just be done with the command that we've previously made, it has to have it's own command inside of it. So, now we're going to build the parameters for our first parameter, "money".

We'll start in the same way that we started the initial command, adding a sscanf function to add our new parameters.

pawn Code:
if(!strcmp(option, "money", true))
    {
        new TargetID,
            Cash;
           
        if(sscanf(params, "ui", TargetID, Cash)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give money [PlayerID] [Cash]");
        return 1;
    }
You'll probably notice that we've followed almost exactly the same format. We've added two new variables to store our playerid, and our money (cash) in, and we've added them into sscanf. You'll notice that we have two completely different format codes: "u" and "i". "U" is a user, and uses an ID or a name. While "i" is an integer, and takes a numerical value, which will be our cash.

We're then going to check if the playerid that was added into the command actually exists, and someone hasn't just entered a random ID of a player that is not actually online, we do this by using:

pawn Code:
if(TargetID == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Invalid Player ID!");
The "TargetID" that we added earlier is now being checked to see if the ID entered in its place actually exists.

We're now going to repeat this process (not exactly) for the weapon part of our /give command, see if you can do it yourself first, and then check with the part below if you managed to do it correctly!

Hopefully, you should have this:

pawn Code:
if(!strcmp(option, "weapon", true))
    {
        new TargetID;
       
        if(sscanf(params, "u", TargetID)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give weapon [PlayerID]");
        {
            if(TargetID == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Invalid Player ID!");
           
            return 1;
        }
    }
The reason we have to add TargetID once again is because the original TargetID was inside of the money parameter, if you wish to add "TargetID" throughout the entire command without having to add it over and over for each command, then add it beneath the initial "new option[10]" line that we created at the very start.

Again, we're following the same steps by checking if the ID is valid.

Now that this is done, we've pretty much created our parameters - but we still need to build a command. I'm going to quickly jump through a basic pay command inside of this parameter, for those of you who may wish to use this in your own script(s). It's simple really, and is basic PAWNO knowledge.

Creating Our Actual Commands!
So let us start off with the money parameter that we created. We're firstly going to check if the player has the right amount of cash, and then we're going to send that cash to the other player with two strings so that both players know what has happened - to avoid confusion.

We're going to start off by checking if the numerical value entered under the "Cash" variable is actually cash that the player who did the command has, we're going to do this simply with a single line:

pawn Code:
if(GetPlayerMoney(playerid) < Cash) return SendClientMessage(playerid, COLOR_RED, "You do not have that much money!");
GetPlayerMoney is a function already built into SAMP, and can be used simply as GetPlayerMoney(playerid), but we're going to check if the money actually matches the Cash value, so we're using it in that method.

So, let's create some new variables for our strings and names, and we'll start with making the strings.

pawn Code:
new paystring[128],
                paidstring[128],
                player[MAX_PLAYER_NAME],
                target[MAX_PLAYER_NAME];
These can be named whatever you like, however I like to keep mine simple and easy to remember later on without checking back, so keep them simple and short and you shouldn't have any confusion later on.

Building the string:

Getting the names, and storing them into our variables:

pawn Code:
GetPlayerName(playerid, player, sizeof(player));
GetPlayerName(TargetID, target, sizeof(target));
Formatting the strings that we created, and implementing the names and the Cash from the original command into them:

pawn Code:
format(paystring, sizeof(paystring), "You have given $%i to %s.", Cash, target);
format(paidstring, sizeof(paidstring), "%s has paid you %i.", player, Cash);
Sending the strings to each player:

pawn Code:
SendClientMessage(playerid, COLOR_WHITE, paystring);
SendClientMessage(TargetID, COLOR_WHITE, paidstring);
Then, taking the money from our player and giving it too our target:

pawn Code:
GivePlayerMoney(playerid, -Cash);
GivePlayerMoney(TargetID, Cash);
And that's it! Your money parameter of your give command is now finished, and ready to use! Now, take a shot at creating your own give weapon command using the functions found on the SA-MP Wiki site, and test it out for yourself!

On completion, your code should now look like this:

pawn Code:
#include <a_samp>
#include <zcmd>
#include <sscanf2>

#define COLOR_WHITE 0xFFFFFFAA
#define COLOR_RED 0xAA3333AA

COMMAND:give(playerid, params[])
{
    new option[10];
   
    if(sscanf(params, "s[10]", option)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give [money | weapon]");

    if(!strcmp(option, "money", true))
    {
        new TargetID,
            Cash;
           
        if(sscanf(params, "ui", TargetID, Cash)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give money [PlayerID] [Cash]");
        {
            if(TargetID == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Invalid Player ID!");
           
            if(GetPlayerMoney(playerid) < Cash) return SendClientMessage(playerid, COLOR_RED, "You do not have that much money!");
           
            new paystring[128],
                paidstring[128],
                player[MAX_PLAYER_NAME],
                target[MAX_PLAYER_NAME];

            GetPlayerName(playerid, player, sizeof(player));
            GetPlayerName(TargetID, target, sizeof(target));
            format(paystring, sizeof(paystring), "You have given $%i to %s.", Cash, target);
            format(paidstring, sizeof(paidstring), "%s has paid you %i.", player, Cash);
            SendClientMessage(playerid, COLOR_WHITE, paystring);
            SendClientMessage(TargetID, COLOR_WHITE, paidstring);
            GivePlayerMoney(playerid, -Cash);
            GivePlayerMoney(TargetID, Cash);
            return 1;
        }
    }
   
    if(!strcmp(option, "weapon", true))
    {
        new TargetID;
       
        if(sscanf(params, "u", TargetID)) return SendClientMessage(playerid, COLOR_RED, "USAGE: /give weapon [PlayerID]");
        {
            if(TargetID == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_RED, "Invalid Player ID!");
            // Your own weapon code here.
            return 1;
        }
    }
    return 1;
}
And there you have it. You may manipulate, change, and add to this code as you wish. Base your own commands on this tutorials, but follow the same principles - and replace the parts that you don't need with the parts that you do need.

Final Words!
Thank you reading, and please don't critique too much; this is my first tutorial, and the reason I wrote this was because when I first started scripting, I was never told how to create commands with parameters through a simple tutorial - and instead, I had to learn myself by messing around with a few things from sscanf.

I hope that people will actually use this and I intend to create more in the future, on much more useful things rather than something as basic as this, but we all start some where - both tutorial makers, and scripters.

Once again; thanks for reading!
Reply
#2

Very well explained!
Reply
#3

is very well explained,i am a beginer and after i compile in Pawno what i must to do for this working?
Reply
#4

Test it on your own server, it's very easy to start a server (a bare one to test scripts) with SAMP, and there are a number of guides on the forums that help you with this. Just change your samp.cfg accordingly, and then start the server via the .exe and connect!

You may need to port forward, too.

@FireCat: Thanks!
Reply
#5

Very nice, very useful, espacially the sscanf part, is much more easy than params. Exelent Tutorial, +rep-
Reply
#6

woah, you toke a very simple command and made it complex including the usage of other functions, very nice 10/10.
Reply
#7

Nice Tutorial.
Reply
#8

You deserve 2 reputations for this tutorial! Very nicely explained. Very nicely written. Comprehensible. A thing which is not explained is this.
pawn Code:
COMMAND:give(playerid, params[])
You should explain what the argument does and what is params[].
Reply
#9

Thank you for the comments, everybody!

@T0pAz

Yeah, I should of actually commented about that. I'll be sure to edit it in, thank you.
Reply
#10

Wow, good tutorial since a long time! Also, everything explained.
I'd expect to see more of tutorials like this from you.
Reply
#11

This is nice, well i don't use parameters but i think it will be useful for me for some commands i will make. Nice job btw and fix the title (you entered ZMCD and should be ZCMD)
Reply
#12

Ah, yeah, thanks. Fixed it!
Reply
#13

Instead of creating two strings, you can format, send, then format and send again, no need for two of them.
Reply
#14

I used to use that method but it affected how I presented my script, so instead of having the format, and then the send line, I decided to bunch them together into separate blocks. It's more of a personal preference, I guess.
Reply
#15

Good evening!

I've used your tutorial to do the following command but somehow, somewhere, i've failed:

pawn Code:
CMD:phone(playerid, params[])
{
    new cmd[6];
    if(sscanf(params,"s[6]", cmd))
    {
        SendClientMessage(playerid, COLOR_WHITE, "USAGE: /phone <cmd>");
        SendClientMessage(playerid, COLOR_WHITE, "COMMANDS: call <number>, answer, hangup, toggle, sms <number> <text>");
    }
    else if(PlayerInfo[playerid][pPhone] == 0) return SendClientMessage(playerid, COLOR_RED, "You don't have a phone!");
    else if(!strcmp(cmd, "call", true))
    {
        new phonenumber;
        if(sscanf(params, "i", phonenumber)) return SendClientMessage(playerid, COLOR_WHITE, "USAGE: /phone call <number>");
        else
        {
            format(gString, sizeof(gString), "** You are calling: %d **", phonenumber);
            SendClientMessage(playerid, COLOR_DARK_RED, gString);
            foreach (Player, i)
            {
                if(PlayerInfo[i][pPhone] == phonenumber && i != playerid)
                {
                    SpeakingWith[playerid] = i;
                    SpeakingWith[i] = playerid;
                    format(gString, sizeof(gString), "%s's phone rings.", RemoveUnderScore(i));
                    SendLocalMessage(i, COLOR_ACTION, gString, 15.0);
                    format(gString, sizeof(gString), "** You are being called by: %d **", PlayerInfo[playerid][pPhone]);
                    SendClientMessage(i, COLOR_DARK_RED, gString);
                    SendClientMessage(i, COLOR_WHITE, "HINT: Type /phone answer to talk or /phone hangup to reject the call.");
                    return 1;
                }
            }
            SendClientMessage(playerid, COLOR_DARK_RED, "** Busy tone **");
        }
    }
    else
    {
        SendClientMessage(playerid, COLOR_WHITE, "COMMANDS: call <number>, answer, hangup, toggle, sms <number> <text>");
    }
    return 1;
}
When I type /phone call 123456 it's says

Quote:

USAGE: /phone call <number>

Can you please tell me what am I doing wrong?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)