Adjusted the macro again though i really dont know if i did it right so im going to include the entire mac and the msg i get. All your help has been much apreciated. Wish i knew more about this stuff...
|TODO:
|Stuckness on strafe. Stop strafing till next target
|Degree to pull. 360degrees = everyting
|Pull to homepoint - sometimes cast twice to upull the mob!
| Waiting for mobs doesnt allways work on slow mobs
| Natural Beastlord Hunter Macro c
| nbh.mac
| Author : wolf5
| Version : v1.1.9 - 2004-07-11
| Useage : /macro nbh Legionnaire
| /macro nbh target1|target2|target3|...|targetn
| Description : This macro will run your character around killing any mobs
| matching your targets.
| Then it will loot either all items or none.
| Features:
|
|- Pet allways up, and no further than a defined distance away before being
| autosummoned
|
|- Keep pet buffed (noncombat)
|
|- Keep myself buffed (noncombat)
|
|- During combat, keep myself buffed with critical spells (SoW)låæcghbnhi
|
|- Target from targetlist within a given radius (default 499) - rumor has it
| targetting above 500 gets logged by SoE ? But search for mobs outside
| this range if chosen.
|
|- Run towards target using a selfwritten /face to allow a "slack" of a given
| degree. Ie 45 degree means I wont turn 100% directly towards target
| but within 45 degrees making it look a little more natural.
|
|- Initiate attack at a given range: send in pet, slow, nuke, run to attack
|
|- Let pet tank if:
| Healthdifference in Pct between pet and myself differs more than a
| given percentage.
| If no mobs nearby.
| Only if pet is close.
|- When pet tanks:
| Nuke if mana above a given pct.
| Keep pet updated with buffs and heals.
| Keep self updated. ælæ
| When health of pet reaches same Pct as self, attack again.
|
|- Option to strafe around target to let pet attack the targets back.
|
|- Run to mob-corpse and loot if the mob was above a given level
| (to prevent looting low lvl greens)
|
|- Keep track of the items looted during the runtime of the macro.
|
|- Allways using pet as a reference on me being attacked. If pet has something
| targeted, help it.
|
|- Aquiring a new target:
| After about 6 attempts with a delay between and there is still no target,
| run back to homespot (where the script started) and sit down.
| Restless option. If nothing happens at homepoint, sooner or later we
| run to a random point nearby looking for mobs.
|
|-If my health should drops below a certain %, heal till I'm above
| (after fights or when pet tanks)
|
|-Alarm sound (/beep) if health gets below a certain level so prompt you to get
| back to the computer.
|
|-If pet health drops below a certain %, heal pet
| (after fights or when pet tanks)
|
|-If mana drops below a certain %, sit down and med till it's above.
|
|-Choice of sending in pet before or after slow.
|
|-Only nuke if we got excess mana (mana over a given %)
|
|-Obstacle avoidance. If we are stuck while running to a target, back off
| random length and turn left or right randomly. Setting the default
| "slack" degree of the /face sub to a high degree to prevent running
| into the same obstacle again, in effect letting u run in
| an arc around the obstacle.
|
|-Attack no matter what if mob is below a certain % - dont back off.
|
|-Max Range from homepoint to prevent running amokk on the map.
|
|-Option to pull to homespot all the time.
|-Option to allways run to homespot after a fight.
|
|-2 methods to select mobs. Either by distance or by mobname first.
|
|-Dont pull mobs that are closer to a NPC or PC than a defined radius
|
|--------------------------------------------------------------------------------
#include spellcast.inc
#turbo 40
|Events for counting the money we loot.
|#event Receive "#*#You receive#*#"
#event CashLoot "You receive #1#"
|#event CashLoot2 "#*#You receive #*#"
|-- The normal debug - for normal play. Enable: "/echo", Disable: "/squelch /echo"
#define DEBUG_1 "/echo"
|-- Deeper debugging - enable when trying to find bugs. Enable: "/echo", Disable: "/squelch
/echo"
#define DEBUG_2 "/echo"
|-- The Deepest debugging - will spam a lot. Enable: "/echo", Disable: "/squelch /echo"
#define DEBUG_3 "/echo"
|-- Destroys Silver if you have more than the given amount! 0=disable
#define DESTROY_GOLD_IF_ABOVE 0
|-- Destroys Silver if you have more than the given amount! 0=disable
#define DESTROY_SILVER_IF_ABOVE 500
|-- Destroys Copper if you have more than the given amount! 0=disable
#define DESTROY_COPPER_IF_ABOVE 500
|-- The degree we face towards the target, so we dont run dead on.
#define THE_SLACK_DEGREE 20
|-- The max search radius for a mob (will not use /target untill closer than SEARCH_RADIUS).
#define MAXIMUM_SEARCH_RADIUS 3000
|-- The max TARGET radius for a mob (above 500 could be bad, SoE logging?).
#define TARGET_RADIUS 499
|-- Define the Z radius on our pulls. To prevent pulling to far up or below (floors?)
#define Z_RADIUS_ON_PULLS 250
|-- How far is the max range we want to go from homespot?
#define MAX_RANGE_FROM_HOMEPOINT 3000
|-- Target method. 1-Prioritize mob sequence or 2-Prioritize distance
#define TARGET_METHOD 2
|-- The closest a another PC can be to a target
#define AVOID_PEOPLE_RADIUS 300
|-- The closest a another NPC can be to a target - Only attack single mobs?
#define AVOID_CROWDED_RADIUS 1
|-- Also loot items?
#define LOOT_ITEMS True
|-- Loot all items?
#define LOOT_ALL_ITEMS False
|-- Destroy the remaining items -not in use atm
#define LOOT_ABOVE_LEVEL 1
|-- Keep loot record - Will display how much you have looted + items
#define LOOT_KEEP_RECORD True
|-- No matter other settings. If the value of the item is above this, GET IT! (Value is in
copper)
|-- Not nodrop
#define LOOT_NORMAL_ITEMS_IF_VALUE_IS_ABOVE 10000
|-- No matter other settings. If the value of the item is above this and stackable, GET IT!
(Value is in copper)
|-- Not lore, not nodrop
#define LOOT_STACKABLE_ITEMS_IF_VALUE_IS_ABOVE 1000
|#define LOOT_DESTROY False
|-- What lvl should the mob be before we bother looting it
|-- At what range do we slow/send in pet?
#define INITIALIZE_ATTACK_RANGE 150
|-- If we dont get any target for a while at homepoint, run somewhere else
#define ARE_WE_RESTLESS True
|-- How far do we want to run?
#define RESTLESS_RANGE 500
|-- We dont want to stay back when the mob is fleeing, now do we :-)
#define FORCE_ATTACK_WHEN_MOB_BELOW 30
|-- Do we want to stay on opposite side than the pet on the mob
#define STRAFE_TO_BACK True
|-- If the PCT of your pet and yourself differs from this number, let pet tank
#define LET_PET_TANK_IF_DIFFERENCE 8
|-- If there are more than 1 mob within this radius, just tank on
#define IGNORE_PETTANK_IF_MOBS_RADIUS 100
|-- Allways return to homepoint | can be li'l buggy?
#define RETURN_TO_HOMEPOINT True
|-- Should we allways pull to the same spot?
#define PULL_TO_HOMEPOINT True
|-- What spell should we use to pull ?
#define PULL_TO_HOME_SPELL_NAME "Sha's Advantage"
|-- What spellgem slot should we use?
#define PULL_TO_HOME_SPELL_GEM 2
|-- Should I tell pet to back off while running back. False for those who have /pet hold
#define PULL_TO_HOME_PETBACKOFF True
|-- If we dont have a pet, should we allways summon one?
#define ALLWAYS_HAVE_PET True
|-- What pet do we want?
#define PET_SPELL "Spirit of Khurenz"
|-- Favorite gem spot for the pet (1-8)
#define PET_GEM 1
|-- How far off should the pet be before we summon it?
#define MAX_PET_RANGE_BEFORE_SUMMON 500
|-- Should we slow when pulling?
#define DO_SLOW_ON_PULL True
|-- Should we send in pet before or after we slow?
#define SEND_PET_BEFORE_SLOW False
|-- Only slow mobs above a certain level
#define SLOW_ABOVE_LEVEL 25
|-- What slow spell
#define SLOW_SPELL "Sha's Advantage"
|-- Favorite gem spot for the slow (1-8)
#define SLOW_GEM 6
|-- Should we nuke when we pull?
#define DO_NUKE_ON_PULL False
|-- Prevent nuking when mana below % to not waste mana
#define NUKE_ABOVE_MANA_PCT 50
|-- Prevent nuking low lvls, they arent worth it
#define NUKE_ABOVE_LEVEL 30
|-- Name of nuke spell
#define NUKE_SPELL "Blizzard Blast"
|-- Favorite gem spot for the nuke (1-8)
#define NUKE_GEM 8
|-- How low on health should I be before I heal myself (noncombat)
#define HEAL_BELOW_PCT 50
|-- Name of healing spell
#define HEAL_SPELL "Greater Healing"
|-- Favorite gem spot for the heal (1-8)
#define HEAL_GEM 5
|-- If your health gets below this lvl start /beep'ing
#define ALARM_HEALTH_BELOW_PCT 40
|-- How low on health should the pet be before we heal it (noncombat)
#define HEAL_PET_BELOW_PCT 50
|-- Name of pet healing spell
#define HEAL_PET_SPELL "Sha's Restoration"
|-- Favorite gem spot for the petheal (1-8)
#define HEAL_PET_GEM 7
|-- What is the minimum mana I should have, sit down and med if below
#define MIN_MANA_BEFORE_MEDITATE 50
|----------------------------------------------------------------------------
|SUB: Main - Declarations and Initialization
|----------------------------------------------------------------------------
Sub Main
|Log to output file "/spew on" or turn it off "/spew off" (MacroQuest\logs\DebugSpew.log)
/spew on
|Buffs to be kept up on self (max 15) - "Buff" or "Buff|GemSlot"
/declare MyBuffs[2] string outer
/varset MyBuffs[1] "Spiritual Purity|3"
/varset MyBuffs[2] "Alacrity|4"
|Critical buffs to be kept up on self (max 15) - cast during fight
/declare CritBuffs[1] string outer
/varset CritBuffs[1] "Spiritual Purity|3"
|Buffs to be kept up on petf (max 15) - "Buff" or "Buff|GemSlot"
/declare PetBuffs[2] string outer
/varset PetBuffs[1] "Spirit of the Storm|2"
/varset PetBuffs[2] "Sha's Ferocity|1"
|Loot items we want to loot
/declare LootList[6] string outer
/varset LootList[1] "Fine Steel Short"
/varset LootList[2] "Fine Steel Long"
/varset LootList[3] "Fine Steel Rapier"
/varset LootList[4] "Fine Steel Scimitar"
/varset LootList[5] "silk"
/varset LootList[6] "venom"
DEBUG_1 Starting macro
|Group of locked target data
/declare TargetLevel int outer |Level of Target
/declare TargetName string outer |Name of Target
/declare TargetID int outer |ID of Target
|Data to detect if we are stuck
/declare oldposx float outer
/declare oldposy float outer
/varcalc oldposx ${Me.X} +100
/varcalc oldposy ${Me.Y} +100
|A counter for the Move subs
/declare keypressercnt1 int outer 0
/declare keypressercnt2 int outer 0
/declare keypressercnt3 int outer 0
/declare keypressercnt4 int outer 0
/declare keypressercnt5 int outer 0
/declare keypressercnt6 int outer 0
|Variable to prevent stuckfix after casting a spell
/declare JustCastedSpell bool outer
|/declare tmp string outer |Just a tmp string
|/declare tmp2 string outer |Just a tmp string
/declare lootcnt int outer 0 |Loot counter
/declare homeX float outer ${Me.X} |Our homepoint
/declare homeY float outer ${Me.Y} |Our homepoint
/declare homeZ float outer ${Me.Z} |Our homepoint
/declare rndX float outer ${Me.X} |Rnd
/declare rndY float outer ${Me.Y} |Rnd
DEBUG_2 Homepoint: ${Me.X} ${Me.Y}
/declare leftdown bool outer |Are we turning left
/declare rightdown bool outer |Are we turning right
/declare strafeleftdown bool outer |Are we turning left
/declare straferightdown bool outer |Are we turning right
/declare forwarddown bool outer |Are we moving forward
/declare backdown bool outer |Are we moving backwards
/declare stickontarget bool outer |Bool to prevent us from leaving
/declare stickontarget_2 bool outer |Bool to prevent us from leaving (pull_to_home)
/declare initiatedattack bool outer |Bool to only initiate once
/declare theslack int outer THE_SLACK_DEGREE |the global slack on FaceTarget
/declare waitcounter int outer 0 |How many times shall we get no target found before we
do something (run/wait/gohome)
/declare tickcnt int outer 0 |Tickcounter. 1 delay = 1 tick
/declare aqtargcnt int outer 0 |Aquiretarget ticker
/declare ignoreclearcnt int outer 0 |IgnoreList clearing counter
|Getting targets - Made it for the String.Arg not working - works now tho, but I keep the
code
/declare numbtargs int outer
/if (!${Defined[Param0]}) {
DEBUG_1 No targets chosen! Exiting.
/endmacro
}
|Make "targets" array (global) with list over the mobs we want
/call SplitString targets "${Param0}" "|"
/declare i int local
/for i 1 to ${targets.Size}
DEBUG_2 Target defined (${i}): "${targets[${i}]}"
/next i
|Any secondary targets? (in conjunction with TARGET_METHOD = 2
|Will only go for those if there are none of the primary targets.
/if (${Defined[Param1]}) {
/call SplitString targets2 "${Param1}" "|"
/for i 1 to ${targets2.Size}
DEBUG_2 Secondary Target defined (${i}): "${targets2[${i}]}"
/next i
}
/call MainSub
DEBUG_1 Exited normally!
/return
|----------------------------------------------------------------------------
|SUB: MainSub - The main sub
|----------------------------------------------------------------------------
Sub MainSub
/declare cnt1 int local 0
/if (${Bool[PULL_TO_HOMEPOINT]}) {
/if ( ${Me.Pet.ID} ) /pet guard
}
/if (${Bool[PULL_TO_HOMEPOINT]} && ${Me.Pet.ID}) {
|Allways run to pet before getting new target
DEBUG_1 Moving to pet before we start pulling
/target id ${Me.Pet.ID}
/call RunToSpotTarget
/varset homeX ${Me.X}
/varset homeY ${Me.Y}
}
|The main loop. After an attack we go here to aquire a new target
:NewTarget
/varset stickontarget False
/varset stickontarget_2 False
/varset initiatedattack False
DEBUG_1 NewTarget loop (Tick: ${tickcnt})
/call ClearIgnoreList
/call StopAllMovement "MainSub"
/if (${Bool[PULL_TO_HOMEPOINT]} && ${Me.Pet.ID}) {
|Allways run to pet before getting new target
/target id ${Me.Pet.ID}
/call RunToSpotTarget
|/varset homeX ${Me.X}
|/varset homeY ${Me.Y}
}
/call FaceTarget
:Repeater
DEBUG_2 NewTarget loop2
/call ClearTarget "repeater1"
/call StopAttack
|/call SetTarget
/if ( ${Target.Type.Equal[NPC]} ) {
/call ClearTarget "repeater2"
}
|Assist pet to see if he is busy
/call AssistPet "mainsub"
/if ( ${Target.Type.Equal["Corpse"]} || !${Target.ID} ) {
/call ClearTarget "repeater3"
} else {
/call SetTarget "mainsub"
}
/if ( ${Target.ID}==${Me.Pet.ID} ) {
/call ClearTarget "mainsub1"
}
/if ( ${Spawn[${TargetID}].Type.Equal["NPC"]} ) {
DEBUG_1 Assisting pet: ${Spawn[${TargetID}].CleanName}
/varset waitcounter 0
/varset stickontarget True
|Allready in action, so dont initiate stuff
/varset initiatedattack True
DEBUG_1 PetTarget Locked! ${Spawn[${TargetID}].CleanName}
/call StandUp
/goto :MainAttackLoop
}
/call ClearTarget "mainsub2"
|:FirstTime
/squelch /if ( ${Target.ID} ) /target clear
/call DowntimeWork
/if ( ${Macro.Return}==0 ) {
DEBUG_2 Return to top after DowntimeWork
/goto :NewTarget
}
/call AquireTarget
/if ( ${Macro.Return}==0 ) {
DEBUG_1 No targets found. Waiting.
/call StopAllMovement "MS1"
/call SitDown
/goto :Repeater
} else {
DEBUG_1 Target Name: ${Spawn[${TargetID}].CleanName}, Lvl:${Spawn[${TargetID}].Level},
Class: ${Spawn[${TargetID}].Class}
}
|The main attack loop - Here all the attacking will take place
:MainAttackLoop
|Have we lost our target?
/if ( ${TargetID}==0 ) {
/goto :NewTarget
}
|Warn if I am low on health
/if ( ${Me.PctHPs}<ALARM_HEALTH_BELOW_PCT ) {
/if ( ${Math.Rand[20]} < 3 ) /beep
/popup "ALARM ALARM. HEALTH IS LOW!!!"
}
|Paranoia. Any GM's in zone? abort macro!
/call CheckGM
|If we get attacked while running to our target, we just got ourselves a new one instead
/if ( ${Spawn[${TargetID}].Distance} > TARGET_RADIUS ) {
|If we get attack on the way, assist pet every 4 sec
/varcalc cnt1 ${cnt1}+1
/if ( ${cnt1} > 40 ) {
/call AssistPet "mainattackloop"
/if ( ${Target.ID} && ${Target.Type.Equal[NPC]}) {
/call ClearTarget "MAL"
/call SetTarget "mainattack"
/goto :NewTarget
}
/varset cnt1 0
}
}
|If we have not targeted our locked target and within target range, target
/if ( !${Target.ID} && ${Spawn[${TargetID}].Distance} < TARGET_RADIUS ) {
DEBUG_1 Targetting the mob: ${Spawn[${TargetID}].CleanName} (${TargetID}) Distance:
${Spawn[${TargetID}].Distance}
/call TargetMainTarget
|/target id ${TargetID}
}
|}
/varset waitcounter 0
|If i got no main target is gone
/if (!${Spawn[${TargetID}].ID} || ${Spawn[${TargetID}].Type.Equal[CORPSE]} ) {
DEBUG_1 Ending fight, No Target
/call StopAllMovement "MS2"
/call DoTheLooting ${TargetID}
DEBUG_2 Looting Done
/goto :NewTarget
}
|If target is a corpse
/if ( ${Spawn[${TargetID}].Type.Equal[CORPSE]} ) {
DEBUG_1 Ending fight, Target is a Corpse
/call StopAllMovement "MS3"
/call DoTheLooting ${TargetID}
/call StopAllMovement "MainSub"
/call Delay 10
/call Delay ${Math.Rand[20]}
/goto :NewTarget
}
/call MainAttack ${TargetID}
|/if ( ${Macro.Return}==0 && !${Spawn[${TargetID}].ID} ) /goto :NewTarget
/if ( ${Macro.Return}==0 ) {
DEBUG_2 MainAttack Return: ${Macro.Return}
/goto :NewTarget
}
|Remove pet from target if it is. just in case
|/call UntargetPet
|/call TargetMainTarget
/goto :MainAttackLoop
:EndMacro
/endmacro
/return
|----------------------------------------------------------------------------
|SUB: UntargetPet - If pet is targeted, untarget it.
|----------------------------------------------------------------------------
Sub UntargetPet
/if ( ${Me.Pet.ID} ) {
/if ( ${Target.Name.Equal[${Me.Pet.Name}]} ) {
/squelch /if ( ${Target.ID} ) /target clear
|/call ClearTarget "untargetpet"
}
}
/return
|----------------------------------------------------------------------------
|SUB: CheckToAbortAttack - Sees if we have to abort our attack
|----------------------------------------------------------------------------
Sub CheckToAbortAttack(int targID)
DEBUG_1 >Checking if we should abort...
|To prevent circle running on this intensive part
/call MoveLeftStop
/call MoveRightStop
|/target id ${targID}
/call TargetMainTarget
/call Delay 1
|If target has a speed above 100 assume its running (someone has it)
| Wont work very well if snared
/if ( ${Spawn[${targID}].Speed}>150 ) {
DEBUG_1 Ending fight, Target running (aggroed on someone else)
/pet back
/call AddToNoList IgnoreList ${targID}
|/call ClearTarget
/return 0
}
|Check if mob is heading in a direction of a close by PC
/call DetectNPCtowardsPC ${targID}
/if (${Macro.Return}==0) {
DEBUG_1 NPC seems to be heading for someone else! Aborting.
/pet back
/call AddToNoList IgnoreList ${targID}
|/call ClearTarget
/return 0
}
|Check if anyone is closer than me
/call AnyoneCloser ${targID}
/if (${Macro.Return}==0) {
DEBUG_1 Someone is closer than me! Aborting. ${Spawn[${targID}].CleanName} (${targID})
/pet back
/call AddToNoList IgnoreList ${targID}
|/call ClearTarget
/return 0
}
|If this target is below 100% and I targeted it manually it is probably just snatched
before me
|/if ( ${Target.ID}==${Spawn[${TargetID}].ID} && !${stickontarget} ) {
/if ( !${stickontarget} ) {
/if ( ${Spawn[${targID}].PctHPs}<100 ) {
DEBUG_1 Ending fight, Target(${Spawn[${TargetID}].PctHPs}%) < 100%
/pet back
|/call ClearTarget "checkabort"
/return 0
}
}
|Checking to see if the area is to mob-crowdy
/if ( AVOID_CROWDED_RADIUS>0 ) {
|Is there any other mob very close by the target?
/call AnyNPCCloserTo ${targID} AVOID_CROWDED_RADIUS
/if ( ${Macro.Return}==0 ) {
DEBUG_1 To crowdy at Target: ${Spawn[${targID}].CleanName} (${targID}) (
${Spawn[${targID}].Distance} )
/return 0
}
}
/return 1
|----------------------------------------------------------------------------
|SUB: MainAttack - Handles the fighting
|----------------------------------------------------------------------------
Sub MainAttack(int targID)
/declare timeoutcnt1 int local 0
|Any VERY IMPORTANT buffs worn off? ie SoW for fleeing - dont do it to often
/if ( ${Math.Rand[50]}<=2 ) /call MaintainCriticalSelfBuffs
|Check to see if its time to check for new target, as we are moving in. (approx every 2
second + processing time)
/if ( !${initiatedattack} ) {
/declare tt int local
/varcalc tt ${tickcnt} / 20
/declare oID int local
/varset oID ${TargetID}
/if ( ${tt}>${aqtargcnt} ) {
|To prevent doing circles on heavy targetsearching
/call MoveLeftStop
/call MoveRightStop
DEBUG_1 >Checking if any target is closer than the current:
${Spawn[${TargetID}].CleanName} (${TargetID}) ${Spawn[${TargetID}].Distance}...
/varset aqtargcnt ${tt}
/call TargetIt
/if (${oID}<>${TargetID}) {
/if ( ${TargetID}==0 ) {
DEBUG_1 Target Lost
/return 0
}
DEBUG_1 Target switched to: ${Spawn[${TargetID}].CleanName}, Lvl:
${Spawn[${TargetID}].Level}, Class: ${Spawn[${TargetID}].Class}
}
}
}
|PULLING TO HOMEPOINT ATTACKING
/if (${Bool[PULL_TO_HOMEPOINT]}) {
/if ( ${Spawn[${targID}].Distance}<INITIALIZE_ATTACK_RANGE && !${initiatedattack})
{
/call CheckToAbortAttack ${targID}
/if ( ${Macro.Return}==0 ) /return 0
|Start pulling, and run home
/target id ${targID}
/declare TargetDist int local
/declare i int local
|Face homewards before starting to pull
/face nolook loc ${homeY},${homeX}
:TryAgain
|Return if no active target
/if (!${Target.ID} && !${Target.Type.Equal[NPC]}) /return 1
|Check the distance...
/if ( ${Spell["PULL_TO_HOME_SPELL_NAME"].Range}<${Target.Distance}) /return
1
|Start to pull
DEBUG_1 Casting pullspell ("PULL_TO_HOME_SPELL_NAME") (${Target.ID})
/call Cast "PULL_TO_HOME_SPELL_NAME" gemPULL_TO_HOME_SPELL_GEM
/varcalc tickcnt ${tickcnt} +
${Math.Calc[${Spell["PULL_TO_HOME_SPELL_NAME"].MyCastTime}*10]}
/call Delay 1
|Checking to see if target is heading my way. Or we have failed the pull.
/call NPCtowardsME ${targID}
|If the mob is outside attackrange+buffer and it is not headed in out
direction, presume pull to have failed. Try again
/if ( ${Macro.Return}==1 &&
${Target.Distance}>${Math.Calc[${Target.MaxRange}+50]} ) /goto :TryAgain
/varset JustCastedSpell true
/varset initiatedattack true
/varset stickontarget true
|/face fast nolook loc ${homeY},${homeX}
/varset keypressercnt1 100
/call MoveForward

etBackOff
DEBUG_3 Distance to mob: ${Spawn[${TargetID}].Distance}
/for i 0 to 10
DEBUG_3 Stepping homewards
/call StepToSpot ${homeX} ${homeY} 20
/if ( ${Macro.Return}==0 ) /goto :donelooping
/call Delay 1
/next i
|Dont outrun the mob!
:WaitForMob
/if ( ${Spawn[${TargetID}].Distance}>200 ) {
DEBUG_2 Waiting for the Mob. Distance: ${Spawn[${TargetID}].Distance} > 300
/call StopAllMovement "AquireTarget0"
/varset keypressercnt1 100
|/target clear
|/call Delay 1
|/target id ${TargetID}
/call Delay 2
/varcalc timeoutcnt1 ${timeoutcnt1}+1
/if (${timeoutcnt1}>50) {
DEBUG_1 Timeout waiting for mob!
/call ClearTarget
/return 1
}
/goto :WaitForMob
}
/call MoveForward
/if (${Bool[PULL_TO_HOME_PETBACKOFF]}) /pet back
/goto

etBackOff
:donelooping
DEBUG_2 we are home. turn around
/call StopAllMovement "AquireTarget1"
/if ( ${Target.ID} ) /face nolook
/varset waitcounter 0
/return 1
/goto

etBackOff
}
|NORMAL ATTACKING
} else {
|Initialize the attack - send pet, slow, nuke - Only initiate once per mob
/if ( ${Spawn[${targID}].Distance}<INITIALIZE_ATTACK_RANGE && !${initiatedattack})
{
/call CheckToAbortAttack ${targID}
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_1 ** INITIATING ATTACK: ${Target.CleanName}
/varset initiatedattack True
|Send in pet before slow?
/if (${Bool[SEND_PET_BEFORE_SLOW]}) {
DEBUG_2 Asking pet to attack ${Target.CleanName} (${Target.Name})!
/pet attack
DEBUG_3 Pet attacking ${Target.CleanName}!
}
|Do the Slowing
/if (${Bool[DO_SLOW_ON_PULL]}) {
/if ( ${Target.Level}>SLOW_ABOVE_LEVEL) {
/if ( ${Target.Type.Equal[NPC]} ) {
DEBUG_1 Casting slow!
/call Cast "SLOW_SPELL" gemSLOW_GEM
/varcalc tickcnt ${tickcnt} +
${Math.Calc[${Spell["SLOW_SPELL"].MyCastTime}*10]}
/varset JustCastedSpell true
|To prevent stuckdetecting
/call MoveForward "MainAttack 00"
/call Delay 10
}
}
}
/if (!${Bool[SEND_PET_BEFORE_SLOW]}) {
/if ( ${Target.PctHPs}<100 ) {
|Someone else grabbed it before I got the chance to charge (maybe
during slow)
/pet back
/call Delay 1
/pet back
/call Delay 1
DEBUG_1 Ending fight, Not Attacking + Target ${Target.PctHPs}% < 100%
before Slow went in
/call AddToNoList IgnoreList ${targID}
/call ClearTarget "attackloop1"
/return 0
}
}
|If we havent allready sent the pet, now is the time
/if (!${Bool[SEND_PET_BEFORE_SLOW]}) {
/pet attack
DEBUG_2 Pet attacking ${Target.CleanName}!
}
|Do a nuke before attacking?
/call DoTheNuke
/varset stickontarget True
DEBUG_1 Target Locked! ${Target.CleanName}
}
}
|If we are not attacking and the health of the mob is below 100% asume someone else has it.
back off!
/if ( ${Spawn[${TargetID}].Distance}>200) {
|/if ( ${Target.ID}==${Spawn[${targID}].ID} && !${stickontarget} ) {
/if ( !${stickontarget} ) {
/if (!${Me.Combat} && ${Spawn[${TargetID}].PctHPs}<100) {
/call AddToNoList IgnoreList ${targID}
/pet back
DEBUG_1 Ending fight, Not Attacking + Target(${Spawn[${TargetID}].PctHPs}%) <
100%
/call ClearTarget "attackloop2"
/return 0
}
}
}
|Either attack or move towards target
/declare TargDist float local
|/varset TargDist ${Math.Calc[ ${Target.DistancePredict} - (${Target.MaxRangeTo}/2) ]}
|/varset TargDist ${Math.Calc[ ${Spawn[${targID}].DistancePredict} -
(${Spawn[${targID}].MaxRangeTo}/2) ]}
/varset TargDist ${Math.Calc[ ${Spawn[${targID}].Distance} -
(${Spawn[${targID}].MaxRangeTo}/2) ]}
|/varset TargDist ${Math.Calc[ ${Spawn[${targID}].Distance} -
(${Spawn[${targID}].MaxRangeTo}) ]}
|When we are doing the meleeing!
|DEBUG_3 Distance to target: ${TargDist}
/if ( ${TargDist} < 0 ) {
|Target our target if are fighting it and its not targeted yet
/if ( !${Target.ID} ) /call TargetMainTarget
/call MoveForwardStop "MainAttack"
/call StartAttack
/if ( ${Me.AbilityReady["kick"]} ) /doability "kick"
|Should we back off? - not target is moving/fleeing
/if ( ${Target.PctHPs}>FORCE_ATTACK_WHEN_MOB_BELOW && ${Spawn[${targID}].Speed}==0 ) {
DEBUG_3 BACK OFF FOR PET ${Target.ID} - ${Spawn[${targID}].ID} - ${targID}
/call BackoffForPet ${Target.ID}
|Target the main target and continue
/call TargetMainTarget
/call StandUp
}
|Keep face towards mob
/call FaceTarget
|Strafe around to back of mob (opposite of pet)?
/if (${Bool[STRAFE_TO_BACK]} && ${Target.Speed}==0 && ${Me.Pet.Distance}<100 ) {
/declare mydeg float local
/declare petdeg float local
/declare targdeg float local
/varcalc mydeg ${Heading[${Target.Y},${Target.X}].DegreesCCW}
/varset petdeg ${Me.Pet.Heading.DegreesCCW}
/if ( ${petdeg<180} ) {
/varcalc targdeg ${petdeg} + 180
} else {
/varcalc targdeg ${petdeg} - 180
}
/if ( ${targdeg} > 360 ) /varcalc targdeg ${targdeg} - 360
/if ( ${targdeg} < 0 ) /varcalc targdeg ${targdeg} + 360
/call StepStrafeToAngleTarget ${targdeg}
}
|/return 1
} else {
|If we are allways pulling home. Only run when getting target
/if (${Bool[PULL_TO_HOMEPOINT]}) {
/if ( !${initiatedattack}) {
/call StepToSpot ${Spawn[${targID}].X} ${Spawn[${targID}].Y}
${Math.Calc[${Spawn[${targID}].MaxRangeTo}/2]}
} else {
|Head towards the mob when its very close. Or we are allready in
combat (backoffrompet)
/if ( ${TargDist} < 20 || ${stickontarget_2}) {
|/pet attack
|DEBUG_3 /if ( ${TargDist} < 50 || ${stickontarget})
/call StepToSpot ${Spawn[${targID}].X} ${Spawn[${targID}].Y}
${Math.Calc[${Spawn[${targID}].MaxRangeTo}/2]}
/varset stickontarget_2 True
} else {
|/varset stickontarget True
}
|If pet is engaging, get it to back off
/if (${Bool[PULL_TO_HOME_PETBACKOFF]}) {
/if ( !${Me.Combat} && ${Me.Pet.Speed}>0 ) {
/pet back
/call Delay 3
}
}
/if (${Defined[timeoutcounter1]}) {
/varcalc timeoutcounter1 ${timeoutcounter1} + 1
} else {
/declare timeoutcounter1 int outer 0
}
/if ( ${Me.Combat} ) {
/varset timeoutcounter1 0
}
/if ( ${timeoutcounter1}>400 ) {
/varset timeoutcounter1 0
|/if ( ${Target.Distance}<500 ) {
| DEBUG_1 Seems the mob is not coming. Going to get it
again!
|
| /varset initiatedattack false
|} else {
DEBUG_1 Seems the mob is not coming. Scrapping it...
/return 0
|}
}
}
|Checking for timeout
/if (${Defined[justcastspellcounter]}) {
/varcalc justcastspellcounter ${justcastspellcounter} + 1
} else {
/declare justcastspellcounter int outer 0
}
} else {
|Non PULL_TO_HOMEPOINT code
/call StepToSpot ${Spawn[${targID}].X} ${Spawn[${targID}].Y}
${Math.Calc[${Spawn[${targID}].MaxRangeTo}/2]}
}
}
/return 1
|----------------------------------------------------------------------------
|SUB: MainAttack - Handles the fighting
|----------------------------------------------------------------------------
Sub DowntimeWork
/call StopAllMovement "DowntimeWork"
| Make sure critical spells are up
/call MaintainCriticalSelfBuffs
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 1. Critical Buffs Checked
| Check if we are low on mana or health. Heal or sit down if low
/call CheckMana
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 2. Mana Checked
/call HealMyself
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 3. Health Checked
| Make sure pet is up + all its buffs are on it
/call HealPet
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 4. Pet Health Checked
/call MaintainPetBuffs
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 5. Pet Buffs Checked
| Make sure all buffs on self are up
/call MaintainSelfBuffs
/if ( ${Macro.Return}==0 ) /return 0
DEBUG_2 6. Buffs Checked
/return 1
|----------------------------------------------------------------------------
|SUB: AquireTarget - Finding a target
|----------------------------------------------------------------------------
Sub AquireTarget
/declare TargetDist float local |Distance to Target
/declare tmpint int local
/declare rand int local |random var
/varset TargetDist ${Math.Distance[${homeY},${homeX},0:${Me.Y},${Me.X},0]}
/if ( ${TargetDist}>40 ) /varcalc waitcounter ${waitcounter}+1
|/if ( !${Target.ID} ) {
/if ( !${Spawn[${TargetID}].ID} ) {
/call ClearTarget "aquiretarget"
DEBUG_3 Do target
|Target distance to run home if we are outside max range
/varset TargetDist ${Math.Distance[${homeY},${homeX},0:${Me.Y},${Me.X},0]}
/if ( ${TargetDist}>MAX_RANGE_FROM_HOMEPOINT || ${waitcounter}>3) {
DEBUG_1 Running home.
|Run to homespot
:Retarget0
/for rand 0 to 10
/call StepToSpot ${homeX} ${homeY} 40
/call Delay 1
/next rand
|/call MoveForwardStop
/varset TargetDist ${Math.Distance[${homeY},${homeX},0:${Me.Y},${Me.X},0]}
|If we are inside the maxrange border/2, search for a mob
/if ( ${TargetDist}<${Math.Calc[MAX_RANGE_FROM_HOMEPOINT/2]} ) {
/call TargetIt AT1
/if ( ${Spawn[${TargetID}].ID} ) /return 1
} else {
|If we get attack on the way, assist pet
/call AssistPet "aquiretarget"
/if ( ${Target.ID} && ${Target.Type.Equal[NPC]}) {
/return 0
}
}
|We are home
/if ( ${TargetDist}<40 ) {
/call StopAllMovement "AquireTarget1"
/varset waitcounter 0
/return 0
}
/goto :Retarget0
|/if ( !${Spawn[${TargetID}].ID} ) /goto :Retarget0
}
/call TargetIt AT2
/if ( ${Spawn[${TargetID}].ID} ) /return 1
|Calculating distance home
/varset TargetDist ${Math.Distance[${homeY},${homeX},0:${Me.Y},${Me.X},0]}
|Should we allways return to homepoint after a fight?
/if ( ${Bool[RETURN_TO_HOMEPOINT]} ) {
/if ( ${TargetDist}>40 ) {
DEBUG_1 Running home again
/call RunToSpot ${homeX} ${homeY} 40
/varset waitcounter 0
/return 0
}
}
/if ( ${Bool[ARE_WE_RESTLESS]} ) {
/if ( ${TargetDist}<40 ) {
/varcalc waitcounter ${waitcounter}-1
/if ( ${waitcounter}<-5 ) {
DEBUG_1 We are restless. Running a bit. ${rndX}, ${rndY}
:Retarget1
/for tmpint 0 to 10
/call StepToSpot ${rndX} ${rndY} 40
/call Delay 1
/next tmpint
/call TargetIt AT3
/if ( ${Spawn[${TargetID}].ID} ) /return 1
/varset TargetDist ${Math.Distance[${rndY},${rndX},0:${Me.Y},${Me.X},0]}
/if ( ${TargetDist}<40 ) {
/call StopAllMovement "AquireTarget2"
/varset waitcounter 0
/if ( ${Math.Rand[10]} < 5 ) {
/varset rndX ${Math.Calc[ ${Me.X} + ${Math.Rand[RESTLESS_RANGE]} *
2 ]}
} else {
/varset rndX ${Math.Calc[ ${Me.X} - ${Math.Rand[RESTLESS_RANGE]} *
2 ]}
}
/if ( ${Math.Rand[10]} < 5 ) {
/varset rndY ${Math.Calc[ ${Me.Y} + ${Math.Rand[RESTLESS_RANGE]} *
2 ]}
} else {
/varset rndY ${Math.Calc[ ${Me.Y} - ${Math.Rand[RESTLESS_RANGE]} *
2 ]}
}
/return 0
}
|/if ( !${Target.ID} ) /goto :Retarget1
|/if ( !${Spawn[${TargetID}].ID} )
/goto :Retarget1
}
}
}
/if ( ${waitcounter}==1 ) /call SitDown
/call StopAllMovement "MainSub"
/call Delay 40
/return 0
}
/if ( ${TargetID}<=0 ) /return 0
|DEBUG_3 Target: ${TargetID} - ${Spawn[${TargetID}].CleanName} ${Spawn[${TargetID}].Level}
${Spawn[${TargetID}].Class} (${Spawn[${TargetID}].Name})
/return 1
|----------------------------------------------------------------------------
|SUB: DoTheNuke - Nuke target
|----------------------------------------------------------------------------
Sub DoTheNuke
/if (${Bool[DO_NUKE_ON_PULL]}) {
/if ( ${Me.PctMana}>NUKE_ABOVE_MANA_PCT) {
/if ( ${Target.Level}>SLOW_ABOVE_LEVEL && ${Target.Type.Equal[NPC]}) {
/call Cast "NUKE_SPELL" gem1
/varcalc tickcnt ${tickcnt} +
${Math.Calc[${Spell["NUKE_SPELL"].MyCastTime}*10]}
/varset JustCastedSpell true
}
}
}
/return
|----------------------------------------------------------------------------
|SUB: BackoffFromMob - Backing off outside the mob range
|----------------------------------------------------------------------------
Sub BackoffFromMob(int targID)
/declare TargDist float local
|Move off the double range
/varcalc TargDist ${Spawn[${targID}].Distance} - (${Spawn[${targID}].MaxRange}*1.3)
|DEBUG_3 backoff mob
|DEBUG_3 backoff/moveback ${TargDist} should be less than 0
/if ( ${TargDist}<0) /call MoveBack "BackoffFromMob"
|Move back out of range
:BackOff1
/varcalc TargDist ${Spawn[${targID}].Distance} - (${Spawn[${targID}].MaxRange}*1.3)
|DEBUG_3 BackOff1 ${TargDist} --- ${Spawn[${targID}].Distance}
/if ( !${Target.ID} ) /return
|If we are not out of range (times 2)
/if ( ${TargDist}<0) {
|DEBUG_3 BackOff: ${TargDist} --- ${Spawn[${targID}].Distance}
(${Spawn[${targID}].MaxRange}*1.3)
/call Delay 1
/call FaceTarget
/goto :BackOff1
}
|DEBUG_3 stop attack
/call StopAttack
/call StopAllMovement "BackoffFromMob"
|DEBUG_3 backoff mob done
/return
|----------------------------------------------------------------------------
|SUB: BackoffForPet - Backing off when its the pets turn to tank
|----------------------------------------------------------------------------
Sub BackoffForPet(int targID)
/if ( ${Math.Calc[ ${Me.Pet.PctHPs} - ${Me.PctHPs} ]} > LET_PET_TANK_IF_DIFFERENCE ) {
/declare cnt int local
|/declare themobname string local
|/varset themobname ${Target.Name}
|What to do while idle - This will be main loop til we help pet again
:Repeat1
|We cant back off if pet is out of range
/if ( ${Me.Pet.Distance}>150 ) {
|DEBUG_3 Pet out of range
/call StartAttack
/return
}
|If there is more than 1 mob within range, dont back off
/call AnyExtraMobsNearby IGNORE_PETTANK_IF_MOBS_RADIUS
/if ( ${Macro.Return}>1 ) {
DEBUG_2 Cannot back off. ${Macro.Return} mobs close (including our target).
/call MoveLeftStop
/call MoveRightStop
/call StartAttack
/return
}
|DEBUG_3 Number of mobs close by is: ${Macro.Return}
/call BackoffFromMob ${targID}
/varcalc cnt ${cnt}+1
|/varset mymobID ${Target.ID}
/if ( ${cnt}==1 ) /squelch /if ( ${Target.ID} ) /target clear
|/if ( ${cnt}==1 ) /call ClearTarget "backoffforpet"
|Check once per second if something is happening
/if ( ${cnt}>5 ) {
|If spawn is moving, attack again!
|DEBUG_3 Pet range ${Me.Pet.Distance}
/if ( ${Spawn[${targID}].Speed}>10 ) {
DEBUG_1 Target moving or fleeing. Attacking.
/call StartAttack
/return
}
|DEBUG_3 Letting pet tank some!
/call SitDown
DEBUG_1 Main target(${Spawn[${targID}].CleanName}) at ${Spawn[${targID}].PctHPs}%
|/if ( !${Target.ID} ) /return
|/target ${themobname}]}
/if ( !${Spawn[${targID}].ID} ) {
DEBUG_1 Returning because pet has killed the target!
/return
}
/if ( ${Spawn[${targID}].PctHPs}<FORCE_ATTACK_WHEN_MOB_BELOW ) {
DEBUG_1 Mob is so low I can maul him dead now!
/call StartAttack
/return
}
/call Delay 3
/call AssistPet "backoffforpet"
|Pet on wrong target? put it on the right one
/if ( ${Target.ID}!=${targID} ) {
/call TargetMainTarget
/call Delay 1
/pet back
/call Delay 1
/pet attack
}
|Nuke some?
/call DoTheNuke
|Maintain my important buffs
/call MaintainCriticalSelfBuffs
|Maintain pet buffs
/call MaintainPetBuffs
|Heal myself if needed
/call HealMyself
|Will wait until the pet reaches same % of health as self
/varset cnt 0
}
/call Delay 1
|If pet still has more HPs than me just loop
/if ( ${Me.Pet.PctHPs} > ${Me.PctHPs} ) /goto :Repeat1
DEBUG_1 Pet health equal to mine! Back to action!
/call StartAttack
}
/return
|----------------------------------------------------------------------------
|SUB: AnyExtraMobsNearby - Checks if there is a second mob within radius
|----------------------------------------------------------------------------
Sub AnyExtraMobsNearby(int radius)
/declare i int local
/declare c int local 0
/for i 1 to 5
/if ( ${NearestSpawn[${i}].Distance} < ${radius} &&
${NearestSpawn[${i}].Type.Equal[NPC]}) {
|DEBUG_3 ${i} - ${NearestSpawn[${i}].CleanName} ${NearestSpawn[${i}].Distance}
/varcalc c ${c}+1
/call Delay 2
}
/next i
/if ( ${c}>0 ) /return ${c}
/return 0
|----------------------------------------------------------------------------
|SUB: StartAttack
|----------------------------------------------------------------------------
Sub StartAttack
/if ( !${Me.Combat} ) /attack on
/varset theslack THE_SLACK_DEGREE
/return
|----------------------------------------------------------------------------
|SUB: StopAttack
|----------------------------------------------------------------------------
Sub StopAttack
/if ( ${Me.Combat} ) /attack off
/return
|----------------------------------------------------------------------------
|SUB: AssistPet - Target pet, assist it and wait for a target
|----------------------------------------------------------------------------
Sub AssistPet
DEBUG_3 AssistPet called from ${Param0}
/declare cnt int local
/if ( !${Target.ID} ) {
/if ( ${Me.Pet.ID} ) {
/target ${Me.Pet.CleanName}
:GetTarget1
/if ( !${Me.Pet.CleanName.Equal[${Target.CleanName}]} ) {
/call Delay 1
/goto :GetTarget1
|DEBUG_3 waiting for pet: ${Target.CleanName}
}
/assist
:GetTarget2
/if ( ${Me.Pet.CleanName.Equal[${Target.CleanName}]} ) {
/varcalc cnt ${cnt}+1
/call Delay 1
/if ( ${cnt}>10 ) {
/squelch /if ( ${Target.ID} ) /target clear
|/call ClearTarget "assistpet"
/return
|DEBUG_3 waiting for target: ${Target.CleanName}
}
/goto :GetTarget2
}
|DEBUG_3 Pet is targetting: ${Target.CleanName}
}
}
/return
|----------------------------------------------------------------------------
|SUB: SummonPet - Summon pet if farther away than the defined range
|----------------------------------------------------------------------------
Sub SummonPet(bool force)
/if ( MAX_PET_RANGE_BEFORE_SUMMON>0 || ${force}) {
/if ( ${Me.Pet.Distance}>MAX_PET_RANGE_BEFORE_SUMMON || ${force}) {
DEBUG_1 Summoning pet. Its range is ${Me.Pet.Distance}
/call Cast "Summon Companion" gem7
/varcalc tickcnt ${tickcnt} + ${Math.Calc[${Spell["Summon
Companion"].MyCastTime}*10]}
/varset JustCastedSpell true
/call Delay 10
/if (${Bool[PULL_TO_HOMEPOINT]}) {
/if ( ${Me.Pet.ID} ) /pet guard
}
/return 0
}
}
/return 1
|----------------------------------------------------------------------------
|SUB: HealPet - Heal pet if needed
|----------------------------------------------------------------------------
Sub HealPet
|Heal pet?
/if ( ${Me.Pet.PctHPs}<HEAL_PET_BELOW_PCT ) {
/if ( ${Me.Pet.ID} ) {
/target ${Me.Pet.CleanName}
/call Cast "HEAL_PET_SPELL" gemHEAL_PET_GEM
/varcalc tickcnt ${tickcnt} +
${Math.Calc[${Spell["HEAL_PET_SPELL"].MyCastTime}*10]}
/varset JustCastedSpell true
/if ( !${Me.Sitting} ) /sit
/return 0
}
}
/return 1
|----------------------------------------------------------------------------
|SUB: HealMyself
|----------------------------------------------------------------------------
Sub HealMyself
|Heal?
/if ( ${Me.PctHPs}<HEAL_BELOW_PCT ) {
/call StopAllMovement "HealMyself"
/if ( !${Target.Name.Equal[${Me.Name}]} ) /target ${Me.Name}
/call Cast "HEAL_SPELL" gemHEAL_GEM
/varcalc tickcnt ${tickcnt} + ${Math.Calc[${Spell["HEAL_SPELL"].MyCastTime}*10]}
/varset JustCastedSpell true
/if ( !${Me.Sitting} ) /sit
/squelch /if ( ${Target.ID} ) /target clear
|/call ClearTarget "healmyself"
/call Delay 1
/return 0
}
/return 1
|----------------------------------------------------------------------------
|SUB: CheckMana
|----------------------------------------------------------------------------
Sub CheckMana
/if ( ${Me.PctHPs}<HEAL_BELOW_PCT && ${Me.PctMana}<50 ) {
/call Delay 10
/if ( !${Me.Sitting} ) /sit
/return 0
}
|Meditate?
/if ( ${Me.PctMana}<MIN_MANA_BEFORE_MEDITATE ) {
DEBUG_1 Mana below MIN_MANA_BEFORE_MEDITATE%. Meditating.
/if ( !${Me.Sitting} ) /sit
/declare i int local
/squelch /if ( ${Target.ID} ) /target clear
|/call ClearTarget "checkmana"
/for i 1 to 10
/call Delay 10
/if ( ${Target.ID} ) /return 1
/next i
/if ( ${Me.PctMana}<MIN_MANA_BEFORE_MEDITATE ) {
/return 0
}
DEBUG_2 Mana OK now.
}
/return 1
|----------------------------------------------------------------------------
|SUB: MaintainPetBuffs - Heal pet and keep its buffs up
|----------------------------------------------------------------------------
Sub MaintainPetBuffs
|If we have pet
/if ( ${Bool[ALLWAYS_HAVE_PET]} ) {
/if ( !${Me.Pet.ID} ) {
DEBUG_1 Creating new pet
/call Cast "PET_SPELL" gemPET_GEM
/varcalc tickcnt ${tickcnt} + ${Math.Calc[${Spell["PET_SPELL"].MyCastTime}*10]}
/varset JustCastedSpell true
/if (${Bool[PULL_TO_HOMEPOINT]}) {
/if ( ${Me.Pet.ID} ) /pet guard
}
/return 0
}
/call SummonPet
|KeepUpBuffsOnPet
/declare iCount int local
/declare t string local
/for iCount 1 to ${PetBuffs.Size}
/call SplitString tmp_tmp ${PetBuffs[${iCount}]} "|"
/varset t ${Me.PetBuff[${tmp_tmp[1]}]}
/if ( ${t.Equal[NULL]} ) {
/if ( !${Target.ID}!=${Me.Pet.ID} ) {
/target ${Me.Pet.Name}
}
|If we are to far away to buff pet - run to it
/if (${Spell["${tmp_tmp[1]}"].Range}<${Me.Pet.Distance}) {
|Echo pet to far away to buff. Summoning it, or running to it
/if ( ${Me.Pet.Distance}>200 ) {
/call SummonPet true
} else {
/call RunToSpotTarget
}
/pet follow
}
|Cast with gemselection or default
/if ( ${tmp_tmp.Size}>1 ) {
DEBUG_2 Trying to cast "${tmp_tmp[1]}"
/call Cast "${tmp_tmp[1]}" gem${tmp_tmp[2]}
/varset JustCastedSpell true
} else {
DEBUG_2 Trying to cast "${tmp_tmp[1]}"
/call Cast "${tmp_tmp[1]}"
/varset JustCastedSpell true
}
/varcalc tickcnt ${tickcnt} +
${Math.Calc[${Spell["${tmp_tmp[1]}"].MyCastTime}*10]}
|/delay 5
|Return to top - so we dont keep buffing if being attacked
/return 0
}
/next iCount
/return 1
|----------------------------------------------------------------------------
|SUB: MaintainSelfBuffs - Keep buffs up
|----------------------------------------------------------------------------
Sub MaintainSelfBuffs
|KeepUpBuffsOnMe
/declare iCount int local
/declare t string local
/for iCount 1 to ${MyBuffs.Size}
/call SplitString tmp_tmp ${MyBuffs[${iCount}]} "|"
/varset t ${Me.Buff[${tmp_tmp[1]}]}
/if ( ${t.Equal[NULL]} ) {
/if ( !${Target.ID}!=${Me.ID} ) {
/target ${Me.Name}
}
|Cast with gemselection or default
/if ( ${tmp_tmp.Size}>1 ) {
DEBUG_2 Trying to cast "${tmp_tmp[1]}"
/call Cast "${tmp_tmp[1]}" gem${tmp_tmp[2]}
/varset JustCastedSpell true
} else {
DEBUG_2 Trying to cast "${tmp_tmp[1]}"
/call Cast "${tmp_tmp[1]}"
/varset JustCastedSpell true
}
/varcalc tickcnt ${tickcnt} + ${Math.Calc[${Spell["${tmp_tmp[1]}"].MyCastTime}*10]}
|Return to top - so we dont keep buffing if being attacked
/return 0
}
/next iCount
/return 1
|----------------------------------------------------------------------------
|SUB: MaintainCriticalSelfBuffs - Keep buffs up, even during fight - SOW!
|----------------------------------------------------------------------------
Sub MaintainCriticalSelfBuffs
|KeepUpCriticalBuffsOnMe
/declare iCount int local
/declare t string local
/for iCount 1 to ${CritBuffs.Size}
/call SplitString tmp_tmp ${CritBuffs[${iCount}]} "|"
/varset t ${Me.Buff[${tmp_tmp[1]}]}
/if ( ${t.Equal[NULL]} ) {
DEBUG_3 Infinity loop? Echoing debug data...
DEBUG_3 ${t},${tmp_tmp[1]},${Me.Buff[${tmp_tmp[1]}]}
/if ( !${Target.ID}!=${Me.ID} ) {
/target ${Me.Name}
}
|Cast with gemselection or default
/if ( ${tmp_tmp.Size}>1 ) {
|DEBUG_3 Cast "${tmp_tmp[1]}" gem${tmp_tmp[2]}
/call Cast "${tmp_tmp[1]}" gem${tmp_tmp[2]}
/varset JustCastedSpell true
} else {
|DEBUG_3 Cast "${tmp_tmp[1]}"
/call Cast "${tmp_tmp[1]}"
/varset JustCastedSpell true
}
/varcalc tickcnt ${tickcnt} + ${Math.Calc[${Spell["${tmp_tmp[1]}"].MyCastTime}*10]}
|/delay 5
|Return to top - so we dont keep buffing if being attacked
/return 0
}
/next iCount
/return 1
|----------------------------------------------------------------------------
|SUB: FaceTarget - Corpse or NPC
|----------------------------------------------------------------------------
Sub FaceTarget
/if ( !${Target.ID} || ${Target.Type.Equal[PC]} || ${Target.Type.Equal[Pet]} ) {
DEBUG_3 Stopping facing
/call StopAllMovement "FaceTarget"
/return
}
|DEBUG_3 Face ON
/call FacePosition ${Target.X} ${Target.Y}
/return ${Macro.Return}
|----------------------------------------------------------------------------
|SUB: FacePosition
|----------------------------------------------------------------------------
Sub FacePosition(float X, float Y)
|Face towards target - At a 'slack' degrees slack - more natural
/call WhatDirection ${X} ${Y} ${theslack}
/if ( ${Macro.Return}==0 ) {
/call MoveLeft "FacePosition"
}
/if ( ${Macro.Return}==1 ) {
/call MoveRight "FacePosition"
}
/if ( ${Macro.Return}==-1 ) {
/call MoveLeftStop "FacePosition"
/call MoveRightStop "FacePosition"
/return 0
}
/return 1
|----------------------------------------------------------------------------
|SUB: WhatDirection is the target? 0=left, 1=right, -1=dead on (with slack)
|----------------------------------------------------------------------------
Sub WhatDirection(float X, float Y, int slack)
/if (!${Defined[slack]}) /declare slack int local
/declare currdeg int local
/varset currdeg ${Me.Heading.DegreesCCW}
/declare targdeg string local
/varset targdeg ${Heading[${Y},${X}].DegreesCCW}
/if ( ${currdeg}<${targdeg} ) {
/if ( ${Math.Abs[${currdeg}-${targdeg}]} > ${slack} ) {
/if (${Math.Calc[${targdeg}-${currdeg}]} < 180 ) {
/return 0
} else {
/return 1
}
} else {
/return -1
}
} else {
/if ( ${Math.Abs[${targdeg}-${currdeg}]} > ${slack} ) {
/if (${Math.Calc[${currdeg}-${targdeg}]} < 180 ) {
/return 1
} else {
/return 0
}
} else {
/return -1
}
}
/return -1
|----------------------------------------------------------------------------
|SUB: StuckFixTarget
|----------------------------------------------------------------------------
Sub StuckFixTarget
/declare targpct int local
/if ( ${Target.ID} ) {
/if ( ${Target.PctHPs}==100 ) { |To prevent stuckfix during combat
/call StuckFix
/return ${Macro.Return}
}
}
/return
|----------------------------------------------------------------------------
|SUB: StuckFix
|----------------------------------------------------------------------------
Sub StuckFix
/if ( ${forwarddown} ) {
/declare moved float local
/declare rnd int local
|Trying to get out of a spot where we are stuck
/varset moved ${Math.Distance[${oldposy},${oldposx},0:${Me.Y},${Me.X},0]}
|Storing the old position, for next check
|DEBUG_3 ${oldposy},${oldposx} - ${Me.Y},${Me.X} - ${JustCastedSpell}
/varset oldposx ${Me.X}
/varset oldposy ${Me.Y}
/varset rnd ${Math.Rand[1500]}
|Fixes the detection of stuckiness after casting a spell
/if ( ${JustCastedSpell} ) {
/if (${Defined[justcastspellcounter]}) {
/varcalc justcastspellcounter ${justcastspellcounter} + 1
} else {
/declare justcastspellcounter int outer 0
}
/if ( ${justcastspellcounter}>10 ) {
/varset JustCastedSpell false
/varset justcastspellcounter 0
}
/return 1
}
/if ( ${moved}<50 ) {
/if ( ${rnd}<250 ) {
/if ( ${moved}<0.10 ) {
/call MoveForwardStop "StuckFix"
DEBUG_1 Moving around obstacle
/call MoveBack "StuckFix"
/delay ${Math.Rand[15]}
/call MoveRight "StuckFix"
/delay ${Math.Rand[15]}
/call MoveBackStop "StuckFix"
/call MoveRightStop "StuckFix"
/varset theslack 95
/delay ${Math.Rand[15]}
DEBUG_2 Moving forward after obst
/delay 5
/call MoveForward "StuckFix"
/return 0
}
} else /if ( ${rnd}<500 ) {
/if ( ${moved}==0 ) {
/call MoveForwardStop "StuckFix"
DEBUG_1 Moving around obstacle
/call MoveBack "StuckFix"
/delay ${Math.Rand[15]}
/call MoveLeft "StuckFix"
/delay ${Math.Rand[15]}
/call MoveBackStop "StuckFix"
/call MoveLeftStop "StuckFix"
/varset theslack 95
/delay ${Math.Rand[15]}
DEBUG_2 Moving forward after obst
/delay 5
/call MoveForward "StuckFix"
/return 0
}
} else {
|There is a chance to do nothing.
}
}
}
/return 1
|----------------------------------------------------------------------------
|SUB: RunToSpotTarget - Runs to target. Returns when we are at target
|----------------------------------------------------------------------------
Sub RunToSpotTarget
/declare tmp string local
/varset tmp ${Target}
/if ( ${tmp.Equal["NULL"]} ) /return
/call RunToSpot ${Target.X} ${Target.Y} ${Math.Calc[${Target.MaxRangeTo}/2]}
/return
|----------------------------------------------------------------------------
|SUB: RunToSpot - Runs to spot. Returns when we are at spot
|----------------------------------------------------------------------------
Sub RunToSpot(float X, float Y, float howclose)
:RunLoop
/call StepToSpot ${X} ${Y} ${howclose}
/if ( ${Macro.Return}==0 ) /return 1
/goto :RunLoop
/return 1
|----------------------------------------------------------------------------
|SUB: StepToSpot - Runs towards spot. Returns immediately
|----------------------------------------------------------------------------
Sub StepToSpot(float X, float Y, float howclose)
|Immediately stop if me or my pet is targeted
/if ( ${Target.ID}==${Me.ID} || ${Target.ID}==${Me.Pet.ID}) {
DEBUG_3 Am i targeted.
/call StopAllMovement "StepToSpot"
/call StopAttack
/squelch /if ( ${Target.ID} ) /target clear
|/call ClearTarget "steptospot"
/return 1
}
|If slack has been set up to a high number adjust it to come back down to
| the defined number over time
/if ( ${theslack} > THE_SLACK_DEGREE ) {
DEBUG_3 Adjust slack
/varcalc theslack ${theslack}-2
}
/declare TargDist float local |Distance to Target
/varset TargDist ${Math.Distance[${Y},${X},0:${Me.Y},${Me.X},0]}
/if ( ${TargDist}<${howclose} ) {
DEBUG_3 targdist<${howclose} - ${TargDist}<${howclose}
/call StopAllMovement "StepToSpot"
/return 0
}
/call FacePosition ${X} ${Y}
/if ( ${TargDist}>100 ) {
DEBUG_3 targdist>100 - ${TargDist}>100
|Move forward if range is above 100
/call MoveForward "StepToSpot"
} else {
DEBUG_3 targdist<100 - ${TargDist}<100
|Move forward only if we are faced towards the mob
| to prevent a large arc towards the close mob
/if ( ${Macro.Return}==0 ) {
/call MoveForward "StepToSpot"
}
}
/call Delay 1
|Debugging purpose. To prevent to run veeeery long
/if ( ${TargDist} > MAXIMUM_SEARCH_RADIUS ) DEBUG_3 Distance to spot ${X},${Y} =
${TargDist} - slack: ${theslack}
/call StuckFix
/if ( ${Macro.Return}==0 ) {
DEBUG_2 StuckFixed
|/return 0
}
|Checking if we are stuck
/return 1
|----------------------------------------------------------------------------
|SUB: StepToTarget
|----------------------------------------------------------------------------
Sub StepToTarget(float X, float Y)
/call StepToSpot ${Target.X} ${Target.Y} ${Math.Calc[${Target.MaxRangeTo}/2]}
/return
|----------------------------------------------------------------------------
|SUB: DoTheLooting
|----------------------------------------------------------------------------
Sub DoTheLooting(int targID)
DEBUG_1 Going to loot
DEBUG_2 DoTheLooting Target: ${TargetLevel} ${TargetName}'s corpse, ID:${TargetID}
/call StopAllMovement
/if (${TargetLevel}>LOOT_ABOVE_LEVEL) {
|/call TargetMainTarget
/call Delay 3
DEBUG_2 Running to the corpse
/call RunToSpot ${Spawn[${targID}].X} ${Spawn[${targID}].Y}
${Math.Calc[${Spawn[${targID}].MaxRangeTo}/2]}
DEBUG_2 Running done
/if ( ${Spawn[${targID}].Type.Equal["Corpse"]} ) {
/varcalc lootcnt ${lootcnt}+1
DEBUG_1 Looting corpse #${lootcnt}
/call LootMob
/varset theslack THE_SLACK_DEGREE
|/call MoveForward
/doevents
} else {
DEBUG_1 Can't loot a non-corpse!
}
} else {
DEBUG_1 This one is to low lvl. I wont loot it!
/squelch /if ( ${Target.ID} ) /target clear
|/call Clear