[Tutorial] Dynamic Faction System [MySQL]
#1

Dynamic Faction System


Alright this tutorial will basically teach you how easy it is to make dynamic systems for your server. When I started scripting, it was my dream to make everything dynamic, and now I have the knowledge to do do, So I am sharing it with you guys.

I will be making this completely from scratch, with explanations to most things, let's start ey;

THINGS NEEDED:
  • MySQL Database
  • Pawno to make the script
  • Patience to follow along
Alright, let's open a new script, and let's place our defines, and enums up top.

pawn Code:
#define MAX_FACTIONS 10 // Max amount of factions you could create/have

enum faction // Enums, way better then using 10 variables per thing needed for faction system.
{
    ID, // Faction ID
    Name[32], // Name of the faction
    Type, // What kind of faction? Criminal, law, etc
    Rank1[32], // Rank Name
    Rank2[32], // Rank Name
    Rank3[32], // Rank Name
    Rank4[32], // Rank Name
    Rank5[32] // Rank Name
};

new Factions[MAX_FACTIONS][faction], Total_Factions_Created, facid[MAX_PLAYERS];
// The Factions[Max_factions] is for the enum, the total factions checks how many factions
// are created and the facid is for admin things, which you will find out about later.
That should all be pretty straight forward, you could add more ranks if you please, I am only doing 5 to make things simpler in teaching. With the enums, we could now use things like:

Factions[id][Type], Or Factions[id][Name], etc.
Now, let's include MySQL,SSCANF2, and ZCMD to our scripts.

pawn Code:
#include <zcmd>
#include <a_mysql>
#include <sscanf2>
Add this to top, and ensuring you include those files in your /pawno/include folder.


Add these defines, and of course replace them with your own connection information:

pawn Code:
#define     MYSQLIP         "localhost"
#define     MYSQLUSER       "root"
#define     MYSQLDB         "test"
#define     MYSQLPASSWORD   ""
And in OnGameModeInit, add these 2 lines, which will get the mysql to connect:

pawn Code:
mysql_connect(MYSQLIP, MYSQLUSER, MYSQLDB, MYSQLPASSWORD);
mysql_debug(1);
The mysql_connect, connects to the mysql server, and the debug, created a debug log in your folder which shows you every single mysql thing done, all the queries.


Now we could get to the fun parts, some commands to create factions!


pawn Code:
CMD:fcreate(playerid, params[])
{
    new string[128], query[400], fname[32];
    if(sscanf(params, "s[32]", fname)) return SendClientMessage(playerid, -1, "USAGE: /fcreate factionname");
    // GETTING ALL THE FACTIONS CREATED, THEN ADDING 1 TO MAKE THE NEW ONE
    Total_Factions_Created++;
    //=====================================================================
   
    // THIS SETS THE FACTIONS NAME TO WHATEVER YOU JUST NAMED IT, PLUS SETS THE ID FOR THE FACTION
    format(Factions[Total_Factions_Created][Name], 64, "%s", fname);
    Factions[Total_Factions_Created][ID] = Total_Factions_Created;
    //==============================================================================================
   
    // THIS IS JUST TELLING YOU CREATED A FACTION, WITH THE NAME
    format(string, sizeof(string), "You have created a faction named: %s(ID:%d).",Factions[Total_Factions_Created][Name], Factions[Total_Factions_Created][ID]);
    SendClientMessage(playerid, -1, string);
    //================================================================================================
   
    // THIS IS SETTING ALL THE FACTION NAMES, WILL BE USED LATER FOR EDITTING AROUND
    format(Factions[Total_Factions_Created][Rank1], 32, "Rank 1 - Lowest");
    format(Factions[Total_Factions_Created][Rank2], 32, "Rank 2");
    format(Factions[Total_Factions_Created][Rank3], 32, "Rank 3");
    format(Factions[Total_Factions_Created][Rank4], 32, "Rank 4");
    format(Factions[Total_Factions_Created][Rank5], 32, "Rank 5 - Leader");
    //================================================================================
   
    // THIS IS FOR SAVING ALL THE DATA INTO THE MYSQL DATABASE
    format(query, sizeof(query), "INSERT INTO `Factions` (ID, Name, Rank1, Rank2, Rank3, Rank4, Rank5) VALUES(%d,'%s','%s','%s','%s','%s','%s')",

                        Factions[Total_Factions_Created][ID], Factions[Total_Factions_Created][Name],
                        Factions[Total_Factions_Created][Rank1],Factions[Total_Factions_Created][Rank2],
                        Factions[Total_Factions_Created][Rank3],Factions[Total_Factions_Created][Rank4],
                        Factions[Total_Factions_Created][Rank5]);
    mysql_query(query);
    //=================================================================================
    return 1;
}
The explanations in there should help out enough to understand whats going on, if not please ask and I WILL explain even further to ensure you understand.


Now we just passed the most difficult part, creating the factions, not that bad ey? Let's create a loading system:


Place this under OnGameModeInit, so it loads when the gamemode starts up:

pawn Code:
LoadFactions();
And now for the function which loads the factions, be careful this might look very confusing:


pawn Code:
stock LoadFactions()
{
    new query[400];
    for(new id; id < MAX_FACTIONS; id++) // Goes through all the slots, looking for the data
    {
        format(query, sizeof(query), "SELECT * FROM Factions WHERE ID = %d", id); // Selects all the information from the table
        mysql_query(query);
        mysql_store_result();
        if(mysql_num_rows())
        if(mysql_fetch_row_format(query,"|"))
        {
            sscanf(query, "p<|>e<is[64]ds[32]s[32]s[32]s[32]s[32]>",Factions[id]); // SSCANF seperates the data into the variables
            Total_Factions_Created++; // Counts the factions created
        }

    }
    printf("> %d factions have been loaded from the database.", Total_Factions_Created); // Prints out the information of how many factions created
    return 1;
}
You could throw that code all the way in the bottom, it should work flawlessly. Yet again, I added comments to explain the information, there isn't really much more to it than that.



Now you have a command to make the faction.. function to load the function.. let's get 2 more commands, to set the ranks, and the faction name:


pawn Code:
CMD:editfname(playerid, params[])
{
    new string[128], query[400], fname[32], fid;
   
    if(sscanf(params, "ds[32]", fid,fname)) return SendClientMessage(playerid, -1, "USAGE: /editfname factionid newfactionname");
   
    // SETS THE NEW NAME
    format(Factions[fid][Name], 32, "%s", fname);
    //=============================================
   
    // TELLS YOU THAT YOU CHANGED THE NAME OF THE FACTION
    format(string, sizeof(string), "You have renamed faction id %d to %s", fid, Factions[fid][Name]);
    SendClientMessage(playerid, -1, string);
    //======================================================
   
    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Name = '%s' WHERE ID = %d", Factions[fid][Name],fid);
    mysql_query(query);
    //======================================
    return 1;
}
Yet again, all the explanations are placed as comments in the above code, ask any questions if you get stuck on it.



Now just to make the rank name changeable:

pawn Code:
CMD:editrank1(playerid, params[])
{
    new string[128], rname[32], query[400], fid;
    if(sscanf(params, "ds[32]", fid,rname)) return SendClientMessage(playerid, -1, "USAGE: /editrank1 factionid newrankname");
   
    format(Factions[fid][Rank1], 32, "%s", rname);
    format(string, sizeof(string), "You have set faction ids %d rank 1 to %s", fid, Factions[fid][Rank1]);
   
    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Rank1 = '%s' WHERE ID = %d", Factions[fid][Rank1],fid);
    mysql_query(query);
    //======================================
    return 1;
}


CMD:editrank2(playerid, params[])
{
    new string[128], rname[32], query[400], fid;
    if(sscanf(params, "ds[32]", fid,rname)) return SendClientMessage(playerid, -1, "USAGE: /editrank2 factionid newrankname");

    format(Factions[fid][Rank2], 32, "%s", rname);
    format(string, sizeof(string), "You have set faction ids %d rank 2 to %s", fid, Factions[fid][Rank2]);

    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Rank2 = '%s' WHERE ID = %d", Factions[fid][Rank2],fid);
    mysql_query(query);
    //======================================
    return 1;
}

CMD:editrank3(playerid, params[])
{
    new string[128], rname[32], query[400], fid;
    if(sscanf(params, "ds[32]", fid,rname)) return SendClientMessage(playerid, -1, "USAGE: /editrank3 factionid newrankname");

    format(Factions[fid][Rank3], 32, "%s", rname);
    format(string, sizeof(string), "You have set faction ids %d rank 3 to %s", fid, Factions[fid][Rank3]);

    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Rank3 = '%s' WHERE ID = %d", Factions[fid][Rank3],fid);
    mysql_query(query);
    //======================================
    return 1;
}

CMD:editrank4(playerid, params[])
{
    new string[128], rname[32], query[400], fid;
    if(sscanf(params, "ds[32]", fid,rname)) return SendClientMessage(playerid, -1, "USAGE: /editrank4 factionid newrankname");

    format(Factions[fid][Rank4], 32, "%s", rname);
    format(string, sizeof(string), "You have set faction ids %d rank 4 to %s", fid, Factions[fid][Rank4]);

    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Rank4 = '%s' WHERE ID = %d", Factions[fid][Rank4],fid);
    mysql_query(query);
    //======================================
    return 1;
}

CMD:editrank5(playerid, params[])
{
    new string[128], rname[32], query[400], fid;
    if(sscanf(params, "ds[32]", fid,rname)) return SendClientMessage(playerid, -1, "USAGE: /editrank5 factionid newrankname");

    format(Factions[fid][Rank5], 32, "%s", rname);
    format(string, sizeof(string), "You have set faction ids %d rank 5 to %s", fid, Factions[fid][Rank5]);

    // UPDATES THE INFORMATION ON THE TABLE
    format(query, sizeof(query), "UPDATE Factions SET Rank5 = '%s' WHERE ID = %d", Factions[fid][Rank5],fid);
    mysql_query(query);
    //======================================
    return 1;
}
There is so many other ways, then 5 different commands to do, such as dialogs, and etc, if you don't understand those codes, go ahead and ask any questions



PART B: MAKING THE TABLE IN PHPMYADMIN/MYSQL:

  • First open your phpmyadmin, whether it be wamp or an actual host.
  • Next go to the database you had created for this
  • Now create a new table with 8 columns
  • For the columns, set them like this:
  • You are now all done!
Quick note, for the ID, it doesn't need to be 5, 2 would be much more appropriate since you wouldn't have more then 99 factions, since it's only 10 defined.


That's all for the tutorial, if you have any other questions ask away. In this tutorial, I didn't include the player part or joining factions and stuff, you have to do that yourselves, unless enough people ask for it.
Reply
#2

Nice work! I'd use this for sure if I was making a RP script. What about vehicles? How are you meant too invite people?
Reply
#3

I only made the faction system, not the player involvement, to allow you to learn some also, but if requested, I'd make a tutorial including that as well.
Reply
#4

If you REALLY would want to make this as dynamic as possible, then make a seperate table for the ranks;
PHP Code:
factionidrankidrankname
primary key 
(factionidrankid
And oh, forgot to mention that you should update this to R7. No point to keep dangling with old methods.
Reply
#5

Y U NO USE R7 VERSION?
Reply
#6

Yeah make a separate table for ranks and use another set of enums for it as well. Been doing it myself since 2008 lol, been the best thing ever.
Reply
#7

Fixed with a downgrade to R6
Reply
#8

I don't see the difference between one table or two tables honestly, running a update query changes it nicely, unless your implying dynamic amount of ranks or something.

For the r7 comment, didn't realize it updated, I don't really pay much attention to things like that until my stuff full out breaks lol.
Reply
#9

Check out this tutorial.

https://sampforum.blast.hk/showthread.php?tid=337810
Reply
#10

Nice!
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)