• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to Create Basic Commands
#1
Note: I'm by no means a professional at scripting but what I'm going to tell is what I've learned through the years. I'm going to explain it how I understand it so apologizes if how I describe something isn't correct. This also won't be using sampctl for obtaining the proper include/plugin files, I've simply haven't learned it yet so please don't haze me for not using it here.







How to Create Basic Commands

Last Updated: 17/04/19





This tutorial is aimed at beginners who have little experience with coding. It will go over what you'll need, how to create a command, what you can do within a command, etc.





I. Requirements





- Improved ZCMD

- sscanf





II. Getting started





First thing you'll need to do is get your script ready. If you use the default IDE that comes with the SA-MP server package, you can press ?New? and it will create this for you. However, the following will work as well:





PHP Code:
#include <a_samp>





public OnGameModeInit()

{

? ??return 
1;

}





public 
OnGameModeExit()

{

? ? return 
1;







The first thing we'll need to do is add I-ZCMD and sscanf to our script so that we can access their functions. We do this by typing #include <include_name_here>?at the top of your script. It should look something like this:





PHP Code:
#include <a_samp> //any native samp includes should be above all user-made includes

#include <izcmd>

#include <sscanf2> 





Now you should compile the script to make sure no errors occur. If done right, you should have no errors or warnings. Next step is creating the commands.





III. Creating a Command





Creating a command in the early days of SA-MP required use of public OnPlayerCommandText(playerid, cmdtext[]) along with using strcmp and strtok to understand what commands were being typed and to gather command parameters that the player typed alongside the command. This is no longer used by most scripters as its been shown time and time again to be very inefficient compared to other command processors made today. We'll be using izcmd as our command processor as its (or the original zcmd) the one that most scripters use today. We create a command by doing the following:





PHP Code:
CMD:examplecmd(playeridparams[])

{

? ? return 
1;







The example above is one of the common ways scripters will create a command, however izcmd allows you to create a command a few more ways such as:





PHP Code:
COMMAND:examplecmd(playeridparams[])

{

? ? return 
1;

}

command(examplecmd,playeridparams[])

{

? ??return 
1;

}

cmd(examplecmd,playeridparams[])

{

? ??return 
1;







For the rest of the tutorial, we'll be using the first example. Commands can be placed anywhere in the script below the #include?lines. Now when a player types in /examplecmd, it won't do anything as there's no code to go along with it however the script will recognize it as a command. Let's made this command send out a simple message:





PHP Code:
CMD:examplecmd(playeridparams[])

{

? ??
SendClientMessage(playerid, -1, ?Hello worldI made a command!?); //sends a message to the client (the player)

? ??return 1;







Now when a player types /examplecmd, it will show them the message ?Hello world, I made a command!?. This is a very simple command however, so let's make it give the player full health and armour:





PHP Code:
CMD:examplecmd(playeridparams[])

{

? ??
SendClientMessage(playerid, -1, ?Hello worldI made a command!?); //sends a message to the client (the player)

? ??SetPlayerHealth(playerid100.0); //sets the player's health value to 100 (full health)

? ??SetPlayerArmour(playerid100.0); //sets the player's armor value to 100 (full armour)

? ??return 1;







Now when the player types /examplecmd, it will set the player's health and armour values to 100 along with sending them a message. Now, making commands like this will work fine but what if a player needs to type in additional information that the command requires from the player?





IV: Dealing with parameters





Parameters are what the player will type after the command so that the script can use them. Not all commands will require parameters but when they do, you'll need something to discern if the player's typed any parameters after the command, what those parameters are, how many there are, etc. This is what sscanf will help us do. Here's an example command where the player needs to type in a number to set their health to a specific value:





PHP Code:
CMD:sethealth(playeridparams[])

{

? ??new 
Float:hpstring[128]; //we declare a float variable that will hold the specific value typed by the player along with a string variable that'll be used to display a formatted message

? ??if(sscanf(params,?f?,hp)) //here, sscanf is used to tell the script the values it should expect from the player. In this case, its checking if anything besides the command name was typed or if the value provided will work (i.e. if a letter was typed in place of a number)

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?Syntax: /sethealth [value]?); //this is where you tell the player how to use the command properly

? ??}



? ??
SetPlayerHealth(playerid,hp); //assuming that sscanf found nothing wrong with the value the player provided, it will store that value in our `hp` variable, ready to be used in our command here.

? ??format(string,sizeof(string),?You have set your health value to %f.?,hp); //format is used here to have the string variable store a message where the message needs additional information to finish, in this case the value the player typed in for the command

? ??SendClientMessage(playerid, -1string); //instead of typing a message, we put our `string` variable in place as its already storing a message to be used

? ??return 1;







When the player types /sethealth, the script will see that no parameters have been typed in and will give a message to the player on how to use the command. The same will happen if the player was to type something like `/sethealth f` as its looking for a decimal number. Once the player types in a number, the script will see that and (assuming there's no other parameters to deal with) continue with the command with the information given by the player. If the player typed `/sethealth 100`, it will set their health to 100, if they typed `/sethealth 1`, it will set their health to 1 and so on.





V: Further Examples





For the final section, I'm going to leave a few basic commands that do various things to give an idea of how creating a command goes. If there's something I'm doing that I haven't covered earlier, it will be mentioned in the examples.





a. /freezeplayer

PHP Code:
CMD:freezeplayer(playeridparams[])

{

? ??new 
targetidstring[128], name[MAX_PLAYER_NAME]; //name string is to store player's name, the  is to account for null character

? ??if(sscanf(params,?r?,targetid)) //?r? specifier tells sscanf to look for a playerid. Some will tell you to use ?u? but that looks for both players AND npcs, either way it will work but if you don't want npcs to be included, use ?r? for playerid parameters

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?Syntax:?/freezeplayer [playerid/name]?);

? ??}

? ??
TogglePlayerControllable(targetidfalse); //this function will toggle the player's ability to move, depending on whether its toggled true or false (1 or 0)

? ??GetPlayerName(targetidnamesizeof(name)); //this is used to get the player's name and store it in the `name` variable

? ??format(stringsizeof(string), ?You have frozen %s.?, name);

? ??
SendClientMessage(playerid, -1string);

? ??return 
1;







b. /givedeagle

PHP Code:
CMD:givedeagle(playeridparams[])

{

? ??new 
targetidammo,string[128],name[MAX_PLAYER_NAME];

? ??if(
sscanf(params,?rd?,targetid,ammo)) //the ?d? specifier is meant for integers, you can use ?i? in place of it as well

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?Syntax:?/givedeagle [playerid/name] [ammo]?);

? ??}

? ??
GivePlayerWeapon(targetidWEAPON_DEAGLEammo); //gives the targetid a desert eagle with the ammo the player specified (you can use 24 in place of WEAPON_DEAGLE and it will work the same).

? ??GetPlayerName(targetidnamesizeof(name));

? ??
format(stringsizeof(string), ?You have given %s a Desert Eagle with %d ammo.?, nameammo);

? ??
SendClientMessage(playerid, -1string);

? ??return 
1;







c. /setserverhour

PHP Code:
CMD:setserverhour(playeridparams[])

{

? ??new 
hourstring[128];

? ??if(
sscanf(params,?d?,hour)) 

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?Syntax:?/setserverhour [hour]?);

? ??}

? ??if(
hour || hour 23//checking to see if the hour inputted is either below 0 or above 23

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?You can only set the server hour between 0 to 23.?);

? ??}

? ??
SetWorldTime(hour); //this is used to set the server's time and thus whether its day or night, it only accepts an hour parameter

? ??format(stringsizeof(string), ?You have set the server hour to %d.?, hour);

? ??
SendClientMessage(playerid, -1string);

? ??return 
1;







d. /setmoney

PHP Code:
CMD:setmoney(playeridparams[])

{

? ??new 
amountstring[128];

? ??if(
sscanf(params,?d?,amount))

? ??{

? ??? ??return 
SendClientMessage(playerid, -1, ?Syntax:?/setmoney [amount]?);

? ??}

? ??
ResetPlayerMoney(playerid); //resets any money the player has to 0

? ??GivePlayerMoney(playeridamount); //gives the player the amount of money they specify

? ??format(stringsizeof(string), ?You have set your money to $%d.?, amount);

? ??
SendClientMessage(playerid, -1string);

? ??return 
1;







This concludes the tutorial. I've never really written anything like this so feedback is appreciated, I hope one of you learns something from this!
Stoned Ape

  Reply
#2
The code looks worse the way you write it because you use brackets just for a single "return" statement and leave absolutely no spacing in between.

PHP Code:
CMD:freezeplayer(playeridparams[]) {

    new 
        
targetidstring[128], name[MAX_PLAYER_NAME]; //name string is to store player's name, the  is to account for null character
    
    
if (sscanf(params"r"targetid)) //?r? specifier tells sscanf to look for a playerid. Some will tell you to use ?u? but that looks for both players AND npcs, either way it will work but if you don't want npcs to be included, use ?r? for playerid parameters
        
return SendClientMessage(playerid0xFF0000FF"Syntax: {FFFFFF}/freezeplayer [playerid/name]");

    if (
targetid == INVALID_PLAYER_ID)
        return 
SendClientMessage(playerid0xFF0000FF"Error: {FFFFFF}The specified player is not connected or is a NPC.");
    
    
GetPlayerName(targetidnamesizeof name); //this is used to get the player's name and store it in the `name` variable
    
    
format(stringsizeof string"You've frozen %s."name);
    
SendClientMessage(playerid0xFF0000FFstring);
    
    
TogglePlayerControllable(targetidfalse); //this function will toggle the player's ability to move, depending on whether its toggled true or false (1 or 0)
    
return 1;

  Reply
#3
(2019-04-18, 08:05 AM)Alaska Wrote: The code looks worse the way you write it because you use brackets just for a single "return" statement and leave absolutely no spacing in between.



From a post I wrote a while back:



Quote:Not using braces around single line statements is a bad habit that can make your code more prone to human errors. You might be interested in reading about Apple's gotofail bug. The PAWN style guide by Southclaws states the following:?



Quote:Blocks must always use braces, even if only a single line of code exists within a block. This applies to all levels including functions.



This style guide is indeed unofficial, but is approved by many reputable scripters in these forums and is the closest what we have to generally accepted and/or official code standards at the moment. It is based on years worth of knowledge in other programming languages, as well as their standards. Barr Group's Embedded C Coding Standard book, which can still be a good reference here due to PAWN being a language with a C-like syntax, states pretty much the same as the PAWN style guide:



Quote:Braces shall always surround the blocks of code (a.k.a., compound statements), following if, else, switch, while, do, and for statements; single statements and empty statements following these keywords shall also always be surrounded by braces.



However you are correct about having no spacing, I'm a sucker for whitespace myself. The tutorial itself... tl;dr for now, but it seems okay at the first glance. You might want to use [php] tags instead of [code] tags and use Courier New font for inline?code?instead of surrounding them with backticks (``) though.
  Reply
#4
I updated the thread, thanks for the feedback :)
Stoned Ape

  Reply


Forum Jump: