27.08.2012, 12:25
(
Последний раз редактировалось Roko_foko; 27.08.2012 в 13:28.
)
Introduction
Hello dear readers! In this tutorial I will try to show you my way of making commands.
I saw a lot of people complaining about strcmp and strtok speed. But in this scripting language it’s not hard to avoid strtok(what I think used the most time). In my opinion speed of this will be very fast. As I already said, I think, it’s fast and I hope experts in this field will comment the speed of it and and tell us if it is better or worse than other command systems as ZCMD,YCMD, or any else.
For me, the best way of understanding things about programming is trough examples.
That’s the reason I will try to teach you by making three commands. One “easy” one a “medium” and one “hard”,
Easy command (/suicide)
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
if(!strcmp(cmdtext,"/suicide",true,8) && !cmdtext[8])
{
SendClientMessage(playerid,COLOR_ORANGE,"Server:{FFFFFF} It's ilegal to use this function to avoid being arrested, killed, etc.");
SetPlayerHealth(playerid,0);
return 1;
}
return 0;
}
1)
pawn Код:
!strcmp(cmdtext,"/suicide",true,8)
truth ( anything expect 0)) .
2)
pawn Код:
&& !cmdtext[8]
3)
pawn Код:
SendClientMessage(playerid,COLOR_ORANGE,"Server:{FFFFFF} It's ilegal to use this function to avoid being arrested, killed, etc.");//sending message to command user.
SetPlayerHealth(playerid,0);//Killing player
return 1;// command is done well.
Medium command (/report)
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
if(!strcmp("/report", cmdtext, true, 7))//first 7 char are /,r,e,p,o,r,t. Note that here we don't expect that on 8th place is EOS.
{
if(!cmdtext[7])return SendClientMessage(playerid,0xFFFFFF,"Ussage: /report [Text]");//if on the 8th place is EOS send usage message.
if(cmdtext[7]==' ')// in case 8th char is space execute the command
{
new i;//defining a variable
for(i=8;cmdtext[i]==' ';i++){}//checking if there are more spaces after 8th char. If so, we will cut that from message that is sent to admins.
if(!cmdtext[i])return SendClientMessage(playerid,0xFFFFFF,"Ussage: /report [Text]");//if first char after space(s) is EOS stop the execution and send the usage message.
new String[128+MAX_PLAYER_NAME];//declaring new variable
GetPlayerName(playerid,String,MAX_PLAYER_NAME);//getting name of the reporter and storing it in String.
format(String,128+MAX_PLAYER_NAME,"%s[%d] reporting: %s",String,playerid,cmdtext[i]);//Constructing the report message. cmdtext[i] is usually one char. But his time it is string( part of cmdtext with start from i-pos and end with EOS)
for(i=0;i<MAX_PLAYERS;i++)if(IsPlayerConnected(i)&& !IsPlayerNPC(i))//looping all players that could be admins
{
if(IsPlayerAdmin(i) /* AdminLevel[i]>0*/)//checking if they are admins
{
SendClientMessage(i,0xFF0000,String);//sending the message to admins
}
}
SendClientMessage(playerid,0x00FFFF,"Report sent.");
return 1;
}
}
return 0;
}
Hard command (/pay)
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
if(!strcmp(cmdtext,"/pay",true,4))//first 4 chars: /, p, a, y
{
if(!cmdtext[4])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if there is nothing after /pay
if(cmdtext[4]==' ')//if there is space after /pay
{
new i,j;//defining variables
for(i=5;cmdtext[i]==' ';i++){}//cutting not-needed spaces also finding first char after spaces( first char of the word that comes after spaces )
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");// if after spaces comes EOS - stop the command
for(j=i+1;cmdtext[j]!=' ';j++)if(!cmdtext[j])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//finding the last char in the word. If loop finds EOS before space that means third parameter of the command isn't inputted - stop command.
new Str[MAX_PLAYER_NAME];//defining a string
strmid(Str,cmdtext,i,j);//inserting word into Str
new id=GetIdOfPartOfNameOrId(Str);//as Function says. The function is below
if(id==-1)return SendClientMessage(playerid,COLOR_RED,"Server: There are more players with that name.");
if(id==-2)return SendClientMessage(playerid,COLOR_RED,"Server: That player doesn't exist.");
if(id==playerid)return SendClientMessage(playerid,COLOR_RED,"Server: You cannot pay yourself!");
for(i=j+1;cmdtext[i]==' ';i++){}//after finding id of player we want to cut space(s) after the Id or PlayerName
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if after spaces comes EOS - stop the command
if(IsNumber(cmdtext[i]))// checking if string (part of cmdtext with beggining at i-pos) is number, positive one
{
new amount=strval(cmdtext[i]);//converting string into integer
if(amount>gPlayerCash[playerid])SendClientMessage(playerid,COLOR_RED,"Server: You don't have that much money!");// does player have that amount of money?
else
{
gPlayerCash[playerid]-=amount;// decreasing player's cash by the amount
gPlayerCash[id]+=amount;//increasing player's cash by the amount
ShowPlayerMoney(id);//showing player his money
new String[MAX_PLAYER_NAME+60];//defining a string
format(String,sizeof(String),"takes out %s wallet and gives some ammount of cash to %s.",(gPlayerSex[playerid][0]=='M')?("his"):("her"),RealisticName(gPlayerCharName[id]));
//^^making message that will be sent to players around. Same as /me
SendTextToNearlyPlayers(playerid, String, ME);//sending message
PlayAnimEx(playerid, "DEALER", "shop_pay", 4.0, 1, 0, 0, 0, 0, 1);//animation
}
ShowPlayerMoney(playerid);
}
else SendClientMessage(playerid,COLOR_RED,"Server: The paying amount must be numeric!");
return 1;
}
}
return 0;
}
One more thing
And, one thing more. To make it faster I and one friend of mine( Alex ) came up with this idea. On the beginning of the OnPlayerCommandText make a >>CommandTeleport<<.
To make it, you first need to sort all commands in alphabet order.
After that, add this on the beginning of the OnPlayerCommandText.
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
switch(cmdtext[1])
{
case 'a','A':goto CmdA;
case 'b','B':goto CmdB;
case 'c','C':goto CmdC;
case 'd','D':goto CmdD;
case 'e','E':goto CmdE;
case 'f','F':goto CmdF;
case 'g','G':goto CmdG;
case 'h','H':goto CmdH;
case 'i','I':goto CmdI;
case 'j','J':goto CmdJ;
case 'k','K':goto CmdK;
case 'l','L':goto CmdL;
case 'm','M':goto CmdM;
case 'n','N':goto CmdN;
case 'o','O':goto CmdO;
case 'p','P':goto CmdP;
case 'q','Q':goto CmdQ;
case 'r','R':goto CmdR;
case 's','S':goto CmdS;
case 't','T':goto CmdT;
case 'u','U':goto CmdU;
case 'v','V':goto CmdV;
case 'w','W':goto CmdW;
case 'x','X':goto CmdX;
case 'y','Y':goto CmdY;
case 'z','Z':goto CmdZ;
default: return 0;
}
CmdA:
//cmds that start with 'a' .( example /Auction)
CmdB
// cmds that start with 'b'.(example /breakdoor)
//etc
return 0;
}
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
switch(cmdtext[1])
{
case 'a','A':goto CmdA;
case 'b','B':goto CmdB;
case 'c','C':goto CmdC;
case 'd','D':goto CmdD;
case 'e','E':goto CmdE;
case 'f','F':goto CmdF;
case 'g','G':goto CmdG;
case 'h','H':goto CmdH;
case 'i','I':goto CmdI;
case 'j','J':goto CmdJ;
case 'k','K':goto CmdK;
case 'l','L':goto CmdL;
case 'm','M':goto CmdM;
case 'n','N':goto CmdN;
case 'o','O':goto CmdO;
case 'p','P':goto CmdP;
case 'q','Q':goto CmdQ;
case 'r','R':goto CmdR;
case 's','S':goto CmdS;
case 't','T':goto CmdT;
case 'u','U':goto CmdU;
case 'v','V':goto CmdV;
case 'w','W':goto CmdW;
case 'x','X':goto CmdX;
case 'y','Y':goto CmdY;
case 'z','Z':goto CmdZ;
default: return 0;
}
CmdP:
if(!strcmp(cmdtext,"/pay",true,4))//first 4 chars: /, p, a, y
{
if(!cmdtext[4])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if there is nothing after /pay
if(cmdtext[4]==' ')//if there is space after /pay
{
new i,j;//defining variables
for(i=5;cmdtext[i]==' ';i++){}//cutting not-needed spaces also finding first char after spaces( first char of the word that comes after spaces )
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");// if after spaces comes EOS - stop the command
for(j=i+1;cmdtext[j]!=' ';j++)if(!cmdtext[j])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//finding the last char in the word
new Str[MAX_PLAYER_NAME];//defining a string
strmid(Str,cmdtext,i,j);//inserting word into Str
new id=GetIdOfPartOfNameOrId(Str);//as Function says. The function is below
if(id==-1)return SendClientMessage(playerid,0xFF0000FF,"Server: There are more players with that name.");
if(id==-2)return SendClientMessage(playerid,0xFF0000FF,"Server: That player doesn't exist.");
if(id==playerid)return SendClientMessage(playerid,0xFF0000FF,"Server: You cannot pay yourself!");
for(i=j+1;cmdtext[i]==' ';i++){}//after finding id of player we want to pay cutting spaces
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if after spaces comes EOS - stop the command
if(IsNumber(cmdtext[i]))// checking if string is number, positive one
{
new amount=strval(cmdtext[i]);//converting string into integer
if(amount>gPlayerCash[playerid])SendClientMessage(playerid,0xFF0000FF,"Server: You don't have that much money!");// does player have that amount of money?
else
{
gPlayerCash[playerid]-=amount;// decreasing player's cash by the amount
gPlayerCash[id]+=amount;//increasing player's cash by the amount
ShowPlayerMoney(id);//showing player his money
new String[MAX_PLAYER_NAME+60];//defining a string
format(String,sizeof(String),"takes out %s wallet and gives some ammount of cash to %s.",(gPlayerSex[playerid][0]=='M')?("his"):("her"),RealisticName(gPlayerCharName[id]));
//^^making message that will be sent to players around. Same as /me
SendTextToNearlyPlayers(playerid, String, ME);//sending message
PlayAnimEx(playerid, "DEALER", "shop_pay", 4.0, 1, 0, 0, 0, 0, 1);//animation
}
ShowPlayerMoney(playerid);
}
else SendClientMessage(playerid,0xFF0000FF,"Server: The paying amount must be numeric!");
return 1;
}
}
CmdR:
if(!strcmp("/report", cmdtext, true, 7))//first 7 char are /,r,e,p,o,r,t. Note that here we don't expect that on 8th place is EOS.
{
if(!cmdtext[7])return SendClientMessage(playerid,0xFFFFFFFF,"Ussage: /report [Text]");//if on the 8th place is EOS send usage message.
if(cmdtext[7]==' ')// in case 8th char is space execute the command
{
new i;//defining a variable
for(i=8;cmdtext[i]==' ';i++){}//checking if there are more spaces after 8th char. If so we will cut that from message that is sent to admins
if(!cmdtext[i])return SendClientMessage(playerid,0xFFFFFFFF,"Ussage: /report [Text]");//if first char after space(s) is EOS stop the execution and send the usage message.
new String[128+MAX_PLAYER_NAME];//declaring new variable
GetPlayerName(playerid,String,MAX_PLAYER_NAME);//getting name of the reporter and storing it in String.
format(String,128+MAX_PLAYER_NAME,"%s[%d] reporting: %s",String,playerid,cmdtext[i]);//Constructing the report message
for(i=0;i<MAX_PLAYERS;i++)if(IsPlayerConnected(i)&& !IsPlayerNPC(i))//looping all players that could be admins
{
if(IsPlayerAdmin(i) /* AdminLevel[i]>0*/)//checking if they are admins
{
SendClientMessage(i,0xFF0000FF,String);//sending the message to admins
}
}
SendClientMessage(playerid,0x00FFFFFF,"Report sent.");
return 1;
}
}
CmdS:
if(!strcmp(cmdtext,"/suicide",true,8) && !cmdtext[8])
{
SendClientMessage(playerid,0xFF0000FF,"Server:{FFFFFF} It's ilegal to use this function to avoid being arrested, killed, etc.");
SetPlayerHealth(playerid,0);
return 1;
}
//strcmp checks if the two strings are equal( in this case ). If they are equal strcmp returns 0(lie, non-truth). With '!' we are telling program to make result opposite( if strings are equal strcmp will return true) .
//!cmdtext[8] is checking if on the 9th place in string is "End of string( aka EOS)" what's value is 0(lie).
//sending message to command user.
//Killing player
if(!strcmp(cmdtext,"/pay",true,4))//first 4 chars: /, p, a, y
{
if(!cmdtext[4])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if there is nothing after /pay
if(cmdtext[4]==' ')//if there is space after /pay
{
new i,j;//defining variables
for(i=5;cmdtext[i]==' ';i++){}//cutting not-needed spaces also finding first char after spaces( first char of the word that comes after spaces )
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");// if after spaces comes EOS - stop the command
for(j=i+1;cmdtext[j]!=' ';j++)if(!cmdtext[j])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//finding the last char in the word
new Str[MAX_PLAYER_NAME];//defining a string
strmid(Str,cmdtext,i,j);//inserting word into Str
new id=GetIdOfPartOfNameOrId(Str);//as Function says. The function is below
if(id==-1)return SendClientMessage(playerid,0xFF0000FF,"Server: There are more players with that name.");
if(id==-2)return SendClientMessage(playerid,0xFF0000FF,"Server: That player doesn't exist.");
if(id==playerid)return SendClientMessage(playerid,0xFF0000FF,"Server: You cannot pay yourself!");
for(i=j+1;cmdtext[i]==' ';i++){}//after finding id of player we want to pay cutting spaces
if(!cmdtext[i])return SendClientMessage(playerid,-1,"{FF0000}Usage: {FFFFFF}/pay {009BFF}[amount]{FFFFFF}.");//if after spaces comes EOS - stop the command
if(IsNumber(cmdtext[i]))// checking if string is number, positive one
{
new amount=strval(cmdtext[i]);//converting string into integer
if(amount>gPlayerCash[playerid])SendClientMessage(playerid,0xFF0000FF,"Server: You don't have that much money!");// does player have that amount of money?
else
{
gPlayerCash[playerid]-=amount;// decreasing player's cash by the amount
gPlayerCash[id]+=amount;//increasing player's cash by the amount
ShowPlayerMoney(id);//showing player his money
new String[MAX_PLAYER_NAME+60];//defining a string
format(String,sizeof(String),"takes out %s wallet and gives some ammount of cash to %s.",(gPlayerSex[playerid][0]=='M')?("his"):("her"),RealisticName(gPlayerCharName[id]));
//^^making message that will be sent to players around. Same as /me
SendTextToNearlyPlayers(playerid, String, ME);//sending message
PlayAnimEx(playerid, "DEALER", "shop_pay", 4.0, 1, 0, 0, 0, 0, 1);//animation
}
ShowPlayerMoney(playerid);
}
else SendClientMessage(playerid,0xFF0000FF,"Server: The paying amount must be numeric!");
return 1;
}
}
return 0;
pawn Код:
GetIdOfPartOfNameOrId(str[])
{
new id=0,i,bool:flag=true;
for(i=0;str[i];i++)
{
if('9'<str[i] || str[i]<'0'){flag=false;break;}
id=id*10+str[i]-'0';
}
if(flag)return (IsPlayerConnected(id))?id:-2;
new Name[MAX_PLAYER_NAME],br=0,lenght;
lenght=strlen(str);
for(i=0;i<MAX_PLAYERS;i++)
{
if(!IsPlayerConnected(i))continue;
GetPlayerName(i,Name,MAX_PLAYER_NAME);
if(strcmp(Name,str,true,lenght)==0)
{
br++;
if(br==2)return -1;
id=i;
}
}
if(br==1)return (IsPlayerConnected(id))?id:-2;
else return -2;
}
Last words
Thank you for reading it. I hope you found it usefull.