14.10.2011, 13:44
(
Последний раз редактировалось SmiT; 20.10.2011 в 14:12.
)
Introduction
Linux
Including
We need to load sscanf and y_commands features. At the top of our script we have to include them.
This will load the codes from "..pawno/include/YSI/y_commands.inc" and "..pawno/include/sscanf2.inc" into your script.
Important Note
y_commands help system
Creating commands without sscanf
2.We use the "help" parameter and make a check if the parameters of the command are null:
Another example
String
Placeholders
Adding an alternate spelling
Gamemode
Creating commands with sscanf
Declaring
Specifiers
A simple setskin command
Declaring
Declaring
Result
- This is my first tutorial, I will show you how you can create commands with y_commands and sscanf.
- y_commands - Most flexible and fastest command processor by ******
- sscanf - String splitting routine, easy to use to unformat strings by ******
- Download YSI Server Includes.
- Download sscanf.
- Copy/Cut the "YSI" folder into your "..pawno/include" folder.
- Copy/Cut the "sscanf2.inc" file into your "..pawno/include" folder.
- Copy the "sscanf.dll" file in your "plugins" folder. If you don't have one, create it.
- Open "server.cfg" and add "sscanf" in the line "plugins".
Код:
plugins sscanf
- Copy the "sscanf.so" file in your "plugins" folder. If you don't have one, create it.
- Open "server.cfg" and add "sscanf.so" in the line "plugins".
Код:
plugins sscanf.so
We need to load sscanf and y_commands features. At the top of our script we have to include them.
pawn Код:
#include <YSI\y_commands>
#include <sscanf2>
Important Note
- Our commands should NOT be inside any Callback.
- Callbacks are the chunks of code already in your script, that look something like this:
pawn Код:
public OnPlayerConnect(playerid)
{
return 1;
}
- Placing our commands in these callbacks, it will occur errors, so for a clean script we can scroll all the way down to the last line, where we can start creating commands.
- To add a command, you just have to make a public function using the following formulas.
pawn Код:
YCMD:my_command(playerid, params[], help)
{
return 1;
}
- params is the parameters string, playerid is an ID of the player who execute this command.
- y_commands has inbuilt support for a help system.
- NOTE: Instead of "params" we could also use "o".
pawn Код:
YCMD:my_command(playerid, o[], help)
{
return 1;
}
- If you want to use this feature, simply do:
pawn Код:
YCMD:help(playerid, params[], help)
{
if (help) return SendClientMessage(playerid, -1, "Displays help about commands");
// If help system occured, "/help help" the player will get the message above.
if (isnull(params)) return SendClientMessage(playerid, -1, "Syntax Error: /help [Command]");
// If the parameters are null "/help" the player will get the syntax message above ( COLOR = -1 wich is some sort of black )
Command_ReProcess(playerid, params, true);
// Call to put text through the command processor, with the help functions enabled or disabled.
return 1;
}
- Let's start by creating a simple "/information" command without using sscanf.
pawn Код:
YCMD:information(playerid, params[], help)
{
SendClientMessage(playerid, -1, "Tutorial by SmiT !");
return 1;
}
- This command will send the player a simple message, "Tutorial by SmiT !"
- If you hit compile, you will get some warnings:
Код:
warning 203: symbol is never used "params" warning 203: symbol is never used "help"
- This tell you that you didn't use the "params" and the "help" parameter in your command.
- There are two ways to fix that:
pawn Код:
YCMD:information(playerid, params[], help)
{
#pragma unused params, help
SendClientMessage(playerid, -1, "Tutorial by SmiT !");
return 1;
}
pawn Код:
YCMD:information(playerid, params[], help)
{
if( help ) return SendClientMessage(playerid, -1, "This command displays some information");
// if parameter HELP occured, (player types "/help information") it will return the message above.
if( isnull( params ) ) // We check if the parameters are NULL. So it won't work something like "/information word".
{
SendClientMessage(playerid, -1, "Tutorial by SmiT !");
// So, if the parameters are null the player will get the message above.
}
return 1;
}
- Let's create a simple OOC chat command.
pawn Код:
YCMD:ooc(playerid, params[], help)
{
new string[ 128 ];
new PlayerName[ MAX_PLAYER_NAME ];
if( help ) return SendClientMessage(playerid, -1, "With this command you can talk in OOC chat!");
if( isnull( params ) ) return SendClientMessage(playerid, -1, "Syntax Error: /ooc [Your Text]");
GetPlayerName( playerid, PlayerName, sizeof( PlayerName ) );
format( string, sizeof( string ),"(OOC CHAT) %s: %s", PlayerName, params);
SendClientMessageToAll(-1, string);
return 1;
}
String
- new string[ 128 ]; Declares the variable "string" with enough space for 127 characters.
- new PlayerName[ MAX_PLAYER_NAME ]; Declares the variable "PlayerName" wich will hold the name of a player. The variable has an array "MAX_PLAYER_NAME" wich means 24, wich also is the maximum name lenght in SA:MP.
- Instead: pawn Код:new string[ 128 ];
new PlayerName[ MAX_PLAYER_NAME ]; - You can do: pawn Код:new string[ 128 ], PlayerName[ MAX_PLAYER_NAME ];
- pawn Код:if( help ) return SendClientMessage(playerid, -1, "With this command you can talk in OOC chat!");
- pawn Код:if( isnull( params ) ) return SendClientMessage(playerid, -1, "Syntax Error: /ooc [Your Text]");
- An array is a variable in which you can store multiple pieces of data at once and access them dynamically, example:
MAX_PLAYER_NAME
- GetPlayerName( playerid, PlayerName, sizeof( PlayerName ) ); The script will get the player's name that executes the command, the "sizeof( PlayerName )" it gets the size of the array in the variable called "PlayerName" which in this case is MAX_PLAYER_NAME.
- pawn Код:format( string, sizeof( string ),"(OOC CHAT) %s: %s", PlayerName, params);
- "%s" inserts a string . First "%s" is a placeholder for the player's name and the second "%s" is a placeholder for the player text. (/ooc [Player Text]) in the end of our formatted string, we added PlayerName, this is the variable containing the player's name and "params" for the player text.
- SendClientMessageToAll(-1, string); This will send the string containing our message to all the players on the server.
- SmiT types "/ooc Hello".
Код:
(OOC CHAT) SmiT: Hello
Код:
%b Inserts a number at this position in binary radix. %c Inserts a single character. %d Inserts an integer (whole) number %f Inserts a floating point number. %i Inserts an integer. %s Inserts a string. ( We used this ) %x Inserts a number in hexadecimal notation. %% Inserts the literal '%'
Gamemode
pawn Код:
public OnGameModeInit()
{
Command_AddAltNamed("information", "info");
return 1;
}
- This function will add "/info" as an alternate name for "/information".
pawn Код:
public OnFilterScriptInit()
{
Command_AddAltNamed("information", "info");
return 1;
}
- Let's start by creating a basic "/heal" command.
pawn Код:
YCMD:heal(playerid, params[], help)
{
new PlayerID;
if( help ) return SendClientMessage(playerid, -1, "With this command you can heal a player!");
if( sscanf( params, "u", PlayerID ) ) return SendClientMessage(playerid, -1, "Syntax Error: /heal [PlayerName / ID]");
if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
SetPlayerHealth(PlayerID, 100);
return 1;
}
- new PlayerID; This declares the variable "PlayerID" for the player wich we will heal.
- pawn Код:if( help ) return SendClientMessage(playerid, -1, "With this command you can heal a player!");
- pawn Код:if( sscanf( params, "u", PlayerID ) ) return SendClientMessage(playerid, -1, "Syntax Error: /heal [PlayerName / ID]");
- pawn Код:if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
- SetPlayerHealth(PlayerID, 100); This is the action itself, it will heal the targeted player to 100.
- Sscanf formula in a command should look something like this:
pawn Код:
if( !sscanf( params, "specifiers_here", your_variables ) ) // If the player entered the CORRECT parameters ( NOTE the "!" )
{
// Do your code
}
- Or:
pawn Код:
if( sscanf ( params, "specifiers_here", your_variables ) ) // If the player entered the WRONG parameters
{
// Do your code
}
Quote:
Код:
Format Use L(true/false) Optional logical truthity l Logical truthity B(binary) Optional binary number b Binary number N(any format number) Optional number n Number C(character) Optional character c Character I(integer) Optional integer i Integer D(integer) Optional integer d Integer H(hex value) Optional hex number h Hex number O(octal value) Optional octal value o Octal value F(float) Optional floating point number f Floating point number G(float/INFINITY/-INFINITY/NAN/NAN_E) Optional float with IEEE definitions g Float with IEEE definitions { Open quiet section } Close quiet section P<delimiter> Invalid delimiter change p<delimiter> Delimiter change Z(string)[length] Invalid optional string z(string)[length] Deprecated optional string S(string)[length] Optional string s[length] String U(name/id) Optional user (bot/player) u User (bot/player) Q(name/id) Optional bot (bot) q Bot (bot) R(name/id) Optional player (player) r Player (player) A<type>(default)[length] Optional array of given type a<type>[length] Array of given type E<specification>(default) Optional enumeration of given layout e<specification> Enumeration of given layout 'string' Search string % Deprecated optional specifier prefix |
- We start with the y_commands formula.
pawn Код:
YCMD:setskin(playerid, params[], help)
{
return 1;
}
- It will be a little more complex here, we will use 2 parameters, one for the Player Name / ID and one for the Skin ID.
pawn Код:
YCMD:setskin(playerid, params[], help)
{
new PlayerID, SkinID, PlayerName[ MAX_PLAYER_NAME ], TargetName[ MAX_PLAYER_NAME ], string[ 128 ];
if( help ) return SendClientMessage(playerid, -1, "With this command you can change a player skin!");
if( sscanf( params, "ui", PlayerID, SkinID)) return SendClientMessage(playerid, -1, "Syntax Error: /setskin [PlayerName / ID] [SkinID]");
if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
if( SkinID > 299 || SkinID < 1 ) return SendClientMessage(playerid, -1, "Available SA:MP Skins: 1-299");
GetPlayerName( playerid, PlayerName, sizeof ( PlayerName ) );
GetPlayerName( PlayerID, TargetName, sizeof ( TargetName ) );
format( string, sizeof ( string ), "Your Skin has been set to ID: %d by %s", SkinID, PlayerName);
SendClientMessage(PlayerID, -1, string);
format( string, sizeof ( string ), "You have changed %s Skin to ID: %s", TargetName, SkinID);
SendClientMessage(playerid, -1, string);
SetPlayerSkin(PlayerID, SkinID);
return 1;
}
- new PlayerID, We declare the variable "PlayerID" for the player on wich the command will be executed.
- SkinID, We declare the variable "SkinID" for the skin id we will set to the player.
- PlayerName[ MAX_PLAYER_NAME ], We declare the variable "PlayerName" for the player name who will execute this command.
- TargetName[ MAX_PLAYER_NAME ], We declare the variable "TargetName" for the player name on wich the command will be executed.
- string[ 128 ]; We declare a 128 array string.
- pawn Код:if( help ) return SendClientMessage(playerid, -1, "With this command you can change a player skin!");
- pawn Код:if( sscanf( params, "ui", PlayerID, SkinID)) return SendClientMessage(playerid, -1, "Syntax Error: /setskin [PlayerName / ID] [SkinID]");
- pawn Код:if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
- pawn Код:if( SkinID > 299 || SkinID < 1 ) return SendClientMessage(playerid, -1, "Available SA:MP Skins: 1-299");
- GetPlayerName( playerid, PlayerName, sizeof ( PlayerName ) ); It will get the player name who exectues this command as explained above (playerid)
- GetPlayerName( PlayerID, TargetName, sizeof ( TargetName ) ); It will get the player name on wich the command will be executed (PlayerID).
- pawn Код:format( string, sizeof ( string ), "Your Skin has been set to ID: %d by %s", SkinID, PlayerName);
- pawn Код:SendClientMessage(PlayerID, -1, string);
- pawn Код:format( string, sizeof ( string ), "You have changed %s Skin to ID: %d", TargetName, SkinID);
- pawn Код:SendClientMessage(playerid, -1, string);
- SetPlayerSkin(PlayerID, SkinID); This is the action itself, this function will set the PlayerID skin to the SkinID we want to.
- Let's create a simple "/eat" command with 2 options.
- Option 1: "/eat Cookie"
- Option 2: "/eat Cake"
pawn Код:
YCMD:eat(playerid, params[], help)
{
new option[ 20 ];
if( help ) return SendClientMessage(playerid, -1,"With this command you can eat a Cookie or a Cake");
if( sscanf( params ,"s[20]", option) ) return SendClientMessage(playerid, -1,"Syntax Error: /eat [Cookie,Cake]");
if( !strcmp( option,"Cookie") )
{
SendClientMessage(playerid, -1, "You have ate a cookie! You have been healed to 100.");
SetPlayerHealth(playerid, 100);
}
else if( !strcmp( option,"Cake"))
{
SendClientMessage(playerid, -1, "You have ate a cake! You have been healed to 100.");
SetPlayerHealth(playerid, 100);
}
else return SendClientMessage(playerid, -1,"[ERROR] The option can only be Cookie or Cake.");
return 1;
}
- new option[ 20 ]; We declare the variable option with enough space for 19 characters.
- pawn Код:if( help ) return SendClientMessage(playerid, -1,"With this command you can eat a Cookie or a Cake");
- pawn Код:if( sscanf( params ,"s[20]", option) ) return SendClientMessage(playerid, -1,"Syntax Error: /eat [Cookie,Cake]");
- pawn Код:if( !strcmp( option,"Cookie") )
- pawn Код:else if( !strcmp( option,"Cake") )
- pawn Код:else return SendClientMessage(playerid, -1,"[ERROR] The option can only be Cookie or Cake.");
- Let's set some permissions, we will disable "/setskin" for players, enabling it only for RCON Administrators. (based on an imaginary login system)
pawn Код:
public OnPlayerLogin(playerid)
{
if (IsPlayerAdmin ( playerid )) // If the player is logged into RCON
{
Command_SetPlayerNamed("setskin", playerid, true); // Enable the command for him
}
else // If the player is NOT logged into rcon
{
Command_SetPlayerNamed("help", playerid, false); // Disable the command for him
}
}
- This will configure the command, so only RCON administrators can use the "/setskin" command.
- y_commands has a special system, it knows every command you have, so you don't have to update your "/commands" list.
pawn Код:YCMD:commands(playerid, params[], help)
{
if ( help ) return SendClientMessage(playerid, -1, "Lists all the commands a player can use.");
new
count = Command_GetPlayerCommandCount( playerid );
for ( new i = 0; i != count; ++i) SendClientMessage( playerid, -1, Command_GetNext ( i, playerid ) );
return 1;
}
- Replace the codes from "y_commands.inc" with this version: Quote:
- When a player types a wrong command, to return the message: "SERVER: Unknown Command." simply add the OnPlayerCommandPerformed callback:
pawn Код:public OnPlayerCommandPerformed(playerid, cmdtext[], success)
{
if( !success ) return false;
return true;
}
- To return your own message instead of the "SERVER: Unknown Command." simply do:
pawn Код:public OnPlayerCommandPerformed(playerid, cmdtext[], success)
{
if( !success )
{
format( cmdtext, 128, " ERROR: This command doesn't exists. Type /commands for a list of all available commands " );
SendClientMessage( playerid, -1, cmdtext );
}
return true;
}
Result
- Example result:
pawn Код:
// This is a comment
// uncomment the line below if you want to write a filterscript
//#define FILTERSCRIPT
#include <a_samp>
#include <YSI\y_commands>
#include <sscanf2>
#if defined FILTERSCRIPT
public OnFilterScriptInit()
{
print("\n--------------------------------------");
print(" Blank Filterscript by your name here");
print("--------------------------------------\n");
return 1;
}
public OnFilterScriptExit()
{
return 1;
}
#else
main()
{
print("\n----------------------------------");
print(" Blank Gamemode by your name here");
print("----------------------------------\n");
}
#endif
public OnGameModeInit()
{
// Don't use these lines if it's a filterscript
SetGameModeText("Blank Script");
AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
Command_AddAltNamed("information", "info");
return 1;
}
public OnGameModeExit()
{
return 1;
}
public OnPlayerRequestClass(playerid, classid)
{
SetPlayerPos(playerid, 1958.3783, 1343.1572, 15.3746);
SetPlayerCameraPos(playerid, 1958.3783, 1343.1572, 15.3746);
SetPlayerCameraLookAt(playerid, 1958.3783, 1343.1572, 15.3746);
return 1;
}
public OnPlayerConnect(playerid)
{
return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
return 1;
}
public OnPlayerSpawn(playerid)
{
return 1;
}
public OnPlayerDeath(playerid, killerid, reason)
{
return 1;
}
public OnVehicleSpawn(vehicleid)
{
return 1;
}
public OnVehicleDeath(vehicleid, killerid)
{
return 1;
}
public OnPlayerText(playerid, text[])
{
return 1;
}
public OnPlayerCommandText(playerid, cmdtext[])
{
if (strcmp("/mycommand", cmdtext, true, 10) == 0)
{
// Do something here
return 1;
}
return 0;
}
public OnPlayerEnterVehicle(playerid, vehicleid, ispassenger)
{
return 1;
}
public OnPlayerExitVehicle(playerid, vehicleid)
{
return 1;
}
public OnPlayerStateChange(playerid, newstate, oldstate)
{
return 1;
}
public OnPlayerEnterCheckpoint(playerid)
{
return 1;
}
public OnPlayerLeaveCheckpoint(playerid)
{
return 1;
}
public OnPlayerEnterRaceCheckpoint(playerid)
{
return 1;
}
public OnPlayerLeaveRaceCheckpoint(playerid)
{
return 1;
}
public OnRconCommand(cmd[])
{
return 1;
}
public OnPlayerRequestSpawn(playerid)
{
return 1;
}
public OnObjectMoved(objectid)
{
return 1;
}
public OnPlayerObjectMoved(playerid, objectid)
{
return 1;
}
public OnPlayerPickUpPickup(playerid, pickupid)
{
return 1;
}
public OnVehicleMod(playerid, vehicleid, componentid)
{
return 1;
}
public OnVehiclePaintjob(playerid, vehicleid, paintjobid)
{
return 1;
}
public OnVehicleRespray(playerid, vehicleid, color1, color2)
{
return 1;
}
public OnPlayerSelectedMenuRow(playerid, row)
{
return 1;
}
public OnPlayerExitedMenu(playerid)
{
return 1;
}
public OnPlayerInteriorChange(playerid, newinteriorid, oldinteriorid)
{
return 1;
}
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
return 1;
}
public OnRconLoginAttempt(ip[], password[], success)
{
return 1;
}
public OnPlayerUpdate(playerid)
{
return 1;
}
public OnPlayerStreamIn(playerid, forplayerid)
{
return 1;
}
public OnPlayerStreamOut(playerid, forplayerid)
{
return 1;
}
public OnVehicleStreamIn(vehicleid, forplayerid)
{
return 1;
}
public OnVehicleStreamOut(vehicleid, forplayerid)
{
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
return 1;
}
public OnPlayerClickPlayer(playerid, clickedplayerid, source)
{
return 1;
}
public OnPlayerCommandPerformed(playerid, cmdtext[], success)
{
if( !success ) return false;
return true;
}
/* COMMANDS */
YCMD:help(playerid, params[], help)
{
if (help) return SendClientMessage(playerid, -1, "Displays help about commands");
if (isnull(params)) return SendClientMessage(playerid, -1, "Syntax Error: /help [Command]");
Command_ReProcess(playerid, params, true);
return 1;
}
YCMD:commands(playerid, params[], help)
{
if ( help ) return SendClientMessage(playerid, -1, "Lists all the commands a player can use.");
new
count = Command_GetPlayerCommandCount( playerid );
for ( new i = 0; i != count; ++i) SendClientMessage( playerid, -1, Command_GetNext ( i, playerid ) );
return 1;
}
YCMD:information(playerid, params[], help)
{
if( help ) return SendClientMessage(playerid, -1, "This command displays some information");
if( isnull( params ) )
{
SendClientMessage(playerid, -1, "Tutorial by SmiT !");
}
return 1;
}
YCMD:ooc(playerid, params[], help)
{
new string[ 128 ];
new PlayerName[ MAX_PLAYER_NAME ];
if( help ) return SendClientMessage(playerid, -1, "With this command you can talk in OOC chat!");
if( isnull( params ) ) return SendClientMessage(playerid, -1, "Syntax Error: /ooc [Your Text]");
GetPlayerName( playerid, PlayerName, sizeof( PlayerName ) );
format( string, sizeof( string ),"(OOC CHAT) %s: %s", PlayerName, params);
SendClientMessageToAll(-1, string);
return 1;
}
YCMD:heal(playerid, params[], help)
{
new PlayerID;
if( help ) return SendClientMessage(playerid, -1, "With this command you can heal a player!");
if( sscanf( params, "u", PlayerID ) ) return SendClientMessage(playerid, -1, "Syntax Error: /heal [PlayerName / ID]");
if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
SetPlayerHealth(PlayerID, 100);
return 1;
}
YCMD:setskin(playerid, params[], help)
{
new PlayerID, SkinID, PlayerName[ MAX_PLAYER_NAME ], TargetName[ MAX_PLAYER_NAME ], string[ 128 ];
if( help ) return SendClientMessage(playerid, -1, "With this command you can change a player skin!");
if( sscanf( params, "ui", PlayerID, SkinID)) return SendClientMessage(playerid, -1, "Syntax Error: /setskin [PlayerName / ID] [SkinID]");
if( PlayerID == INVALID_PLAYER_ID ) return SendClientMessage(playerid, -1, "[ERROR] This player is OFFLINE");
if( SkinID > 299 || SkinID < 1 ) return SendClientMessage(playerid, -1, "Available SA:MP Skins: 1-299");
GetPlayerName( playerid, PlayerName, sizeof ( PlayerName ) );
GetPlayerName( PlayerID, TargetName, sizeof ( TargetName ) );
format( string, sizeof ( string ), "Your Skin has been set to ID: %d by %s", SkinID, PlayerName);
SendClientMessage(PlayerID, -1, string);
format( string, sizeof ( string ), "You have changed %s Skin to ID: %s", TargetName, SkinID);
SendClientMessage(playerid, -1, string);
SetPlayerSkin(PlayerID, SkinID);
return 1;
}
YCMD:eat(playerid, params[], help)
{
new option[ 20 ];
if( help ) return SendClientMessage(playerid, -1,"With this command you can eat a Cookie or a Cake");
if( sscanf( params ,"s[20]", option) ) return SendClientMessage(playerid, -1,"Syntax Error: /eat [Cookie,Cake]");
if( !strcmp( option,"Cookie") )
{
SendClientMessage(playerid, -1, "You have ate a cookie! You have been healed to 100.");
SetPlayerHealth(playerid, 100);
}
else if( !strcmp( option,"Cookie"))
{
SendClientMessage(playerid, -1, "You have ate a cake! You have been healed to 100.");
SetPlayerHealth(playerid, 100);
}
else return SendClientMessage(playerid, -1,"[ERROR] The option can only be Cookie or Cake.");
return 1;
}
- If I missed anything or you didn't understand something, please reply. I tried my best.