Page 1 of 2

Bazaar Tribute Item Search .mac

Posted: Sat May 26, 2007 2:57 am
by zoobish
I use MQ2 to look for tribute items in the bazaar...

I set my price range 1 - 3000, set the slot and search.

I then open things up and look at what the tribute value is, decide if the price is right for the item, then buy if its good.

?? :?: ??

BUT THEN I THORT SUM THORTS !!!

I thought, "Hold on.. Im using MQ to just open up item views to see the tribute on an item to see if is worth buying for tribute :oops: "...

Then I thought, "Crap!! I could automate this whole thing!!! :idea: "

Then I hacked, slept, wasn't quite pleased, and hacked again...

INTRODUCING TRIBUTE.MAC v0.2

This macro will open the bazaar search window, set the max price, loop the slots, press the search button, look at the items, then alert you when it finds an item with good tribute value, according to a ratio YOU set...

OMG, it even presses the "FIND TRADER" button!

Im working on some sort of "follow the magic gold path" thing, but I believe it may not be in the MQ stuff yet... May look into finding it and implimenting some sort of "follow the magic gold path" type thing... hmm..

So... All you do is goto the bazaar Trader side bank (not barter..), and type:

Code: Select all

/mac tribute 10 3000
Then sit back, chat, wait for the alert to tell you it found sompthin =)

Here it is:

Code: Select all

| tribute.mac	v0.2
|
| Author: 	I made it myself =P (zoobish)
| =======
|
| Function: 	Searches bazaar for tribute items worth buying.
| =========	You set the RATIO you like, i.e. 10 means 100pp
|		for 1000 tribute.  You may set the RATIO via the
|		first argument when calling this.
|		e.g. /mac tribute 15
|		You can also set the MaxPrice with the second
|		argument if you wish.
|		e.g. /mac tribute 15 3000
|		I find 3000 to be ample.
|		It will alert you when it finds something.
|

#turbo

| This is the trigger for restarting the search after yah buy the current item.
| You can change it to whatever you want I suppose...
#event gogogo "#*#i need more TRIB now#*#"

#event notForSale "#*#That item is no longer for sale in the bazaar#*#"

Sub Main
	| SET THESE IF YOU WISH, overridden by calling arguments.
	/declare RATIO int outer 10
	/declare MaxPrice int local 3000

	/declare reStartFlag bool outer
	/declare I int local
	/declare J int local
	/declare cPrice int local
	/declare cTrib int local
	/declare forSale bool outer
	/declare aSlotNum[15] int local
	/varset aSlotNum[1] 3
	/varset aSlotNum[2] 4
	/varset aSlotNum[3] 6
	/varset aSlotNum[4] 7
	/varset aSlotNum[5] 8
	/varset aSlotNum[6] 9
	/varset aSlotNum[7] 10
	/varset aSlotNum[8] 11
	/varset aSlotNum[9] 12
	/varset aSlotNum[10] 13
	/varset aSlotNum[11] 14
	/varset aSlotNum[12] 16
	/varset aSlotNum[13] 18
	/varset aSlotNum[14] 19
	/varset aSlotNum[15] 20

	/echo Starting Bazaar Tribute Search...

	| Check if a ratio and price were entered when called...
	/if (${Defined[Param0]}) {
		/echo RATIO set to ${Param0}
		/varset RATIO ${Param0}
	}
	/if (${Defined[Param1]}) {
		/echo MaxPrice set to ${Param1}
		/varset MaxPrice ${Param1}
	}

	| *** Open the Bazaar window.
	/baz
	/delay 10s (${Window[BazaarSearchWnd].Open})
	/if ( !${Window[BazaarSearchWnd].Open} ) {
		/echo FATAL ERROR: Bazaar window could not be found or opened.
		/echo ABORTING...
		/endm
	}
	| *** Reset the Bazaar Search form.
	/notify BazaarSearchWnd BZR_Default leftmouseup

	| *** Key in monetary values
	/call SetTextBox BazaarSearchWnd BZR_MaxPriceInput ${MaxPrice}

	| *** Loop using Search by Slot.
	/for I 1 to 15
		/call selectSlotAndSearch ${aSlotNum[${I}]}
		
		| *** Fix for activating "Inspect Item" button.
		/notify BazaarSearchWnd BZR_ItemList leftmouseup
		
		| *** Open each item and check stats
		/for J 1 to 200
			/varset cPrice NULL
			/varset cTrib NULL

			| *** Get the price of the item
			/call getPriceAndSelect ${J}
			/varset cPrice ${Macro.Return}

			| *** If end of list, get next slot.
			/if ( ${cPrice} == NULL ) /next I

			| *** Get the tribute value, if any...
			/call getSelectedTributeValue
			/varset cTrib ${Macro.Return}

			| *** If no tribute value, get next item via looking ahead.
			/if ( ${cTrib} == NULL ) {
				/call lookAhead ${J}
				/varset J ${Macro.Return}
				/next J
			}

			| *** Check ahead for the same item, and compare, alert if good.
			/call checkAheadCompareAlert ${J} ${cPrice} ${cTrib}

			| *** Set J to the position of the last item of the "copies"
			/varset J ${Macro.Return}
                                
			/if ( ${Window[ItemDisplayWindow].Open} ) /keypress esc
		/next J
		| *** End item loop
	/next I
	| *** End Slot loop
	/echo DONE.
/return


|==============================================================================
| Returns the position of the last occurrance of the item.
Sub lookAhead(int itemNum)
	/declare lastOccur int local ${itemNum}
	/declare iName string local 
	/declare K int local

	/call getItemName ${itemNum}
	/varset iName ${Macro.Return}

	/for K 1 to 2
		/varcalc lastOccur ${lastOccur} + 1
		| Check if named the same...
		/if ( ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${lastOccur},1].Find[${iName}]} ) {
			/varset K 1
		} else {
			/varset K 2
		}
	/next K
	/varcalc lastOccur ${lastOccur} - 1
/return ${lastOccur}


|==============================================================================
| Returns the name of the item, without the (number) bit...
Sub getItemName(int itemNum)
	/declare iName string local NULL
	/declare len int local

	/varset iName ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${itemNum},1]}
	/varset len ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${itemNum},1].Find[(]}
	/varcalc len ${len} - 1
/return ${iName.Mid[1,${len}]}


|==============================================================================
| I suppose v0.1 of this was crap, it opened every item to find tribute value.
| This was slow, especially when there is usually a few of the same item for
| sale.  This just looks at the first occurrence of an item for the tribute,
| then looks ahead at the prices to find the cheapest, without re-opening an
| item window(cause of much time waste). Returns the position of the last
| occurrence.
Sub checkAheadCompareAlert(int itemNum, int tPrice, int tTrib)
	/declare lastOccur int local ${itemNum}
	/declare lowPos int local ${itemNum}
	/declare lowPrice int local ${tPrice}
	/declare iName string local
	/declare K int local

	/call getItemName ${itemNum}
	/varset iName ${Macro.Return}

	/for K 1 to 2
		/varcalc lastOccur ${lastOccur} + 1
		| Check if named the same...
		/if ( ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${lastOccur},1].Find[${iName}]} ) {
			/varset K 1
			| Get the price...
			/call getPriceAndSelect ${lastOccur}
			/if ( ${Macro.Return} < ${lowPrice} ) {
				/varset lowPrice ${Macro.Return}
				/varset lowPos ${lastOccur}
			}
		} else {
			/varset K 2
		}
	/next K
	/varcalc lastOccur ${lastOccur} - 1
	
	| Check if item meets value requirements. If good, alert and wait.
	/varcalc lowPrice ${lowPrice} * ${RATIO}
	/if ( ${lowPrice} < ${tTrib} ) {
		/call getPriceAndSelect ${lowPos}
		/call alertAndWait "${iName}"
	}
/return ${lastOccur}

|==============================================================================
| Alerts, beeps, and waits for continue text...
Sub alertAndWait(string itemName)
	/declare K int local
	/if ( ${Window[ActionsWindow].Child[AMP_EndFindButton].Open} ) {
		| end find...
		/notify ActionsWindow AMP_FindButton leftmouseup
		/delay 1
	}
	/popup GOOD ITEM FOUND: >>> ${itemName} <<<
	/notify BazaarSearchWnd BZR_FindTraderButton leftmouseup
	/for K 1 to 5
		/beep
		/delay 2
	/next K
	/popup GOOD ITEM FOUND: >>> ${itemName} <<<
	/call waitForGo
/return

|==============================================================================
| Returns the tribute value of an item.  Does this by opening its item view and
| extracting the text.
Sub getSelectedTributeValue
	/declare K int local
	/declare tTrib int local NULL
	/declare tInfo string local
	/declare tPos int local NULL
	
	/if ( ${Window[ItemDisplayWindow].Open} ) /keypress esc
	| Open the item window
	/notify BazaarSearchWnd BZR_RequestItemButton leftmouseup
	/delay 6s (${Window[ItemDisplayWindow].Open})
	/if (!${Window[ItemDisplayWindow].Open}) {
		/varset forSale TRUE
		/doevents
		/if ( ${forSale} ) {
			/echo BAD ITEM...
			/return ${tTrib}
		}
	}
	| Get the text, check for tribute...
	/varset tInfo ${Window[ItemDisplayWindow].Child[IDW_ItemDescription].Text}
	/varset tPos ${tInfo.Find[<BR>Tribute Value:]}
	/if ( ${tPos} == NULL ) {
		/return ${tTrib}
	}

	| Parse the tribute value
	/varcalc tPos ${tPos} + 19
	/varset tTrib 0
	/for K ${tPos} to 10000
		/if ( ${tInfo.Mid[${K},1].Compare[<]} != 0 ) {
			/varcalc tTrib ${tTrib} * 10
			/varcalc tTrib ${tTrib} + ${tInfo.Mid[${K},1]}
		} else {
			/varset K 10000
		}
	/next K
/return ${tTrib}


|==============================================================================
| Gets the price of an item in the bazaar search list, also selects it in list.
Sub getPriceAndSelect(int itemNum)
	/declare tPrice int local NULL
	/notify BazaarSearchWnd BZR_ItemList listselect ${itemNum}
	/delay 1
	/varset tPrice ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${itemNum},2]}
/return ${tPrice}


|==============================================================================
| Selects the Item Slot and does search.  Waits Max 10s for results.
Sub selectSlotAndSearch(int slotNum)
	/declare gotText string local
	/declare count int local 0
	/declare tt int local NULL
	/notify BazaarSearchWnd BZR_ItemSlotCombobox listselect ${slotNum}
	/notify BazaarSearchWnd BZR_QueryButton leftmouseup
    :WAIT_RESULT
	/delay 5
	/varset gotText ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[1,1]}
	/varset tt ${gotText.Find[(]}
	/if ( ${tt} != NULL ) /goto :WAIT_END
	/varcalc count ${count} + 1
	/if ( ${count} > 20 ) {
		/echo ALERT: There doesn't seem to be anything to look at from the search...
		/return
	}
	/goto :WAIT_RESULT
    :WAIT_END
	/delay 5
/return


|==============================================================================
| This waits for the user to buy the found item, user then keys a phrase,
| and search restarts.
Sub waitForGo
	/varset reStartFlag FALSE
    :WAIT
	/doevents
	/if ( ${reStartFlag} ) /return
	/delay 1s
    /goto :WAIT
/return


|==============================================================================
|This is the event handler for when the user has keyed the restart phrase
Sub Event_gogogo
	/varset reStartFlag TRUE
/return


|==============================================================================
|This is the event handler for when the item is no longer for sale
Sub Event_notForSale
	/varset forSale FALSE
/return


|==============================================================================
| This sets the text in a text box control.  Does not affect sliders. There is
| different code for that.
Sub SetTextBox(string Wnd, string Ctrl, string Inp)
	/declare I int local

	| Clear the text box
	/notify ${Wnd} ${Ctrl} leftmouseup
	/for I 1 to 2
		/notify ${Wnd} ${Ctrl} leftmouseup
		/if ( ${Window[${Wnd}].Child[${Ctrl}].Text.Length} > 0 ) {
            		/keypress backspace chat 
			/varset I 1
		} else {
			/varset I 2
		}
	/next I
	
	| Fill the box...
	/for I 1 to ${Inp.Length}
		/keypress ${Inp.Mid[${I},1]} chat
	/next I
/return

|===========================================================================end
HAVE FUN!!! oh, click of lev, U know how it stuffs up find =P

Posted: Sat May 26, 2007 3:31 am
by dont_know_at_all
Some item names have parens in them...

Parens... So?

Posted: Sat May 26, 2007 6:49 am
by zoobish
So... they have parens... Im only using them to cut off the (3) bit at end of name to compare to next item. If item is called: My Dodgy (but good) Weapon(1), Im gonna do a Find on the next item for My Dodgy, it will still find it.

I doubt there would be many cases of:

1) A Big (dull) Sword(1)
2) A Big (fine) Fish Scale(3)

So I am not too fussed if items have parens in them... won't cause a problem as they are rare spawns...

I'm more interested now in seeing how modules are made. Im wondering if its possible to find the loc "nodes" of the gold FIND path. If it is, it should be easy to make something that will follow the path, or at least make the "nodes" available when making a script...

Im thinkin they are buried somewhere in memory, doubt the server keeps em, client still needs to know about them to make the pretty graphics... Time to look at dumps again...

Oh...

Code: Select all

Sub  getItemName(int itemNum)
	/declare iName string local NULL
	/declare len int local
	/declare K int local	

	/varset iName ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${itemNum},1]}
	/varcalc len ${iName.Length} - 2
	
	/for K ${len} downto 1
		/if ( ${iName.Mid[${K},1].Equal[(]} ) {
			/varcalc K ${K} - 1
			/return ${iName.Mid[1,${K}]}
		}
	/next K
	/varcalc len ${len} - 1
/return ${iName.Mid[1,${len}]}
:lol:

Posted: Sun May 27, 2007 4:59 am
by A_Enchanter_00
Prevent looking up lore items, if you already have one

Code: Select all

Sub checkAheadCompareAlert(int itemNum, int tPrice, int tTrib)
   /declare lastOccur int local ${itemNum}
   /declare lowPos int local ${itemNum}
   /declare lowPrice int local ${tPrice}
   /declare iName string local
   /declare K int local

   /call getItemName ${itemNum}
   /varset iName ${Macro.Return}

   /for K 1 to 2
      /varcalc lastOccur ${lastOccur} + 1
      | Check if named the same...
      /if ( ${Window[BazaarSearchWnd].Child[BZR_ItemList].List[${lastOccur},1].Find[${iName}]} ) {
         /varset K 1
         | Get the price...
         /call getPriceAndSelect ${lastOccur}
         /if ( ${Macro.Return} < ${lowPrice} ) {
            /varset lowPrice ${Macro.Return}
            /varset lowPos ${lastOccur}
         }
      } else {
         /varset K 2
      }
   /next K
   /varcalc lastOccur ${lastOccur} - 1
   
   | Check if item meets value requirements. If good, alert and wait.
   /varcalc lowPrice ${lowPrice} * ${RATIO}
   /if ( ${lowPrice} < ${tTrib} ) {
	/if ( ( !${FindItem[=${iName}].ID} || ( ${FindItem[=${iName}].ID} && !${FindItem[=${iName}].Lore} ) ) && ( !${FindItemBank[=${iName}].ID} || ( ${FindItemBank[=${iName}].ID} && !${FindItemBank[=${iName}].Lore} ) ) ) {
	      /call getPriceAndSelect ${lowPos}
	      /call alertAndWait "${iName}"
	}
   }
/return ${lastOccur}

Posted: Mon May 28, 2007 4:51 am
by zoobish
Good deal. Had thought about that, but ive never come across a good tribute item that I already had, lol, it would have been tributed...

But its good to be ready for that, maybe reporting that a good item was found but it was already somewhere(inv, bank, etc) would be good. lol, the crap that lies around sometimes =)

Automate...

Posted: Thu May 31, 2007 6:02 am
by zoobish
hmmm, hmmmmm... Was just chattin with A_Enchanter_00 about his advPath plugin... Then I had thoughts...

So based on my thoughts, I am going to automate this further =) set, forget =) hee hee, it will run round the bazaar and BUY the items, hahahaha. Then, if you have Origin, it will activate it, so yah can run to tribute dude and sell, hahaha yeah =P

Stay tuned... Startin work now.

yeah yeah yeah

Posted: Thu May 31, 2007 10:18 am
by zoobish
Ha ha, I have made my own loc recorder:

Code: Select all

| recordloc.mac

#turbo

#event setLoc "#*#set new loc#*#"
#event endIt "#*#end it now#*#"
#event newSection "#*#set section to <#1#>#*#"



Sub main
	/if ( !${Defined[Param0]} ) {
		/echo RECORDLOC.MAC: ALERT - you must supply a file name to record to.
		/endmacro
	}
	/declare fileName string outer d:\mq2\Macros\tribute.locs
	/declare count int outer 0
	/declare currSection string outer ${Param0}
	
	/echo RECORDLOC.MAC: starting record mode.  Saving to ${fileName}, in ${currSection}.

  :LOOP
	/doevents
  	/delay 1
  /goto :LOOP


/return

Sub Event_setLoc
	/declare msg string local
	/varcalc count ${count} + 1
	/varset msg ${Me.Y} ${Me.X}
	/echo ${count}=${msg}
	/ini ${fileName} ${currSection} ${count} "${msg}"
/return

Sub Event_endIt
	/echo RECORDLOC.MAC: saved ${count} locs in ${fileName}
	/endmacro
/return

Sub Event_newSection(string Line, string sect)
	/varset currSection ${sect}
	/varset count 0
	/echo RECORDLOC.MAC: changed section - ${currSection}
/return
This baby made me a file I can retrieve locs from, neat =P

I recorded paths to all the rooms... Smoked a few bongs... Still capable of decent code... OMG.. I must be a real programmer :evil:

I can now also determine which room the merchant is in, and travel there...

I have the next bit logiked out in my head, finding which secton of the room the merchant is in.. haha, good ole LineOfSight...

Gettin tired tho =( got work tomorrow.. hmm... 12:20am, Friday morn in Australia.. maybe nother hour or 2 it be done =) if not, tomorrow...

Posted: Fri Jun 15, 2007 9:59 am
by cheater
Can you set a min price also? like if you are too lazy to fill a backpack with items costing 10 pp and worth 300 tribute, but prefer running a few more costly items

Posted: Fri Jun 15, 2007 11:09 pm
by Fatal
I'm looking for the minimum price also, please.

Posted: Sat Jun 16, 2007 12:54 pm
by KungFuHamster
I wouldn't advise running around on auto in the bazaar unless you have a REALLY humanistic navigation routine. I saw some mq'er running through the bazaar once and it was painfully obvious it was on rails.

Posted: Thu Jun 21, 2007 6:27 am
by zoobish
bah, fatal, and too true KFH...

use the follow route =P

I use the concurrent auto one =P

make one yourself!!! all the code is there.

Posted: Wed Jul 18, 2007 12:10 pm
by anon_coward
Question for you zoobish. Can I use part of your bazaar search code to write a FindUpgrade macro?

I plan to add code to add an INI file with values for how much each stat is worth to me then compare the search results with what I have equiped and then factor in price. It should be pretty easy to extend your code instead of reinventing it all.

OPEN SOURCE

Posted: Fri Jul 27, 2007 6:31 pm
by zoobish
YEAH,

Use all, or part of my code.

Just stick in a comment somewhere like this:

Code: Select all

| Code reused from soandso.mac by zoobish
or

Code: Select all

|**********************************************|
|**                                          **|
|**    SOME OF THIS CODE WAS COPIED FROM     **|
|**              soandso.mac                 **|
|**                   by                     **|
|**                 ZOOBISH                  **|
|**                                          **|
|**********************************************|
YEAH!!

Too easy :roll:

Crash

Posted: Sun Feb 15, 2009 5:45 pm
by Manual
Hey, This works untill it comes to a piece of Defiant armor, then it crashes EQ...

I tried looking at the armor in question with MQ running and no macro and had no problems.

Posted: Sun Feb 15, 2009 6:25 pm
by fearless