ID:262168
 
I've constructed my own Skill Level Up code, and it's going quite well if i say so myself. Be there's this certain part that has gotten be to ask some questions. When I execute the verb, I get this runtime error:

runtime error: Cannot read null.miningexp proc name: LevelUp (/mob/skill/levelup/mining/proc/LevelUp) source file: Skill Level Up.dm,7 usr: Tikey (/mob/players/Wizard) src: null call stack: LevelUp(Tikey (/mob/players/Wizard)) Mineral Rock (/mob/Skills/Rock): Mine()

As you see, it's reading null.miningexp. Here's the LevelUp() to it:

mob
skill
levelup
mining
proc
LevelUp()
if(src.miningexp >= src.miningmaxexp)
src << "<font color=green size=1 face=Arial>Your mining is now [mining+1]!"
src.mining++
src.miningmaxexp+=2
src.miningexp=0


I though that's all right. But what I suspect is that the problem is in the mine verb itself. Which I will show you now:

mob
Skills
icon = 'skills.dmi'
Rock
icon_state = "Rock"
name = "Mineral Rock"
density = 1
verb/Mine()
set src in oview(1)
var/obj/pickaxe = locate(/obj/pickaxe) in usr.contents
if(pickaxe)
if(mining == 1)
return
else
mining=1
usr << "<B><font color=white size=1 face=Arial>\[SKILL]: You begin to mine."
sleep(30)
if(prob(10+usr.mining))
usr << "<B><font color=white size=1 face=Arial>\[SKILL]: You find to what you see is a mineral!"
usr.contents+=new/obj/JEWELS/Granite
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return
else
usr << "<b><font color=white size=1 face=Arial>You don't find anything."
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return

/*--SNIP--*/

else
usr << "<font color=white size=1 face=Arial>You don't have a pick axe!"
mining=0
return


Now, what I think the problem is, is that I'm calling call() wrong. If this is the case, can someone tell me how to fix it? If not, give me some tips on how to fix it. Thank you and good night.

~Tikey
Hmm... your code is interesting, to say the least. Anyhow, since call() doesn't belong to anything in particular, it isn't called from any obj or mob (ie. no src). What you CAN do, since you're passing in usr as an argument, is include support for an argument in the LevelUp() proc:

LevelUp(mob/M)
if(M.miningexp >= M.miningmaxexp)
M << "<font color=green size=1 face=Arial>Your mining is now [mining+1]!"
M.mining++
M.miningmaxexp+=2
M.miningexp=0


This way, usr is passed in from the verb, and referenced as M by the call() proc. Please note, however, that M's type will need to be a mob which supports miningexp, miningmaxexp, mining, etc., or you'll wind up with more runtime errors. So, if your player characters are all of type /mob/PC, then make the appropriate change to the argument for LevelUp(). Hopefully this helps.
In response to Igmolicious
I also had to add "M" to "mining+1". Othe than that, all of it works fine! Thanks!
In response to Mega fart cannon
Er, isn't it easier to do this?

LevelUp(mob/M)
if(M.miningexp >= M.miningmaxexp)
M.mining++
M << "<font color=green size=1 face=Arial>Your mining is now [mining]!"
M.miningmaxexp+=2
M.miningexp=0
In response to Elation
mob
Skills
icon = 'skills.dmi'
Rock
icon_state = "Rock"
name = "Mineral Rock"
density = 1
verb/Mine()
set src in oview(1)
var/obj/pickaxe = locate(/obj/pickaxe) in usr.contents
if(pickaxe)
if(mining == 1)
return
else
mining=1
usr << "<B><font color=white size=1 face=Arial>\[SKILL]: You begin to mine."
sleep(30)
if(prob(10+usr.mining))
usr << "<B><font color=white size=1 face=Arial>\[SKILL]: You find to what you see is a mineral!"
usr.contents+=new/obj/JEWELS/Granite
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return
else
usr << "<b><font color=white size=1 face=Arial>You don't find anything."
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return
if(prob(9+usr.mining))
usr << "<B><font color=white size=1 face=Arial>\[SKILL]: You find to what you see is a mineral!"
usr.contents+=new/obj/JEWELS/Gem
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return
else
usr << "<b><font color=white size=1 face=Arial>You don't find anything."
mining=0
usr.miningexp++
call(/mob/skill/levelup/mining/proc/LevelUp)(usr)
return
else
usr << "<font color=white size=1 face=Arial>You don't have a pick axe!"
mining=0
return


If I wanted to make the user to mine different items, would this be how you would call it?
That you're even using call() for this in the first place is what's wrong. You don't need it there; don't use it.

That, and the if(mining==1) test should be if(mining) instead, since this is a true/false value.

Lummox JR
In response to Lummox JR
Lummox JR wrote:
That you're even using call() for this in the first place is what's wrong. You don't need it there; don't use it.

Ah, but how would I call LevelUp() without doing it to the same skill?

mob
skill
levelup
mining
proc
LevelUp(mob/players/M)
if(M.miningexp >= M.miningmaxexp)
M << "<font color=green size=1 face=Arial>Your mining is now [M.mining+1]!"
M.mining++
M.miningmaxexp+=2
M.miningexp=0
fishing
proc
LevelUp(mob/players/M)
if(M.fishingexp >= M.fishingmaxexp)
M << "<font color=green size=1 face=Arial>Your fishing is now [M.fishing+1]!"
M.fishing++
M.fishingmaxexp+=2
M.fishingexp=0
meditating
proc
LevelUp(mob/players/M)
if(M.meditatingexp >= M.meditatingmaxexp)
M << "<font color=green size=1 face=Arial>Your meditating is now [M.meditating+1]!"
M.meditating++
M.meditatingmaxexp+=2
M.meditatingexp=0
In response to Mega fart cannon
Your LevelUp() procs are defined incorrectly. They don't need an M argument, because they already belong to a mob and that's the one (src) that's leveling up. No other mobs are involved in this process, so the argument is unneeded.

You'll do better to change all instances of M in those procs to src, and remove the argument. When you call it, call it from the verb as usr.LevelUp().

I see now though why you were trying to use call(). It's because of the path system you've structured for all these skills and different LevelUp() procs. However, the fact that those are all so similar is a strong clue as to what you can do differently to combine them. Here, associative lists are your friends.

Consider this:
mob/proc
SkillUp()
// for every skill you know
for(var/S in skillexp)
if(!skillmaxexp[S])
skillmaxexp[S] = 100 // default
if(skillexp[S] >= skillmaxexp[S])
src << "<span class=levelup>Your [S] skill is now at level [++skills[S]]!</span>"
skillexp[S]-=skillmaxexp[S]
skillmaxexp[S]=round(skillmaxexp[S]*1.5,1)

Notice how much cleaner that is. One proc, no huge panoply of vars with similar names like miningexp, fishingexp, etc. Those associative lists would be defined like this:
mob
var/list
skills
skillexp
skillmaxexp

When checking or improving a skill you could simply call another proc:
mob/proc
CheckSkill(S)
if(!skills) return 0
return (skills[S] || 0)

LearnSkill(S, n)
// if these lists haven't been defined yet, define them
if(!skills)
skills = new
skillexp = new
skillmaxexp = new
// the < in this line instead of <= is not a typo
for(var/i=1, i<args.len, i+=2)
S = args[i]
n = args[i+1]
skillexp[S] += n
SkillUp()

The only possible trouble is that I don't recall if the skillexp[S]+=n line is kosher. If you get a type mismatch runtime error on that, you'll have to insert this line just before it:
if(!skillexp[S]) skillexp[S]=0

Now to call LearnSkill(), just follow the name of the skill with the points learned, like LearnSkill("fishing",3). And it takes multiple arguments, so you can use LearnSkill("mining",5,"gemology",1) to learn several skills at once.

So all in all, you now have a much cleaner way of managing all those skills, without having 3 vars and a proc for each one.

Lummox JR