XP not being given to player? (1.4)

I

IncuTyph

Guest
Hi, I'm fairly new to GML. I've been slowly working on my first game, and so far things have been pretty good. I came across an issue that is probably super simple to fix, but I'm not entirely sure what is wrong with what I have.

So, I'm trying to implement an XP system. When a monster is killed, its base xp (bxp) value (the amount of xp scales with monster level; think Pokemon) is supposed to be added to the player's (or other party members' once I actually add them) xp totals. This part seems to work, as the debug message I put in the monster's code shows when it's killed. However, what doesn't work is when the xp the player gets doesn't advance them to the next level.

This is the monster's code. Currently just touching the monster inflicts damage on it. This is in the monster's collision event with the player object:

Code:
if hp <= 0
    {
        with(obj_player)
            {
            xp += obj_goobey_grey_ow.bxp; //(player?)xp += monster's bxp
            show_debug_message("xp gained");
            }
    instance_destroy();
    }
As I said, this displays the debug message, so I'm assuming it works. This is my player's code though (Create event):

Code:
lvl = 1;
xp = 0;
nlvl = lvl*10; //nlvl stands for next level

if xp >= nlvl
    {
    lvl += 1;
    show_debug_message("Leveled up!")
    }
In the monster's code, I did try using self.xp and obj_player.xp but it doesn't seem to work either. I'm just not sure what's wrong with what I have. Also, I do have the monster set to give 10,000 xp, so surely I meet the requirements to level up a few times with that. Any help would be appreciated though.
 
You can use the dot operator to link an instance to a variable, then you can just use what you commented out
Code:
if hp <= 0
   {
   obj_player.xp += bxp;
   show_debug_message("xp gained");

   instance_destroy();
   }
 

TailBit

Member
The create event is only run once when the object is created, so it will never check if you have enough xp after a kill.

Instead consider doing the level up check in the xp code:
Code:
with(obj_player)
           {
           xp += other.bxp; //(player?)xp += monster's bxp
           show_debug_message("xp gained");
           }
in with statements, you can use other to refer back to the spesific monter that told player to increase xp
 
I

IncuTyph

Guest
The create event is only run once when the object is created, so it will never check if you have enough xp after a kill.

Instead consider doing the level up check in the xp code:
Code:
with(obj_player)
           {
           xp += other.bxp; //(player?)xp += monster's bxp
           show_debug_message("xp gained");
           }
in with statements, you can use other to refer back to the spesific monter that told player to increase xp
That might be my problem. My player's stats are all in the create event. I'm not sure what else to stick that in though. A step event? A script?
 

TsukaYuriko

☄️
Forum Staff
Moderator
The code you quoted should be executed whenever the player earns experience. Ideally, you'd have this in a script so you can call it whenever the player should get experience, and could execute the level-up check there as well.

If you're unsure what sort of code goes where, I suggest refreshing your knowledge about the basic types of events.
 
I

IncuTyph

Guest
The code you quoted should be executed whenever the player earns experience. Ideally, you'd have this in a script so you can call it whenever the player should get experience, and could execute the level-up check there as well.

If you're unsure what sort of code goes where, I suggest refreshing your knowledge about the basic types of events.
Sorry, I've just been a tad burnt out from doing other things. Been a long day and ended up having a brain fart. Stuck it in a step event and it works now. Kinda mad at myself for not just trying that first, but at least it's working!
 

TsukaYuriko

☄️
Forum Staff
Moderator
No need to apologize for anything - remembering that trying stuff yourself is always an option is a step forward, if you ask me. :)
 
I

IncuTyph

Guest
No need to apologize for anything - remembering that trying stuff yourself is always an option is a step forward, if you ask me. :)
I usually try things out, but when I get stuck, I like to have a soundboard because I'll forget basic stuff after trying to fiddle with something for so long.

I must say though that as I was typing the last post, I actually did discover a problem! Yes it levels, but I don't think my nlvl variable is updating. I set my enemy to give out 50 xp upon dying, and had the nlvl value set to lvl*100 (so at lvl 1, this would be 100 xp). Ideally, killing two enemies would give a total of 100 xp, and then nlvl would be 200 to get to lvl 3. However, if I kill another enemy, I'll level up immediately again, and it levels infinitely. I did try moving the lvl, xp, and nlvl variables into the step event, but then levelling doesn't actually happen. Just having the nlvl in Step DOES level, but if I get another enemy, I'll get another level, while with a 3rd I'll level up twice, and a 4th enemy levels me 3 times (and so on). Tried several combinations of the variables being moved between Step and Create, and either I level infinitely, consecutively, or not at all. I'm wondering if my experience formula is just bad or something, but I can't work it out. Tried setting it to lvl*150 and it just says the same (though it takes a bit longer obviously).
 
Post the formula and such you're using. It'll also be better to move that stuff to another event, one that only fires off when it needs to (such as the Destroy event of an enemy)
 
I

IncuTyph

Guest
Post the formula and such you're using. It'll also be better to move that stuff to another event, one that only fires off when it needs to (such as the Destroy event of an enemy)
So this, again, is the enemy's collide event with the player:
Code:
if hp <= 0
   {
   obj_player.xp += bxp;
   obj_player.xptotal += obj_player.xp; //I have this because somehow I thought if I had an xptotal separate from xp, I could somehow use it to correct this levelling issue. I don't think it's needed after all, honestly.
   show_debug_message("xp gained");

   instance_destroy();
   }
I have it in the collide event because at the moment I have no battle system in place, so simply the player touching the enemy kills it.
This is in the player's step event:
Code:
nlvl = lvl*150; //this is the formula for determining the xp needed for next level (nlvl)
hp = ((2*bhp*lvl)/100)+50; //these variables are for stat calculations. Not using them yet so i'm not worried about their placements
mp = ((2*bmp*lvl)/100)+50;
str = ((2*bstr)*lvl)/100 +50;
mag = ((2*bmag)*lvl)/100 +50;
p_def = ((2*bp_def)*lvl)/100 +50;
m_def = ((2*bm_def)*lvl)/100 +50;
bspd = ((2*bbspd)*lvl)/100 +50;

if xptotal >= nlvl
    {
    lvl += 1;
    show_debug_message("Leveled up!") //this part seems to work as the debug message shows
    }
This is in my Create event:
Code:
///Stats
bhp = 80; //the b stands for base stat, for influencing growth
bmp = 200;
bstr = 70;
bmag= 230;
bp_def = 115;
bm_def = 115;
bbspd = 70;
corruption = 50;
lvl = 1; //I've tried moving these around in the step event with mixed to no results. 
xp = 0;
xptotal = 0;
Sorry if it's weirdly messy or spaghetti-like.
 

TailBit

Member
Your problem there is that you increase xptotal exponensly with your xp
50 in xp, 50 in total -> 100, 150 -> 150, 300 -> 200, 500
So it is messing up your system
Code:
if hp <= 0
    {
        with(obj_player)
            {
            xp += other.bxp; //(player?)xp += monster's bxp
            if(xp >= nlvl){
                lvl++;
                nlvl = lvl * 100;
            }
// You could also adjust all the variables here after increasing lvl
            show_debug_message("xp gained");
            }
    instance_destroy();
    }
You do want a lot of enemies to drop xp, so I would consider making it a script like scr_give_xp, moving the whole with into the script and replacing bxp with argument0.

Then the enemy code in the brackets would just be
Code:
scr_give_xp(bxp);
instance_destroy();
 
Last edited:
I

IncuTyph

Guest
Your problem there is that you increase xptotal exponensly with your xp
50 in xp, 50 in total -> 100, 150 -> 150, 300 -> 200, 500
So it is messing up your system
Code:
if hp <= 0
    {
        with(obj_player)
            {
            xp += other.bxp; //(player?)xp += monster's bxp
            if(xp >= nlvl){
                lvl++;
                nlvl = lvl * 100;
            }
// You could also adjust all the variables here after increasing lvl
            show_debug_message("xp gained");
            }
    instance_destroy();
    }
You do want a lot of enemies to drop xp, so I would consider making it a script like scr_give_xp, moving the whole with into the script and replacing bxp with argument0.

Then the enemy code in the brackets would just be
Code:
scr_give_xp(bxp);
instance_destroy();
After a long day of retail work, I finally have a chance to try this out. I did drop the xptotal variable, but my problem doesn't seem to be fixed. The problem is that the player isn't actually levelling. I put my variables for level into my step event (the lvl, xp, and nlvl were in a create event) and still no. Here's my player's step event:
Code:
//effective stats
lvl = 1;
nlvl = lvl*100;
xp = 0;
hp = ((2*bhp*lvl)/100)+50; //stat calculating formulas. the b in front means 'base'
mp = ((2*bmp*lvl)/100)+50;
str = ((2*bstr)*lvl)/100 +50;
mag = ((2*bmag)*lvl)/100 +50;
p_def = ((2*bp_def)*lvl)/100 +50;
m_def = ((2*bm_def)*lvl)/100 +50;
bspd = ((2*bbspd)*lvl)/100 +50;

if xp >= nlvl
    {
    lvl += 1;
    show_debug_message("Leveled up!") //the debug message is not displaying
    }
I just don't understand what could be wrong.

Sorry if I'm frustrating lol
 

Simon Gust

Member
After a long day of retail work, I finally have a chance to try this out. I did drop the xptotal variable, but my problem doesn't seem to be fixed. The problem is that the player isn't actually levelling. I put my variables for level into my step event (the lvl, xp, and nlvl were in a create event) and still no. Here's my player's step event:
Code:
//effective stats
lvl = 1;
nlvl = lvl*100;
xp = 0;
hp = ((2*bhp*lvl)/100)+50; //stat calculating formulas. the b in front means 'base'
mp = ((2*bmp*lvl)/100)+50;
str = ((2*bstr)*lvl)/100 +50;
mag = ((2*bmag)*lvl)/100 +50;
p_def = ((2*bp_def)*lvl)/100 +50;
m_def = ((2*bm_def)*lvl)/100 +50;
bspd = ((2*bbspd)*lvl)/100 +50;

if xp >= nlvl
    {
    lvl += 1;
    show_debug_message("Leveled up!") //the debug message is not displaying
    }
I just don't understand what could be wrong.

Sorry if I'm frustrating lol
To be in the clear, the code you've shown is the step event? You mentioned lvl, xp and nlvl are in the create event, so what are lvl and xp doing here in the step event? If you continously set xp to 0 and lv to 1, they will be set to that every frame. Say you gain 40 xp, next frame xp is just set back to 0.
 

Yal

🐧 *penguin noises*
GMC Elder
Yeah, you should ideally only set level/EXP to 0 once, perhaps at the game start (not every room, and definitely not every step) and then store them globally (e.g. in a global array if you've got more than one player - each player would then have a "player_id" that tells the game which of the levels / EXPs / other stats to use).
Code:
if hp <= 0
   {
   global.xp[other.player_id] += bxp;
   global.xptotal[other.player_id] += global.xp[other.player_id]; 
   show_debug_message("xp gained");

   instance_destroy();
   }
 
I

IncuTyph

Guest
To be in the clear, the code you've shown is the step event? You mentioned lvl, xp and nlvl are in the create event, so what are lvl and xp doing here in the step event? If you continously set xp to 0 and lv to 1, they will be set to that every frame. Say you gain 40 xp, next frame xp is just set back to 0.
I had them in the Create event first, and when that didn't work I moved them to the Step event to see if that would change anything. It didn't lol




Yeah, you should ideally only set level/EXP to 0 once, perhaps at the game start (not every room, and definitely not every step) and then store them globally (e.g. in a global array if you've got more than one player - each player would then have a "player_id" that tells the game which of the levels / EXPs / other stats to use).
Code:
if hp <= 0
   {
   global.xp[other.player_id] += bxp;
   global.xptotal[other.player_id] += global.xp[other.player_id];
   show_debug_message("xp gained");

   instance_destroy();
   }
I think I see what you mean. So I'd set the player (there's only one player, but there's party members [RPG], so I assume it would still be like your example) lvl, xp, maybe the nlvl into a game start event, but set them as global variables? I want to make sure I understand this before I screw it up worse.
 

Yal

🐧 *penguin noises*
GMC Elder
Set them at the start of the game (doesn't need to be a Game Start event, I prefer having stuff in the Create event of a special "setup" object in the first room, so that IF I decide to add a new room before that - e.g. for most of the game the first room is a title screen, but when it's almost complete, I add a new "Yal logo" room before that - things aren't broken), then don't ever reset them again - only add to them when the player gets EXP or levels up. Making them global means they carry over between rooms, so you don't need to set them at the create/room start to avoid "variable doesn't exist" errors. Global things exist forever once you set them once (until you quit/restart the game).
 
I

IncuTyph

Guest
Set them at the start of the game (doesn't need to be a Game Start event, I prefer having stuff in the Create event of a special "setup" object in the first room, so that IF I decide to add a new room before that - e.g. for most of the game the first room is a title screen, but when it's almost complete, I add a new "Yal logo" room before that - things aren't broken), then don't ever reset them again - only add to them when the player gets EXP or levels up. Making them global means they carry over between rooms, so you don't need to set them at the create/room start to avoid "variable doesn't exist" errors. Global things exist forever once you set them once (until you quit/restart the game).
You know, I never thought of making a title screen a room (don't have any yet; this is something I haven't been working on for long). I'll try making a stat-handling setup object for my first room and see if that works. I was going to implement saving (it is an RPG after all) but I'm nowhere near doing that so I think I'll be ok with values resetting when I boot up to test for now.
 
Top