ID:2080139
 
(See the best response by Lummox JR.)
Code:
mob
var
stamina = /mob/stamina
stamina
var
current
max
level
experience_current
experience_max
proc
add_experience(value)
if(value)
while(value >= experience_max)
level_up()
experience_current -= 100 // 100 resembles 100%
printl(world.log, "[src].stamina leveled up!")
level_up()
level++
verb
levelup()
usr.stamina.add_experience(200)//should bring out 2 levels
//this doesn't work, which makes me confused


Problem description:

I'm sorry, but i think i need some help understanding what exactly i am doing here. I don't even know if this works, or how it's supposed to be done.

What i am trying to achieve here, is a system which involves each stat having it's own path with unique proc's and var's, for example:
mob/stamina/proc/add_experience(value)
mob/stamina/var
current
max
level
experience
experience_max

You can see where i am going with this.

I am having trouble undestanding how to use individual paths like this in a scenario where I need to actually use them, for example how to level up src.stamina. I think the code above explains what i mean.

Please help me. I cannot figure out how this works.


Disclaimer
I didn't really intend to use individual path's for each stat, but i thought it was good practice and that i could apply a structure like this elsewhere.
Best response
You don't want stamina to be defined as /mob/stamina type, because that would make it a mob. I think what you really want is a datum.

attribute
var/value = 0
var/limit = 0 // max is a built-in proc, so don't use it as a var name
var/level = 1
var/xp = 0
var/xp_next = 100 // xp for next level
var/xp_gain_rate = 1.5

New(name,value=0,limit=0,level=1,xp_next=100)
src.name = name
src.value = value
src.limit = limit
src.level = level
src.xp_next = xp_next

proc/GainXP(_xp, owner)
xp += _xp
. = level
while(xp >= xp_next)
++level
xp -= xp_next
xp_next = round(xp_next * xp_gain_rate, 1)
if(. != level)
owner << "Your [name] is now at level [level]."

mob
var/list/stats

New()
// you might not want stats for all mobs, like for instance NPCs,
// so plan accordingly
stats = list(\
new/attribute("stamina",10,10),
new/attribute("awesomeness",5,5),
new/attribute("moxie",3,3))

proc/GetAttibute(attr)
var/attribute/A = stats && stats[attr]
return A ? A.value : 0

proc/UseAttibute(attr, amount)
var/attribute/A = stats && stats[attr]
if(A) A.value = max(0, A.value - amount)

proc/GainXP(attr, amount)
var/attribute/A = stats && stats[attr]
if(A) A.GainXP(amount, src)
Thank you very much!
Helps out a ton!

This is actually a brilliant way of handling it, and precisely what i wanted. But i failed miserable and got confused about how to do it

Now i haven't programmed in DM for a while, and i wasn't any good at it previoustly, but now i realize... Since i didn't think DM was class-oriented i thought for example having "everything" for mobs inside /mob would be the better choise. Boy was i wrong. Datun seems to be just another interpretation for class. Jesus christ i was so blind when i was younger.
Ouch, i tend to get bugs with the list stats[attr] being empty. Something i am doing wrong?

Now, i have just tryed adjusting my current practice-project with your datum, but i struggle figuring out why
var/attribute/A = stats && stats[attr] // Equals: null


I have pretty much the identical code, and i tryed tossing in
mob
verb
level()
gain_xp("stamina",100)
get_stat(name as text)
printl(usr, "[get_attribute(name)]", "chat.output")
//printl( ref, message, interface )


Any sort of textoutput to debug the code suggests the error being var/attribute/A:
mob

proc/gain_xp(attr, amount)
var/attribute/A = stats && stats[attr]
if(A) A.gain_xp(amount, src)
else throw EXCEPTION("invalid attribute: [A]")
/*
runtime error: Exception thrown: invalid attribute: (/exception)
proc name: gain xp (/mob/proc/gain_xp)
source file: code.dm,48
usr: (src)
src: Tafe (/mob)
src.loc: Mountain (1,1,1) (/turf/earth_outside/mountain)
call stack:
Tafe (/mob): gain xp("stamina", 100)
Tafe (/mob): level()
*/


I don't quite understand how do go about this, since
mob
verb/view_stats()
for(var/attribute/A in stats)
printl(world.log, "[A].value=[A.value]")
printl(world.log, "[A].limit=[A.limit]")
printl(world.log, "[A].level=[A.level]")
printl(world.log, "[A].xp=[A.xp]")
printl(world.log, "[A].xp_next=[A.xp_next]")
/*
stamina.value=10
stamina.limit=10
stamina.level=1
stamina.xp=0
stamina.xp_next=100
*/

Runs all fine
I made a mistake in my code, here:

        stats = list(\
new/attribute("stamina",10,10),
new/attribute("awesomeness",5,5),
new/attribute("moxie",3,3))

It should actually be:

        stats = list(\
"stamina" = new/attribute("stamina",10,10),
"awesomeness" = new/attribute("awesomeness",5,5),
"moxie" = new/attribute("moxie",3,3))