spell_routines.inc ( updated: 11/07/2004 )

A forum for macro code snippets to be used in writing other macros. Post routines or .inc files here only, completed macros go to the Macro Depot. MQ2Data format only!

Moderator: MacroQuest Developers

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

spell_routines.inc ( updated: 11/07/2004 )

Post by Rusty~ » Sun May 30, 2004 9:28 pm

general include file to cast spells, items, and AAs for you. feel free to add any suggestions or report any possible bugs

Code: Select all

| spell_routines.inc
|
| Written by Rusty~
| Last Modified 11/07/2004
|
| Features:
| - Casts spells, clicks items, or uses AA abilities for you
| - Allows back to back casting without waiting on spell gems to pop all the way up
| - Will interrupt spell if target dies while casting. If on a mount, it will dismount and duck if the time left
|   is greater than 7 seconds, else it will move forward a bit to interrupt, then move you back
|    ** IMPORTANT: if you don't want to interrupt a spell while mounted, put this at the top of your macro: **
|    **   /declare noInterrupt int outer 1                                                                  **
| - Allows you to use items in bags. Equips item, clicks it, then returns it to its previous location
| - Lets you set how long you want to keep trying to cast the spell (defaults to 0)
|   If the spell is interrupted before the given time, it will recast, else it will return CAST_INTERRUPTED
| - Lets you call a custom subroutine while waiting for spell to finish casting
|   Try to keep custom subroutines very small. A common use would be to interrupt the spell if a certain condition is true
| - This file also includes a sub named Interrupt. You can call this to interrupt any spell you're casting instantly.
| - You can also use the SwapItem sub included in this to swap items to certain slots
| - Added EquipItem sub to easily equip items in your main Inventory slots.
| - Note: if you don't want this to cast spells while you're invis, in your main macro have this at the top:
|      /declare noInvis int outer 1 
|   This will make it return CAST_INVIS if you're invis
|
|  Below is a list of outer scope variables you can access in your macros:
|      refreshTime        - How much time is left till you're done recovering from casting
|      castEndTime        - How much time left till you're done casting the current spell... usable in custom spell Subs
|      spellNotHold       - 1 if your last spell didn't take hold, 0 otherwise
|      spellRecastTime1-9 - How much time left till that spell is back up
|
|======================================================================================================================
|  EquipItem:  An easier way to equip items you have in bags ( useful for weapons or focus items )
|              slot name is optional. If not given, it will equip it in the first possible spot
|
|    Usage:   
|        /call EquipItem "item name|slotname"
|
|        Returns: "old item name|slotname"
|    Examples:
|    
|    To Equip Sharp Ended Broken Lever when you have Serpent of Vindication equiped:
|        /call EquipItem "Sharp Ended Broken Lever"
|    It will return "Staff of Vindication|mainhand"
|    To reequip the original item, you can save the return in a variable, and then use it later like this:
|       /varset oldPrimary ${Macro.Return}
|       | ... do stuff here with your new item equiped
|       /call EquipItem ${oldPrimary}
|
|======================================================================================================================
|  SwapItem:  a subroutine which is used in the Cast sub itself. You don't need to do this to cast an item in a bag
|             but you can call it in your macro to SwapItems (such as weapons or focus items)
|    Usage:   
|        /call SwapItem "item name" slotname|slotID
|    Examples:
|    
|    To swap Darkblade of the Warlord to your main hand:
|        /call SwapItem "Darkblade of the Warlord" mainhand
|
|    To swap stat food in one bag with other food in another bag:
|        /call SwapItem "Bristlebanes Party Platter" ${FindItem[halas 10lb meat pie].InvSlot}
|
|======================================================================================================================
|  Cast: the main subroutine that casts spells or items for you
|     Usage:
|        /call Cast "spellname|itemname|AAname|AA#" [item|alt|gem#] [give up time][s|m] [custom subroutine name]
|     Examples:
| 
|     To cast Howl of Tashan and mem it in slot 3 if not memmed:
|       /call Cast "Howl of Tashan" gem3
|
|     To cast Arcane Rune and keep trying for 7 seconds, in case of interrupts.
|       /call Cast "Arcane Rune" gem5 7s
|
|     To click Grim Aura earring that's in a bag:
|       /call Cast "Shrunken Goblin Skull Earring" item
|
|     To use AA ability Eldritch Rune:
|       /call Cast "Eldritch Rune" alt
|         or
|       /call Cast "173" alt
|
|     To call a subroutine that interrupts CH if target gets healed before it lands:
|       /call Cast "Complete Healing" gem1 0 CheckHP
|     Then in your macro have somewhere:
|       Sub CheckHP
|          /if ( ${Target.PctHPs}>=80 ) /call Interrupt
|       /return
|
| Returns these values:
|----------------------+----------------------------------------------------------------------+
| CAST_CANCELLED       | Spell was cancelled by ducking (either manually or because mob died) |
| CAST_CANNOTSEE       | You can't see your target                                            |
| CAST_IMMUNE          | Target is immune to this spell                                       |
| CAST_INTERRUPTED     | Casting was interrupted and exceeded the given time limit            |
| CAST_INVIS           | You were invis, and noInvis is set to true                           |
| CAST_NOTARGET        | You don't have a target selected for this spell                      |
| CAST_NOTMEMMED       | Spell is not memmed and you gem to mem was not specified             |
| CAST_NOTREADY        | AA ability or spell is not ready yet                                 |
| CAST_OUTOFMANA       | You don't have enough mana for this spell!                           |
| CAST_OUTOFRANGE      | Target is out of range                                               |
| CAST_RESISTED        | Your spell was resisted!                                             |
| CAST_SUCCESS         | Your spell was cast successfully! (yay)                              |
| CAST_UNKNOWNSPELL    | Spell/Item/Ability was not found                                     |
|----------------------+----------------------------------------------------------------------+

#event BeginCast "You begin casting#*#"
#event Collapse "Your gate is too unstable, and collapses.#*#" 
#event FDFail "#1# has fallen to the ground.#*#" 
#event Fizzle "Your spell fizzles#*#" 
#event Immune "Your target is immune to changes in its attack speed#*#" 
#event Immune "Your target is immune to changes in its run speed#*#" 
#event Immune "Your target cannot be mesmerized#*#"
#event Interrupt "Your casting has been interrupted#*#" 
#event Interrupt "Your spell is interrupted#*#" 
#event NoHold "Your spell did not take hold#*#"
#event NoLOS "You cannot see your target.#*#" 
#event NoTarget "You must first select a target for this spell!#*#"
#event NotReady "Spell recast time not yet met.#*#"
#event OutOfMana "Insufficient Mana to cast this spell!#*#" 
#event OutOfRange "Your target is out of range, get closer!#*#" 
#event Recover "You haven't recovered yet...#*#" 
#event Recover "Spell recovery time not yet met#*#" 
#event Resisted "Your target resisted the #1# spell#*#" 
#event Resisted2 "You resist the #1# spell#*#" 
#event Standing "You must be standing to cast a spell#*#"
#event Stunned "You are stunned#*#" 
#event Stunned "You can't cast spells while stunned!#*#" 
#event Stunned "You *CANNOT* cast spells, you have been silenced!#*#" 


Sub Cast(string spellName,string spellType,timer giveUpTimer,string mySub)
   /declare castTime float local
   /if ( ${spellType.Equal[item]} ) {
      /varset castTime ${FindItem[${spellName}].CastTime}
   } else /if ( ${spellType.Equal[alt]} ) {
      /varset castTime ${AltAbility[${spellName}].Spell.MyCastTime}
   } else {
      /varset castTime ${Spell[${spellName}].MyCastTime}
   }
   /if ( ${Me.Invis} && ${noInvis} ) {
      /return 
   }
   :wait_for_stop
   /if ( !${Defined[spellType]} ) /declare spellType string local spell
   /if ( ${Me.Casting.ID} ) {
      /if ( ${Defined[mySub]} ) /call ${mySub}
      /goto :wait_for_stop
   }  
   /if ( ${Me.Speed} ) {
   :wait_for_stop2
      /if ( ${Defined[mySub]} ) /call ${mySub}
      /if ( ${Me.Moving} && ${castTime}>0.1 ) /goto :wait_for_stop2
   }
   /if ( !${Defined[giveUpTimer]} ) /declare giveUpTimer timer local 0
   /if ( !${Defined[spellRecastTime1]} ) {
      /if ( !${Defined[noInterrupt]} ) /declare noInterrupt int outer 0
      /declare moveBack bool outer false
      /declare selfResist int outer
      /declare selfResistSpell string outer
      /declare castEndTime timer outer
      /declare refreshTime timer outer 0
      /declare itemRefreshTime float outer 0
      /declare startCastingLoc string outer
      /declare i int local
      /declare castReturn string outer
      /declare spellNotHold string outer
      /delay 5
      /for i 1 to 9
         /declare spellRecastTime${i} timer outer 
         /if ( ${Me.SpellReady[${i}]} ) {
            /varset spellRecastTime${i} 0
         } else {
            /varcalc spellRecastTime${i} 10*${Me.Gem[${i}].RecastTime}
         }
      /next i
   }
   /varset spellNotHold 0
   /varset selfResist 0
   /declare delayTime timer local
   /declare swapItemBack bool local false
   /declare slotName int local
   /declare oldItemName string local
   /declare slotID int local
   /declare oldSlotID int local
   /declare spellID int local
   /declare charges int local

   /if ( ${Window[SpellBookWnd].Open} ) /keypress spellbook
   /if ( ${Me.Ducking} ) /keypress duck
   /if ( !${Me.Standing} ) /stand 

   /doevents Recover
   /doevents BeginCast
   /doevents Fizzle 
   /doevents Interrupt 
   /doevents Standing 
   /doevents FDFail
   /doevents OutOfRange 
   /doevents OutOfMana 
   /doevents NoLOS 
   /doevents Resisted2
   /doevents Resisted 
   /doevents Immune 
   /doevents Stunned 
   /doevents Collapse
   /doevents NoTarget
   /doevents NotReady
   /varset castReturn CAST_SUCCESS
   
      /if ( ${spellType.Equal[item]} ) /goto :cast_item
   /if ( ${spellType.Equal[alt]} ) /goto :cast_alt

:cast_spell
   /if ( !${Int[${Me.Book[${spellName}]}]} ) {
      /echo Spell: "${spellName}" was not found in your book
      /return CAST_UNKNOWNSPELL
   }
   /if ( !${Me.Gem[${spellName}]} ) {
   :mem_spell
      /if ( ${Cursor.ID} ) {
         /autoinventory
         /delay 5
         /goto :mem_spell  
      }
      /if ( ${spellType.Left[3].Equal[gem]} ) {
         /memspell ${spellType.Right[1]} "${spellName}"
      } else {
         /return CAST_NOTMEMMED
      }
      /delay 6s ${Me.Gem[${spellName}]}
      /if ( !${Me.Gem[${spellName}]} ) {
         /echo Spell mem interrupted...
         /return CAST_INTERRUPTED
      }
      :wait_for_mem
      
      /delay 15s ${Me.SpellReady[${spellName}]}
      /if ( !${Me.SpellReady[${spellName}]} ) {
         /if ( ${giveUpTimer} ) /goto :wait_for_mem
         /return CAST_NOTREADY
      }
   }
   /varset spellType spell
   /if ( ${spellName.Find[illusion: ]} && ${Me.AltAbilityReady[project illusion]} ) /call Cast "project illusion" alt

   /varset giveUpTimer ${giveUpTimer.OriginalValue}
   /declare recoverWaitTime timer local 30

:cast_spell_loop
:wait_for_spell
   /if ( ${Me.SpellReady[${spellName}]} ) {
      /varset spellRecastTime${Me.Gem[${spellName}]} 0
      /goto :skip_delay  
   }
   /if ( ${spellRecastTime${Me.Gem[${spellName}]}}  ) {
      /if ( !${giveUpTimer} ) /return CAST_NOTREADY
      /if ( ${Defined[mySub]} ) /call ${mySub}
      /goto :wait_for_spell
   }
   /if ( !${refreshTime} ) /goto :skip_delay
:wait_on_refresh
   /if ( ${Me.SpellReady[${spellName}]} ) /varset refreshTime 0
   /if ( ${refreshTime}>0 ) {
      /if ( ${Defined[mySub]} ) /call ${mySub}
      /goto :wait_on_refresh
   }
   /varcalc delayTime 10*(1.5-${Spell[${spellName}].MyCastTime})
:cast_delay_loop
   /if ( ${delayTime}>0 ) {
      /if ( ${Defined[mySub]} ) /call ${mySub}
      /goto :cast_delay_loop
   }
:skip_delay
   /varset startCastingLoc ${Me.X} ${Me.Y} ${Me.Z}
   /cast "${spellName}"

   /if ( ${Me.Casting.ID} ) {
      /varset spellID ${Me.Casting.ID}
      /varcalc castEndTime ${Me.Casting.MyCastTime}*10
      /if ( ${castEndTime}<${Math.Calc[${Me.Casting.CastTime}*5]} ) /varcalc castEndTime ${Me.Casting.CastTime}*5
      /echo Casting: ${Me.Casting.Name}${If[!${Me.Casting.TargetType.Equal[PB AE]} && !${Me.Casting.TargetType.Equal[self]} && ${Target.ID}, on >> ${Target.CleanName} <<,]}
   }

   /varset moveBack false

   /call WaitCast ${mySub}

   /if ( ${moveBack} ) {
      /keypress back hold
      /delay 4
      /keypress back
      /delay 15 !${Me.Moving}
   }

   /if ( ${castReturn.Equal[CAST_CANCELLED]} ) {
      /echo Spell was cancelled...
      /return CAST_CANCELLED
   }

   /doevents Recover
   /doevents BeginCast
   /doevents Fizzle
   /doevents Interrupt
   /doevents Standing
   /doevents FDFail
   /doevents OutOfRange
   /doevents OutOfMana
   /doevents NoLOS
   /doevents Resisted2
   /doevents Resisted
   /doevents Immune
   /doevents Stunned
   /doevents Collapse
   /doevents NoTarget
   /doevents NotReady
   
   /if ( !${spellID} ) /varset spellID ${Spell[${spellName}].ID}
   /if ( !${castReturn.Equal[CAST_SUCCESS]} ) {
      /if ( ${castReturn.Equal[CAST_NOTREADY]} ) /return CAST_NOTREADY
      /if ( ${castReturn.Equal[CAST_FIZZLE]} ) {
         /echo Spell Fizzled. Recasting...
         /goto :cast_spell_loop
      }
      /if ( ${castReturn.Equal[CAST_RECOVER]} ) {
         /if ( !${recoverWaitTime} ) {
            /varcalc spellRecastTime${Me.Gem[${spellName}]} 10*${Spell[${spellID}].RecastTime}
            /if ( !${giveUpTimer} ) /return CAST_NOTREADY
         }
         /goto :cast_spell_loop
      }
      /if ( ${castReturn.Equal[CAST_RESTART]} ) /goto :cast_spell_loop
      /if ( ${castReturn.Equal[CAST_STUNNED]} ) {
         /if ( ${Me.Stunned} ) {
            /delay 3s !${Me.Stunned}
         } else {
            /delay 7
         }
         /goto :cast_spell_loop
      }
      /if ( ${castReturn.Equal[CAST_INTERRUPTED]} ) {
         /if ( ${giveUpTimer} ) {
            /echo Spell was interrupted. Recasting...
            /goto :cast_spell_loop
         }
         /echo Spell was interrupted...
         /return CAST_INTERRUPTED
      }
   }
   /if ( !${castReturn.Equal[CAST_CANNOTSEE]} && !${castReturn.Equal[CAST_OUTOFRANGE]} && !${castReturn.Equal[CAST_OUTOFMANA]} && !${castReturn.Equal[CAST_NOTARGET]} ) {
      /varcalc refreshTime 10*${Spell[${spellID}].RecoveryTime}
      /varcalc spellRecastTime${Me.Gem[${spellName}]} 10*${Spell[${spellID}].RecastTime}
   }
   /if ( ${castReturn.Equal[CAST_COLLAPSE]} ) {
      /varset giveUpTimer 200
      /goto :cast_spell_loop
   }
/return ${castReturn}


:cast_item
   /if ( !${FindItem[${spellName}].InvSlot} ) {
      /echo Cannot find item: ${spellName}
      /return CAST_UNKNOWNSPELL
   }  
   /if ( ${FindItem[${spellName}].InvSlot}>21 ) {
      /varset swapItemBack true
      /if ( ${FindItem[${spellName}].WornSlot[1]} && ${FindItem[${spellName}].EffectType.Find[worn]} ) {
         /varset slotName ${FindItem[${spellName}].WornSlot[1]}
      } else /if ( ${FindItem[${spellName}].InvSlot}>29 ) {
         /varset slotName 29
      } else {
         /varset slotName ${FindItem[${spellName}].InvSlot}
      }
      /varset slotID ${InvSlot[${slotName}].ID}      
      /varset oldSlotID ${FindItem[${spellName}].InvSlot.ID}
      /varset oldItemName ${InvSlot[${slotID}].Item.Name}
      /call SwapItem "${spellName}" ${slotID}
   }
:cast_item_loop
:wait_item_loop
   /if ( ${itemRefreshTime} > ${MacroQuest.Running} ) {
      /delay 1
      /goto :wait_item_loop
   }
   /varset itemRefreshTime ${Math.Calc[${MacroQuest.Running}+000]}
   /varset charges ${FindItem[${spellName}].Charges}
   /varset startCastingLoc ${Me.X} ${Me.Y} ${Me.Z}
   /cast item "${spellName}"
   /if ( ${Me.Casting.ID} ) {
      /varcalc castEndTime ${FindItem[${spellName}].CastTime}*10
      /echo Casting: ${FindItem[${spellName}].Spell.Name}${If[!${FindItem[${spellName}].Spell.TargetType.Equal[PB AE]} && !${FindItem[${spellName}].Spell.TargetType.Equal[self]} && ${Target.ID}, on >> ${Target.CleanName} <<,]}
   }
   /if ( ${charges}>0 ) /delay 1s ${FindItem[${spellName}].Charges}!=${charges}

   /call WaitCast ${mySub}
   
   /if ( ${swapItemBack} ) {
      /if ( ${FindItem[${spellName}].ID} ) {
         /call SwapItem "${spellName}" ${oldSlotID}
      } else /if ( ${FindItem[${oldItemName}].ID} ) {
         /call SwapItem "${oldItemName}" ${slotID}         
      }
      /if ( ${Cursor.Container} ) /autoinventory
   }

   /if ( ${castReturn.Equal[CAST_CANCELLED]} ) {
      /echo Spell was cancelled...
      /return CAST_CANCELLED
   }

   /doevents BeginCast
   /doevents Interrupt
   /doevents Standing
   /doevents FDFail
   /doevents OutOfRange
   /doevents NoLOS
   /doevents Resisted2
   /doevents Resisted
   /doevents Immune
   /doevents Stunned
   /doevents Collapse
   /doevents NoTarget
   /doevents NotReady

   /if ( !${castReturn.Equal[CAST_SUCCESS]} ) {
      /if ( ${castReturn.Equal[CAST_NOTREADY]} ) /return CAST_NOTREADY
      /if ( ${castReturn.Equal[CAST_RESTART]} ) /goto :cast_item
      /if ( ${castReturn.Equal[CAST_STUNNED]} ) {
         /if ( ${Me.Stunned} ) {
            /delay 3s !${Me.Stunned}
         } else {
            /delay 7
         }
         /goto :cast_item
      }
      /if ( ${castReturn.Equal[CAST_INTERRUPTED]} ) {
         /if ( ${giveUpTimer} ) {
            /echo Spell was interrupted. Recasting...
            /goto :cast_item
         }
         /echo Spell was interrupted...
         /return CAST_INTERRUPTED
      }
   }
   /if ( ${castReturn.Equal[CAST_COLLAPSE]} ) {
      /varset giveUpTimer 200
      /goto :cast_item
   }
/return ${castReturn}


:cast_alt
   /if ( !${Me.AltAbilityReady[${spellName}]} ) /return CAST_NOTREADY
   /echo Using AA Ability: ${AltAbility[${spellName}].Name}
   /alt activate ${AltAbility[${spellName}].ID}
   /if ( ${AltAbility[${spellName}].Spell.MyCastTime}>=0.5 ) /delay 1s ${Me.Casting.ID}
   /call WaitCast ${mySub}
   
   /if ( ${castReturn.Equal[CAST_CANCELLED]} ) {
      /echo Spell was cancelled...
      /return CAST_CANCELLED
   }
   
   /doevents BeginCast
   /doevents Interrupt
   /doevents Standing
   /doevents FDFail
   /doevents OutOfRange
   /doevents NoLOS
   /doevents Resisted2
   /doevents Resisted
   /doevents Immune
   /doevents Stunned
   /doevents NoTarget
      
   /if ( !${castReturn.Equal[CAST_SUCCESS]} ) {
      /if ( ${castReturn.Equal[CAST_RESTART]} ) /goto :cast_alt
      /if ( ${castReturn.Equal[CAST_STUNNED]} ) {
         /if ( ${Me.Stunned} ) {
            /delay 3s !${Me.Stunned}
         } else {
            /delay 7
         }
         /goto :cast_alt
      }
      /if ( ${castReturn.Equal[CAST_INTERRUPTED]} ) {
         /if ( ${giveUpTimer} ) {
            /echo Spell was interrupted. Recasting...
            /goto :cast_alt
         }
         /echo Spell was interrupted...
         /return CAST_INTERRUPTED
      }
   }
/return ${castReturn}


Sub EquipItem(string WhatWhere) 
   /declare DestName string local 
   /declare ItemName string local ${String[${WhatWhere}].Arg[1,|]} 
   /declare SlotName string local ${String[${WhatWhere}].Arg[2,|]} 
   /if (${SlotName.Equal[NULL]}) /varset SlotName ${InvSlot[${FindItem[=${ItemName}].WornSlot[1]}].Name} 
   /if (${FindItem[=${ItemName}].InvSlot}<22 || !${FindItem[=${ItemName}].WornSlot[${SlotName}]}) /return 
   /if (!${InvSlot[${SlotName}].Item.Name.Equal[NULL]}) /varset DestName "${InvSlot[${SlotName}].Item.Name}|${SlotName}" 
   /call SwapItem "${ItemName}" "${SlotName}" 
/return ${DestName} 

| Sub EquipItem(string itemName,string slotName)
   /if ( !${Defined[slotName]} ) /declare slotName string local ${FindItem[${itemName}].WornSlot[1]}
   /declare oldItem string local ${Me.Inventory[${slotName}].Name}
   /call SwapItem "${itemName}" ${slotName}
/return "${oldItem}" ${slotName}

Sub SwapItem(string itemName,string slotName)
   /if ( ${InvSlot[${slotName}].Item.Name.Equal[${itemName}]} ) /return
   /declare slotID int local
   /declare oldSlotID int local
   /declare oldItem string local
   /declare i int local
   /varset slotID ${InvSlot[${slotName}].ID}		     | slotID = slot you're swapping item to
   /varset oldSlotID ${FindItem[${itemName}].InvSlot.ID} | oldSlotID = slot the item was originally in
   /varset oldItem ${InvSlot[${slotName}].Item.Name}     | oldItem = name of item in the slot you're swapping WITH
   /if ( !${slotID} ) {
      /echo Invalid slot name: ${slotName}
      /return
   }
   /if ( !${oldSlotID} ) {
      /echo Could not find item ${itemName}
      /return
   }
:auto_inv
   /if ( ${Cursor.ID} && !${Cursor.Name.Equal[${itemName}]} ) {
      /if ( ${Cursor.Container} ) {
         /for i 1 to 8
            /if ( !${InvSlot[pack${i}].Item.Container} ) {
               /nomodkey /itemnotify pack${i} leftmouseup
            }
         /next i
      } else {
         /autoinventory
      }
      /goto :auto_inv
   } 
   

:pick_up_item
 | if the item is in a bag and it's not open, then open it!
   /if ( ${InvSlot[${oldSlotID}].Pack} && !${Window[${InvSlot[${oldSlotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${oldSlotID}].Pack} rightmouseup

 | if the slot you're putting it in is inside a bag and it's not open, then open it!
   /if ( ${InvSlot[${slotID}].Pack} && !${Window[${InvSlot[${slotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${slotID}].Pack} rightmouseup

 | ok.. pick up the item now!
   /squelch /nomodkey /shiftkey /itemnotify ${InvSlot[${oldSlotID}]} leftmouseup

 | if item isn't on your cursor, try again!
   /if ( !${Cursor.Name.Equal[${itemName}]} ) {
      /if ( ${Cursor.ID} && !${Cursor.Container} ) /autoinventory
      /goto :pick_up_item
   }
:exchange_items
   /if ( ${InvSlot[${oldSlotID}].Pack} && !${Window[${InvSlot[${oldSlotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${oldSlotID}].Pack} rightmouseup
   /if ( ${InvSlot[${slotID}].Pack} && !${Window[${InvSlot[${slotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${slotID}].Pack} rightmouseup

 | put the item in the new slot, and pick up whatever item was there
   /squelch /nomodkey /shiftkey /itemnotify ${slotID} leftmouseup

 | if it didnt get exchanged, try again!
   /if ( ${Cursor.ID} && !${Cursor.Name.Equal[${oldItem}]} && !${Cursor.Name.Equal[${itemName}]} && !${Cursor.Container} ) /autoinventory
   /if ( !${InvSlot[${slotID}].Item.Name.Equal[${itemName}]} ) /goto :exchange_items
:drop_item
   /if ( !${Cursor.Container} || ( ${InvSlot[${oldSlotID}]}<30 && ${InvSlot[${oldSlotID}]}>=22 ) ) {
      /if ( ${InvSlot[${oldSlotID}].Pack} && !${Window[${InvSlot[${oldSlotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${oldSlotID}].Pack} rightmouseup
      /if ( ${InvSlot[${slotID}].Pack} && !${Window[${InvSlot[${slotID}].Pack.Name}].Open} ) /nomodkey /itemnotify ${InvSlot[${slotID}].Pack} rightmouseup
      /squelch /nomodkey /itemnotify ${oldSlotID} leftmouseup
      /if ( ${Cursor.ID} ) {
         /if ( !${Cursor.Name.Equal[${oldItem}]} ) /autoinventory
         /goto :drop_item
      }
   }
:close_pack
   /if ( ${InvSlot[${oldSlotID}].Pack} && ${Window[${InvSlot[${oldSlotID}].Pack.Name}].Open} && ( ${Cursor.Name.Equal[${itemName}]} || ${FindItem[${itemName}].ID} ) ) {
      /squelch /nomodkey /itemnotify ${InvSlot[${oldSlotID}].Pack} rightmouseup
      /goto :close_pack
   }
   /if ( ${InvSlot[${slotID}].Pack} && ${Window[${InvSlot[${slotID}].Pack.Name}].Open} && ( ${Cursor.Name.Equal[${itemName}]} || ${FindItem[${itemName}].ID} ) ) {
      /squelch /nomodkey /itemnotify ${InvSlot[${slotID}].Pack} rightmouseup
      /goto :close_pack
   }
/return

Sub Interrupt
   /if ( ${Me.Mount.ID} ) /dismount
   /stopcast
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_CANCELLED
/return ${Macro.Return}


Sub WaitCast(string mySub)
   /declare currentTarget int local ${Target.ID}
   /declare currentTargetType string local ${Target.Type}
:wait_cast_loop
   /if ( ${Bool[${mySub}]} ) /call ${mySub}
   /if ( ${Me.Casting.ID} ) {
      /if ( ${currentTarget} && !${Spawn[${currentTarget}].Type.Equal[${currentTargetType}]} ) {
         /if ( !${Me.Casting.TargetType.Equal[PB AE]} && !${Me.Casting.TargetType.Equal[self]} && !${moveBack} && ( !${Me.Mount.ID} || !${noInterrupt} ) ) {
            /if ( !${Me.Mount.ID} || ${castEndTime}>70 ) {
               /call Interrupt
            } else /if ( ${Me.Casting.RecastTime}>3 ) { 
               /varset castReturn CAST_CANCELLED
               /keypress forward hold
               /delay 6
               /keypress forward
               /varset moveBack true
            }
         }
      }
      /if ( ${Me.State.Equal[DUCK]} ) /varset castReturn CAST_CANCELLED
      /delay 1
      /goto :wait_cast_loop
   }
/return

Sub Event_Fizzle 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_FIZZLE 
/return

Sub Event_Resisted(string line,string name)
   /if ( ${selfResist} && ${name.Equal[${selfResistSpell}]} ) {
      /varset selfResist 0
      /return   
   }
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_RESISTED 
/return

Sub Event_Resisted2(string line,string name)
   /if ( ${Defined[selfResist]} ) {
      /varset selfResist 1
      /varset selfResistSpell ${name}
   }
/return

Sub Event_Interrupt 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_INTERRUPTED
/return

Sub Event_Recover 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_RECOVER
/return

Sub Event_Immune
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_IMMUNE
/return

Sub Event_Stunned
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_STUNNED
/return

Sub Event_NoLOS 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_CANNOTSEE 
/return

Sub Event_Standing 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_RESTART 
/return

Sub Event_Collapse 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_COLLAPSE 
/return

Sub Event_OutOfMana 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_OUTOFMANA 
/return

Sub Event_OutOfRange 
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_OUTOFRANGE 
/return

Sub Event_NoTarget
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_NOTARGET 
/return

Sub Event_NotReady
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_NOTREADY 
/return

Sub Event_NoHold
   /if ( ${Defined[spellNotHold]} ) /varset spellNotHold 1
/return

Sub Event_BeginCast
   /if ( ${Defined[castReturn]} ) /varset castReturn CAST_SUCCESS
/return

Sub Event_FDFail(string line,string name) 
   /if ( ${name.Equal[${Me.Name}]} && ${Defined[castReturn]} ) {
      /if ( !${Me.Standing} ) /stand
      /varset castReturn CAST_RESTART 
   }
/return  
Last edited by Rusty~ on Sun Nov 07, 2004 12:53 pm, edited 43 times in total.

Chill
Contributing Member
Contributing Member
Posts: 435
Joined: Fri May 07, 2004 5:06 pm
Location: Erie, PA

Nice Macro!

Post by Chill » Thu Jun 03, 2004 10:13 pm

Somehow posted to the wrong subject. Post moved sorry.
Last edited by Chill on Tue Jun 08, 2004 6:43 am, edited 1 time in total.

Drumstix42
a grimling bloodguard
a grimling bloodguard
Posts: 808
Joined: Mon May 03, 2004 4:25 pm

Re: Nice Macro!

Post by Drumstix42 » Fri Jun 04, 2004 9:46 am

Chill wrote: -Have you seen Rusty's Spell_routines.inc?
why did you ask him if he's seen his own macro??

User avatar
Trails
a lesser mummy
a lesser mummy
Posts: 35
Joined: Mon May 24, 2004 3:09 pm

Post by Trails » Fri Jun 04, 2004 9:58 am

I was wondering the same thing lol

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

Post by Rusty~ » Mon Jun 14, 2004 7:57 pm

cleaned up code a bit. made some minor changes.

made it so that if you're on a mount and lose target, if the spell has over 3 seconds left to cast, it will dismount and duck, else it will strafe to interrupt

fantum409
a ghoul
a ghoul
Posts: 141
Joined: Fri Nov 14, 2003 10:03 pm

Post by fantum409 » Thu Jun 17, 2004 8:00 pm

/applause Rusty~
I wish I had read this over sooner. Very nice mac.

Edited out my post of this mac using /stopcast, guess it wasn't all I hoped it'd be.
Last edited by fantum409 on Fri Jun 18, 2004 12:41 am, edited 1 time in total.

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

Post by Rusty~ » Thu Jun 17, 2004 9:46 pm

actually, after trying /stopcast i don't really like it. it stops spells but still makes you recover afterwards, as opposed to ducking which lets you cast another spell right away. the only benefit would be if it worked on a horse but it doesn't :(

i think it's stupid that you can't stop casting something without having to move, but then again there are lots of things about eq that dont make sense!

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

Post by Rusty~ » Thu Jun 17, 2004 9:52 pm

made minor change to code. it'll now return CAST_NOTREADY if you try to click a modrod and it's recast time isn't over yet
Last edited by Rusty~ on Fri Jun 18, 2004 12:34 am, edited 1 time in total.

Drumstix42
a grimling bloodguard
a grimling bloodguard
Posts: 808
Joined: Mon May 03, 2004 4:25 pm

Post by Drumstix42 » Thu Jun 17, 2004 10:21 pm

Rusty~ wrote:actually, after trying /stopcast i don't really like it. it stops spells but still makes you recover afterwards, as opposed to ducking which lets you cast another spell right away. the only benefit would be if it worked on a horse but it doesn't :(

i think it's stupid that you can't stop casting something without having to move, but then again there are lots of things about eq that dont make sense!
Main reason it was added was by request from the hybrid classes, cause we all too lazy to hit duck AND attack. Basically saying so you can stop castign with out stopping your DPS (for a whole millisecond) ;)

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

Post by Rusty~ » Sat Jun 19, 2004 2:31 pm

made another small change to how spell recovery was checked.
there would be a problem if you casted a spell with long recast time manually, when it was cast with the macro it would keep trying to cast till it was up again.. made it so it'll timeout after 3 secs if that happens.

also had some problems if you would try to manually cast a spell while a spell was already being cast by a macro. it would pick up the "you have not recovered" message and return the wrong thing... so fixed that too.

fantum409
a ghoul
a ghoul
Posts: 141
Joined: Fri Nov 14, 2003 10:03 pm

Post by fantum409 » Wed Jun 23, 2004 11:15 pm

I have switched all of my macros that run my toons over... they all use this now.
Nice job Rusty~

Any chance for a switch to be added, that can disable interrupting in the beginning of the macro? My wizard keeps killing his horse to interrupt, or moves around in a kinda conspicuous way to interrupt spells that could simply be allowed to finish as they dont cost him mana if target is dead.

User avatar
blueninja
a grimling bloodguard
a grimling bloodguard
Posts: 541
Joined: Thu Aug 28, 2003 7:03 am
Location: Göteborg, Sweden

Post by blueninja » Thu Jun 24, 2004 8:20 am

How about adding a parameter to the cast sub for a focus item so the sub swaps it in before casting and swaps it out when cast is finished? Would be handy among other things for buff duration focus items that aren't worn all the time.

Something like this:

Code: Select all

/call cast "symbol of kazad" focus "ceramic shield of valor"
This would swap in the shield, cast symbol and once it's finished casting it would remove the shield.

Great macro btw, thanks!

Rusty~
a hill giant
a hill giant
Posts: 244
Joined: Wed Apr 14, 2004 2:55 pm

Post by Rusty~ » Tue Jun 29, 2004 4:26 am

those are both nice suggestions. in fact i was going to work on the focus thing sometime. i already had it coded into my macro but it's sloppy (ie i /call swapitem before and after the cast each time)... also i can see how some classes dont really need to interrupt spells.

the problem is i would have to completely rewrite how it handles parameters and i dont want to have to make people rewrite any code. ive also pretty much quit so im not really gonna be able to test it much but i'll give it a shot.

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

Post by aChallenged1 » Tue Jun 29, 2004 8:39 am

Just so I know for sure (Yes, I am a freaking noob! There is hope for me though) will this inc work in place of spellcast.inc if renamed? Or if I changed the #include line? Or is it so different that they are not compatible?

Thanks.

fantum409
a ghoul
a ghoul
Posts: 141
Joined: Fri Nov 14, 2003 10:03 pm

Post by fantum409 » Tue Jun 29, 2004 6:06 pm

this file works out of the box in place of spellcast.inc in most cases... just change your macro so it says #include spell_routines.inc instead of #include Spellcast.inc

basically the only time it would not interchange completely would be if your macro uses some of the same variables as this one does. If thats the case, you'll likely get an error message the first time you /call Cast
The other thing that is possible would be that spell_routines.inc might try to cast the spell before the gem is totally lit up, and if the call didn't specify a give up time it would need to be called again by your macro.
But give it a whorl, in most cases they interchange with no bugs.