• You've discovered RedGuides 📕 an EverQuest multi-boxing community 🛡️🧙🗡️. We want you to play several EQ characters at once, come join us and say hello! 👋
  • IS THIS SITE UGLY? Change the look. To dismiss this notice, click the X --->
PetBot

Macro - PetBot (1 Viewer) 1.0

make your while (1) into while (me.pet.id).

could use some more options to break the inf loops too. a use command to break or something.
 
/varset NearestMobID ${NearestSpawn[1,npc targetable radius 200 zradius 50].ID}

your loop never increments the nearest mob. its always going to go back to the same one even if its on your ignore list.
 
so you make the looping worse and dont fix the whiles.

why are you looping 100 mob searches? what if theres only 1 mob or 300.. you've already established you're only searching to 200 paces which is also flawed as some pet classes go to 350 for a pet range. but why not just search by the spawn count as the loop?
 
Even /echo Hi! can be critiqued.

Evaluation 6-29-21:
Exceeds output expectations set out for his/her department



In all seriousness, thank you, AmericanNero!

I am sure not many people understand the reason I requested this, but it will make camping a small radius easy without all the running around PKF or CWTNPlugins do.
 
Everyone starts somewhere. You see it as bad habits, I see it as a new user trying to start with a simple macro and build onto it to create something better. A lot of the things available in the MQ2 community start out that way. Pretty sure none of us have written perfect code the first time around and refactoring code is an extremely common practice.

I often remind myself that there was once a time when I didn't know any of this stuff and that building up my knowledge of macros is a large part of how I got to the point where I am today. That covers everything from proper indentation, spacing, knowing what information I had access to use, and some good common practices to implement into macros. There are things I've learned from the Wiki, but the biggest thing I learned from when writing macros was other macros. When I first started the simpler the macro the better. It might only inspire 1 or two people to create something for themselves, but it might also be that it's the start for the next KA, RGMercs, MA, ModBot, Entropy, PocketFarm, etc. hard to say.

What I do know is that I think it's better to try to help someone if you feel there is an improvement that can be made as opposed to shaming them for not being perfect.
 
I often remind myself that there was once a time when I didn't know any of this stuff and that building up my knowledge of macros is a large part of how I got to the point where I am today.
This actually sums up pretty well why I feel the way I do about honoring the MQ license and not having closed source things.

Maybe https://gist.github.com/ or a pastebin would be more suited for learning? I generally interpret resources to be something a little more polished.
But I agree with this as a good way to collaborate. However, as a bridge, maybe a section on the forums for works in progress rather than going straight to a resource. Because…

I think it's better to try to help someone if you feel there is an improvement that can be made as opposed to shaming them for not being perfect.
I also agree with this. Criticism can be constructive or destructive and there are very few personality types that learn from destructive criticism. Constructive criticism is given with the intent of building someone up, not tearing them down.

I disagree with the “write it yourself” approach, since no one learns from that. But a good approach is to tell someone what they’re doing wrong, but also offer tips for how to improve, allowing room for questions.
 
Wow. WTG guys, I help someone out with a basic request and everyone starts fighting. That's not the spirit of this. I'm not charging anything for it... am I stealing turkey off your plate posting this?
 
For perspective, I saw this as a discussion, not a fight.

I suspect the crux of the issue is that a quick fix and a resource are seen as two different things. The important part about this is that it solved the problem Rusang had. As for whether it should be a resource, that goes back to what a resource means.

To me a resource doesn’t mean anything, but to others it may be seen as “curated content.”
 
Last edited:
I followed the discussion, and haven't really determined if this was intended as a resource, or a learning exercise, or a favor to someone. But it did remind me of a similar macro that I used to farm a few TS items (cazicite at the temple in CT for one). I decided to pretty it up and post it here not so much as better, but as a possible example of 'sometimes less is more'. The macro has only ~25 lines of actual code in it, but I think it has all of the functionality required for the task. I have tested it, but not since I added a few more comments (with the conceit that this example might help someone, per the original intent). Also, full disclosure - I updated my macro to include a couple things from AN's version (like a better way to check for the mob being dead without using my own target).

There are a few things that could be improved as an exercise (not worth it to me as I don't use it much, and don't actually AFK with it):
1) Add PC proximity check in addition to GM. Thinking I might need to use a different alert list to allow group or guild members to be ignored (don't think Spawn search allows a negative search criteria).
2) If a mob moves out of pet range it might still be alive after the timeout and be added to the ignore list even if it wanders back later.
3) More parameter options (level range, zradius, etc.)

pethunt.mac:
| ------------------------------------------------------------------
| Basic pet hunt macro.
|
| If you have a pet, this macro will send it out to kill anything
| within the search radius. Best used to farm in an area where pathing makes
| killing them yourself a hassle, or you don't otherwise use an automation macro.
|
| Running this in a zone with high level mobs is likely to get you killed. There
| is no self-defense built in. Pet will only come back and kill mobs that
| attack you after killing their current target.
|
| Running this AFK in a zone with a lot of PCs is likely to get you banned. It
| only implements a minimal zone-wide GM check.
|
| Useage: /mac pethunt <radius>
| ------------------------------------------------------------------
Sub Main

  | Variable declarations.
  /declare closest_mob_id   int inner 0
  /declare pet_pull_radius  int inner 200
 
  | First parameter is pet pull radius to use. Defaults to 200.
  /if (${Defined[Param0]}) {
    /varset pet_pull_radius ${Param0}
  }
 
  | Clear the ignore list.
  /alert clear 1

  | Alert list 1 is used as the mob ignore list. Add a line for each mob
  | you want to ignore. Normally you will just add them for the zone
  | you are hunting in (e.g. make a button such as /alert add 1 ${Me.Target}).
  |/alert add 1 "mob to ignore"
 
  | Loop until something drastic happens.
  /while ( ${Me.Pet.ID} ) {

    | If there is a GM in the zone, just wait.
    /if (${Spawn[gm].ID}) {
      /delay 30s
      /continue
    }
    
    | Get the ID of the nearest qualified mob.
    /varset closest_mob_id ${NearestSpawn[npc radius ${pet_pull_radius} targetable noalert 1].ID}
    /if (${closest_mob_id} == 0) {
      /delay 5s
      /continue
    }
      
    | Target the mob, send pet to kill it, and wait until the mob is dead.
    /echo Sending ${Pet.CleanName} to kill ${Spawn[id ${closest_mob_id}].Name}
    /target id ${closest_mob_id}
    /pet attack
    /delay 90s (!${Spawn[id ${closest_mob_id}].ID} || ${Spawn[id ${closest_mob_id}].Type.Equal[Corpse]})

    | Recall pet. This may sometimes be faster than issuing a new target
    | and attack while pet wanders back, depending on mob arrangement. Adjust
    | to taste. Back off is in case mob is still alive (in which case you
    | better hope he is a quest or merchant mob and isn't coming back to keeel you).
    /pet back off
    /alt act 1215
      
    | If the mob is still alive then add it to the ignore list. This adds only
    | this specific mob.
    /if (${Spawn[id ${closest_mob_id}].ID} && !${Spawn[id ${closest_mob_id}].Type.Equal[Corpse]}) {
      /alert add 1 ${Spawn[id ${closest_mob_id}].Name}
    }
  }
/end
 
couple Ideas you could throw in there:

- only recall a pet when it is more then a specific range away. that can eat up mana. and whats the point of the pet is 20 paces away.
- wrap your target ID check in a small timed loop to make sure your target is correct before sending pet or bail and retry. Also, check that the pet isnt engaged first before the back of.
- use a spawn data type.
- the delay 90s might be a little excessive. small loop with a few reasons to break and a very short timer for the loop. mobs in range, being attacked, no mobs, mob dead, so on.

id change the way you are passing the initial variable for pet radius too, but thats me.

none of these are critical, just some thoughts.
 
I wasn't planning on going further but, what the heck. Here's what's on the menu.

| -----------------------------------------------------------------------------
| petbot.mac v1.0 by AmericanNero 6/30/2021
|
| /mac petbot bite/wild/wag(optional)
|
| Petbot will faithfully maul all nearby mobs until they are out of hps.
| Unless it dies, you die, are cowardly and invis, enter a "safe space",
| tuck your tail between your legs and flee to the zoneline, or evac, it will
| continue it's rampage of senseless slaughter. I repeat. Petbot is rabid!
|
| What good is a pet if it won't protect it's master? If you are aggrod, the
| pet will rush to your aid and taunt them off. It will even try to save your
| cleric merc. Now that's a good boy!
|
| Petbot is also cunning. Details...details...
|
| Petbot.ini is created on initial startup. Each setting has instructions
| within the ini.
|
| If petbot is started without an option, or you zone, it will be a good boy
| on its leash. You can then tell it what to do next. You have three options.
| Bite now, wag later....be wild and free....or wag now, bite later. These
| will be explained. But first, the commands.
|
| /pbpause or /pbleash
| /pbresume or /pbunleash
| /pbquit or /pbgohome
|
| /pbbite
| /pbwild or /pbfree
| /pbwag
|
| /pbignore or /pbdownboy "name in quotes"
| /pbkos or /pbkill "name in quotes"
| /pbremove or /pbforget "name in quotes"
|
| Bite Now /pbbite
| Petbot will start attacking everything around it. If the mob is the
| right level and not on the ignore list, it will be mercilessly hunted.
| Pro-tip: /pbleash before you try to /pbignore nearby npcs that you'd rather
| not aggro. Otherwise, if you target a mob that is not ignored, it's going
| to try to eat it. That's... how petbot do. (H/T zefrank)
|
| Wild and Free /pbwild or /pbfree
| Your pet is wary of strangers. As long as the mob is the right level (if
| you use that option), then a mob on the KOS list will be dispatched, and a
| mob on ignore will be left alone. Other options, explained further down,
| will allow petbot to make decisions about friend or foe and risk aversion.
|
| Wag Now /pbwag
| Petbot is a good boy, and won't try to bite group members. But, if you target
| a grove hare that is the right level, and /pbkos or /pbkill, your pet will
| happily interpret that as a thumbs down and take care of business. The mob
| is added to the KOS list and your pet will deal with any it sees. Petbot won't
| senselessly attack everything you target.
|
| To manually add a mob to the zone ignore list, use /pbignore "name in quotes".
| You may instead target the mob. Leashing the pet, before you /pbignore, is
| highly recommended because it may take great interest in anything you target
| and might murder it depending on what mood the pet is in. If the mob was
| KOS, it will be removed from that list. Putting a mob on the kos list /pbkos
| will also remove it from the ignore list. Use /pbremove to take the mob off
| both lists.
|
| Petbot can /consider mobs for you, if you let it. Non-hostile mobs will be
| placed on ignore, and hostile on kos. If you are factioning, you may need to
| update the lists. Petbot can take a look around and decide whether the time
| is ripe. If there are a lot of mobs close to the target, or a dangerous mob
| in aggro range, it may opt to hang back.
|
| PetBot is a good boy. Yes you are!
|
| -----------------------------------------------------------------------------
 
couple Ideas you could throw in there:

- only recall a pet when it is more then a specific range away. that can eat up mana. and whats the point of the pet is 20 paces away.
- wrap your target ID check in a small timed loop to make sure your target is correct before sending pet or bail and retry. Also, check that the pet isnt engaged first before the back of.
- use a spawn data type.
- the delay 90s might be a little excessive. small loop with a few reasons to break and a very short timer for the loop. mobs in range, being attacked, no mobs, mob dead, so on.

id change the way you are passing the initial variable for pet radius too, but thats me.

none of these are critical, just some thoughts.
In the spirit of the thread, and not just being defensive
1) I've never been in a zone where there are more than 20-30 mobs within pet pull range, and pet usually takes a tick or so to get to and kill mobs, so mana has never dropped more than 1-2% when using this (then there's the usual 10-20 minute respawn anyway). So while the input is valid, it is not a practical concern.
2) The purpose of the back off is exactly for the case where the pet is engaged (if not engaged he wouldn't need to be backed off). If he has been fighting the same mob for 90 seconds it is likely non-killable and I don't want him running back out to it. Yes, he could immediately have a new target from a social mob (unlikely for non-killable mobs), but in that case the mob will come-a-calling anyway. So why add the complexity? As for the target ID check - I don't know of any design that would avoid the potential to have a last-instant change in targets (between the /tar command and /pet attack command) where I would end up sending the pet against a target different than closest_mob_id. If you can suggest such a design pattern (or indeed what would cause the target switch in the first place) please do.
3) For what?
4) This is a timeout - don't really care if it is excessive, as it should never occur anyway. The delay ends as soon as the mob is dead. I would rather have it take 90 seconds to correctly add a mob to the ignore list than have real target mobs get ignored because some pathing issue made the pet take a few extra seconds to get to the mob. Also, this type of thing is what the /delay condition is for - why re-invent that wheel? New conditions can just be added there.

Needless complexity makes debugging much harder. AN's current version has an apparently significant error on line 61 where it is looking for the last iteration on the loop but uses 10 instead of 100. But the defect isn't even noticed because the whole construct isn't required - if it was actually working as intended it would cause the 100th mob to be ignored even if it was not in the ignore list. As it is right now, if the first 9 mobs in the list are being ignored, and the 10th mob is not, it will stop and restart the loop, effectively stopping the whole macro. But this situation will likely never come up, and the whole thing shouldn't really exist since the alert list is a better way of handling this anyway (just add a loop to the start of the macro to add the ignored mobs to the alert list).

P.S. Assuming that loop in AN's code is retained, I would redesign it as follows (not sanctioning the design, just fixing it). This makes it a bit more clear that this is effectively an infinite loop with no delays.
INI:
           /while (1) {
                /varset NearestMobID 0
                /varset MobCount ${SpawnCount[npc targetable radius 200 zradius 50 noalert 1]}
                /for i 1 to ${MobCount}
                    /varset CandidateMobId ${NearestSpawn[${i},npc targetable radius 200 zradius 50 noalert 1].ID}
                    /if (!${IgnoreList.Find[${Spawn[id ${CandidateMobId}].CleanName}]}) {
                        /varset NearestMobId ${CandidateMobId}
                        /break;
                    }
                /next i
                /if (${NearestMobId} != 0) /break
            }
 
Last edited by a moderator:
your macro, all you bud.
Believe it or not, I was looking for input here. The documentation on MQ2 is sparse and often out of date, so if there are better ways to do things then I am all for it. I included two comments giving the opportunity for you to explain what you meant - the first for the target issue, and the second for the obscure spawn type reference. But instead, we get a dismissive and passive aggressive response. Thanks for the effort.
 
I should have shown the evolution of the script. The code fragment that people are concerned with was intended by a contributor to guide me how I could investigate further. The road, as is said, is paved with good intentions. But, since pets elicit such strong reactions in-game and are downright fun and useful when employed right, I am preparing a more fully realized petbot.
 
Wow, nice add @AmericanNero

I love the discussion and hate that it turned into one way is better than the other. AN, in his initial 0.1, already made a macro exceeding my expectations. I was thinking at most I might get a /if command line response in my original post, not a macro evolving each day.

Sometimes a small request can turn into something big... I like it.

I'll be using 1.0 when it's posted, if not already. I will try out the other posters macro also.
 
so, i decided to take a different approach as my suggestions seemed to be taken as some form of hate or discourse. this is an adaptation/adjustment of ANs last post of the macro. feel free to butcher it.

/mac petbot ###

where ## is the radius you want to kill in.
keep in mind over 350 on a mage is useless for pets.

NOTE: this is on MQNext, i'm not sure if the spawn data types were ever adapted to legacy MQ2.
 

Attachments

  • petbot.mac
    2.2 KB · Views: 5
Believe it or not, I was looking for input here. The documentation on MQ2 is sparse and often out of date, so if there are better ways to do things then I am all for it. I included two comments giving the opportunity for you to explain what you meant - the first for the target issue, and the second for the obscure spawn type reference. But instead, we get a dismissive and passive aggressive response. Thanks for the effort.

you're right. i should have gone about this all differently. so i did.

to address some of the other things. the spawn data type is not exactly obscure. its very handy. you can see how it can be used i the example i posted. as well as an alternate copntrol over the mobs to be found and killed.

and yah, the MQ wiki is not maintained very well. people try, but it has fallen behind in places.
 
you're right. i should have gone about this all differently. so i did.

to address some of the other things. the spawn data type is not exactly obscure. its very handy. you can see how it can be used i the example i posted. as well as an alternate copntrol over the mobs to be found and killed.

and yah, the MQ wiki is not maintained very well. people try, but it has fallen behind in places.
Thanks for the reply. It was helpful.

I agree, spawn isn't obscure - it is used commonly. But the use of spawn as a data type, and how to set it using /vardata is a bit obscure. The use of /vardata is not that clearly indicated on the Wiki (I am still a bit fuzzy on its uses, but I will play a bit). In the macros I have downloaded, there is only a single use of 'spawn' as a data type (in RGMERCS), and only 2 other macros even use /vardata (kiss and mule assist), and then sparingly. Most tend to work with the spawn's ID instead and use Spawn[id ID] to get back to the original spawn type and members, and we learn by example...

Still fairly new to this stuff. That was probably the third MQ2 macro I made. So everything is appreciated.
 
look in my signature, there are hundreds of different examples of varadata being used, for spawn, spell, and other things. there are a lot more maros out there then mule and kiss.
 
look in my signature, there are hundreds of different examples of varadata being used, for spawn, spell, and other things. there are a lot more maros out there then mule and kiss.
But Johnny, you ain’t got no signature (on mobile).

It’s also likely that, as brainiac pointed out somewhere around here — handling id was safer in the old MQ2. You had to be more careful with spawn to not crash, which led to it getting used less.
 
I downloaded it and it isn't showing up in the red guides launcher. I refreshed, didn't work, rebooted the computer, and tried again but it still isn't showing up in the launcher.
 
Macro - PetBot

Users who are viewing this thread

Back
Top