AcquireTarget - Makes Pulling Macros Possible

A forum for macro code snippets to be used in writing other macros. Post routines or .inc files here only, completed macros go to the Macro Depot. MQ2Data format only!

Moderator: MacroQuest Developers

SlimFastForYou
a hill giant
a hill giant
Posts: 174
Joined: Sat Jan 24, 2004 1:38 am

AcquireTarget - Makes Pulling Macros Possible

Post by SlimFastForYou » Thu Sep 16, 2004 11:03 pm

Hi Everyone,

I made a routine called AcquireTarget2.inc which will pull any NPC which isn't near another and doesn't have any other NPCs in the path to pull (animated gif below).

Haven't had too much time to test this with the new code rewrite but the old one seemed pretty stable (although it took a while). Before the rewrite it would take 5-8 seconds (an eternity if your calling it every few seconds). Now it takes ~1.5s. Not to mention it was a major mindfuck before and took almost twice as much code (thank you all who contributed your thoughts on optimization in the Macro Help forum).

Please post any bug reports / comments you have in this thread.

Image


BE SURE TO /call InitializeTargettingVariables somewhere in your macro ONCE!!

Code: Select all

|
| AcquireTarget will evaluate the distance between the closest
| X mobs and see if there is one that isn't too close to another mob
| Returns true if it found and targetted a valid spawn
|
| Also builds the array of ids of the nearest ${ClosestMobsToEvaluate} npcs
| This is later checked to see if mobs are moving around and if there is need
| to worry (return to anchor and reacquire target)
|
| Pieced together by SlimFastForYou.. many thanks to the MacroQuest Community for
| their help and feedback - this belongs to anyone and everyone who wants it.
|
|
Sub AcquireTarget
	/varset NumCandidates 0

	/for Counter 1 to 10
		| CheckMob is a whore... here it is being employed as a temp spawn id holder..
		| in the future it will be used for loops

		/varset CurrentMobID ${NearestSpawn[${Counter},npc nopcnear].ID}

		/if (!${Spawn[${CurrentMobID}].NearestSpawn[npc radius ${TooCloseDistance}].ID}) {
			/varcalc NumCandidates ${NumCandidates}+1
			/varset CandidateArray[${NumCandidates}] ${CurrentMobID}
		}
	/next Counter

	/if (!${NumCandidates}) /return 0

	/for Counter 1 to ${NumCandidates}

		/varset CannotPull 0

			/for CheckCoordinate 0 to 15

				/call ComputePlane ${CheckCoordinate} 15 ${Me.Y} ${Spawn[${CandidateArray[${Counter}]}].Y}

				/varset CheckY ${Macro.Return}

				/call ComputePlane ${CheckCoordinate} 15 ${Me.X} ${Spawn[${CandidateArray[${Counter}]}].X}

				/varset CheckX ${Macro.Return}

				/if (${Spawn[loc ${CheckX} ${CheckY} npc radius ${TooCloseDistance} notid ${CandidateArray[${Counter}]}].ID}) {

					/varset CannotPull 1

					/varset CheckCoordinate 15

					/varset CheckMob 15

				}

			/next CheckCoordinate

			/if (!${CannotPull}) {

				/varset TargetToPull ${CandidateArray[${Counter}]}

				/echo Targeting ${TargetToPull}

				/target id ${TargetToPull}

				/return 1

			}
			
	/next Counter

	/return 0

	}

/return 0


Sub InitializeTargettingVariables

	/squelch /target clear

	/declare Counter int outer
	/declare CheckMob int outer
	/declare CheckCoordinate int outer
	/declare CurrentMobID int outer

	/declare CheckX float outer
	/declare CheckY float outer
	/declare CheckMobID int outer
	/declare TargetToPull int outer

	/declare TooCloseDistance int outer 134

	/declare CannotPull bool outer

	/declare NumCandidates int outer

	/declare CandidateArray[10] int outer

/return


Sub ComputePlane(int Numerator, int Divisor, float MeN, float MobN)

	/declare tempint int local

	/declare Answer int local

	/varcalc tempint ${MobN}-${MeN}

	/varcalc tempint ${tempint}*${Numerator}

	/varcalc Answer ${Math.Calc[${tempint}/${Divisor}]}+${MeN}

/return ${Answer}

Current Wishlist:
- Better Comments
- Alerts (good mobs, bad mobs, dont wanna go near mobs, etc)

EqMule
Developer
Developer
Posts: 2697
Joined: Fri Jan 03, 2003 9:57 pm
Contact:

I like it

Post by EqMule » Fri Sep 17, 2004 4:13 am

looks good, will do some live testing
My status o/
If you like MQ2 and would like to contribute, please do. My goal is 25 donations per month.
So far I've received Image donations for this month's patches.

Bitcoin: 1Aq8ackjQ4f7AUvbUL7BE6oPfT8PmNP4Zq
Krono: PM me.
I can always use characters for testing, PM me if you can donate one.

dman
a hill giant
a hill giant
Posts: 181
Joined: Fri Dec 05, 2003 12:54 pm

Post by dman » Fri Sep 17, 2004 9:52 pm

This has nothing to do with the functioning of the macro, but a lot of my personal includes have checks that will initialize the variables for me if I haven't done so.

Code: Select all

/if (!${Defined[TooCLoseDistance]} /call Sub InitializeTargettingVariables
This won't eat many cpu cycles and also makes the include more idiot-proof I think

Lane
a hill giant
a hill giant
Posts: 201
Joined: Fri Dec 06, 2002 11:57 am

Post by Lane » Thu Sep 23, 2004 6:09 pm

This looks really great, and was something I was trying to do maually, so thank you.

If I were going to add a list of mob names to check that I didn't want to pull (in an ini file maybe) where do you as the author think the best place for that would be?

I was thinking the top of the /for Counter loop. Check the name of the spawn, and just do a /next Counter if it's not one that I want to pull.

-Lane
I Macroquest, therefor I am!

SlimFastForYou
a hill giant
a hill giant
Posts: 174
Joined: Sat Jan 24, 2004 1:38 am

Post by SlimFastForYou » Sat Sep 25, 2004 3:14 am

That question is difficult to answer Lane. I'll do my best to answer it hehe.

For now this routine will pull the target the closest "safe" NPC. I designed this to be run in PoN, but it could be easily applied to places like OT, DL, and friends. To change it to work in any other zones would require a moderate rewrite. I need to think a little about how I want to do this so that MQ isn't having to do more math than it has to (ideally a target aquire macro should take 2 secs max otherwise you might aggro something).

My PoN puller macro works something like this:
The warrior runs 4 seconds. Stops. Calls acquiretarget and if it returns false he runs back.

If this is called while the warrior is running, it bugs. Reason for that is ${NearestSpawn[n]} isn't always the same 1 second later. So with this routine you need to stop running when you call it. If I put it in to constantly evaluate spawns with several filters applied that is an expensive operation.

Basically, I think that to make AcquireTarget effective, I need to write somewhat of a SnagMob routine to encompass this, and make AcquireTarget more of an initial thing. Initial processing can be done before the puller actually leaves his anchor; from where he stands he will try to find the nearest pullable mob, and constantly the path to see if anything will add. If something will add he will simply return to his anchor and retry. If I am correct, this will not only be faster, but safer and with better features. The puller wont be evaluating once every four seconds (to use my macro as an example), but will be constantly checking the path as frequent as the computer can.

So I guess what I'm trying to say is I need to make something that actually takes care of running to the mob as well (due to me needing to do a semi-complex candidate selection, not simply kill 'em all). Finding the candidate needs to be called one time only, not several. If that candidate no longer is a candidate, the puller needs to return to anchor because if he goes for something else he will effectively be making a triangle and likely pulling adds to the camp.

Lane, as far as checking a candidate against a blacklist, Counter would probably be the simplest place to put it. As far as updating this macro, when I do get the chance to rewrite I want to have three different classifications: Mobs to pull, mobs to ignore (harmless, not worth the effort), mobs to stay away from. Of course I would like it to be flexible - where you could conservatively pull specific mobs or use it as as the leave-none-alive that it is now.

User avatar
Cr4zyb4rd
Plugins Czar
Posts: 1449
Joined: Tue Jul 20, 2004 11:46 am

Post by Cr4zyb4rd » Sat Sep 25, 2004 3:58 am

I'd be willing to look at turning this into a plugin, if you'd be interested.

Shenlon
a ghoul
a ghoul
Posts: 103
Joined: Fri Jul 30, 2004 8:02 am

Post by Shenlon » Mon Sep 27, 2004 5:02 pm

Your code looks great, and what you have is not completely dissimilar to something I had in mind to do.

I want to insert spawns into an array based on location though, let's take the example you used to illustrate my point.

In my scenario, consider mobs 1, 2, and 3. Now, I do not need a proximity aggro code, just need to NOT pull certain mobs (summoners). So, I want the code to /target mob1 and check to see if it's name is a summoner. If it is, mark off mob1. Next, /target mob2. Mob2 is not a summoner, so I want to put it into a target array.

BUT, here's the catch, I want to put it into a specific position in the array because it is mob2 and therefore at a different location. So, let's say in my target array I want location 0 to be for mob1, location 1 for mob2, and location 2 for mob3. Thus, if I target mob1 and it's a summoner, place a null value for location0 in target array and move to mob2. If mob2 is not a summoner, check it's loc and make sure that it is mob2 and not a wanderer. If loc checks out and not a summoner, insert into location1.

Does that make sense? Is it possible to do that way?

Furiousness
a lesser mummy
a lesser mummy
Posts: 62
Joined: Tue Aug 26, 2003 3:48 pm

Post by Furiousness » Tue May 10, 2005 6:32 pm

Hi,

Slight modification if you want to target a specific mob with no mobs around it. Still works great, and save my ass a lot, awesome code thank you.


Change:

Code: Select all

Sub AcquireTarget
   /varset NumCandidates 0

   /for Counter 1 to 10
      | CheckMob is a whore... here it is being employed as a temp spawn id holder..
      | in the future it will be used for loops

      /varset CurrentMobID ${NearestSpawn[${Counter},npc nopcnear].ID}
to:

Code: Select all

Sub AcquireTarget(string TName)
   /varset NumCandidates 0
/echo Acquiring Target
   /for Counter 1 to 10
      | CheckMob is a whore... here it is being employed as a temp spawn id holder..
      | in the future it will be used for loops

      /varset CurrentMobID ${NearestSpawn[${Counter},npc ${TName} nopcnear].ID}
Usage:

Code: Select all

/call AcquireTarget "a big sacrey monster" 
Thanks

Fury :D