ID:139499
 
Code:
mob
proc
AI()
if(src.NPC == 1)
return
if(src.NPC == 3)
return
if(src.NPC == 2)//If it's a NPC that is supposed to use this AI
while(src)
for(var/mob/M in oview(6))
if(M in oview(6))
if(M.NPC == 0)//If it's a player
walk_to(src,M,1,5)
if(M in oview(1))
var/Damage = (60+src.str-M.def)
view() << "[src.name] attacks [M.name] for [Damage]"
M.hp -= Damage
if(M.hp <= 0)
M.Death(src)
else
walk_rand(src,10)
break
else
walk_rand(src,10)
break
walk_rand(src,10)
break
spawn(1)
AI()


Problem description: The problem is that the AI acts really random, sometimes it will follow me as it's supposed to but in most cases it will walk randomly and then just suddently stop walking and when I get in range 1 of it it will attack me, but it's supposed to follow me every time and not stop when I get in range 6

Well, there are a few little things that you could do to save memory. What I found solved your little problem for me in my testing was adding a variable, "tar", which would track if the NPC had a target or not. A few other things you could remove to save memory are present, but are unnecessary. Here's what I came up with if you want to use it. I stayed as close to your original programming as I could to solve the problem and save memory. Just add the "tar" var to the mob and this should work like a charm. It may not be needed, but you can initialize it at 0 when you declare it.

mob
proc
AI()
if(src.NPC != 2)
..()
else
while(src)
for(var/mob/M in oview(6))
if(M in oview(6))
if(M.client)//If it's a player
tar = 1
walk_to(src,M,1,5)
if(M in range(1))
var/Damage = (60+src.str-M.def)
view() << "[src.name] attacks [M.name] for [Damage]"
M.hp -= Damage
if(M.hp <= 0)
M.Death(src)
tar = 0
break
spawn(2)
if(tar==0)
walk_rand(src,20)
else
..()
AI()


/Regards

Valyrin
In response to Valyrin
Thanks for the help, there was one problem in it and that was once you get out of range of 6 they still chase but I managed to fix that, thanks once again~ ^^
In response to Valyrin
That will ultimately lock up the game once that proc has been executed...
In response to Spunky_Girl
I've tested this myself, and it works without locking up the game. The "break" is there to ensure that it won't.
In response to Valyrin
Oh, sorry. I thought it was indented under the for() loop.

You also should not be calling the proc recursively.
In response to Spunky_Girl
Yeah, you've got a point there. This is more what it should be.

mob
proc
AI()
if(src.NPC != 2)
..()
else
while(src)
for(var/mob/M in oview(6))
if(M in oview(6))
if(M.client)//If it's a player
tar = 1
walk_to(src,M,1,5)
if(M in range(1))
var/Damage = (60+src.str-M.def)
view() << "[src.name] attacks [M.name] for [Damage]"
M.hp -= Damage
if(M.hp <= 0)
M.Death(src)
tar = 0
break
spawn(2)
if(tar==0)
walk_rand(src,20)
else
..()
spawn(2)
AI()


Stress-tested this with 9600 AI vs. the original and this one runs better.
In response to Valyrin
You're still calling it recursively... Bad...

The whole point of this proc is to wander aimlessly until a target is found, and once one is found, chase it and attack it, right?

mob
var/tmp/mob/target
npc
proc/ai()
while(src)
if(!src.target) //if no target
for(var/mob/m in oview(6,src)) //search for a target
if(m.client) //if a player
src.target = m //player becomes target
break //break the for() loop once a target has been established
sleep(5)
else
if(src.target in oview(6,src)) //if the target is within range
step_to(src,src.target,1) //take a step towards the target
if(src.target in get_step(src,src.dir)) //if the target is in front of src
//attack it
sleep(/*however long between attacks*/) //then pause for an "attack delay", must be at least 1 tick
else //if not in front of src
sleep(/*however long between movements*/) //pause for a "move delay", must be at least 1 tick
else src.target = null //set src's target to null to establish a new target while wandering aimlessly

Among calling the proc recursively, you did a couple other things bad as well.

1) You did an extra check to see if the mob being considered to be the next target, was in range, when the for() loop already does that. The "if(m in oview(6))" line was pointless.

2) Your for() loop will make the mob attack everything around it, which could be intentional, but I'm going to assume it isn't. If your intention was for the mob to attack only its target, then you should use get_step() instead of range().

3) Another thing which I doubt you foresaw, was that if 2 players stood in a flanking position on either side of the mob, then the mob will end up pickling itself, meaning it will take a step towards one, then step back towards the other, then step towards the former, and then the latter, and it will do this infinitely.
In response to Spunky_Girl
I know that there needs to be a mob/target var. All I did was modify the given code and, since I cannot guess the person's intentions, all I can do is offer a generalized modification to fit what they provided. Yes, I did the recursively incorrectly, which I now realize and won't forget, and thank you for that. However, you shouldn't question my intentions but the intentions of the person who requested the code.
In response to Valyrin
A very bad one at that... Using an infinite loop like this is generally frowned upon anyways.