ID:166367
 
I'm just making random programs to see if I know what I'm doing, and I'm having a problem with one. I have it set up so there's one group of Archers at the top of the screen, and a bunch of blobs at the bottom. The Archers stay still, but the blobs move around randomly. I have it so that every time the blobs move, each archer's checkenemy() is called, which basically sees if any blob is within 3 squares. If one is, then an arrow is created on the archer, and the arrow's Shoot() is called. Shoot() is passed the mob as an argument, and then while the arrow exists, it steps towards locate(blob). When the arrow Bump()s the blob, it deleted both. The problem I'm having is apparently an infinite loop. I'm new to programming, so I can't figure it out. If you need to see my code, just ask.
here is the default shoot verb i use, it's all in one.

    verb//or proc, for NPCs
Shoot()
var/obj/H = new/obj/arrow//makes an arrow nowhere
if(usr.attacking == 0)
usr.attacking = 1
spawn(7)
usr.attacking = 0
H.dir = usr.dir//arrow faces you
H.loc = src.loc//arrow goes to you
spawn(30) del(H)//makes the arrow fall after 3 seconds
while(H)//a loop to keep the arrow going and to check for enemies
step(H,H.dir)//make it move
if(src.health<=0)
var/turf/T = H.loc
if(T.density == 1)//if it hits a wall...
del(H)//kill the arrow
break//and break the loop
for(var/mob/M as mob in T)
if(M == src)//if the mob is the one who shot the arrow...
continue//the arrow will keep going! win!
else
view() << "[src] shoots [M]!"//this lets you know they got busted
M.loc=null //this plunges the enemy into nowhere
spawn(35) del(M) //this kills it after 3 and a half seconds, so they don't leave
////dead arrows behind, assuming an archer shoots another archer
del(H)//gets rid of arrow after enemy is shot.
sleep(5)//how fast arrow goes

This is the basic outline I made using bits and pieces of shoot and attack codes. It can be modified to your needs, but it should work for your needs. You may need to mod your existing code to make this work with what you have, but i garuntee it will work.
Ok, now I want it so arrows don't collide with eachother. Also, when too many enemies are within range, they just stop moving, until they are all killed. How would I fix this?
In response to Seraphrevan
The code could potentially cause problems in ways I am not up to explaining at the moment and is just plain horrible.

mob
proc
Shoot(mob/target)
if(!target||!get_dist(src,target)<=3){return}
missile('arrow.dmi',src.loc,ltarget.oc)
target.HP-=10
if(target.HP<=0&&!target.client){del(target)}
else {world<<"[target] died!";target.RemoveFromGame()}


You could use that, but it won't give you the full effect you want. I used missile() because if you used step_towards(), that could look pretty funky since it'll look how most mobs do when they walk to you in games. Well I made up a few procs in there like RemoveFromGame(), and that was just to fill in some crap, but if you want GOOD arrow movement that only takes away damage when it actually hits a target, then you should probably try pixel movement for arrows.
In response to Exophus
How do I do pixel movement?
In response to Seraphrevan
It involves the use of sin() and cos(), but I don't feel like getting into it. You'll also probably need to have a custom get_dir() for pixel movement to tell you which way the arrows should go in degrees. You can look at a demo by Theodis that shows alternate movement using pixel movement, and it's in the demos section so you could either go there or do a search on it. You will also want pixel detection, which is a whole other story. :P

-Exophus