Page 1 of 3

XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:31 pm
by Archive-Poster
This might be worth a "usefull link"

I was really bored and decided to make a XP tutorial.
There is a million ways to make a XP plugin, and here is one of them.
If you find any errors or something, just tell me.

If use this tutorial to make a plugin, dont post here if you need help.
Many have asked if they can use my idea, and make animal mod.
Just make animal mod if you want...

This is just a "beta"...
Just as you know:
• You will get XP for killing team-mates too.
• You dont get any extra XP for a headshot, planting bomb, using hostages etc...
• After getting levels, nothing will happend. This is what you have to add.

As in all scripts, include stuff

Code: Select all

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun>
#include <vault>
Lets say im going to make animal mod.
Now we define all the "classes". (animals)

Code: Select all

#define CLASS_NOTHING 0
#define CLASS_DOG 1
#define CLASS_CAT 2
#define CLASS_HORSE 3
#define CLASS_COW 4
// Etc...
// Note: I made a "nothing" animal. This is the class that all new people will automaticly get.
Now we make a "maxclasses" variable. Umm.. We need this later to give the classes name.
Would be strange to call em "CLASS_DOG" etc. in game eh?

Code: Select all

#define MAXCLASSES 5
// I set MAXCLASSES to 5, since we have 5 classes
Now we create variables that hold your class, xp and level.

Code: Select all

new PlayerClass[33]
new PlayerXP[33]
new PlayerLevel[33]
Here we need the "maxclasses" variable we made earlier. This will be the names that will be in game.

Code: Select all

new const CLASSES[MAXCLASSES][] = {
    "None",
    "Dog",
    "Cat",
    "Horse",
    "Cow"
}
Just some stuff for the ShowHUD... Will explain later.

Code: Select all

new msgtext
Now we create the levels and how much xp you need per level. You can edit to more or less XP/levels here...

Code: Select all

//Lets say we have 6 levels now..
new const LEVELS[6] = {
    100, //100 XP for level 1
    200, //200 XP for level 2
    400, //Etc..
    800,
    1600,
    3200
}
Now lets create the plugin_init()

Code: Select all

public plugin_init()
{
    register_plugin("Animal Mod", "1.0", "XunTric")
    
    //I'll create a on/off cvar for the mod... You dont have to add this.
    register_cvar("sv_animalmod", "1")
    
    //Now we register the DeathMsg event. This is where we can add XP when you kill somebody.
    register_event("DeathMsg", "DeathMsg", "a") 
    //Note that i registered it as "a"; global event
    
    //Now we register a "XP Per Kill" cvar...
    //Now I made 20 xp per kill.
    register_cvar("xp_per_kill", "20")

    //Lets register a SaveXP toggle cvar.
    register_cvar("SaveXP", "1")
    
    //Lets register a menu to choose animal with...
    register_menucmd(register_menuid("menu_ChooseAnimal"),1023,"DoChooseAnimal"); 
    
    //ResetHUD event... (Check if user has no class)
    register_event("ResetHUD", "ResetHud", "b")
    
    //Something for ShowHUD... Will explain later.
    msgtext = get_user_msgid("StatusText") 

    //Lets make a "Change Animal" cmd for players.
    //I just lead it to the change animal menu.
    //Ill get back to the menu later.
    register_clcmd("say /changeanimal", "ChangeAnimal")
    register_clcmd("say_team /changeanimal", "ChangeAnimal")
}
Now lets create a function to save XP with.
(XP gets loaded from amxmodx/data/vault.ini)

Code: Select all

public SaveXP(id)
{
    new authid[32]; 
    get_user_authid(id,authid,31); 

    new vaultkey[64], vaultdata[64]; 
  
    //Save their class
    format(vaultkey,63,"ANIMAL-%s-class",authid); 
    format(vaultdata,63,"%d",PlayerClass[id]); 
    set_vaultdata(vaultkey,vaultdata); 

    //Save their XP
    format(vaultkey,63,"ANIMAL-%s-xp",authid); 
    format(vaultdata,63,"%d",PlayerXP[id]); 
    set_vaultdata(vaultkey,vaultdata); 

    //Save their level
    format(vaultkey,63,"ANIMAL-%s-level",authid); 
    format(vaultdata,63,"%d",PlayerLevel[id]); 
    set_vaultdata(vaultkey,vaultdata);
}
Now lets create a function to load XP
(XP gets loaded from amxmodx/data/vault.ini)

Code: Select all

public LoadXP(id)
{
    new authid[32]; 
    get_user_authid(id,authid,31); 

    new vaultkey[64], vaultdata[64]; 

    //Load their class
    format(vaultkey,63,"ANIMAL-%s-class",authid); 
    get_vaultdata(vaultkey,vaultdata,63); 
    PlayerClass[id] = str_to_num(vaultdata); 

     //Load their XP
    format(vaultkey,63,"ANIMAL-%s-xp",authid); 
    get_vaultdata(vaultkey,vaultdata,63); 
    PlayerXP[id] = str_to_num(vaultdata);   

    //Load their level
    format(vaultkey,63,"ANIMAL-%s-level",authid); 
    get_vaultdata(vaultkey,vaultdata,63);
    PlayerLevel[id] = str_to_num(vaultdata);  
}
Now that we have a SaveXP and LoadXP function, lets load their XP when they connect.

Code: Select all

public client_connect(id)
{
    //Only load their XP if our SaveXP cvar is 1.
    if(get_cvar_num("SaveXP") == 1) {
       
         LoadXP(id)

         //Add a message if you want....
         client_print(id, print_chat, "[Animal Mod] XP Loaded!")
         client_print(id, print_chat, "[Animal Mod] You are a %s with level %s and %s XP", PlayerClass[id], PlayerLevel[id], PlayerXP[id])
    }
}
Now we save their XP when they disconnect.

Code: Select all

public client_disconnect(id)
{
    //Only save their XP if our SaveXP cvar is 1.
    if(get_cvar_num("SaveXP") == 1) {
    
         SaveXP(id)
    }
}
Lets create the menu to choose class with.

Code: Select all

//Call it whatever you want...
stock ChooseAnimal(id)
{
    new menu[192] 
    
    //Add keys for how many classes you have + exit key.
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3 

    
    //Here we write the menu options..
    format(menu, 191, "Animal Mod: Choose Animal^n^n1. Dog^n2. Cat^n3. Horse^n4. Cow^n^n0. Exit") 
    
    //We created a menu in plugin_init() and now we make the plugin know that its this menu it has to show.
    show_menu(id, keys, menu, -1, "menu_ChooseAnimal") 
    
    return PLUGIN_CONTINUE
}
Now lets create the second part of the menu. This is where we write exacly what happends when you press one of the buttons.

Code: Select all

public DoChooseAnimal(id, key)
{
    // Remeber that the keys starts on 0...
    if(key == 0) {
       
         //Lets check if the player allready has Dog...
         if(PlayerClass[id] == CLASS_DOG) {
         
              //Make a message here if you want...
              client_print(id, print_chat, "[Animal Mod] You are allready a Dog! Choose something else!")
              
              //Open the menu again...
              ChooseAnimal(id)
              
              //Exit...
              return PLUGIN_HANDLED
         }        

         //Now, if the player didnt have dog allready, we'll set his class to dog.
         PlayerClass[id] = CLASS_DOG
         
         //Make a message if you want...
         client_print(id, print_chat, "[Animal Mod] You are now a Dog!")
    }        
    
    //Im doing the same on all other buttons...
         
    if(key == 1) {
         
         if(PlayerClass[id] == CLASS_CAT) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Cat! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_CAT
         client_print(id, print_chat, "[Animal Mod] You are now a Cat!")
    }
    
    if(key == 2) {
         
         if(PlayerClass[id] == CLASS_HORSE) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Horse! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_HORSE
         client_print(id, print_chat, "[Animal Mod] You are now a Horse!")
    }    

    if(key == 3) {
         
         if(PlayerClass[id] == CLASS_COW) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Cow! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_COW
         client_print(id, print_chat, "[Animal Mod] You are now a Cow!")
    }
      
    //Show new HUD after picking class.
    //Ill get back to this later...
    ShowHUD(id)
    
    return PLUGIN_HANDLED
}
Now lets create the ResetHUD event.

Code: Select all

public ResetHUD(id)
{
    //Lets check if "sv_animalmod" is on. If its off, we'll stop the function.
    if(get_cvar_num("sv_animalmod") == 0) {
         return PLUGIN_HANDLED
    }

    //Lets check if the player has no animal.
    if(PlayerClass[id] == CLASS_NOTHING) {
    
         //If the player doesnt have a animal;
         //Open the choose animal menu for him.
         ChooseAnimal(id)
         return PLUGIN_HANDLED
    }
    
    return PLUGIN_HANDLED
}
Now lets create the DeathMsg event, where we can add XP if you kill somebody

Code: Select all

public DeathMsg() //Note that i only had (), and not (id)
{
    //Lets check if "sv_animalmod" is on. If its off, we'll stop the function.
    if(get_cvar_num("sv_animalmod") == 0) {
         return PLUGIN_HANDLED
    }
    
    //Now we create a "attacker" varriable. So the XP will be given to the killer, and not all players on the server.
    new attacker = read_data(1)
    
    //Now the plugin will check if the attacker doesnt have a class, and if he doesnt, the function will stop.
    if(PlayerClass[attacker] == CLASS_NOTHING) {
         return PLUGIN_HANDLED
    }
    
    //Now lets see if the attacker allready has level 6, and doesnt need more XP, and if he is, stop the function.
    //You can remove this if you want, and let the player get as much XP he want. But we wont get more than level 6 anyway.
    if(PlayerLevel[attacker] == 6) {
         return PLUGIN_HANDLED
    }
    
    //Now we can add XP to the attacker.        
    PlayerXP[attacker] += get_cvar_num("XP_per_kill") //Add the amout of XP you have on the "XP_per_kill" cvar.
    
    //Now we check if the attacker has enough XP for a new level. And if he has, we add it.
    if(PlayerXP[attacker] >= LEVELS[PlayerLevel[attacker]]) {
     
         //Add his level...
         PlayerLevel[attacker] += 1
         
         //Now you can make a "congratualtions" message if you want...
         client_print(attacker, print_chat, "[Animal Mod] Congratulations! You are now level %i!", PlayerLevel[attacker])
         
         //Lets save his XP every time he gets a level incase the server crashes or something. So they wont loose it all.
         if(get_cvar_num("SaveXP") == 1) {
 
              SaveXP(attacker)
         }


         //Show His New Level on the HUD message.
         //Ill get back to this later...
         ShowHUD(attacker)
    }   
    
    //Show new HUD if you didnt get level too. (To show the new XP)
    //Ill get back to this later...
    ShowHUD(attacker)
    
    return PLUGIN_CONTINUE
}
Now lets create the mystic ShowHUD
This is the thing in the corner of your screen in game that shows your animal, xp and level.

Code: Select all

public ShowHUD(id)    
{ 
    new HUD[51] 
    
    //This is the stuff that will actually show in game.
    format(HUD, 50, "[%s]Level: %i XP: %i", CLASSES[PlayerClass[id]], PlayerLevel[id], PlayerXP[id]) 

    message_begin(MSG_ONE, msgtext, {0,0,0}, id) 
    write_byte(0) 
    write_string(HUD) 
    message_end() 
    return
}
So finially, heres our full code!
(With no comments)

Code: Select all

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun>
#include <vault>

#define CLASS_NOTHING 0
#define CLASS_DOG 1
#define CLASS_CAT 2
#define CLASS_HORSE 3
#define CLASS_COW 4

#define MAXCLASSES 5

new PlayerClass[33]
new PlayerXP[33]
new PlayerLevel[33]

new const CLASSES[MAXCLASSES][] = {
    "None",
    "Dog",
    "Cat",
    "Horse",
    "Cow"
}

new msgtext

new const LEVELS[6] = {
    100, 
    200, 
    400, 
    800,
    1600,
    3200
}

public plugin_init()
{
    register_plugin("Animal Mod", "1.0", "XunTric")
    
    register_cvar("sv_animalmod", "1")
    
    register_event("DeathMsg", "DeathMsg", "a") 
    
    register_cvar("XP_per_kill", "20")
    
    register_menucmd(register_menuid("menu_ChooseAnimal"),1023,"DoChooseAnimal"); 
    
    register_event("ResetHUD", "ResetHud", "b")
    
    msgtext = get_user_msgid("StatusText") 

    register_clcmd("say /changeanimal", "ChangeAnimal")
    register_clcmd("say_team /changeanimal", "ChangeAnimal")
}

public SaveXP(id)
{
    new authid[32]; 
    get_user_authid(id,authid,31); 

    new vaultkey[64], vaultdata[64]; 
  
    format(vaultkey,63,"ANIMAL-%s-class",authid); 
    format(vaultdata,63,"%d",PlayerClass[id]); 
    set_vaultdata(vaultkey,vaultdata); 

    format(vaultkey,63,"ANIMAL-%s-xp",authid); 
    format(vaultdata,63,"%d",PlayerXP[id]); 
    set_vaultdata(vaultkey,vaultdata); 

    format(vaultkey,63,"ANIMAL-%s-level",authid); 
    format(vaultdata,63,"%d",PlayerLevel[id]); 
    set_vaultdata(vaultkey,vaultdata);
} 

public LoadXP(id)
{
    new authid[32]; 
    get_user_authid(id,authid,31); 

    new vaultkey[64], vaultdata[64]; 

    format(vaultkey,63,"ANIMAL-%s-class",authid); 
    get_vaultdata(vaultkey,vaultdata,63); 
    PlayerClass[id] = str_to_num(vaultdata); 

    format(vaultkey,63,"ANIMAL-%s-xp",authid); 
    get_vaultdata(vaultkey,vaultdata,63); 
    PlayerXP[id] = str_to_num(vaultdata);   

    format(vaultkey,63,"ANIMAL-%s-level",authid); 
    get_vaultdata(vaultkey,vaultdata,63);
    PlayerLevel[id] = str_to_num(vaultdata);  
} 

public client_connect(id)
{
    if(get_cvar_num("SaveXP") == 1) {
       
         LoadXP(id)

         client_print(id, print_chat, "[Animal Mod] XP Loaded!")
         client_print(id, print_chat, "[Animal Mod] You are a %s with level %s and %s XP", PlayerClass[id], PlayerLevel[id], PlayerXP[id])
    }
}

public client_disconnect(id)
{
    if(get_cvar_num("SaveXP") == 1) {
    
         SaveXP(id)
    }
}

stock ChooseAnimal(id)
{
    new menu[192] 
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3 

    
    format(menu, 191, "Animal Mod: Choose Animal^n^n1. Dog^n2. Cat^n3. Horse^n4. Cow^n^n0. Exit") 
    show_menu(id, keys, menu, -1, "menu_ChooseAnimal")    
    return PLUGIN_CONTINUE
}

public DoChooseAnimal(id, key)
{
    if(key == 0) {
       
         if(PlayerClass[id] == CLASS_DOG) {
         

              client_print(id, print_chat, "[Animal Mod] You are allready a Dog! Choose something else!")
              ChooseAnimal(id)           
              return PLUGIN_HANDLED
         }        

         PlayerClass[id] = CLASS_DOG         
         client_print(id, print_chat, "[Animal Mod] You are now a Dog!")
    }        
         
    if(key == 1) {
         
         if(PlayerClass[id] == CLASS_CAT) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Cat! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_CAT
         client_print(id, print_chat, "[Animal Mod] You are now a Cat!")
    }
    
    if(key == 2) {
         
         if(PlayerClass[id] == CLASS_HORSE) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Horse! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_HORSE
         client_print(id, print_chat, "[Animal Mod] You are now a Horse!")
    }    

    if(key == 3) {
         
         if(PlayerClass[id] == CLASS_COW) {
              
              client_print(id, print_chat, "[Animal Mod] You are allready a Cow! Choose something else!")
              ChooseAnimal(id)
              return PLUGIN_HANDLED
         }
                   
         PlayerClass[id] = CLASS_COW
         client_print(id, print_chat, "[Animal Mod] You are now a Cow!")
    }
      
    ShowHUD(id)
    
    return PLUGIN_HANDLED
}

public ResetHUD(id)
{
    if(PlayerClass[id] == CLASS_NOTHING) {
    
         ChooseAnimal(id)
         return PLUGIN_HANDLED
    }
    
    return PLUGIN_HANDLED
}

public DeathMsg()
{
    if(get_cvar_num("sv_animalmod") == 0) {
         return PLUGIN_HANDLED
    }
    
    new attacker = read_data(1)
    
    if(PlayerClass[attacker] == CLASS_NOTHING) {
         return PLUGIN_HANDLED
    }
    
    if(PlayerLevel[attacker] == 6) {
         return PLUGIN_HANDLED
    }
            
    PlayerXP[attacker] += get_cvar_num("XP_per_kill") 
    
    if(PlayerXP[attacker] >= LEVELS[PlayerLevel[attacker]]) {
     
         PlayerLevel[attacker] += 1
         
         client_print(attacker, print_chat, "[Animal Mod] Congratulations! You are now level %i!", PlayerLevel[attacker])

         if(get_cvar_num("SaveXP") == 1) {
 
              SaveXP(attacker)
         }
         
         ShowHUD(attacker)
    }   
    
    ShowHUD(attacker)
    
    return PLUGIN_CONTINUE
}

public ShowHUD(id)    
{ 
    new HUD[51]
    format(HUD, 50, "[%s]Level: %i XP: %i", CLASSES[PlayerClass[id]], PlayerLevel[id], PlayerXP[id]) 

    message_begin(MSG_ONE, msgtext, {0,0,0}, id) 
    write_byte(0) 
    write_string(HUD) 
    message_end() 
    return
}

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:33 pm
by Archive-Poster
Nice man..

May I make one suggestion?

Instead of all of those if() statements, use a switch() statement..

Code: Select all

switch(key) {

    case 0: { 
        // .. 
    }
    case 1: { 
        // .. 
    }
    case 2: { 
        // .. 
    }
    // etc.
}

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:34 pm
by Archive-Poster
Hrm, I altered a bit of your code ;)
Also, excuse my use of semicolons =P

EDIT: Actually compiles now ;)

Code: Select all

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun>

// An enum is nicer than #defining macros Wink
enum pclass
{
    CLASS_NOTHING=0,
    CLASS_DOG,
    CLASS_CAT,
    CLASS_HORSE,
    CLASS_COW,

    NUM_OF_CLASSES
}


// You need a cell for each player, and I prefix globals with g_ Smile
new pclass:g_PlayerClass[33];
new g_PlayerXP[33];
new g_PlayerLevel[33];

new const CLASS_NAMES[NUM_OF_CLASSES][] = {
    "None",
    "Dog",
    "Cat",
    "Horse",
    "Cow"
}

#define NUM_OF_LEVELS 6

// The qutoes were wrong ;o
new const LEVELS[NUM_OF_LEVELS] = {
    100, //100 XP for level 1
    200, //200 XP for level 2
    400, //Etc..
    800,
    1600,
    3200
}

new gmsgStatusText; // I've renamed this to gmsgStatusText - reminds me of the gamedll code Wink

public plugin_init()
{
    register_plugin("Animal Mod", "1.0", "XunTric")
    
    register_cvar("sv_animalmod", "1")
    
    register_event("DeathMsg", "DeathMsg", "a")
    
    register_cvar("XP_per_kill", "20")

    // I've renamed the menu action function to that because I think that it's nicer Very Happy
    register_menucmd(register_menuid("menu_ChooseAnimal"),1023,"MenuAction_ChooseAnimal");
    
    register_event("ResetHUD", "ResetHud", "b")
    
    gmsgStatusText = get_user_msgid("StatusText")
}

// No need to make this a stock
ChooseAnimal(id)
{
    // You had horse here two times Very Happy
    new menu[] = "Animal Mod: Choose Animal^n^n1. Dog^n2. Cat^n3. Horse^n4. Cow^n^n0. Exit" // I think this should be better than doing format, in case it works Wink
    new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3
    
    show_menu(id, keys, menu, -1, "menu_ChooseAnimal")    

    // We don't need a return value in here either
}

public MenuAction_ChooseAnimal(id, pclass:key)
{
    // The keys map to the pclass ids (I think), so no need to have a big if construct;)
    if (key == g_PlayerClass[id])
    {
        client_print(id, print_chat, "[Animal Mod] You are already a %s! Choose something else!", CLASS_NAMES[key]);
        ChooseAnimal(id);
        return;
    }
    client_print(id, print_chat, "[Animal Mod] You are now a %s!", key);
    g_PlayerClass[id] = key;      
    ShowHUD(id);
}

public ResetHUD(id)
{
    if (g_PlayerClass[id] == CLASS_NOTHING)
         ChooseAnimal(id);
}

public DeathMsg()
{
    if (!get_cvar_num("sv_animalmod"))
         return;
    
    new attacker = read_data(1)
    
    if (g_PlayerClass[attacker] == CLASS_NOTHING)
         return;
    
    if(g_PlayerLevel[attacker] == NUM_OF_LEVELS)
         return;
    
    g_PlayerXP[attacker] += get_cvar_num("XP_per_kill")
    
    if(g_PlayerXP[attacker] >= LEVELS[g_PlayerLevel[attacker]])
    {
        ++g_PlayerLevel[attacker];
         
        client_print(attacker, _:print_chat, "[Animal Mod] Congratulations! You are now level %i!", g_PlayerLevel[attacker])
    }
    ShowHUD(attacker);
}

ShowHUD(id)    
{
    new HUD[51]
    format(HUD, 50, "[%s]Level: %i XP: %i", CLASS_NAMES[g_PlayerClass[id]], g_PlayerLevel[id], g_PlayerXP[id])

    message_begin(MSG_ONE, gmsgStatusText, {0,0,0}, id)
    write_byte(0)
    write_string(HUD)
    message_end()
}

public client_connect(id)
{
    // A client is coming -> clear all vars for him, so that he doesn't have the pclass/level/xp of the player who was in here before him
    g_PlayerClass[id] = CLASS_NOTHING;
    g_PlayerXP[id] = 0;
    g_PlayerLevel[id] = 0;
}

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:38 pm
by Archive-Poster
To save XP, you could use one of the following methods:
1) Vault (either the old one, or the new one, or Twilight Suzuka's one)
2) MySQL
3) Writing to a file

I myself would support the new vault and mysql.

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:39 pm
by Archive-Poster
Thanx man, definetitaly (sp? lol) worth reading through (I read most of it lol) and learning. Quick question though: why are you using cvars instead of just regular script vars for all that stuff?
Because then you can change "XP per kill" easy, instead of editing the script.

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:40 pm
by Archive-Poster
Something I noticed:

Code: Select all

//Add keys for how many classes you have. In our case 5.(4 animals + exit) (Not 6, since "CLASS_NOTHING" doesnt count) 
//Remeber at it starts at 0, and not 1 
new keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3
That isn't true. MENU_KEY_0 is actually the 0 key, and MENU_KEY_1 is actually the 1 key. This will only let users pick 1, 2, 3, and 0, thus crippling Cow lovers. Also, even using your logic, this wouldn't let players pick Exit. You need this:

Code: Select all

new keys = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_0;
That whole "starts at 0" thing is only in the function that handles menu input.

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:41 pm
by Archive-Poster
You said that MENU_KEY_0 is the actual key 0, but its not.
Well, it works for me.
And im sure your way works too.
But in my tutorial I do it in my way

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 9:45 pm
by Archive-Poster
Normal Vault is so laggy. You should use VaultX! It is (slightly) faster then a local mysql host!

Re: XP Based Plugin - Tutorial!

Posted: Thu Aug 20, 2026 10:36 pm
by Archive-Poster
this may be my newbishness speaking again but in the plugin init u wrote:

Code: Select all

register_menucmd(register_menuid("menu_ChooseAnimal"),1023,"DoChooseAnimal");
shouldnt it be:

Code: Select all

register_menucmd(register_menuid("menu_ChooseAnimal"),],0123,"DoChooseAnimal");
Actually it works the first way too, and in my opinion is a bit cleaner.

Re: XP Based Plugin - Tutorial!

Posted: Sun Aug 23, 2026 9:31 pm
by Archive-Poster
btw, how to add more and more (for an example) run speed per level??
To add more run speed per level its very simple.
go into the plugin_init() and register an event for when players change weapons

Code: Select all

public plugin_init() {
    // ...
    register_event("CurWeapon", "Event_CurWeapon", "be", "1=1");
}
And have event_curweapon check speed, since speed resets when you change weapons, we want to renew it to what we want.
Inside it we will calculate how much speed the player should recieve per level. And then give the player that speed.

Code: Select all

public Event_CurWeapon(id) {
    new Float:Speed = 300.0+(g_PlayerLevel[id]*50)
    set_user_maxspeed(id, Float:Speed)
}