PDA

View Full Version : Scripting Tutorial || Basic Commands || Taking suggestions!



Harry Slice
2nd June 2014, 05:49 AM
Hi,

First off I would highly recommend you to read James' tutorial: Click here (http://www.gta-sarp.com/forums/showthread.php?103437-Scripting-guide), his tutorial is great to start to understand the basics of Pawn.

I'll be talking on my tutorial about commands which are made with both ZCMD and SSCANF.

Link to ZCMD: Click here! (http://forum.sa-mp.com/showthread.php?t=91354)
Link to SSCANF: Click here! (http://forum.sa-mp.com/showthread.php?t=120356)

Contents:

1.0 - What are ZCMD and SSCANF?

1.1 - What is ZCMD?
1.2 - What is SSCANF?

2.0 - First commands!

2.1 - Ban command!
2.2 - Suggestion!
2.3 - Advanced /report command

1.1: What is ZCMD? ZCMD is a command processor in a include which has been created by Zeex, it is one of the fastest command processors out there.
1.2: What is SSCANF? SSCANF is a plugin that takes a string and extracts different types of data from it., I'do highly recommend to read this: Click here! (https://github.com/Y-Less/sscanf/wiki), it will make you understand it easier.

2.1: To make a /ban command you need one include and one plugin: ZCMD & SSCANF.

Okay let's go to the code, this is going to be the base where we work from:

Needed functions for this command:


stock PlayerRPName(playerid)
{
new name[MAX_PLAYER_NAME];
strmid(name, str_replace('_', ' ', ReturnPlayerName(playerid)), 0, MAX_PLAYER_NAME); // Removes the underscore between the player's forename and surname
return name; // Returns the new name without the '_'
}

stock ReturnPlayerName(playerid)
{
new name[MAX_PLAYER_NAME+1]; // Making a new string
GetPlayerName(playerid, name, sizeof(name)); // Get's the player's name.
return name; // Returns it
}

Due to a security update from 0.3x they have decided that when there is being called that a player is kicked/banned, he will get kicked/banned before any other functions, therefore you have to delay the kick/ban with a delay of 1 second so he can recieves the clientmessage about him being kicked/banned.

Therefore you need this(This is what the timer does when it's being called):

forward BanTimer(playerid);
public BanTimer(playerid)
{
return Ban(playerid);
}

It'll become something like this:


CMD:ban(playerid, params[])
{
if(IsPlayerAdmin(playerid)) // Checks if the player who wrote the command is admin if so, continue!
{
new userid, reason[128], string[128]; // userid = the target's playerid, reason = his ban reason, string = we will format our clientmessages into that!
if (sscanf(params, "us[128]", userid, reason)) // This will check wether the /ban command contains a player & string.
return SendClientMessage(playerid, 0xFFFFFFFF, "/ban [playerid] [reason]"); // If not, it will send the synthaxmessage!

format(string, sizeof(string), "AdmCmd: %s was banned by %s, reason: %s", PlayerRPName(userid), PlayerRPName(playerid), reason); // Formats the string!
SendClientMessageToAll(0xFF6347AA, string); // Send a global message to every player that the player has been banned.

SetTimerEx("BanTimer", 1000, false, "i", userid); // Sets a timer on the userid, banning him when 1 sec passed to he is able to see his ban reason.

}
return 1; // Just to know that the command has been recieved.
}

Image:

http://i58.tinypic.com/apiiw1.png

2.2: Suggest on this thread where you would like to see a tutorial about, I'll take everything, I can better spend my time by making the things the people want instead of taking random commands that most people can make from theirselves.

2.3: Okay, thanks for the suggestion in the first place, we will use the functions we used last time again, to get the player's name ect, we will be using the foreach include by Y_Less, it's a better loop than the regular one.

We will be using an enumerator to save the player's report text! Here is the code to make a new enumerator!


enum _AccountData
{
pReportText[128]
};
new AccountData[MAX_PLAYERS][_AccountData];

We will have to reset the string at, under OnPlayerConnect add:
format(AccountData[playerid][pReportText], 5, "None"); // Clears it!

The command will look like this:

IMAGE:

http://i59.tinypic.com/331owlx.png

Text:


CMD:report(playerid, params[])
{
new string[128], reason[128]; // string = string to format for the clientmessage, reason = /report [text]!
if (sscanf(params, "s[128]", reason)) // This will check wether the /report command contains a string.
return SendClientMessage(playerid, 0xFFFFFFFF, "USAGE: /report [text]"); // If not, it will send the synthaxmessage!

if(AccountData[playerid][pReportText]) return SendClientMessage(playerid, 0xFFFFFFF, "You already got a pending report!"); // Checking if the player got a report

SendClientMessage(playerid, "Your report message has been sent to online administrators."); // Sends the client the the player who wrote the comamnd!
format(string, sizeof(string), "Report from [%d]%s: %s", playerid, PlayerRPName(playerid), reason); // Make the message correctly to send it to the admins

format(AccountData[playerid][pReportText], 128, "%s", reason); // Adds the reason to his reporttext variable!

foreach(Player, i)
{
if (IsPlayerAdmin(i)) // Check if the player is rcon admin, if so continue!
SendClientMessage(i, 0xF5DEB3FF, string); // Sends the message to them!
}
return 1; // Just to know that the command has been recieved.
}


Okay, now the /acceptreport & /denyreport commands.

We will start off with the /acceptreport command:

Image:

http://i62.tinypic.com/rk0n0m.png

Code:


CMD:acceptreport(playerid, params[])
{
if (IsPlayerAdmin(playerid)) // Checks if the player is RCON admin
{
new target, string[128]; // new variable, and a new string for our messages!

if (sscanf(params, "u", target)) // This will check wether the /report command contains a playerid.
return SendClientMessage(playerid, 0xFFFFFFF, "USAGE: /acceptreport [playerid]"); // If not, it will send the synthaxmessage!

if(!strcmp(AccountData[target][pReportText], "None", true, 5)) // Compares the reportext to the basic, if it's the same the player didn't /report!
return SendClientMessage(playerid, 0xFFFFFFF, "This player doens't got a pending report!"); // Checks if the player got a report, if not send the message!

format(string, sizeof(string), "Admin %s accepted your report", PlayerRPName(playerid)); // Message that goes to the player with an active report!
SendClientMessage(target, 0xFFFFFFF, string); // Send the message to the person who did /report!

format(string, sizeof(string), "You have accepted %s's report", PlayerRPName(target)); // Message that goes to the admin who accepted the /report!
SendClientMessage(playerid, 0xFFFFFFF, string); // Send the message to the person who did /report!

format(AccountData[playerid][pReportText], 5, "None"); // Clears it!
}
return 1;
}


/denyreport!

IMAGE:

http://i62.tinypic.com/sws6sg.png

CODE:


CMD:denyreport(playerid, params[])
{
if (IsPlayerAdmin(playerid)) // Checks if the player is RCON admin
{
new target, reason[128], string[128]; // new variable, and a new string for our messages, reason for denial!

if (sscanf(params, "us[128]", target, reason)) // This will check wether the /report command contains a playerid & a string.
return SendClientMessage(playerid, 0xFFFFFFF, "USAGE: /denyreport [playerid] [reason]"); // If not, it will send the synthaxmessage!

if(!strcmp(AccountData[target][pReportText], "None", true, 5)) // Compares the reportext to the basic, if it's the same the player didn't /report!
return SendClientMessage(playerid, 0xFFFFFFF, "This player doens't got a pending report!"); // Checks if the player got a report, if not send the message!

format(string, sizeof(string), "Admin %s declined your report reason: %s", PlayerRPName(playerid), reason); // Message that goes to the player with an active report!
SendClientMessage(target, 0xFFFFFFF, string); // Send the message to the person who did /report!

format(string, sizeof(string), "You have declined %s's report, reason: %s", PlayerRPName(target), reason); // Message that goes to the admin who accepted the /report!
SendClientMessage(playerid, 0xFFFFFFF, string); // Send the message to the person who did /report!

format(AccountData[playerid][pReportText], 5, "None"); // Clears it!
}
return 1;
}

Baby
2nd June 2014, 06:37 AM
Good job Harry, I was about to write the same thing.

Flux
2nd June 2014, 11:43 AM
I'm going to keep it off the Featured Guides list for now, however when you've added some more content (just a bit more, not loads) requested by users then I'll add it.

Good job so far!

Harry Slice
2nd June 2014, 12:45 PM
I'm going to keep it off the Featured Guides list for now, however when you've added some more content (just a bit more, not loads) requested by users then I'll add it.

Good job so far!

I am waiting for suggestions :)

Sweety
2nd June 2014, 01:38 PM
Good job Harry, I was about to write the same thing.

'Hi im R-T-even Suhl, i'm from 2009 ' (take it as a joke next time steven ruhl)

Yeah time to learn !

Agent Gideon
2nd June 2014, 02:14 PM
I'm a programmer IRL + have PAWNO experience aswell. So, this guide was not bad at all. However, for the guy who do not know anything about programming, it's pretty hard.

First, you should have explained what includes were. What functions could do. You should have spoken about variables too.

Anyway, good job.

Donbot™
2nd June 2014, 02:51 PM
I'm a programmer IRL + have PAWNO experience aswell. So, this guide was not bad at all. However, for the guy who do not know anything about programming, it's pretty hard.

First, you should have explained what includes were. What functions could do. You should have spoken about variables too.

Anyway, good job.

thats why he said read james' guide first

http://www.gta-sarp.com/forums/showthread.php?103437-Scripting-guide

###
2nd June 2014, 03:18 PM
Just to help you out - /report command.

Agent Gideon
2nd June 2014, 05:53 PM
Just to help you out - /report command.

Defines:



#define COLOR_LIGHTGOLD 0xFAFAD2FF


CMD:Report:



CMD:Report(playerid, params[]) {
new wMsg[523], msg[500];
if(sscanf(params, "s[500]", msg))
{
SendClientMessage(playerid,-1,"USAGE: /report [report message]");
}
else
{
SendClientMessage(playerid,-1,"Your report message has been sent to online administrators.");
new pName[MAX_PLAYER_NAME];
GetPlayerName(playerid, pName, sizeof(pName));
removeUnderscore(pName);
format(wMsg, sizeof(wMsg), "Report from %s[%d]: %s", pName, playerid, msg);
new pCount;
pCount=GetPlayersCount();
for(new i=0;i<pCount;i++)
{
if(IsPlayerConnected(i) && IsPlayerAdmin(i)) SendClientMessage(i, COLOR_LIGHTGOLD, wMsg);
}
}
}

In OnPlayerCommandText



new cmd[STR_SIZE],params[500];
sscanf(cmdtext,"s[32]s[500]",cmd,params);
if(!strcmp("/report",cmd))
{
Report(playerid, params);
return 1;
}

GetPlayersCount:



stock GetPlayersCount() {
new count=0;
new i=0;
for(i=0;i<MAX_PLAYERS; i++) {
if(IsPlayerConnected(i)) count++;
}
return count;
}

OT: Sadly, I don't know how admin system is scripted on the SARP. Basically, report message just goes to RCON administrators.

P.S: Was too lazy to make it tutorial-ish.

Dylan.
2nd June 2014, 06:09 PM
I was waiting too see this from you! Good work as always my friend :)

BicMercer
2nd June 2014, 09:45 PM
You should explain more in depth of the code, being said that means by explaining what a string is, how to format a string and each parameter's meaning in each function.

E.G:
Prob. like a 9th of the people in this thread knows what this means.



strmid(name, str_replace('_', ' ', ReturnPlayerName(playerid)), 0, MAX_PLAYER_NAME);


To sum up my point, try to explain the code a little more further.

You should add in the SA-MP wiki (www.wiki.sa-mp.com) website for people to look at, it might help.

Nice tutorial anyways, it's good. (Scripting Experience)

Calvin Catt
3rd June 2014, 02:50 AM
I suggest a /report system, with /acceptreport, and /denyreport

Harry Slice
3rd June 2014, 04:20 AM
I suggest a /report system, with /acceptreport, and /denyreport

Added, see 2.3

Flux
6th June 2014, 04:23 PM
I've added this to the list of Featured Guides so it can be easily accessible. It would be brilliant if you could try to update it regularly with new commands.

Good job.

Harry Slice
6th June 2014, 04:27 PM
I've added this to the list of Featured Guides so it can be easily accessible. It would be brilliant if you could try to update it regularly with new commands.

Good job.

Since I am hired in the dev team, I know I should focus on fixing sa-rp, I'll update it but not yet!

Donbot™
6th June 2014, 08:08 PM
Defines:



#define COLOR_LIGHTGOLD 0xFAFAD2FF


CMD:Report:



CMD:Report(playerid, params[]) {
new wMsg[523], msg[500];
if(sscanf(params, "s[500]", msg))
{
SendClientMessage(playerid,-1,"USAGE: /report [report message]");
}
else
{
SendClientMessage(playerid,-1,"Your report message has been sent to online administrators.");
new pName[MAX_PLAYER_NAME];
GetPlayerName(playerid, pName, sizeof(pName));
removeUnderscore(pName);
format(wMsg, sizeof(wMsg), "Report from %s[%d]: %s", pName, playerid, msg);
new pCount;
pCount=GetPlayersCount();
for(new i=0;i<pCount;i++)
{
if(IsPlayerConnected(i) && IsPlayerAdmin(i)) SendClientMessage(i, COLOR_LIGHTGOLD, wMsg);
}
}
}

In OnPlayerCommandText



new cmd[STR_SIZE],params[500];
sscanf(cmdtext,"s[32]s[500]",cmd,params);
if(!strcmp("/report",cmd))
{
Report(playerid, params);
return 1;
}

GetPlayersCount:



stock GetPlayersCount() {
new count=0;
new i=0;
for(i=0;i<MAX_PLAYERS; i++) {
if(IsPlayerConnected(i)) count++;
}
return count;
}

OT: Sadly, I don't know how admin system is scripted on the SARP. Basically, report message just goes to RCON administrators.

P.S: Was too lazy to make it tutorial-ish.

note to beginners: there is absolutly no point of making msg 500 cells big as user max input is only 128 cells

http://wiki.sa-mp.com/wiki/Limits

Sam Gideon
9th April 2015, 01:25 PM
Nice tutorial