ID:158130
 
ok i have no idea how to get 2 NPC's to attack each other.

1 NPC (good guys)
stand there and melee,range,and mage

1 NPC (bad guys)
spawn from the void and move and attack with melee range and mage.

so far hes what i could do
mob
Good
Green_Unit
icon = 'mob.dmi'
icon_state = "1"
var/A = /mob/Bad/Black_Unit
New()
start
if(A in oview(10))
step_towards(A,src)
sleep(10)
goto start
else
step_rand(src)
sleep(10)
goto start



mob
Bad
Black_Unit
icon = 'mob.dmi'
icon_state = "6"



*note this is my first defence style try*
It will be the same as the AI proc you'd find in a tutorial. See: http://www.byond.com/developer/articles/start
mob
NPC
icon = 'mob.dmi'
var/types_of_guys_i_hate = "I love everyone" //default guys the npc hates is nobody <3
var/mob/target //the target, once it is found
New()
..()
spawn find_enemy() //when the NPC is created, it will start searching for an enemy
proc
find_enemy()
for() //as long as the NPC exists, everything below will loop
sleep(10) //1 second pause between loop
for(var/mob/NPC/m in oview(7)) //for npc's in view
if(m.type == types_of_guys_i_hate) //if the NPC is the same type as the NPC hates
target = m //the NPC's target is now m!
break
if(target) //if a target was found
hunting_time() //time to kill m
break //we've found a target, so no need to keep looping...
hunting_time()
while(target) //while the target exists
sleep(10) //wait 10 seconds between steps
step_towards(src,target) //walk towards the enemy
find_enemy() //once the target ceases to exist, the code continues and we start searching\
for a new enemy again...





Good_Guy //the good guys!
types_of_guys_i_hate = /mob/NPC/Bad_Guy //they all hate bad guys :o
Donkey
Chicken

Bad_Guy
types_of_guys_i_hate = /mob/NPC/Good_Guy
Turtle
Rabbit

verb
createnpcgood()
new/mob/NPC/Good_Guy(loc)
createbad()
new/mob/NPC/Bad_Guy(loc)


Of course there's so many different ways to perform this... Almost everything here could be done in multiple ways, and I can't garantee you this would even be the best method (most likely not), but hopefully it will shed some light on the very basics. Basically just search for the paticular mob you want to kill, instead of everything.
In response to Speedro
That results in infinite recursion and it abuses usr. It also causes creating the object to block forever, meaning you have to jump through hoops to actually create those NPCs.
In response to Garthor
Er, were you responding to me?

I just tested my code; it works exactly as intended :s

However I did miss one thing which I've now edited- using spawn before the loop to allow for further procedures to occur.
In response to Speedro
Yes, I was responding to you, and your edit fixed one error (new() blocking) but did not fix the other errors I've described. Just because it works in your limited test case does not mean the code is good.
In response to Garthor
Can you elaborate upon my usr abuse and infinite recursion?
In response to Speedro
The default center for oview() is usr.

Having proc X call proc Y which calls proc X, with no exit condition, results in infinite recursion.
In response to Garthor
I thought an empty "for" loop would function the same as "while(src)" in this situation. I've been told before that the for loop will cease just as the while(src) would, if src was deleted.

Either than that, (if what I thought was correct) than it's doing exactly what I wanted to show- an NPC that would continuously look for targets until it is deleted. In which case it wouldn't be infinite, and there would be a way to get out of the loop: delete the src. Of course it would be so simple to change it so that you could choose when it decided to look for targets.

As for the oview(), woops.

So if for does do what I thought, than everything works as it should and there is no infinite recursion in the way this example is meant to be played; NPC's being deleted. If they weren't it would be so easy to change, so it's just an example since no way was specified. No?
In response to Speedro
Alright, I figured it out. Instead of usr.group I used usr.icon and it responded.
Thanks for all your help.
In response to Speedro
Just because the poor design is practically a non-issue doesn't mean it isn't poor design. If you wanted to farm off subroutines to alternate procs, you would have those alternate procs simply return, instead of calling the main proc again. IE:

mob
var/targettype = /mob/enemy
var/atom/movable/target
proc
AI()
while(src)
target = locate(targettype) in oview(src)
if(target)
attack()
else
wander()
sleep(10)
attack()
while(target in oview(src))
if(get_dist(src,target) > 1)
step_to(src,target)
else
damage(target)
sleep(10)
target = null
return
wander()
step_rand(src)
return
In response to Garthor
That's actually what I originally considered doing, but decided against it because I didn't see it as any different. That locate thing seems relatively useful and would save me some time writing for loops only to find one paticular thing in a list.

As for the 'return' at the end of your other procs, is it actually necassary? I wouldn't think it would be, considering the procedure is ending anyways, and it returns null as default anyways.
In response to Speedro
Speedro wrote:
That's actually what I originally considered doing, but decided against it because I didn't see it as any different.

The difference is that doing it your way causes infinite recursion.

As for the 'return' at the end of your other procs, is it actually necassary?

No, I'm using it to illustrate to you that the proc simply ends and that calling the original proc again would cause infinite recursion.
In response to Garthor
Garthor wrote:
Speedro wrote:
That's actually what I originally considered doing, but decided against it because I didn't see it as any different.

The difference is that doing it your way causes infinite recursion.

I don't see how it's infinite, it stops in the same way as the regular loop does- when src ceases to exist. Either than that, they're both infinite.
In response to Speedro
Speedro wrote:
Garthor wrote:
Speedro wrote:
That's actually what I originally considered doing, but decided against it because I didn't see it as any different.

The difference is that doing it your way causes infinite recursion.

I don't see how it's infinite, it stops in the same way as the regular loop does- when src ceases to exist. Either than that, they're both infinite.

The key word here is recursion. When you call a new proc, the previous proc still needs to keep any variables in memory. If a proc calls itself, it's called recursion, and if you don't have a DEFINITE exit condition (relying on another proc somewhere else maybe to possibly delete the mob is not definite) then you just end up taking up more and more memory on the stack. In this case, it doesn't recurse fast enough to cause a crash, but it DOES still take up MANY times more memory than it needs to. It might be absolutely small, but with a large number of mobs it DOES add up.
In response to Garthor
I don't think I completely follow...

There's no definite exit condition for the version you provided either, since (as I've been told) for() will behave the same as while(src), and they both rely on a procedure to delete the mob.

As for memory exactly how does the version I provided slow it down significantly further? Both will eventually have to find new variables anyways for a target, both loop, it's just mine ends the current procedure and moves on to another for when a target is found, which when the target is lost, it will just begin the searching loop again.

In the same sense the version you provided finds a target, then runs a loop for as long as the target exists will perform a specific action, and once the target no longer exists the original procedure will continue on it's way.

How do these differentiate in memory stack? Can you elaborate further? (I hope you know I'm not trying to defend myself blindly, I just really do want to know the why's and how they're different.)
In response to Speedro
Last attempt. This time, a practical example.

world/loop_checks = 0

proc/recurse(var/N)
if(N <= 0)
return
recurse(N-1)

mob/verb
recursion()
recurse(1000000)
world << "DONE"
iteration()
for(var/N = 1000000, N > 0, N--)
;
world << "DONE"


recursion() will crash Dream Seeker. iteration() will not. This is because recursion() takes up massive amounts of memory as each call to recurse() is taking up a bit more memory storing data while it waits for the next iteration of recurse() to finish.

Look, if you actually want to know how this works, read up on what the "call stack" is. It's a generic computer programming term.