Warrior Group Clickies

Have a macro idea but not sure where to start? Ask here.

Moderator: MacroQuest Developers

Krs01
orc pawn
orc pawn
Posts: 27
Joined: Tue May 18, 2004 7:30 pm
Location: Seattle

Warrior Group Clickies

Post by Krs01 » Wed May 19, 2004 10:45 pm

Looking for a macro i could use in a group that would target each group member .. Shrink them x 2 with a clicky item .. cast see inv on them and give them my health buff ... and a strength buff...

Cobalt Bracer - Shrink x 2
Bracer of the Hidden - See invis
Cobalt Gauntlets - Strength
Kizrak's Greaves of Battle - Health

would be a nice macro for the start of a LDON or such ... cast it take your quick afk and come back... Thanks in advance

yesman
a lesser mummy
a lesser mummy
Posts: 64
Joined: Tue Apr 27, 2004 9:06 pm

Post by yesman » Wed May 19, 2004 11:11 pm

Wow do a search...I will help you this time...

http://macroquest2.com/phpBB2/viewtopic.php?t=7238

Krs01
orc pawn
orc pawn
Posts: 27
Joined: Tue May 18, 2004 7:30 pm
Location: Seattle

Post by Krs01 » Wed May 19, 2004 11:31 pm

I saw that post, I was looking for 1 that would auto equip each item and cast it on each group member... if you know how that macro could be setup to do so it would be nice... but F2 /mac swapcast "item" F3 /mac swapcast "item" .. for alot of items wouldnt allow a afk .. taking 10 seconds per click on legs x 6 and 15 seconds per x2 shrink x6 + others = a decent afk time and your actually doing something during this

yesman
a lesser mummy
a lesser mummy
Posts: 64
Joined: Tue Apr 27, 2004 9:06 pm

Post by yesman » Thu May 20, 2004 2:46 pm

Code: Select all

     /if (${Group}>=1) {
      /target ${Group[1]}
     /call SwapCast "Cobalt Bracer" rwrist
     /delay 1s 
     }
     
Now you can cut and paste that all and just fill in Group[2],[3], etc. Or you can make an array out of it. Find what works best for you.

Now I don't know how you can check if someone is taller, but for the buffs with durations...

Code: Select all

/if (!${Me.Buff[See Invisible]}) /call SeeInvis
Just make a sub SeeInvis and put in the code up top, and make one to cast on you, otherwise it will loop endlessly.

That should get you started.

Krs01
orc pawn
orc pawn
Posts: 27
Joined: Tue May 18, 2004 7:30 pm
Location: Seattle

Post by Krs01 » Thu May 20, 2004 7:57 pm

well i appreciate that i put a bit together and it actually worked ! lol ty

Krs01
orc pawn
orc pawn
Posts: 27
Joined: Tue May 18, 2004 7:30 pm
Location: Seattle

Post by Krs01 » Thu May 20, 2004 8:25 pm

Well it worked for me had a few issues ... What "needs" to change to make this work and target each group member?


_________________________________

Sub Main(p0,p1)

/call SwapCast "Cobalt Bracer" "${p1}"
/call SwapCast "Cobalt Bracer" "${p1}"
/call SwapCast "Bracer of the Hidden" "${p1}"
/call SwapCast "Cobalt Gauntlets" "${p1}"
/call SwapCast "Cobalt Boots" "${p1}"
/call SwapCast "Kizrak's Greaves of Battle" "${p1}"
/call SwapCast "Shrunken" "${p1}"
/delay 3
/autoinv
/delay 3

/endmacro

Sub SwapCast(item,equipslot)
/declare inventoryslot int local
/declare pack local
/declare packslot int local
/declare leaveopen int local 1
/declare packnumber int local 0
/declare leavetwisting int local 0

/if (!${Defined[item]}) /goto :end
/if (${Twisting}) {
/twist stop
/varset leavetwisting 1
}
:stopsingingdelay
/if (${Me.Casting.ID}>0) {
/stopsong
/goto :stopsingingdelay
}
/varset inventoryslot ${FindItem[${item}].InvSlot}
/if (!${inventoryslot}) /goto :notfound
:packcountloop
/if (${inventoryslot}>250 && ${inventoryslot}<331) {
/varset packnumber ${Math.Calc[${packnumber}+1]}
/varset inventoryslot ${Math.Calc[${inventoryslot}-10]}
/goto :packcountloop
}
/if (${packnumber} > 0) {
/varset pack pack${packnumber}
/varset packslot ${Math.Calc[${inventoryslot}-240]}
/goto :foundit
}
:notinpack
/call CastItem ${inventoryslot}
/goto :end
:foundit
/if (!${Window[${pack}].Open}) {
/nomod /itemnotify ${pack} rightmouseup
/varset leaveopen 0
}
/call WaitCursor ${packslot} ${pack}
/if (${String[${equipslot}].Find[null]}) {
/if (${Cursor.WornSlots}>0) {
/varset equipslot ${Cursor.WornSlot[1]}
} else {
/varset equipslot pack1
}
}
/call WaitCursor ${equipslot}
/call CastItem ${equipslot}
/call WaitCursor ${equipslot}
/call WaitCursor ${packslot} ${pack}
/if (${leaveopen} == 0) /nomod /itemnotify ${pack} rightmouseup
/goto :end
:notfound
/echo ${item} not found in inventory.
:end
/if (${leavetwisting} == 1) /twist start
/return

Sub CastItem(slot)
/nomod /itemnotify ${slot} rightmouseup
/echo Casting the effect on your ${InvSlot[${slot}].Item.Name}
:castloop
|| special case composer greaves don't ever stop casting
/if (${InvSlot[${slot}].Item.Name.Find["Composers Greaves"]}) {
/delay 12
/stopsong
}
/if (${Me.Casting.ID}>0) /goto :castloop
/return

Sub WaitCursor(slot, pack)
/declare item local
/varset item ${Cursor.ID}
/if (${Defined[pack]}) /goto :waitloop2
:waitloop1
/nomod /itemnotify ${slot} leftmouseup
/if (${item} == ${Cursor.ID}) /goto :waitloop1
/goto :donewaiting
:waitloop2
/nomod /itemnotify in ${pack} ${slot} leftmouseup
/if (${item} == ${Cursor.ID}) /goto :waitloop2
:donewaiting
/return

_____________________


everytime that i click "code" btw here at work it does not pop up sorry /sigh

Chill
Contributing Member
Contributing Member
Posts: 435
Joined: Fri May 07, 2004 5:06 pm
Location: Erie, PA

Post by Chill » Thu May 20, 2004 10:09 pm

Okay heres a start:

Code: Select all

#include swap.inc
#include SpellCast.inc

Sub Main

/declare c int local
/echo Buffing...

   /for c 0 to ${Group}

      /target id ${Group[${c}].ID}
      /delay 2

      <CODE TO SWAP AND/OR CAST ALL YOUR GROUP BUFFS HERE>

   /next c

   /target myself
   <CODE YOUR SELF BUFFS HERE>

/endmacro
K now the stuff to cast your buffs...

If its something you wear full time, then use:

Code: Select all

/call cast "Kizrak's Greaves of Battle" item
If its something you keep bagged, then you will want to use Preocts' swapper. There are a number of ways to use it--I suggest reading her doccumentation to get the best way for you--but it might look something like:

Code: Select all

/call swap "swap:Cobalt Bracer=Kizrak's Bracer of Battle|clicky:Cobalt Bracer|swap:Kizrak's Bracer of Battle=Cobalt Bracer"
SpellCast.inc you can find posted in the snippets section.

Swap is posted in the Macro Depot as a standalone macro, but I modified very slightly to make it an include. You could probably cut the functions out and add them to your macro, but I left it as an incude to make it easier to updete. Heres what I have:

Code: Select all

|** Swap.mac Version 2. by: Preocts   Updated Last: 05/15/2004 
        As a summer project to help me learn C++ I am currently creating 
        a plugin that will completely replace this macro and more. I am 
        thinking this will eliminate the ini functions of the operation. In 
        replacement /commands will be able to be used in macros for complex 
        or multi-staged swaps. Everything is up in the air at this point 
        because I still get headaches trying to learn Pointers. ::sigh:: 
        As my knowledge of C++ increases I hope to be able to contribute 
        to the advancement of the MacroQuest project. 

Introduction: 
  A much much much evolved version of my old switch.mac that I wrote about 
  a month ago. This one is VERY flexible in what you can do. Ini or param 
  driven commands. You can also store ini commands in-game. Does not open 
  your inventory window but will open packs as needed. Resets your packs 
  after macro is done so if you had 'that' one open it will remain open. 

  I use this most heavily on my bard, allowing me to swap instruments out 
  with a push of a hotkey. Wrote in a clicky command for my rogue who always 
  seemed to lose her buff gear in her packs! ((cronic packrat)) 

  This is written to be modular and expanded. Almost all the subs handle one 
  aspect of the 'switch' so adding this to your existing macros as an include 
  should be almost painless. 

Making an Include File: (or using parts of this macro) 
  There are 7 subs below that can be pulled out of this entire macro and 
  used inside your own macros for the manipulation of items and slots. 
  The two rightclick subs will wait for any casting items to finsih before 
  releasing control back to where they were called 
     1) Sub LeftClickItem(ItemName) <------ Searches, finds, left clicks 
     2) Sub LeftClickSlot(Slot) <---------- Left clicks any slot name or num 
     3) Sub LeftClickPackSlot(Pack,Slot) <- Opens bags, then left clicks 
     4) Sub RightClickItem(ItemName) <----- For those rightclick items 
     5) Sub RightClickSlot(Slot) <--------- Same, but with slotnames 
    *6) Sub OpenPack(Pack) <--------------- Needed for 1, and 3 
    *7) Sub DisplayError(sInput) <--------- Needed for ALL the above. 
  The parameters they need are self explaining. If you want to use them just 
  copy them and the following two subs to you macro file or an include. 
  *These are standalones but required if you use 1-5 

Some important notes: 
+ If the item is stacked the ENTIRE stack is picked up. 
+ Be cool. "Enclose your commandline in quotes" 
+ Options are explicit. If it tells you [ItemName]>[SlotName/CustomName] then 
  that is what you MUST give it. IN THAT ORDER! 
+ All commands must be separated by | when entering mulitple actions. The 
  expection are IF commands. They use /. Mixing will cause problems. 
+ No command will check Cursor Status before executing. Assumed Empty! 
  This means you need to think your logic out. If move an item to your neck 
  slot and then move an item to your mainhand, be sure you did something with 
  the item that 'was' in your neck slot before you began. 
+ Clicky Commands for items inside packs are pointless and will do nothing. 
+ bouncy bouncy bouncy bouncy boun- damnit 
+ HolyShit! Did I just add IF statements? Why yes! Yes I did. 

+ VERY VERY IMPORTANT INOFRMATION: 
  The newest installment of this macro includes rewritten command handling. 
  What does this mean to you? Well, you now have no limits as to how you 
  do commands. You can call CommandSet@s from CommandSet@s, inside IFs, and 
  'nest' them as deeply as MQ2 can handle. THE MAJOR FACTOR HERE IS: 
  You now run the change of creating an infinite loop. In non-programming 
  terms this means you can cause this macro to keep running forever with no 
  end. There is an example of this at the end of the comments section. 
  (although I haven't tested it, I'm sure you still CANNOT nest ifs. Sorry) 

Commands: 

+ "Swap:[ItemName/SlotName/CustomName]=[ItemName/SlotName/CustomName]" 
   Puts the first item you give it where the second is and puts the second 
   where the first was. 

+ "MoveTo:[ItemName]>[SlotName/CustomName]" 
   Moves Item to Slot 

+ "PickUp:[ItemName/SlotName/CustomName]" 
   Places Item onto cursor (More literally, preforms a leftmouseup on []) 

+ "Clicky:[ItemName/SlotName]" 
   Rightclicks Item/Slot. Waits for Cast. 

+ "Empty" 
   Smart Empty of Cursor. Fails on full Inv. 

+ "IfOn?ItemName?TrueAction/?FalseAction/?" 
   If ItemName is on the cursor, preform TrueAction. Else, preform FalseAction 
   Ending ? is required or you risk errors. 
   Actions can contain more than one command. Divider inside Ifs is / not |. 
   Neither True or False actions are required. ?-1? will skip that action 

+ "IfIn?ItemName:SlotName?TrueAction/?FalseAction/?" 
   If ItemName is in SlotName then do TrueAction, else do FalseAction. 
   Ending ? is required or you risk errors. CANNOT CHECK INSIDE PACKS. 
   Actions can contain more than one command. Divider inside Ifs is / not |. 
   Neither True or False actions are required. ?-1? will skip that action 
    
+  "KeyName$Commands" 
    Writes Commands to KeyName in the INI file. Does not run Commands. 

Options: 
  [ItemName] are full item names only. No partial names will be found. 
  [SlotName] The following list are valid slot names: 
    mainhand offhand ranged charm leftear rightear leftwrist rightwrist arms 
    head neck face shoulder chest legs waist rightfinger leftfinger feet ammo 
    back pack1 pack2 pack3 pack4 pack5 pack6 pack7 pack8 
    (Slot Numbers will work as long as they are not located inside a pack) 
  [CustomName] may be used to identify a slot inside a pack. Format: 
    pack1!2     Slot 2 in Pack1 
    pack5!4     Slot 4 in Pack5 
    (Forces the macro to make sure that pack is open) 

Using Swap.Mac: 
  Something to always remember: Swap.Mac does not care what is on the cursor 
  when it runs a command. That's why I made Ifs. 

  /macro swap "Swap:Foraging Machette=Scimitar of the Emerald Dawn" 
    Swaps the two items between their current slots. 

  /macro swap "MoveTo:Fisherman's Companion>Pack8!3" 
    Moves Companion to pack8, slot three. Note: if anything was there it is 
    now on the cursor. 

  /macro swap "pickup:arms" 
    Leftclicks the arms slot. 

  /macro swap "Clicky:LeftEar" 
    This rightclicks your left ear piece. 

  /macro swap "Moveto:Shrunken Goblin Skull Earring>LeftEar|Clicky:LeftEar|Pickup:LeftEar|Empty" 
    Moves your SGSE to your ear slot (whatever was there in on cursor) 
    Clicks the slot, casting the self-buff 
    Picks up the SGSE(leftear) which places whatever was there back there. 
    Empty the Cursor. 

  /macro swap "EarBuff$Moveto:Shrunken Goblin Skull Earring>LeftEar|Clicky:LeftEar|Pickup:LeftEar|Empty" 
    Writes the command to ini. DOES NOT RUN COMMANDS 
    Ini would then contain: 
      EarBuff=Moveto:Shrunken Goblin Skull Earring>LeftEar|Clicky:LeftEar|Pickup:LeftEar|Empty 

  /macro swap "EarBuff@"   <------- MUST end with @ to pull from ini. 
    The same thing as: 
  /macro swap "Moveto:Shrunken Goblin Skull Earring>LeftEar|Clicky:LeftEar|Pickup:LeftEar|Empty" 

  /macro swap "IfOn?Foraging Machette?pickup:MainHand/Empty?-1?" 
    If your foraging Machette is on the cursor, place it in the MainHand 
    slot and empty cursor. 

  /macro swap "IfIn?Shrunken Goblin Skull Earring:LeftEar?clicky:LeftEar?EarBuff@? 
    If the SGKE is in the leftear click it. 
    Otherwise, do a bunch of commands to put the earring in the LeftEar 
    slot and click it. 

Rules about IFs 
  1) Thou shalt not ever nest IFs. 
  2) Thou shalt not ever use | in IFs. Thou shall use / instead. 

Ini File: 
  Default Ini Filename: Swapper.ini 

  Example: 
    [SwapCommands] 
    Drums=Swap:OffHand=Mistmoore Battle Drums| 
    Lute=Swap:OffHand=Lute| 
    Fight=PickUp:OffHand|MoveTo:Symphonic Saber>MainHand|MoveTo:Battle Drummers Main Gauche>OffHand| 
    Kite=PickUp:MainHand|MoveTo:Mistmoore Battle Drums>OffHand|Empty| 
    EarBuff=Moveto:Shrunken Goblin Skull Earring>LeftEar|Clicky:LeftEar|Pickup:LeftEar|Empty 

Examples of things you can now do: 
  [SwapCommands] 
  Wow=Drums@|Lute@|EarBuff@ 
  /macro swap "Wow@" 
  /macro swap "ifin?Mistmoore Battle Drums:offhand?Lute@?Drums@?" 

Never End Loop: (really simple "duh!" kind of example) 
  [SwapCommands] 
  Set1=bunchofcommandshere|Swap2@ 
  Set2=bunchmorecommandshere|Swap1@ 

  /macro swap Swap1@ 

  THIS WILL NEVER STOP! Set1 calls Set2 which calls Set1 again, on and on. 
**| 

#define IniFileName Swapper.ini 

Sub Swap(sInput) 
  /if (!${Defined[sInput]}) /call DisplayError "SwitchMain;No Parameter Defined" 
  /if (${sInput.Right[1].NotEqual[|]}) /varset sInput ${sInput}| 

|  /declare GlobalTimerOut timer outer 0 
  /declare nCount int local 
  /declare InvState[8] int local 

  /if (${sInput.Find[$]}) { 
    /ini "IniFileName" "SwapCommands" "${sInput.Arg[1,$]}" "${sInput.Arg[2,$]}" 
    /echo Written to IniFileName: 
    /echo ${sInput.Arg[1,$]}=${sInput.Arg[2,$]} 
    /return 
  } 

  /for nCount 1 to 8 
    /if (${Window[Pack${nCount}].Open}) { 
      /varset InvState[${nCount}] 0 
    } else { 
      /varset InvState[${nCount}] 1 
    } 
  /next nCount 

  /call Parser "${sInput}" 

  /for nCount 1 to 8 
    /if (${Window[Pack${nCount}].Open} && ${InvState[${nCount}]}) /itemnotify Pack${nCount} rightmouseup 
    /delay 1 
  /next nCount 

/return 

Sub Parser(sInput) 
  /if (!${Defined[sInput]}) /call DisplayError "Parser;No Parameter Defined" 
  /if (${sInput.Right[1].NotEqual[|]}) /varset sInput ${sInput}| 

  /declare CommandSet string local 
  /declare nCount int local 1 

  :ParserLoop 
    /if (${sInput.Arg[${nCount},|].Find[@]}) { 
      /varset CommandSet ${Ini[IniFileName,SwapCommands,${sInput.Arg[${nCount},|].Arg[1,@]},NOTFOUND]} 
      /if (${CommandSet.Equal[NOTFOUND]}) /call DisplayError "Main;Swapset ${sInput.Arg[${nCount},|].Arg[1,@]} not found" 
      /call Parser "${CommandSet}" 
    } else { 
      /call HandleCommand "${sInput.Arg[${nCount},|]}" 
    } 
    /varcalc nCount ${nCount}+1 
  /if (${sInput.Arg[${nCount},|].Length}) /goto :ParserLoop 
/return 

Sub IfCommandSet(sInput) 
|This does absolutly nothing with the commands given. It only changes 
|all the /s to |s for the main parser. 
  /if (!${Defined[sInput]}) /call DisplayError "IfCommandSet;No parameter given" 
  /if (${sInput.Equal[-1]}) /return 
  /declare nStep int local 1 
  /declare sStep string local 

  /for nStep 1 to ${sInput.Length} 
    /if (${sInput.Mid[${nStep},1].Equal[/]}) { 
      /varset sStep ${sStep}| 
    } else { 
      /varset sStep ${sStep}${sInput.Mid[${nStep},1]} 
    } 
  /next nStep 
  /call Parser "${sStep}" 
/return 

Sub HandleCommand(sInput) 
  /if (!${Defined[sInput]}) /call DisplayError "HandleCommand;No Parameter Defined 

|IfOn: IF statement directly checks the cursor.name and compares. Pulls the 
|resulting command out of sInput and parses them separetly. 
  /if (${sInput.Arg[1,?].Equal[IfOn]}) { 
    /if (${Cursor.Name.Equal[${sInput.Arg[2,?]}]}) { 
      /call IfCommandSet "${sInput.Arg[3,?]}" 
    } else { 
      /call IfCommandSet "${sInput.Arg[4,?]}" 
    } 
  } 

|IfIn: If statement checks for the presents of an item in a slot. Pulls the 
|resulting command out of sInput and parses them separetly. ITEM BEFORE SLOT 
  /if (${sInput.Arg[1,?].Equal[IfIn]}) { 
    /if (${sInput.Arg[2,?].Arg[2,:].Find[!]}) /varset ${sInput} 
    /if (${InvSlot[${sInput.Arg[2,?].Arg[2,:]}].Item.Name.Equal[${sInput.Arg[2,?].Arg[1,:]}]}) { 
      /call IfCommandSet "${sInput.Arg[3,?]}" 
    } else { 
      /call IfCommandSet "${sInput.Arg[4,?]}" 
    } 
  } 

|Swap: Most complex since both params can be any of the three types. Determine 
|what type the param is, send a leftclick command, then do the same for the 
|next param. In the end send a leftclick command to the slot used in the first 
|param. Follow? 
  /if (${sInput.Arg[1,:].Equal[Swap]}) { 
    /varset sInput ${sInput.Arg[2,:]} 
    /declare Param1 string local ${sInput.Arg[1,=]} 
    /declare Param2 string local ${sInput.Arg[2,=]} 
    /declare SlotUsed int local 
    /if (${Param1.Find[!]}) { 
      /call LeftClickPackSlot ${Param1.Arg[1,!]} ${Param1.Arg[2,!]} 
    } else { 
      /call ValidSlot ${Param1} 
      /if (${Macro.Return.Equal[true]}) { 
        /call LeftClickSlot "${Param1}" 
        /varset SlotUsed ${InvSlot[${Param1}].ID} 
      } else { 
        /call LeftClickItem "${Param1}" 
        /varset SlotUsed ${Macro.Return} 
      } 
    } 
    /if (${Param2.Find[!]}) { 
      /call LeftClickPackSlot ${Param2.Arg[1,!]} ${Param2.Arg[2,!]} 
    } else { 
      /call ValidSlot ${Param2} 
      /if (${Macro.Return.Equal[true]}) { 
        /call LeftClickSlot "${Param2}" 
      } else { 
        /call LeftClickItem "${Param2}" 
      } 
    } 
    /call LeftClickSlot ${SlotUsed} 
  } 

|MoveTo: Pickup the item and move it to the slot. Nothing is done to the 
|cursor after this point. i.e. If the slot had an item in it that item is now 
|on the cursor. 
  /if (${sInput.Arg[1,:].Equal[Moveto]}) { 
    /varset sInput ${sInput.Arg[2,:]} 
    /call LeftClickItem "${sInput.Arg[1,>]}" 
    /varset sInput ${sInput.Arg[2,>]} 
    /if (${sInput.Find[!]}) { 
      /call LeftClickPackSlot ${sInput.Arg[1,!]} ${sInput.Arg[2,!]} 
    } else { 
      /call LeftClickSlot "${sInput}" 
    } 
  } 

|PickUp: Determine whether the param given is a slot/packslot/or item then 
|send the proper leftclick command. Does not concider any items already on 
|the cursor. 
  /if (${sInput.Arg[1,:].Equal[PickUp]}) { 
    /varset sInput ${sInput.Arg[2,:]} 
    /if (${sInput.Find[!]}) { 
      /call LeftClickPackSlot ${sInput.Arg[1,!]} ${sInput.Arg[2,!]} 
    } else { 
      /call ValidSlot ${sInput} 
      /if (${Macro.Return.Equal[true]}) { 
        /call LeftClickSlot "${sInput}" 
      } else { 
        /call LeftClickItem "${sInput}" 
      } 
    } 
  } 

|Clicky: Determine whether the param given is a slot or item. Send a click 
|command to that slot/item. Very simple. 
  /if (${sInput.Arg[1,:].Equal[Clicky]}) { 
    /varset sInput ${sInput.Arg[2,:]} 
    /call ValidSlot ${sInput} 
    /if (${Macro.Return.Equal[true]}) { 
      /call RightClickSlot "${sInput}" 
    } else { 
      /call RightClickItem "${sInput}" 
    } 
  } 

|Empty: Easiest of all. Empty the cursor of any contents as long as there is 
|room for them in the inventory. Will error exit if there is not room. 
  /if (${sInput.Arg[1,:].Equal[EMPTY]}) { 
    /call Command_Empty 
  } 

| /delay 1 
/return 

| BEGIN THE GUTS OF THE MACRO ------------------------ 

Sub LeftClickItem(ItemName) 
  /if (!${Defined[ItemName]}) /call DisplayError "LeftClickItem;No Parameter" 
  /declare CC int local ${Cursor.ID} 
  /if (${Window[BigBankWnd]}) { 
    /declare ItemLoc int local ${FindItem[=${ItemName}].InvSlot.ID} 
    /if (!${ItemLoc}) { 
      /varset ItemLoc ${FindItemBank[=${ItemName}].InvSlot.ID} 
      /if (!${ItemLoc}) /call DisplayError "LeftClickItem;${ItemName} not found in inventory or bank." 
    } 
  } else { 
   /declare ItemLoc int local ${FindItem[=${ItemName}].InvSlot.ID} 
   /if (!${ItemLoc}) /call DisplayError "LeftClickItem;${ItemName} not found in inventory." 
  } 
  /if (${InvSlot[${ItemLoc}].Pack.ID}) /call OpenPack ${InvSlot[${ItemLoc}].Pack.ID} 
|Inventory Window doesn't need to be open but Packs do for /itemnotify to work 
  /shift /itemnotify ${ItemLoc} leftmouseup 
  /declare TimerOut timer local 2s 
  :LCIWait 
    /if (!${TimerOut}) /call DisplayError "LeftClickItem;Operation Timed Out" 
    /if (${Cursor.ID}==${CC}) /goto :LCIWait 
|Stay in loop until timeout or cursor change. Error exit on timeout because 
|something has gone wrong at that point. The item WAS reported in the slot 
|we DID just click. If we don't get a change in the cursor.... 
|Return ItemLoc so we can use it in a Swap call. 
|ItemLoc==SlotNumber of where we just got this item. 
/return ${ItemLoc} 

Sub LeftClickSlot(Slot) 
  /if (!${Defined[Slot]}) /call DisplayError "LeftClickSlot;No Parameter" 
  /declare CC int local ${Cursor.ID} 
  /shift /itemnotify ${Slot} leftmouseup 
  /declare TimerOut timer local 2s 
  :LCSWait 
    /if (${Cursor.ID}==${CC} && ${TimerOut}) /goto :LCSWait 
|Keep in loop until cursor changes or timeout. Don't error on timeout since 
|we can assume no cursor change meant that slot was empty or the item can't 
|go into that slot. 
/return 

Sub LeftClickPackSlot(Pack,Slot) 
  /if (!${Defined[Pack]} || !${Defined[Slot]}) /call DisplayError "LeftClickPackSlot;No Parameter" 
  /declare CC int local ${Cursor.ID} 
  /call OpenPack ${Pack} 
  /shift /itemnotify in ${Pack} ${Slot} leftmouseup 
  /declare TimerOut timer local 2s 
  :LCPSWait 
    /if (${Cursor.ID}==${CC} && ${TimerOut}) /goto :LCPSWait 
|Keep in loop until cursor changes or timeout. Don't error on timeout since 
|we can assume no cursor change meant that slot was empty or the item can't 
|go into that slot. 
/return 

Sub RightClickItem(ItemName) 
  /if (!${Defined[ItemName]}) /call DisplayError "RightClickItem;No Parameter" 
  /declare ItemLoc int local ${FindItem[=${ItemName}].InvSlot.ID} 
  /if (!${ItemLoc}) /call DisplayError "RightClickItem;Error, ${ItemName} not found in inventory." 

  /if (${InvSlot[${ItemLoc}].Pack.ID}) /return 
|If the item is inside a pack just exit. Nothing happens if you click them. 
  /itemnotify ${ItemLoc} rightmouseup 
  /delay 2 
  :WaitForCast 
    /if (${Me.Casting.ID}) /goto :WaitForCast 
|Really nothing to check beyond waiting for a spell to cast. Either something 
|happens or something doesn't. Items don't fizzle and one should hope this 
|isn't being used to cast a Crusiable of Escape where interuppts matter. 
/return 

Sub RightClickSlot(Slot) 
  /if (!${Defined[Slot]}) /call DisplayError "RightClickSlot;No Parameter" 
  /itemnotify ${Slot} rightmouseup 
  /delay 2 
  :WaitForCast 
    /if (${Me.Casting.ID}) /goto :WaitForCast  
|Yay, so easy. Slot name->Click->WaitForCast->DONE! 
/return 

Sub OpenPack(Pack) 
|Input can be string or int. 
  /if (!${Defined[Pack]}) /call DisplayError "OpenPack;No Parameter Defined" 
|Looks reduntant but makes sense. This allows either a slotname or number to be evaluated. 
  /if (!${Window[${InvSlot[${Pack}].Name}].Open}) { 
    /itemnotify ${Pack} rightmouseup 
    /declare TimerOut timer local 4s 
    :Wait1 
    /if (!${TimerOut}) /call DisplayError "OpenPack;Error Could Not open ${InvSlot[${Pack}].Name}" 
    /if (!${Window[${InvSlot[${Pack}].Name}].Open}) /goto :Wait1 
    /delay 3 
|Bags seem to take a few extra cycles to register 'open' with both MQ and EQ, hence the /delay 
  } 
/return 

Sub DisplayError(sInput) 
  /echo Warning, Error. Macro Ended in Sub ${sInput.Arg[1,;]} 
  /if (${sInput.Arg[2,;].Length}) /echo Error Message: ${sInput.Arg[2,;]} 
  /endmacro 
/return 

| END THE GUTS OF THE MACRO ------------------------ 


Sub Command_Empty 
|Rather basic. Exception is now we can make sure there is room for the item. 
  :EmptyLoop 
    /if (!${Cursor.ID}) /return 
|Better to end the macro than drop something really important. 
    /if (!${Me.FreeInventory[${Cursor.Size}]}) /call DisplayError "Command_Empty:No Inventory Space for ${Cursor.Name}." 
    /autoinventory 
  /goto :EmptyLoop 
/return  

Sub ValidSlot(SlotName) 
|Input can be string or int. 
  /if (!${Defined[SlotName]}) /call DisplayError "ValidSlot;No Parameter Defined" 
|If the slotname or number has an ID then it exists. 
  /if (${InvSlot[${SlotName}].ID}) { 
    /return TRUE 
  } else { 
    /return FALSE 
  } 
/return FALSE