khi Tradeskills - Tradeskills Macro with Ini File Support

Post your completed (working) macros here. Only for macros using MQ2Data syntax!

Moderator: MacroQuest Developers

nincom
decaying skeleton
decaying skeleton
Posts: 4
Joined: Fri Apr 22, 2005 8:00 pm

Post by nincom » Fri Apr 22, 2005 8:18 pm

I was having the same problem with this macro as a few others were, couldnt use a trade container that was in inventory. I removed a section of code that was trying to clear the trade container at the same it was trying to add components.

Save the ollowing as khits.mac

Code: Select all

|** 
    khiTS.mac 

    Author:     Kaitain Heavy Industries 
    Date:       30 Apr 04 
    Version:    2.2.2.14 

    Description: 
    Performs tradeskill combines using recipes supplied in an ini file 

    Credits: 
    Inspired by Dont_Know_At_All's Trade Skills macro - The status report idea is completely stolen from him (but rewritten by me) 
    Ini file uses the format created by Diggler (this will eventually being changed to a new format using item id's) 

    Notes: 
    * Updated to use MQ2DataVars 
    * This is a complete overhaul of the whole macro in addition changing it to work with MQ2Data and MQ2DataVars 
    * You should be able to simply rename "sub main" to "sub khiTS" if you want to use this as an included file. 
    * No longer destroys tools or components used to do combines when destroy-results is enabled. 
    * This is a BIG macro and may be slow as hell on older computers. 

   Usage: 
   #include khits.inc 
   . 
   . 
   . 
   /call Make  <recipe_name> <options> 

   Example: 
   /call Make khits bits "show-stats=0 destroy=0 abort-on-tell=0 end-on-trivial=0 silent-mode=0 stop-at-skill-level=200" 
   Ported to Inc by Draco 
**| 

| ***** Tweak this to your computer, if you get a lot of an item in the combine container, increase this number ***** | 
#define COMBINE_DELAY 4 

| ***** CHANGE THIS TO MATCH YOUR INI FILE NAME IF NECESSARY ***** | 
#define INIPATH "recipes.ini" 


#event SkillTrivial "You can no longer advance your skill from making this item#*#" 
#event SkillUp "You have become better at #1#! (#2#)" 
#event SkillFailure "You lacked the skills#*#" 
#event SkillSuccess "You have fashioned the items together to create something new#*#" 
#event FullInventory "There was no place to put that#*#" 
#event CombineError "You cannot combine these items in this container type!" 
#event HandsFull   "You cannot combine items when your hands are full#*#" 

#chat tell 

#define COMBINE_SUCCESS         0 
#define COMBINE_FAILED         1 
#define COMBINE_ERROR         2 
#define COMBINE_INVENTORY_FULL   3 
#define COMBINE_TRIVIAL         4 

#include utils.inc 

| Main entry point 
sub Main 
    /echo 
    /echo ***************************************** 
    /echo khiTs: Tradeskills running : ${Time} 
    /echo ***************************************** 
    /echo 


    | Check for no parameters or help 
    /if (!${Defined[Param0]} || ${Param0.Equal[HELP]}) { 
        /call displayHelp 
        /call clearCursor ${iDestroyResults} 
        /endmacro 
    } 
    
    | container in which the recipe will be made 
    /declare containerName      string  local   NOT_SET 
    
    | The name of the current component we're getting 
    /declare currentComp        string  local   NOT_SET 
    
    | Make sure we have that recipe in the ini file 
    /declare recipeCheck        string  local   NOT_SET 

    | Settings (see end of this file for list of settings) 
    | Stops the macro if someone sends you a tell 
    /declare abortOnTell        int     local   0 
    
    | How many itmes the user has requested be made 
    /declare makeThisMany       int     local   0 
    
    | Display when you succed, get skillups, fail, etc. 
    /declare showStats          int     local   0 

    | For looping through containers 
    /declare slotNumber         int     local   1 
    

   | Exit and Return Flags added by Draco 
   /declare combineResult int outer 0 
   /declare cleanUpAndExit int outer 0 
   /declare combineErrorCounter int outer 0 

    | Only declare outer variables once, this is in case you use this as an include    
   /if (!${Defined[components]}) { 
        | Array of components used to make the recipe 
        /declare components[10]     string  outer 
        
       | The name of the combination being done, this is used to look up the recipe in the recipe.ini file 
       /declare recipeName         string  outer 
        
        | Container in which the recipe will be made 
        /declare containerNum       string  outer   NOT_SET 
        
        | The number of components in the recipe 
        /declare iCompCount         int     outer   0 

        | Flags 
        /declare bCombineDone       bool    outer   FALSE 
        /declare bSkillTrivial      bool    outer   FALSE 

        | Destroys the results of a combine (but not any items used in the combine) 
        /declare iDestroyResults     int     outer   0 

        | Stops the macro when you can no longer get skillups from doing the combine 
        /declare iEndOnTrivial       int     outer   0 

        | How many times you've tried a combination 
        /declare iSkillAttempts      int     outer   0 
        
        | How many times it worked 
        /declare iSkillSuccess       int     outer   0 
        
        | How many times it didn't work 
        /declare iSkillFailure       int     outer   0 
        
        | How many skill points you have received 
        /declare iSkillUps           int     outer   0 
        
        | Skill level to stop at 
        /declare iStopAtSkillLevel    int     outer    0 

       | Keeps MQ window spam to a minimum 
       /declare silentMode          int     outer   0 
        
       | Output debugging information 
       /declare debug             int   outer    0 
        
       | Flag to close tradeskill container when finished 
       /declare iCloseContainer    int   outer    1 
        
        | The results of what we are making 
        /declare sResults           string  outer 
        
        | Skill we are using (i.e. Brewing, Smithing, etc) 
        /declare sUsing            string   outer   NOT_SET 
    } else { 
        | Clean out the last components used, this is in case we have not cleared the variables or are using this as an include 
        /deletevar components 
        /declare components[10] 
    } 


    |Get requested recipe's name 
    /varset recipeName ${Param0} 

    | If there is only one parameter, then there are no options 
    /if (${Defined[Param1]}) { 
       /declare tmp int local 
       /declare parms int local ${Macro.Params} 
       /declare parmString string local 
       /varcalc parms ${parms}-1 
      
      /for tmp 1 to ${parms} 
         /varset parmString ${parmString} ${Param${tmp}} 
      /next tmp 
      
        /call parseArguments "abort-on-tell" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset abortOnTell ${Macro.Return} 
       } 

        /call parseArguments "destroy-results" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset iDestroyResults ${Macro.Return} 
       } 

        /call parseArguments "end-on-trivial" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset iEndOnTrivial ${Macro.Return} 
       } 

        /call parseArguments "make-this-many" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset makeThisMany ${Macro.Return} 
       } 

        /call parseArguments "show-stats" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset showStats ${Macro.Return} 
       } 

        /call parseArguments "stop-at-skill-level" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset iStopAtSkillLevel ${Macro.Return} 
       } 
        
        /call parseArguments "close-container" "${parmString}" 
        
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset iCloseContainer ${Macro.Return} 
       } 
        
        /call parseArguments "debug" "${parmString}" 
        /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
           /varset debug ${Macro.Return} 
       } 

        /if (!${debug}) { 
           /call parseArguments "silent-mode" "${parmString}" 
           /if (${Macro.Return.NotEqual[__NOT_FOUND__]}) { 
              /varset silentMode ${Macro.Return} 
          } 
       } else { 
          /echo ***** DEBUGGING ON ***** 
       } 
    } 

    | Make sure the recipe file exists (the recipes thing is a fix for a bug in the Ini function) 
    /varset recipeCheck ${Ini[INIPATH,recipes]} 
    /if (${recipeCheck.Equal[NULL]}) { 
        /echo khiTS Error: Recipe file not found 
        /echo Path = INIPATH 
        /goto :khiTSreset 
    } 

    | Make sure this recipe exists in the recipe.ini file 
    /varset recipeCheck ${Ini[INIPATH,${recipeName}]} 
    /if (${recipeCheck.Equal[NULL]}) { 
        /echo khiTS Error: Recipe not found 
        /echo Recipe name = ${recipeName} 
        /goto :khiTSreset 
    } 

    | Get the container name 
    /varset containerName ${Ini[INIPATH,${recipeName},Cont]} 
    /if (${containerName.Equal[NULL]}) { 
        /echo khiTS Error: Error in ini file for this recipe, no container is specified 
        /echo khiTS      : Recipe = ${RecipeName} 
        /goto :khiTSreset 
    } 
    
    | Get the skill we are using 
    /varset sUsing ${Ini[INIPATH,${recipeName},Skill]} 
    /if (${sUsing.Equal[NULL]})   /varset sUsing NOT_SET 

    | Get the item we are making 
    /varset sResults ${Ini[INIPATH,${recipeName},LongName]} 
    /if (${sResults.Equal[NULL]})   /varset sResults ${recipeName} 

    | Find the combine container number 
    /if (${containerName.Equal[Enviro]}) { 
        /if (!${Window[Enviro].Open}) { 
            /echo khiTS Error: You must have the enviromental container open to begin 
            /goto :khiTSreset 
        } 
        /varset containerNum e 
    } else { 
        | Not an enviromental container so find the container's pack number, this is how we will refer to it from now on 
        /varset containerNum ${FindItem[=${containerName}].InvSlot.ID} 
        /if (${containerNum}) { 
            /varcalc containerNum ${containerNum}-21 
            /varset containerNum ${containerNum.Arg[0,.]} 
        } else { 
            | Didn't find the container 
            /echo khiTS Error: Could not find container in your inventory 
            /echo khiTS      : Contanier name = ${containerName} 
            /goto :khiTSreset 
        } 
    } 
    
    | Read the ingredients for the recipe from the ini file        
    :khiTSReadComponentsLoop 
    /varset currentComp ${Ini[INIPATH,${recipeName},Comp${iCompCount}]} 
   /if (${currentComp.NotEqual[NULL]}) { 
        /varcalc iCompCount ${iCompCount}+1 
        /varset components[${iCompCount}] ${currentComp} 
        /goto :khiTSReadComponentsLoop 
    } 

    /call OpenPacks 

    | Remove anything from the cursor if needed 
    /call clearCursor ${iDestroyResults} 

    | Clear the combine pack 
    /call cleanPack ${containerNum} 
    /if (${cleanUpAndExit})   /goto :khiTSreset 

   | Let's just do this here rather than through every iteration of combines 
   /declare MAIN_CONTAINER string local 
    /if (${containerNum.Equal[e]}) { 
        /varset MAIN_CONTAINER enviro 
    } else { 
        /varset MAIN_CONTAINER pack${containerNum} 
    } 
    
    
    :khiTSCombineLoop 
        | Delete or Save items depending on settings 
        /call clearCursor ${iDestroyResults} 

      /if (!${silentMode})   /echo khiTS: Making ${sResults} - Count = ${iSkillSuccess} 

        | Move ingredients to container 
        /call addComponents 
        /if (${cleanUpAndExit})   /goto :khiTSCleanUpMacro 

        | Combine 
        /varset bCombineDone FALSE 
        /varcalc iSkillAttempts ${iSkillAttempts}+1 
        
        :DoCombineLoop 
        /combine ${MAIN_CONTAINER} 

        | Need this delay here to make sure the combine is finished 
        /delay COMBINE_DELAY 

        | Call these events individually so they do not conflict with a parent macro if this macro is used as an included file 
        /doevents SkillTrivial 
        /doevents SkillUp 
        /doevents SkillFailure 
        /doevents SkillSuccess 
        /doevents CombineError 
        /doevents FullInventory 
        /doevents tell 
        /doevents HandsFull 
      
         /if (${cleanUpAndExit})   /goto :khiTSCleanUpMacro 
        /if (!${bCombineDone})   /goto :DoCombineLoop 

        /varset combineErrorCounter 0 

        | See if we have made enough 
        /if (${makeThisMany} && ${makeThisMany} == ${iSkillSuccess})   /goto :khiTSCleanUpMacro 

        /goto :khiTSCombineLoop 

    | The macro is ending, clean up 
    :khiTSCleanUpMacro 
      | Delete or Save items depending on settings - Just in case 
      /call clearCursor ${iDestroyResults} 
      /call cleanPack ${containerNum} 
      /call DisplayStats 
      
    :khiTSreset 
      /if (${iCloseContainer})   /notify ContainerWindow DoneButton leftmouseup 
      /call resetKhits 

/return ${combineResult} 


Sub resetKhits 
   /deletevar combineResult 
   /deletevar cleanUpAndExit 
   /deletevar combineErrorCounter 
   /deletevar containerNum 
   /deletevar iCompCount 
   /deletevar bCombineDone 
   /deletevar bSkillTrivial 
   /deletevar iDestroyResults 
   /deletevar iEndOnTrivial 
   /deletevar iSkillAttempts 
   /deletevar iSkillSuccess 
   /deletevar iSkillFailure 
   /deletevar iSkillUps 
   /deletevar sResults 
   /deletevar components 
   /deletevar iStopAtSkillLevel 
   /deletevar recipeName 
   /deletevar iCloseContainer 
/return 



sub clearCursor(int DestroyResults) 
   /declare saveCount int local 

    :khiTSClearCursorLoop 
    /delay 2 ${Cursor.ID} 

    | Is there anything on the cursor? 
    /if (${Cursor.ID}) { 
        /if (${DestroyResults}) { 
            | Make sure the item on the cursor is not something we want to save 
            /for saveCount 1 to 10 
                /if (${components[${saveCount}].Equal[${Cursor.Name}]}) { 
                   /if (!${silentMode})   /echo -- Saving ${components[${saveCount}]} to inventory 
                    /autoinv 
                    /goto :khiTSClearCursorLoop 
                } 
            /next saveCount 

            | Whatever is on the cursor wasn't in the save list 
            /if (!${silentMode})   /echo -- Destroying ${Cursor.Name} 
            /destroy 
        } else { 
            /autoinv 
        } 

        /goto :khiTSClearCursorLoop 
    } 
/return 



Sub DisplayStats 
    /echo 
    /echo khiTS: Stat display 
    /echo ================================ 
    /echo Attempts: ${iSkillAttempts} 
    /echo Successes: ${iSkillSuccess} 
    /echo Faliures: ${iSkillFailure} 
    /echo Skill Ups: ${iSkillUps} 

    /if (${Me.Skill[${sUsing}]}) { 
       /echo Skill Level: ${Me.Skill[${sUsing}]} 
    } else { 
       /echo Skill Level: Unknown 
    } 
/return 



Sub Event_Chat(string type, string sender, string text) 
    /if (${String[${abt}].Equal[TRUE]} && ${type.Equal[tell]} ) { 
        /echo khiTS Event_Chat: Got a tell, pausing. 
        /if (!${Defined[pauseTimer]}) /declare pauseTimer timer outer 
        /varset pauseTimer 600 
      :TellPause 
         /if (${Spawn[gm]}) { 
           /if (!${Me.Sitting})   /docommand /sit 
           /docommand /camp desktop 
           /call mqout "GM in Zone! Logging out" 
           /endmacro 
         } 

        /if (${pauseTimer<1}) /return 
        /goto :TellPause 
        /mqpause 
    } 
/return 



Sub Event_HandsFull 
   /echo khiTS Event_HandsFull Error: Unrecoverable error, ending macro 
   /endmacro 
/return 



Sub Event_CombineError 
    /varcalc combineErrorCounter ${combineErrorCounter}+1 
    /if (!${silentMode})   /echo khiTS Event_CombineError: ${combineErrorCounter} 

    /endmacro 
    
    | *** FIXME *** | 
    /if (${combineErrorCounter} < 3) { 
       /call cleanPack ${containerNum} 
       /call clearCursor ${iDestroyResults} 
       /varset bCombineDone TRUE 
   } else { 
       /varset combineResult COMBINE_ERROR 
       /varset cleanUpAndExit 1 
   } 
/return 



Sub Event_FullInventory 
    /echo khiTS Event_FullInventory Error: Your inventory is full, ending macro. 
    /call DisplayStats 
    /varset combineResult COMBINE_INVENTORY_FULL 
    /varset cleanUpAndExit 1 
/return 



Sub Event_SkillFailure 
    /varcalc iSkillFailure ${iSkillFailure}+1 
    /varset bCombineDone TRUE 
    /varset combineResult COMBINE_FAILED 
/return 



Sub Event_SkillSuccess 
    /if (${sResults.Equal[${recipeName}]}) { 
       /declare MaxWaitCount timer local 100 
       :WaitForIt 
       /delay 2 ${Cursor.ID} 
       /if (!${Cursor.ID} && !${MaxWaitCount} == 0)   /goto :WaitForIt 
       /varset sResults ${Cursor.Name} 
    } 

    /varcalc iSkillSuccess ${iSkillSuccess}+1 
    /varset bCombineDone TRUE 
    /varset combineResult COMBINE_SUCCESS 
/return 



Sub Event_SkillUp 
   /varset sUsing ${Param1} 
    /varcalc iSkillUps ${iSkillUps}+1 

    /if (${iStopAtSkillLevel} && ${iStopAtSkillLevel} == ${Param2}) { 
        /call DisplayStats 
        /call cleanPack ${containerNum} 
        /call clearCursor ${iDestroyResults} 
        /varset cleanUpAndExit 1 
    } 
/return 



Sub Event_SkillTrivial 
    /if (!${bSkillTrivial}) { 
        /echo khiTS Event_SkillTrivial: Skill is trivial 
        /varset bSkillTrivial TRUE 
    } 

    /if (${iEndOnTrivial}) { 
        /call DisplayStats 
        /call cleanPack ${containerNum} 
        /call clearCursor ${iDestroyResults} 
        /varset cleanUpAndExit 1 
    } 

    /varset combineResult COMBINE_TRIVIAL 
/return 



sub cleanPack(string PackNumber) 
    /if (!${silentMode})   /echo khiTS cleanPack: Cleaning out pack: ${PackNumber} 
    
    | Used for looping through pack slots 
    /declare iSlot      int local 
    
    | How many freeslots are in the bag 
    /declare iCount     int local 

    /if (${PackNumber.Equal[e]}) { 
       /if (!${silentMode})    /echo khiTs cleanPack: Clearing enviro 

        /for iSlot 1 to 10 
           /if (${InvSlot[enviro${iSlot}].Item.ID}) { 
               /shiftkey /itemnotify enviro${iSlot} leftmouseup 
               /call clearCursor ${iDestroyResults} 
           } 
        /next iSlot 
    } else { 
      /if (!${silentMode})   /echo khiTs cleanPack: Cleaning out ${PackNumber} 
        | Can't empty a non-pack duh! 
        /if (!${Me.Inventory[Pack${PackNumber}].Container}) { 
            /echo khiTs cleanPack Error: No pack in slot 
            /varset cleanUpAndExit 1 
            /return 
        } 

        /for iSlot 1 to ${Me.Inventory[Pack${PackNumber}].Container} 
            | Quit if the pack is empty 
            /if (!${Me.Inventory[Pack${PackNumber}].Container})   /return 

            /if (${debug})   /echo khiTs cleanPack: Clearing Pack: Pack${PackNumber}, Slot:${iSlot}, Item: ${Me.Inventory[Pack${PackNumber}].Item[${iSlot}]} 

            /if (${Me.Inventory[Pack${PackNumber}].Item[${iSlot}].ID}) { 
                /varset iCount ${Me.Inventory[Pack${PackNumber}].Items} 

                /shiftkey /itemnotify in pack${PackNumber} ${iSlot} leftmouseup 
                /call clearCursor ${iDestroyResults} 

                | Make sure we aren't just putting it back in the same bag 
                /if (${Me.Inventory[Pack${PackNumber}].Items} == ${iCount}) { 
                    /echo khiTs cleanPack Error: Unable to empty pack 
                    /varset cleanUpAndExit 1 
                    /return 
                } 
            } 
        /next iSlot 
    } 

    /if (!${silentMode})   /echo khiTs: Done Cleaning pack 
/return TRUE 



Sub addComponents 
    /declare newLen      int      local 
    /declare compNum    int      local 
    /declare componentId      int      local 0 
    /declare combineSlot   int      local   1 

    /for compNum 1 to ${iCompCount} 
        /if (!${silentMode})   /echo -- components[${compNum}] = ${components[${compNum}]} : Length = ${components[${compNum}].Length} 
        /if (!${components[${compNum}].Length})   /return 

        /varset componentId ${FindItem[=${components[${compNum}]}].InvSlot.ID} 
        
        /if (${String[${componentId}].NotEqual[NULL]} && ${componentId} > 0) { 
           /call addComponent ${combineSlot} ${componentId} 
        } else { 
           /echo khiTS addComponents Error: You are out of ${components[${compNum}]} 
           /varset cleanUpAndExit 1 
           /return 
        } 
    /next compNum 
/return 


Sub addComponent(int combineSlot, int packSlot) 
   /declare failCount   int      local   0 
    
   :FindEmptySlot 
   /if (${containerNum.Equal[e]}) { 
      /if (${combineSlot} > 10) { 
         /echo khiTS AddComp Error: No such slot ${combineSlot} in container 
         /varset cleanUpAndExit 1 
         /return 
      } 
   } else { 
      /if (${combineSlot} > ${Me.Inventory[pack${combineSlot}].Container}) { 
         /echo khiTS AddComp Error: No such slot ${combineSlot} in container 
         /varset cleanUpAndExit 1 
         /return 
      } 
   } 

   | See if there's anything in the slot in which we are trying to put the combine component 
   /if (${containerNum.Equal[e]}) { 
      /itemnotify in enviro ${combineSlot} leftmouseup 
    
      | Make sure the cursor is clear, otherwise something was in that slot 
      /if (${Cursor.ID}) { 
         /itemnotify in enviro ${combineSlot} leftmouseup 
         /varcalc combineSlot ${combineSlot}+1 
         /goto :FindEmptySlot 
      } 
   } else { 
      /if (${Me.Inventory[pack${containerNum}].Item[${combineSlot}].ID}) { 
         /varcalc combineSlot ${combineSlot}+1 
         /varset combineSlot ${String[${combineSlot}].Arg[0,.]} 
         /goto :FindEmptySlot 
      } 
   } 

   :PickUpItem 
   | Slot is empty, so go ahead and put item into it 
   /ctrlkey /itemnotify ${packSlot} leftmouseup 

   |Check to see if cursor has multiple a stack. 
   /if (${Cursor.Stack} > 1 && ${failCount} < 3) { 
      /autoinv 
      /varcalc failCount ${failCount}+1 
      /goto :PickUpItem 
   } 

   /if (${containerNum.Equal[e]}) { 
      /itemnotify in enviro ${combineSlot} leftmouseup 
   } else { 
      /itemnotify in pack${containerNum} ${combineSlot} leftmouseup 
   } 
/return 


sub displayHelp 
    /echo Syntax:   /macro khiTS "<recipe name>" "<options>" 
    /echo Example:  /macro khiTS "bits" "show-stats=0 destroy=0 abort-on-tell=0 end-on-trivial=0" 
    /echo - 
    /echo MAKE SURE THAT 
    /echo * Recipe.ini is in your macro folder, or INIPATH points to your recipe.ini file 
    /echo * Inventory is open. 
    /echo * All your containers are open. 
    /echo * Nothing crosses over each other, all windows (bags, inventory, buttons) must be free. 
    /echo * Your windos positions are saved (by closing them and opening them again after they have been moved). 
    /echo - 
    /echo Options: 
    /echo -------- 
    /echo * show-stats 
    /echo -- Syntax: show-stats=1|0 
    /echo -- Example: show-stats=0 
    /echo -- Shows combine statistics. 
    /echo -- Set to 1 for show showing stats, 0 to leave out the stats. 
    /echo -- Default set to 1 (show stats). 
    /echo - 
    /echo * destroy-results 
    /echo -- Syntax: destroy-results=1|0 
    /echo -- Example: destroy-results=1 
    /echo -- Tells the macro wether end-result is destroyed or kept. 
    /echo -- Set to 1 for destroying end-result, 1 to keep end-result. 
    /echo -- Default set to 0 (keep end-result). 
    /echo - 
    /echo * abort-on-tell 
    /echo -- Syntax: abort-on-tell=1|0 
    /echo -- Example: abort-on-tell=1 
    /echo -- Tell the macro wether it should /endmacro when recieving a tell. 
    /echo -- Set to 1 for ending macro on tells, 0 to ignore tells. 
    /echo -- Default set to 0 (ignore tells). 
    /echo - 
    /echo * end-on-trivial 
    /echo -- Syntax: end-on-trivial=1|0 
    /echo -- Example: end-on-trivial=1 
    /echo -- Tell the macro wether it should stop when recieving a trivial message. 
    /echo -- Set to 1 for ending macro on trivial, 0 to ignore trivial. 
    /echo -- Default set to 0 (ignore trivial). 
    /echo - 
    /echo * make-this-many 
    /echo -- Syntax: make-this-many=# 
    /echo -- Example: make-this-many=100 
    /echo -- The number of successfull combines you want made (or till no more components are available). 
    /echo -- Set to 0 for unlimited combines (or till no more components are available), or to the wanted amount. 
    /echo -- Default set to 0 (unlimited). 
    /echo - 
    /echo * stop-at-skill-level 
    /echo -- Syntax: stop-at-skill-level=### 
    /echo -- Example: stop-at-skill-level=123 
    /echo -- Tell the macro to stop when a certain skill level is reached. 
    /echo -- Default set to 0 (do not stop at any skill level) 
    /echo - 
    /echo * silent-mode 
    /echo -- Syntax: silent-mode=1|0 
    /echo -- Example: silent-mode=1 
    /echo -- Tell the macro to only output errors 
    /echo -- Default set to 0 (output everything) 
    /echo - 
    /echo * debug 
    /echo -- Syntax: debug=1|0 
    /echo -- Example: debug=1 
    /echo -- Tell the macro to only everything. This also sets silent-mode=0 
    /echo -- Default set to 0 (do not output debugging information) 
    /echo - 
    /echo * close-container 
    /echo -- Syntax: close-container=1|0 
    /echo -- Example: close-container=1 
    /echo -- Tell the macro to close the tradeskill container when finished 
    /echo -- Default set to 1 
/return 
Save the following as Utils.inc

Code: Select all

| Generic sub to wait for something 
| i.e. Cursor.ID, Merchant.Open, etc 
Sub WaitFor 
   /declare MaxWaitCount timer local 1 
   :WaitForX 
   /echo WaitFor ${Param0} (${${Param0}}) 
   /if (${String[${${Param0}}].Equal[NULL]} && ${MaxWaitCounter} > 0) { 
      /delay 1 
      /goto :WaitForX 
   } else { 
      /delay 5 
      /if (${${Param0}})   /return 1 
   } 
/return 0 


Sub OpenPacks 
   /declare slotNumber int local 

    | Open all packs if they aren't already 
    /for slotNumber 1 to 8 
        /if (!${Window[Pack${slotNumber}].Open}) { 
            /itemnotify pack${slotNumber} rightmouseup 
        } 
    /next slotNumber 
/return 


Sub OpenBanks 
   /declare slotNumber int local 

    | Open all bank packs if they aren't already 
    /for slotNumber 1 to 18 
        /if (!${Window[Bank${slotNumber}].Open}) { 
         /if (${slotNumber} < 17) { 
            /itemnotify bank${slotNumber} rightmouseup 
         } else { 
            /itemnotify sharedbank${Int[${Math.Calc[${slotNumber}-16]}]} rightmouseup 
         } 
        } 
    /next slotNumber 
/return 


Sub ClosePacks 
   /declare slotNumber int local 

    | Close all packs if they aren't already 
    /for slotNumber 1 to 8 
        /if (${Window[Pack${slotNumber}].Open}) { 
            /itemnotify pack${slotNumber} rightmouseup 
        } 
    /next slotNumber 
/return 


Sub CloseBanks 
   /declare slotNumber int local 

   | Open all bank packs if they aren't already 
   /for slotNumber 1 to 18 
      /if (${Window[bank${slotNumber}].Open}) { 
         /if (${slotNumber} < 17) { 
            /itemnotify bank${slotNumber} rightmouseup 
         } else { 
            /itemnotify sharedbank${Int[${Math.Calc[${slotNumber}-16]}]} rightmouseup 
         } 
      } 
   /next slotNumber 
/return 


| Finds the value of an argument in a parameter string 
| Use __ in place of spaces 
sub parseArguments(string sArgument, string sParameters) 
    /declare iArgNum    int     local 
    /declare sArgValue  string  local 
    
    /for iArgNum 1 to ${sParameters.Count[=]} 
       /if (${sParameters.Arg[${iArgNum}, ].Left[${sArgument.Length}].Equal[${sArgument}]}) { 
          |/declare tmp int local ${sArgument.Length} 
          |/varcalc tmp (${tmp}+1)*-1 
          |/varset sArgValue ${sParameters.Arg[${iArgNum}, ].Right[${tmp}]} 
          
          /varset sArgValue ${sParameters.Arg[${iArgNum}, ].Right[${Math.Calc[(${sArgument.Length}+1)*-1]}]} 
          
          /if (${String[${sArgValue.Find[__]}].NotEqual[NULL]}) { 
             /declare sepLoop int local 
             /declare tmpValue string local ${sArgValue} 
             /varset sArgValue 

             /for sepLoop 1 to ${Math.Calc[${tmpValue.Count[_]}+1]} 
                /if (${Math.Calc[${sepLoop}%2]}) { 
                   /varset sArgValue ${sArgValue} ${tmpValue.Token[${sepLoop},_]} 
                } 
             /next sepLoop 
          } 

          /return ${sArgValue} 
       } 
    /next iArgNum 
/return __NOT_FOUND__ 
Hopefully, this will work for you guys.

]\[E()
a lesser mummy
a lesser mummy
Posts: 48
Joined: Mon Sep 30, 2002 10:13 pm
Location: Flint Michigan
Contact:

Post by ]\[E() » Fri Apr 29, 2005 1:08 am

So is this working with containers in your 8th slot? im trying to combine but when it goes to pick out the first item it wont only pick up one... it opens the box and has 20 but dosent say 1 then hit ok for the one item to pop to cursor?


anyone got any ideas?
Thanks in advance

nincom
decaying skeleton
decaying skeleton
Posts: 4
Joined: Fri Apr 22, 2005 8:00 pm

Post by nincom » Fri Apr 29, 2005 5:19 pm

I have it working in all slots so far, you need to open the tradeskill container before turning the macro on. It does not work with the gui tradeskill interface, you have to hit the experiment button so you can see the slots in the container.

]\[E()
a lesser mummy
a lesser mummy
Posts: 48
Joined: Mon Sep 30, 2002 10:13 pm
Location: Flint Michigan
Contact:

Post by ]\[E() » Sun May 01, 2005 6:15 pm

im trying to do mage research combines.... the Elemental Grimrore is the pack that you have to do the combines in but it doesnt use the new GUI recipe book, it doesnt have a experiment mode... just streight combine...

omnislash1979
decaying skeleton
decaying skeleton
Posts: 2
Joined: Mon Jun 20, 2005 10:16 am

Post by omnislash1979 » Mon Jun 20, 2005 11:10 am

problem i am having witht he macro is i'm on dial up, so every 5 to 15 combines the macro screws up either tries to combine while i have something in my hand or puts the product into the combine container

draco
a ghoul
a ghoul
Posts: 145
Joined: Thu Jan 29, 2004 7:06 pm
Contact:

Post by draco » Mon Jun 20, 2005 8:11 pm

Increase the combine delay

Code: Select all

| ***** Tweek this to your computer, if you get a lot of an item in the combine container, increase this number 
#define COMBINE_DELAY 4 


omnislash1979
decaying skeleton
decaying skeleton
Posts: 2
Joined: Mon Jun 20, 2005 10:16 am

Post by omnislash1979 » Wed Jun 22, 2005 6:22 pm

cackle, i recommend not using this macro in pok, just seems to crash the zone if you have a combine with 5 or more items. Did this about 5 times in a row before i realized it was me doing it. word of warning :D


P.S. thanks for the tip bud, i'll tweak it to see what works and what not <3

stevec
orc pawn
orc pawn
Posts: 10
Joined: Tue Jul 20, 2004 12:58 pm

Post by stevec » Wed Jul 06, 2005 4:31 am

I use this macro a lot and it was working fine for me until they removed the TLO String. I updated my copy and did some testing with it and it now seems to work fine. Here is my updated copy if anybody wants it.

Code: Select all

|** 

khiTS.mac 

Author: Kaitain Heavy Industries 
Date: 30 Apr 04 
Version: 2.2.2.14 

Description: 
Performs tradeskill combines using recipes supplied in an ini file 

Credits: 
Inspired by Dont_Know_At_All's Trade Skills macro - The status report idea is completely stolen from him (but rewritten by me) 
Ini file uses the format created by Diggler (this will eventually being changed to a new format using item id's) 

Notes: 
* Updated to remove the TLO String
* Updated to use MQ2DataVars 
* This is a complete overhaul of the whole macro in addition changing it to work with MQ2Data and MQ2DataVars 
* You should be able to simply rename "sub main" to "sub khiTS" if you want to use this as an included file. 
* No longer destroys tools or components used to do combines when destroy-results is enabled. 
* This is a BIG macro and may be slow as hell on older computers. 

Usage: 
/macro khits <recipe_name> <options> 

Example: 
/macro khits bits "show-stats=0 destroy=0 abort-on-tell=0 end-on-trivial=0 silent-mode=0" 

**| 


#event SkillTrivial "You can no longer advance your skill from making this item" 
#event SkillUp "You have become better at" 
#event SkillFailure "You lacked the skills" 
#event SkillSuccess "You have fashioned the items together to create something new" 
#event FullInventory "There was no place to put that" 
#event CombineError "You cannot combine these items in this container type!" 
#chat tell 
#define INIPATH "recipes.ini" 

| ***** Tweek this to your computer, if you get a lot of an item in the combine container, increase this number 
#define COMBINE_DELAY 15

| Main entry point 
sub Main 
/echo 
/echo 
/echo ***************************************** 
/echo khiTs: Tradeskills running : ${Time} 
/echo ***************************************** 
/echo 


| Check for no parameters or help 
/if (${Defined[Param0]}==FALSE) { 
/call displayHelp 
/call clearCursor ${iDestroyResults} 
/endmacro 
} 

| Variable declarations 

| Recipe info 

| The name of the combination being done, this is used to look up the recipe in the recipe.ini file 
/declare recipeName string local NOT_SET 
| container in which the recipe will be made 
/declare containerName string local NOT_SET 
| Loop variable, which component we are getting the name of 
/declare iCompLoop int local 1 
| The name of the current component we're getting 
/declare currentComp string local NOT_SET 
| Make sure we have that recipe in the ini file 
/declare recipeCheck string local NOT_SET 

| Settings : "abort-on-tell=0 destroy-results=0 end-on-trivial=0 show-stats=0 silent-mode=0" 
| Stops the macro if someone sends you a tell 
/declare abortOnTell int local 0 
| How many itmes the user has requested be made 
/declare makeThisMany int local 0 
| Display when you succed, get skillups, fail, etc. 
/declare showStats int local 0 
| Keeps MQ window spam to a minimum 
/declare silentMode int local 0 

| GenPurpParms 
/declare slotNumber int local 1 
| For looping through containers 

| Only declare outer variables once, this is in case you use this as an include 
/if (${Defined[components]}==FALSE) { 
| Recipe info 

| Array of components used to make the recipe 
/declare components[10] string outer 
| Container in which the recipe will be made 
/declare containerNum string outer NOT_SET 
| The number of components in this recipe 
/declare iCompCount int outer 0 

/declare bCombineDone bool outer FALSE 
/declare bSkillTrivial bool outer FALSE 

| Settings 
| Destroys the results of a combine (but not any items used in the combine) 
/declare iDestroyResults int outer 0 

| Stops the macro when you can no longer get skillups from doing the combine 
/declare iEndOnTrivial int outer 0 

| Skillup info 
| How many times you've tried a combination 
/declare iSkillAttempts int outer 0 
| How many times it worked 
/declare iSkillSuccess int outer 0 
| How many times it didn't work 
/declare iSkillFailure int outer 0 
| How many skill points you have received 
/declare iSkillUps int outer 0 

| The results of what we are making 
/declare sResults string outer NOT_SET 

} else { 
| Clean out the last components used, this is in case we have not cleared the variables or are using this as an include 
/deletevar components 
/declare components[10] 
} 

| Read the settings 

|Get requested recipe's name 
/varset recipeName ${Param0} 

| If there is only one parameter, then there are no options 
/echo khiTS: Reading parameters 
/if (${Defined[Param1]}==TRUE) { 

/call parseArguments "abort-on-tell" "${Param1}" 
/varset abortOnTell ${Macro.Return} 

/call parseArguments "destroy-results" "${Param1}" 
/varset iDestroyResults ${Macro.Return} 

/call parseArguments "end-on-trivial" "${Param1}" 
/varset iEndOnTrivial ${Macro.Return} 

|/call parseArguments "make-this-many" "${Param1}" 
|/varset makeThisMany ${Macro.Return} 

/call parseArguments "show-stats" "${Param1}" 
/varset showStats ${Macro.Return} 

/call parseArguments "silent-mode" "${Param1}" 
/varset silentMode ${Macro.Return} 

} else { 
/echo khiTS: No additional parameters specified
| Default settings 
/varset abortOnTell 0 
/varset iDestroyResults 0 
/varset iEndOnTrivial 0 
/varset showStats 0 
/varset silentMode 0 
} 



| *** Get recipe container and ingredients 

| Make sure the recipe file exists (the recipes thing is a fix for a bug in the Ini function) 
/varset recipeCheck ${Ini[INIPATH,recipes]} 
/if (${recipeCheck.Equal[NULL]}) { 
/echo khiTS Error: Recipe file not found 
/echo Path = INIPATH\recipe.ini 
/goto :khiTSCleanUpMacro 
} 


| Make sure this recipe exists in the recipe.ini file 
/varset recipeCheck ${Ini[INIPATH,${recipeName}]} 
/if (${recipeCheck.Equal[NULL]}) { 
/echo khiTS Error: Recipe not found 
/echo Recipe name = ${recipeName} 
/goto :khiTSCleanUpMacro 
} 

| Get the container name 
/varset containerName ${Ini[INIPATH,${recipeName},Cont]} 
/if (${containerName.Equal[NULL]}) { 
/echo khiTS Error: Error in ini file for this recipe, no container is specified 
/echo Recipe name = ${RecipeName} 
/goto :khiTSCleanUpMacro 
} 

| Read the ingredients for the recipe from the ini file 
/varset iCompLoop 0 
:khiTSReadComponentsLoop 
/varset currentComp ${Ini[INIPATH,${recipeName},Comp${iCompLoop}]} 
/if (${currentComp.NotEqual[NULL]}) { 
/varcalc iCompLoop ${iCompLoop}+1 
/varset components[${iCompLoop}] ${currentComp} 
/goto :khiTSReadComponentsLoop 
} 
/varset iCompCount ${iCompLoop} 

| Find the combine container number 
/if (${containerName.Equal[Enviro]}) { 
/if (${Window[Enviro].Open}==FALSE) { 
/echo khiTS Error: You must have the enviromental container open first (${Window[Enviro].Open}) 
/goto :khiTSCleanUpMacro 
} 
/varset containerNum e 
} else { 
| Not an enviromental container so find the container's pack number, this is how we will refer to it from now on 
/varset containerNum ${FindItem[=${containerName}].InvSlot.ID} 
/if (${containerNum}) { 
/varcalc containerNum ${containerNum}-21 
/varset containerNum ${containerNum.Arg[0,.]} 
} else { 
| Didn't find the container 
/echo khiTS Error: Could not find container in your inventory (x) 
/echo Contanier name = ${containerName} 
/goto :khiTSCleanUpMacro 
} 

} 
:khiTSFoundContainerNum 


| Open inventory if not open 
/echo khiTS: Opening inventory and containers 
/if (${Window[Inventory].Open}==FALSE) { 
/windowstate inventory open 
} 

| Open all packs if they aren't already - you have to handle arranging them and you have to have "use ctrl-r-click" set properly - for now 
/for slotNumber 1 to 8 
/if (${Window[Pack${slotNumber}].Open}==FALSE) { 
/itemnotify pack${slotNumber} rightmouseup 
} 
/next slotNumber 

| Remove anything from the cursor if needed 
/call clearCursor ${iDestroyResults} 

| Clear the combine pack 
/call cleanPack ${containerNum} 

| If you can't clean out the pack - exit 
/if (${Macro.Return}==FALSE) { 
/echo khiTS Error: Unable to clean out pack (${containerNum}) 
/return 
} 

:khiTSCombineLoop 
|/echo combine loop 
| Delete or Save items depending on settings 
/call clearCursor ${iDestroyResults} 

/if (${sResults.Equal[NOT_SET]}) { 
/echo khiTS: Making ${recipeName} 
} else { 
/echo khiTS: Making ${sResults} - Count = ${FindItemCount[${sResults}]} 
} 


| Move ingredients to container 
/call addComponents 
/if (${Macro.Return}==FALSE) { 
/echo khiTS Error: Component not found 
/goto :khiTSCleanUpMacro 
} 

| Combine 
/varset bCombineDone FALSE 
/varcalc iSkillAttempts ${iSkillAttempts}+1 
:DoCombineLoop 
|/echo Combining 
/delay COMBINE_DELAY 
/call clearCursor ${iDestroyResults} 
/if (${containerNum.Equal[e]}) { 
/combine enviro 
} else { 
/combine pack${containerNum} 
} 
| needs this delay here to make sure the combine is finished, you may need to tweek this to your computer/connection 10 should be safe, I can get away with 7 
/delay COMBINE_DELAY 

| Keep track of what we've done - these events are called individually so they do not conflict with a parent macro if this macro is used as an included file 
/doevents SkillTrivial 
/doevents SkillUp 
/doevents SkillFailure 
/doevents SkillSuccess 
/doevents CombineError 
/doevents FullInventory 
/doevents tell 
/call clearCursor ${iDestroyResults} 
| /if (!${bCombineDone}) { 
| /goto :DoCombineLoop 
| } 

| See if we have made enough 
|/if (${makeThisMany}.Equal[${iSkillSuccess}]) { 
| /goto :khiTSCleanUpMacro 
|} 

/goto :khiTSCombineLoop 


| The macro is ending, clean up 
:khiTSCleanUpMacro 
| /mqpause 
| Delete or Save items depending on settings - Just in case 
/call clearCursor ${iDestroyResults} 
/call cleanPack ${containerNum} 
/call DisplayStats 
/endmacro 

/return 

| Removes anything on the cursor. If DestroyResults is 1, then it will destroy anything not in the components array 
sub clearCursor(int DestroyResults) 
|/echo Destroy Results = ${DestroyResults} 
:khiTSClearCursorLoop 
/delay 5 
| Is there anything on the cursor? 
/if (${Cursor.Name.NotEqual[NULL]}) { 
/if (${DestroyResults}==1) { 
| Make sure the item on the cursor is not something we want to save 
/for saveCount 1 to 10 
/if (${components[${iCompLoop}].Equal[${Cursor.Name}]) { 
/autoinv 
/goto :khiTSClearCursorLoop 
} 
/next saveCount 
| Whatever is on the cursor wasn't in the save list 
/destroy 
} else { 
/autoinv 
} 

/goto :khiTSClearCursorLoop 
} 
/return 

| Finds the value of an argument in a parameter string 
sub parseArgument(string sArgument,string sParameters) 

/declare iArgNum int local 
| Loop variable 
/declare sArgValue string local 
| Save the current arg 

/for iArgNum 1 to 10 

/if (${sParameters.Arg[${iArgNum}, ].Left[-2].Equal[${sArgument}]}) { 
/varset sArgValue ${sParameters.Arg[${iArgNum}, ].Right[1]} 
/goto :FoundArg 
} 

/next iArgNum 
:FoundArg 

/return sArgValue 



Sub DisplayStats 
/echo 
/echo khiTS: Stat display - Not Completely done 
/echo ================================ 
/echo Attempts: ${iSkillAttempts} 
/echo Successes: ${iSkillSuccess} 
/echo Faliures: ${iSkillFailure} 
/echo Skill Ups: ${iSkillUps} 

/return 

Sub Event_Chat 
/if (${abt}.Equal[TRUE]) { 
/echo khiTS: Got a tell, pausing. 
/press mqpause 
} 
/return 

Sub Event_CombineError 
/echo khiTS: Combine Error - Oh shit, it's all fucked up 
/call cleanPack ${containerNum} 
/call clearCursor ${iDestroyResults} 
/endmacro 
/return 

Sub Event_FullInventory 
/echo khiTS Error: Your inventory is full, ending macro. 
/call DisplayStats 
/endmacro 
/return 

Sub Event_SkillFailure 
/varcalc iSkillFailure ${iSkillFailure}+1 
/varset bCombineDone TRUE 
/return 

Sub Event_SkillSuccess 
/if (${sResults.Equal[NOT_SET]}) { 
:WaitForIt 
/delay 5 
/varset sResults ${Cursor.Name} 
/if (${sResults.Equal[NULL]}) /goto :WaitForIt 
} 
/varcalc iSkillSuccess ${iSkillSuccess}+1 
/varset bCombineDone TRUE 
/return 

Sub Event_SkillUp 
/varcalc iSkillUps ${iSkillUps}+1 

/return 

Sub Event_SkillTrivial 

/if (!${bSkillTrivial}) { 
/echo khiTS: Skill is trivial 
/varset bSkillTrivial TRUE 
} 


/if (${iEndOnTrivial}==1) { 
/call DisplayStats 
/call cleanPack ${containerNum} 
/call clearCursor ${iDestroyResults} 
/endmacro 
} 
/return 

| Return the number of free slots in your inventory or a container 
sub freeInventory(int PackNumber,string ItemName) 

| ItemName - If you are looking for free inventory available for a specific item give an item name 
| PackNumber - If you want to look in just one pack for an item, give a pack number 


| How many slots are available 
/declare freeSlots int local 0 
| Used for looping through inventory pack nunbers 
/declare iPack int local 1 
| Used for looping through pack slots 
/declare iSlot int local 1 
| Used with iPack to limit checking the contents of just one pack 
/declare startPack int local 1 
| Used with iPack to limit checking the contents of just one pack 
/declare EndPack int local 8 

| If no pack number is given, we need to define it and set it to null so we don't error out later 
/if (!${Defined[PackNumber]}) { 
/declare PackNumber local NULL 
} 

| Are we looking at an enviromental container or in our inventory 
/if (${PackNumber}.Equal[e]}) { 

/if (${Window[Enviro].Open}==NULL) { 
/echo freeInventory Error: You must have the enviromental container open before testing it for available space 
/return -1 
} 

/if (${Defined[ItemName]}) { 
/echo freeInventory Error: Currently this sub does not support checking for stackable ItemName space in an enviromental container 
/return -1 
} 

| This is REALLY crappy and slow, but right now there is no way (that I know of) to examine the contents of an enviromental container 
/for iPack 0 to 9 
/shiftkey /click left enviro ${iPack} 
/if (${Cursor.ID}==NULL) { 
/varcalc freeSlots ${freeSlots}+1 
} else { 
/click left enviro ${iPack} 
} 
/next iPack 

} else { 
| Not enviromental container 

| If a pack number was given, only look in that one pack 
/if (${PackNumber}.NotEqual[NULLl]) { 
/varset startPack ${PackNumber} 
/varset EndPack ${PackNumber} 
} 

/for iPack ${startPack} to ${EndPack} 
| /echo iPack = ${iPack} 
| Check to see if there is a bag in this slot 
/if (${Me.Inventory[Pack${iPack}].Container}==0) { 
| No bag, see if there is anything 
/if (${Me.Inventory[21+${iPack}]}.Equal[Me]) { 
| Nothing in this slot 
/if (${Defined[ItemName]}) { 
| /echo Empty Pack slot 
/varadd freeSlost 20 
} else { 
/varadd freeSlots 1 
} 
} else { 
| See if this ItemName is what we are looking for, and see if there is free stackable space 
/if (${Defined[ItemName]}) { 
| /echo Name = ${Me.Inventory[21+${iPack}].Name} : iPack = ${iPack} 
if (${Me.Inventory[21+${iPack}].Name.Equal[${ItemName}]}) { 
| See how many stackable slots are available 
/if (${Me.Inventory[21+${iPack}].Stackable}) { 
/varcalc freeSlots ${freeSlots}+(20-${Me.Inventory[21+${iPack}].Stack}) 
} 
} 

} 
} 
} else { 
| This is a bag 

| Are we looking for item space or just free space 
/if (${Defined[ItemName]}) { 

/for iSlot 1 to ${Me.Inventory[Pack${iPack}].Container} 
| /echo Looking at item: ${Me.Inventory[Pack${iPack}].Item[${iSlot}].Name} 
| /echo ItemName = ${ItemName} 
/if (${Me.Inventory[Pack${iPack}].Item[${iSlot}].Name.Equal[${ItemName}]}) { 
| /echo Found item ${ItemName} 
| Make sure it's stackable 
/if (${Me.Inventory[Pack${iPack}].Item[${iSlot}].Stackable}) { 
/varcalc freeSlots ${freeSlots}+(20-${Me.Inventory[Pack${iPack}].Item[${iSlot}].Stack}) 
} 
} else { 
/if (${Me.Inventory[Pack${iPack}].Item[${iSlot}]}.Equal[NULL]) { 
/varcalc freeSlots ${freeSlots}+20 
} 
} 
/next iSlot 

} else { 
| This is a bag, but item name is not given 
/varcalc freeSlots ${freeSlots}+(${Me.Inventory[Pack${iPack}].Container}-${Me.Inventory[Pack${iPack}].Items}) 
} 

} 
/next iPack 
} 

/return ${freeSlots} 


| Remove everything from a pack and puts in in your inventory 
sub cleanPack(string PackNumber) 
/echo khiTS: Cleaning out pack 
/declare iSlot int local 
| Used for looping through pack slots 
/declare iCount int local 
| How many freeslots are in the bag 

/if (${containerNum.Equal[e]}) { 
/echo clearing enviro 
|This is REALLY crappy and slow, but right now there is no way (that I know of) to examine the contents of an enviromental container 
/for iSlot 1 to 10 
/shiftkey /itemnotify enviro${iSlot} leftmouseup 
/call clearCursor ${iDestroyResults} 
/next iSlot 

} else { 

| Can't empty a non-pack duh! 
/if (${Me.Inventory[Pack${PackNumber}].Container}==0) { 
/return 
} 

/for iSlot 1 to ${Me.Inventory[Pack${PackNumber}].Container} 
| Quit if the pack is empty 
/if (${Me.Inventory[Pack${PackNumber}].Container}==0) { 
/return TRUE 
} 

/if (${Me.Inventory[Pack${PackNumber}].Item[${iSlot}].ID}!=NULL) { 
/varset iCount ${Me.Inventory[Pack${PackNumber}].Items} 
/shiftkey /itemnotify in pack${PackNumber} ${iSlot} leftmouseup 
/call clearCursor ${iDestroyResults} 
| Make sure we aren't just putting it back in the same bag 
/if (${Me.Inventory[Pack${PackNumber}].Items}==${iCount}) { 
/echo CleanPack Error: Unable to empty pack. 
/return FALSE 
} 
} 
/next iSlot 
} 
/delay 5 
/echo Done Cleaning pack 
/return TRUE 

| Put the components needed into the container 
sub addComponents 
|/echo khiTS: Adding Components 
/delay 5 
/declare iPack int local 
| Used for looping through inventory pack nunbers 
/declare iSlot int local 
| Used for looping through pack slots 
/declare compNum int local 
| Loop integer 
/declare combSlot int local 
| The slot number in the combine container to put the next item 

/varset combSlot 1 

/for compNum 1 to ${iCompCount} 
| /echo components[${compNum}] = ${components[${compNum}]} : Length = ${components[${compNum}].Length} 
/if (${components[${compNum}].Length}==0) { 
| Didn't fail, so must have passed 
/return TRUE 
} 
| Find the item - can't use ${FindItem[]} because I want to ignore anything in the combine container 
/for iPack 1 to 8 
| Don't look in the container we are using to do the combine 
/if ((${Int[${containerNum}]} < ${iPack}) || (${Int[${containerNum}]} > ${iPack})) {  
| Look inside bags 
/if (${Me.Inventory[Pack${iPack}].Container}>0) { 
/for iSlot 1 to ${Me.Inventory[Pack${iPack}].Container} 
| Does this item match the component 
/if (${components[${compNum}].Equal[${Me.Inventory[Pack${iPack}].Item[${iSlot}].Name}]}) { 
/call AddComp ${Me.Inventory[Pack${iPack}].Item[${iSlot}].InvSlot.ID} ${containerNum} ${combSlot} 
/if (!${Macro.Return}) { 
/return FALSE 
} 
/varcalc combSlot ${combSlot}+1 
/goto :FoundItem 
} 
/next iSlot 
} else { 
| Handle stuff not in bags 
/if (${components[${compNum}].Equal[${Me.Inventory[21+${iPack}]}]}) { 
/call AddComp (21+${iPack}) ${containerNum} ${combSlot} 
/if (!${Macro.Return}) { 
/return FALSE 
} 
/varcalc combSlot ${combSlot}+1 
/goto :FoundItem 
} 
} 

} 
/next iPack 

| Didn't find the item 
/echo khiTS addComponents: Couldn't find component: ${components[${compNum}]} 
/return FALSE 

:FoundItem 

/next compNum 

/return TRUE 



sub AddComp(int InvSlotNum,string CombinePackNumber,int CombineSlotNumber) 
| InvSlotNum - The slot in which the item exists 
| CombinePackNumber - Destination pack number, e for enviro 
| CombineSlotNumber - Destination slot number 
|/echo InvSlotNum = ${InvSlotNum} 
|/echo CombinePackNumber = ${CombinePackNumber} 
|/echo CombineSlotNumber = ${CombineSlotNumber} 

/if (!${Defined[InvSlotNum]} || !${Defined[CombinePackNumber]} || !${Defined[CombineSlotNumber]}) { 
/echo AddComp Error: You must specify the component's InvSlotNum.ID, the container number, and the container slot in which to put the compents 
/echo Syntax: /call AddComp <InvSlotNum> <Pack Number> <Slot Number in Pack> 
/return FALSE 
} 

| Check container to see if it is full 
/if (${CombinePackNumber.Equal[e]}) { 
| No way I know of to check enviro containers for space - but I'm ignorant so... 
} else { 
/if (${Me.Inventory[pack${CombinePackNumber}].Container}-${Me.Inventory[pack${CombinePackNumber}].Items}==0) { 
/echo AddComp Error: Unable to add this item to the container, it is full 
/return FALSE 
} 
} 

:FindEmptySlot 
| /echo CombineSlot = ${CombineSlotNumber} 
/if (${CombinePackNumber.Equal[e]}) { 
/if (${CombineSlotNumber}>10) { 
/echo AddComp Error: Unable to find and empty slot in enviro container, it is full 
/return FALSE 
} 
} else { 
/if (${CombineSlotNumber}>${Me.Inventory[pack${CombinePackNumber}].Container}) { 
/echo AddComp Error: Unable to find and empty slot in this container, it is full 
/return FALSE 
} 
} 
| See if there's anything in the slot in which we are trying to put the combine component 
/if (${CombinePackNumber.Equal[e]}) { 
/itemnotify in enviro ${CombineSlotNumber} leftmouseup 
| Make sure the cursor is clear, otherwise something was in that slot 
/if (${Cursor.ID}!=NULL) { 
/itemnotify in enviro ${CombineSlotNumber} leftmouseup 
/varcalc CombineSlotNumber ${CombineSlotNumber}+1 
/varset CombineSlotNumber ${CombineSlotNumber}.Arg[0,.]
/goto :FindEmptySlot 
} 
} else { 
/if (${Me.Inventory[pack${CombinePackNumber}].Item[${CombineSlotNumber}].ID}!=NULL) { 
/varcalc CombineSlotNumber ${CombineSlotNumber}+1 
/varset CombineSlotNumber ${CombineSlotNumber}.Arg[0,.]
/goto :FindEmptySlot 
} 
} 

| Slot is empty, so go ahead and put item into it 
| Found it, pick it up and move it to the combine container 
/ctrlkey /itemnotify ${InvSlotNum} leftmouseup 
| /echo ComponentName = ${ComponentName} 
| /echo CombinePackNumber = ${CombinePackNumber} 
/if (${CombinePackNumber.Equal[e]}) { 
/itemnotify in enviro ${CombineSlotNumber} leftmouseup 
} else { 
/itemnotify in pack${CombinePackNumber} ${CombineSlotNumber} leftmouseup 
} 


/return TRUE 

| Explain to the user how to use the macro 
sub displayHelp 

/echo Syntax: /macro khiTS "<recipe name>" "<options>" 
/echo Example: /macro khiTS "bits" "show-stats=0 destroy=0 abort-on-tell=0 end-on-trivial=0" 
/echo - 
/echo MAKE SURE THAT 
/echo * Recipe.ini is in your macro folder, or INIPATH points to your recipe.ini file 
/echo * Inventory is open. 
/echo * All your containers are open. 
/echo * Nothing crosses over each other, all windows (bags, inventory, buttons) must be free. 
/echo * Your windos positions are saved (by closing them and opening them again after they have been moved). 
/echo - 
/echo Options: 
/echo -------- 
/echo * show-stats 
/echo -- Syntax: show-stats=1|0 
/echo -- Example: show-stats=0 
/echo -- Shows combine statistics. 
/echo -- Set to 1 for show showing stats, 0 to leave out the stats. 
/echo -- Default set to 1 (show stats). 
/echo - 
/echo * destroy 
/echo -- Syntax: destroy=1|0 
/echo -- Example: destroy=1 
/echo -- Tells the macro wether end-result is destroyed or kept. 
/echo -- Set to 1 for destroying end-result, 1 to keep end-result. 
/echo -- Default set to 0 (keep end-result). 
/echo - 
/echo * abort-on-tell 
/echo -- Syntax: abort-on-tell=1|0 
/echo -- Example: abort-on-tell=1 
/echo -- Tell the macro wether it should /endmacro when recieving a tell. 
/echo -- Set to 1 for ending macro on tells, 0 to ignore tells. 
/echo -- Default set to 0 (ignore tells). 
/echo - 
/echo * end-on-trivial 
/echo -- Syntax: end-on-trivial=1|0 
/echo -- Example: end-on-trivial=1 
/echo -- Tell the macro wether it should stop combines when recieving a trivial message. 
/echo -- Set to 1 for ending macro on trivial, 0 to ignore trivial. 
/echo -- Default set to 0 (ignore trivial). 
/echo - 
/echo * combines 
/echo -- Syntax: combine=# 
/echo -- Example: combine=100 
/echo -- The number of successfull combines you want made (or till no more components are available). 
/echo -- Set to 0 for unlimited combines (or till no more components are available), or to the wanted amount. 
/echo -- Default set to 0 (unlimited). 
/echo - 
/echo * default 
/echo -- Syntax: default 
/echo -- Tell the macro to use all default settings, any other options set will be ignored and defaults will be used. 
/return