SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 04/10/2016, 12:51 PM   #1
Eoussama
High-roller
 
Eoussama's Avatar
 
Join Date: Jul 2016
Location: Kingdom of Morocco // Tangier
Posts: 1,078
Reputation: 149
Default Admin system for beginners

Howdy,
So a lot of people were requesting this on this forums, on social medias, even on youtube comments, So I thought that here I should step forward and tutor others who aren't aware of such technics to do certain things,
so hope you guys enjoy...

REQUIREMENTS
the last version of sscanf, http://download2124.mediafire.com/h2...00-dneeTHA.rar
ZCMD : http://forum.sa-mp.com/showthread.php?t=91354
YSI\y_ini : http://forum.sa-mp.com/showthread.ph...957(Pa%C4%8Dio
TUTORIAL
So first of all, you must include the new installed files, they should go beneath the a_samp include,
Code:
#include <a_samp>
#include <ZCMD>
#include <sscanf2>
#include <YSI\y_ini>
now, if we are going to do this, let's make it perfect, we want to make the admin status auto acquired by admins when logging-in, thus we must save the data somewhere, so let's define the path of the data saving,
Code:
#define ADMIN_PATH "/Admins/%s.ini"
Ok, now we want to rename the data-holding file to the player's name, to do so, insert the following code,
Code:
AdminPath(playerid) {
	new
	    str[36],
	    name[MAX_PLAYER_NAME];
	GetPlayerName(playerid, name, sizeof(name));
	format(str, sizeof(str), ADMIN_PATH, name);
	return str;
}
you might have a palm face now, and say, wait..w.wwhat? Wth just happened, well, just chill mate, and let me start explaining what the code above stands for,
so as you can see, we created a string named "str" and set it's size to 36, and the other variable to hold the player's name which is "name" and its size is MAX_PLAYER_NAME, which is by default equal to 24,
after that, we stored the player's name in the variable "name", then comes the "format", which replaces the file's name with the player's name, so that we will final have a .ini file with the player's name,

let's move on.
Now we need to declare new variables, so let's got ahead and use the enum function
Code:
enum E_ADMIN_DATA {
	AdminLevel,
	bool:LoggedIn
}
so we've created the "AdminLevel" variable and the "LoggedIn" boolean, which is by default set to false,
underneath of that, do this:
Code:
new PlayerInfo[MAX_PLAYER_NAME][E_ADMIN_DATA];
OK, now he are done with the first part, make sure that your script look like this :

Code:
#include <a_samp>
#include <ZCMD>
#include <sscanf2>
#include <YSI\y_ini>

#define ADMIN_PATH "/Admins/%s.ini"

AdminPath(playerid) {
	new
	    str[36],
	    name[MAX_PLAYER_NAME];
	GetPlayerName(playerid, name, sizeof(name));
	format(str, sizeof(str), ADMIN_PATH, name);
	return str;
}
enum E_ADMIN_DATA {
	AdminLevel,
	bool:LoggedIn
}
new PlayerInfo[MAX_PLAYER_NAME][E_ADMIN_DATA];
before you do anything, go to "scriptfiles" and create a new folder, thennamed it "Admins"

now, moving the second part, go to the OnPlayerConnect(playerid) callback, and type this:
Code:
PlayerInfo[playerid][AdminLevel] = 0;
PlayerInfo[playerid][LoggedIn] = false;
what the first line means is, when a player their stats would be reseted concerning their AdminLevel until their identify get confirmed, (world perfectly with a login system),
right underneath that, insiter the following,
Code:
	GetPlayerName(playerid, name, sizeof(name));
	if(fexist(AdminPath(playerid))) {
	    INI_ParseFile(AdminPath(playerid), "LoadPlayerData_AdminData", .bExtra = true, .extra = playerid);
	}
so this part should look like this:
Code:
public OnPlayerConnect(playerid)
{
	PlayerInfo[playerid][AdminLevel] = 0;
	PlayerInfo[playerid][LoggedIn] = false;
	new name[MAX_PLAYER_NAME];
	GetPlayerName(playerid, name, sizeof(name));
	if(fexist(AdminPath(playerid))) {
	    INI_ParseFile(AdminPath(playerid), "LoadPlayerData_AdminData", .bExtra = true, .extra = playerid);
	}
	return 1;
}
that part was all about reseting the player's stats and checking if they previousely have an admin data file,
the INI_ParseFile function is calling a forwarded callback, which we are about to creat,
next, go ahead bellow thes OnPlayerConnect callback and forward,
Code:
Code:
forward LoadPlayerData_AdminData(playerid, name[], value[]);
now right below this, type the following code,
Code:
public LoadPlayerData_AdminData(playerid, name[], value[]) {
	INI_Int("AdminLevel", PlayerInfo[playerid][AdminLevel]);
	return 1;
}
that callback above stands for making the admin level data stored in form of an integer, that's why we had in the biggining INI_Int

OK, now we made the necessary part, let's do the setlevel command next,
this is going to work for both level 4 admins and rcon admins, therefore the code should look like this,
Code:
CMD:setlevel(playerid, params[]) {
	if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][AdminLevel] >= 3)
	{
               //do something here
               return 1;
        else {
		SendClientMessage(playerid, 0xFF0000, "[ERROR]: you are not authorized to use this command");
		return 1;
	}
}
next define some variables,
Code:
CMD:setlevel(playerid, params[]) {
	if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][AdminLevel] >= 3)
	{
               new
			string[MAX_PLAYER_NAME+64],
			pname[MAX_PLAYER_NAME],
			tname[MAX_PLAYER_NAME],
			targetid,
		 	level;
               //do something here
               return 1;
        else {
		SendClientMessage(playerid, 0xFF0000, "[ERROR]: you are not authorized to use this command");
		return 1;
	}
}
string[MAX_PLAYER_NAME+64] : a string which is going to be used to display a message, its size is ([MAX_PLAYER_NAME] = 24)+64 which is 88
pname[MAX_PLAYER_NAME] : a variable which will hold the player's name (the admin who is using the command), its size is 24
tname[MAX_PLAYER_NAME] : a variable that holds the target id's name (the player whom is going to be promoted/demoted), its size is 24
targetid : self-explanatory, a variable which helps define the target's id,
level : this will hold the value of the admin level you want to stick to someone,
next step, we are goin to tell the server what to do in case a player uses the command with null parameters, and where comes sscanf's role, so type this in your code

Code:
if(sscanf(params, "ii", targetid, level))
        {
            return SendClientMessage(playerid, -1, "USAGE: /setlevel (playerid) (level)");
        }
then your code should look like this:
Code:
CMD:setlevel(playerid, params[]) {
	if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][AdminLevel] >= 3)
	{
                 new
			string[MAX_PLAYER_NAME+64],
			pname[MAX_PLAYER_NAME],
			tname[MAX_PLAYER_NAME],
			targetid,
		 	level;
                        if(sscanf(params, "ii", targetid, level))
                        {
                                return SendClientMessage(playerid, -1, "USAGE: /setlevel (playerid) (level)");
                        }
                        //do something here
                        return 1;
        else {
		SendClientMessage(playerid, 0xFF0000, "[ERROR]: you are not authorized to use this command");
		return 1;
	}
}
what we've done so far, is sending a client message to the user "USAGE:..etc" in case he didn't add the command params,
so next, we need to check if the targetid(the promoted/demoted guy) is connected or has a valid ID,
in order to do this, we need to loop through all connected players one by one, and the fast way to do this is using "for" statement, so we need to add this,
Code:
for(new i=0;i<MAX_PLAYERS; i++) continue; {

	     if((!IsPlayerConnected(targetid)) || (targetid == INVALID_PLAYER_ID))
            {
                    SendClientMessage(playerid, 0xFF0000, "Player Is Not Connected!");
            }
}
if(level < 1 || level > 4)
{
        return SendClientMessage( playerid, 0xFF0000, "available levels (1-4)");
}
OK, let's freez a minute and explain the content above,
so first we started the code line with for, which stands for a loop, and what loop besically is? a loop is a sequence of instruction s that is continually repeated until a certain condition is reached, in this case, the targetid, so we typed new i = 0, whioch creates a new variable "i" and sets its value to 0, then we typed i<MAX_PLAYERS, which sets the limite of "i" to the max players connected, so now the value of "i"is closed between 0 and MAX_PLAYERS, next we typed, i++, which tells the server to add 1 to the value of "i" every time, then we finished the line with continue, your code will stop and start again at the start of the loop, skipping everything else after the continue;
then we made a limite to admin levels, (1-4),
once you do all of this, your code should look like this:
Code:
CMD:setlevel(playerid, params[])
{
    if((IsPlayerAdmin(playerid)) || PlayerInfo[playerid][AdminLevel] >= 3)
    {
        new
             string[MAX_PLAYER_NAME+64],
             pname[MAX_PLAYER_NAME],
             tname[MAX_PLAYER_NAME],
             targetid,
             level;

	if(sscanf(params, "ii", targetid, level))
        {
            return SendClientMessage(playerid, -1, "USAGE: /setlevel (playerid) (level)");
        }
        for(new i=0;i<MAX_PLAYERS; i++) continue; {
                if((!IsPlayerConnected(targetid)) || (targetid == INVALID_PLAYER_ID))
                {
                        SendClientMessage(playerid, 0xFF0000, "Player Is Not Connected!");
                }
         }
	 if(level < 1 || level > 4)
        {
        	return SendClientMessage( playerid, 0xFF0000, "available levels (1-4)");
	}
    }
    else
    {
         SendClientMessage( playerid, 0xFF0000, "you can't use this command!");
         return 1;
    }
    return 1;
}
and now let's sent the players admin level,
first, let's store the player and target's names in their variables,
Code:
GetPlayerName(playerid, pname, sizeof(pname));
GetPlayerName(targetid, tname, sizeof(tname));
then send a client message to all, so players would notice the promotion,
Code:
format(string, sizeof(string), "Administrator %s has promoted %s to level %i admin", pname, tname, level);
SendClientMessageToAll(-1, string);
now to set the player's level, just type this
Code:
PlayerInfo[targetid][AdminLevel] = level;
we still missing the most important part, which is saving the data, do to so, we're going to use YSI\y_ini,
Code:
new INI:File = INI_Open(AdminPath(targetid));
INI_SetTag(File, "AdminData");
INI_WriteInt(File, "AdminLevel", PlayerInfo[targetid][AdminLevel]);
INI_Close(File);
so far, your overall command code, should look like this,
Code:
CMD:setlevel(playerid, params[])
{
    if((IsPlayerAdmin(playerid)) || PlayerInfo[playerid][AdminLevel] >= 3)
    {
        new
             string[MAX_PLAYER_NAME+64],
             pname[MAX_PLAYER_NAME],
             tname[MAX_PLAYER_NAME],
             targetid,
             level;

		if(sscanf(params, "ii", targetid, level))
        {
            return SendClientMessage(playerid, -1, "USAGE: /setlevel (playerid) (level)");
        }
        for(new i=0;i<MAX_PLAYERS; i++) continue; {
                 if((!IsPlayerConnected(targetid)) || (targetid == INVALID_PLAYER_ID))
                {
                       SendClientMessage(playerid, 0xFF0000, "Player Is Not Connected!");
                }
	}
        if(level < 1 || level > 4)
        {
        	return SendClientMessage( playerid, 0xFF0000, "available levels (1-4)");
        }

        else
        {
            GetPlayerName(playerid, pname, sizeof(pname));
            GetPlayerName(targetid, tname, sizeof(tname));
            format(string, sizeof(string), "Administrator %s has promoted %s to level %i admin", pname, tname, level);
            SendClientMessageToAll(-1, string);
            PlayerInfo[targetid][AdminLevel] = level;
            new INI:File = INI_Open(AdminPath(targetid));
            INI_SetTag(File, "AdminData");
            INI_WriteInt(File, "AdminLevel", PlayerInfo[targetid][AdminLevel]);
            INI_Close(File);
            return 1;
        }
    }
    else
    {
         SendClientMessage( playerid, 0xFF0000, "you can't use this command!");
         return 1;
    }
    return 1;
}
all the data would be saved in "scriptfiles > Admins"
hope I helped most of you guys,
if you find this useful, give it a +REQ
regards, oussama
__________________
Eoussama is offline   Reply With Quote
Old 04/10/2016, 01:33 PM   #2
Spmn
Gangsta
 
Join Date: Jun 2015
Location: Romania
Posts: 528
Reputation: 113
Default Re: Admin system for beginners

Y u do dis?

Code:
for(new i=0;i<MAX_PLAYERS; i++) continue; {
                 if((!IsPlayerConnected(targetid)) || (targetid == INVALID_PLAYER_ID))
                {
                       SendClientMessage(playerid, 0xFF0000, "Player Is Not Connected!");
                }
	}
Spmn is offline   Reply With Quote
Old 04/10/2016, 03:03 PM   #3
Eoussama
High-roller
 
Eoussama's Avatar
 
Join Date: Jul 2016
Location: Kingdom of Morocco // Tangier
Posts: 1,078
Reputation: 149
Default Re: Admin system for beginners

Quote:
Originally Posted by Spmn View Post
Y u do dis?

Code:
for(new i=0;i<MAX_PLAYERS; i++) continue; {
                 if((!IsPlayerConnected(targetid)) || (targetid == INVALID_PLAYER_ID))
                {
                       SendClientMessage(playerid, 0xFF0000, "Player Is Not Connected!");
                }
	}
when I don't add this, the server doesn't check if the targetid is valid or not,whatever the id you would enter, you would ended up being the targetid instead, even if you do /setlevel 5000 4 it would work
__________________
Eoussama is offline   Reply With Quote
Old 04/10/2016, 03:08 PM   #4
GoldenLion
Gangsta
 
GoldenLion's Avatar
 
Join Date: Sep 2014
Location: Estonia
Posts: 963
Reputation: 129
Default Re: Admin system for beginners

What about just
Code:
if (targetid == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "The specified player is not connected.");
It will do all the job...
GoldenLion is offline   Reply With Quote
Old 04/10/2016, 03:12 PM   #5
Luis-
High-roller
 
Luis-'s Avatar
 
Join Date: Jan 2010
Location: England
Posts: 4,075
Reputation: 347
Default Re: Admin system for beginners

Why are people still using ini? It's so outdated.
Luis- is offline   Reply With Quote
Old 04/10/2016, 03:16 PM   #6
Eoussama
High-roller
 
Eoussama's Avatar
 
Join Date: Jul 2016
Location: Kingdom of Morocco // Tangier
Posts: 1,078
Reputation: 149
Default Re: Admin system for beginners

Quote:
Originally Posted by Luis- View Post
Why are people still using ini? It's so outdated.
what do you suggest

Quote:
Originally Posted by GoldenLion View Post
What about just
Code:
if (targetid == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "The specified player is not connected.");
It will do all the job...
I tried it, the command always end up not working as it should, I would enter any ID and the cmd would still work but only on the playerid
__________________
Eoussama is offline   Reply With Quote
Old 04/10/2016, 03:59 PM   #7
Luis-
High-roller
 
Luis-'s Avatar
 
Join Date: Jan 2010
Location: England
Posts: 4,075
Reputation: 347
Default Re: Admin system for beginners

MySQL is much easier than having to mess around with files.
Luis- is offline   Reply With Quote
Old 04/10/2016, 04:28 PM   #8
Eoussama
High-roller
 
Eoussama's Avatar
 
Join Date: Jul 2016
Location: Kingdom of Morocco // Tangier
Posts: 1,078
Reputation: 149
Default Re: Admin system for beginners

Quote:
Originally Posted by Luis- View Post
MySQL is much easier than having to mess around with files.
can you give me links to some nice tutorials on MySQL? I want to learn it so bad
__________________
Eoussama is offline   Reply With Quote
Old 04/10/2016, 05:07 PM   #9
Quinncell
Guest
 
Posts: n/a
Default Re: Admin system for beginners

Quote:
Originally Posted by Luis- View Post
Why are people still using ini? It's so outdated.
Most people start off with Y_ini even though I agree it's outdated but it's good for beginners.Imagine what the 'Script Help' section would be if everyone started off with MySQL xD

Quote:
Originally Posted by Eoussama View Post
can you give me links to some nice tutorials on MySQL? I want to learn it so bad
Here you go > http://forum.sa-mp.com/showthread.php?t=129183

OT: The tutorial is quite useful for beginners.Well done.
Also, use the 'php' tags when making tutorials, it's much better imo.
  Reply With Quote
Old 04/10/2016, 07:34 PM   #10
Freshncool
High-roller
 
Freshncool's Avatar
 
Join Date: Aug 2014
Location: United Kingdom, England.
Posts: 1,146
Reputation: 253
Default Re: Admin system for beginners

OH MY GOD SO MANY WRONG THINGS:

1ST:
Why are you looping to check if the player is connected? if(!IsPlayerConnected(targetid)) !!!!

2ND:
Why are you using 'i' for targetid, use 'u' sscanf supports name/id with 'u'. (IF U DOESNT WORK UPDATE IT)


Quote:
Originally Posted by KeithCooper View Post
OT: The tutorial is quite useful for beginners.Well done.
WHAT??!!?!?!?! Sure, the INI parts are useful but no beginner should be seeing loops to check if a player is connected. Reminds me of people that don't even download a gm and say "Good job +rep"
__________________


TOMMYBATE ^
click here
Freshncool is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[FilterScript] Admin Spec Filter Script (Used for Beginners) Khaled_Ahmed Filterscripts 3 27/02/2014 09:49 AM
[FilterScript] DM SYSTEM [For Beginners] Rockstar128 Filterscripts 1 10/11/2013 12:48 AM
[FilterScript] Duel System Good For Beginners Rockstar128 Filterscripts 4 09/11/2013 06:22 AM
[FilterScript] Cross Admin System V1.2 [updated] + Added IRC System + Anti Cheat(sscanf, dcmd,y_ini) No.1 Admin System CROSS_Hunter Filterscripts 21 02/01/2013 07:32 PM
[FilterScript] Cross Admin System V1.1 [updated] + Added V.I.P System(sscanf, dcmd,y_ini) No.1 Admin System CROSS_Hunter Filterscripts 8 10/09/2012 12:18 PM


All times are GMT. The time now is 01:59 AM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.