TheNomadMan
New member
- Joined
- Feb 8, 2014
- RedCents
- 451¢
So; I finally got some time to put in a few changes to heals.
-Heal Loop: The current heal loop does not loop back to the top after each successful heal cast. Instead, it continues on down the heal logic and then restarts from the bottom. IMO this defeats the purpose. In order to make a good logic based "decision" on the next heal, it must start at the top after each successful heal.
-Group Heal: The current Group Heal logic is based solely on the group average. While this metric is necessary, it's also insufficient for deciding if a group heal is required. So; I put in a system to determine the number of people currently in need of a heal. This way; if only one person needs a heal, only single heals will fire. This could easily be turned in to a ini setting if for some reason single target group healing, or a higher threshold, is desired.
-Heal Order: With the group heal no longer firing on single targets, moving the group heal to the front of the line becomes an option. And; one that I find to be very effective and efficient.
-XTarget Healing: Currently only one XTarget Heal-Target is allowed, the slot must be specified in the ini, and this does not work for NPC's. On raids we need a lot more than one Xtarget slot, we need to be able to switch slots on-the-fly, we need it to work for pet tanks and/or protected NPCs and we need it to be snappy. So; I've rigged up exactly that. if Xtarget healing is on; the ${AggroTargetID} now swiches on-the-fly, any player/npc/pet can be added to (or removed from) any xtarget slot at any time without restarting the macro or messing up the DPS targeting, and the hard delays have been pulled out.
-Healing tags: In an attempt to have the smartest healer out there, I had been adding new tags (Mob, XT, Me, etc). Eventually my heal spell array was 25 deep with three entries for everything, defined different ways. So; I ended up reflowing the heal section in such a manner that everything I was trying to do with all these tags is just part of the normal heal logic and all the tags could be dropped. Now I have a single entry for all heal spells, no tags, and it's all much simpler to setup and run with. All such tags are still valid if one wishes to over-ride the built-in logic. But after seeing this tag-less system in action, we haven't found a call to tag anything; yet.
-Rezzing: All healers have at least two options for rezzing. A "call" for +mana or a "rez" for +xp. In the case of shammies/druids this isn't so much of an option as a requirement, use call in combat, rez after. Added an option to define your Battle Rez spell and OOC rez spell seprate like. I will be adding a "do not rez if player is already in zone" option, soon, too. Because it sucks having rebuffed and run back only to have auto-rez start ya over.
-DPS/Buffs Interrupt- I like my healers to have some utility to them, and to use spells other than healing spells to keep the group in good shape (DI, twin-heal nukes, stuns, etc.). But I'm unwilling to allow them to cast these spells at the cost of a group member going down. So, yeah; being able to monitor the health of at least Self and MA, if not the entire group, and duck-out of a DPS or Buff in order to cast a heal is a must IMO. This requires going back to MQ2Cast and using while loops. The aforementioned whiles are based on advice garnered here.
-Mana Buffs, in combat: These were eating up more time than I felt the bot could afford to use on them, but at the same time the bot needs mana now and then. Pulled out the delays and smoothed the transition back in to the heal loop.
-Breaking Invis: I often run from place to place with my boxes in-tow. When doing so; I want them to support me if I get in to a fight, but I do not want them breaking invis and starting a fight. Added a condition to CastWhat that prevents casting if invis and is no mob exists on Xtarget.
-That's all that I remember off top my head, at the moment. I'll attach a functional example called "RaidAssist", at the bottom. Now, on to the code:
- - - Updated - - -
Example of my old cleric [Heals]
And: my new cleric [Heals] after the above code changes.
-Heal Loop: The current heal loop does not loop back to the top after each successful heal cast. Instead, it continues on down the heal logic and then restarts from the bottom. IMO this defeats the purpose. In order to make a good logic based "decision" on the next heal, it must start at the top after each successful heal.
-Group Heal: The current Group Heal logic is based solely on the group average. While this metric is necessary, it's also insufficient for deciding if a group heal is required. So; I put in a system to determine the number of people currently in need of a heal. This way; if only one person needs a heal, only single heals will fire. This could easily be turned in to a ini setting if for some reason single target group healing, or a higher threshold, is desired.
-Heal Order: With the group heal no longer firing on single targets, moving the group heal to the front of the line becomes an option. And; one that I find to be very effective and efficient.
-XTarget Healing: Currently only one XTarget Heal-Target is allowed, the slot must be specified in the ini, and this does not work for NPC's. On raids we need a lot more than one Xtarget slot, we need to be able to switch slots on-the-fly, we need it to work for pet tanks and/or protected NPCs and we need it to be snappy. So; I've rigged up exactly that. if Xtarget healing is on; the ${AggroTargetID} now swiches on-the-fly, any player/npc/pet can be added to (or removed from) any xtarget slot at any time without restarting the macro or messing up the DPS targeting, and the hard delays have been pulled out.
-Healing tags: In an attempt to have the smartest healer out there, I had been adding new tags (Mob, XT, Me, etc). Eventually my heal spell array was 25 deep with three entries for everything, defined different ways. So; I ended up reflowing the heal section in such a manner that everything I was trying to do with all these tags is just part of the normal heal logic and all the tags could be dropped. Now I have a single entry for all heal spells, no tags, and it's all much simpler to setup and run with. All such tags are still valid if one wishes to over-ride the built-in logic. But after seeing this tag-less system in action, we haven't found a call to tag anything; yet.
-Rezzing: All healers have at least two options for rezzing. A "call" for +mana or a "rez" for +xp. In the case of shammies/druids this isn't so much of an option as a requirement, use call in combat, rez after. Added an option to define your Battle Rez spell and OOC rez spell seprate like. I will be adding a "do not rez if player is already in zone" option, soon, too. Because it sucks having rebuffed and run back only to have auto-rez start ya over.
-DPS/Buffs Interrupt- I like my healers to have some utility to them, and to use spells other than healing spells to keep the group in good shape (DI, twin-heal nukes, stuns, etc.). But I'm unwilling to allow them to cast these spells at the cost of a group member going down. So, yeah; being able to monitor the health of at least Self and MA, if not the entire group, and duck-out of a DPS or Buff in order to cast a heal is a must IMO. This requires going back to MQ2Cast and using while loops. The aforementioned whiles are based on advice garnered here.
-Mana Buffs, in combat: These were eating up more time than I felt the bot could afford to use on them, but at the same time the bot needs mana now and then. Pulled out the delays and smoothed the transition back in to the heal loop.
-Breaking Invis: I often run from place to place with my boxes in-tow. When doing so; I want them to support me if I get in to a fight, but I do not want them breaking invis and starting a fight. Added a condition to CastWhat that prevents casting if invis and is no mob exists on Xtarget.
-That's all that I remember off top my head, at the moment. I'll attach a functional example called "RaidAssist", at the bottom. Now, on to the code:
Rich (BB code):
| ************************* Heals ***************************************|
/call LoadIni Heals Help string "Format Spell|% to heal at i.e. Devout Light Rk. II|50"
/call LoadIni Heals HealsOn int 0
/if (${Select[${Me.Class.ShortName},CLR,SHM,DRU,PAL,ENC]}) {
/declare Heals[20] string outer
} else {
/declare Heals[5] string outer
}
/call LoadIni Heals Heals string NULL Heals
/call LoadIni Heals XTarHeal int 0
/call LoadIni Heals InterruptHP int "At What HP% for Me/MA to abort casting and heal. 0=OFF"
/if (${Select[${Me.Class.ShortName},CLR,NEC,SHM,DRU,PAL]}) {
/call LoadIni Heals AutoRezOn int 0
/call LoadIni Heals AutoRezWith string "Your Battle Rez Item/AA/Spell"
/call LoadIni Heals OOCRezWith string "Your OOC Rez Item/AA/Spell"
}
| ************************* Cures ***************************************|
Rich (BB code):
/declare TaskGiver string outer
/declare HealAgain int outer 0
/declare ManyHurt int outer 0
| Set AA DurationMod for various timer from Spell Casting Reinforcement AA
/if (${Me.AltAbility[Spell Casting Reinforcement]}==6) /varset DurationMod 1.15
Rich (BB code):
| ----------------------------------------------------------------------------
| SUB: CheckHealth
| ----------------------------------------------------------------------------
Sub CheckHealth
/if (!${HealsOn}) /return
/if (${DebugHeal}) /echo Sub CheckHealth enter
/declare x int local 1
/declare i int local 0
/declare j int local 1
/declare NewHaters int local 0
/declare MostHurtName string local
/declare MostHurtType string local
/declare MostHurtID int local 0
/declare MostHurtHP int local 100
/declare MostHurtNo int local 0
/declare GroupHealthAvg string local 0
:CheckAgain
/varset MostHurtName
/varset MostHurtType
/varset MostHurtID
/varset MostHurtHP 100
/varset MostHurtNo 0
/varset HealAgain 0
/varset GroupHealthAvg 0
| Group Heal Check only call for those clases that can group heal
/if (${Select[${Me.Class.ShortName},BST,CLR,SHM,DRU,PAL,ENC]}) {
/call GroupHealthCheck
/varset GroupHealthAvg ${Macro.Return}
/if (${DebugHeal}) /echo Group Health Average ${GroupHealthAvg}
| Check for group heals
/if (${GroupHealthAvg} < 100 && ${Group} && ${ManyHurt}>1) {
/call DoGrouopHealStuff ${GroupHealthAvg}
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
}
| Check self health
/if (${Me.PctHPs} < 100) {
/call SingleHeal "${Me}" PC ${Me.PctHPs} 0
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
| Call group health check for only those that can heal others
/if (${Select[${Me.Class.ShortName},BST,CLR,SHM,DRU,RNG,PAL,ENC]}) {
| This is to target Main Assist out of group if class can heal
/if (${Select[${HealsOn},1,3]} && !${Spawn[${MainAssist} ${MainAssistType} group].ID} && ${Spawn[${MainAssist} ${MainAssistType}].ID} && ${Spawn[${MainAssist} ${MainAssistType}].Type.NotEqual[corpse]} && ${Spawn[${MainAssist}].ID}!=${Me.Pet.ID} && ${Spawn[${MainAssist}].ID}!=${Me.ID}) {
| Skip targeting tank if MA is defined to watch for heals in XTarget
| /if (!${XTarHeal} || ${XTarHeal} && ${Me.XTarget[${XTarHeal}].ID}!=${Spawn[${MainAssist} ${MainAssistType}].ID}) {
| /target id ${Spawn[${MainAssist} ${MainAssistType}].ID}
| /delay 5
| }
/if (${DebugHeal}) /echo Tank OOG: ${Spawn[${MainAssist}].PctHPs} ${Spawn[${MainAssist} ${MainAssistType}].ID} ${Spawn[${MainAssist} ${MainAssistType}].Type.NotEqual[corpse]}
/if (${Spawn[${MainAssist} ${MainAssistType}].PctHPs} < 100) {
/call SingleHeal "${MainAssist}" "${MainAssistType}" ${Spawn[${MainAssist} ${MainAssistType}].PctHPs} 6
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
} else {
/if (${Select[${HealsOn},3]} ${Spawn[${MainAssist} ${MainAssistType}].PctHPs} < 100) /call SingleHeal "${MainAssist}" "${MainAssistType}" ${Spawn[${MainAssist} ${MainAssistType}].PctHPs} 6
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
| Who is the most hurt
/if (${Select[${HealsOn},1,2]} && ${Group} && !${JustZoned} && !${JoinedParty}) {
/for i 0 to ${Group}
/if (${Group.Member[${i}].ID}==${Spawn[${MainAssist} ${MainAssistType}].ID}) /goto :NextGMember
/if (${Group} && ${Group.Member[${i}].ID} && ${Group.Member[${i}].Type.NotEqual[corpse]} && ${Group.Member[${i}].PctHPs}>=1) {
/if (${DebugHeal}) /echo -- Most Hurt:${i} ${MostHurtNo} ${MostHurtName} ${MostHurtID} ${MostHurtHP}
/if (${Group.Member[${i}].PctHPs} < ${MostHurtHP}) {
/varset MostHurtName ${Group.Member[${i}].CleanName}
/varset MostHurtType ${Group.Member[${i}].Type}
/varset MostHurtID ${Group.Member[${i}].ID}
/varset MostHurtHP ${Group.Member[${i}].PctHPs}
/varset MostHurtNo ${i}
}
}
:NextGMember
/next i
/if (${MostHurtHP} < 100) {
/call SingleHeal "${MostHurtName}" "${MostHurtType}" ${MostHurtHP} ${MostHurtNo}
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
}
}
| Check xtarget health if on.
/if (${XTarHeal}) {
/varset NewHaters 0
/for j 1 to ${XSlotTotal}
/if (${NewHaters}==0 && ${Me.XTarget[${j}].TargetType.Equal[Auto Hater]}) {
/varcalc NewHaters ${NewHaters}+1
/varset XTSlot ${j}
}
/next j
/for x 1 to ${XSlotTotal}
/if (${Select[${Spawn[${Me.XTarget[${x}].ID}].Type},PC,NPC,Pet]} && ${Me.XTarget[${x}].ID} && ${Spawn[${Me.XTarget[${x}].ID}].PctHPs}<100) {
/call SingleHeal "${Spawn[${Me.XTarget[${x}].ID}]}" "${Spawn[${Me.XTarget[${x}].ID}].Type}" ${Spawn[${Me.XTarget[${x}].ID}].PctHPs} 7
/if (${DebugHeal}) /echo Sub CheckHealth XtargetHeal "${Spawn[${Me.XTarget[${x}].ID}].CleanName}" "${Spawn[${Me.XTarget[${x}].ID}].Type}" ${Spawn[${Me.XTarget[${x}].ID}].PctHPs} 7
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
}
/next x
}
/if (${AutoRezOn}) /call RezCheck
/if (${PetOn} && ${Me.Pet.ID} && ${Me.Pet.PctHPs} < 100) /call DoPetHealStuff
/if (${DebugHeal}) /echo Sub CheckHealth leave
/if (${HealAgain}) {
/delay 5
/goto :CheckAgain
}
/return
|----------------------------------------------------------------------------
Rich (BB code):
| ----------------------------------------------------------------------------
| SUB: Group Health Check
| ----------------------------------------------------------------------------
Sub GroupHealthCheck
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS GroupHealthCheck Enter
/declare j int local 0
/declare GroupHealthTl float local .1
/declare GroupHealthPct float local 0
/declare NotDead int local 0
/varset ManyHurt 0
/for j 0 to ${Group}
/if (${Group} && ${Group.Member[${j}].ID} && ${Group.Member[${j}].Type.NotEqual[corpse]}) {
| Calculate total group health for group heal spells
/if (${Group.Member[${j}].Distance}<100) {
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS GroupHealthCheck Group Health: GM:${j} Health:${Group.Member[${j}].PctHPs}
/varcalc GroupHealthTl ${GroupHealthTl}+${Group.Member[${j}].PctHPs}
/varcalc NotDead ${NotDead}+1
/varcalc GroupHealthPct ${GroupHealthTl}/${NotDead}
/if (${Group.Member[${j}].PctHPs}<100) /varcalc ManyHurt ${ManyHurt}+1
}
}
/next j
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS GroupHealthCheck Leave ${GroupHealthPct}
/return ${GroupHealthPct}
| ----------------------------------------------------------------------------
Rich (BB code):
|----------------------------------------------------------------------------
| SUB: Single Heals
|----------------------------------------------------------------------------
Sub SingleHeal(SHealName, SHealType, int SHealHPs, int WhoNum)
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal !${HealsOn} || ${Me.Moving} || ${Window[RespawnWnd]} || !${Spawn[${SHealName} ${SHealType}].ID} || !${Select[${SHealType},PC,Pet,Mercenary]}
/if (!${HealsOn} || ${Me.Moving} || ${Window[RespawnWnd]} || !${Spawn[${SHealName} ${SHealType}].ID} || !${Select[${SHealType},PC,Pet,Mercenary]}) /return
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal ${SHealName} ${SHealType} ${SHealHPs} ${WhoNum}
/doevents
/declare i int local 0
/declare SHealSpell string local
/declare SHealPct int local
/declare SHealTag string local
/declare SHealThem int local ${Spawn[${SHealName} ${SHealType}].ID}
/declare MainAssistID int local ${Spawn[=${MainAssist}].ID}
/declare SHealRange int local 0
| Set MA Id to 6 to keep spell durations correct
/if (${WhoNum}!=6 && ${SHealThem}==${MainAssistID}) /varset WhoNum 6
/for i 1 to ${SingleHeal.Size}
| If heal is null or off |0 or spell/aa/item not ready skip it
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Spell ${i}: ${SingleHeal[${i}]} ${SingleHeal[${i}].Arg[1,|]} ${SingleHeal[${i}].Arg[2,|]} ${SingleHeal[${i}].Arg[3,|]}
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal SpellSkip: !${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}}
/if (!${SingleHeal[${i}].Length} || ${SingleHeal[${i}].Arg[2,|].Equal[0]}) /goto :SNextHeal
/if ((!${IAmABard} && !${Cast.Ready[${SingleHeal[${i}]}]}) && (${Me.SpellReady[${Me.Gem[1].Name}]} || ${Me.SpellReady[${Me.Gem[2].Name}]} || ${Me.SpellReady[${Me.Gem[3].Name}]} || ${Me.SpellReady[${Me.Gem[4].Name}]} || ${Me.SpellReady[${Me.Gem[5].Name}]} || ${Me.SpellReady[${Me.Gem[6].Name}]} || ${Me.SpellReady[${Me.Gem[7].Name}]} || ${Me.SpellReady[${Me.Gem[8].Name}]})) /goto :SNextHeal
/varset SHealSpell ${SingleHeal[${i}].Arg[1,|]}
/varset SHealPct ${SingleHeal[${i}].Arg[2,|]}
/varset SHealTag ${SingleHeal[${i}].Arg[3,|]}
/varset SHealRange ${Spell[${SHealSpell}].Range}
/if (${Spell[SHealSpell].TargetType.Find[Group]}) /varset SHealRange ${Spell[${SHealSpell}].AERange}
/if (!${SHealRange}) /varset SHealRange 100
| Check Heal Tags and skip as needed.
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal TAG: ${SHealTag.Equal[MA]} && ${SHealThem}!=${MainAssistID} || ${SHealTag.Equal[!MA]} && ${SHealThem}==${MainAssistID}
/if (${SHealTag.Equal[pet]}) /goto :SNextHeal
/if (${SHealTag.Equal[Me]} && ${SHealThem}!=${Me.ID}) /goto :SNextHeal
/if (${SHealTag.Equal[!MA]} && ${SHealThem}==${MainAssistID}) /goto :SNextHeal
/if (${SHealTag.Equal[Mob]} && ${SHealThem}!=${MainAssistID}) /goto :SNextHeal
/if (${SHealTag.Equal[MA]} && ${SHealThem}!=${MainAssistID}) /goto :SNextHeal
/if (${SHealTag.Equal[XT]} && ${SHealThem}!=${Me.XTarget[1].ID} && ${SHealThem}!=${Me.XTarget[2].ID} && ${SHealThem}!=${Me.XTarget[3].ID} && ${SHealThem}!=${Me.XTarget[4].ID} && ${SHealThem}!=${Me.XTarget[5].ID} && ${SHealThem}!=${Me.XTarget[6].ID} && ${SHealThem}!=${Me.XTarget[7].ID} && ${SHealThem}!=${Me.XTarget[8].ID}) /goto :SNextHeal
| Cleric Divine Arbitration and Epics do not work on pets
/if ((${Spawn[${SHealThem}].Type.Equal[Pet]} || !${Spawn[${SHealName} ${SHealType} group].ID}) && (${HealSpell.Find[Aegis of Superior Divinity]} || ${HealSpell.Find[Harmony of the Soul]} || ${HealSpell.Find[Divine Arbitration]})) /goto :SNextHeal
| Check For Life Taps
/if (${SHealTag.Find[Tap]}) {
/if (!${Pulled} && ${CombatStart} && ${Me.PctHPs}<=${SHealPct} && ${Spawn[${MyTargetID}].ID} && ${Spawn[${MyTargetID}].Distance}<=${SHealRange} && ${Spell${i}GM0}==0) {
/call CastWhat "${SHealSpell}" ${Spawn[${MyTargetID}].ID} Heal
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/call BroadCast ${IRCOn} ${EQBCOn} o "${SHealSpell} for >> ${Me.CleanName} <<"
/varcalc Spell${i}GM0 (${Spell[${SHealSpell}].Duration.TotalSeconds}*${DurationMod})*10
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Assign Timer:Spell${i}GM0 (${Spell[${SHealSpell}].Duration.TotalSeconds}*${DurationMod}) ${Spell${i}GM0}
/varset HealAgain 1
/return
}
} else {
/goto :SNextHeal
}
}
| Check For Nuke Heals
/if (${SHealTag.Find[Mob]}) {
/if (!${AggroTargetID}) /goto :SNextHeal
/doevents Switch
/if (!${MyTargetID} || ${Spawn[${MyTargetID}].Type.Equal[Corpse]}) /call Assist Heals
/if (${MyTargetID} && ${Spawn[${MainAssist}].PctHPs}<=${SHealPct} && ${Spawn[${MyTargetID}].LineOfSight} && ${Spawn[${MyTargetID}].Distance}<=${SHealRange} && !${Spawn[${MyTargetID}].Type.Equal[Corpse]}) {
/call CastWhat "${SHealSpell}" ${Spawn[${MyTargetID}].ID} Heal
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/call BroadCast ${IRCOn} ${EQBCOn} o "${SHealSpell} for ${SHealThem} >> Heal Nuke << aginst ${Spawn[${MyTargetID}]} "
/varset HealAgain 1
/return
}
} else {
/goto :SNextHeal
}
}
| Check conditons for heals
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal ${SHealHPs}<=${SHealPct} && ${Spawn[${SHealName} ${SHealType}].Distance}<=${SHealRange} && ${Spell${i}GM${WhoNum}}==0
/if (${SHealHPs}<=${SHealPct} && ${Spawn[${SHealName} ${SHealType}].Distance}<=${SHealRange} && ${Spell${i}GM${WhoNum}}==0) {
/if (${Select[${EverQuest.Server},zek]} && ${Select[${Target.Type},PC]} && ${Me.Combat}) {
/attack off
/delay 25 !${Me.Combat}
}
/call CastWhat "${SHealSpell}" ${SHealThem} Heal
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal MR: ${Macro.Return}
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/call BroadCast ${IRCOn} ${EQBCOn} o "${SHealSpell} on >> ${Spawn[${SHealName} ${SHealType}].CleanName} <<"
/varcalc Spell${i}GM${WhoNum} (${Spell[${SHealSpell}].Duration.TotalSeconds}*${DurationMod})*10
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Assign Timer:Spell${i}GM${WhoNum} ${Spell[${SHealSpell}].Duration.TotalSeconds}*${DurationMod} ${Spell${i}GM${WhoNum}}
/varset HealAgain 1
/return
}
}
:SNextHeal
/next i
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS SingleHeal Leave
/return
Rich (BB code):
| Wait for global cooldown active
:Waitforcooldown
/if (!${IAmABard} && !${Cast.Ready[${castWhat}]} && !${Me.SpellReady[${Me.Gem[1].Name}]} && !${Me.SpellReady[${Me.Gem[2].Name}]} && !${Me.SpellReady[${Me.Gem[3].Name}]} && !${Me.SpellReady[${Me.Gem[4].Name}]} && !${Me.SpellReady[${Me.Gem[5].Name}]} && !${Me.SpellReady[${Me.Gem[6].Name}]} && !${Me.SpellReady[${Me.Gem[7].Name}]} && !${Me.SpellReady[${Me.Gem[8].Name}]}) {
/delay 1
/goto :Waitforcooldown
}
/if (${Cast.Ready[${castWhat}]} && !${IAmABard}) {
/casting "${castWhat}"
|Monitor MA/Me HP While Casting. Abort if InterruptHP is hit.
:MonitorHPWhileCasting
/if (${sentFrom.NotEqual[Heal]} && ${sentFrom.NotEqual[Mez]} && ${HealsOn} && ${Spawn[${MainAssist} ${MainAssistType}].PctHPs}<=${InterruptHP}) {
/docommand /stopcast
/echo ${sentFrom} spell ${castWhat} ABORTED to cast a heal!
/call CheckHealth
}
/if (${sentFrom.Equal[Heal]} && ${HealsOn} && ${${Cast.Status}.Equal[C]}) {
/delay 1
/goto :MonitorHPWhileCasting
}
:Stillcasting
/if (${${Cast.Status}.Equal[C]}) {
/delay 1
/goto :Stillcasting
}
/varset CastResult ${Cast.Return}
/if (${Debug}) /echo DEBUG CastWhat cast Spell result: ${Macro.Return}
/doevents
/call CheckCasting 50
}
/if (${IAmABard}) {
/squelch /twist once ${Me.Gem[${castWhat}]}
/varset CastResult CAST_SUCCESS
}
}
/if (${WasTwisting} && !${Twist}) /squelch /twist
/if (${Debug}) /echo DEBUG CastWhat Leave ${CastResult}
/return ${CastResult}
Rich (BB code):
| -------------------------------------------------------------------------------------
| SUB: Rez Check
| -------------------------------------------------------------------------------------
Sub RezCheck
/if (!${AutoRezOn} || ${DMZ} || ${Me.Hovering}) /return
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS RezCheck Enter
/declare i int local
/declare j int local
/declare CorpseCount int local
/declare RezMeID int local
/declare RezID int local
/declare RezRadius int local 150
| Does Group Member have a corpse?
/for i 1 to ${Group}
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS RezCheck ${BattleRezTimer${i}}==0 && ${Spawn[${Group.Member[${i}].CleanName} corpse].Distance}<${RezRadius} ${Spawn[${Group.Member[${i}].CleanName} corpse].Deity.ID} || !${Cast.Ready[${AutoRezWith}]}
/if (!${Spawn[${Group.Member[${i}].CleanName} pccorpse].ID} || !${Cast.Ready[${AutoRezWith}]}) /goto :NextChar
| Check for group member corpses and battle rez
/if (${BattleRezTimer${i}}==0 && ${Spawn[${Group.Member[${i}].CleanName} corpse].Distance}<${RezRadius}) {
/squelch /tar id ${Spawn[${Group.Member[${i}].CleanName} corpse].ID}
/delay 10 ${Target.ID}
/if (${Target.Distance}<100) {
/if (${Target.Distance}>${CampRadius} && !${Target.CleanName.Find[${MainAssist}]}) /corpse
/delay 10
/call CastWhat "${AutoRezWith}" ${Target.ID}
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/call BroadCast ${IRCOn} ${EQBCOn} o "BATTLE REZZED =>> ${Group.Member[${i}]} <<="
/varset BattleRezTimer${i} 3m
} else {
/if (${Group.Member[${i}].Name.NotEqual[${MainAssist}]}) /varset BattleRezTimer${i} 1m
}
}
}
:NextChar
/next i
| Out of Combat Rez |
/varset CorpseCount ${SpawnCount[corpse radius ${RezRadius} zradius 50]}
/if (${CorpseCount}>0 && !${CombatStart}) {
| Do I have a Corpse
/varset RezMeID ${Spawn[corpse ${Me} radius ${RezRadius} zradius 50].ID}
/if (${RezMeID} && ${OOCRezTimer${RezMeID}}==0 && ${Cast.Ready[${OOCRezWith}]}) {
/if (!${Defined[OOCRezTimer${RezMeID}]}) /declare OOCRezTimer${RezMeID} timer outer 1m
/target id ${RezMeID}
/delay 10 ${Target.ID}
/if (${Target.Distance}>${CampRadius}) /corpse
/delay 10
/call CastWhat "${OOCRezWith}" ${Target.ID}
/if (${Macro.Return.Equal[CAST_SUCCESS]}) /varset OOCRezTimer${RezMeID} 3m
}
/for j 1 to ${CorpseCount}
/varset RezID ${NearestSpawn[${j},pccorpse radius ${RezRadius} zradius 50].ID}
/if (${Spawn[${RezID}].Type.Equal[corpse]} && ${OOCRezTimer${RezID}}==0 && ${Cast.Ready[${OOCRezWith}]} && (${Spawn[${RezID}].Guild.Equal[${Me.Guild}]} || ${Spawn[${Me.Fellowship.Member[${Spawn[${RezID}].CleanName.Left[-9]}]} pccorpse].ID} || ${XTarHeal} && ${Spawn[${RezID}].ID}==${Me.XTarget[${XTarHeal}].ID})) {
/target id ${RezID}
/delay 10 ${Target.ID}==${RezID}
/if (!${Defined[OOCRezTimer${RezID}]}) /declare OOCRezTimer${RezID} timer outer 1m
/if (${Target.Distance}<=${RezRadius}) {
/call CastWhat "${OOCRezWith}" ${Target.ID}
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/call BroadCast ${IRCOn} ${EQBCOn} o "Rezzing =>> ${Target.CleanName} <<="
/varset OOCRezTimer${RezID} 5m
/delay 30 !${Me.Casting.ID}
}
}
}
/next j
}
/if (${DebugHeal} || ${DebugAll}) /echo DEBUGHEALS RezCheck Leave
/Return
| -------------------------------------------------------------------------------------
Rich (BB code):
| Check and Cast mana type spells/aas/items - Canni/Paragon/Harvest
/if (${2ndPart.Equal[Mana]} && ${Buff${i}GM${j}}==0) {
/if (${Me.Class.Name.Equal[Bard]} && ${Me.PctMana}<=${3rdPart}) {
/if (${DebugBuffs}) /echo DEBUGBUFFS Bard Mana
/call CastWhat "${1stPart}" ${Me.ID} Buffs
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/echo Casting >> ${1stPart} << for mana
/varcalc Buff${i}GM${j} (${Spell[${1stPart}].RecastTime})*10+35
}
| Combat check to return - no other buffing allowed
/goto :SkipBuff
}
/if (${Me.PctMana}<=${3rdPart} && ${Me.PctHPs}>${4thPart} && ${Cast.Ready[${1stPart}]}) {
/if (${DebugBuffs}) /echo DEBUGBUFFS Canni/Paragon/Harvest/Bear
| Check for stupid druid bear
/if (${Me.Class.Name.Equal[Druid]} && ${1stPart.Find[Nurturing Growth]} && (${Me.Buff[Nurturing Growth].ID} || ${Me.Buff[Nurturing Growth RK. II].ID} || ${Me.Buff[Nurturing Growth Rk. III].ID})) /goto :SkipBuff
/call CastWhat "${1stPart}" ${Me.ID} Buffs
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/echo Casting >> ${1stPart} << for mana
/varcalc Buff${i}GM${j} (${Spell[${1stPart}].Duration.TotalSeconds}*${DurationMod})*10
}
| Combat check to return - no other buffing allowed
/goto :SkipBuff
}
}
Rich (BB code):
Sub CastWhat(string castWhat,int castTargetID,string sentFrom)
/if (${Debug}) /echo DEBUG CastWhat: Enter castWhat - ${castWhat} castTargetID - ${castTargetID}
/declare WasTwisting bool local ${Twist}
/varset CastResult CAST_NO_RESULT
/if (${Me.Invis} && !${AggroTargetID}) {
/varset CastResult CAST_IM_INVIS
/return ${CastResult}
}
- - - Updated - - -
Example of my old cleric [Heals]
Rich (BB code):
[Heals]
Help=Format Spell|% to heal at i.e. Devout Light Rk. II|50
HealsOn=1
Heals1=Fifteenth Emblem Rk. III|45
Heals2=Burst of Life|45
Heals3=Beacon of Life|45
Heals4=Graceful Remedy Rk. III|45|!MA
Heals5=Forceful Rejuvenation|45
Heals6=Graceful Remedy Rk. III|95|MA
Heals7=Virtuous Intervention Rk. III|95
Heals8=Virtuous Contravention|95|Mob
Heals9=Fraught Renewal Rk. II|95|MA
Heals10=Fervent Renewal|95|MA
Heals11=Frenzied Renewal Rk. II|95|MA
Heals12=Graceful Remedy Rk. III|95|XT
Heals13=Virtuous Intervention Rk. III|95|XT
Heals14=Fraught Renewal Rk. II|95|XT
Heals15=Fervent Renewal|95|XT
Heals16=Frenzied Renewal Rk. II|95|XT
Heals17=Word of Reformation|99
Heals18=Frenzied Renewal Rk. II|99
XTarHeal=8
AutoRezOn=1
AutoRezWith=Blessing of Resurrection
OOCRezWith=Blessing of Resurrection
InterruptHP=55
And: my new cleric [Heals] after the above code changes.
Rich (BB code):
[Heals]
Help=Format Spell|% to heal at i.e. Devout Light Rk. II|50
HealsOn=1
Heals1=Fifteenth Emblem Rk. III|45
Heals2=Burst of Life|45
Heals3=Beacon of Life|85
Heals4=Graceful Remedy Rk. III|95
Heals5=Forceful Rejuvenation|45
Heals6=Virtuous Intervention Rk. III|95
Heals7=Fraught Renewal Rk. II|95
Heals8=Fervent Renewal|95
Heals9=Frenzied Renewal Rk. II|95
Heals10=Word of Reformation Rk. III|99
Heals11=NULL
Heals12=NULL
Heals13=NULL
Heals14=NULL
Heals15=NULL
Heals16=NULL
Heals17=NULL
Heals18=NULL
Heals19=NULL
Heals20=NULL
XTarHeal=1
AutoRezOn=0
AutoRezWith=Blessing of Resurrection
OOCRezWith=Blessing of Resurrection
InterruptHP=55
Attachments
Last edited:


