Help on MOB count/array

Need some help with that macro you're working on or aren't quite sure how to get your macro to do something? Ask here!

Moderator: MacroQuest Developers

bonehand
a lesser mummy
a lesser mummy
Posts: 48
Joined: Tue Feb 17, 2004 5:16 pm

Help on MOB count/array

Post by bonehand » Fri Mar 19, 2004 9:07 am

I'm looking to find a method to get a count on the number of MOBs in a circular or spherical area.

Using $spawnsearch, I can get the ID of a single mob in the search radius at a x,y location and know if there are no spawns in the search area, but if another is only a single increment further from the center then it remains unknown.

Eg.

Code: Select all

  /echo $searchspawn(npc,loc:100:400,radius:200)
(BTW: loc:x:y option is undocumented as far as I can tell)

I can get a tally by running a routine that makes a number of smaller circles and entering the data into an array, but it was so CPU intensive that it literally bogged EQ down.

I can see this being very useful in AE groups, pulling, and a number of other uses, but I've come to a standstill in how to do this code using the MQ2 script language. The closest I have seen is no-ks code but that deals with only a single PC trigger the event, and pulling routines haven't evolved to the level I am looking for.

If someone could come up with something I would very greatful, but I'm thinking the best option would be to add an option to $spawn, $searchspawn, and /target that targets the next furthest mob from an x,y location or spawn ID...much like the [next|prev] do with the MOB's ID.

mcswanbeck
a lesser mummy
a lesser mummy
Posts: 70
Joined: Fri Jan 16, 2004 5:16 am

Re: Help on MOB count/array

Post by mcswanbeck » Fri Mar 19, 2004 9:12 am

bonehand wrote:I'm looking to find a method to get a count on the number of MOBs in a circular or spherical area.
I've thought about this myself in order to quickly be able to tell the puller how many mobs there is in camp, however I never got to look into it.

Anyways, I'm sure you can extract what you need from ml2517's autodebuff macro which handles what you seek, as far as I can tell.
/mcswanbeck

Gumby
a ghoul
a ghoul
Posts: 99
Joined: Sat Jan 24, 2004 5:27 pm

Post by Gumby » Fri Mar 19, 2004 10:47 am

Off the cuff code:

Code: Select all

:CheckMore
/varset CountID $searchspawn(npc,loc:100:400,radius:200,noalert:1)>0
/if n @CountID>0 {
   /varadd Count 1
   /alert add 1 id @CountID
   /goto :CheckMore
}
/echo @Count mobs in camp
G

bonehand
a lesser mummy
a lesser mummy
Posts: 48
Joined: Tue Feb 17, 2004 5:16 pm

Post by bonehand » Fri Mar 19, 2004 11:13 am

Gumby:
Looks like a promising start, I will try that out when I get home and see how well it does.

Maybe with Gumby's code I will be happy, but he made his post while I was typing this reply. As it was a decent amount of typing and has what I consider great ideas to expand MQ2 it's getting posted anyway =)

MCS:
Yes, that is a beautifully written script. I tried it out with my enchanter and it does it's job well.

The problem is that is does everything like I want, but it can only do it around the character. It does not allow you to set an x,y location, use a MOB ID's x,y to spit out MOB ID's or how many mobs are in the area by going through the code.

The people who make these scripts are great, and I'm sure if what I wanted to do was possible, someone would have done it by now. It must be a limitation in MQ2 and short of having a custom command for doing what I'm looking for built in, it's probably not possible.

If I had a magic coder ring(as opposed to the magic decoder ring I do have) I guess I would want $searchspawn to either return a count based on radius or place every mob in the search area into and array. I could see how implimenting this could expand /who, $spawn, $target and possibley other commands into automatic array builders, Boolean output searches and any number of other uses, as their code seems fairly well intertwined.

/Who from a characters perspective has the funtionality in some ways when you use radius, but there is no way to define the axis or from my current ability, move a /who's results into a script. Possibley a $who command tied to the current coding of $searchspawn and /who. If created it could work out well but I'm not up to the level of the developers here in coding C++. Soon maybe, but definately not right now.

Another concept I was playing with was notnearalert and nearalert functions. If nearalert or notnearalert search an array and send out flags, would it be improbable to impliment "general" statements like npc, pc or whatever other arrays that might exist behind the scenes. I assume that superwho's access the "array" in EQ's memory, but have to bring the data out of EQ's memory to perform the fuctionality it has.

Something like:

Code: Select all

/echo $searchspawn(npc,loc:100:400,radius:200,nearalert:pc)
The huge anti-ks routines would be so simplified that it may take away some coders job, but it does sound relatively feasible if I understand what's going on properly =)

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Fri Mar 19, 2004 6:23 pm

Actually at one point Raebis and I were screwing around with the exact question you have. I have some code somewhere, I'll take a look and post it if I can find it.

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Fri Mar 19, 2004 6:35 pm

I believe this was the ghetto style one I was playing with before switching to another method. Not able to get in game at the moment and test it but give it a try. I'll look for the other one.

Currently this simply finds the mob closest to the location you specify.

Code: Select all

|
|  Usage: /macro testsearch.mac [y] [x]
|
|  If you do not provide the location to search from it uses the location of where your character was standing
|  when the macro was launched.
|

#turbo 50
Sub Main
/declare StartLocY global
/declare StartLocX global
/if $defined(Param0)==TRUE /if $defined(Param1)==TRUE {
    /varset StartLocY @Param0
    /varset StartLocX @Param1
} else {
    /varset StartLocY $char(y)
    /varset StartLocX $char(x)
}
/call IterateNPC
/return

Sub IterateNPC 
/declare npcid local 
/declare firstnpcid local 
/declare lastnpcid local 
/declare lastmob local
/declare lastmobdist local
/declare NpcCount local
/varset npcid 0 
/varset firstnpcid 0 
/varset lastnpcid 0 
/varset NpcCount 0
/varset npcid $searchspawn(npc) 
/varset lastmob @npcid
/varset lastmobdist $distance(@StartLocY,@StartLocX:$spawn(@npcid,y),$spawn(@npcid,x))
/varadd NpcCount 1
:Loop 
/if n @npcid==@firstnpcid { 
       /echo Closest Mob is: $spawn(@lastmob,name) -- It is @lastmobdist locs from the anchor point.
       /target id @lastmob
       /delay 10s
   /return 
} else { 
   /if n @NpcCount==0 /varset firstnpcid @npcid 
   /varset lastnpcid @npcid 
   /varset npcid $searchspawn(npc,id:@lastnpcid,next) 
    /if n @npcid!=@firstnpcid { 
        /varadd NpcCount 1
        /if n $distance(@StartLocY,@StartLocX:$spawn(@npcid,y),$spawn(@npcid,x))<@lastmobdist {
            /varset lastmob @npcid
            /varset lastmobdist $distance(@StartLocY,@StartLocX:$spawn(@npcid,y),$spawn(@npcid,x))
        }
    }
} 
/goto :Loop 
/return 

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Fri Mar 19, 2004 7:00 pm

Ok I dug through some more old scripts and I think this should be an example of how you can call the sub to get a mob close to the loc you specify (I think this is the method that Raebis thought of. Its fairly efficient.) I modified this a bit to get rid of some of the things it was doing:

You should just be able to call the sub like (Just a note, if you are looking at the /loc output from EQ it is: y,x,z. So pass this sub the first two.):

/call GetTarget 133.01 -123.11

And it should start searching in rings extending from that location for mobs. You then retrieve the $returned Mob ID like this:

Code: Select all

/call GetTarget 133.01 -123.11

/if n $return>0 {
    /varset TargetMob $return
    /target id @TargetMob
} else {
    /echo No Targets Found
}
Anyways you get the idea.

Code: Select all

Sub GetTarget(YLoc,XLoc)
   /declare LastMobID local 
   /declare FirstMobID local 
   /declare MobID local 
   /declare SRadius local 
   /varset MobID 0 
   /varset FirstMobID 0 
   /varset LastMobID 0 
   /for SRadius 0 to 10000 step 100 
      /delay 0
      /if n @MobID==0 { 
          /varset MobID $searchspawn(npc,loc:@XLoc:@YLoc,radius:@SRadius) 
          /varset FirstMobID @MobID 
      } else { 
          /varset LastMobID @MobID 
          /varset MobID $searchspawn(npc,id:@LastMobID,loc:@XLoc:@YLoc,radius:@SRadius,next) 
          /if n @FirstMobID==@MobID { 
              /next SRadius 
          } 
      } 
      /if n @MobID!=0 { 
          /goto :Done 
      } 
   /next SRadius 
   /return 0
:Done 
   /echo Target: $spawn(@MobID,name,clean) - Distance: $spawn(@MobID,distance) 
/return @MobID

bonehand
a lesser mummy
a lesser mummy
Posts: 48
Joined: Tue Feb 17, 2004 5:16 pm

Post by bonehand » Fri Mar 19, 2004 7:26 pm

Thanks for the code ml but I'm afraid you missed my point =)

Actually, doing a simple $searchspawn(npc,loc:x:y,radius:radius1:radius2) does return the closest mob to the x,y set in it in the circle for radius:x or the area beyween radis1 and radius2. I was looking to get the ID of all of them into an array or a number for how many mobs were in that radius.

Try eg.,

/echo $searchspawn(npc,loc:0:0,radius:2000)

It will give the closest MOB ID to that location, no matter where the x,y location is set.

So, I have been working on the idea G posted above, which is to try to do a repetitious $searchspawn that would put MOB ID's into an /alert array, but it's not going so well...

I will post what I have if I can ever figure out how the hell I have an infinite loop in some fairly straight forward code...

As I'll admit all the time...I'm a tard.

Gumby
a ghoul
a ghoul
Posts: 99
Joined: Sat Jan 24, 2004 5:27 pm

Post by Gumby » Fri Mar 19, 2004 8:40 pm

Ah, didn't know what ya wanted specifically. I use code I posted earlier for a MobCount around my toons location, and simply modded the $searchspawn to meet the example you posted. To be honest I haven't played with the loc paramester in $ss but I've seen it discussed here earlier. I only use the alert list to keep Count from getting repeated mobs; unfortunately, there's no way through the default source to dump the alert list or mod it on the fly. A more full example I think of what you're looking for would be something along the lines of (not tested):

Code: Select all

Sub Main

/declare MobID array
/declare CountID global
/declare Count global
/declare i global

/varset Count 0
/alert 1 clear
/alert 1 id -1

:CheckMore 
/varset CountID $searchspawn(npc,loc:100:400,radius:200,noalert:1)>0 
/if n @CountID>0 {
   /varset MobID(@Count) @CountID 
   /varadd Count 1 
   /alert add 1 id @CountID 
   /goto :CheckMore 
}
| dostuff with array / count here a la
/echo @Count number of mobs total
| or
/for i 0 to $calc(@Count-1)
   /echo Mob number @i has ID @MobID(@i)
/next
/return
Would wind up with Count as a number of mobs, and MobID as an array from 0 to Count-1 elements for the ID's found by $searchspawn. After that can do whatever to it since you can list / change elements in the array.

G

bonehand
a lesser mummy
a lesser mummy
Posts: 48
Joined: Tue Feb 17, 2004 5:16 pm

Post by bonehand » Fri Mar 19, 2004 10:17 pm

I cleaned it up and removed that -1 you used as a primer. It could easily be removed at the end, but by using $ss without the noalert in one pass it will start the array and begin looping through the area adding MOB ID's.

It's truely inspiring =) This will fit perfectly in so many scripts that it is shameful that nobody did it before.

Code: Select all

| Area51.mac
| Logic by Gumby - Refined by bonehand
|
| Special thanks to Gumby who came up with the basic idea!!
|
| Tested and working 100% as is.
| This is base code. You would need to impliment your own code to this 
| so that you could change the loc based on user input or a target.
| This is absolutely groundbreaking, in my humble opinion, for single pull
| logic. Currently is set up to tell you how many MOBs are within 200 feet
| of Orc_1 in East Commonlands. Test it out!
|
| If you find something great to do with this code, please post it!
| 

Sub Main 

/declare MobID array 
/declare CountID global 
/declare Count global 
/declare ForInc global 

/varset Count 0 

/alert clear 1 

| Prime the Alert with a known target location or use $target(x) 
| and $target(y) to get them from your current target.
| I used static numbers in this example to just simplify for now.
/varset CountID $searchspawn(npc,loc:2650:1020,radius:200)
/if n @CountID>0 { 
   /varset MobID(@Count) @CountID 
   /varadd Count 1 
   /alert add 1 id @CountID 
} 

| Fucking brilliant code here thanks to Gumby
:CheckMore 
/varset CountID $searchspawn(npc,loc:2650:1020,radius:200,noalert:1) 
/if n @CountID>0 { 
   /varset MobID(@Count) @CountID 
   /varadd Count 1 
   /alert add 1 id @CountID 
   /goto :CheckMore 
} 

| Stuff you can do:
| If the array count comes back 1 then it is single pull!
| If the array has a number of MOB IDs, pull the one you want, 
| search for a specific spawn or select the monster that is 
| closest to all other monsters for AE grouping...and what else?
/echo @Count number of mobs total 

| Spit out all entries in array, again, do as you wish with them
/for ForInc 0 to $calc(@Count-1) 
   /echo Mob number @ForInc has ID @MobID(@ForInc) 
/next ForInc
/alert clear 1
/return 
I'm starting a thread in snippets on this code.

bone

ml2517
a grimling bloodguard
a grimling bloodguard
Posts: 1216
Joined: Wed Nov 12, 2003 1:12 am

Post by ml2517 » Fri Mar 19, 2004 10:30 pm

Ah ok.. I guess I should have read it a bit closer. Looks good.