AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   XP Based Plugin - Tutorial! (https://forums.alliedmods.net/showthread.php?t=12518)

XunTric 04-17-2005 08:42

XP Based Plugin - Tutorial!
 
This might be worth a "usefull link" bailopan :P


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...


Thanks to:
• XxAvalanchexX (Extra big thanks to you :P)
• Knekter
• Xeroblood
• PM


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.

Ill maybe add more later...


Update log:
1.2
-Added Save XP

1.1
-Fixed all errors in whole plugin (with help from PM)
-Added a "Change Animal" command for players

1.0
-Tutorial released.

-------------------------------------------------------------------------

As in all scripts, include stuff :P
Code:
#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:
#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? :P
Code:
#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:
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:
new const CLASSES[MAXCLASSES][] = {     "None",     "Dog",     "Cat",     "Horse",     "Cow" }

Just some stuff for the ShowHUD... Will explain later.
Code:
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:
//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:
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:
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:
  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:
  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:
  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:
    //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:
  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:
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:
  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 :P
This is the thing in the corner of your screen in game that shows your animal, xp and level.
Code:
  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:
    #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 }

n0obie4life 04-17-2005 08:46

err

tutorial. not toturial.

btw, did u get this from my idea?

XunTric 04-17-2005 08:48

Oh sorry... my english :P
Editing now.

Actually yes.
I was allready thinking of making a toturial, but the animal thing was your idea. :P

v3x 04-17-2005 08:52

Nice man..

May I make one suggestion?

Instead of all of those if() statements, use a switch() statement..
Code:
switch(key) {     case 0: {         // ..     }     case 1: {         // ..     }     case 2: {         // ..     }     // etc. }
:)

n0obie4life 04-17-2005 08:52

another error.....seems to be a global one.


Allready . ITS ALREADY :P.

PM 04-17-2005 09:28

Hrm, I altered a bit of your code ;)
Also, excuse my use of semicolons =P


EDIT: Actually compiles now ;)

Code:
#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; }

Note that I haven't tried to compile it, so it may be broken.

Belsebub 04-17-2005 10:21

yea PM your code is broken

errors:

Code:

(12) : error 001: expected token: "}", but found "-identifier-"
(17) : error 010: invalid function or declaration
(24) : error 017: undefined symbol "NUM_OF_CLASSES"
(35) : error 008: must be a constant expression; assumed zero
(79) : warning 213: tag mismatch
(86) : warning 213: tag mismatch
(106) : warning 213: tag mismatch
(109 -- 111) : warning 213: tag mismatch
(111) : error 001: expected token: "]", but found ")"
(113) : error 017: undefined symbol "PlayerLevel"
(113) : warning 215: expression has no effect
(113) : error 001: expected token: ";", but found "]"
(113) : error 029: invalid expression, assumed zero
(113) : fatal error 107: too many error messages on one line


v3x 04-17-2005 10:24

It's not the full code.

PM 04-17-2005 10:27

I'll fix it then, one sec...

EDIT: Okay, compiles, no idea whether it runs though!

XunTric 04-17-2005 11:22

You didnt have to steal my thread :P

Well... Thanks PM
I credited you.

And btw, I use this on my code on my mod, and I doesnt have to set class to "nothing" when they connect.
Since its first class, it chooses it auto (I think). Well, works for me... :P
And if im going to add save XP later, it cant reset all stuff on connect? :P


All times are GMT -4. The time now is 17:25.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.