Upcoming enhancements create the ini file if it doesn't exist.
Move the configuration settings to a settings section of the ini file. that way you don't have to use parameter unless you need/want to overide your preferences.
Thanks to all that have suffered my questions over the last month as I ported this one from pre-MQData pre /notify code.
I added the loot methods and converted it to be suitable to use as an include.
Code: Select all
|----------------------------
| Maintained by Draco
| Version 3.1
| To Be a general Purpose LootFilter
|
|Version 3.1 incorporated suggestions from forum.
| Added check in Sub Forage for ability checks so when
| included in larger loops just checks and return in order
| Provide for cleaner calling code.
|
|Version 3.0 -Draco
| Seperated Load from ini made it a more generic array loader
| Ported to MQData/MQDataVar/Updated Events
| Fixed a Bug in Array indexing
|
|Version 2.3 -Draco
| Added a debug flag to assist in Debuging
| Added Loot Events
|
|Version 2.2 -Draco
| Added Loot routine and made it generic for all looting
|
|
|
| Forager with ini file support and
| statistic gathering and reporting
| version 2.1
| Set this define to the desired .ini file
| Requires a blank .ini file to start. The marco will
| populate the .ini file automatically for any zone
| and default to keeping the item. Then just change
| the values in the .ini file to 0 for an item to be
| automatically destroyed (requires FastItemDestroy
| be turned on in the options window)
#Event ZoneChange "Loading please wait#*#"
#Event NoCorpse "You must first target a corpse to loot!"
#Event CorpseTooFar "You are too far away to loot that corpse."
#Event NotYourKill "You may not loot this Corpse at this time."
||**
[lootFilter]
version=3.1
**||
#turbo
#define ITEM_NAME 1
#define KEEP_DESTROY 2
#define LOOT_COUNT 3
Sub LootFilterSetup
/declare LootINIFile string outer "forager.ini"
/declare debugLoot int outer 0
/declare EnableShowStats int outer 0 | Set to 1 to show foraging statistics
/declare EnableWriteLog int outer 0 | Set to 1 to write statistics to MQLog
/declare EnableClear int outer 0 | Set to 1 to clear before writing stats
/declare LootAttempts int outer 0
/declare LootSuccess int outer 0
/declare LootFailure int outer 0
/declare LootKeeps int outer 0
/declare LootDestroys int outer 0
/declare NumItem int outer 0
/declare LootIndex int outer 0
/declare ItemArray[3,60] string outer
/declare DefaultKeepItem int outer 1
/declare LootTooFar int outer 0
/declare NoCorpseToTarget int outer 0
/declare UnableToLoot int outer 0
| ##### User set variables #####
| /alias /showstats /call ShowStats
/call LoadFromIni ${LootINIFile} global ItemArray ${NumItem}
/varset NumItem ${Macro.Return}
/call LoadFromIni ${LootINIFile} "${Zone}" ItemArray ${NumItem}
/varset NumItem ${Macro.Return}
/return
| ########## Subroutines ##########
Sub Forage
/if (${Me.Ability[Forage]} && ${Me.AbilityReady[Forage]}) {
/doability Forage
/varadd LootAttempts ${LootAttempts}+1
}
/return
sub LootMob
/declare LootSlot int local 1
/lootn never
/delay 1s
/varset LootTooFar 0
/loot
/delay 10
/doevents NotYourKill
/doevents CorpseTooFar
:lootloop
/if (${LootTooFar}==1) /goto :doneloot
/if (${Corpse.Items}==0) {
/if (${debugLoot}>0) /echo Corpse Empty
/goto :doneloot
}
/if (${LootSlot}>=32) /goto :doneloot
/itemnotify Loot${LootSlot} leftmouseup
/delay 2s
/if (${debugLoot}>0) /echo Cursor has: ${Cursor}
| Use LootFilter Check here initially building the LootINIFile then file will be edited
| to Adjust for preference on Keep Destroy
/call CheckItem
/call HandleItem
/if (${Bool[${Cursor.Name}]}) {
/delay 1s
/if (${debugLoot}>0) /echo Destroying: ${Cursor.Name}
/destroy
/delay 1s
}
/varcalc LootSlot ${LootSlot}+1
/goto :lootloop
:doneloot
/notify LootWnd DoneButton leftmouseup
/lootn always
/varset LootSlot 0
/return
Sub LogStats
/declare xy int local
/if (${EnableClear}==1) /mqlog clear
/mqlog #############################################
/mqlog For Zone: ${Zone}
/mqlog Attempts = (${LootAttempts})
/mqlog Success = (${LootSuccess}) [(${Math.Calc[${LootSuccess}/${LootAttempts}*100]})%]
/mqlog Failures = (${LootFailure}) [(${Math.Calc[${LootFailure}/${LootAttempts}*100]})%]
/mqlog Keeps = (${LootKeeps}) [(${Math.Calc[${LootKeeps}/${LootAttempts}*100]})%]
/mqlog Destroys = (${LootDestroys}) [(${Math.Calc[${LootDestroys}/${LootAttempts}*100]})%]
/mqlog [Idx] [Item] [Keep] [Qty] [%]
/mqlog -------------------------------------------
/if (${NumItem}>0) {
/for xy 1 to ${NumItem}
/if (${ItemArray[LOOT_COUNT,${xy}]}>0) {
/mqlog "[${xy}] [${ItemArray[ITEM_NAME,${xy}]}] [${ItemArray[KEEP_DESTROY,${xy}]}] [${ItemArray[LOOT_COUNT,${xy}]}] [${Math.Calc[${ItemArray[LOOT_COUNT,${xy}]}/${LootAttempts}*100]}%]"
}
/next xy
}
/return
Sub ShowStats
/declare xy int local
/if (${EnableClear}==1) /clear
/echo #############################################
/echo For Zone: ${Zone}
/echo Attempts = (${LootAttempts})
/echo Success = (${LootSuccess}) [(${Math.Calc[${LootSuccess}/${LootAttempts}*100]})%]
/echo Failures = (${LootFailure}) [(${Math.Calc[${LootFailure}/${LootAttempts}*100]})%]
/echo Keeps = (${LootKeeps}) [(${Math.Calc[${LootKeeps}/${LootAttempts}*100]})%]
/echo Destroys = (${LootDestroys}) [(${Math.Calc[${LootDestroys}/${LootAttempts}*100]})%]
/echo [Idx] [Item] [Keep] [Qty] [%]
/echo -------------------------------------------
/if (${NumItem}>0) {
/for xy 1 to ${NumItem}
/if (${ItemArray[LOOT_COUNT,${xy}]}>0) {
/echo "[${xy}] [${ItemArray[ITEM_NAME,${xy}]}] [${ItemArray[KEEP_DESTROY,${xy}]}] [${ItemArray[LOOT_COUNT,${xy}]}] [${Math.Calc[${ItemArray[LOOT_COUNT,${xy}]}/${LootAttempts}*100]}%]"
}
/next xy
}
/return
Sub CheckItem
/declare iter int local
/varcalc LootAttempts ${LootAttempts}+1
/if (${NumItem}==0) {
/varset NumItem 1
/call AddToArray ${NumItem)
/varset LootIndex 0
} else {
/for iter 1 to ${NumItem}
/if ( ${Cursor.Name.Equal[${ItemArray[ITEM_NAME,${iter}]}]} ) {
/varset LootIndex ${iter}
/if (${debugLoot}>0) /echo "${ItemArray[ITEM_NAME,${iter}]} : ${ItemArray[KEEP_DESTROY,${iter}]}: ${ItemArray{LOOT_COUNT,${iter}]}"
}
/next iter
/if (${LootIndex}==0) {
/varcalc NumItem ${NumItem}+1
/if (${debugLoot}>0) /echo "${Cursor.Name} not found!"
/call AddToArray ${NumItem)
} else {
/varcalc ItemArray[LOOT_COUNT,${LootIndex}] ${ItemArray[LOOT_COUNT,${LootIndex}]}+1
}
}
/return
Sub AddToArray(int endPos)
/if (${debugLoot}>0) /echo "Adding ${Cursor} to Item Array"
/varset ItemArray[ITEM_NAME,${NumItem}] ${Cursor}
/varset ItemArray[KEEP_DESTROY,${NumItem}] ${Ini["${LootINIFile}","${Zone}","${Cursor}" NOTFOUND]}
/if (${ItemArray[KEEP_DESTROY,${NumItem}].Equal[NOTFOUND]} ) {
/if (${debugLoot}>0) /echo "${Cursor} Not Found in ${LootINIFile}"
/varset ItemArray[KEEP_DESTROY,${NumItem}] ${DefaultKeepItem}
/ini "${LootINIFile}" "${Zone}" "${Cursor}" ${DefaultKeepItem}
/if (${debugLoot}>0) /echo "Added [${Zone}] ${Cursor}=${DefaultKeepItem} to ${LootINIFile}"
/mqlog "Added [${Zone}] ${Cursor}=${DefaultKeepItem} to ${LootINIFile}"
}
/varset ItemArray[LOOT_COUNT,${NumItem}] 1
/return
Sub HandleItem
/if ( ${ItemArray[KEEP_DESTROY,${LootIndex}].NotEqual[1]} ) {
/varcalc LootDestroys ${LootDestroys}+1
/if (${debugLoot}>0) /echo Destroying: ${Cursor.Name}
/destroy
} else {
/varcalc LootKeeps ${LootKeeps}+1
/if (${debugLoot}>0) /echo Keeping: ${Cursor.Name}
/autoinv
}
/return
| ########## Subroutines ##########
Sub LoadFromIni(string iniFileName, string zoneName, ArrayName, startIndex )
/declare IniPosition int local 0
/declare IniList string local
/declare finishIndex int local ${startIndex}
/if (${debugLoot}>0) /echo "Loading Loot Table for ${zoneName}: ${Ini[${iniFileName},${zoneName}]}"
/varset IniList ${Ini[${iniFileName},${zoneName}]}
/if (${Bool[${IniList}]}) {
/if (${debugLoot}>0) /echo "KeySet[${zoneName}]=${IniList}"
:CheckZoneLoot
/varcalc IniPosition ${IniPosition}+1
/varcalc finishIndex ${finishIndex}+1
/if (${debugLoot}>0) /echo Item(${IniPosition}): ${IniList.Arg[${IniPosition},|]}
/varset ${ArrayName}[1,${finishIndex}] ${IniList.Arg[${IniPosition},|]}
/varset ${ArrayName}[2,${finishIndex}] ${Ini[${iniFileName},${zoneName},${${ArrayName}[1,${finishIndex}]}]}
/if (${debugLoot}>0) /echo "ZONE LOAD ${${ArrayName}[1,${finishIndex}]}=${${ArrayName}[2,${finishIndex}]}"
/if (${Bool[${IniList.Arg[${Math.Calc[${IniPosition}+1]},|]}]}) /goto :CheckZoneLoot
}
/return ${finishIndex}
Sub Event_ZoneChange
/delay 1m
/call LoadFromIni ${LootINIFile} global ItemArray 0
/varset NumItem ${Macro.Return}
/call LoadFromIni ${LootINIFile} "${Zone}" ItemArray ${NumItem}
/varset NumItem ${Macro.Return}
/return
Sub Event_CorpseTooFar
/varset LootTooFar 1
/return
Sub Event_NoCorpse
/varset NoCorpseToTarget 1
/return
Sub Event_NotYourKill
/varset UnableToLoot 1
/return
Usage:
In your initialization code call LootFilterSetup
After a corpse is targetted call LootMob i.e.
Code: Select all
|Loot.mac
#include lootFilter.inc
Sub Main
/call lootFilterSetup
/call LootMob
/return
Code: Select all
|----------------------------
| Forager with ini file support and
| statistic gathering and reporting
| version 3.0 By Draco
| Move the guts to forager.inc left this as a place to call the main loop
| I have used to /call CheckItem and /call HandleItem in my lootMob code
| sample Here:
| sub LootMob
| /lootn never
| /delay 1s
| /loot
| /delay 1s
| /varset LootTooFar 0
| :lootloop
| /if (${LootTooFar}==1) /goto :doneloot
| /if (${LootSlot}>=32) /goto :doneloot
| /click left corpse ${LootSlot}
| /delay 1s
| /if (${Bool[${Cursor.Name}]}) /goto :doneloot
| | Use Forager Check here initially building the LootINIFile then file will be edited
| | to Adjust for preference on Keep Destroy
| /call CheckItem
| /call HandleItem
|
| /if "$cursor()"}=="TRUE" {
| /delay 1s
| /click left destroy
| /delay 1s
| }
| /varadd LootSlot 1
| /varset CheckLoot 0
| /goto :lootloop
| :doneloot
| /lootn always
| /varset LootSlot 0
|/return
|
| This loot loop was orignally found in Grimkjacks hunter.mac I removed his
| loot filter arrays and use calls to the included forager.inc. I also
| implemented several of the sugestion found in this forum to include a outer
| section, etc.
|
| version 2.1
| Set this define to the desired .ini file
| Requires a blank .ini file to start. The marco will
| populate the .ini file automatically for any zone
| and default to keeping the item. Then just change
| the values in the .ini file to 0 for an item to be
| automatically destroyed (requires FastItemDestroy
| be turned on in the options window)
|
| TODO
| Add a combat check to forage to turn off attack forage them turn it back on.
#turbo
#include "lootFilter.inc"
Sub Main
/call ForageSetup
:Continue
/varset ForageIndex 0
/if (${Me.Ability[Forage]} && ${Me.AbilityReady[Forage]}) {
/call Forage
/if( ${Bool[${Cursor.Name}]} ){
/varcalc ForageFailure ${ForageFailure}+1
} else {
/varcalc ForageSuccess ${ForageSuccess}+1
/call CheckItem
/call HandleItem
}
/if (${EnableShowStats}==1 ) /call ShowStats
/if (${EnableWriteLog}==1 ) /call LogStats
}
|/delay ${ForageDelay}
/goto :Continue
/return
Though, I included sample macro implementations I posted this in snipets because, I feel the real power of this macro is being able to be included in hunter macros , etc. Enjoy, please comment. If we can make these better I welcome the input. And again The orginal macro was not mine. However unfortunately there name isn't in the code.
Sample ini
Code: Select all
[Global]
Spider Silk=1
Roots=1
Fishing Grubs=0


