Converting the Following to make it suitable for a necro

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

Moderator: MacroQuest Developers

WeeWillyWinkie
decaying skeleton
decaying skeleton
Posts: 2
Joined: Thu Aug 26, 2004 11:52 am
Location: North Pole - Working with Santa
Contact:

Converting the Following to make it suitable for a necro

Post by WeeWillyWinkie » Thu Aug 26, 2004 12:12 pm

Hi guys,

I am not new to macroing, but I am new to using MQ2. I used to use another program in several different games and could script it fairly well. It was called XUnleased. Decided to try this one as people say it is better for EQ. However, I need some input on this program before I strat writing.

First, I need to know how to make the follwoing script, the BeastHunter script, suitable for a Necromancer. I have already pondered out that I need to chage the spell names and I can do that fairly simply. What I need to know is in the follwowing script that the other person wrote where and how can I add a snippet for meditation and its syntax and where and how can I add a snippet for waiting for my pet to heal and its syntax. Also, since Necros dont get buffs except for one, can I remove the code in the buffing section down to a single line containg that buff?

THanks in advance for the help.
WWW

|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 target
| /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 "/squelch /echo"
|-- The Deepest debugging - will spam a lot. Enable: "/echo", Disable: "/squelch /echo"
#define DEBUG_3 "/squelch /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 500
|-- 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 40

|-- 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 False
|-- How far do we want to run?
#define RESTLESS_RANGE 200
|-- 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 False

|-- Should we allways pull to the same spot?
#define PULL_TO_HOMEPOINT False
|-- What spell should we use to pull ?
#define PULL_TO_HOME_SPELL_NAME "Sicken"
|-- What spellgem slot should we use?
#define PULL_TO_HOME_SPELL_GEM 1
|-- 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 Zehkes"
|-- Favorite gem spot for the pet (1-8)
#define PET_GEM 7
|-- 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 True
|-- Only slow mobs above a certain level
#define SLOW_ABOVE_LEVEL 36
|-- What slow spell
#define SLOW_SPELL "Sha's Lethargy"
|-- Favorite gem spot for the slow (1-8)
#define SLOW_GEM 2

|-- 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 80
|-- Prevent nuking low lvls, they arent worth it
#define NUKE_ABOVE_LEVEL 30
|-- Name of nuke spell
#define NUKE_SPELL "Ice Shard"
|-- Favorite gem spot for the nuke (1-8)
#define NUKE_GEM 1

|-- How low on health should I be before I heal myself (noncombat)
#define HEAL_BELOW_PCT 85
|-- Name of healing spell
#define HEAL_SPELL "Healing"
|-- Favorite gem spot for the heal (1-8)
#define HEAL_GEM 4
|-- 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 5

|-- What is the minimum mana I should have, sit down and med if below
#define MIN_MANA_BEFORE_MEDITATE 30



|----------------------------------------------------------------------------
|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[6] string outer
/varset MyBuffs[1] "Spirit of Wolf|8"
/varset MyBuffs[2] "Chloroplast|6"
/varset MyBuffs[3] "Deftness|4"
/varset MyBuffs[4] "Furious Strength|4"
/varset MyBuffs[5] "Spiritual Radiance|3"
/varset MyBuffs[6] "Frenzy|6"

|Critical buffs to be kept up on self (max 15) - cast during fight
/declare CritBuffs[1] string outer
/varset CritBuffs[1] "Spirit of Wolf|8"

|Buffs to be kept up on petf (max 15) - "Buff" or "Buff|GemSlot"
/declare PetBuffs[4] string outer
/varset PetBuffs[1] "Spirit of Wolf|8"
/varset PetBuffs[2] "Bond of the Wild|3"
/varset PetBuffs[3] "Spirit of the Storm|6"
/varset PetBuffs[4] "Deftness|4"

|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
:PetBackOff
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 :PetBackOff
:donelooping

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

/goto :PetBackOff
}


|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 corps
Being an elf I have most of the year to play EQ....aint life just grand!

Shenlon
a ghoul
a ghoul
Posts: 103
Joined: Fri Jul 30, 2004 8:02 am

Post by Shenlon » Thu Aug 26, 2004 12:23 pm

First off, I'd like to say that I am working on the same thing at the moment. Secondly, I'd suggest you use the code tags when you are displaying code, otherwise most people won't even look at it. Thirdly if you're converting a macro, it might help more to link to the post that the macro was originally posted from. Fourth, RTFM. Not trying to be rude here, but as far as converting goes it really isn't all that hard especially when there are a few good necro macros already out there. Fifth, use search, just posting here asking for someone to help you without searching is like playing Russian Roulette minus the empty chamber(s). As I said before there are a couple good necro macros available, look at them and take all the pieces of each macro you like, put them together, write whatever "patch" code you need to ge tthe result you want and then voila you have a macro.

WeeWillyWinkie
decaying skeleton
decaying skeleton
Posts: 2
Joined: Thu Aug 26, 2004 11:52 am
Location: North Pole - Working with Santa
Contact:

Post by WeeWillyWinkie » Thu Aug 26, 2004 1:00 pm

THank you for the VERY helpful criticism! I am also glad you posted your modified script so I could look at it and learn how to write my own so I wouldnt have to "bother" you with any posts asking for help.

I DID do a search and came up empty. Not one showed up as a good working Necro Hunting script for this version of MacroQuest.

Also, I didnt ask for you to write the damn code for me, just point me in the direction of the two snippets I ask for or post the ones you wrote. I just need to know how it should look when you want to meditate and how to wait for your pet to heal. I will incorporate it in there myself.

I love when people flame you for trying to learn how to write it yourself. I could have just trolled and possibly found what I needed but then I wouldnt have learned anything except how to cut and paste.
Being an elf I have most of the year to play EQ....aint life just grand!

JP5
a lesser mummy
a lesser mummy
Posts: 70
Joined: Tue Jul 06, 2004 10:32 pm

Post by JP5 » Thu Aug 26, 2004 1:03 pm

Post finished and tested macros in Macro Depot 3.0

Post macros you need help with in "Macro Help"

User avatar
aChallenged1
a grimling bloodguard
a grimling bloodguard
Posts: 1804
Joined: Mon Jun 28, 2004 10:12 pm

Post by aChallenged1 » Thu Aug 26, 2004 1:46 pm

See those pretty boxes above the text entry window? Now, do you see the one marked Code? Great, use it next time. Click once before you paste in your code and again after you finish. It will look something like this...

Code: Select all

This is where code belongs, within a the code brackets so that everything gets the right indentations and is easy to pick out from anything else that is typed around it.

Why did I put this here, because after reading the first response you didn't go back and fix it.  USE THE FUCKING CODE BRACKETS!
Fuck writing MQ2 macros. Go with IS scripts; IS Rules!

User avatar
Cr4zyb4rd
Plugins Czar
Posts: 1449
Joined: Tue Jul 20, 2004 11:46 am

Post by Cr4zyb4rd » Thu Aug 26, 2004 1:55 pm

I'd suggest reading Shenlon's post again, then reading Shenlon's post again. When that sinks in, read Shenlon's post, and then perhaps glance at Shenlon's post, as I feel it might help. Also, I'd make a new account with a new name, since I doubt you're capable of the ammount of pride-swallowing that would be required for you to make an apology post convincing enough for most of us to try to help you again.

Shenlon
a ghoul
a ghoul
Posts: 103
Joined: Fri Jul 30, 2004 8:02 am

Post by Shenlon » Thu Aug 26, 2004 4:15 pm

Not really sure why I should bother doing this, but since you searched oh so hard and couldn't find ANY necro macros, I guess just looking down the front page of the Macro Depot was beyond your ability.

http://macroquest2.com/phpBB2/viewtopic.php?t=8538

http://macroquest2.com/phpBB2/viewtopic.php?t=8663

Damn those look aweful close to me, especially since i've been TESTING them and have almost gotten my version of the same thing that you're trying to do to work since this morning. I've never written a macro before in my life, I've been using MQ for about a month now. I'm nothing special, but I do know that the answers are already out there 99% of the time. If you'd read this board for more than a day you would realize that anyone that posts weak shit like that is going to elicit the same response.

If you want flame free help then donate and join the VIP pool. Or, at the very least post it in the CORRECT FUCKING FORUM.

hiipii
a ghoul
a ghoul
Posts: 93
Joined: Sat Jun 19, 2004 5:01 pm

Post by hiipii » Thu Aug 26, 2004 8:18 pm

Gonna have to follow everyone else here and say first of all use code brackets ( i for one can't even read the code without code brackets lol ). And secondly post in the right forum, this post should be in macro help.