ID:144072
 
Arrow Code:
obj/Arrow
icon = 'weapons.dmi'
icon_state="Arrow_Moving"
density = 1
Bump(mob/b)
if(ismob(b))
if(b.isplayer==0)
b.hp -= 25
b.death_check()
else
del(src)
else
del(src)

obj/proc/Fire(var/obj/O
var/L
var/PL
start
PL = L
step(O,O:dir)
L = O:loc
sleep(10)
if(PL == L)
del(O)
else
goto start

mob/verb/Fire()
var/obj/O = new /obj/Arrow(usr.loc)
O:dir = usr.dir
O:owner=usr.key
O:Fire(O)


Death_Check Code:
    proc/death_check(mob/M as mob)//handles death
if(src.hp <= 0)
M <<"You killed [src]!"
if(src.client)
src <<"[M] killed you!"
src.loc = locate(7,290,1)
src.hp = src.maxhp
src.canbuild = 0
else
var/YIN=rand(1,10)
var/BYIN=rand(25,100)
src.loc=locate(0,0,0)
if(ismob(M))
if(src.GOOGLEPLEX==1)
M.crowns+=BYIN
M.contents+=new/Items/Frog_Head
M<<"Congratulations! You got the Frog Head from the Evil Frog!!"
world<<"[M] has killed the Evil Frog!"
else
M.crowns+=YIN
sleep(1200)
src.loc=locate(src.sx,src.sy,src.sz)
src.hp=src.maxhp
else
usr=M.owner
usr.crowns+=YIN
if(src.GOOGLEPLEX==1)
usr.contents+=new/Items/Frog_Head
usr<<"Congratulations! You got the Frog Head from the Evil Frog!!"
world<<"[M] has killed the Evil Frog!"
del(M)
sleep(1200)
src.loc=locate(src.sx,src.sy,src.sz)

Problem description:

When I kill the monster, I get this runtime error:

runtime error: Cannot read null.owner
proc name: death check (/mob/proc/death_check)
source file: RisingEmpire.dm,1524
usr: 0
src: Frog (/Enemies/Normal)
call stack:
Frog (/Enemies/Normal): death check(null)
Arrow (/obj/Arrow): Bump(Frog (/Enemies/Normal))
Arrow (/obj/Arrow): Fire(Arrow (/obj/Arrow))
{OWNER} Mikal (/mob/character): Fire()

I believe the arrow is deleted before it can read the owner. Please help if you can. =)


Michael3131 wrote:
I believe the arrow is deleted before it can read the owner. Please help if you can. =)

Actually, it doesn't look like the arrow is getting deleted until it moves to the spot occupied by the enemy. Your main problem is easily fixable, but will present more problems afterwards (like the arrow never getting deleted, or hitting more people).

Starting from top to bottom, the main problem lies in Bump(). You're not sending the owner (that variable should point to the mob itself, though) of the arrow to death_check(). I know you have death_check() set up to receive an arrow, but you didn't send it and it's better to just send the mob. =) Also, it looks like you want the arrow to be deleted whenever it bumps into anything, but I'm going to guess you don't want it sitting on the edge of the map when there's nothing to Bump() either so we'll save the deleting for the Fire proc.
obj/Arrow
icon = 'weapons.dmi'
icon_state="Arrow_Moving"
density = 1
Bump(mob/b)
if(ismob(b))
if(b.isplayer==0) // if(!b.isplayer) is a good idea if this is a boolean variable.
b.hp -= 25 // Consider making a take_damage() proc. Modularization FTW!
b.death_check(src.owner)


Fire, apart from having a few common no-nos, has the distinct problem of assuming that the arrow will eventually end up in O's loc. It will if there happens to be a person on the same x or y axis that you're facing, but there's a much better way. step() will return a FALSE value if movement fails (if something is in the way (Bump()ed), or if there is no location to move to (the edge of the map)). Since you'll only want this loop going while the arrow is still around (and the arrow should be moving while it's around), while() is clearly a better choice than goto.
obj/proc/Fire(var/obj/O)
while(step(O,O.dir)) // No advantage for a colon here.
sleep(10)
del O


Consider type casting as an alternative to using the colon operator. It actually saves you typing here. =) Also, remember that I'm making owner hold the mob instead of the key.
mob/verb/Fire() 
var/obj/Arrow/O = new (usr.loc)
O.dir = usr.dir
O.owner=src
O.Fire(O)


I don't really know your plan here, so I'm short on some ideas. I would suggest that the item be created inside of M instead of added to the contents list, contents is a special list and I'm not sure how it responds to that. Refilling the enemies health before placing them on them map makes more sense to me, but I doubt anyone could actually attack it in such a short amount of time. =) Of course, since we're not sending any arrows to death_check(), we can get rid of the second half of this proc. =)
    proc/death_check(mob/M)//handles death   the as mob clause is only needed for input.
if(src.hp <= 0)
M <<"You killed [src]!"
if(src.client)
src <<"[M] killed you!"
src.loc = locate(7,290,1)
src.hp = src.maxhp
src.canbuild = 0
else
var/YIN=rand(1,10)
var/BYIN=rand(25,100)
src.loc=locate(0,0,0)
if(ismob(M))
if(src.GOOGLEPLEX==1)
M.crowns+=BYIN
new/Items/Frog_Head(M)
M<<"Congratulations! You got the Frog Head from the Evil Frog!!"
world<<"[M] has killed the Evil Frog!"
else
M.crowns+=YIN
sleep(1200)
src.hp=src.maxhp
src.loc=locate(src.sx,src.sy,src.sz)
In response to YMIHere
Ah! Thank you for replying to my topic in such great detail! ^_^

I tested the code and it works perfectly. Thank you so much for the help.
In response to Michael3131
D'oh! I just came back to shamelessly promote my type casting article by adding a link. Oh well, I'll edit it in shortly anyways. =) Glad to help.
In response to YMIHere
Yeah, here are some comments about it (you had that coming for shamelessly plugging it :p):

--Teh saying there is no problam with colon??? dieee.
Really, unless you really have to re-typecast a certain var a lot, you should never use the colon. Unless you're very lazy, but as you said, typecasting will make it easier in the long run. It can also help with code readability.

--You went off the scope of just type casting, really. I don't blame you though since if you're already posting an article then it needs to have some length, there isn't much to say about 'just type casting'.

--Oh yeah, you refer to "problems" that have nothing to do whatsoever with typecasting and also exist when using the colon, as "evils of typecasting" etc. :P At most, it can confuse newbs because they think typecasting limits a var to a certain type.
I would reccomend makeing 10 files with 100 lines of code rather than 1 with a 1000. Organizing is key.
In response to Kaioken
Kaioken wrote:
--Teh saying there is no problam with colon??? dieee.
Really, unless you really have to re-typecast a certain var a lot, you should never use the colon. Unless you're very lazy, but as you said, typecasting will make it easier in the long run. It can also help with code readability.


There really isn't a problem with it, it's just with how a lot people use it. "Oh, usr.hp gave me an error, but usr:hp doesn't. Fixed!" =) Why shouldn't people use the colon? It's not as safe, right? I think you'll find I already said that in the same paragraph. =p

--You went off the scope of just type casting, really. I don't blame you though since if you're already posting an article then it needs to have some length, there isn't much to say about 'just type casting'.

Yeah, I tried to keep it entertaining. Reading it again it just sounds silly. =\

--Oh yeah, you refer to "problems" that have nothing to do whatsoever with typecasting and also exist when using the colon, as "evils of typecasting" etc. :P At most, it can confuse newbs because they think typecasting limits a var to a certain type.

I specifically show that you can assign a different type to a variable, and state it repeatedly. As far as the evilness of type casting versus the evilness of the colon (neither or them have problems themselves, obviously, there are just some common user errors), sure you could assign an object to the wrong type and use a colon, but generally the colon is being used in place of type casting. =) It's the same problem without type casting involved (which was covered), I don't really see how someone could think that the colon doesn't have this problem considering it has it to a greater extent. =\

I appreciate the input, if you have any other thoughts please feel free to share. I'll definitely leave out the abuse of the reader next time I write an article, it really doesn't add anything. =)
In response to Revojake
Whoa... you limit each file to just 100 lines? My 10% game already has some 300 and 400 line files. Just my file with only my #defines and global vars (and not all of them) is 100 lines. :P

Tell you what, mate; 'organizing' isn't 'keeping things separate'. Actually it is closer to the opposite, when organizing you are mostly grouping things. You should group your code so parts that have to do with eachother are in the same file, with a filename that matches the "topic". ie verbs.dm with your common general verbs,monsters.dm with monster prototype definitions, AI procs, and whatnot. And so you can have items.dm,turfs.dm,testing.dm, and whatnot. Also, if you're not using a library for that, then procs.dm with the general-usage procs you'll be using a lot.
If one of those files ends up with 200 lines, theres no reason to split it off to another file... that will just make it less organized if you end up having tons of files all over the having problems finding stuff.