04.04.2012, 10:12
(
Last edited by [ABK]Antonio; 11/04/2012 at 05:32 AM.
)
Preface
Before we begin this tutorial, there's some things you should know. This doesn't cover how to actually save the data. Why it doesn't is simply because...Many people use different systems to save their player's data. There's also many, many tutorials based on those systems.
Some may not be able to follow my simplifications of certain things inside this tutorial.
You should know at LEAST...a few things...such as control structures. If you don't..don't worry, I'll cover a LITTLE of that. The reason I'm showing how to do player data structures is because..It's a LOT more useful than just a team based tutorial. It opens many doors to the scripter who learns it.
At the bottom there will be an example of the admin level system. If you have sscanf & zcmd and don't know how to make a setlevel command for example.. That will teach you how.
What You Will Learn
Player Data Structure
So we'll start of with our structure for the players data.
So what we have here is our enum. What does this do? Well, I'll have to show you the array to better explain.
Right that's simple enough isn't it?
Let's think of this something like a box with slots in it...How many slots are in this box you ask? Well, we've defined it as MAX_PLAYERS. So by default there's 500 slots. So we have this box with 500 slots...We can put separate things in each one of those slots...We can ALSO put slots...INSIDE of slots! That's the basics of a 2-dimensional array. That's pretty easy to understand isn't it?
So when we want to put something in those slots...With our enum it makes things more readable and easier to change things in the long run.
Say I want to set the players Kills to 7...Well we'll do this
That's pretty simple right? What is it actually doing though? Well, it's like taking a piece of paper...Putting it into the slot equivalent to the players ID...Then placing that piece of paper inside of our other slot which is Kills.
Let's say our players ID is 4
That's basically what it's doing. Inserting something into these little slots in the box.
SO what is an enum? It's basically just a place-holder for these numbered slots (how we're using it here at least).
Now we should set their info to 0 when they connect.
What can we do with this...I'm sure you've found some uses in your head, if not...Here's an example.
Creating Teams
First, we'll start off by creating an enum.
As you've probably noticed..It's nameless..Why is that? Well, this way we don't need to define those numbers..It's much cleaner than doing this
So.. How do we assign them to a team...Well, it's quite simple actually.
First we need to create our classes.
So we've got our classes..What do we do with them though? We do this...
So that's the basics of creating teams.
Learning More
Here's that setlevel example.
the reason i created 2 name strings is for easier reading
Before we begin this tutorial, there's some things you should know. This doesn't cover how to actually save the data. Why it doesn't is simply because...Many people use different systems to save their player's data. There's also many, many tutorials based on those systems.
Some may not be able to follow my simplifications of certain things inside this tutorial.
You should know at LEAST...a few things...such as control structures. If you don't..don't worry, I'll cover a LITTLE of that. The reason I'm showing how to do player data structures is because..It's a LOT more useful than just a team based tutorial. It opens many doors to the scripter who learns it.
At the bottom there will be an example of the admin level system. If you have sscanf & zcmd and don't know how to make a setlevel command for example.. That will teach you how.
What You Will Learn
- How to structure your players data
- How to create multiple teams
- How to use arrays and why to use arrays
- How to do simple control structures
Player Data Structure
So we'll start of with our structure for the players data.
pawn Code:
enum PlayerInfo
{
aLevel, //short for adminLevel (0)
Kills, //1
Deaths, //2
Team //3
}
pawn Code:
new Info[MAX_PLAYERS][PlayerInfo];
Let's think of this something like a box with slots in it...How many slots are in this box you ask? Well, we've defined it as MAX_PLAYERS. So by default there's 500 slots. So we have this box with 500 slots...We can put separate things in each one of those slots...We can ALSO put slots...INSIDE of slots! That's the basics of a 2-dimensional array. That's pretty easy to understand isn't it?
So when we want to put something in those slots...With our enum it makes things more readable and easier to change things in the long run.
Say I want to set the players Kills to 7...Well we'll do this
pawn Code:
Info[playerid][Kills] = 7;
Let's say our players ID is 4
pawn Code:
Info[playerid][Kills] = 7;
Info[4][1] = 7; //it will be 1 instead of 2 as we start counting with 0 in computer language
SO what is an enum? It's basically just a place-holder for these numbered slots (how we're using it here at least).
Now we should set their info to 0 when they connect.
pawn Code:
public OnPlayerConnect(playerid)
{
Info[playerid][Kills] = 0; //We'll set all of our players things to 0 when they connect.
Info[playerid][Deaths] = 0;
Info[playerid][aLevel] = 0;
return 1;
}
pawn Code:
public OnPlayerDeath(playerid, killerid, reason)
{
//The != operator means NOT equal to.
//This is one of the simplest forms of control structures.
//INVALID_PLAYER_ID is a define inside of a_players (or a_samp) to detect, well if they're not a real player...Or not connected
if(killerid != INVALID_PLAYER_ID)
{
//So if they ARE a valid player, let's continue our code.
//Here we INCREMENT our player's Kills variable...or array slot.
//What incrementing does is adds 1 to whatever the previous value is.
//It's like doing...Info[killerid][Kills]+=1;
Info[killerid][Kills]++;
}
//Even if the killer is an invalid player...We'll still give our player a death.
Info[playerid][Deaths]++; //we increment again, this time using playerid instead of killerid (playerid = the one who died | killerid = the one who killed the player)
//So basically, it will check our if statement... REGARDLESS of whether the player is a valid player we'll give the dead guy a death
return 1;
}
Creating Teams
First, we'll start off by creating an enum.
pawn Code:
enum
{
Grove,
Ballas,
Vagos,
Nameless
}
pawn Code:
#define Grove 0
#define Ballas 1
#define Vagos 2
#define Namess 3
First we need to create our classes.
pawn Code:
public OnGameModeInit()
{
//I'm not going to fill these in..If you want to know more about AddPlayerClass
//Go here - https://sampwiki.blast.hk/wiki/AddPlayerClass
//=======[Grove]=======
AddPlayerClass(105, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //0
AddPlayerClass(106, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //1
AddPlayerClass(107, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //2
//=======[Ballas]======
AddPlayerClass(102, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //3
AddPlayerClass(103, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //4
AddPlayerClass(104, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //5
//=======[Vagos]=======
AddPlayerClass(108, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //6
AddPlayerClass(109, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //7
AddPlayerClass(110, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //8
//=====[Nameless]======
AddPlayerClass(264, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //9
AddPlayerClass(259, x, y, z, angle, weapon1, ammo1, weapon2, ammo2, weapon3, ammo3); //10
}
pawn Code:
public OnPlayerRequestClass(playerid, classid)
{
//We can set their camera positions and stuff..I'm not really going to get into that. Just the teams
switch(classid) //A switch is basically an if statement on steroids.
{
case 0..2: Info[playerid][Team] = Grove; //If the class ID is 0, 1, or 2 this will set their team to grove.
case 3..5: Info[playerid][Team] = Ballas;
case 6..8: Info[playerid][Team] = Vagos;
case 9, 10: Info[playerid][Team] = Nameless; //The comma is like...if the classid is 9 or 10.
}
//So we've set their teams now what do we do?
//Let's actually create a function (just for easy reading)
AssortTeam(playerid);
return 1;
}
stock AssortTeam(playerid) //Please note that you can put this on the bottom of your script (very nice for organization)
{
switch(Info[playerid][Team]) //We do another switch here
{
case Grove: SetPlayerTeam(playerid, Grove); //We then set their team corresponding to their team ID.
case Ballas: SetPlayerTeam(playerid, Ballas);
case Vagos: SetPlayerTeam(playerid, Vagos);
case Nameless: SetPlayerTeam(playerid, NO_TEAM); //No team is a built in define that will make them teamless.
}
}
So that's the basics of creating teams.
Learning More
- The sa-mp wiki covers so many things that can help you in the long run - https://sampwiki.blast.hk/wiki/Main_Page
- Control structures are important - https://sampwiki.blast.hk/wiki/Control_Structures
- Initialisers are a good thing to know - https://sampwiki.blast.hk/wiki/Keywords:Initialisers
- Here you can find resources like skin IDs, model ids, etc. - https://sampwiki.blast.hk/wiki/Category:..._Documentation
- You can get familiar with functions here - https://sampwiki.blast.hk/wiki/Category:Scripting_Functions
Here's that setlevel example.
pawn Code:
CMD:setlevel(playerid, params[])
{
if(IsAdmin(playerid, 4)) //we check if they're an rcon admin or above level 4
{
new target, level; //create our variables to store our parameters in
if(sscanf(params, "ri", target, level)) return SendClientMessage(playerid, 0xCC0000AA, "USAGE: /setlevel [playerid] [level]");
if(level > 5) return SendClientMessage(playerid, 0xCC0000AA, "The maximum level is 5!"); //if it's above 5 it's a no no
Info[target][aLevel] = level; //we set the level of our target to what the player enters
new aName[MAX_PLAYER_NAME], tName[MAX_PLAYER_NAME]; //we create 2 string so we can store names in them.
GetPlayerName(playerid, aName, sizeof(aName)); //we get the players name then store it
GetPlayerName(target, tName, sizeof(tName)); //like above but for target
new string[128]; //create a string so we can store our formatted message in it
format(string, sizeof(string), "You set %s to admin level %d!", tName, level); //format our message...enables us to add the targets name & new level
SendClientMessage(playerid, 0x00CCCCAA, string); //we send the string to the player
format(string, sizeof(string), "%s set your admin level to %d!", aName, level); //like above
SendClientMessage(target, 0x00CCCCAA, string); //we send it to the target
}
else return SendClientMessage(playerid, 0xCC0000AA, "You aren't the required admin level!");
return 1;
}
stock IsAdmin(playerid, level) //What I usually do is something simple like this..just for ease of access for RCON admins.
{
if(Info[playerid][aLevel] >= level || IsPlayerAdmin(playerid)) return true; //checks if they're level is greater than or equal to the input level, or if they're logged into rcon
else return false; //returns true if they are, false if not.
}