ID:147526
 
I've got a simple little bomb in my game that can be fired from one of a few specified aircraft. I'm using Spuzzum's s_missile library(I'd be crazy not to), and I designed the bomb itself as follows:
ATGmissile
icon = 'tiles.dmi'
icon_state = "ata"
Del()
for(var/obj/O in view(4,src))
if(O.dontdeleteme) continue
del O
..()
<dm>
But every time I use it, Dream Seeker bellyaches about reaching the maximum recursion level.

runtime error: Maximum recursion level reached (perhaps there is an infinite loop)
To avoid this safety check, set world.loop_checks=0.
proc name: Del (/obj/Missile/ATGmissile/Del)
usr: Mobius Evalon (/mob/characters/mobius)
src: ATGmissile (/obj/Missile/ATGmissile)
call stack:
(Insert spam here)

I really don't want to disable loop_checks(I'm more than confident I'll need it in the future); is there some feature in s_missile I'm overlooking?

[Edit: Heheh, scratch setting loop_checks to zero, it instantly crashes the world and closes Dream Seeker.]
Enigmaster2002 wrote:
> ATGmissile
> icon = 'tiles.dmi'
> icon_state = "ata"
> Del()
> for(var/obj/O in view(4,src))
> if(O.dontdeleteme) continue
> del O
> ..()
>


The problem here is that it is bad coding, because when this 'missile' trys to delete itself, it is going to call that delete loop, which then in turn gets to the missile, and calls the del proc, which calls the loop, which calls the missiles del proc, etc etc, in a never ending cycle.
In response to Lazyboy
What should I do to make it perform what I want then? Something similar works peachy for air-to-air missiles that shoot down other planes...
ATAmissile
icon = 'tiles.dmi'
icon_state = "ata"
Del()
var/mob/M
for(M in oview(0,src))
if(M.client || istype(M,/mob/FGE)) continue
del M
..()
In response to Enigmaster2002
Spot the difference, people: =)

view()
oview()

You're looping through view(), which includes the Center object. So you're deleting the missile, which then tries to delete itself, which makes it try to delete itself AGAIN, and again and again and again and again... ad nauseum. (Or should that be "ad crasheum"? Har har, bad joke. Anyway...)

The fix? A single character. Just add an "o" on the beginning of "view", and it should work...

...EXCEPT...

What happens if a missile is deleted while there's another missile of that type in oview()? One tries to delete the other, which tries to delete the first one, which tries to delete the second one, which tries to delete the first one... hmm, this looks familiar. You need to include a check that stops it doing that; easiest way would be to not let missiles delete other missiles by including an istype(). A slightly better way would be to set a flag on missiles just before they run their for() loop that causes other missiles to not delete them. I see you've already got a "dontdeleteme" flag, so you're half done already!

Rule of thumb: If you're ever calling del within Del(), be very. Very. Careful.

Oh, and world.loop_checks=0 is pure evil and serves no purpose whatsoever. That message really needs to be removed; it gives the false impression that surpressing the error message will fix the problem. It won't, and the game will either crash (as in your case) or lag to high heaven.
In response to Crispy
Oh, and world.loop_checks=0 is pure evil and serves no purpose whatsoever. That message really needs to be removed; it gives the false impression that surpressing the error message will fix the problem. It won't, and the game will either crash (as in your case) or lag to high heaven.

During stuff like random map generation you occasionally need to loop a lot or recurse very deep in which case this falsely triggers the loop check.
In response to Theodis
I still think that message is much more harmful than helpful. There are other ways of getting around it too.