[Tutorial] How to make a /goto and /gethere command for newbies!
#1

Hello all! So I have noticed a lot of people here are newbies and I haven't seen a roper tutorial on /goto and /gethere. So I now present to you how to make the two commands!

First, we need to download a plugin and include called sscanf. What this does is takes text you entered after your command in SA-MP (for example /ban [ID] [REASON]). You can also use strtok (stands for string token) but I find it too confusing and you might too. Another include we need is ZCMD. This makes command easier. Instead of finding your "OnPlayerCommandText" and typing
pawn Код:
if(strcmp(cmdtext,"/mycommand",true)==0)
you only need to type
pawn Код:
CMD:mycommand(playerid)
or if you are using sscanf (which is strtok simplified) you can type
pawn Код:
CMD:mycommand(playerid,params[])
. This makes scripting much easier.

First, we need to download sscanf and ZCMD. To download sscanf please go here. To download ZCMD please go here. Each will have install instructions in them.

Next, we need to add some stock code to the bottom of your game mode/filterscript.

pawn Код:
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
                    num = 0,
                    ch = string[stringPos];
                do
                {
                    stringPos++;
                    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;
                        }
                    }
                }
                while ((ch = string[stringPos]) > ' ' && ch != delim);
                setarg(paramPos, 0, num);
            }
            case 'c':
            {
                setarg(paramPos, 0, string[stringPos++]);
            }
            case 'f':
            {

                new changestr[16], changepos = 0, strpos = stringPos;
                while(changepos < 16 && string[strpos] && string[strpos] != delim)
                {
                    changestr[changepos++] = string[strpos++];
                    }
                changestr[changepos] = '\0';
                setarg(paramPos,0,_:floatstr(changestr));
            }
            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;
}
I would explain this but I honestly have no idea exactly what it is since I did not make it. Next, at the top of your script under where it says
Код:
 #include <a_samp>
please put
pawn Код:
#include <zcmd>
. This will make it so you can write the commands with
Код:
 CMD:my command(playerid,params[])
. Now we will get to the real script writing. Now I am going to do this in parts so people don't just copy and paste.

First, we need to define the command. Anywhere besides any
pawn Код:
public
functions (in example public OnPlayerCommandText), put
pawn Код:
CMD:goto(playerid,params[])
Let me explain this. Of course you have the command WITHOUT the "/". Playerid means it gets the ID of the player initiating the command. Params is what records the ID that you enter to teleport to.

Next you need to type,
pawn Код:
{
new pname[MAX_PLAYER_NAME],aname[MAX_PLAYER_NAME],string[128],id; /*Creates the player's name to teleport to, and the admin that initiated the command, and the target ID to teleport to.*/
if(!IsPlayerAdmin(playerid)) == 0) /*Checks if the player is logged into RCON. If your script has its own admin system use that.*/
Next, we need to type,
pawn Код:
{
if(sscanf(params,"u",id)) SendClientMessage(playerid, 0xAA3333AA, "/goto <id>"); /*Takes the ID you entered and makes it the "id" we defined. If no ID is entered the error message shows up*/
if(playerid == id) return SendClientMessage(playerid, 0xAA3333AA, "You can't teleport to yourself..."); /*Checks if the player id entered is not yours and if it is it shows the error message*/
Wow that was a lot so far. For the players that don't understand maybe you do now. Now, we need to type,
pawn Код:
else {
if(!IsPlayerConnected(id)) SendClientMessage(playerid, 0xAA3333AA, "Player is Not Online"); /*Checks if the ID entered is a player that is online in the server, otherwise sends the error message*/
else {
new Float:x,Float:y,Float:z; //Defines the x,y, and z co-ordinates of the target player
GetPlayerPos(id,Float:x,Float:y,Float:z)://Sets what the x,y, and z means
GetPlayerName(id,pname,sizeof(pname)); //Gets the name of the player that is to be teleported to
SetPlayerPos(playerid,x,y,z);//Teleports the admin to the player's x,y, and z co-ordinates we set earlier
format(string,sizeof(string),"Teleported to %s!",pname);//Shows the admin they teleported to the player
SendClientMessage(playerid, 0xAA333AA, string);//^^
}
}
}
else return 0; //Sends the "SERVER: Unknown command" if the person wanting to teleport isn't an admin
return 1;
}
Okay so that was the /goto command. Now we need to make /gethere. Please do the following:

pawn Код:
CMD:gethere(playerid,params[])
{
new pname[MAX_PLAYER_NAME],aname[MAX_PLAYER_NAME],string[128],id; /*Creates the player's name to teleport to the admin, and the admin that initiated the command, and the target ID to teleport to the admin.*/
if(!IsPlayerAdmin(playerid)) == 0) /*Checks if the admin is logged into RCON. If your script has its own admin system use that.*/
if(sscanf(params,"u",id)) SendClientMessage(playerid, 0xAA3333AA, "/goto <id>"); /*Takes the ID you entered and makes it the "id" we defined. If no ID is entered the error message shows up*/
if(playerid == id) return SendClientMessage(playerid, 0xAA3333AA, "You can't teleport to yourself..."); /*Checks if the player id entered is not yours and if it is it shows the error message*/
else {
if(!IsPlayerConnected(id)) SendClientMessage(playerid, 0xAA3333AA, "Player is Not Online"); /*Checks if the ID entered is a player that is online in the server, otherwise sends the error message*/
else {
new Float:x,Float:y,Float:z; //Defines the x,y, and z co-ordinates of the admin
GetPlayerPos(id,Float:x,Float:y,Float:z)://Sets what the x,y, and z means
GetPlayerName(id,pname,sizeof(pname)); //Gets the name of the player that is to be teleported to the admin
SetPlayerPos(playerid,x,y,z);//Teleports the player to the admin's x,y, and z that was defined earlier
format(string,sizeof(string),"Teleported %s to you!",pname);//Shows the admin the player was teleported to them
SendClientMessage(playerid, 0xAA333AA, string);//^^
}
}
}
else return 0; //Sends the "SERVER: Unknown command" if the person wanting to initiate teleport isn't an admin
return 1;
}
I didn't separate the /gethere like i did with /goto because it is basically /goto backwards. So this is how to do it. If you have an admin script where you have your own admin checks (in example: if(UserFile[playerid][uAdminLevel] >=3) NOTE this is only an example) you can use those instead. If you have any errors please post them down below and I will check them when I can!

Thanks and happy scripting!

~Adam
Reply
#2

Bumpity bump bump. Newbies need to see this!
Reply
#3

pawn Код:
if(!IsPlayerAdmin(playerid)) == 0)
better remove the == 0
and fail it checks if player is not logged as rcon administrator.

you could just do

pawn Код:
if(!IsPlayerAdmin(playerid))
checks if player is not admin, if player is admin this function will not called

plus bad indentation

hope you read this!
2/10

EDIT:

also this one is fail

pawn Код:
if(playerid == id)
Are you crazy? did you copy/paste this from other?

this is the correct one

pawn Код:
if(id == playerid)
checks if the selected id is playerid. really really bad tutorial plus
you could just do

pawn Код:
if(id == INVALID_PLAYER_ID)
instead of IsPlayerConnected. sscanf supports what i give above ^^^
Reply
#4

This command works just fine for me. No I do not copy from others. I use 100% scripts that I make on my own without any help from other people. Just my knowledge of scripting. Now, if you want to continue to say how this doesn't work etc etc, you are not welcome unless you show errors.
Reply
#5

Quote:
Originally Posted by adampoconnor
Посмотреть сообщение
This command works just fine for me. No I do not copy from others. I use 100% scripts that I make on my own without any help from other people. Just my knowledge of scripting. Now, if you want to continue to say how this doesn't work etc etc, you are not welcome unless you show errors.
Then you should learn how to script before making commands. Also, he showed you the errors.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)