necrokite.mac

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

Moderator: MacroQuest Developers

Terramantian
a ghoul
a ghoul
Posts: 120
Joined: Thu May 13, 2004 6:20 pm

necrokite.mac

Post by Terramantian » Sat Aug 28, 2004 1:19 pm

I was bored this morning, so I threw this macro together. It's VERY rough, and very simple, but it works decently by itself and would be a good place to start for someone making a more advanced macro.


It requires: move.inc and spell_routines.inc from the Snippets section.

What it assumes: From your starting point, your kite area will be from that point to 350 units in the direction you are facing, and back, after strafing right 1.5 seconds.

What it does: It identifies and pulls a mob that is fairly close in level to you. It pulls with your snare dot, and if it is resisted you FD and wait til aggro (hopefully) is gone. Then it runs home and starts again. Once a mob is pulled home, it will kite it back and forth along the path, casting a snare dot, a damage dot, and a lifetap, as each is needed. When the mob is at 50% HP, it sends your pet in. Once the mob is dead it will med if necessary and repeat.

What it DOES NOT do: It is not for AFK exping. If you use it in this way, don't be surprised if you come back dead (or fd'd, if you're lucky). It does not detect or handle adds very well. Or pet aggro/death. Or mob running.

What I *might* add: Less hard-coded and more easily configured. Better movement-stopping routines when casting. Additional dot's to cast, etc. Loot sub, if I ever get to a point where it's worthwhile.

What would be useful but I probably will not add: Add avoidance and better pulling system. Better fd management. Any other necro spells, aas, skills, etc, etc.

One last note: I have *very* little time to work on things like this anymore, so I'll probably not update it often at all. Mostly posting in case it helps someone get a start on a better one.

Code: Select all

|Necrokite.mac
|By: Terramantian
|
|Simple auto-pulling and kiting macro for a necromancer.


#turbo
#include spell_routines.inc
#include move.inc

#define PetSpell "Summon Dead"
#define PetHaste "Intensify Death"
#define SnareDOT "Dooming Darkness"
#define DamageDOT "Boil Blood"
#define Lifetap "Spirit Tap"
#define LichSpell "Allure of Death"

#event Hit "#*#YOU for#*#"

Sub Main
   /declare HomeX int outer ${Me.X}
   /declare HomeY int outer ${Me.Y}
   /declare PetHastT timer outer
   /declare SnareT timer outer
   /declare DamageT timer outer
   /declare MOB int outer
   /declare EndX int outer
   /declare EndY int outer
   /declare PetAttacking bool outer

   /if ((${String[${Me.Heading}].Equal[N]}) || (${String[${Me.Heading}].Equal[NNW]}) || (${String[${Me.Heading}].Equal[NNE]})) {
      /varset EndY ${Math.Calc[${Me.Y} + 350]}
      /varset EndX ${Me.X}
   } else /if (${String[${Me.Heading}].Equal[NE]}) {
      /varset EndY ${Math.Calc[${Me.Y} + 240]}
      /varset EndX ${Math.Calc[${Me.X} - 240]}
   } else /if ((${String[${Me.Heading}].Equal[E]}) || (${String[${Me.Heading}].Equal[ENE]}) || (${String[${Me.Heading}].Equal[ESE]})) {
      /varset EndY ${Me.Y}
      /varset EndX ${Math.Calc[${Me.X} - 350]}
   } else /if (${String[${Me.Heading}].Equal[SE]}) {
      /varset EndY ${Math.Calc[${Me.Y} - 240]}
      /varset EndX ${Math.Calc[${Me.X} - 240]}
   } else /if ((${String[${Me.Heading}].Equal[S]}) || (${String[${Me.Heading}].Equal[SSW]}) || (${String[${Me.Heading}].Equal[SSE]})) {
      /varset EndY ${Math.Calc[${Me.Y} - 350]}
      /varset EndX ${Me.X}
   } else /if (${String[${Me.Heading}].Equal[SW]}) {
      /varset EndY ${Math.Calc[${Me.Y} - 240]}
      /varset EndX ${Math.Calc[${Me.X} + 240]}
   } else /if ((${String[${Me.Heading}].Equal[W]}) || (${String[${Me.Heading}].Equal[WNW]}) || (${String[${Me.Heading}].Equal[WSW]})){
      /varset EndY ${Me.Y}
      /varset EndX ${Math.Calc[${Me.X} + 350]}
   } else /if (${String[${Me.Heading}].Equal[NW]}) {
      /varset EndY ${Math.Calc[${Me.Y} - 240]}
      /varset EndX ${Math.Calc[${Me.X} + 240]}
   }      

   /call Initialize

   :Loop
   
   /call PullMob
   /call KiteMob
   /varset PetAttacking 0
|   /call LootMob
   /call Downtime
   /goto :Loop
   
/return

Sub Initialize
   /if (!${Me.Pet.ID}) /call Cast "PetSpell"
   /pet guard here
   /pet taunt
   /call Cast "PetHaste"
   /varset PetHastT ${Math.Calc[${Spell[PetHaste].Duration} * 6]}s
   /call Cast "LichSpell" 
   :MedCheck
   /if (${Me.PctMana} < 70) {
      /if (!${Me.Sitting}) /sit
      /delay 1m (${Me.PctMana} > 80)
      /goto :MedCheck
   }
/return


Sub PullMob
   :PullBegin

   /doevents
   /varset MOB ${Spawn[nopcnear 400 npc range ${Math.Calc[${Me.Level} * .75]} ${Me.Level} radius 1000].ID}
   :TarLoop
   /if ((${Spawn[id ${MOB}].PctHPs} < 100) || (!${String[${Spawn[${MOB}].Type}].Compare["Pet"]})) {	
      /varset MOB ${Spawn[nopcnear 400 npc id ${MOB} range ${Math.Calc[${Me.Level} * .75]} ${Me.Level} radius 1000 next].ID}  
      /goto :TarLoop
   }
   /call MoveToSpawn ${MOB} 120
   /target id ${MOB}
   /assist
   /delay 1s
   /doevents
   /if ((${Target.ID} != ${MOB}) && (${Target.ID} != ${Me.ID})) {
      /call MoveToLoc ${HomeY} ${HomeX}
      /goto :PullBegin
   }
   /if (${Target.PctHPs} < 100) /goto :PullBegin

   /doevents

   /call Cast "SnareDOT"
   /if (!${Macro.Return.Equal[CAST_SUCCESS]}) {
      /call Cast "Feign Death"
      /delay 3m (${Target.Distance} > 100)
      /call MoveToLoc ${HomeY} ${HomeX}
      /goto :PullBegin
   }
   /varset SnareT ${Math.Calc[${Spell[SnareDOT].Duration} * 6]}s
   /call MoveToLocF ${HomeY} ${HomeX} 150
/return

Sub KiteMob
  

   :KiteLoop
   /doevents
   /call MoveToLocF ${EndY} ${EndX} 200
   /if (!${Target.ID}) /return
   /doevents
   /if (${SnareT} <= 200) {
      /call Cast "SnareDOT" 6s
      /if (${Macro.Return.Equal[CAST_SUCCESS]}) /varset SnareT ${Math.Calc[${Spell[SnareDOT].Duration} * 6]}s
   }
   /if (${SnareT} == 0) {
      /echo Snare DOT is not on... FDing and pausing
      /call Cast "Feign Death" 10s
      /if (${Me.Buff[LichSpell].ID}) /notify BuffWindow Buff${Int[${Math.Calc[${Me.Buff[LichSpell].ID}-1]}]} leftmouseup
      /mqpause
   }
   /if ((${Target.Distance} > ${Math.Calc[${Target.Speed} / 4 * ${Spell[Lifetap].MyCastTime}]}) && (${Me.PctHPs} < 80)) {
      /call Cast "Lifetap"
   }
   /if ((${Target.Distance} > ${Math.Calc[${Target.Speed} / 4 * ${Spell[DamageDOT].MyCastTime}]}) && (${DamageT} <= 150)) {
      /call Cast "DamageDOT"
      /if (${Macro.Return.Equal[CAST_SUCCESS]}) /varset DamageT ${Math.Calc[${Spell[DamageDOT].Duration}* 6]}s
   }
   /if ((!${PetAttacking}) && (${Target.PctHPs} < 50)) {
      /pet attack
      /varset PetAttacking 1
   }
   /delay 10s (${Target.Distance} <= 50)
   /face fast nolook
   /if (!${Target.ID}) /return

   /keypress strafe_right hold
   /delay 20
   /keypress strafe_right
   /call MoveToLocF ${HomeY} ${HomeX} 200
   /if (!${Target.ID}) /return
   /doevents
   /if (${SnareT} <= 200) {
      /call Cast "SnareDOT" 12s
      /if (${Macro.Return.Equal[CAST_SUCCESS]}) /varset SnareT ${Math.Calc[${Spell[SnareDOT].Duration} * 6]}s
   }
   /if (${SnareT} == 0) {
      /echo Snare DOT is not on... FDing and pausing
      /call Cast "Feign Death" 10s
      /if (${Me.Buff[LichSpell].ID}) /notify BuffWindow Buff${Int[${Math.Calc[${Me.Buff[LichSpell].ID}-1]}]} leftmouseup
      /mqpause
   }
   /if ((${Target.Distance} > ${Math.Calc[${Target.Speed} / 4 * ${Spell[Lifetap].MyCastTime}]}) && (${Me.PctHPs} < 80)) {
      /call Cast "Lifetap"
   }
   /if ((${Target.Distance} > ${Math.Calc[${Target.Speed} / 4 * ${Spell[DamageDOT].MyCastTime}]}) && (${DamageT} <= 150)) {
      /call Cast "DamageDOT"
      /if (${Macro.Return.Equal[CAST_SUCCESS]}) /varset DamageT ${Math.Calc[${Spell[DamageDOT].Duration}* 6]}s
   }
   /if ((!${PetAttacking}) && (${Target.PctHPs} < 50)) {
      /pet attack
      /varset PetAttacking 1
   }
   /delay 10s (${Target.Distance} <= 50)
   /face fast nolook
   /if (!${Target.ID}) /return

   /keypress strafe_right hold
   /delay 15
   /keypress strafe_right
   /if (!${Target.ID}) /return
   /doevents
   /goto :KiteLoop
/return


Sub Downtime

   /call MoveToLoc ${HomeY} ${HomeX}
   /if (!${Me.Pet.ID}) {
      /call Cast "PetSpell"
      /pet guard here
      /pet taunt
   }
   /call Cast "LichSpell" 
   :MedCheck
   /if (${Me.PctHPs} < 70) {
      /if (${Me.Buff[LichSpell].ID}) /notify BuffWindow Buff${Int[${Math.Calc[${Me.Buff[LichSpell].ID}-1]}]} leftmouseup
   }
   /if (${Me.PctMana} < 70) {
      /if (!${Me.Sitting}) /sit
      /doevents
      /delay 300 (${Me.PctMana} > 80)
      /goto :MedCheck
   }
   /call Cast "LichSpell"
   /if (${PetHastT} < 300) {
      /call Cast "PetHaste"
      /varset PetHastT ${Math.Calc[${Spell[PetHaste].Duration} * 6]}s
   }
   /doevents

/return


| Sub MoveToLoc   F                                 | 
|---------------------------------------------------| 
|This simply moves the player to within 1 unit of   | 
|the requested location, while avoiding obstacles   | 
|                                                   | 
|This is beatnik007's original sub, with a few minor| 
|changes and rewritten in MQ2Data format            |
|                                                   |
|                                                   | 
|F is for Follow. designed for pulling or kiting,   |
|If the mob's distance exceeds Distance, it will 
|pause and wait for the mob to catch up.
|
|SYNTAX: /call MoveToLocF Y X Distance              | 


Sub MoveToLocF(MoveToY, MoveToX, FDistance) 

    /declare FailureTimer timer local 0 
    /declare StrafeFailure int local 
    /declare running int local 
    /declare MaxSpeed int local 
    /declare StopDistance int local 
    /declare distanceNow float local 
    /declare distanceBefore float local 
    /declare distanceModifier int local 
    /varset running 0 
    /declare distanceTimer timer 15 
    /varset distanceBefore ${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]} 
    /varset distanceModifier 1 
    /varset MaxSpeed 0 
    :moveToLocation 

   /if (${Me.Speed}>=${MaxSpeed}) /varset MaxSpeed ${Me.Speed} 
   /if (${MaxSpeed}<=166) { 
      /varset StopDistance 3 
   } else { 
      /varset StopDistance 10 
   } 

    /face fast nolook loc ${MoveToY},${MoveToX} 

    /if (${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]}<${StopDistance}) { 
        /keypress forward 
        /return 
    } 

    /if (${distanceTimer}==0) { 
        /if (${Me.Sneaking}) { 
            /varset distanceModifier 2 
        } else { 
            /varset distanceModifier 1 
       } 

        /varset distanceNow ${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]} 
        /if (${Math.Calc[${distanceBefore}-${distanceNow}]}<${Math.Calc[10/${distanceModifier}]}) { 
           /if (${FailureTimer}==0) { 
              /varset StrafeFailure 0 
              /varset FailureTimer 600 
           } 
           /if (${FailureTimer}>0) { 
              /varset StrafeFailure ${Math.Calc[${StrafeFailure} + 1]} 
           } 
      /if (${StrafeFailure}>=10 && ${FailureTimer}>0) { 
             /keypress forward 
             /keypress back hold 
             /delay 5 
                 /keypress back 
         /afk Be back later, leave a message 
         /echo Your movement failed more than 10 times in 30 seconds and most likely looked macroed.  Ending macro. . . 
         /endmacro 
         /quit 
      } 
            /call strafePastObstacle ${StrafeFailure} 
        } 

        /varset distanceBefore ${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]} 
        /varset distanceTimer 15 
    } 

    /if (${running}==0) { 
        /keypress forward 
        /if (${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]}>${StopDistance}) { 
            /varset running 1 
            /keypress forward hold 
        } 
    } else { 
        /if (${Math.Distance[${Me.Y},${Me.X}:${MoveToY},${MoveToX}]}<${StopDistance}) { 
            /varset running 0 
            /keypress forward 
        } 
    } 
    /if (${Target.Distance} > ${FDistance}) {
        /keypress forward
        /delay 5s (${Target.Distance} < ${Math.Calc[${FDistance} * .75]})
        /if (${running}) /keypress forward hold
    }
    /if (${Me.PctHPs} < 30) {
        /echo Low health on pull, FDING
        /call Cast "Feign Death"
        /if (${Me.Buff[LichSpell].ID}) /notify BuffWindow Buff${Int[${Math.Calc[${Me.Buff[LichSpell].ID}-1]}]} leftmouseup
        /mqpause
    }
    /goto :moveToLocation 
/return

Sub Event_Hit

  /if (!${PetAttacking}) /pet back off
  /if (${Me.PctHPs} < 30) {
     /echo Low health, FDING
     /call Cast "Feign Death"
     /if (${Me.Buff[LichSpell].ID}) /notify BuffWindow Buff${Int[${Math.Calc[${Me.Buff[LichSpell].ID}-1]}]} leftmouseup
     /mqpause
  }
/return

Hamner
a lesser mummy
a lesser mummy
Posts: 47
Joined: Wed Aug 04, 2004 9:30 am

Post by Hamner » Sat Aug 28, 2004 3:49 pm

I have a necro of about this level, will be trying this out. Thanx :smile:

missingfiles
a hill giant
a hill giant
Posts: 224
Joined: Wed Jun 09, 2004 1:15 pm

Post by missingfiles » Mon Aug 30, 2004 4:21 pm

Im going to try this tonight to see what can be updated etc. If I die meh only a 300pp loss on a ee :P Dont think my friend will mind be killing his necro

Terramantian
a ghoul
a ghoul
Posts: 120
Joined: Thu May 13, 2004 6:20 pm

Post by Terramantian » Mon Aug 30, 2004 10:22 pm

Cool. Like I said I have virtually 0 time to work with this, but I'll try to keep it updated when I can. Just wanted to throw it out for others to play with.

User avatar
Madman
a ghoul
a ghoul
Posts: 144
Joined: Wed Jun 26, 2002 4:16 pm

Post by Madman » Sat Oct 23, 2004 3:41 pm

all i can say is i can feel the love this is the best thing i have found for my necro yet. now jsut need to adjust it down a few spell lvls and figure out where/how to adapt and use it

twisted82
decaying skeleton
decaying skeleton
Posts: 7
Joined: Tue Mar 23, 2004 5:52 pm

Post by twisted82 » Sat Oct 23, 2004 9:32 pm

Awesome macro, works nicely - i've edited it and put in another dot spell. Odd thing is macro can kite a mob down for 20% mana, where it would run me 40% mana, timing the dots like it does is VERY efficent.


-Twisted-
Im just a noob, trying to get a nut.

omghi2u
decaying skeleton
decaying skeleton
Posts: 1
Joined: Thu Oct 28, 2004 4:51 am

Post by omghi2u » Thu Oct 28, 2004 3:33 pm

just wondering if anybody has been able to work out the spells getting interupted because you're still running when it starts casting issue

Lane
a hill giant
a hill giant
Posts: 201
Joined: Fri Dec 06, 2002 11:57 am

Post by Lane » Mon Nov 15, 2004 1:56 pm

I had issues with this in a kite macro I was working on. I think I had to eventually just put a pause in just before I cast.

I'm sure there must be a better way, but I don't know what it is. When I play my toon I start to turn in place before I cast. Maybe you could modify it to do something like that.

Or even check your loc and when it doesn't change, start casting.

-Lane
I Macroquest, therefor I am!

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

Post by Shenlon » Mon Nov 15, 2004 3:06 pm

Code: Select all

:Waitloop
/if (${Me.Moving}) {
  /goto :Waitloop
} else {
  /cast Thundering_Spell_of_DOOM
}
There's a little bit better way to do it provided you are moving to a set location and are planning on stopping. Has worked for me flawlessly.

Lane
a hill giant
a hill giant
Posts: 201
Joined: Fri Dec 06, 2002 11:57 am

Post by Lane » Tue Nov 16, 2004 1:04 pm

Thank Shenlon. I'll be changing my macro when I get home. :)

BTW, nice spell choice. ;)

-Lane
I Macroquest, therefor I am!

eqsomebody
a lesser mummy
a lesser mummy
Posts: 74
Joined: Thu Jul 29, 2004 10:36 am

Post by eqsomebody » Thu Nov 18, 2004 5:07 pm

Hmm... I'm going to look at stripping out all the kiting. Getting rid of the kiting would make this a good faction generating macro for a Necro in Draniks Scar. Lots of wandering low level mobs. In DS outside of Bloodlands there is a spot with 4 to 5 static spawns with a 20 minute repop. Just snag some long lasting virtue and KEI (ewww..) and plop yourself up on your horse/lizard and let the macro roll. Kick the macro off and go to bed. :D

Target, Darkness, go pet go, Horror, Touch of Mujaki, wait for mob to die and Force Shield after dead. Rinse and repeat.

eqsomebody
a lesser mummy
a lesser mummy
Posts: 74
Joined: Thu Jul 29, 2004 10:36 am

Post by eqsomebody » Thu Nov 18, 2004 5:48 pm

omghi2u wrote:just wondering if anybody has been able to work out the spells getting interupted because you're still running when it starts casting issue
I have this problem in normal game play. When I lay off the arrow key to stop running, I have to pause for a second before casting or else I will get the interrupted message.

Ranger_Space
a lesser mummy
a lesser mummy
Posts: 42
Joined: Thu Aug 26, 2004 4:25 pm

Post by Ranger_Space » Fri Nov 19, 2004 1:32 pm

eqsomebody wrote:
omghi2u wrote:just wondering if anybody has been able to work out the spells getting interupted because you're still running when it starts casting issue
I have this problem in normal game play. When I lay off the arrow key to stop running, I have to pause for a second before casting or else I will get the interrupted message.
Quicker way of doing this is once you stop running with your arrow keys, turn left then turn right, then cast your spell. What's happening, is the client position isn't immediately updated when you stop. Rotating Left and Right forces a client update to your positing, thus making it so you are not "moving".

Lane
a hill giant
a hill giant
Posts: 201
Joined: Fri Dec 06, 2002 11:57 am

Post by Lane » Fri Nov 19, 2004 1:44 pm

I actually had someone ask me why I was always turning in circles. I got interupted spells so much when I first started that after I learned this trick I do it all the time before I cast out of habit.

-Lane
I Macroquest, therefor I am!

User avatar
KungFuHamster
a snow griffon
a snow griffon
Posts: 337
Joined: Wed Oct 02, 2002 7:47 am

Post by KungFuHamster » Fri Nov 19, 2004 3:25 pm

Yep. I always turn just a little bit after I stop moving. I don't remember having to do it when I first started; I think when they started doing the network optimizations like a year or two ago, messing around with player update packets, is when I had to start doing it.