Introduction

Well, First of all to everyone, This is a tutorial on making a level and exp system with paydays, good for RP servers. This is not recommended for beginners.
Second this is my FIRST TUTORIAL so If there's something wrong, Please Do tell me.

Requirements

Here's what you'll need :
sscanf ( Credits goes to Y_Less.)
Zcmd ( Goes to Zeex. )
y_ini ( To Y_Less)
WARNING : MAKE SURE YOU HAVE THE REGISTER/LOGIN SYSTEM AND SAVING/LOADING.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Lets Get Started

On top of the script :
Code:
#include <a_samp> // Credits goes to SA-MP team.
#include <YSI\y_ini>
#include <sscanf2>
#include <zcmd>

Now.. You'll need these defines :
Code:
#define LIME 0x88AA62FF
#define PATH "/Users/%s.ini" // the path where EXP and LEVEL data will be stored.

Okay.. Lets add some forwards..
Code:
forward ScoreUpdate();
forward PayDay(playerid);
forward PlayerPlayMusic(playerid);
forward StopMusic();

Now lets create some enums.. If you do not know what it is, Here's a link to it - Click!

Code:
enum pInfo
{
Level,
Exp
};
new PlayerInfo[MAX_PLAYERS][pInfo]; // //We create a variable that stores our enumerator info for each player.
new ScoreOld; // Old Score/Level of player.
new levelexp = 1; // Sets to 1.

Real Coding starts.
Now.. Add this Under " Public OnGameModeInIt " -- I hope so far you have understood all that.
Code:
SetTimer("PayDay",360000,1);// 360000 = 1 hr.. you can change it.
SetTimer("ScoreUpdate", 1000, 1); // Do not change it.

Now.. Add this under " Public OnPlayerConnect(playerid)" Make sure you already have the register/login system since I won't be doing the register/login system..
Code:
PlayerInfo[playerid][Level] = 1; // As soon as player connects, It will set his/her level to 1.
PlayerInfo[playerid][Exp] = 0; // Exp to 0.

Before proceeding.. Make sure you have the register/login system already done.. We'll be using Y_INI for saving/loading data.

Okay.. lets head on..Go to OnPlayerDisconnect and add this ( If you already have it, just add those both exp, level )
Code:
new INI:File = INI_Open(UserPath(playerid));
INI_SetTag(File,"data");
INI_WriteInt(File,"Level",PlayerInfo[playerid][Level]);
INI_WriteInt(File,"Exp",PlayerInfo[playerid][Exp]);
INI_Close(File);

Okay.. now the levelup command..
Code:
COMMAND:levelup(playerid,params[])
{
new string[30]; // String.
if(IsPlayerConnected(playerid) == 1) // Checks if player is connected.
{
new points[248]; // Points.
new nxtlevel = PlayerInfo[playerid][Level]+1; // As soon as its executed, It adds +1 to your score.
new expamount = nxtlevel*levelexp; // Exp amount, Its 2 CURRENTLY but you can raise it by adding +number after levelexp
if(PlayerInfo[playerid][Exp] < expamount) // Checks if player's exp amount is above the required one or not.
{
format(points,sizeof(points)," You need [%d] Exp Points in order to level up, You currently have [%d]",expamount,PlayerInfo[playerid][Exp]); // Format, This is pretty obvious.
SendClientMessage(playerid,LIME,points); // Sends the message.
return 1;
}
else
{
PlayerInfo[playerid][Exp] = 0; // Sets the EXP amount to 0 as you level'd up.
PlayerInfo[playerid][Level]++; // Adds a level.
format(string,sizeof(string),"~g~Your now level:[%d]",PlayerInfo[playerid][Level]); // Format.
GameTextForPlayer(playerid,string,6000,1); // Sends gametext about his new level'ing up.
return 1;
}
}
return 1;
}
Now to check your level and exp.. here's a /stats command..
Code:
COMMAND:stats(playerid,params[])
{
new string2[200];
new name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(string2,sizeof(string2),"Name: %s \nLevel: %d\nExp: %d",name,PlayerInfo[playerid][Level],PlayerInfo[playerid][Exp]);
ShowPlayerDialog(playerid,DIALOG_STATS,DIALOG_STYL E_MSGBOX,"Player Stats",string2,"Close","");
return 1;
}
Okay.. If you already have the LoadUser Data thing.. IGNORE THIS..
Code:
forward LoadUser_data(playerid,name[],value[]);
public LoadUser_data(playerid,name[],value[])
{
INI_Int("Level",PlayerInfo[playerid][Level]);
INI_Int("Exp",PlayerInfo[playerid][Exp]);
return 1;
}

A stock that will fetch the data.
Code:
stock UserPath(playerid)
{
new string[128],playername[MAX_PLAYER_NAME];
GetPlayerName(playerid,playername,sizeof(playernam e));
format(string,sizeof(string),PATH,playername);
return string;
}

Now.. the Timers!
Code:
public ScoreUpdate()
{
new Score;
new name[MAX_PLAYER_NAME];
//new string[256];
for(new i=0; i<MAX_PLAYERS; i++)
{
if (IsPlayerConnected(i))
{
GetPlayerName(i, name, sizeof(name));
Score = PlayerInfo[i][Level];
SetPlayerScore(i, Score);
if (Score > ScoreOld)
{
ScoreOld = Score;
}
}
}
}
public PayDay(playerid)
{
for (new i; i < MAX_PLAYERS; i++)
{
if (IsPlayerConnected(i))
{
new nxtlevel = PlayerInfo[playerid][Level];
new payday = nxtlevel*0;
GivePlayerMoney(i,payday);
PlayerInfo[playerid][Exp]++;
GameTextForPlayer(i," ~p~ PayDay",6,5000);
PlayerPlayMusic(playerid);
}
}
}
public PlayerPlayMusic(playerid)
{
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(IsPlayerConnected(i))
{
SetTimer("StopMusic", 5000, 0);
PlayerPlaySound(i, 1068, 0.0, 0.0, 0.0);
}
}
}
public StopMusic()
{
for(new i = 0; i < MAX_PLAYERS; i++)
{
if(IsPlayerConnected(i))
{
PlayerPlaySound(i, 1069, 0.0, 0.0, 0.0);
}
}
}


Summing up all.
Well, Now you got a Working Level/exp system with Paydays! You can edit it to your style, Remember.. you need a Working REGISTER/LOGIN SYSTEM ..

Also :
I didn't added a LoadUser thing in OnPlayerConnect, please do that manually.

With Kind Regards,
- Benzke.