Post
by SomeEqDude » Sun May 02, 2004 8:49 pm
Here's a quick stab at a MQ2Vars version, *not tested at all*
| Click.mac - v2.21 - Resurrect corpses around you - by blueninja
| Resurrects all corpses within a radius using the cleric epic or spell
| Resurrects high priority classes first as defined in the ini file
|
| Usage:
| /macro click [radius] [only] [con/nocon] [racecheck/noracecheck] [useblacklist/noblacklist]
| [usespell/useepic] [sit/stand] [spellname] <nameofspell> [spellslot] <X> [prioritygroup0]
| [prioritygroup1] [prioritygroup2]...
| /macro click buildraces
| [radius] - set radius to look for corpses in, default value is in ini file
| [only] - stop ressing after corpses in priority groups have been ressed
| [con/nocon] - toggle /consider to test if corpse is pc or npc
| [racecheck/noracecheck] - toggle check for race to test if corpse is pc or npc
| (requires ini file)
| [useblacklist/noblacklist] - toggle check for blacklisted corpses
| (requires ini file)
| [usespell/useepic] - use epic or spell to resurrect
| [sit/stand] - toggle sitting while not casting to regen mana
| [spellname] <nameofspell> - name of spell to use if using spell
| [spellslot] <X> - spell gem number to use for spell if using spell
| [prioritygroupX] - names of groups to res before others
|
| [buildraces] - update list of player races in ini file
|
| Example:
| /macro click 200 nocon dps healers
| /macro click 200 only cr
| /macro click usespell 150 only cr spellname resurrection spellslot 5
| /macro click buildraces
|
| Make sure you set CLICKINIFILE a few lines down to a valid filename
| You probably want to run this with '/filter macros enhanced' to avoid targeting spam
#turbo
|Make sure you set this to point to a valid location
#define CLICKINIFILE "click.ini"
#define MEMDELAY 30
#define DEFAULTSPELL Reviviscence
#event interrupt "Your spell is interrupted"
#event notequipped "You cannot use this item unless it is equipped."
#event notmemmed "You do not seem to have that spell memorized."
#event willdecay "This corpse will decay in"
#event restime "This corpse's resurrection time will expire in "
#event corpsetooold "This corpse is too old to be resurrected."
#event clickedoldcorpse "This player cannot be resurrected. The corpse is too old."
#event corpseexpire "This corpse is waiting to expire."
#event couldnotrez "You were unable to restore the corpse to life, but you may have success with a later attempt."
#event youmustbestanding "You must be standing to cast a spell."
#event fizzle "Your spell fizzles!"
#event oom "Insufficient Mana to cast this spell"
Sub Event_restime
|Got a message that the corpse has time left on rez timer
/varset ispccorpse 1
/return
Sub Event_willdecay
|Since the rez time message comes before the expiry time message the
|event should fire now
/doevents restime
|Small pause to be sure
/if (${ispccorpse}!=1) {
/delay 5
/doevents restime
}
/varset gotconmsg 1
/return
Sub Event_corpsetooold
|Corpse too old to rez, treat as npc corpse
/varset gotconmsg 0
/return
Sub Event_corpseexpire
|Corpse about to poof, treat as npc corpse
/varset gotconmsg 0
/return
Sub Event_couldnotrez
/varadd couldnot 1
/return
Sub Event_clickedoldcorpse
| Tried to resurrect a corpse that was too old
| Remove from statistics
/varsub clicked 1
/varset status 1
/return
Sub Event_interrupt
/if (${Me.State.Equal["DUCK"]}) {
/varset status 1
/varsub clicked 1
/call output 4 "Ducked, moving to next.."
} else {
/varset status 2
}
/return
Sub Event_fizzle
/varset status 2
/return
Sub Event_oom
/varset status 3
/return
Sub Event_notequipped
/beep
/call output 1 "ERROR: Epic is in an inventory slot, need to equip it in primary"
/endmacro
/return
Sub Event_notmemmed
/call sitdown
/if (${usespell}==0) {
/beep
/call output 1 "ERROR: Epic is bagged or banked"
/endmacro
} else {
| Memorize spell
/call output 3 "Spell ${spellname} not memorized"
/memspell "${spellslot}" "${spellname}"
/delay MEMDELAY
| Check if it's memmed now, otherwise quit
/if (!${Me.Gem[${spellslot}].Name.Equal["${spellname}"]}) {
/call output 1 "Couldn't memorize spell ${spellname}"
/endmacro
}
/varset status 4
}
/return
Sub Event_youmustbestanding
/varset status 2
/call output 4 "Standing up.."
/call standup
/return
Sub Main
/declare status outer
/declare ispccorpse outer
/declare gotconmsg outer
/declare oldtargetid local
/declare radius local
/declare contimer timer
/declare timeouts outer
/declare corpses outer
/declare skippedrace outer
/declare skippedcon outer
/declare skippedblacklist outer
/declare clicked outer
/declare couldnot outer
|prios(x,y) - contains name of profile in (x,0) and number of filters in profile in (x,1)
/declare prios array2
/declare priocount outer
|priofilters(x,y) - y=0..prios(x,1) contains the values of the filters for prios(x,0)
/declare priofilters array2
/declare only local
/declare argloop int local
/declare racecount int outer
|List of valid player races
/declare races array
/declare curid outer
/declare spellmaxrange local
/declare noiselevel outer
/declare contimeout outer
/declare defaultradius local
/declare showstats local
/declare useraces outer
/declare consider outer
/declare usespell outer
/declare spellname outer
/declare spellslot outer
/declare useblacklist outer
/declare sit outer
/varset noiselevel 0
|Read configuration
/call getconfig "noiselevel" 2
/varset noiselevel ${Macro.Return}
/call getconfig "contimeout" 50
/varset contimeout ${Macro.Return}
/call getconfig "defaultradius" 100
/varset defaultradius ${Macro.Return}
/call getconfig "showstats" 1
/varset showstats ${Macro.Return}
/call getconfig "useraces" 0
/varset useraces ${Macro.Return}
/call getconfig "consider" 1
/varset consider ${Macro.Return}
/call getconfig "useblacklist" 0
/varset useblacklist ${Macro.Return}
/call getconfig "usespell" 0
/varset usespell ${Macro.Return}
/call getconfig "spellname" DEFAULTSPELL
/varset spellname ${Macro.Return}
/call getconfig "spellslot" 8
/varset spellslot ${Macro.Return}
/call getconfig "sit" 0
/varset sit ${Macro.Return}
/varset corpses 0
/varset clicked 0
/varset skippedrace 0
/varset skippedcon 0
/varset timeouts 0
/varset skippedblacklist 0
/varset couldnot 0
/varset only 0
/varset radius ${defaultradius}
/varset priocount -1
/varset spellmaxrange 200
|Check if parameter is passed
/for argloop 0 to 10
/if (${Defined[Param${argloop}]}) {
/call IsNumeric "${Param}${argloop}"
/if ("${Macro.Return}"=="false") {
|non-numeric argument
/if ("${Param}${argloop}"=="only") {
/varset only 1
} else /if ("${Param}${argloop}"=="buildraces") {
/call buildini
/endmacro
} else /if ("${Param}${argloop}"=="noracecheck") {
/varset useraces 0
} else /if ("${Param}${argloop}"=="racecheck") {
/varset useraces 1
} else /if ("${Param}${argloop}"=="noblacklist") {
/varset useblacklist 0
} else /if ("${Param}${argloop}"=="useblacklist") {
/varset useblacklist 1
} else /if ("${Param}${argloop}"=="usespell") {
/varset usespell 1
} else /if ("${Param}${argloop}"=="useepic") {
/varset usespell 0
} else /if ("${Param}${argloop}"=="sit") {
/varset sit 1
} else /if ("${Param}${argloop}"=="stand") {
/varset sit 0
} else /if ("${Param}${argloop}"=="nocon") {
/varset consider 0
} else /if ("${Param}${argloop}"=="con") {
/varset consider 1
} else /if ("${Param}${argloop}"=="spellname") {
/varadd argloop 1
/varset spellname "${Param}${argloop}"
} else /if ("${Param}${argloop}"=="spellslot") {
/varadd argloop 1
/varset spellslot "${Param}${argloop}"
} else {
/varadd priocount 1
/varset prios(${priocount},0) "${Param}${argloop}"
/call buildprios "${Param}${argloop}" ${priocount}
/varset prios(${priocount},1) ${Macro.Return}
}
} else {
|Numeric argument, set radius
/varset radius ${Param}${argloop}
}
} else {
|No argument passed, default
/goto :argsdone
}
/next argloop
:argsdone
/call sitdown
/if (${usespell}==1) {
/varset spellmaxrange ${Spell[${spellname}].Range}
}
/if (${radius}>${spellmaxrange}) {
/call output 2 "WARNING: Radius larger than range of spell, setting to ${spellmaxrange}"
/varset radius ${spellmaxrange}
}
/varadd priocount 1
|If we havent found any profiles on command line, set first one to default
/if (${priocount}==0) {
/varset prios(${priocount},0) "default"
/call buildprios "default" ${priocount}
/varset prios(${priocount},1) ${Macro.Return}
/varset priocount 1
}
|Build an array of valid player races from ini file
/if (${useraces}==1) {
/varset racecount -1
:iniloop
/varadd racecount 1
/varset races(${racecount}) "${Ini[${CLICKINIFILE},races,${racecount},NOTFOUND)}"
/if ("${races}(${racecount})"=="NOTFOUND") /goto :leaveloop
/goto :iniloop
}
:leaveloop
|Read the blacklist after the normal profiles
/varset prios(${priocount},0) "blacklist"
/call buildprios "blacklist" ${priocount}
/varset prios(${priocount},1) ${Macro.Return}
|First loop through high priority classes..
/varset curid 0
/echo Doing priority corpses
/declare corpsecnt local
/varset corpsecnt 1
/for argloop 0 to ${Math.Calc[${priocount}-1].Int}
/varset corpsecnt 0
:loopprio
/varset corpsecnt ${Math.Calc[${corpsecnt}+1]}
/doevents
/varset status 0
/varset oldtargetid ${curid}
/varset curid ${Spawn[corpse radius ${radius} next id:${oldtargetid}].ID}
/varset curid ${NearestSpawn[${corpsecnt},corpse radius ${radius}].ID}
|If we didn't get a new target move on to low priority
/if (${curid}==0) /goto :clicktherest
|Check if this is a high priority corpse
/call HasPriority ${prios}(${argloop},0) ${curid}
/if (!${Macro.Return.Equal["true"]}) /goto :loopprio
/echo Rezzing ${Spawn[${curid}].Name}
/call clickit ${curid}
|Gather statistics
/doevents couldnotrez
/goto :loopprio
:clicktherest
/next argloop
/echo Doing low priority corpses
|If parameter 'only' is specified don't move on to low priority corpses
/if (${only}==1) /goto :end
/varset curid 0
/varset corpsecnt 0
|.. then everyone else
:restloop
/varset corpsecnt ${Math.Calc[${corpsecnt}+1]}
/doevents
/varset status 0
/varset oldtargetid ${curid}
/varset curid ${NearestSpawn[${corpsecnt},corpse radius ${radius}].ID}
|If we didn't get a new target quit
/if (${curid}==0) /goto :end
|Check that this isn't a priority corpse
/for argloop 0 to ${Math.Calc[${priocount}-1]}
/call HasPriority ${prios}(${argloop},0) ${curid}
/if (${Macro.Return.Equal["true"]}) /goto :restloop
/next argloop
/echo Rezzing ${Spawn[${curid}].Name}
/call clickit ${curid}
|Gather statistics
/doevents couldnotrez
/goto :restloop
:end
|Gather statistics
/call sitdown
/doevents couldnotrez
/if (${showstats}==1) /call statsub
/return
Sub getconfig(key,default)
|Read the value of a [config] parameter in ini file
|/call getconfig "paramname" "defaultvalue"
|Returns value
/if (!${Defined[key]}) /return "false"
/if (!${Defined[default]}) /return "false"
/declare inivalue local
/varset inivalue ${Ini[${CLICKINIFILE},config,${key},${default}]}
/return "${inivalue}"
Sub output
|Echo that uses the noiselevel setting
/if (!${Defined[Param0]}) /return
/if (!${Defined[Param1]}) /return
/if (${Param0}<=${noiselevel}) {
/echo ${Param1}
}
/return
Sub IsNumeric
|Returns true if Param0 is numeric, false if not
/if (!${Defined[Param0]}) /return "false"
/if (${String[${Param0}].Length}==0) /return "false"
/declare counter int local
/for counter 1 to ${String[${Param0}].Length}
/if (${String[${Param0}].Mid[${counter},1]}<"0" || ${String[${Param0}].Mid[${counter},1]}>"9") /return "false"
/next counter
/return "true"
Sub statsub
|Display stats
/declare runtime local
/declare runstring local
/varset runtime ${Macro.RunTime}
/echo Corpses found: ${Int[${corpses}]}, ressed: ${Int[${clicked}]}, could not restore: ${Int[${couldnot}]}
/echo Skipped race: ${Int[${skippedrace}]}, Skipped con: ${Int[${skippedcon}]}, Skipped blacklist: ${Int[${skippedblacklist}]}
/varset runstring "Time taken ${Int[${Math.Calc[${runtime}/60]}]} minutes ${Int[${Math.Calc[${runtime}%60]}]} seconds"
/if (${timeouts}>0) /echo Consider timeouts: ${timeouts}
/if (${corpses}>0) /varset runstring "${runstring} (avg time per corpse: ${Math.Calc[${runtime}/${corpses}]}s)"
/echo ${runstring}
/return
Sub buildprios(Param0,Param1)
|Builds priority lists from ini file into priofilters(${Param1},y)
|${Param0} is the name of the profile
/declare filters local
/declare temp local
/declare curfilt local
/declare pipeloc local
/declare nextpipe local
/declare filtercount local
/if (!${Defined[Param0]}) /return
/varset filters "${Ini[${CLICKINIFILE},${Param0},-1,NOTFOUND]}"
/if (${String["${filters}"].Equal["NOTFOUND"]}) {
/if (${String["${Param0}"].Equal["default"]}) {
||If default is empty, set defaults to bards and clerics
/varset priofilters(${Param1},0) "cBard"
/varset priofilters(${Param1},1) "cEnchanter"
/varset priofilters(${Param1},2) "cCleric"
/return 3
} else {
/return -1
}
}
/varset filters $left($calc($strlen(${filters})-2),${filters})
/varset filtercount 0
/varset nextpipe $instr("|",${filters})
/if n ${nextpipe}<0 {
/varset priofilters(${Param1},0) $left(1,${filters})"$ini("CLICKINIFILE","${Param0}","${filters}")"
/goto :leavebuildprios
}
:loopfilters
/varset curfilt $mid(0,${nextpipe},${filters})
/varset filters $right($calc($strlen(${filters})-${nextpipe}-1),${filters})
/varset temp $ini("CLICKINIFILE","${Param0}",curfilt)
/varset priofilters(${Param1},${filtercount}) $left(1,${curfilt})"$ini("CLICKINIFILE","${Param0}","${curfilt}")"
/varset nextpipe $instr("|",${filters})
/varadd filtercount 1
/if n ${nextpipe}<0 {
/varset priofilters(${Param1},${filtercount}) $left(1,${filters})"$ini("CLICKINIFILE","${Param0}","${filters}")"
/goto :leavebuildprios
}
/goto :loopfilters
:leavebuildprios
/varadd filtercount 1
/return ${filtercount}
Sub HasPriority(Param0,Param1)
|Test if corpse with id ${Param1} has high priority in profile ${Param0}
/declare test local
/declare hpcount int local
/declare filtnum local
/if (!${Defined[Param0]}) {
/varset test default
} else {
/varset test ${Param0}
}
/echo ${Param0}
/end
/call findprioinarray "${test}"
/echo Checking Priority on ${Spawn[${test}].Name} ${prios}(${Macro.Return},1)
/if (${prios}(${Macro.Return},1)<=0) /return "false"
/varset filtnum ${Macro.Return}
/for hpcount 0 to $calc(${prios}(${filtnum},1)-1)
/if (${String[${priofilters}(${filtnum},${hpcount})].Left[1].Equal["c"]}) {
/if (${Spawn[${Param1}].Class.Equal[${String[${priofilters}(${filtnum},${hpcount})].Right[-1]}]}) {
/return "true"
}
} else /if (${String[${priofilters}(${filtnum},${hpcount})].Left[1].Equal["n"]}) {
/if "$spawn(${Param1},name)"~~"$right($calc($strlen("${priofilters}(${filtnum},${hpcount})")-1),"${priofilters}(${filtnum},${hpcount})")" {
/return "true"
}
} else /if (${String[${priofilters}(${filtnum},${hpcount})].Left[1].Equal["g"]}) {
/if "$spawn(${Param1},guild)"=="$right($calc($strlen("${priofilters}(${filtnum},${hpcount})")-1),"${priofilters}(${filtnum},${hpcount})")" {
/return "true"
}
}
/next hpcount
/return "false"
Sub findprioinarray
|Search array for ${Param0}, returns the location or -1 if not found
/declare counter int local
/for counter 0 to ${priocount}
/if (${String[${Param0}].Equal[${prios}(${counter},0)]}) /return ${counter}
/next counter
/return -1
Sub IsPCRace
|Test if race of corpse with id ${Param0} is in the array of valid races
/declare loopcounter int local
/for loopcounter 0 to ${racecount}
/if "$spawn(${Param0},race)"=="${races}(${loopcounter})" /return "true"
/next loopcounter
/return "false"
Sub clickit
/declare counter local
/declare giveup local
/declare castwait local
|Test if valid race
/if (${useraces}==1) {
/call IsPCRace ${Param0}
/if (${Macro.Return.Equal["false"]}) {
/varadd skippedrace 1
/return
}
}
/if (${useblacklist}==0) /goto :skipblacklist
|Check if corpse is blacklisted
/call HasPriority "blacklist" ${curid}
/if (${Macro.Return.Equal["true"]}) {
/call output 3 "Skipping blacklisted ${Spawn[${curid}].Name}"
/varadd skippedblacklist 1
/return
}
:skipblacklist
|Target corpse
/tar id ${Param0}
/if (!${Target.ID}) /return
/varadd corpses 1
|Doevents to get stats and flush /con messages
/doevents
/if (${consider}==1) {
/varset ispccorpse 0
/varset gotconmsg 0
/consider
|Set timer so we don't get stuck waiting for a /con message
/varset contimer ${contimeout}
:waitcon
/doevents corpseexpire
/doevents willdecay
/delay 1
|After a few seconds give up and assume it's a pc corpse
/if (${contimer}==0) {
/call output 3 "Timeout waiting for /con message, assuming pc corpse"
/varadd timeouts 1
/varset gotconmsg 1
/varset ispccorpse 1
}
/if (${gotconmsg}==0) /goto :waitcon
/if (${ispccorpse}!=1) {
/varadd skippedcon 1
/call output 3 "Skipping $target(name)"
/return
}
}
/varadd clicked 1
|Counter to give up after 4 attempts at rezzing a corpse
|that fail either by interrupt or if we can't cast for 3 seconds
/varset giveup 0
:tryagain
/varadd giveup 1
|Too many tries, move on to next
/if (${giveup}>4) /return
/varset status 0
/varset castwait 0
|Wait until we are not casting, if we wait too long, treat as an interrupt
:waitforcast
/if (!${Me.Casting.ID}) /goto :castit
/delay 5
/varadd castwait 1
/if (${castwait}>5) /goto :tryagain
/goto :waitforcast
:castit
/call output 3 "Resurrecting $target(name)"
/hail
/if (${usespell}==0) {
| Use epic
/call standup
/cast item "water sprinkler of nem ankh"
} else {
| Use spell
:waitspellrefresh
| Check if enough mana, if not med until there is enough
/if (${Me.CurrentMana}<${Spell[${spellname}].Mana}) /call medup
| Wait until spell is refreshed
/if (!${Me.SpellReady[${spellname}]}) {
/delay 1
/goto :waitspellrefresh
}
/call standup
/cast ${spellname}
}
|Wait until not casting anymore
:castdelay
/delay 5
/doevents
/if (${status}==4) {
/varsub giveup 1
/goto :tryagain
}
/if (${status}==3) {
/varsub giveup 1
/call medup
/goto :tryagain
}
/if (${status}==2) /goto :tryagain
/if (${status}==1) {
/call sitdown
/return
}
/if (${Me.Casting.ID}) /goto :castdelay
/call sitdown
/return
Sub medup
/call sitdown
| Loop until enough mana to cast
:medloop
/delay 1s
/if (${Me.CurrentMana}<${Spell[${spellname}].Mana}) /goto :medloop
/call standup
/return
Sub sitdown
| Don't bother sitting if full mana
/if (${Me.PctMana}==100) /return
| Check sit setting
/if (${sit}==0) /return
| Don't try to sit if on a mount
/if (${Me.Mount.ID}) /return
| If not sitting, sit down
/if (!${Me.State.Equal["SIT"]}) /sit
/return
Sub standup
| Don't try to stand if on a mount
/if (${Me.Mount.ID}) /return
| If not standing, stand up
/if (!${Me.State.Equal["STAND"]}) /stand
/return
Sub buildini
|Loop through the players in zone and compare their race to the list of valid
|player races in ini file and add new races
/declare currace local
/declare curid local
/varset racecount -1
|Read races from ini file
:buildiniloop
/varadd racecount 1
/varset races(${racecount}) "$ini("CLICKINIFILE","races",${racecount})"
/if ("${races}(${racecount})"=="NOTFOUND") /goto :buildleaveloop
/goto :buildiniloop
:buildleaveloop
/declare oldtarget local
/declare added int local
/varset added 0
/declare pccount int local
/varset pccount int 0
|Get first pc
/varset curid $searchspawn(pc)
/varset currace "$spawn(${curid},race)"
:buildloop
/varadd pccount 1
|See if race is in array already
/call buildisinarray "${currace}"
/if (${Macro.Return}==0) {
|New race, add to ini
/if ("$defined(currace)"!="FALSE" && "${currace}"!="NULL") {
/ini "CLICKINIFILE" "races" ${racecount} "${currace}"
/varset races(${racecount}) "${currace}"
/varadd racecount 1
/varadd added 1
/call output 2 "Added race: ${currace}"
}
}
/varset curid $searchspawn(pc,next,id:${curid})
/varset currace "$spawn(${curid},race)"
/if (${curid}==0) /goto :buildend
/goto :buildloop
:buildend
/call output 2 "Players counted: ${pccount} Races in ini: ${racecount}, added ${added}"
/return
Sub buildisinarray
|Search array for ${Param0}
/declare loopcounter int local
/for loopcounter 0 to $Math.Calc[${racecount}-1]
/if ("${Param0}"=="${races}(${loopcounter})") {
/return 1
}
/next loopcounter
/return 0