ID:1884375
 
(See the best response by Kaiochao.)
I need help figuring out what the problem is.

Code:
Levels
parent_type = /mob
var/Level = 1
var/Exp = 0
var/ExpN = 12


proc/Check()
if(Exp >= ExpN)
Level++
ExpN = ExpN*7^2/8/3
src<<"Level Up!"
return Check()
else
return Check()


mob/var/Levels/level = new

mob
Stat()
stat("Exp : [level.Exp] | [level.ExpN]")
stat("Level : [level.Level]")


Problem description:

I Get This Error.
proc name: Stat (/mob/Stat)
source file: Basic.dm,22

Why not just put the proc under say mob/player/ unless you intend on having NPC's being able to level aswell? Ter gave me really good write up on a similar topic.

http://www.byond.com/forum/?post=1869567#comment15419097

When I actually tested your code I had 0 errors. So there may be a problem elsewhere in your project.

mob
player
var
Level = 1
Exp = 0
Max_Exp = 100


proc/Check()
//do stuff

Stat()
//stat code
Best response
You didn't include the full runtime error. It starts with "runtime error".

Also, Check() causes an infinite loop because it always calls itself without delay.

You're also using the ^ operator, which is a bitwise operator. If you want exponent, it's **.

In Check(), src refers to your Levels object, not the player that has a reference to it. Your Levels object currently has no reference to the player who is using it.
Kidman90 (/mob): Stat()
runtime error: Cannot read .Exp
proc name: Stat (/mob/Stat)
source file: Basic.dm,24
usr: Kidman90 (/mob)
src: Kidman90 (/mob)
call stack:


Thats all it shows when u run it
In response to Kidman90
Sorry, I was wrong. Although calling Check() would cause an infinite loop, you haven't actually called it yet.

There's still an infinite loop, though. It's caused by this:
Levels
parent_type = /mob

mob
var Levels/level = new

Whenever a mob is created, a Levels is also created. Since Levels is a child of mob, it creates its own Levels, and so on.

The solution to this is to not make Levels a mob. If you want to use composition to build your leveling system with datums, you could try this:
leveling
var mob/owner
var level = 1
var exp = 0
var max_exp = 12

// pass the owner when you create it
New(Owner) owner = Owner

proc/Check()
while(exp >= max_exp)
max_exp *= 7/4 // simplified your thing
level++
owner << "Level up!"

mob
// don't do "= new" here, or else all of your mobs will have it,
// which misses the point of object composition.
var leveling/leveling

// you might do this instead, so that only players can level up
Login()
..()
leveling = new (src)
Math nits:

7^2 is actually 7 XOR 2 in DM. I think you want 7**2, which would just be 49. Also dividing by 8 and then by 3 is the same as dividing by 24. Although if you're multiplying by 49/24, that's close enough to 2 that I'd probably just multiply by 2 and be done with it.

Unless you want fractions in play, I suggest using round().

A better progression, since you're changing max_exp without resetting exp, is probably something like this:

max_exp = round(initial(max_exp) * (EXP_SCALE**level - 1) / (EXP_SCALE-1), 1)

...where EXP_SCALE is the factor by which the new exp per level scales up.

The reason for this: Your current formula would double max_exp at level 2, but since you're already halfway there, level 3 takes pretty much just as much exp to attain as level 2, not twice as much as you intended.

With the new formula, let's say EXP_SCALE is 1.5 and you start off with max_exp=10. Then when you reach level 2:

max_exp = round(10 * (1.5**2-1) / 0.5, 1)
max_exp = round(20 * (2.25-1), 1)
max_exp = round(20 * 1.25, 1)
max_exp = 25

It's clearer in this chart:
Level     delta XP to next      XP total to next
1         10                    10
2         15                    25
3         23                    48
4         34                    82
5         51                    133
What you want is for the delta exp (the additional amount to get to the next level) to go up by EXP_SCALE. Since your level check only uses the total exp, it should take that into account.

Another common way to track level progress is to reset exp at each new level, and only calculate the delta exp to the next level. In that case, you'd have something much simpler:

// this level system only tracks delta exp
proc/LevelCheck()
while(exp >= next_exp)
exp -= next_exp
next_exp = round(next_exp*EXP_SCALE, 1)
level++
owner << "Level up!"

The only downside to this approach is that rounding errors will creep into the delta, so the chart looks more like this:
Level     delta XP to next      XP total to next
1         10                    10
2         15                    25
3         23                    48
4         35                    83
5         52                    135
Over a large number of levels it will probably require more or fewer points, depending on EXP_SCALE and how the rounding errors tend to fall.

One other pro tip: The delta method will scale better with high levels. Eventually, you may reach a point where exp is calculated in the millions. For integer accuracy, BYOND is limited to integers up to 224, which is about 16.8 million. If you go by total exp, you may reach a point where adding the exp from a kill under- or overvalues it, or eventually even does nothing, because the value of exp has gotten so high.

Also if EXP_SCALE is 2, remember that even with delta calculations, you'll hit the integer precision limit before level 24.