ID:144493
 
Code:
mob
proc
wander()
sleep(20)
step_rand(src)
while(src)
for(var/mob/M in view(3))
if(M == src)
wander()
return
if(M == istype(M,/mob/enemy/zombie))
wander()
return
zattack(M)
wander()


Problem description: The problem with the above code is not that it doesn't work, because it does. But it's that after a few moments of the game running, it crashes, and says this:

Zombie (/mob/enemy/zombie4): Move(the g1 (65,22,1) (/turf/nat/ngrass/g1), 8)
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
...
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): New(the s4 (22,1,1) (/turf/nat/sand/s4))
Shutting down after encountering too many critical errors.
runtime error: Maximum recursion level reached (perhaps there is an infinite loop)
To avoid this safety check, set world.loop_checks=0.
proc name: Move (/mob/Move)
usr: Zombie (/mob/enemy/zombie4)
src: Zombie (/mob/enemy/zombie4)
call stack:
Zombie (/mob/enemy/zombie4): Move(the g2 (15,46,1) (/turf/nat/ngrass/g2), 9)
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
...
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()
Zombie (/mob/enemy/zombie4): wander()

And so on and so on.

What's wrong? : /
shouldnt it be M.wander() because its a mob/proc.
~Grand~
In response to KillerGrand
Please learn DM before trying to help. That has absolutely nothing to do with the problem in question, and is, indeed, counterproductive - wander() is short for src.wander(), and src is correct in this case.
You're doing things a little weirdly there.

The problem is because you're causing the stack to overflow by constantly calling wander() again. You can patch it up by simply replacing any instances of 'wander()' with 'spawn() wander()', but it would be better to remove the recursiveness altogether:

mob/proc/wander()
while(src)
sleep(20)
if(!src) return //Just in case
step_rand(src)
for(var/mob/m in oview(src,3)) //src to avoid hidden usr abuse, oview because it removes the looker.
if(!istype(m,/mob/enemy/zombie)) //Don't want to attack other zombies.
zattack(m)
break //Only attack one person per 'wander' cycle. Not sure if that's what you want - if it is, just remove the 'break'
In response to Jp
Well, that works great now! Thanks!

BUT!

mob/proc/wander()       
while(src)
sleep(20)
if(!src) return //Just in case
step_rand(src)
for(var/mob/M in oview(src,3)) //src to avoid hidden usr abuse, oview because it removes the looker.
if(!istype(M,/mob/enemy/zombie)) //Don't want to attack other zombies.
zattack(M)
break //Only attack one person per 'wander' cycle. Not sure if that's what you want - if it is, just remove the 'break'
mob
proc
zattack(var/mob/target)
var/connect = src.attackrating - target.dodgelvl - target.cfin
target << "BEEP"
if(connect >= 1)
target << "BEEP2"
src.AllowMove = 0
target.AllowMove = 0
target << "A zombie grabs hold of you!"
if(target.rdefitems >= 1)
target << "Lightning fast, you bury a defense item into the zombie's brain!"
src.hp = 0
src.death()
else
target << "The zombie rips flesh from you!"
target.infection += rand(1,3)
target.hp -= rand(10,25)
target.death()
else
target << "A zombie lunges for you, but misses!"


My attack code is screwwy : /

It calls the attack on other zombies, and when the zombies are killed, I am still taking damage/dying.
In response to Pakbaum
mob/proc/wander()       
while(src)
sleep(20)
if(!src) return //Just in case


If the source of the proc is deleted, all active procedures belonging to that mob terminate. You don't need the while(src) and if(!src) stuff.

There is also a much better way to do a "wander" thing. Your way loops indefinitely, even if no one is online or near them. (Wasting CPU!)
Search the developer forums. It's around here somewhere.

As for continually being attacked, perhaps you did something wrong in death()? Perhaps it's other zombies nearby (Your code doesn't require they be next to you)? We need to see your death() proc to have a more full understanding.

Suggestion: Try putting just 1 zombie there and go kill it.

-Jack
In response to Pakbaum
mob/var/target
mob/var/alignment
mob/var/attacked

mob/proc/hunt()
if(src.target==null||src.target:hp<=0||src.target:alignment=="Evil")//if src targe is not in game or hp is beloew 0 or is on the bad side
spawn() src.wander()//star the wander again
else
for(var/mob/M in oview(src,6))//we put this here juss in case a new player thats closer to the zombie the zombie will go after that one instead
if(get_dist(M,src)<get_dist(src.target,src))
if(M.alignment=="Good")
src.target=M
if(src.target in oview(src,1))//if src target in in view 1
src.zattack()//attack it
else// if not
step_towards(src,src.target)// step towards it
spawn(src.speed) src.hunt()//start loop again

mob/proc/wander()
if(src.target==null||src.target:hp<=0||src.target:alignment=="Evil")//if has no target
step_rand(src)//make it wonder
for(var/mob/player/M in oview(src,6))//if there is a person in view 6
if(M.alignment=="Good")//and its on the good side
src.target=M//make that person the zombies target
spawn(rand(10,50)) src.wander()//and start the loop again
else//If it has a target
spawn() src.hunt()//start the hunt proc

mob/proc
zattack()
if(src.target:attacked=null)//if its not beeing attacked
var/connect = src.attackrating - src.target:dodgelvl - src.target:cfin
src.target<< "BEEP"
if(connect >= 1)
src.target<< "BEEP2"
src.target:attacked=1
src.AllowMove=0
src.target:AllowMove=0
src.target<< "A zombie grabs hold of you!"
if(src.target:rdefitems >= 1)
src.target<< "Lightning fast, you bury a defense item into the zombie's brain!"
src.hp = 0
spawn(20)src.target:attacked=null//Give you a 2 sec chance to run before getting attacked again
src.death()
else
src.target<< "The zombie rips flesh from you!"
src.target:infection += rand(1,3)
src.target:hp -= rand(10,25)
src.target:death()
spawn(30)src.target:attacked=null//Give you a 3 sec chance to run before getting attacked again
else
src.target<< "A zombie lunges for you, but misses!"
else
return


Ok havnt tested it but if you know your coding than you should have no prob making it work :/.

- Dark Emrald
Ok ok, so I got all that working. But now:

        for(var/mob/M in oview(src,8))
if(M.living)
step_towards(src,M)
else
break
for(var/mob/M in oview(src,1)) //src to avoid hidden usr abuse, oview because it removes the looker.
if(!istype(M,/mob/enemy/zombie)) //Don't want to attack other zombies.
zattack(M)
break


What can I do to the code above to make it check first if there's anything that's var/living in oview(8), if there is, step towards it. BUT! If there's something living that's within 1, stay there and attack it.
In response to Dark Emrald
You shouldn't use the ':' operator if there is a better way to do it. What you're doing is not defining the "target" variable properly, which is somewhat forcing you to use the ':' operator. A simple fix of this would be type casting:

mob/var/mob/target


In doing this, you can now replace your ':' operators with '.'! =)

Edit: Also, in the first if() statement of your zattack() proc, you need to use '==' instead of '='. Either ways though, I'd rather check if it's nothing:

if(!target.attacked)


Edit 2: It'd also be better if you had a zombie sub type, that way, you wouldn't need that useless alignment variable:

mob/Zombie
var
Attacked=0
Speed=5
mob/Player/Target
Bump(atom/movable/A)
if(istype(A,/mob/Player)) ZAttack(A)
return ..()
New()
Search()
Wander()
..()
proc
Wander()
if(Target) return
while(!Target)
sleep(Speed)
step_rand(src)
Search()
set background=1
sleep(Speed)
if(!Target||!(Target in view(src,10)))
Target=null
for(var/mob/Player/M in view(src,10))
if(M.Health<=0) continue
Target=M
if(!Target) {spawn(1) {Search()};Wander();return}
step(src,get_dir(src,Target))
spawn(1) Search()
ZAttack(mob/Player/M)
if(dir!=get_dir(src,M)) return //It doesn't make sense to attack when you're not facing the victim! :)
M<<"Urngh! Braaaaaaiiiins!"
M.Health-=10
M.Death(src)