[Tutorial] Simple Team Setup + Player Data Template
#1

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
  • How to structure your players data
  • How to create multiple teams
  • How to use arrays and why to use arrays
What you MIGHT learn
  • 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
}
So what we have here is our enum. What does this do? Well, I'll have to show you the array to better explain.

pawn Code:
new Info[MAX_PLAYERS][PlayerInfo];
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
pawn Code:
Info[playerid][Kills] = 7;
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
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
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.

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;
}
What can we do with this...I'm sure you've found some uses in your head, if not...Here's an example.

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
}
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
pawn Code:
#define Grove   0
#define Ballas  1
#define Vagos   2
#define Namess  3
So.. How do we assign them to a team...Well, it's quite simple actually.

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
}
So we've got our classes..What do we do with them though? We do this...


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
If you've encountered a problem or anything...Feel free to post in this thread. If you find that something could be better in here, feel free to post too.

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.
}
the reason i created 2 name strings is for easier reading
Reply
#2

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[playerid][Kills]+=1;
        Info[playerid][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;
}
You're giving the player who died a kill.. instead of "playerid" use "killerid"
Reply
#3

Very good explanations +rep
Reply
#4

Good tutorial for newbies
Reply
#5

very well explained!! this will help alot of users!

9/10!!!
+rep
Reply
#6

At least one good tutorial which is step-by-step 'n fairly explained. It'll be useful for sure...
Reply
#7

Thanks! Good grammar and good explaining
Reply
#8

Thanks !
Reply
#9

Good tut. and very good explenation!
Reply
#10

And how do we invite a player to a team? I am new to scripting, and i became a developer on a friend's server. It's a roleplay, and we want to make teams like Paramedic, Police, Taxi ect. Could you please help me? ^_^
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)