Explanation for sscanf2 and ZCMD -
admantis - 27.02.2011
Introduction
Tired of these newbies using strcmp along with strtok. When will they learn? They say it's too hard to learn sscanf2 and zcmd. I thought it was hard too, but I had to focus, take a coffee and look the code. I learnt it in 2 minutes. I will teach you how to use ZCMD as COMMAND PROCESSORS and with sscanf2 to help us to split the parameters.
What we will need?
For this tutorial you need to download the plugin sscanf2 and the include zcmd
Sscanf2:
http://forum.sa-mp.com/showthread.ph...hlight=sscanf2
Zcmd:
http://forum.sa-mp.com/showthread.ph...highlight=zcmd
There is also a function version of sscanf2, no need to download anything just copy & paste in your gamemode it and sscanf2 is ready to go, but it's slow, probably just slow as strtok so for your own good im not posting it.
Remember zcmd can be implemented in apart functions so they should NOT be inside any callback, so if you are not going to use strcmp to process commands you can delete 'OnPlayerCommandText' as we won't use it
Let's get to work
To make a basic command without parameters, you will first see this.
pawn Код:
COMMAND:heal(playerid, params[]) // 'heal' is the command, so you type /heal and this will be called
{
SetPlayerHealth( playerid, 100.00 ); // Set players health
return true; // Returning a value is VERY important ! Your commands won't work if you don't do so
}
It works the SAME way as strcmp command just change the start to COMMAND:...., and code like you would always do in PAWN.
However, if you want to heal
other player, the thing gets more complex.
pawn Код:
COMMAND:healplayer(playerid, params[]) // hence we've changed to 'healplayer'
{
new id; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others.
if (sscanf(params, "u", id)) return SendClientMessage(playerid,0xFFFFFFFF, "Incomplete input");
SetPlayerHealth(id, 100.00);
return 1;
}
Now the explanation
pawn Код:
if (sscanf(params, "u", id)) return SendClientMessage(playerid,0xFFFFFFFF, "Incomplete input");
As first, we need to put always that to split the parameters, if they weren't there it will return something (in this case 'Incomplete value' error.
In every command, it should be "if (sscanf(params," untill that point. Then you will need to choose a operator. Where "u" means a playerid OR a part of a name.
We can also use "q" and "r" for player names / ids.
We use "i" or "d" for numbers.
We use "s[size]" for strings.
We use "x" for hexadecimals
We use "f" for floats (health, positions and armour)
More operators can be also found in the official sscanf2 thread.
Also it's important to contain the parameters after the operators.
For example, a common mistake is to copy paste the previous command, and change the functions to make it a different command, but if this command has more parameters it will fail.
Example:
pawn Код:
COMMAND:healplayer(playerid, params[]) // hence we've changed to 'healplayer'
{
new id, Float:ammount; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others.
if (sscanf(params, "uf", id)) return SendClientMessage(playerid,0xFFFFFFFF, "Incomplete input");
SetPlayerHealth(id, ammount);
return 1;
}
Do you spot the error? I do, do you? Probably not.
pawn Код:
new id, ammount; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others.
if (sscanf(params, "uf", id)) return SendClientMessage(playerid,0xFFFFFFFF, "Incomplete input");
Here it checks if 'id' is not put, but what about 'ammount'? If you don't put the 'id' parameter it will say Incomplete input, but if you don't put ammount it will keep processing, and probably cause a bug. Therefore, the right usage is.
pawn Код:
COMMAND:healplayer(playerid, params[]) // hence we've changed to 'healplayer'
{
new id, ammount; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others.
if (sscanf(params, "uf", id, ammount)) return SendClientMessage(playerid,0xFFFFFFFF, "Incomplete input");
SetPlayerHealth(id, ammount);
return 1;
}
While you more play with it, you will learn HOW easy it's to deal with.
After you've defined the parameters and used sscanf to check them, theire automatically READY TO USE!
Now let's make a /report command for our final challenge.
If you don't understand, please don't go further and re-read.
pawn Код:
COMMAND:report(playerid, params[])
{
new id, reason[128]; // Strings are usually text, and they need a size. Make them 128, NOT 256!
if (sscanf(params, "us[128]", id, reason)) return SendClientMessage(playerid, 0xFFFFFFFF,"report > incorrect usage");
new string[128]; // you should know how to work with strings already
format(string, 128, "report > you've reported playerid %i for %s", id, reason); // we format it
SendClientMessage(playerid, 0xFFFFFFFF, string); // and we send the string
return true;
}
This will make a 'fake' report message, just saying you report someone for a specific reason but it doesn't send a message to admins. Just a example.
pawn Код:
if (sscanf(params, "us[128]", id, reason)) return SendClientMessage(playerid, 0xFFFFFFFF,"report > incorrect usage");
Why it says a [128]?. When dealing with sscanf, you need to specify string sizes, or it will return a warning in RCON console and it will spam your console. Also it will have to match with string size declaration.
You can't have this:
pawn Код:
new string[32];
if (sscanf(params, "s[64]")) return 1;
Since 64 is not 32.
Also remember you
can't use OnPlayerCommandText when you use shis system
That's all for now
I hope you've enjoy and learnt from my tutorial.
Made by Admantis.
Re: Explanation for sscanf2 and ZCMD -
Hal - 27.02.2011
Very nice work, I will sure be linking people here, who have no clue how to use these tools.
Re: Explanation for sscanf2 and ZCMD -
Retardedwolf - 27.02.2011
I heard YCMD was faster than zcmd.
Re: Explanation for sscanf2 and ZCMD - [L3th4l] - 27.02.2011
Quote:
Originally Posted by Retardedwolf
I heard YCMD was faster than zcmd.
|
zcmd: "clean, easy to read, short and efficent command processor"
Not bad, will help lot of newbies.
Re: Explanation for sscanf2 and ZCMD -
Hiddos - 27.02.2011
About time someone posted a (decent) tutorial on this, though a few things:
1. Like RetardedWolf said, YCMD is faster then ZCMD. Nor is sscanf a command processor
2. This code:
pawn Код:
new id, ammount; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others.
if (sscanf(params, "uf", id, ammount))
'amount' is an integer, but you try to store a float in it.
3. You forgot to post that you can't use OnPlayerCommandText anymore when using ZCMD, you could also explain something about OnPlayerCommandReceived and OnPlayerCommandPerformed.
Re: Explanation for sscanf2 and ZCMD -
admantis - 27.02.2011
Quote:
Originally Posted by Hiddos
About time someone posted a (decent) tutorial on this, though a few things:
1. Like RetardedWolf said, YCMD is faster then ZCMD. Nor is sscanf a command processor
2. This code:
pawn Код:
new id, ammount; // Here we will define ALL our parameters like 'id', 'heal ammount', 'reason', and others. if (sscanf(params, "uf", id, ammount))
'amount' is an integer, but you try to store a float in it.
3. You forgot to post that you can't use OnPlayerCommandText anymore when using ZCMD, you could also explain something about OnPlayerCommandReceived and OnPlayerCommandPerformed.
|
Sorry about my errors, but I meant zcmd as the processor and sscanf2 as the tool to split the parameters.
Also that code 'ammount' is meant to be a float, because armour ammounts are floats, not integers.
Re: Explanation for sscanf2 and ZCMD -
Calgon - 27.02.2011
You spell "amount" incorrectly, and you show this example:
pawn Код:
new string[64];
if (sscanf(params, "s[32]")) return 1;
There's no point in using sscanf if you're just parsing one value (that isn't a userid/name) as you can use strval(params) or just directly use the params variable.
Re: Explanation for sscanf2 and ZCMD -
admantis - 27.02.2011
Quote:
Originally Posted by Calg00ne
You spell "amount" incorrectly, and you show this example:
pawn Код:
new string[64]; if (sscanf(params, "s[32]")) return 1;
There's no point in using sscanf if you're just parsing one value (that isn't a userid/name) as you can use strval(params) or just directly use the params variable.
|
Of course. I just gave a quick example, but thanks for pointing that out.
Re: Explanation for sscanf2 and ZCMD -
Miguel - 27.02.2011
Quote:
Originally Posted by admantis
Introduction
You can't have this:
pawn Код:
new string[64]; if (sscanf(params, "s[32]")) return 1;
Since 64 is not 32.
|
You CAN do that, since the size you have to specify is not the size of the array but the size of the input you are expecting to go through the function. In both cases, if the size of the input is greater than the size you specified, the server console will give you a warning.
Quote:
Originally Posted by admantis
Sorry about my errors, but I meant zcmd as the processor and sscanf2 as the tool to split the parameters.
Also that code 'ammount' is meant to be a float, because armour ammounts are floats, not integers.
|
It should be:
Re: Explanation for sscanf2 and ZCMD -
admantis - 27.02.2011
Oh right lol I didn't realise, I edit it.