Introduction:

This is a warn system, where RCON'ly logged in admins can warn other players, once the other player receives 3 warns, they'll be kicked. This is usually useful for NON-RP servers.

Downloads:

sscanf2
ZCMD

Tutorial: The top of your script:

At the top of your script, under #include <a_samp> you need to add the following:

Code:
#include <sscanf2> // include the sscanf file
#include <zcmd> // include the zcmd file

new Warns[MAX_PLAYERS]; // global variable to check if a player is muted

forward KickTimer(playerid); // a kick timer we will use, since the update of 0.3x secures something that means the player can't see why he got kicked

Tutorial: KickTimer(playerid) callback:

We need to add a new callback that we forwarded previously, this will basically kick the player who we will forward the ID to once the player gets warned. Since 0.3x, you can no longer see messages before you get kicked, so that's why we use something like this:

Code:
public KickTimer(playerid)
{
Kick(playerid); // this will kick the player that we will be forwarding the ID of once we do the /warn command and the warn level is 3
return 1;
}

Make sure you have added that code somewhere towards the bottom of your script, underneath main().

Tutorial: OnPlayerConnect:

Under OnPlayerConnect, we will need to be adding the following things:

Code:
public OnPlayerConnect(playerid)
{
Warns[playerid] = 0; // this will reset the warns to 0, so if the previous player who logged out with the same ID had a warn, the new player won't get it
return 1; // don't add this if you've already got it at the bottom of your OnPlayerConnect
}

I've explained in that code what the line(s) will do.

Tutorial: Command /warn:

For this command to work, you'll need to be a bit patient and understand what I'm showing you here, else, if you just copy and paste it, it's no use to your brain and you simply won't learn.

Code:
CMD:warn(playerid, params[])
{
if(!IsPlayerAdmin(playerid)) return 0; // this will return "SERVER: Unknown command." if the player who entered the command is not an RCON admin, change this with your own variable of course
new giveplayerid, reason[50]; // make 2 new variables that we'll use with sscanf, we can do the rest later because if we don't use the rest now, it'll go to waste
if(sscanf(params, "us[50]", giveplayerid, reason)) return SendClientMessage(playerid, 0xFFFFFFFF, "Correct usage: /warn [playerid/name] [reason]"); // will return with this message if the player entered a wrong syntax
if(giveplayerid == INVALID_PLAYER_ID) return SendClientMessage(playerid, 0xFFFFFFFF, "Player not connected."); // will return this message if the player's not connected
new string[150], sender[MAX_PLAYER_NAME], receiver[MAX_PLAYER_NAME]; // creates the rest of the variables, as we'll be needing them now
GetPlayerName(playerid, sender, sizeof(sender)); // get the player's name
GetPlayerName(giveplayerid, receiver, sizeof(receiver)); // get the other player's name
format(string, sizeof(string), "%s (%d) was warned by %s (%d), reason: %s (%d/3)", receiver, giveplayerid, sender, playerid, reason, Warns[giveplayerid]+1); // sets the string
SendClientMessageToAll(0x00FFFFFF, string); // will send the formatted message
if(Warns[playerid] == 2) // this will check if the player's warns are equal to 2, because adding 1 will result in 3 which is a kick, of course
{
format(string, sizeof(string), "%s (%d) was automatically kicked, reason: had 3 warnings", receiver, giveplayerid); // sets the string once again
SendClientMessageToAll(0x00FFFFFF, string); // will send the formatted message
SetTimerEx("KickTimer", 1000, false, "i", giveplayerid); // forwards the giveplayerid to be kicked, with regards to the KickTimer that we created earlier
}
else // otherwise, if the player's warn level is less than 2
{
Warns[giveplayerid] ++; // warn up
GameTextForPlayer(giveplayerid, "~r~warned~n~~w~check the chat", 5000, 6); // sends a game text so the player will notice
}
return 1;
}

Tutorial: Command /unwarn:

Perhaps you warned someone by accident? Or you came to terms with it and gave 'em the benefit of the doubt to be forgiven? No worries, there's an unwarn command for that too:

Code:
CMD:unwarn(playerid, params[], help)
{
if(!IsPlayerAdmin(playerid)) return 0; // this will return "SERVER: Unknown command." if the player who entered the command is not an RCON admin, change this with your own variable of course
new giveplayerid, reason[50]; // make 2 new variables that we'll use with sscanf, we can do the rest later because if we don't use the rest now, it'll go to waste
if(sscanf(params, "us[50]", giveplayerid, reason)) return SendClientMessage(playerid, 0xFFFFFFFF, "Correct usage: /unwarn [playerid/name] [reason]"); // will return with this message if the player entered a wrong syntax
if(giveplayerid == INVALID_PLAYER_ID) return SendClientMessage(playerid, 0xFFFFFFFF, "Player not connected."); // will return this message if the player's not connected
if(Warns[giveplayerid] == 0) return SendClientMessage(playerid, 0xFFFFFFFF, "That player already has 0 warnings."); // this will check if the player's warnings are equal to 0, and if so it will return this message
new string[150], sender[MAX_PLAYER_NAME], receiver[MAX_PLAYER_NAME]; // creates the rest of the variables, as we'll be needing them now
GetPlayerName(playerid, sender, sizeof(sender)); // get the player's name
GetPlayerName(giveplayerid, receiver, sizeof(receiver)); // get the other player's name
format(string, sizeof(string), "%s (%d) was unwarned by %s (%d), reason: %s (%d/3)", receiver, giveplayerid, sender, playerid, reason, Warns[giveplayerid]-1); // sets the string
SendClientMessageToAll(0x00FFFFFF, string); // will send the formatted message
GameTextForPlayer(giveplayerid, "~g~unwarned~n~~w~check the chat", 5000, 6); // sends a game text so the player will notice
Warns[giveplayerid] --; // unwarn the player by 1 point
return 1;
}

That's all for this tutorial, I hope you liked it. Thanks for reading it. That was my basic tutorial on how to create a warn system command that will kick the player after 3 warns.