-Scrime if you have a new version I'll whack this post, thanks for the macro.
Code: Select all
| Fixed necrofarm.mac - v0.4.1 11/06/03
| - removed most "nopredict" from distance calcs in /face
| - added "/face loc $target(y), $target(x)" in MoveToTarget Sub
| - only oddity I can see is that character looks up just before attacking mob
| - All credit goes to Scrime for this awesome script - Stogar
|
| converted necrofarm.mac - v0.4.0b 10/21/2003 by Scrime
| Basic pet hunter script converted to new var format
| w/ some ideas borrowed from GrimJack's hunter script.
|
| Usage:
| ! Have a pet up.
| ! Put the correct spells in the spell names.
| ! Use /call AddToMobList to add the mobs that you want to hunt.
| ! Use /call AddToLootList to add the items that you want to loot
| ! Use /call AddToDontLootList to add the items that you want to destroy
| because they accidently get looted due to the wildcard nature of the loot list.
|
| Features:
| + Anti-KS code. Selects targets with no other PCs within a variable radius.
| Also checks to make sure the target is undamaged and is not already attacking
| someone else before engaging.
| + Selective auto-looting. Only keeps the items that you want it to. Also has a
| destroy list, in the case that you are looting all "lightstones", but still want
| to destroy "Burned Out Lightstones" (for example)
| + Closest mob selection. Looks through the whole list of mobs you want to hunt
| goes after the closest one.
| + Debugging code. Set DEBUG to "1==1" to show debugging code, set to "0==1" to turn
| it off.
| + Buff tracking. Keeps track of buffs up on you and your pet, refreshes as nescessary.
| + Heals your pet once it drops below 90% health.
| + Obstruction avoidance. Should back up and try to go around something if it gets stuck.
|
| Known Issues/Limitations/Bugs:
| - Does not know when to stop hunting. $freeinv works for some people, crashes the client for
| other people. Until it is fixed, the script will not know when you bags are full.
| - Does not stop to med up, stops casting spells once below 20% mana.
| - Obstruction detection needs some tweaking, maybe an "allowance" value for being in the same spot
| instead of waiting for the x/y locs to be the same.
| - Some of the global variables need to be turned in to locals.
|
| Release Notes for v0.4.0b :
| * NOTE: This is considered a beta release of the converted previous v0.3.0b, it still needs some more testing.
| Use at you own risk, please report any problems. Enjoy and macro responsibly.
| * Hunt distance is now a constant (cHuntDistance) that you can set at the beginning of the script. This
| is the maxiumum distance away from you that the script will look for a new target. Set to 99999 for no
| max distance.
| * In the anti-ks code, when looking at our targets assisted target, it will look at the name and if
| the name contains the word "corpse" it will disregard the assist and attack anyway.
| * In the anti-ks code, if a mob it tries to target becomes invalid because it is not full health or is
| currently attacking someone it will not be considered the next time thru the loop.
| * Aggro'd mob protection. If we have a mob aggro'd on us, then the script will select that mob as our next
| target to kill AFTER we are done with out current target before doing a normal search for a hunt target.
| * Continuous target re-evaluation. As long as we are moving towards our target, the script will keeping
| looking for closer targets. This makes it so that we wont run past newly spawned valid targets on our way
| to our current target (which is farther away).
| * Script now backs away from a target if it gets too close to us (too close range defined as cTooCloseRange)
|
#turbo
| used to echo debugging messages. set to 1=1 if you want to see them, 0==1 if you dont
#define DEBUG 1==1
| distance defines, setting these alters the behavior of the script
| cAntiKSRadius is the distance from each mob that will exclude it from selecting as a
| target if there is another PC within this range.
#define cAntiKSRadius 50
| cAtkRange is how close we get to the mob before we send in the pet
#define cAtkRange 50
| cTooCloseRange is how close we let a mob we are attacking get to us before we start to
| back away
#define cTooCloseRange 30
| cHuntDistance is the maximum distance away that the script will select a new target.
#define cHuntDistance 1500
| spell names
#define SelfShieldSpell "Greater Shielding"
#define PetBuffSpell "Augment Death"
#define PetHealSpell "Mend Bones"
| special events to respond to
#event PetHasteDown "Your pet's Augment Death spell has worn off."
#event Fizzle "Your spell fizzles!"
| MAIN =========================================================
Sub Main
| clear out all variables and set up new ones
/zapvars
/call DeclareGlobals
| clear target, et al
/press esc
/press esc
/press esc
/press shift
/press alt
/press ctrl
| never confirm looting nodrop items
/lootn never
| macro title
/echo Starting NecroFarm v0.4.0a - by Scrime
/if DEBUG /echo Debugging messages WILL be shown.
/echo Attack range is cAtkRange.
/echo AntiKS range is cAntiKSRadius.
/echo TooClose range is cTooCloseRange.
/echo Hunt range is cHuntDistance.
| set up our hunting array
/call AddToMobList "willowisp"
/call AddToMobList "spider"
| set up the loot array
/call AddToLootList "silk"
/call AddToLootList "lightstone"
| set up the dont loot array
/call AddToDontLootList "burned out lightstone"
:StartHunting
/doevents
/call CastSpells
/if n @HaveTarget==0 /call FindAggroTarget
/if n @HaveTarget==0 /call MoveToTarget
/if n @HaveTarget==1 /call KillTarget
/if n @HaveTarget==1 /call LootTarget
/if n @BagsFull==1 /goto :EndMacro
/goto :StartHunting
:EndMacro
/if n @BagsFull==1 /echo NecroFarm ended: Bags are full, go sell!
/return
| SUBS =========================================================
Sub DeclareGlobals
/declare CurrTarget global
/declare CurrMana global
/declare LastPosX global
/declare LastPosY global
/declare OldTarget global
/declare PetHasteStatus global
/declare MobArraySize global
/declare LootArraySize global
/declare MobArrayIndex global
/declare LootArrayIndex global
/declare ClosestMobID global
/declare ClosestMobDist global
/declare HaveTarget global
/declare ObstCount global
/declare DontLootArraySize global
/declare InvalidTargetID global
/declare LootSlot global
/declare BagsFull global
/declare FizzleFlag global
| array number defines, dont change
/declare MobArray array
/declare LootArray array
/declare DontLootArray array
/return
Sub AddToMobList
/if "@Param0"!="" {
/varadd MobArraySize 1
/varset MobArray(@MobArraySize) "@Param0"
/if DEBUG /echo Added @Param0 to the MobArray at position $int(@MobArraySize).
}
/return
Sub AddToLootList
/if "@Param0"!="" {
/varadd LootArraySize 1
/varset LootArray(@LootArraySize) "@Param0"
/if DEBUG /echo Added @Param0 to the LootArray at position $int(@LootArraySize).
}
/return
Sub AddToDontLootList
/if "@Param0"!="" {
/varadd DontLootArraySize 1
/varset DontLootArray(@DontLootArraySize) "@Param0"
/if DEBUG /echo Added @Param0 to the DontLootArray at position $int(@DontLootArraySize).
}
/return
| ==============================================================
| FindAggroTarget
| this function targets the closest mob that is not our pet and looks to see if it has us as its
| target. If we find a target here, then we put our pet on it and skip normally finding
| a target.
Sub FindAggroTarget
/if DEBUG /echo Entering FindAggroTarget...
| clear our current target
/press esc
| target the closest mob that is not our pet
/target npc notid $char(pet)
| if we have a target, then we need to see if it has a target
/if $target()=="TRUE" {
/if DEBUG /echo Checking closest target ($target(name), id:$target(id)) for aggro.
/varset ClosestMobID $target(id)
/assist
/delay 5
| if the closest mob's target is us, then select it as our target to kill.
/if n $target(id)==$char(id) {
/target id @ClosestMobID
/if DEBUG /echo $target(name) ($target(id)) is aggro'd on us, selecting as next target to kill.
/varset HaveTarget 1
/varset ClosestMobID $target(id)
}
}
/if DEBUG /echo Leaving FindAggroTarget...
/return
| ==============================================================
Sub FindTarget
/if DEBUG /echo Entering FindTarget...
| make sure we have nothing targeted
/press esc
| routine to find the closest, non-engaged mob from our list
| returns nothing, but ClosestMobID will be set to the mob to engage. Keeps looking until it finds a target.
:StartFindTarget
| reset the distance and ID of closest mob
/varset ClosestMobDist cHuntDistance
/varset ClosestMobID 0
/varset HaveTarget 0
| go thru the list of mobs we want to hunt and find the closest one that isn't being engaged.
/for MobArrayIndex 1 to @MobArraySize
/target npc nopcnear cAntiKSRadius notid InvalidTargetID @MobArray(@MobArrayIndex)
/if DEBUG {
/if $target()=="TRUE" {
/echo Looking for @Mobarray(@MobArrayIndex), found $target(name,clean) (id: $target(id)), Distance: $target(distance)
}
}
| check to make sure we targeted something
/if $target()=="FALSE" /goto :SkipMob
| if the target is not full life, someone else is probably fighting it, skip it
/if n $target(hp,pct)!=100 {
/if DEBUG /echo Target is not full life, skipping.
/varset InvalidTargetID $target(id)
/goto :SkipMob
}
| see if this mob is closer than the last mob we checked
/if n $target(distance)<@ClosestMobDist {
/if DEBUG {
/echo $target(name) is closer than our former target, switching.
}
/varset ClosestMobID $target(id)
/varset ClosestMobDist $target(distance)
/varset InvalidTargetID 0
/varset HaveTarget 1
}
:SkipMob
/next MobArrayIndex
| if we didn't find a target, start over
/if n @HaveTarget!=1 /goto :StartFindTarget
| re-target whichever mob was closest
/target id @ClosestMobID
:EndFindTarget
/if DEBUG /echo Leaving FindTarget...
/return
| ==============================================================
Sub MoveToTarget
/if DEBUG /echo Entering MoveToTarget...
| moves us to the currently target, stops once we are within our cAtkRange
:KeepMoving
| constantly look for a closer target
/call FindTarget
/call CheckForObst
| check to make sure our target is still alive
/if $target()=="FALSE" {
/if DEBUG /echo Our target died before we got to it, finding a new one.
/sendkey up up
/varset HaveTarget 0
/goto :EndMoveToTarget
}
| check to make sure our target is still full life, if not someone is probably fighting it
/if n $target(hp,pct)!=100 {
/if DEBUG /echo Our target started losing hp before we got to it, finding a new one.
/sendkey up up
/varset InvalidTargetID $target(id)
/varset HaveTarget 0
/goto :EndMoveToTarget
}
/face loc $target(y), $target(x)
/sendkey down up
| check to see if we are close enough yet
/if n $target(distance)<=cAtkRange {
/if DEBUG /echo In range of target, stop moving.
/sendkey up up
/goto :EndMoveToTarget
}
/goto :KeepMoving
:EndMoveToTarget
/if DEBUG /echo Leaving MoveToTarget...
/return
| ==============================================================
Sub KillTarget
/if DEBUG /echo Entering KillTarget...
| check to make sure our target is still alive
/if $target()=="FALSE" {
/if DEBUG /echo Our target died before we attacked it, finding a new one.
/varset InvalidTargetID 0
/varset HaveTarget 0
/goto :EndKillTarget
}
| check to make sure our target is still full life, if not someone is probably fighting it
/if n $target(hp,pct)!=100 {
/if DEBUG /echo Our target started losing hp before we attacked it, finding a new one.
/varset InvalidTargetID $target(id)
/varset HaveTarget 0
/goto :EndKillTarget
}
| make sure our target doesnt have a target, if it does then it's attacking someone, skip it
/assist
/delay 5
/if DEBUG /echo Our target's ID=@ClosestMobID, assisted target's ID=$target(id)
| check the assisted target's id, then check its name. if the name contains "corpse", then
| our original target should be considered valid.
/if n $target(id)!=@ClosestMobID /if n $instr(corpse,$target(name))==-1 {
/if DEBUG /echo Our target had a living target, it must've been fighting someone, skip it.
/varset InvalidTargetID $target(id)
/varset HaveTarget 0
/goto :EndKillTarget
}
| send our pet in
/pet attack
| wait until mob is dead, if it starts to flee, follow it
:MainCombatLoop
/call CastSpells
:FollowMob
| check to see if the mob is getting away from us, if so follow
/if n $target(distance)>cAtkRange {
/if DEBUG /echo Target moved away from us, following.
/face
/sendkey down up
} else {
/face
/sendkey up up
}
| check to see if the mob is getting too close to us, if so back off
/if n $target(distance)<cTooCloseRange {
/if DEBUG /echo Target getting too close to us, backing away.
/face
/sendkey down down
} else {
/face
/sendkey up down
}
| if we lose our target while attacking it, then the mob died.
/if $target()=="FALSE" /goto :EndKillTarget
/goto :MainCombatLoop
:EndKillTarget
| make sure our pet follows us
/pet follow
| make sure we stop moving
/sendkey up up
/sendkey up down
/if DEBUG /echo Leaving KillTarget...
/return
| ==============================================================
Sub LootTarget
:StartLootTarget
/if DEBUG /echo Entering LootTarget...
| target the corpse of the mob we just killed
/target id @ClosestMobID
| move up to it
/face
:CheckCorpseDistance
/call CheckForObst
/if n $target(distance)>15 {
/face
/sendkey down up
/goto :CheckCorpseDistance
} else {
/sendkey up up
}
| open the loot window
/loot
/delay 2s
| check each slot (0-7) to see if its something we want to keep
/for LootSlot 0 to 7
/click left corpse @LootSlot
/delay 1s
| if there is nothing on the cursor, then we are out of loots, stop the loop
/if "$cursor()"=="NULL" /goto :EndLootTarget
/if DEBUG /echo Checking loot slot #@LootSlot: $cursor(name)
| check whats on our cursor against the list of things we DONT want to keep
/for LootArrayIndex 1 to @DontLootArraySize
/if "$cursor(name)"=="@DontLootArray(@LootArrayIndex)" {
/if DEBUG /echo $cursor(name) matches @DontLootArray(@LootArrayIndex), destroying.
/click left destroy
/delay 1s
/goto :NextLoot
}
/next LootArrayIndex
| check whats on our cursor against the list of things we want to keep
/for LootArrayIndex 1 to @LootArraySize
/if "$cursor(name)"~~"@LootArray(@LootArrayIndex)" {
/if DEBUG /echo $cursor(name) matches @LootArray(@LootArrayIndex), keeping.
/click left auto
/delay 1s
/goto :NextLoot
}
/next LootArrayIndex
| if we make it to here, it means that the loot didnt match anything in our list
| so, we destroy the object.
/if DEBUG /echo $cursor(name) doesn't match anything in our list, destroying.
/click left destroy
/delay 1s
:NextLoot
/next LootSlot
:EndLootTarget
/press esc
/varset HaveTarget 0
| if our bags are full, its time to stop hunting and go sell. For now, end the macro.
| /if n $freeinv(space)==0 /varset BagsFull 1
| /if DEBUG /echo Inventory space remaining: $freeinv(space) slots.
/if DEBUG /echo Leaving LootTarget...
/return
| ==============================================================
Sub CastSpells
/if DEBUG /echo Entering CastSpells...
:StartSpells
| see if we have mana to spare
/if n $char(mana,pct)<20 /goto :SkipSpells
| decide which spell to cast
/if n $char(buff,"SelfShieldSpell")==0 {
/if DEBUG /echo Trying to cast "SelfShieldSpell".
/call NoFizzleCast "SelfShieldSpell"
/if DEBUG /echo Delay time is: $int($calc($spell("SelfShieldSpell",casttime)*10+5))
/delay $int($calc($spell("SelfShieldSpell",casttime)*10+5))
/goto :StartSpells
}
| check to see if we have a pet up
/if n $char(pet)!=0 {
| check to see if we need to heal our pet.
/if n $spawn($char(pet),hp,pct)<50 {
/if DEBUG /echo Trying to cast "PetHealSpell".
/target id $char(pet)
/call NoFizzleCast "PetHealSpell"
/if DEBUG /echo Delay time is: $int($calc($spell("PetHealSpell",casttime)*10+5))
/delay $int($calc($spell("PetHealSpell",casttime)*10+5))
/goto :StartSpells
}
| check to see if we need to buff our pet
/if n @PetHasteStatus==0 {
/if DEBUG /echo Trying to cast "PetBuffSpell".
/target id $char(pet)
/call NoFizzleCast "PetBuffSpell"
/if DEBUG /echo Delay time is: $int($calc($spell("PetBuffSpell",casttime)*10+5))
/delay $int($calc($spell("PetBuffSpell",casttime)*10+5))
/varset PetHasteStatus 1
/goto :StartSpells
}
}
:SkipSpells
/target id @ClosestMobID
/if DEBUG /echo Leaving CastSpells...
/return
| ==============================================================
Sub NoFizzleCast
| make sure we dont get passed a null spell name
/if "@Param0"!="" {
:NoFizzleCastStart
/varset FizzleFlag 0
| check to make sure we have mana to cast this spell
/if n $char(mana,cur)<$spell("@Param0",mana) /goto :NoFizzleCastEnd
/cast "@Param0"
/doevents Fizzle
| if we fizzled, try to cast again
/if n @FizzleFlag==1 /goto :NoFizzleCastStart
}
:NoFizzleCastEnd
/return
| ==============================================================
Sub CheckForObst
/if n $char(x)==@LastPosX /if n $char(y)==@LastPosY {
/varadd ObstCount 1
} else {
/varset ObstCount 0
}
/varset LastPosX $char(x)
/varset LastPosY $char(y)
/if n @ObstCount>3 {
/call GoAroundObst
}
/return
| ==============================================================
Sub GoAroundObst
/if DEBUG /echo Entering GoAroundObst...
| back up some
/sendkey up up
/sendkey down down
/delay 1s
/sendkey up down
| go left or right a bit, randomly
/if n $rand(2)==1 {
/sendkey down left
/delay 5
/sendkey up left
} else {
/sendkey down right
/delay 5
/sendkey up right
}
| move forward a bit
/sendkey down up
/delay 1s
/sendkey up up
/if DEBUG /echo Leaving GoAroundObst...
/return
| EVENTS =======================================================
Sub Event_PetHasteDown
/varset PetHasteStatus 0
/return
Sub Event_Fizzle
/varset FizzleFlag 1
/return 