• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

Potion Vendor Bot macro

Moonspell

Member
Joined
May 14, 2005
RedCents
This is a fairly useful macro that I wrote for use inside of my Guild Hall. This macro allows you to have a bot distribute player crafted healing/buff potions to those who ask for them. This way, you don't have to clutter up your guild's bank and your bot can hold up to 80 stacks of potions.

The bot is written to work kind of like any other NPC you might find out and about. It'll give a bit of a sales pitch periodically and it will also respond to hails. Upon request, it'll also tell you how many of each type of potion are in stock. Also, the bot will explain how to get potions from it if the user asks.

The bot is also set up to automatically accept trades, so your friends can give you plat/item donations if they so desire. My guildies funnel all their Nodding Blue Lillies to me, so this makes it convenient for them to hook me up while I'm AFK.

In order to set the bot up, stand them somewhere (preferably in a corner, facing outwards) and start the macro. Position the mouse on the center of your screen. You have to be in first person view for this to work properly. I also recommend that if you are a tall race that you look down a bit so you'll be able to click on shorter races in order to initiate trades.

Right now the user can only request one stack of potions at a time. Eventually I'll incorporate asking for multiple stacks, but I like controlling how much someone can ask for at once.

I hope you all enjoy this.

Rich (BB code):
| PotionBot.mac
| Written by Moonspell for RedGuides.com 
| Additional code provided by: z166204
| Don't steal it or I'll sick a killer Redbot on you!

| Operating Instructions
| This bot is designed to hand out various player made healing/buff potions
| when asked.  It can be queried to see what it currently has in stock
| and behaves similarly to an NPC that you would find in any given zone.

| In order to set it up, run the macro and leave your mouse positioned on the center of 
| the screen.  I've found it helpful to angle the camera downwards a bit to make sure you'll
| be able to click on short PCs (or upwards if you are a short race).  You are required to
| stay in first person view when using this macro, else it won't work.

| The bot will automatically accept any trades that it is offered so the people who
| are using your bot can make donations to you.

#turbo
#event WhatPotions "#*#What potions#*#"
#event WhatInventory "#*#What inventory#*#"
#event IGotHailed "#*#Hail, #*#"
#event BuyHoT "#0# tells you#*#Buy HoT Potion#*#"
#event BuyClarity "#0# tells you#*#Buy Clarity Potion#*#"
#event BuyHaste "#0# tells you#*#Buy Haste Potion#*#"
#event BuyDirect "#0# tells you#*#Buy Direct Heal Potion#*#"
#event LetsTrade "#*#has offered you a#*#"

Sub Main
:SalesPitch
  /echo <<< Entering Merchant Mode >>>
  /say Hey, wanna buy some "performance enhancing and mind altering drugs"?  I have some high quality [potions] in stock.  Feel free to check my [inventory]!

:wait4customers
  /doevents
  /if (${Window[TradeWnd]}) /notify TradeWnd TRDW_Trade_Button LeftMouseUp 
  /doevents
  /goto :wait4customers
  /return


|---------------------------------------------------------|
|-----------What has it gots in its pocketses?------------|
|---------------------------------------------------------|
Sub event_WhatInventory
/say So you wanna see the goods, eh? Well I have ${FindItemCount[Elixir of Healing X]} HoT Potions, ${FindItemCount[Elixir of Clarity X]} Clarity Potions, ${FindItemCount[Elixir of Speed X]} Haste Potions, and ${FindItemCount[Healing Potion X]} Direct Heal Potions.
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/doevents
/call Main


|---------------------------------------------------------|
|-----------How's it work and what do I get?--------------|
|---------------------------------------------------------|
Sub event_WhatPotions
/say I sell HoT, Clarity, Haste, and Direct Healing potions.  I also accept donations!  Check my [inventory] to see what is in stock.
/doevents
/say To buy something from me, stand directly in front of me and tell me what you want to buy.  Your choices are HoT, Clarity, Haste, or Direct Heal.
/doevents
/delay 2s
/say For example, to buy a stack of HoT potions, /tell me "buy HoT potions"
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/delay 1s
/doevents
/doevents
/call Main


|---------------------------------------------------------|
|---------------Someone said hello to me!-----------------|
|---------------------------------------------------------|
Sub event_IGotHailed
/say Hello, friend.  Wanna see my [inventory]?  Perhaps you just want to get down to business and score some [potions]?
/delay 2s
/doevents
/delay 2s
/doevents
/delay 2s
/doevents
/delay 2s
/doevents
/call Main


|---------------------------------------------------------|
|------------------Let's make a deal!---------------------|
|---------------------------------------------------------|
Sub event_LetsTrade
/delay 3s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp
/delay 10s
/say Thanks for the goods, mang!
/return



|---------------------------------------------------------|
|------------------Sell the HoT Potions-------------------|
|---------------------------------------------------------|
Sub event_BuyHoT(string targetstring)
|If person requesting pots not in zone return to mainloop.
/if (!${Spawn[pc ${targetstring}].ID}) /return
|If person is out of range return to mainloop.
/if (${Spawn[pc ${targetstring}].Distance3D}>10) {
   /t ${targetstring} Your too far away. Get closer so i can reach you.
   /return
}
|If out of potions return to loop with notify.
/if (!${FindItemCount[Elixir of Healing X]}) {
   /t ${targetstring} Oh dammit!  I ran out of Haste potions.  You're going to have to wait til the next shipment from Columbia comes in, sorry.
   /return
}

/t ${targetstring} Okay, let me get your goods ready for you.  This can take a minute or two.  Make sure you're standing right in front of me and are close.
/delay 1s


/call openbags
/delay 5

|picks up 1 stack of potions in one line.
/shift /itemnotify ${FindItem[Elixir of Healing X].InvSlot} LeftMouseUp
/delay 5

|force target type as pc so no pet targeting issues
/target pc ${targetstring}
/delay 1s
/click left target

/delay 2s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp

|loop to wait for accept of trade.
:claritytradeclose
/delay 1
/if (${Window[TradeWnd]}) /goto :claritytradeclose
/delay 1s


/call closebags
/say Nice doing business with you!
/return


|---------------------------------------------------------|
|-----------We've got a crackhead on our hands------------|
|---------------------------------------------------------|
Sub event_BuyClarity(string targetstring)
|If person requesting pots not in zone return to mainloop.
/if (!${Spawn[pc ${targetstring}].ID}) /return
|If person is out of range return to mainloop.
/if (${Spawn[pc ${targetstring}].Distance3D}>10) {
   /t ${targetstring} Your too far away. Get closer so i can reach you.
   /return
}
|If out of potions return to loop with notify.
/if (!${FindItemCount[Elixir of Clarity X]}) {
   /t ${targetstring} Sorry I'm currently out of crack in a bottle. Cocaine is a hell of a drug!
   /return
}

/t ${targetstring} Okay, let me get your goods ready for you.  This can take a minute or two.  Make sure you're standing right in front of me and are close.
/delay 1s


/call openbags
/delay 5

|picks up 1 stack of potions in one line.
/shift /itemnotify ${FindItem[Elixir of Clarity X].InvSlot} LeftMouseUp
/delay 5

|force target type as pc so no pet targeting issues
/target pc ${targetstring}
/delay 1s
/click left target

/delay 2s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp

|loop to wait for accept of trade.
:claritytradeclose
/delay 1
/if (${Window[TradeWnd]}) /goto :claritytradeclose
/delay 1s


/call closebags
/say Nice doing business with you!
/return



|---------------------------------------------------------|
|-----------We have a speed freak on our hands------------|
|---------------------------------------------------------|
Sub event_BuyHaste(string targetstring)
|If person requesting pots not in zone return to mainloop.
/if (!${Spawn[pc ${targetstring}].ID}) /return
|If person is out of range return to mainloop.
/if (${Spawn[pc ${targetstring}].Distance3D}>10) {
   /t ${targetstring} Your too far away. Get closer so i can reach you.
   /return
}
|If out of potions return to loop with notify.
/if (!${FindItemCount[Elixir of Speed X]}) {
   /t ${targetstring} Oh dammit!  I ran out of Haste potions.  You're going to have to wait til the next shipment from Columbia comes in, sorry.
   /return
}

/t ${targetstring} Okay, let me get your goods ready for you.  This can take a minute or two.  Make sure you're standing right in front of me and are close.
/delay 1s


/call openbags
/delay 5

|picks up 1 stack of potions in one line.
/shift /itemnotify ${FindItem[Elixir of Speed X].InvSlot} LeftMouseUp
/delay 5

|force target type as pc so no pet targeting issues
/target pc ${targetstring}
/delay 1s
/click left target

/delay 2s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp

|loop to wait for accept of trade.
:claritytradeclose
/delay 1
/if (${Window[TradeWnd]}) /goto :claritytradeclose
/delay 1s


/call closebags
/say Nice doing business with you!
/return



|---------------------------------------------------------|
|-----------Someone wants blast heal potions??------------|
|---------------------------------------------------------|
Sub event_BuyDirect(string targetstring)
|If person requesting pots not in zone return to mainloop.
/if (!${Spawn[pc ${targetstring}].ID}) /return
|If person is out of range return to mainloop.
/if (${Spawn[pc ${targetstring}].Distance3D}>10) {
   /t ${targetstring} Your too far away. Get closer so i can reach you.
   /return
}
|If out of potions return to loop with notify.
/if (!${FindItemCount[Healing Potion X]}) {
   /t ${targetstring} Oh dammit!  I ran out of Direct Healing potions.  You're going to have to wait til the next shipment from Columbia comes in, sorry.
   /return
}

/t ${targetstring} Okay, let me get your goods ready for you.  This can take a minute or two.  Make sure you're standing right in front of me and are close.
/delay 1s

/call openbags
/delay 5

|picks up 1 stack of potions in one line.
/shift /itemnotify ${FindItem[Healing Potion X].InvSlot} LeftMouseUp
/delay 5

|force target type as pc so no pet targeting issues
/target pc ${targetstring}
/delay 1s
/click left target

/delay 2s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp

|loop to wait for accept of trade.
:claritytradeclose
/delay 1
/if (${Window[TradeWnd]}) /goto :claritytradeclose
/delay 1s


/call closebags
/say Nice doing business with you!
/return


|---------------------------------------------------------|
|---------Open up your bags and see what we got-----------|
|---------------------------------------------------------|
Sub openbags
/delay 2s
/cleanup
/keypress I
/delay 1s
/itemnotify 22 rightmouseup
/itemnotify 23 rightmouseup
/itemnotify 24 rightmouseup
/itemnotify 25 rightmouseup
/itemnotify 26 rightmouseup
/itemnotify 27 rightmouseup
/itemnotify 28 rightmouseup
/itemnotify 29 rightmouseup
/delay 1s
/return


|---------------------------------------------------------|
|-----------Clean up your room when you're done-----------|
|---------------------------------------------------------|
Sub closebags
/delay 2s
/cleanup
/delay 1s
/return

Thanks again to z166204 for the help!
 
Last edited:
While I like the idea you have I think this type of macro would just bring too much attention to yourself. Its like saying hi I'm so and so, I'm using macroquest, please ban me. All it would take is one person in your guild to bring attention to yourself.

Mabye if it was setup fully private (all communication via tells, commands etc) it would be safer but you still run risks.

The scripting itself looks ok for the most part. I would suggest changing the calls to main to returns though.

Rich (BB code):
/call Main
to
Rich (BB code):
/return

Basically with your current setup it is already permanently repeating in the :wait4customers loop you have. The /doevents calls will end up recalling the main sub which shouldnt be needed, as your subs will /return back to this main loop you have in place.

One other suggestion to improve the script would be setup forced trading to specific target when they request it the potions. First get the potions on your cursor then target and add the items to trade window.

Rich (BB code):
/target <someone>
/delay 1s
/if (${Target.Distance3D}<15) {
  /click left target
  } else {
  /autoinventory
  /r Your too far away to get your crack potions
  }
 
Thanks for the tip, z166. I always had trouble getting the click command to work for me, but I didn't know that you could set it up to click what you had targeted. So would you recommend that in order to target whoever is asking for buff that I just use /rt vice setting up an event? I think it would be easier that way.


As far as advertising/sales pitch goes I think it adds flavor to the bot, and I'm really not concerned with detection. I think (as with most other things you can do with vanilla MQ) that the only thing that'll get you busted is if someone in your guild hall decides to /report you. Even then, I don't know that the CSR's would particularly care since the bot isn't distruptive to gameplay since he's not getting money, items, nor experience. Then again, I could be 100% wrong, but that's the chance I'm willing to take on my bot account :-D

Thanks again.
 
Personally I would setup the macro to force the target. Say your going to request them tell you for the potions... heres a sample of a sub that I believe would work - not tested.

Rich (BB code):
#event BuyClarity "#0# tells you#*#Buy Clarity Potions#*#"

Sub Event_BuyClarity(string targetstring)
|If person requesting pots not in zone return to mainloop.
/if (!${Spawn[pc ${targetstring}].ID}) /return
|If person is out of range return to mainloop.
/if (${Spawn[pc ${targetstring}].Distance3D}>10) {
   /t ${targetstring} Your too far away. Get closer so i can reach you.
   /return
}
|If out of potions return to loop with notify.
/if (!${FindItemCount[Elixir of Clarity X]}) {
   /t ${targetstring} Sorry I'm currently out of crack in a bottle.
   /return
}

/t ${targetstring} Okay, let me get your goods ready for you.  This can take a minute or two.  Make sure you're standing right in front of me and are close.
/delay 1s

|make a sub to open all bags for universal use.
/call openbags
/delay 5

|picks up 1 stack of potions in one line.
/shift /itemnotify ${FindItem[Elixir of Clarity X].InvSlot} LeftMouseUp
/delay 5

|force target type as pc so no pet targeting issues
/target pc ${targetstring}
/delay 1s
/click left target

/delay 2s
/notify TradeWnd TRDW_Trade_Button LeftMouseUp

|loop to wait for accept of trade.
:claritytradeclose
/delay 1
/if (${Window[TradeWnd]}) /goto :claritytradeclose
/delay 1s

|make a function to close all bags universal
/call closebags
/return
 
Thanks for the helpful post. When I get some time I think I'll incorporate your idea into my macro!
 
I've been thinking about making a macro for the longest time to run on an alt account in Guild Lobby to be a Buff Bot and Potion Distributor and have a userlist. I may borrow some of this for it :) (and give credit if I decide to distrubute my finished product)
 
The macro has been updated on the first post to add some more functionality and fix a bug which prevented users from donating cash to the bot.
 
need to change the loops in each sub for different potions so they are unique. :)

Rich (BB code):
:claritytradeclose
 
z166204, they just have to be unique to each sub, not unique to the entire macro.

Here's an example which will work just fine.

Sub Sub1
:Loop
/goto :Loop
/return

Sub Sub2
:Loop
/goto :Loop
/return
 
Rewritten (untested) Moonspells macro to use tells, and with fewer events, which instead are handled within one (or actually two) events.
Also added linked messages..

Rich (BB code):
| PotionBot.mac
| Written by Moonspell for RedGuides.com 
| Additional code provided by: z166204
| Don't steal it or I'll sick a killer Redbot on you!

| Operating Instructions
| This bot is designed to hand out various player made healing/buff potions
| when asked.  It can be queried to see what it currently has in stock
| and behaves similarly to an NPC that you would find in any given zone.

| In order to set it up, run the macro and leave your mouse positioned on the center of 
| the screen.  I've found it helpful to angle the camera downwards a bit to make sure you'll
| be able to click on short PCs (or upwards if you are a short race).  You are required to
| stay in first person view when using this macro, else it won't work.

| The bot will automatically accept any trades that it is offered so the people who
| are using your bot can make donations to you.

#turbo
#Event  ChatSay     "#1# says, '#2#'"
#Event  ChatTell    "#1# tells you, '#2#'"

Sub Main
    /declare ElixirOfHealingX   string  outer   012FDC000000000000000000000000000000024CEFC8FElixir of Healing X
    /declare ElixirOfSpeedX     string  outer   012FFA00000000000000000000000000000002E89CDF6Elixir of Speed X
    /declare ElixirOfClarityX   string  outer   0130040000000000000000000000000000000C170CD9BElixir of Clarity X
    /declare HealingPotionX     string  outer   012FE60000000000000000000000000000000968561C4Healing Potion X

    /echo <<< Entering Merchant Mode >>>

    :WaitLoop
        /doevents
        /if (${Window[TradeWnd]}) /notify TradeWnd TRDW_Trade_Button LeftMouseUp 
        /doevents
    /goto :WaitLoop
/return

Sub OpenBags
    /declare bag                int     local   0
    /cleanup
    /if (!${Window[InventoryWindow].Open}) /nomodkey /keypress inventory
    /delay 1s
    /for bag 1 to 8
        /if (!${Window[Pack${bag}].Open}) /nomodkey /itemnotify pack${bag} rightmouseup
    /next bag
    /delay 1s
/return

Sub CloseBags
    /declare bag                int     local   0
    /if (!${Window[InventoryWindow].Open}) /nomodkey /keypress inventory
    /delay 1s
    /for bag 1 to 8
        /if (${Window[Pack${bag}].Open}) /nomodkey /itemnotify pack${bag} rightmouseup
    /next bag
    /delay 1s
    /if (${Window[InventoryWindow].Open}) /nomodkey /keypress inventory
    /delay 1s
/return

Sub Event_ChatSay(string Line, string Toon, string Msg)
    /if (${Msg.Equal[Hail, $Me.Name]}) {
        /tell ${Toon} Hello, friend. Wanna see my [inventory]? Perhaps you just want to get down to business and score some [potions]?
        /delay 1s
        /tell ${Toon} Use /tell's to communicate your wishes.
    }
/return

Sub Event_ChatTell(string Line, string Toon, string Msg)
    /if (${Msg.Find[inventory]}) {
        /tell ${Toon} I have the following items for sale:
        /if (${FindItemCount[Elixir of Healing X]} > 0) {
            /delay 1s
            /tell ${Toon} ${FindItemCount[Elixir of Healing X]}x ${ElixirOfHealingX}
        }
        /if (${FindItemCount[Elixir of Clarity X]} > 0) {
            /delay 1s
            /tell ${Toon} ${FindItemCount[Elixir of Clarity X]}x ${ElixirOfClarityX}
        }
        /if (${FindItemCount[Elixir of Speed X]} > 0) {
            /delay 1s
            /tell ${Toon} ${FindItemCount[Elixir of Speed X]}x ${ElixirOfSpeedX}
        }
        /if (${FindItemCount[Healing Potion X]} > 0) {
            /delay 1s
            /tell ${Toon} ${FindItemCount[Healing Potion X]}x ${HealingPotionX}
        }
    } else /if (${Msg.Find[potions]}) {
        /say I sell ${If[${FindItemCount[Elixir of Healing X]}>0,Elixir of Healing X,]}, ${If[${FindItemCount[Elixir of Clarity X]}>0,Elixir of Clarity X,]}, ${If[${FindItemCount[Elixir of Speed X]}>0,Elixir of Speed X,]} and ${If[${FindItemCount[Healing Potion X]}>0,Healing Potion X,]}. I also accept donations! Check my [inventory] to see what is in stock.
        /say To buy something from me, stand directly in front of me and tell me what you want to buy.  Your choices are HoT, Clarity, Haste, or Direct Heal.
        /say For example, to buy a stack of HoT potions, /tell me "buy HoT potions"
    } else /if (${Msg.Find[buy]}) {
        /if (!${Spawn[pc ${Toon}].ID}) {
            /tell ${Toon} You're not in the zone. Please try again when you're standing beside me.
            /return
        }
        /if (${Spawn[pc ${Toon}].Distance3D}>10) {
            /tell ${Toon} You're too far away. Please try again when you're standing beside me.
            /return
        }
        /if (${Msg.Find[clarity]} || ${Msg.Find[crack]}) {
            /if (!${FindItemCount[Elixir of Clarity X]}) {
                /tell ${Toon} Sorry I'm currently out of ${ElixirOfClarityX}!
                /return
            }
            /tell ${Toon} Okay, let me get your goods ready for you. This can take a minute or two. Make sure you're standing beside me.
            /delay 1s
            /call OpenBags
            /delay 5
            /shift /itemnotify ${FindItem[Elixir of Clarity X].InvSlot} LeftMouseUp
        } else /if (${Msg.Find[speed]} || ${Msg.Find[haste]}) {
            /if (!${FindItemCount[Elixir of Speed X]}) {
                /tell ${Toon} Sorry I'm currently out of ${ElixirOfSpeedX}!
                /return
            }
            /tell ${Toon} Okay, let me get your goods ready for you. This can take a minute or two. Make sure you're standing beside me.
            /delay 1s
            /call OpenBags
            /delay 5
            /shift /itemnotify ${FindItem[Elixir of Speed X].InvSlot} LeftMouseUp
        } else /if (${Msg.Find[hot]} || ${Msg.Find[regen]} || ${Msg.Find[Elixir of Healing]}) {
            /if (!${FindItemCount[Elixir of Healing X]}) {
                /tell ${Toon} Sorry I'm currently out of ${ElixirOfHealingX}!
                /return
            }
            /tell ${Toon} Okay, let me get your goods ready for you. This can take a minute or two. Make sure you're standing beside me.
            /delay 1s
            /call OpenBags
            /delay 5
            /shift /itemnotify ${FindItem[Elixir of Healing X].InvSlot} LeftMouseUp
        } else /if (${Msg.Find[heal]} || ${Msg.Find[Healing Potion]}) {
            /if (!${FindItemCount[Healing Potion X]}) {
                /tell ${Toon} Sorry I'm currently out of ${HealingPotionX}!
                /return
            }
            /tell ${Toon} Okay, let me get your goods ready for you. This can take a minute or two. Make sure you're standing beside me.
            /delay 1s
            /call OpenBags
            /delay 5
            /shift /itemnotify ${FindItem[Healing Potion X].InvSlot} LeftMouseUp
        } else {
        }
        /delay 5
        /target pc ${Toon}
        /delay 1s
        /click left target
        /delay 2s
        /notify TradeWnd TRDW_Trade_Button LeftMouseUp
        :TradeLoop
            /delay 1
        /if (${Window[TradeWnd]}) /goto :TradeLoop
        /delay 1s
        /call CloseBags
        /tell ${Toon} Nice doing business with you!
    }
/return
 
only way i would use that is if the guild all used it , or it was my personal Alt guild.
 
Potion Vendor Bot macro

Users who are viewing this thread

Back
Top
Cart