03.05.2009, 18:13
How to make basic commands
I've saw many people who are trying things who are just impossible. First of all,
I want to note that its good to try stuff. Thats why I made this tutorial, people can read this and learn from it.
Also it might be some assistance in creating commands. You might think that there already is something like this,
but so far I don't like the tutorial on the wiki because that just gives the commands. People just copy it and don't
learn anything from it, and that is not the goal of a tutorial.
Getting started
In this tutorial I will explain how to create simple commands by your own. The big meaning behind this is how to
create messages with strings and integers and such. If you do not know what I'm talking about, please read this.
The tutorial
The first step
I will use dcmd in this tutorial, because it is shorter, faster and more simple to use. More information regarding
this can be found here. Before we continue we need the
code of dcmd. Put this line in the beginning of your script, above "main()".
pawn Code:
#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
Define the command's name and length
To say the server what the command must be, we must use the following code in "OnPlayerCommandText(playerid,cmdtext[])".
pawn Code:
dcmd(cmd,3,cmdtext);
Creating the command
To say the server we're starting the command, we must use this.
Code:
dcmd_cmd(playerid,params[])
You have to open the command with brackets to define to the server we're going to put the code of the command here.
Indexing a variable and checking it for input
To a variable as params[] we have to make them connected to each other. This is called indexing. But watch out, this way is only for a command with one parameter. How to index commands with 2 or more parameters is explained in the next step.
pawn Code:
new action = strval(params);
The next thing isn't really required, but I'll just tell it.
pawn Code:
new action[128] = params;
This needs to be done at every command using 1 parameter.
Using strlen we can check if the person has entered the parameter correctly.
pawn Code:
if(!strlen(action)) return SendClientMessage(playerid,color,"You forgot to enter something!");
Now we're going to check it for input.
pawn Code:
if(!strlen(action))
{
SendClientMessage(playerid,color,"You forgot to enter something!");
return 1;
}
There you go, you just made your check against someone not filling in the command properly.
Indexing multiple variables and checking them for input
There are several ways to index multiple variables. I will only discribe the sscanf way, since sscanf is fast and easy.
This is the code of sscanf which you will need using this function. You can paste this anywhere in your script, except in a function or public.
pawn Code:
stock sscanf(string[], format[], {Float,_}:...)
{
#if defined isnull
if (isnull(string))
#else
if (string[0] == 0 || (string[0] == 1 && string[1] == 0))
#endif
{
return format[0];
}
#pragma tabsize 4
new
formatPos = 0,
stringPos = 0,
paramPos = 2,
paramCount = numargs(),
delim = ' ';
while (string[stringPos] && string[stringPos] <= ' ')
{
stringPos++;
}
while (paramPos < paramCount && string[stringPos])
{
switch (format[formatPos++])
{
case '\0':
{
return 0;
}
case 'i', 'd':
{
new
neg = 1,
num = 0,
ch = string[stringPos];
if (ch == '-')
{
neg = -1;
ch = string[++stringPos];
}
do
{
stringPos++;
if ('0' <= ch <= '9')
{
num = (num * 10) + (ch - '0');
}
else
{
return -1;
}
}
while ((ch = string[stringPos]) > ' ' && ch != delim);
setarg(paramPos, 0, num * neg);
}
case 'h', 'x':
{
new
ch,
num = 0;
while ((ch = string[stringPos]) > ' ' && ch != delim)
{
switch (ch)
{
case 'x', 'X':
{
num = 0;
continue;
}
case '0' .. '9':
{
num = (num << 4) | (ch - '0');
}
case 'a' .. 'f':
{
num = (num << 4) | (ch - ('a' - 10));
}
case 'A' .. 'F':
{
num = (num << 4) | (ch - ('A' - 10));
}
default:
{
return -1;
}
}
}
setarg(paramPos, 0, num);
}
case 'c':
{
setarg(paramPos, 0, string[stringPos++]);
}
case 'f':
{
setarg(paramPos, 0, _:floatstr(string[stringPos]));
}
case 'p':
{
delim = format[formatPos++];
continue;
}
case '\'':
{
new
end = formatPos - 1,
ch;
while ((ch = format[++end]) && ch != '\'') {}
if (!ch)
{
return -1;
}
format[end] = '\0';
if ((ch = strfind(string, format[formatPos], false, stringPos)) == -1)
{
if (format[end + 1])
{
return -1;
}
return 0;
}
format[end] = '\'';
stringPos = ch + (end - formatPos);
formatPos = end + 1;
}
case 'u':
{
new
end = stringPos - 1,
id = 0,
bool:num = true,
ch;
while ((ch = string[++end]) && ch != delim)
{
if (num)
{
if ('0' <= ch <= '9')
{
id = (id * 10) + (ch - '0');
}
else
{
num = false;
}
}
}
if (num && IsPlayerConnected(id))
{
setarg(paramPos, 0, id);
}
else
{
#if !defined foreach
#define foreach(%1,%2) for (new %2 = 0; %2 < MAX_PLAYERS; %2++) if (IsPlayerConnected(%2))
#define __SSCANF_FOREACH__
#endif
string[end] = '\0';
num = false;
new
name[MAX_PLAYER_NAME];
id = end - stringPos;
foreach (Player, playerid)
{
GetPlayerName(playerid, name, sizeof (name));
if (!strcmp(name, string[stringPos], true, id))
{
setarg(paramPos, 0, playerid);
num = true;
break;
}
}
if (!num)
{
setarg(paramPos, 0, INVALID_PLAYER_ID);
}
string[end] = ch;
#if defined __SSCANF_FOREACH__
#undef foreach
#undef __SSCANF_FOREACH__
#endif
}
stringPos = end;
}
case 's', 'z':
{
new
i = 0,
ch;
if (format[formatPos])
{
while ((ch = string[stringPos++]) && ch != delim)
{
setarg(paramPos, i++, ch);
}
if (!i)
{
return -1;
}
}
else
{
while ((ch = string[stringPos++]))
{
setarg(paramPos, i++, ch);
}
}
stringPos--;
setarg(paramPos, i, '\0');
}
default:
{
continue;
}
}
while (string[stringPos] && string[stringPos] != delim && string[stringPos] > ' ')
{
stringPos++;
}
while (string[stringPos] && (string[stringPos] == delim || string[stringPos] <= ' '))
{
stringPos++;
}
paramPos++;
}
do
{
if ((delim = format[formatPos++]) > ' ')
{
if (delim == '\'')
{
while ((delim = format[formatPos++]) && delim != '\'') {}
}
else if (delim != 'z')
{
return delim;
}
}
}
while (delim > ' ');
return 0;
}
On the top of the script we create the integers.
pawn Code:
new otherid, cash;
Now we make the actual check and index those integers. Note that we this time don't have to use the % in front of the placeholders!
pawn Code:
if(sscanf(params,"ddd",playerid,otherid,cash)) return SendClientMessage(playerid,red,"USAGE: /sendcash [playerid] [otherid] [cash amount]");
pawn Code:
if(sscanf(params,"ddd",playerid,otherid,cash))
{
SendClientMessage(playerid,red,"USAGE: /sendcash [playerid] [otherid] [cash amount]");
return 1;
}
Using variables
String
To use strings into each other, you need to create it first. Remember that a string is for text only. My suggestion is: keep the name
as short as possible. Because of one simple reason: you don't have to type that much.
pawn Code:
new str[128];
Integer
To create an integer, you don't need any sizes. An integer is just plain text.
pawn Code:
new int;
Put two variables into each other
In this example I'm going to put .. into one string. To continue you have to know some important things about converting it into one.
Below I have listed all the placeholders you need to use. I've left the unimportant ones away.
Placeholder What is it
%d integer (whole number)
%f float (0.0000 for example)
%i integer (one number, used for loops mostly)
%s string (text (and numbers))
%z optional string (text (and numbers))
%% "%" (inserts the %)
pawn Code:
format(str,sizeof(str),"%s(%d) %s",pname,playerid,action);
turn this into the following result.
Quote:
Originally Posted by Server Output
Neoz(0) action
|
Examples
To just give you an idea, you could also use this with arrays. I'll take as example a check if the player is spawned.
pawn Code:
format(str,sizeof(str),"Check if %s is spawned: %d (0 = no / 1 = yes)",pname,pSpawned[playerid]);
You can also do it with strings to return a nice output. If you like nice outputs, you can store "yes" and "no" in the string. Though, if you want to
use this, the creation of the variable will be a bit more difficult. If you want to read more about that, I suggest you read this.
If you have followed the steps correctly you should now have a begin of the command, with some coding.
Finish the command
To finish the command, you have to put a return 1; in order to stop executing. Also you need a closing bracket to tell the server that the command has ended.
If you haven't used the params[] and didn't index anything(this is common(when making a teleport for example)) you need to put this between "return 1;" and "}".
pawn Code:
#pragma unused params
Explained Examples
Example One: /me [action]
Defining the command at "OnPlayerText(playerid,cmdtext[])".
pawn Code:
dcmd(me,2,cmdtext);
pawn Code:
dcmd_me(playerid,params[]);
Create the string for the players name and the string for the text which shows up using /me.
pawn Code:
new pname[24], str[128];
pawn Code:
GetPlayerName(playerid,pname,24);
pawn Code:
if(!strlen(params)) return SendClientMessage(playerid,0xAA3333AA,"USAGE: /me [action]");
[pawno]format(str,sizeof(str),"%s %s",pname,action);[/pawn]
Sending the message to all the players and to the logs.
pawn Code:
SendClientMessageToAll(0xFFFF33AA,str);
print(str);
Example Two: /warn [playerid] [reason]
Defining the command at "OnPlayerText(playerid,cmdtext[])".
pawn Code:
dcmd(warn,4,cmdtext);
pawn Code:
dcmd_warn(playerid,params[]);
Creating the variables.
pawn Code:
new pname[24], oname[24], otherid, str[128], str2[128];
pawn Code:
GetPlayerName(playerid,pname,24);
GetPlayerName(otherid,oname,24);
pawn Code:
if(sscanf(params,"dz",otherid,reason)) return SendClientMessage(playerid,0xFF0000AA,"USAGE: /warn [playerid] [optional reason]");
pawn Code:
if(!IsPlayerConnected(otherid)) return SendClientMessage(playerid,0xFF0000AA,"That player isn't connected!");
pawn Code:
format(str,sizeof(str),"You warned %s. Reason: %s",oname,reason);
format(str2,sizeof(str2),"You got warned by %s. Reason: %s",pname,reason);
pawn Code:
SendClientMessage(playerid,0xFFFF33AA,str);
SendClientMessage(otherid,0xFFFF33AA,str2);
pawn Code:
printf("%s warned %s. Reason: %s",pname,oname,reason);
Final Word
I hope this tutorial helped you, at least assisted, in creating a command. If you got any questions, please ask them by PM so the topic keeps clean.
Bugs or mistakes
Please report any bugs or mistakes, because I'm busy with this tutorial for 3 hours already and I can't see more of it.
I'm willing to add more stuff in this tutorial if you have any suggestions.
Regards,
иєσz
иєσz