I'm big on not declaring a million outer variables and I prefer to use .ini files if I want to use abilities or spells. All of my toons have their own class specific macro that includes one common macro list so you can simply plug and play the different functions as you see fit.
Here is the code. I update it almost every time I log in and it is a growing list. Hope everyone enjoys it and I am totally open to any changes or suggestions others have.
This is the Common.mac file - I do utilize the Spells.mac that can be found floating around if you go looking for it.
Edit - 25 Apr 2015 - I have added EQBC functionality, added a way to push the current spell list to the ini, added an automatic group buff function, and added a way to toggle on and off the automatic movement behind the target while fighting.
Edit - 27 Apr 2015 - Got rid of the need to map strafe keys, added a way to push a second "attacks" spell set, added a ranger-specific (can be modified for any bow/range wielding class) range attack function, added a caster range attack function, added casting while fiighting, added an auto tank mode to home in on the nearest npc and turn on attack (nothing fancy, careful where you use it, it's designed for open zones), added a stuck check that will simply bounce the toon off of the object if he gets stuck while following or heading to his attack target.
Edit - 29 Apr 2015 - Finally added some one-spell healing into the system. A simple "Save Your Heal!" into EQBC will push your ninth spell slot along with an 80% hp tolerance into the ini file. I added a way to push a different spell slot as well as load a different tolerance in if wanted. Simply type /bc "Save Your Heal! <Slot> <Tolerance>" Fixed a few minor other errors.
Edit - 30 Apr 2015 - Added the alternate advancement abilities to be both generic and tank-specific. Tweaked the healing system and the auto buff function. Fixed a few bugs.
Edit - 05 Sep 2016 - It has been a minute, but I have started playing again. I have made various bug fixes and had to fix a few of the issues with using a higher performance computer.
Code: Select all
#include Spells
#event Assist "<#1#> Assist me with >>> #2# <<<"
#event AutoFight "<#1#> Auto On!"
#event Buffs "<#1#> Buff Up!"
#event Moving "<#1#> Stop Moving!"
#event Ranged "<#1#> Keep Your Distance!"
#event MemHeal "<#*#> Save Your Heal! #1# #2#"
#event MemSpells "<#1#> Push #2#!"
Sub Variables
/declare Leader int outer 1
/declare AutoMode int outer 0
/declare BackAttack int outer 1
/declare GemCount int outer
/declare HealSpell string outer ${Ini[Master.ini,"${Me}",HealSpell]}
/declare HealGem int outer ${Ini[Master.ini,"${Me}",HealGem]}
/declare HealRange int outer ${Ini[Master.ini,"${Me}",HealRange]}
/declare HealTolerance string outer ${Ini[Master.ini,"${Me}",HealTolerance]}
/declare MaxSpellRange int outer 100
/declare RangedFight int outer 1
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_Assist
/declare CurrentExp int ${Me.PctExp}
/declare DifferenceExp float
/if (${Leader} == 0 && ${String[${Target}].NotEqual[NULL]}) /bc Assist me with >>> ${Target.CleanName} <<<
/if (${Me.Moving}) /keypress up
/delay 2s
:Kill
/doevents Moving
/doevents AutoFight
/doevents Ranged
/if (${Me.Pet.CleanName.NotEqual[NO PET]}) {
/if (!${Me.Pet.Target.ID} && ${Target.Distance} < ${Target.MaxRangeTo}) {
/if (${Me.Moving}) /keypress up
/call TargetCheck
/delay 1s
/pet attack
}
}
/if (${HealSpell.NotEqual[NULL]}) {
/doevents MemHeal
/call HealCheck
/if (${Macro.Return.Arg[2,|]} && ${Me.PctMana} > 10) {
/call HealCast ${Macro.Return.Arg[1,|]}
/goto :Kill
}
}
/if (${RangedFight} > 0) {
/if (!${Me.Combat}) /attack
/call StayOnTarget
/if (${Target.Distance} < ${Target.MaxRangeTo}) {
/if (${Me.Class.CanCast} && ${Me.PctMana} > 10) {
/if (${Me.Moving}) /keypress up
/call CasterAttack
} else {
/call DoAbilities
/if (${Group.MainTank.CleanName.Equal[${Me}]}) /call DoTankAbilities
}
}
} else {
/if (${Me.Class.Name.Equal[Ranger]}) {
/call RangerAttack
} else {
/call CasterAttack
}
}
/if (${Me.XTarget[1].PctHPs} > 0) /goto :Kill
/keypress up
/varcalc DifferenceExp ${Me.PctExp} - ${CurrentExp}
/bc ${Me.PctExp} -- ${DifferenceExp}
/doevents flush
/delay 2s
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_AutoFight
/call VarSwap ${AutoMode} AutoMode
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub BeastlordSpells
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_Buffs
/declare Count int
/declare SpellCount int
/if (${Me.Class.CanCast}) {
/squelch /target clear
/call CountGems
/target ${Me}
/delay 1s
/for SpellCount 1 to ${GemCount}
/if (${${Me}BuffsTargetArray[${SpellCount}].Equal[Self]}) {
/if (!${Me.Buff[${${Me}BuffsNameArray[${SpellCount}]}].ID} && ${${Me}BuffsNameArray[${SpellCount}].NotEqual[Feign Death]}) {
/delay 2s
/call Cast "${${Me}BuffsNameArray[${SpellCount}]}" Gem${SpellCount}
}
}
/next SpellCount
/if (${Me.Pet.CleanName.NotEqual[NO PET]}) {
/for SpellCount 1 to ${GemCount}
/if (${${Me}BuffsTargetArray[${SpellCount}].Equal[Pet]}) {
/target ${Me.Pet}
/delay 1s
/if (!${Target.Buff[${${Me}BuffsNameArray[${SpellCount}]}].ID}) {
/call Cast "${${Me}BuffsNameArray[${SpellCount}]}" Gem${SpellCount}
}
}
/next SpellCount
}
/for SpellCount 1 to ${GemCount}
/if (${${Me}BuffsTargetArray[${SpellCount}].Equal[Group v1]} || ${${Me}BuffsTargetArray[${SpellCount}].Equal[Group v2]}) {
/if (!${Me.Buff[${${Me}BuffsNameArray[${SpellCount}]}].ID}) {
/delay 2s
/call Cast "${${Me}BuffsNameArray[${SpellCount}]}" Gem${SpellCount}
}
}
/next SpellCount
/for Count 0 to ${Group.Members}
/target ${Group.Member[${Count}].CleanName}
/delay 2s
/for SpellCount 1 to ${GemCount}
/if (${${Me}BuffsTypeArray[${SpellCount}].Equal[Beneficial]}) {
/if (${${Me}BuffsTargetArray[${SpellCount}].Equal[Single]}) {
/if (!${Target.Buff[${${Me}BuffsNameArray[${SpellCount}]}].ID} && ${${Me}BuffsNameArray[${SpellCount}].NotEqual[${HealSpell}]}) {
/delay 2s
/call Cast "${${Me}BuffsNameArray[${SpellCount}]}" Gem${SpellCount}
}
}
}
/next SpellCount
/next Count
/bc Buffs Done!
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub CasterAttack
/declare Count int 1
/call FindMaxSpellRange
/call CountGems
/call TargetCheck
/if (${RangedFight} < 1) /call StayInRange ${MaxSpellRange}
/if (${HealSpell.NotEqual[NULL]} && ${Me.PctMana} < 40) /return
/if (${Target.Distance} < ${MaxSpellRange}) {
/if (${Me.Moving}) /keypress up
/for Count 1 to ${GemCount}
/if (${${Me}AttacksTypeArray[${Count}].Equal[Detrimental]}) {
/if (${${Me}AttacksDurationArray[${Count}]} > 0) {
/if (!${Target.Buff[${${Me}AttacksNameArray[${Count}]}].ID}) {
/if (${Me.SpellReady[${Count}]}) {
/delay 1s
/call Cast "${${Me}AttacksNameArray[${Count}]}" Gem${Count}
}
}
} else {
/if (${Me.SpellReady[${Count}]}) /call Cast "${${Me}AttacksNameArray[${Count}]}" Gem${Count}
}
}
/next Count
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub CheckStuck(PriorX, PriorY)
/delay 1
/if (${PriorX}==${Me.X} && ${PriorY}==${Me.Y} && ${Me.Moving}) {
/keypress back hold
/delay 1
/keypress back
/keypress strafe_left hold
/delay 1
/keypress strafe_left
/keypress up
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub CheckTarget
/if (${Target.Name.NotEqual[${Me.XTarget[1].Name}]})
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub CountGems
/declare Count int 1
:Next
/if (${Me.Gem[${Count}].Name.NotEqual[NULL]}) {
/varcalc Count ${Count} + 1
/goto :Next
}
/varcalc Count ${Count} - 1
/varset GemCount ${Count}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub DoAbilities
/declare Count int
/for Count 1 to ${${Me}AbilityArray.Size}
/if (${Me.AbilityReady[${${Me}AbilityArray[${Count}]}]}) /doability ${${Me}AbilityArray[${Count}]}
/next Count
/for Count 1 to ${${Me}AAArray.Size}
/if (${Me.AltAbilityReady[${${Me}AAArray[${Count}]}]}) /alt act ${${Me}AAArray[${Count}]}
/next Count
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub DoTankAbilities
/declare Count int
/for Count 1 to ${${Me}TankAbilityArray.Size}
/if (${Me.AbilityReady[${${Me}TankAbilityArray[${Count}]}]}) /doability ${${Me}TankAbilityArray[${Count}]}
/next Count
/for Count 1 to ${${Me}TankAAArray.Size}
/if (${Me.AltAbilityReady[${${Me}TankAAArray[${Count}]}]}) {
/if (${${Me}TankAATypeArray[${Count}].Equal[Multiple]}) {
/if (${Me.XTarget} > 1) /alt act ${${Me}TankAAArray[${Count}]}
} else {
/alt act ${${Me}TankAAArray[${Count}]
}
}
/next Count
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub FindMaxSpellRange
/declare Count int
/for Count 1 to ${GemCount}
/if (${${Me}AttacksTypeArray[${Count}].Equal[Detrimental]} && ${${Me}AttacksRangeArray[${Count}]} < ${MaxSpellRange}) /varset MaxSpellRange ${${Me}AttacksRangeArray[${Count}]}
/next Count
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Follow
/if (${Group.Leader.CleanName.Equal[${Me}]} || !${Group}) {
/varset Leader 0
} else {
/varset Leader 1
}
/if (${Leader} > 0) {
/if (${Group.Leader.Distance} > 10) {
/if (${Group.Leader.HeadingTo.Degrees} != ${Me.Heading.Degrees}) /squelch /face fast ${Group.Leader}
/keypress up hold
/call CheckStuck ${Me.X} ${Me.Y}
} else {
/if (${Me.Moving}) /keypress up
/if (${Group.Leader.Sitting} && !${Me.Sitting}) /sit
}
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub GetBehind
/declare TarHead int
/declare MeHead int
/declare NeutralHead int
/varset TarHead ${Target.Heading.Degrees}
/varset MeHead ${Me.Heading.Degrees}
/if (${Me.XTarget[1].ID} > 0) {
/if (${TarHead} < ${MeHead}) {
/varcalc NeutralHead ${MeHead} - ${TarHead}
} else {
/varcalc NeutralHead 360 - ${TarHead} + ${MeHead}
}
/if (${NeutralHead} > 180 && ${NeutralHead} < 330) {
/keypress strafe_left hold
/delay 1
/keypress strafe_left
} else /if (${NeutralHead} < 180 && ${NeutralHead} > 30) {
/keypress strafe_right hold
/delay 1
/keypress strafe_right
}
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub HealCast(Toon)
/target ${Group.Member[${Toon}]}
/delay 1s
/if (${Target.Distance} > ${HealRange}) {
/call StayInRange ${HealRange}
} else {
/if (${Me.Moving}) /keypress up
/call Cast "${HealSpell}" Gem${HealGem}
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub HealCheck
/declare Count int 0
/declare LowHealth 0
/declare CastRequired bool FALSE
/for Count 0 to ${Group}
/if (${Group.Member[${Count}].PctHPs} < ${HealTolerance} && !${Group.Member[${Count}].Dead}) {
/if (${Group.Member[${Count}].PctHPs} < ${Group.Member[${LowHealth}].PctHPs}) {
/varset LowHealth ${Count}
}
/varset CastRequired TRUE
}
/next Count
/return ${LowHealth}|${CastRequired}
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub LeaderAbilities
/if (${Group} && (${Group.MainAssist.CleanName.NotEqual[${Me}]} || !${Group.MainAssist.ID})) /grouproles set ${Me} 2
/if (${AutoMode} > 0) {
/squelch /target npc radius 40
/delay 1s (!${Target.ID})
/if (!${Target.ID} || ${Target.Dead} || ${Target.DistanceZ} > 50) {
/squelch /target npc los
/delay 1s (!${Target.ID})
}
/attack on
}
/if (${Me.Combat} && ${Target.CleanName.NotEqual[NULL]}) {
/call Event_Assist
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub LoadINI
/call ReadINI Ability
/call ReadINI AA
/call ReadINI TankAbility
/call ReadINI TankAA
/call ReadINI TankAAType
/call ReadINI BuffsName
/call ReadINI BuffsType
/call ReadINI BuffsTarget
/call ReadINI BuffsDuration
/call ReadINI BuffsRange
/call ReadINI AttacksName
/call ReadINI AttacksType
/call ReadINI AttacksTarget
/call ReadINI AttacksDuration
/call ReadINI AttacksRange
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_MemHeal(Line,Gem,Tolerance)
/declare SpellGem int 9
/declare SpellTolerance int 80
/if (${Gem}) /varset SpellGem ${Gem}
/if (${Tolerance}) /varset SpellTolerance ${Tolerance}
/if (!${Me.Class.DruidType} || !${Me.Class.ShamanType} || !${Me.Class.ClericType}) /return
/ini "Master.ini" "${Me}" "HealSpell" "${Me.Gem[${SpellGem}]}"
/ini "Master.ini" "${Me}" "HealGem" "${SpellGem}"
/ini "Master.ini" "${Me}" "HealTolerance" "${SpellTolerance}"
/ini "Master.ini" "${Me}" "HealRange" "${Me.Gem[${SpellGem}].Range}"
/varset HealSpell ${Me.Gem[${SpellGem}]}
/varset HealGem ${SpellGem}
/varset HealTolerance ${SpellTolerance}
/varset HealRange ${Me.Gem[${SpellGem}].Range}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_MemSpells(Line,Caller,List)
/declare Count int
/call CountGems
/if (${Me.Class.CanCast}) {
/for Count 1 to ${GemCount}
/ini "Master.ini" "${Me}" "${List}Name${Count}" "${Me.Gem[${Count}]}"
/ini "Master.ini" "${Me}" "${List}Type${Count}" "${Me.Gem[${Count}].SpellType}"
/ini "Master.ini" "${Me}" "${List}Target${Count}" "${Me.Gem[${Count}].TargetType}"
/ini "Master.ini" "${Me}" "${List}Duration${Count}" "${Me.Gem[${Count}].Duration}"
/ini "Master.ini" "${Me}" "${List}Range${Count}" "${Me.Gem[${Count}].Range}"
/if (${${Me}${List}NameArray.Size} > 0 && ${GemCount} <= ${${Me}${List}NameArray.Size}) {
/varset ${Me}${List}NameArray[${Count}] ${Me.Gem[${Count}]}
/varset ${Me}${List}TypeArray[${Count}] ${Me.Gem[${Count}].SpellType}
/varset ${Me}${List}TargetArray[${Count}] ${Me.Gem[${Count}].TargetType}
/varset ${Me}${List}DurationArray[${Count}] ${Me.Gem[${Count}].Duration}
/varset ${Me}${List}RangeArray[${Count}] ${Me.Gem[${Count}].Range}
} else /if (${Count} == ${GemCount}) {
/macro ${Macro}
}
/next Count
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_Moving(Line,Type)
/echo ${Line} ${Type}
/call VarSwap ${BackAttack} BackAttack
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Plugins
/plugin MQ2EQBC
/bccmd connect
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Event_Ranged
/if (${Me.Class.CanCast}) /call VarSwap ${RangedFight} RangedFight
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub RangerAttack
/declare MinRange int 40
/if (${Leader} > 0) /call TargetCheck
/call StayInRange ${InvSlot[Ammo].Item.Range} ${MinRange}
/if (!${Me.AutoFire}) /autofire
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub RangerSpells
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub ReadINI(ArrayType)
/declare nValues int local 1
/declare nArray int local 0
:CounterLoop
/if (${String[${Ini[Master.ini,"${Me}",${ArrayType}${nValues}]}].Equal[null]}) {
/varcalc nValues ${nValues}-1
/goto :MakeArray
}
/varcalc nValues ${nValues}+1
/goto :CounterLoop
:MakeArray
/if (!${nValues}) /return
/if (${nValues} > 0) {
/declare ${Me}${ArrayType}Array[${nValues}] string outer
}
/for nArray 1 to ${nValues}
/varset ${Me}${ArrayType}Array[${nArray}] ${Ini[Master.ini,"${Me}",${ArrayType}${nArray}]}
/next nArray
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub StayInRange(MaxRange,MinRange)
/if (${Target.ID}) /face fast
/if (${Target.Distance} > ${MaxRange}) {
/keypress up hold
} else /if (${Target.Distance} < ${MinRange}) {
/keypress back hold
} else {
/keypress up
/keypress back
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub StayOnTarget
/declare Range int
/if (${Leader} > 0) /call TargetCheck
/if (${Target.ID} && !${Me.XTarget[1].Dead}) {
/varcalc Range ${Target.MaxRangeTo}/2
/if (${Target.HeadingTo.Degrees} != ${Me.Heading.Degrees}) /face fast
/if (${Target.Distance} > ${Range}) {
/keypress up hold
/call CheckStuck ${Me.X} ${Me.Y}
} else {
/keypress up
/if (${Me.PctAggro} < 100 && ${BackAttack} > 0) /call GetBehind
}
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub TargetCheck
/if (!${Target.ID} || ${Target.Dead} || ${Me.XTarget[1].ID}!=${Target.ID}) {
/assist ${Group.Leader}
/delay 1s
}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub Tasks
/doevents
/call Follow
/if (${Leader} < 1) {
/call LeaderAbilities
}
/if (${Me.XTarget} < 1 && ${Me.Combat}) /attack off
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub VarSwap(Variable, Name)
/if (${Variable} > 0) {
/varset Variable 0
} else {
/varset Variable 1
}
/varset ${Name} ${Variable}
/return
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Code: Select all
#include Common
Sub Main
/xtarget set 1 gat
/call Variables
/call Plugins
/call LoadINI
:Beast
/call Tasks
/goto :Beast
/return
Code: Select all
[CharacterName]
Ability1=Kick
[OtherCharacterName]
Ability1=Kick
TankAbility1=Taunt
[OtherOtherCharacterName]
Ability1=Kick


donations for this month's patches.