Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 12.09.2010
Converting STRCMP & STRTOK to ZCMD/DCMD & SScanF
Why am I making this?
Because most "noobs" don't know how to convert and because there's no tutorial on this yet AFAIK.
NOTE: ZCMD is the fastest command processor, so I recommend using it!
How:
STRCMP to DCMD&ZCMD:
This is really easy. The only differences are that zcmd and dcmd got "params".
Let's convert this easy command:
pawn Код:
if( !strcmp( cmdtext, "/suicide", true ))
{
new
szMessage[ 54 ],
pName[ MAX_PLAYER_NAME ];
GetPlayerName( playerid, pName, sizeof( pName ));
format( szMessage, sizeof( szMessage ), "(%i)%s just commited suicide.", playerid, pName );
SendClientMessageToAll( 0xFFFFFFFF, szMessage );
SetPlayerHealth( playerid, 0.0 );
return true;
}
First of all, for both ZCMD and DCMD, the command doesn't go under OnPlayerCommandText, but as a individual function. Cut it out, and paste outside any callback. On the bottom would be an example of where you can paste it.
Then, if you want DCMD, you need to put a line inside OnPlayerCommandText (zcmd doesn't require this)
pawn Код:
dcmd(command_name_here, length_of_command_excluding_the_slash, cmdtext);
Example:
pawn Код:
dcmd(suicide, 7, cmdtext); //suicide is the command, it's length is 7.
Next, we're going to start on the command itself.
Change:
pawn Код:
if( !strcmp( cmdtext, "/suicide", true ))
To:
pawn Код:
//dcmd:
dcmd_suicide(playerid, params[])
//zcmd:
CMD:suicide(playerid, params[])
When you don't use "params", DCMD will give you a warning, zcmd wont.
To get rid of this warning, put
after the bracket, like this:
pawn Код:
dcmd_mycommand(playerid, params[])
{
#pragma unused params
//rest of code
Let's take a look at our command now:
DCMD
pawn Код:
//onplayercommandtext
dcmd(suicide, 7, cmdtext);
pawn Код:
dcmd_suicide(playerid, params[] )
{
#pragma unused params
new
szMessage[ 54 ],
pName[ MAX_PLAYER_NAME ];
GetPlayerName( playerid, pName, sizeof( pName ));
format( szMessage, sizeof( szMessage ), "(%i)%s just commited suicide.", playerid, pName );
SendClientMessageToAll( 0xFFFFFFFF, szMessage );
SetPlayerHealth( playerid, 0.0 );
return true;
}
ZCMD
pawn Код:
CMD:suicide(playerid, params[])
{
new
szMessage[ 54 ],
pName[ MAX_PLAYER_NAME ];
GetPlayerName( playerid, pName, sizeof( pName ));
format( szMessage, sizeof( szMessage ), "(%i)%s just commited suicide.", playerid, pName );
SendClientMessageToAll( 0xFFFFFFFF, szMessage );
SetPlayerHealth( playerid, 0.0 );
return true;
}
That was easy, wasn't it?
Now let's try converting a command using strtok into dcmd/zcmd & sscanf!
Let's use this vehicle command for an example
pawn Код:
if( !strcmp( cmd, "/v", true ))
{
new
tmp[ 128 ],
vID,
pID,
Float:x,
Float:y,
Float:z;
tmp = strtok(cmdtext, idx);
if( !strlen( tmp ))
return SendClientMessage( playerid, 0xFFFF00FF, ”USAGE: /v [playerid] [vehicleid]” );
pID = strval( tmp );
tmp = strtok(cmdtext, idx);
if( !strlen( tmp ))
return SendClientMessage( playerid, 0xFFFF00FF, ”USAGE: /v [playerid] [vehicleid]” );
vID = strval( tmp );
if( vID < 400 || vID > 611 )
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid vehicle model!” );
else if( !IsPlayerConnected( pID ))
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid ID!” );
GetPlayerPos( pID, x, y, z );
GetXYInFrontOfPlayer( pID, x, y );
CreateVehicle( vID, x, y, z+0.5, 0.0, -1, -1, -1 );
return true;
}
This command spawns a vehicle with the desired model infront of the player with the desired playerid.
NOTE: I'm not making efficient code, but I'm not trying to either.
To convert this, we need to do the basics first.
If you use dcmd add
Then move the command out from OnPlayerCommandText, and change the first line so it works with zcmd and dcmd (as we did above).
After we've done that, we start converting the strtok to sscanf.
The code so far looks like this:
pawn Код:
dcmd_v(playerid, params[]) //or CMD:v(playerid, params[]) if you use zcmd
{
new
tmp[ 128 ],
vID,
pID,
Float:x,
Float:y,
Float:z;
tmp = strtok(cmdtext, idx);
if( !strlen( tmp ))
return SendClientMessage( playerid, 0xFFFF00FF, ”USAGE: /v [playerid] [vehicleid]” );
pID = strval( tmp );
tmp = strtok(cmdtext, idx);
if( !strlen( tmp ))
return SendClientMessage( playerid, 0xFFFF00FF, ”USAGE: /v [playerid] [vehicleid]” );
vID = strval( tmp );
if( vID < 400 || vID > 611 )
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid vehicle model!” );
else if( !IsPlayerConnected( pID ))
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid ID!” );
GetPlayerPos( pID, x, y, z );
GetXYInFrontOfPlayer( pID, x, y );
CreateVehicle( vID, x, y, z+0.5, 0.0, -1, -1, -1 );
return true;
}
Now let's start converting!
First of all, we don't need the variable called "tmp" anymore, so delete that.
Text, delete the part starting at "tmp = strtok(cmdtext, idx);" all the way down to the second "vID = strval( tmp );",
leaving us with this code:
pawn Код:
dcmd_v(playerid, params[]) //or CMD:v(playerid, params[]) if you use zcmd
{
new
vID,
pID,
Float:x,
Float:y,
Float:z;
if( vID < 400 || vID > 611 )
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid vehicle model!” );
else if( !IsPlayerConnected( pID ))
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid ID!” );
GetPlayerPos( pID, x, y, z );
GetXYInFrontOfPlayer( pID, x, y );
CreateVehicle( vID, x, y, z+0.5, 0.0, -1, -1, -1 );
return true;
}
If you want to check out the syntax on sscanf, search for it here on the forums, as I won't tell you how to do it.
Ok, first of all, we need to add the sscanf line, which is constructed fairly easy:
pawn Код:
if( sscanf( params, "ii", pID, vID )) //will return true if _NOT_ both parameters are typed in.
return SendClientMessage( playerid, 0xFFFF00FF, "USAGE: /v [playerid] [vehicleid]" );
Notice that these lines, does the same as the whole part we deleted from the strtok code, which obviously is easier and much faster.
And since those lines is all you need, you are already done!
Our code atm:
pawn Код:
dcmd_v(playerid, params[]) //or CMD:v(playerid, params[]) if you use zcmd
{
new
vID,
pID,
Float:x,
Float:y,
Float:z;
if( sscanf( params, "ii", pID, vID ))
return SendClientMessage( playerid, 0xFFFF00FF, "USAGE: /v [playerid] [vehicleid]" );
if( vID < 400 || vID > 611 )
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid vehicle model!” );
else if( !IsPlayerConnected( pID ))
return SendClientMessage( playerid, 0xFF0000FF, ”Invalid ID!” );
GetPlayerPos( pID, x, y, z );
GetXYInFrontOfPlayer( pID, x, y );
CreateVehicle( vID, x, y, z+0.5, 0.0, -1, -1, -1 );
return true;
}
Note that you won't need "#pragma unused params" when using dcmd, since "params" is being used.
I told you that I won't explain the sscanf part, but I decided I did a quick explanation:
The sscanf param check always starts with
What comes after depends on the command.
In my example, we use two integers as params.
Integers are represented by either "i" or "d", and that is why I put "ii" in the sscanf line.
What comes after "ii" is the variables you use to store those integer values.
In my example, that is pID and vID.
Other representants are
s - string
u - user (playerid or (part of) name)
f - float
x - hex
There are more, but those you have to check up yourself.
Go to:
https://sampwiki.blast.hk/wiki/Fast_Commands for more info about dcmd and sscanf.
I hope this "tutorial" helped you converting commands.
Good luck & Have fun!
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
mrcoolballs - 13.09.2010
great work,
you should explain how to do a command with multiple parameters, I seen there were a few people wondering about that.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
Not an option, since this is a converting tutorial, not a sscanf tutorial.
I added the link to the wiki page for dcmd & sscanf.
EDIT: Ty for the feedback, btw.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
Calgon - 13.09.2010
Nice work, your indentation is a bit... over the top, though.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
Define "over the top".
Everybody has their own ways, and I like it my way.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
Calgon - 13.09.2010
Quote:
Originally Posted by LarzI
Define "over the top".
Everybody has their own ways, and I like it my way.
|
True, and I used to follow that style of indentation... but it is kind of hard to interpret, with spaces literally everywhere.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
I use spaces so the code won't be so "packed", and imho easier to edit.
Much more easy to read too.
You may not like it, but I do. This isn't a C&P tutorial, it's a watch and learn. People make it their own way.
EDIT: Ty for the feedback, btw.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
playbox12 - 13.09.2010
Nice done, but wasen't sscanf 'U' for ID or NPC, and 'R' for players only.
And I use your way of indendation aswell, I agree its much easier to read.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
Quote:
Originally Posted by playbox12
Nice done, but wasen't sscanf 'U' for ID or NPC, and 'R' for players only.
And I use your way of indendation aswell, I agree its much easier to read.
|
According to ****** and personal experiences, 'u' = playerid or (part of)playername, but can also be NPC, which I don't know anything about.. yet.
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
playbox12 - 13.09.2010
Quote:
Originally Posted by LarzI
According to ****** and personal experiences, 'u' = playerid or (part of)playername, but can also be NPC, which I don't know anything about.. yet.
|
Then, why using 'u' I don't think you want to assign anything to a NPC ;P, but its a bit offtopic, so lets just stop it
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
I don't use 'u' in here...
But yeah, let's just stop it ^^ OT discussion goes in PMs c:
Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
[NoV]LaZ - 13.09.2010
Quote:
Originally Posted by LarzI
DCMD
pawn Code:
//onplayercommandtext dcmd( suicide, 7, cmdtext );
|
I use the same style of indentation like you, and noticed this will output an error if you put those spaces, unless you modify the dcmd define accordingly.
________
BMW CONCEPT 5 SERIES GRAN TURISMO HISTORY
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
LarzI - 13.09.2010
Quote:
Originally Posted by [NoV]LaZ
I use the same style of indentation like you, and noticed this will output an error if you put those spaces, unless you modify the dcmd define accordingly.
|
Ty for noticing that!
I actually know it, it's the same for the definition of functions and callbacks (and foreach) too.
Fixing it now
Re: Converting strcmp(+strtok) to dcmd/zcmd(+sscanf) -
Xer0maR - 18.01.2011
It gives me warning like this when I change from strcmp to zcmd
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\pawno\include\dutils.inc(285) : warning 219: local variable "tmp" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\pawno\include\dutils.inc(449) : warning 219: local variable "tmp" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\pawno\include\dini.inc(46) : warning 219: local variable "tmp" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\pawno\include\dini.inc(54) : warning 219: local variable "tmp" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1105) : warning 219: local variable "tmp" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1150) : error 010: invalid function or declaration
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1155) : error 017: undefined symbol "cmdtext"
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1163) : error 017: undefined symbol "cmdtext"
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1210) : warning 209: function "cmd_afk" should return a value
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1225) : warning 209: function "cmd_back" should return a value
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(123
: error 021: symbol already defined: "cmd_uzi"
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1904) : warning 219: local variable "pName" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(1936) : warning 219: local variable "pName" shadows a variable at a preceding level
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(2903) : warning 203: symbol is never used: "cmd"
E:\SA-MP Stuff\[Ask] Yourself\Ask FightClub GrAvE Zone\gamemodes\W9X.pwn(2903) : warning 203: symbol is never used: "idx"
Pawn compiler 3.2.3664 Copyright © 1997-2006, ITB CompuPhase
4 Errors.