My Shmmybot and Problem

KingArthur

AutoBots
Joined
Dec 15, 2009
Messages
525
Reaction score
31
Points
28
I made this shmbot based on Devestator's Clericbot,so 99% credits should go to Big D.:p

The main goal of this shmmy bot is

1.slow at the very begining of combat, that means slow MUST cast before 95%,normally I wanna it cast when puller inc(at 98% or so..)---btw,Maskoi's shambot is awesome but i just cant let it slow as I wish no matter how I change the variables.

2.heal like clr..

So here it is,basically changed spell name,and ADD a Sub Slow at the start of mainloop with /call slow

Code:
| =================================================================================================
| 									   ShmBot v1.31
| 									Written By: Devestator						
| 													
| 													
| USAGE: /macro shmBot <IniName>
| 													
| 													
| Description:												
|  This is a bot meant to automate the role of a Shaman in a group.  The goal of this bot is to
|  be as mana efficient as possible and require little to know input once started.									
| 													
| 													
| Requirements:												
|  MQ2Cast_Spell_Routines.inc										
|  devMovement.inc
|  devCommon.inc											
|  clericBotSettings.ini (you can create custom INIs nameing them clericBotSettings_name.ini			
|  PLUGIN: MQ2Cast
|  PLUGIN: MQ2Debuffs													
|  PLUGIN: MQ2Exchange
| 
| V1.31 Update Notes
|  -Added the ability to heal watch list members and their pets
|  -Corrected a bug with group heals that would cancel the heal if the target was full on hitpoints
|  -Added command healpets, this will turn healing of pets on and off.
|  -Added a routine CombatCall, to check for heals while buffing if you have in combat buffs.
|  -Corrected a bug that could cause group heals to be cast if there were fewer group members than specified.
| 
| V1.30 Update Notes
|  -Corrected a parenthesis error in the reztarget function -Thanks Blujahz for pointing it out.
|  -Corrected a typo in the LoadSettings routine dealing with AABalance. (Thanks Kombat03)
|  -Modified for devCommon.inc v1.80 and devMovement.inc v1.60
|  -Added the ability to heal pets.  New INI Setting: [General] HealPets=True / False
|  -Can now use Debuffs as part of devCommon.inc v1.80
| 
| V1.20 Update Notes
|  -Added promise and hot tracking for more than one player at a time
|  -Added checks to prevent using heal spells that are not memmed and have a long recast time.
|  -Added checks to prevent trying to use heal spells that aren't ready and thus taking a while to cast.
|  -Added routine to mem heal spells out of combat rather than during combat.
|  -Corrected a problem causing an error message when looting was turned on.
|  -Corrected a crash bug when receiving a tell from an unsafe pc
|  -Turned off debug mode by default that was accidentally left on.  Should be less spam in your
|   mq2 window now.
| 
| V1.10 Update Notes
|  -Fixed an error where epicName was not being set properly and thus never used
|  -Fixed an error preventing castTimer from ever being set and not allow interrupts to work
|  -Moved the hot and promise timers to try and be more accurate about when they will actually expire
|   Also added 1 extra second over the normal duration to the timers
| 
| ==================================================================================================


#include devCommon.inc

#event oom "Insufficient Mana to cast this spell!"

Sub Main(string iniNameStr)
	/declare meVersion		float outer 1.31
	
	/squelch /mqlog clear
	/call CommonInit
	/varset reqCommon 1.80
	/varset reqMovement 1.60
	
	/varset debugMode FALSE
	
	/call EchoLog "Shmbot Initialized" true
	/call EchoLog "Loading variables..." true
	/if (!${Defined[iniNameStr]}) {
		/varset iniName shmbotSettings.ini
	} else {
		/if (!${iniNameStr.Equal[default]}) {
			/varset iniName shmbotSettings_${iniNameStr}.ini
		} else {
			/varset iniName shmbotSettings.ini
		}
	}
	
	/call LoadSettings
	
	/varset targCount 0
               :mainLoop           
              /call slow
		/doevents
		/call ClericCombatCheck
		/if ((${inCombat} || ${outOfCombatHeal.Equal[NULL]}) && ${doHeals} && !${healCheckTimer}) /call HealCheck
		
		/call CheckForAggro
		/if (${iAllowSit} && !${Me.Sitting} && !${sitTimer} && !${Me.Mount.ID} && !${gotAggro} && !${followMode} && !${Me.Casting.ID}) /sit on
		
		/if (!${inCombat}) {
			/if (${rezSpell.NotEqual[NULL]} && ${SpawnCount[Corpse radius ${campRadius} los]}) /call RezCheck
			/if (${outOfCombatHeal.NotEqual[NULL]} && !${healCheckTimer}) /call RestHealCheck
			/if (!${minBuffCheckTimer} && ${Me.PctMana} >= 50) /call buffCheck
			/if (!${otherChecksTimer}) {
				/call CommonRoutines
				/call HealGemCheck
				/if (${yaulpSpell.NotEqual[NULL]} && !${Me.Gem[${yaulpSpell}]} && ${yaulpSlot.Find[Gem]}) /memspell ${yaulpSlot.Right[${Math.Calc[${yaulpSlot.Length} - 3]}]} "${yaulpSpell}"
				/varset otherChecksTimer 10s
			}
		} else {
			/call CommonCombatRoutines CombatCall
		}
	/goto :mainLoop
/return

Sub Slow
/assist pigface
/delay 1s
/if ( ${Target.PctHPs}<=98 && ${Me.AltAbilityReady[Turgur's Swarm]} && ${Target.Type.Equal[NPC]} && ${Target.Buff[Turgur's Swarm].ID}!= 13144) {

/gsay AA slow on %t!
/delay 1s
/aa act Turgur's Swarm
/delay 3s
/return
}
/return

Sub AddCleanUp
	/if (!${Defined[addTracker]}) /declare addTracker[20] int outer
	/declare acLoop				int local 0
	/declare atLoop				int local 0
	/declare atInt				int local 0
	/declare addFound			bool local false
	
	/if (!${targCount}) /return
	
	/for acLoop 1 to ${targCount}
		/varset addFound false
		/varset atInt 0
		/for atLoop 1 to 20
			/if (${addTracker[${atLoop}]} == ${targArray[${acLoop}]}) {
				/varset addFound true
				/varset atInt ${atLoop}
			}
		/if (!${addFound}) /next atLoop
		/if (${Spawn[${targArray[${acLoop}]}].Type.NotEqual[Corpse]} && (!${Spawn[${targArray[${acLoop}]}].LineOfSight} || ${Spawn[${targArray[${acLoop}]}].Distance} > ${campRadius})) {
			/if (!${Spawn[${targArray[${acLoop}]}].ID}) {
				/varset addFound true
				/varset atInt ${acLoop}
				/if (!${Defined[addCleanUp${atInt}]}) /declare addCleanUp${atInt} timer outer 0s
			}
			/if (!${addFound}) {
				/for atLoop 1 to 20
					/if (!${addTracker[${atLoop}]}) {
						/varset atInt ${atLoop}
						/varset addTracker[${atLoop}] ${targArray[${acLoop}]}
					}
				/if (!${atInt}) /next atLoop
				/if (!${Defined[addCleanUp${atInt}]}) /declare addCleanUp${atInt} timer outer 0s
				/varset addCleanUp${atInt} 15s
			} else {
				/if (!${addCleanUp${atInt}}) {
					/call EchoLog "Add removed because it left the camp area, ${Spawn[${targArray[${acLoop}]}].CleanName} | ${targArray[${acLoop}]}" true
					/varset targArray[${acLoop}] 0
					/varcalc corpseCount ${corpseCount} + 1
					/varset corpseArray[${corpseCount}] 0
					/varset addTracker[${atInt}] 0
				}
			}
		} else {
			/if (${addFound}) /varset addTracker[${atLoop}] 0
		}
	/next acLoop
	
	/varcalc lTargCount ${targCount} - ${corpseCount}
	/if (${lTargCount}<1 && ${minBuffCheckTimer} < 50) /varset minBuffCheckTimer 5s
/return

Sub AfterDeath

/return

Sub CastHeal(int healNum, int healTargID, string hpWatch)
	/declare sMaxTry				int local ${resistTries}
	/if (!${Defined[hpWatch]}) /declare hpWatch string local EmergencyHeal
	
	/if (${Me.Casting.ID} && ${allowInterrupt}) /call Interrupt
	/varset currHealID ${Spell[${healSpell[${healNum}]}].ID}
	/varset currHealTarg ${healTargID}
	/if (${Spell[${currHealID}].MyCastTime} > 5) /varset sMaxTry 1	
	/squelch /target clear
	/squelch /target ID ${healTargID}
	/delay 1s ${Target.ID}
	/call EchoLog "Attempting to heal ${Target.CleanName} with ${healSpell[${healNum}]} | ${Target.PctHPs}" true
	/if (${doAnnounce} && ${healAnnounce[${healNum}].NotEqual[NULL]}) /docommand ${announceChan} ${healAnnounce[${healNum}]}
	:tryCast
	/varset castStart true
	/call MQ2Cast "${healSpell[${healNum}]}" ${healSlot[${healNum}]} 0 ${hpWatch} -targetid|${healTargID} -maxtries|${sMaxTry}
	/if (${sMaxTry} == 1 && ${Cast.Result.Equal[CAST_FIZZLE]}) /goto :tryCast
	/if (${Cast.Result.Equal[CAST_SUCCESS]}) {
		/if (${Spell[${currHealID}].Duration}) {
			/if (${Spell[${currHealID}].Name.Find[promised]}) {
				/call TrackPromise ${currHealTarg} ${currHealID}
			} else {
				/if (${healMinGroup[${healNum}]} > 1) {
					/varset groupHotTimer ${Math.Calc[${Spell[${currHealID}].Duration.TotalSeconds} + 1]}s
				} else {
					/call TrackHot ${currHealTarg} ${currHealID}	
				}
			}
		}
		/call EchoLog "Heal cast successfull" true
		/varset healCheckTimer ${healCheckTimerStr}
	} else /if (${Cast.Result.Equal[CAST_CANCELLED]}) {
		/if (${duckHealNum}) {
			/call CastHeal ${duckHealNum} ${duckHealTarg} DuckHeal
		} else /if (${duckHealName.NotEqual[NULL]}) {
			/if (${duckHealSlot.Equal[Item]} && ${FindItem[${epicName}].InvSlot} != 14) /call ItemSwapCheck "${epicName}"
			/varset currHealTarg ${Me.ID}
			/varset currHealID 0
			/call MQ2Cast "${duckHealName}" ${duckHealSlot} 0 DuckHeal -targetid|${Me.ID} -maxtries|${resistTries}
			/if (${Cast.Result.NotEqual[CAST_SUCCESS]}) {
				/call EchoLog "${duckHealName} cast failed, reason: ${Cast.Result}" true
			} else {
				/call EchoLog "${duckHealName} cast succeeded!" true
			}
			/if (${itemSwapped}) /call ItemSwapCheck
		} else {
			/call EchoLog "Heal cast failed: ${Cast.Result}" true
		}
	} else {
		/call EchoLog "Heal cast failed: ${Cast.Result}" true
	}
/return

Sub ClericCombatCheck
	/call CheckForAdds ${campRadius} ${Me.ID} false
	/if (${targCount}) /call AddCleanUp
	/if (!${inCombat} && (${lTargCount} > 0 || ${Me.CombatState.Equal[Combat]})) {
		/varset inCombat true
		/varset healCheckTimer 0
	}
	/if (${inCombat} && ${lTargCount} < 1 && ${Me.CombatState.NotEqual[Combat]}) {
		/varset inCombat false
		/call AfterCombatRoutines
		/varset healCheckTimer 20s
		/if (${minBuffCheckTimer} < 150) /varset minBuffCheckTimer 15s
	}		
/return

Sub Event_oom
	/if (${doAnnounce}) /docommand ${announceChan} I am out of mana!
	/varset manaLow true
/return

Sub BotCommands(string rFrom,string rMsg)
	/declare hMsg			string local COMPLETED_NOTFOUND
	/declare rFromID	int local 0

	/varset rFromID ${Spawn[pc ${rFrom}].ID}
	
	| ==========================
	| Bot specific commands
	| ==========================
	/declare paramCount								int local
	/varcalc paramCount ${rMsg.Count[ ]} + 1
	/declare cParams[20]							string local
	/declare strCommand								string local

	/varset strCommand ${rMsg.Token[1, ]}
	/if (${paramCount}) {
		/for nArray 2 to ${paramCount}
			/varset cParams[${Math.Calc[${nArray}-1]}] ${rMsg.Token[${nArray}, ]}
		/next nArray
	}
	/if (${strCommand.Equal[heal]}) {
		| =======================================
		|  heal (target) (spell)
		| =======================================
		/if (${cParams[1].NotEqual[NULL]}) {
			/declare healTargName						string local ${cParams[1]}
			/if (${healTargName.Equal[Me]}) /varset healTargName ${rFrom}
			/if (${Spawn[${healTargName}].ID}) {
				/squelch /target clear
				/squelch /target ${healTargName}
				/delay 1s ${Target.ID}
				/if (${Target.ID}) {
					/if (${cParams[2].Length}) {
						/declare healName							string local
						/for nArray 2 to 20
							/if (${cParams[${nArray}].Length}) /varset healName ${healName} ${cParams[${nArray}]}
						/if (${cParams[${nArray}].Length}) /next nArray
						/call EchoLog "Attempting to cast ${healName} on ${Target.CleanName} | ${Target.PctHPs}"
						/call MQ2Cast "${healName}"
						/if (${Cast.Result.Equal[CAST_SUCCESS]}) {
							/varset hMsg \agHeal cast successfully
						} else {
							/varset hMsg \arFailed to cast heal, reason: \ag${Cast.Result}
						}
					} else {
						/if (${healCount}) {
							/varset hMsg NULL
							/for nArray 1 to ${healCount}
								/if (${healMinGroup[${nArray}]}) /next nArray
								/if (${Target.Distance} < ${Spell[${healSpell[${nArray}]}].Range}) {
									/if (${Target.Type.NotEqual[Corpse]}) {
										/if (${healClasses[${nArray}].Find[${Target.Class.ShortName}]}) {
											/if (${Target.PctHPs} >= ${healMinHP[${nArray}]} && ${Target.PctHPs} <= ${healMaxHP[${nArray}]}) {
												/call EchoLog "Attempting to cast ${healSpell[${nArray}]} on ${Target.CleanName} | ${Target.PctHPs}" true
												/call MQ2Cast "${healSpell[${nArray}]}" ${healSlot[${nArray}]}
												/if (${Cast.Result.Equal[CAST_SUCCESS]}) {
													/varset hMsg \agHeal cast successfully
												} else {
													/varset hMsg \arFailed to cast heal, reason: \ag${Cast.Result}
												}
											}
										}
									}
								}
							/if (${hMsg.Equal[NULL]}) /next nArray
							/if (${hMsg.Equal[NULL]}) /varset hMsg \ayCould not Find A heal to cast on the specified Target.
						} else {
							/varset hMsg \ayNo heal spells set, cannot heal.
						}
					}
				} else {
					/varset hMsg \ag${healTargName} \aocould not be found to heal.
				}
			} else {
				/varset hMsg No heal Target given
			}
		} else {
			/if (${doHeals}) {
				/varset doHeals false
				/varset hMsg No longer healing
			} else {
				/varset doHeals true
				/varset hMsg I will now heal
			}
		}
	} else /if (${strCommand.Equal[healpets]}) {
		/if (${healPets}) {
			/varset healPets FALSE
			/varset hMsg No longer healing pets
		} else {
			/varset healPets TRUE
			/varset hMsg I will now heal pets
		}
	} else /if (${strCommand.Equal[NULL]}) {
		/varset hMsg \ayCommand not recognized
	}
/return ${hMsg}

Sub CombatCall
	/call HealCheck TRUE
/return

Sub HealGemCheck
	/declare gCheck				int local
	
	/for gCheck 1 to ${healCount}
		/if (${healSlot[${gCheck}].Find[Gem]} && !${Me.Gem[${healSpell[${gCheck}]}]}) {
			/memspell ${spellSlot.Right[${Math.Calc[${spellSlot.Length} - 3]}]} "${healSpell[${gCheck}]}"
		}
		/call ClericCombatCheck
	/if (!${inCombat}) /next gCheck
/return

Sub HealCheck(bool secondaryCall)
	/if (!${Defined[secondaryCall]}) /declare secondaryCall		bool local FALSE
	/declare hInt					int local 0
	/declare groupAvgHP		int local 0
	/declare avgCount			int local 0
	/declare lowHP				int local 100
	/declare pHeal				bool local false
	/declare hHeal				bool local false
	/declare gPets				bool local false
	/declare grpArray			int local 0
	/declare targVariable	string local Target
	
	/if (${healCount}) {
		/for hInt 1 to ${healCount}
			/if (${Spell[${healSpell[${hInt}]}].Duration}) {
				/if (${healSpell[${hInt}].Find[promised]}) {
					/varset pHeal true
					/varset hHeal false
				} else {
					/if (${groupHotTimer}) /next hInt
					/varset hHeal true
					/varset pHeal false
				}
			} else {
				/varset hHeal false
				/varset pHeal false
			}
			/if (${healSlot[${hInt}].Equal[Item]} && ${FindItem[${healSpell[${hInt}]}].Timer}) /next hInt
			/if (${healSlot[${hInt}].Equal[alt]} && !${Me.AltAbilityReady[${healSpell[${hInt}]}]}) /next hInt
			/if (${healSlot[${hInt}].Find[Gem]} && !${Me.Gem[${healSpell[${hInt}]}]} && ${Spell[${healSpell[${hInt}]}].RecastTime} > 2) /next hInt
			/if (${healSlot[${hInt}].Find[Gem]} && ${Me.Gem[${healSpell[${hInt}]}]} && !${Me.SpellReady[${healSpell[${hInt}]}]}) /next hInt
			/if  (${Me.CurrentMana} > ${Spell[${healSpell[${hInt}]}].Mana}) {
				/if (${healMinGroup[${hInt}]}>1) {
					/if (${Group.GroupSize} >= ${healMinGroup[${hInt}]}) {
						/if (${hHeal} && ${groupHotTimer}) /next hInt
						/varset avgCount 0
						/varset groupAvgHP 0
						/for nArray 0 to ${Group.Members}
							/if (${Group.Member[${nArray}].Type.Equal[Corpse]} || !${Group.Member[${nArray}].ID}) /next nArray
							/varcalc groupAvgHP ${groupAvgHP} + ${Group.Member[${nArray}].PctHPs}
							/varcalc avgCount ${avgCount} + 1
							/if (${Group.Member[${nArray}].PctHPs} < 50 && ${hInt} < ${healCount}) /next hInt
						/next nArray
						/if (${avgCount} == 0) /return
						/varcalc groupAvgHP ${groupAvgHP} / ${avgCount}
						/if (${groupAvgHP} <= ${healMaxHP[${hInt}]} && ${groupAvgHP} >= ${healMinHP[${hInt}]}) {
							/call EchoLog "Attempting to cast group heal ${healSpell[${nArray}]}, group avg: ${groupAvgHP}" true
							/call CastHeal ${hInt} ${Me.ID}
							/return
						}
					}
				} else {
					/for nArray 0 to ${Group.Members}
						/if (${Group.Member[${nArray}].Pet.ID} && !${Group.Member[${nArray}].Pet.Name.Find[familiar]}) /varset gPets TRUE
						/if (${pHeal} || ${hHeal}) {
							/if (${pHeal}) /call TrackPromise ${Group.Member[${nArray}].ID}
							/if (${hHeal}) /call TrackHot ${Group.Member[${nArray}].ID}
							/if (${Macro.Return.Equal[FALSE]}) /next nArray
						}
						/if (${Group.Member[${nArray}].Distance} > ${Spell[${healSpell[${hInt}]}].Range}) /next nArray
						/if (${Group.Member[${nArray}].Type.Equal[Corpse]} || !${Group.Member[${nArray}].ID}) /next nArray
						/if (${Group.Member[${nArray}].CleanName.Equal[${pullerName}]} && (!${Group.Member[${nArray}].LineOfSight} || ${Group.Member[${nArray}].Distance} > ${campRadius})) /next nArray
						/if (${healClasses[${hInt}].Find[${Group.Member[${nArray}].Class.ShortName}]} || ${healClasses[${hInt}].Find[${Group.Member[${nArray}].Class.Name}]} || ${healClasses[${hInt}].Find[${Group.Member[${nArray}].CleanName}]} || ((${healClasses[${hInt}].Find[mt]} || ${healClasses[${hInt}].Find[maintank]}) && ${Group.Member[${nArray}].CleanName.Equal[${mainTank}]})) {
							/if (${Group.Member[${nArray}].PctHPs} >= ${healMinHP[${hInt}]} && ${Group.Member[${nArray}].PctHPs} <= ${healMaxHP[${hInt}]}) {
								/call CastHeal ${hInt} ${Group.Member[${nArray}].ID}
								/return
							}
						}
					/next nArray
				}
			}
		/next hInt

		/if (${gPets} && ${healPets}) {
			/for hInt 1 to ${healCount}
				/if (${Spell[${healSpell[${hInt}]}].Duration}) {
					/if (${healSpell[${hInt}].Find[promised]}) {
						/varset pHeal true
						/varset hHeal false
					} else {
						/varset hHeal true
						/varset pHeal false
					}
				} else {
					/varset hHeal false
					/varset pHeal false
				}				
				/if (${healMinGroup[${hInt}]}>1) /next hInt
				/if (${healSlot[${hInt}].Equal[Item]} && ${FindItem[${healSpell[${hInt}]}].Timer}) /next hInt
				/if (${healSlot[${hInt}].Equal[alt]} && !${Me.AltAbilityReady[${healSpell[${hInt}]}]}) /next hInt
				| /if (${healSlot[${hInt}].Find[Gem]} && !${Me.SpellReady[${healSpell[${hInt}]}]} && ${Spell[${healSpell[${hInt}]}].RecastTime} > 3) /next hInt
				/if (${Defined[healRecastTimer${hInt}]} && ${healRecastTimer${hInt}}) /next hInt
				/if  (${Me.CurrentMana} > ${Spell[${healSpell[${hInt}]}].Mana}) {			
					/for grpArray 0 to ${Group.Members}
						/if (${Group.Member[${grpArray}].Pet.ID} && !${Group.Member[${grpArray}].Pet.Name.Find[familiar]}) {
							/if (${pHeal} || ${hHeal}) {
								/if (${pHeal}) /call TrackPromise ${Group.Member[${grpArray}].Pet.ID}
								/if (${hHeal}) /call TrackHot ${Group.Member[${grpArray}].Pet.ID}
								/if (${Macro.Return.Equal[FALSE]}) /next grpArray
							}
							/if (${Group.Member[${grpArray}].Pet.Distance} > ${Spell[${healSpell[${hInt}]}].Range}) /next grpArray
							/if (${healClasses[${hInt}].Find[${Group.Member[${grpArray}].Class.ShortName}-Pet]} || ${healClasses[${hInt}].Find[${Group.Member[${grpArray}].Class.Name}-Pet]} || ${healClasses[${hInt}].Find[${Group.Member[${grpArray}].CleanName}-Pet]} || ${healClasses[${hInt}].Find[Pet]}) {
								/if (${Group.Member[${grpArray}].Pet.PctHPs} >= ${healMinHP[${hInt}]} && ${Group.Member[${grpArray}].Pet.PctHPs} <= ${healMaxHP[${hInt}]}) {
									/call CastHeal ${hInt} ${Group.Member[${grpArray}].Pet.ID}
									/return
								}
							}																	
						}
					/next grpArray
				}
			/next hInt
		}		
		
		/if (${watchCount}) {
			/varset gPets false
			/for hInt 1 to ${healCount}
				/if (${Spell[${healSpell[${hInt}]}].Duration}) {
					/if (${healSpell[${hInt}].Find[promised]}) {
						/varset pHeal true
						/varset hHeal false
					} else {
						/varset hHeal true
						/varset pHeal false
					}
				} else {
					/varset hHeal false
					/varset pHeal false
				}				
				/if (${healMinGroup[${hInt}]}>1) /next hInt
				/if (${healSlot[${hInt}].Equal[Item]} && ${FindItem[${healSpell[${hInt}]}].Timer}) /next hInt
				/if (${healSlot[${hInt}].Equal[alt]} && !${Me.AltAbilityReady[${healSpell[${hInt}]}]}) /next hInt
				| /if (${healSlot[${hInt}].Find[Gem]} && !${Me.SpellReady[${healSpell[${hInt}]}]} && ${Spell[${healSpell[${hInt}]}].RecastTime} > 3) /next hInt
				/if (${Defined[healRecastTimer${hInt}]} && ${healRecastTimer${hInt}}) /next hInt
				/if  (${Me.CurrentMana} > ${Spell[${healSpell[${hInt}]}].Mana}) {
					/for grpArray 1 to ${watchCount}
						/if (${Spawn[${watchList[${grpArray}]}].Pet.ID}) /varset gPets true
						/if (${pHeal} || ${hHeal}) {
							/if (${pHeal}) /call TrackPromise ${Spawn[${watchList[${grpArray}]}].ID}
							/if (${hHeal}) /call TrackHot ${Spawn[${watchList[${grpArray}]}].ID}
							/if (${Macro.Return.Equal[FALSE]}) /next grpArray
						}
						/if (${Spawn[${watchList[${grpArray}]}].Distance} > ${Spell[${healSpell[${hInt}]}].Range}) /next grpArray
						/if (${Spawn[${watchList[${grpArray}]}].Type.Equal[Corpse]} || !${Spawn[${watchList[${grpArray}]}].ID}) /next grpArray
						/if (${Spawn[${watchList[${grpArray}]}].CleanName.Equal[${pullerName}]} && (!${Spawn[${watchList[${grpArray}]}].LineOfSight} || ${Spawn[${watchList[${grpArray}]}].Distance} > ${campRadius})) /next grpArray
						/if (${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].Class.ShortName}]} || ${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].Class.Name}]} || ${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].CleanName}]} || ((${healClasses[${hInt}].Find[mt]} || ${healClasses[${hInt}].Find[maintank]}) && ${Spawn[${watchList[${grpArray}]}].CleanName.Equal[${mainTank}]})) {
							/if (${useEQBC} && ${NetBots[${watchList[${grpArray}]}].Zone}) {
								/varset targVariable NetBots[${watchList[${grpArray}]}]
							} else {
								/squelch /target id ${Spawn[${watchList[${grpArray}]}].ID}
								/delay 1s ${Target.ID}==${Spawn[${watchList[${grpArray}]}].ID}
								/delay 2
								/varset targVariable Target
							}
							/if (${${targVariable}.PctHPs} >= ${healMinHP[${hInt}]} && ${${targVariable}.PctHPs} <= ${healMaxHP[${hInt}]}) {
								/call CastHeal ${hInt} ${Spawn[${watchList[${grpArray}]}].ID}
								/return
							}
						}
					/next grpArray
				}
			/next hInt
			
			/if (${gPets} && ${healPets}) {
				/for hInt 1 to ${healCount}
					/if (${Spell[${healSpell[${hInt}]}].Duration}) {
						/if (${healSpell[${hInt}].Find[promised]}) {
							/varset pHeal true
							/varset hHeal false
						} else {
							/varset hHeal true
							/varset pHeal false
						}
					} else {
						/varset hHeal false
						/varset pHeal false
					}					
					/if (${healMinGroup[${hInt}]}>1) /next hInt
					/if (${healSlot[${hInt}].Equal[Item]} && ${FindItem[${healSpell[${hInt}]}].Timer}) /next hInt
					/if (${healSlot[${hInt}].Equal[alt]} && !${Me.AltAbilityReady[${healSpell[${hInt}]}]}) /next hInt
					| /if (${healSlot[${hInt}].Find[Gem]} && !${Me.SpellReady[${healSpell[${hInt}]}]} && ${Spell[${healSpell[${hInt}]}].RecastTime} > 3) /next hInt
					/if (${Defined[healRecastTimer${hInt}]} && ${healRecastTimer${hInt}}) /next hInt
					/if  (${Me.CurrentMana} > ${Spell[${healSpell[${hInt}]}].Mana}) {
						/for grpArray 1 to ${watchCount}
							/if (${Spawn[${watchList[${grpArray}]}].Pet.ID}) {
								/if (${pHeal} || ${hHeal}) {
									/if (${pHeal}) /call TrackPromise ${Spawn[${watchList[${grpArray}]}].Pet.ID}
									/if (${hHeal}) /call TrackHot ${Spawn[${watchList[${grpArray}]}].Pet.ID}
									/if (${Macro.Return.Equal[FALSE]}) /next grpArray
								}
								/if (${Spawn[${watchList[${grpArray}]}].Pet.Distance} > ${Spell[${healSpell[${hInt}]}].Range}) /next grpArray
								/if (${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].Class.ShortName}-Pet]} || ${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].Class.Name}-Pet]} || ${healClasses[${hInt}].Find[${Spawn[${watchList[${grpArray}]}].CleanName}-Pet]} || ${healClasses[${hInt}].Find[Pet]}) {
									/if (${useEQBC} && ${NetBots[${watchList[${grpArray}]}].Zone}) {
										/varset targVariable NetBots[${watchList[${grpArray}]}].PetHP
									} else {
										/squelch /target id ${Spawn[${watchList[${grpArray}]}].Pet.ID}
										/delay 1s ${Target.ID}==${Spawn[${watchList[${grpArray}]}].Pet.ID}
										/delay 2
										/varset targVariable Target.PctHPs
									}
									/if (${${targVariable}} >= ${healMinHP[${hInt}]} && ${${targVariable}} <= ${healMaxHP[${hInt}]}) {
										/call CastHeal ${hInt} ${Spawn[${watchList[${grpArray}]}].Pet.ID}
										/return
									}
								}
							}
						/next grpArray
					}
				/next hInt
			}
		}		
		:exitHealLoop
	}
	
	/if (${yaulpSpell.NotEqual[null]} && !${Me.Mount.ID} && ${inCombat} && !${Me.Buff[${yaulpSpell}].ID} && ${Me.SpellReady[${yaulpSpell}]} && !${secondaryCall}) {
		/for nArray 0 to ${Group.Members}
			/if (${Group.Member[${nArray}].Type.Equal[Corpse]} || !${Group.Member[${nArray}].ID}) /next nArray
			/if (${Group.Member[${nArray}].PctHPs} < ${lowHP}) /varset lowHP ${Group.Member[${nArray}].PctHPs}
		/if (${lowHP} > 60) /next nArray
		/if (${lowHP} > 60) {
			/call EchoLog "Attempting to use ${yaulpSpell}" true
			/call MQ2Cast "${yaulpSpell}" ${yaulpSlot}
			/if (${Cast.Result.NotEqual[CAST_SUCCESS]}) /call EchoLog "Yaulp failed, reason: ${Cast.Result}" true
		}
	}
/return

Sub EmergencyHeal
	/declare lowHP				int local 100
	/declare lowID				int local 0
	/declare eLoop				int local
	/declare cGroupAvg		int local 100
	/declare cAvgCount		int local 0
	
	/if (${castStart}) {
		/varset castTimer ${Spell[${currHealID}].MyCastTime}s
		/varset castStart false
	}
	/if (!${allowInterrupt}) /return
	/if (!${Me.Casting.ID}) /return
	
	/varset duckHealNum 0
	/varset duckHealTarg 0
	/varset duckHealName NULL
	/varset duckHealSlot NULL
	
	/if (((${Spawn[${currHealTarg}].PctHPs} >= 98 && ${castTimer} > 5) || ${Spawn[${currHealTarg}].Type.Equal[Corpse]} || !${Spawn[${currHealTarg}].ID}) && ${allowInterrupt} && !${Spell[${currHealID}].AERange}) {
		/call EchoLog "The target being healed is either already healed, dead, or not in the zone, canceling heal" true
		/call Interrupt
		/return
	}
	/for eLoop 0 to ${Group.Members}
		/if (${Group.Member[${eLoop}].Type.NotEqual[Corpse]} && ${Group.Member[${eLoop}].ID}) {
			/varcalc cAvgCount ${cAvgCount} + 1
			/varcalc cGroupAvg ${cGroupAvg} + ${Group.Member[${eLoop}].PctHPs}
			/if (${classList.Find[${Group.Member[${eLoop}].Class.ShortName}]} && ${Group.Member[${eLoop}].PctHPs} < ${lowHP}) {
				/varset lowHP ${Group.Member[${eLoop}].PctHPs}
				/varset lowID ${Group.Member[${eLoop}].ID}
			}
		}
	/next eLoop
	/if (${cAvgCount}) /varcalc cGroupAvg ${cGroupAvg} / ${cAvgCount}
	
	/if (${lowHP} < ${emergencyHP} && ${castTimer} > 10 && (${useEpicBalance} || ${useAABalance}) && ${cGroupAvg} > 50) {
		/if (${useEpicBalance} && !${FindItem[${epicName}].Timer}) {
			/call EchoLog "Attempting to use ${epicName} epic click" true
			/call Interrupt
			/varset duckHealName ${epicName}
			/varset duckHealSlot Item
			/return
		}
		/if (${useAABalance} && ${Me.AltAbilityReady[Divine Arbitration]}) {
			/call EchoLog "Attempting to use AA Divine Arbitration" true
			/call Interrupt
			/varset duckHealName Divine Arbitration
			/varset duckHealSlot alt
			/return
		}
	}
	
	/if (${lowID} != ${currHealTarg} && ${Target.PctHPs} > 50 && ${lowHP} < ${emergencyHP} && ${castTimer}>${Math.Calc[${Spell[${currHealID}].MyCastTime} * 5]} && (${Spawn[${currHealTarg}].CleanName.NotEqual[${mainTank}]} || ${lowID} == ${Me.ID} || ${lowID} == ${Spawn[${mainTank}].ID})) {
		/call EchoLog "4"
		/if (${Me.Gem[${healSpell[${fastestHealNum}]}]}) {
			/call EchoLog "Canceling heal to heal someone that is about to die" true
			/call Interrupt
			/call CastHeal ${fastestHealNum} ${lowID} DuckHeal
			/return
		} else {
			/for eLoop 1 to ${healCount}
				/if (${Spell[${heallSpell[${eLoop}]}].Duration}) /next eLoop
				/if (!${Me.Gem[${healSpell[${eLoop}]}]}) /next eLoop
				/if (${Spell[${healSpell[${eLoop}]}].MyCastTime} > 2) /next eLoop
				/if (${healMinGroup[${eLoop}]}>1) /next eLoop
				/if (${healClasses[${eLoop}].Find[${Spawn[${lowID}].Class.ShortName}]}) {
					/call EchoLog "Canceling heal to heal someone that is about to die" true
					/call Interrupt
					/varset duckHealNum ${eLoop}
					/varset duckHealTarg ${lowID}
					/return
				}
			/next eLoop
		}
	} else {
		/if (${Target.PctHPs} < ${emergencyHP}) {
			/if (${fastestCastTime} < ${Math.Calc[${castTimer} + 2.5]} && ${Me.Gem[${healSpell[${fastestHealNum}]}]}) {
				/call EchoLog "Canceling heal to use a faster heal spell" true
				/call Interrupt
				/varset duckHealNum ${fastestHealNum}
				/varset duckHealTarg ${Target.ID}
				/return
			} else {
				/for eLoop 1 to ${healCount}
					/if (!${Me.Gem[${healSpell[${eLoop}]}]}) /next eLoop
					/if (${healMinGroup[${eLoop}]}>1) /next eLoop
					/if (${Spell[${heallSpell[${eLoop}]}].Duration}) /next eLoop
					/if (${Math.Calc[${Spell[${healSpell[${eLoop}]}].MyCastTime} * 10]} < ${Math.Calc[${castTimer} + 2.5]}) {
						/if (${healClasses[${eLoop}].Find[${Spawn[${currHealTarg}].Class.ShortName}]}) {
							/call EchoLog "Canceling heal to use a faster heal spell" true
							/call Interrupt
							/varset duckHealNum ${fastestHealNum}
							/varset duckHealTarg ${Target.ID}
							/return
						}
					}
				}
			/next eLoop
		}
	}
/return

Sub DuckHeal
	| If needed in the future this is what is called when an emergency heal is being cast.
	/if (${Spawn[${currHealTarg}].Type.Equal[Corpse]} || !${Spawn[${currHealTarg}].ID}) {
		/call Interrupt
	}
/return

Sub LoadSettings
| ====================
| Load Heals
| ====================
	/declare healCount											int outer
	/varset healCount ${Ini[${iniName},Heals,Value]}
	/call EchoLog "Loading heals:  ${healCount} heal spell(s)" true

	/declare healSpell[${healCount}]				string outer
	/declare healSlot[${healCount}]					string outer
	/declare healMinGroup[${healCount}]			int outer
	/declare healMinHP[${healCount}]				int outer
	/declare healMaxHP[${healCount}]				int outer
	/declare healClasses[${healCount}]			string outer
	/declare healType[${healCount}]					string outer
	/declare healAnnounce[${healCount}]			string outer
	/declare classList											string outer
	/declare outOfCombatHeal								string outer
	/declare outOfCombatSlot								string outer
	/declare outOfCombatHP									int outer
	/declare fastestHealNum									int outer
	/declare fastestCastTime								float outer 20.0
	
	
	/varset outOfCombatHeal ${Ini[${iniName},Heals,OutOfCombatHeal]}
	/varset outOfCombatSlot ${Ini[${iniName},Heals,OutOfCombatSlot]}
	/varset outOfCombatHP ${Ini[${iniName},Heals,OutOfCombatHP]}
	
	/if (${healCount}) {
		/for nArray 1 to ${healCount}
			/varset healSpell[${nArray}] ${Ini[${iniName},Heals,HealName${nArray}]}
			/varset healSlot[${nArray}] ${Ini[${iniName},Heals,HealSlot${nArray}]}
			/varset healMinGroup[${nArray}] ${Ini[${iniName},Heals,HealMinGroup${nArray}]}
			/varset healMinHP[${nArray}] ${Ini[${iniName},Heals,HealMinHP${nArray}]}
			/varset healMaxHP[${nArray}] ${Ini[${iniName},Heals,HealMaxHP${nArray}]}
			/varset healClasses[${nArray}] ${Ini[${iniName},Heals,HealClasses${nArray}]}
			/varset healType[${nArray}] ${Ini[${iniName},Heals,HealType${nArray}]}
			/varset healAnnounce[${nArray}] ${Ini[${iniName},Heals,HealAnnounce${nArray}]}
			/if (${healType[${nArray}].Equal[NULL]}) /varset healType[${nArray}] ALL
			/call EchoLog "      ${nArray} - NAME: ${healSpell[${nArray}]} SLOT: ${healSlot[${nArray}]} MINGROUP: ${healMinGroup[${nArray}]} MINHP: ${healMinHP[${nArray}]} MAXHP: ${healMaxHP[${nArray}]} TYPE: ${healType[${nArray}]} CLASSES: ${healClasses[${nArray}]}" true
			/varset classList ${classList}${healClasses[${nArray}]}
			
			/if (${Spell[${healSpell[${nArray}]}].MyCastTime} < ${fastestCastTime} && !${Spell[${healSpell[${nArray}]}].Duration}) {
				/varset fastestHealNum ${nArray}
				/varset fastestCastTime ${Math.Calc[${Spell[${healSpell[${nArray}]}].MyCastTime} * 10]}
			}
		/next nArray
	}
	
| ====================
| Load General Settings
| ====================
	/declare pauseTimer						timer outer
	| /declare campAfterGate				bool outer
	/declare pauseActions					bool outer false
	/declare doHeals							bool outer true
	/declare healCheckTimerStr		string outer 5s
	/declare healCheckTimer				timer outer 0s
	/declare iAllowSit						bool outer true
	/declare rezSpell							string outer
	/declare rezSlot							string outer
	/declare rezAnnounce					string outer NULL
	/declare rezTracker[100]			int outer
	/declare rezTimerStr					string outer 2m
	/declare otherChecksTimer			timer outer 10s
	/declare hotTimer							timer outer 0s
	/declare promiseTimer					timer outer 0s
	/declare yaulpSpell						string outer
	/declare yaulpSlot						string outer
	/declare emergencyHP					int outer 35
	/declare useEpicBalance				bool outer false
	/declare useAABalance					bool outer false
	/declare epicBalanceName			string outer NULL
	/declare duckHealNum					int outer 0
	/declare duckHealTarg					int outer 0
	/declare duckHealName					string outer
	/declare duckHealSlot					string outer
	/declare castStart						bool outer false
	/declare epicName							string outer
	/declare healPets							bool outer false
	
	/call EchoLog "Loading general settings" true
	/varset healCheckTimerStr ${Ini[${iniName},General,HealCheckTime]}
	/varset doHeals ${Ini[${iniName},General,HealAtStart]}
	/varset outOfCombatSit ${Ini[${iniName},General,OutOfCombatSit]}
	/varset iAllowSit ${Ini[${iniName},General,AllowSit]}
	/varset rezSpell ${Ini[${iniName},General,RezSpell]}
	/varset rezSlot ${Ini[${iniName},General,RezSlot]}
	/varset rezAnnounce ${Ini[${iniName},General,RezAnnounce]}
	/varset yaulpSpell ${Ini[${iniName},General,YaulpSpell]}
	/varset yaulpSlot ${Ini[${iniName},General,YaulpSlot]}
	/varset emergencyHP ${Ini[${iniName},General,EmergencyHealHP]}
	/varset useEpicBalance ${Ini[${iniName},General,UseEpicBalance]}
	/varset useAABalance ${Ini[${iniName},General,UseAABalance]}
	/varset healPets ${Ini[${iniName},General,HealPets]}
	/if (${Ini[${iniName},General,CampAfterGate].NotEqual[NULL]}) {
		/varset campAfterGate ${Ini[${iniName},General,CampAfterGate]}
	} else {
		/varset campAfterGate true
	}
	/if (${unsafePCAction.Equal[NULL]}) /varset unsafePCAction pause
	/if (${useEpicBalance}) {
		/if (${FindItem[Harmony of the Soul].InvSlot}) /varset epicName Harmony of the Soul
		/if (${FindItem[Aegis of Superior Divinity].InvSlot}) /varset epicName Aegis of Superior Divinity
		/if (${epicName.Equal[NULL]}) /varset useEpicBalance false
	}
	/if (${useAABalance}) {
		/if (!${Me.AltAbility[Divine Arbitration]}) /varset useAABalance false
	}
	/call EchoLog "   MinSafeDistance: ${minSafeDistance}" true
	/call EchoLog "   Camping after gate: ${campAfterGate}" true
	/call EchoLog "   Unsafe PC action: ${unsafePCAction}" true
	
	
| ====================
| Finish Loading
| ====================
	/varset homeX ${Me.X}
	/varset homeY ${Me.Y}
	/varset maxLoc 1
	/varset LocArray[1] ${homeY},${homeX}

| ====================	
| Final var setup
| ====================
	/declare oTargID									int outer
	/declare manaLow									bool outer false
	/declare currHealID								int outer
	/declare currHealTarg							int outer
	/declare castTimer								timer outer 0s
	/declare promiseTrack[20]					int outer
	/declare hotTrack[20]							int outer
	/declare groupHotTimer						timer outer 0s
	
	/varset targID 0
	/varset startZone ${Zone.ShortName}
	/varset movVar 1
	/varset minBuffCheckTimer 0s
	/varset curLoc 1
	/varset lTargCount 0
	
	/call CommonLoad
	/call resetTimers
	/tgb on

	/call EchoLog "ClericBot \agv${meVersion}\ao, written by \awDevestator\ao, initiated"
	/call EchoLog "Looting Corpses: \ag${lootCorpses}"
	/call EchoLog "Main Tank: \ag${mainTank}"
	/call EchoLog "Main Assist: \ag${mainAssist}"
	/call EchoLog "Puller: \ag${pullerName}"
	/call EchoLog "INI FileName: \ag${iniName}"
	/call EchoLog "Healing: \ag${doHeals}"
	/call EchoLog "Debuffing: \ag${doDebuffs}"
	/call EchoLog "Group Buffing: \ag${doGroupBuffs}"
	/if (${doGroupBuffs}) /call EchoLog "Minimum Check Time: \ag${minBuffCheckTimerStr}"
	/call EchoLog "Self Buffing: \ag${doSelfBuffs}"
	/if (${doAnnounce}) {
		/call EchoLog "Announcements: \ag${announceChan}"
	} else {
		/call EchoLog "Announcements: \agOFF"
	}
	/delay 1s
	/doevents
/return

Sub ResetTimers
	/varset globalCooldown 0s
	/if (${csCount}>0) {
		/for nArray 1 to ${csCount}
			/varset csTimer${nArray} 0s
		/next nArray
	}
/return

Sub RestHealCheck
	/declare rhLoop				int local
	
	/if (${Me.PctMana} < 50) /return
	/for rhLoop 0 to ${Group.Members}
		/if (${Group.Member[${rhLoop}].ID} && ${Group.Member[${rhLoop}].PctHPs} < ${outOfCombatHP} && ${Group.Member[${rhLoop}].Type.NotEqual[Corpse]} && ${Group.Member[${rhLoop}].Distance} < ${Spell[${outOfCombatHeal}].Range}) {
			/if (${Group.Member[${rhLoop}].CleanName.Equal[${pullerName}]} && (!${Group.Member[${rhLoop}].LineOfSight} || ${Group.Member[${rhLoop}].Distance} > ${campRadius})) /next rhLoop
			/squelch /target clear
			/squelch /target ID ${Group.Member[${rhLoop}].ID}
			/delay 1s ${Target.ID}
			/call EchoLog "Casting out of combat heal: ${outOfCombatHeal} on ${Target.CleanName}" true
			/if (${doAnnounce}) /docommand ${announceChan} ${outOfCombatHeal} on %t
			/call MQ2Cast "${outOfCombatHeal}" ${outOfCombatSlot} 0 CheckForAggro -targetid|${Target.ID} -maxtries|${resistTries}
			/if (${Cast.Result.NotEqual[CAST_SUCCESS]}) /call EchoLog "Heal failed, reason: ${Cast.Result} | Aggro: ${gotAggro}" true
		}
		/call ClericCombatCheck
		/if (${Me.PctMana} < 50) /return
	/if (!${gotAggro} && ${Me.CombatState.NotEqual[Combat]} && !${inCombat}) /next rhLoop
	/if (!${gotAggro} && ${Me.CombatState.NotEqual[Combat]} && !${inCombat}) /varset healCheckTimer 10s
/return

Sub RezCheck
	/declare corpseID				int local
	/declare corpseNum			int local
	
	/if (${rezSpell.Equal[Null]}) /return
	/varset corpseNum 0
	:nextcorpse
	/if (${rezSlot.Find[Gem]} && ${Me.CurrentMana} < ${Math.Calc[${Spell[${rezSpell}].Mana} + 100]}) /return
	/varcalc corpseNum ${corpseNum} + 1
	/varset corpseID ${Me.NearestSpawn[${corpseNum},Corpse radius ${campRadius}].ID}
	/if (${corpseID}) {
		/if (${Spawn[${corpseID}].Deity.ID}) {
			/call SafePC ${Spawn[${corpseID}].DisplayName}
			/if (${Macro.Return.Equal[true]}) {
				:tryRez
				/call RezTarget ${corpseID}
				/if (${Macro.Return.Equal[COMPLETED_FAIL]}) /goto :tryRez
				/if (${Macro.Return.Equal[ABORT_AGGRO]}) /return
			}
		}
		/goto :nextcorpse
	}
/return

Sub RezTarget(int rezTargID)
	/if (${rezSpell.Equal[Null]}) /return ABORT_NOSPELL
	/if (${rezSlot.Find[Gem]} && ${Me.CurrentMana} < ${Spell[${rezSpell}].Mana}) /return ABORT_MANA
	/if (${rezSlot.Find[Gem]} && !${Me.SpellReady[${rezSpell}]}) /return ABORT_NOTREADY
	/if (${rezSlot.Equal[Item]} && ${FindItem[${rezSpell}].Timer}) /return ABORT_NOTREADY
	/if (${rezSlot.Equal[alt]} && !${Me.AltAbilityReady[${rezSpell}]}) /return ABORT_NOTREADY
	/if (!${Spawn[${rezTargID}].ID} || ${Spawn[${rezTargID}].Type.NotEqual[Corpse]} || !${Spawn[${rezTargID}].Deity.ID}) /return ABORT_NOCORPSE
	/if (!${Spawn[${rezTargID}].LineOfSight}) /return ABORT_CANNOTSEE
	/if (${Spawn[${rezTargID}].Distance} > ${campRadius}) /return ABORT_DISTANCE
	/if (!${Defined[lastRezID]}) /declare lastRezID					int outer
	
	/call OkToRez ${rezTargID}
	/if (${Macro.Return.Equal[false]}) /return ABORT_REZTIMER
	
	/squelch /target clear
	/squelch /target ID ${rezTargID}
	/delay 1s ${Target.ID}
	
	/if (${Target.ID}) {
		/call EchoLog "Attempting to rez ${Target.CleanName}" true
		/if (${rezSlot.Equal[Item]}) /call ItemSwapCheck ${rezSpell}
		/if (${rezAnnounce.NotEqual[NULL]} && ${doAnnounce}) /docommand ${announceChan} ${rezAnnounce}
		/call MQ2Cast "${rezSpell}" ${rezSlot} 0 CheckForAggro -targetid|${corpseID}
		/if (${itemSwapped}) /call ItemSwapCheck		
		/doevents
		/if (${gotAggro}) /return ABORT_AGGRO
		/if (${Cast.Result.Equal[CAST_SUCCESS]}) {
			/call AddRezTracker ${Target.ID}
			/return COMPLETED_SUCCESS
		} else {
			/call EchoLog "Rez Failed, Reason: ${Cast.Result}" true
			/return COMPLETED_FAIL
		}
	}
/return UNKNOWN

Sub AddRezTracker(int rezTrackID)
	/declare rtLoop				int local 0
	/declare rtInt				int local 0
	
	/call CleanRezTracker
	
	/for rtLoop 1 to 60
		/if (!${rezTracker[${rtLoop}]}) /varset rtInt ${rtLoop}
	/if (!${rtInt}) /next rtLoop
	
	/if (!${rtInt}) {
		/call EchoLog "\ayThere are currently 60 corpses being tracked, no more can be tracked at this time."
	} else {
		/call EchoLog "Tracking ${Spawn[${rezTrackID}].CleanName}, number ${rtInt}" true
		/if (!${Defined[rezTimer${rtInt}]}) /declare rezTimer${rtInt}			timer outer
		/varset rezTimer${rtInt} ${rezTimerStr}
		/varset rezTracker[${rtInt}] ${rezTrackID}
	}
/return

Sub OkToRez(int rezCheckID)
	/declare retValue				bool local true
	/declare rtLoop					int local 0
	/declare rtFound				bool local false
	
	/for rtLoop 1 to 60
		/if (${rezTracker[${rtLoop}]} == ${rezCheckID}) {
			/varset rtFound true
			/if (${rezTimer${rtLoop}}) {
				/varset retValue false
			} else {
				/varset retValue true
				/varset rezTracker[${rtLoop}] 0
			}
		}
	/if (!${rtFound}) /next rtLoop
	
	/if (!${rtFound}) /varset retValue true
/return ${retValue}

Sub CleanRezTracker
	/declare rtLoop				int local
	
	/for rtLoop 1 to 60
		/if (${rezTracker[${rtLoop}]}) {
			/if (!${Spawn[${rezTracker[${rtLoop}]}].ID} || ${Spawn[${rezTracker[${rtLoop}]}].Type.NotEqual[Corpse]}) /varset rezTracker[${rtLoop}] 0
		}
	/next rtLoop
/return

Sub TrackPromise(int playerID, int SpellID)
	/if (!${Defined[playerID]}) /return
	/declare pLoop					int local 0
	/declare pInt						int local 0 
	
	/for pLoop 1 to 20
		/if (${promiseTrack[${pLoop}]} == ${playerID}) /varset pInt ${pLoop}
	/if (!${pInt}) /next pLoop
	
	/if (${pInt}) {
		/if (${promiseTrackTimer${pInt}}) {
			/return FALSE
		} else {
			/varset promiseTrack[${pInt}] 0
			/return TRUE
		}
	} else {
		/if (${Defined[SpellID]}) {
			/varset pInt 0
			/for pLoop 1 to 20
				/if (!${promiseTrack[${pLoop}]}) {
					/varset pInt ${pLoop}
					/varset promiseTrack[${pLoop}] ${playerID}
					/if (!${Defined[promiseTrackTimer${pLoop}]}) /declare promiseTrackTimer${pLoop}		timer outer
					/varset promiseTrackTimer${pLoop} ${Math.Calc[${Spell[${SpellID}].Duration} * 6 + 1]}s
				}
			/if (!${pInt}) /next pLoop
		} else {
			/return TRUE
		}
	}
/return FALSE

Sub TrackHoT(int playerID, int SpellID)
	/if (!${Defined[playerID]}) /return
	/declare pLoop					int local 0
	/declare pInt						int local 0 
	
	/for pLoop 1 to 20
		/if (${hotTrack[${pLoop}]} == ${playerID}) /varset pInt ${pLoop}
	/if (!${pInt}) /next pLoop
	
	/if (${pInt}) {
		/if (${hotTrackTimer${pInt}}) {
			/return FALSE
		} else {
			/varset hotTrack[${pInt}] 0
			/return TRUE
		}
	} else {
		/if (${Defined[SpellID]}) {
			/varset pInt 0
			/for pLoop 1 to 20
				/if (!${hotTrack[${pLoop}]}) {
					/varset pInt ${pLoop}
					/varset hotTrack[${pLoop}] ${playerID}
					/if (!${Defined[hotTrackTimer${pLoop}]}) /declare hotTrackTimer${pLoop}		timer outer
					/varset hotTrackTimer${pLoop} ${Math.Calc[${Spell[${SpellID}].Duration} * 6 + 1]}s
				}
			/if (!${pInt}) /next pLoop
		} else {
			/return TRUE
		}
	}
/return FALSE

And it will sure load the setting from shmbotsettings_YourCharName.ini
Here is my sham.ini
Code:
[General]
MinSafeDistance=5
CampRadius=60
ResistTries=3
TimeToSitAfterCast=3s
ReplyToTells=false
LootCorpses=false
UnsafePCAction=continue
AllowInterrupt=true
AllowSit=true

PullerName=group
MainAssist=group
MainTank=group

GroupBuffAtStart=true
SelfBuffAtStart=true
HealAtStart=true
DebuffAtStart=true
HealPets=true

MinBuffCheckTimer=1m
HealCheckTime=0s

Announcements=true
AnnounceChan=/g

RezSpell=Null
RezSlot=Null
RezAnnounce=Reviviscence (96% rez) in on %t

YaulpSpell=
YaulpSlot=

EmergencyHealHP=30
UseEpicBalance=false
UseAABalance=False

[SelfBuffs]
Value=0
SelfBuffName1=Cryostasis Fragment Ring
SelfBuffText1=Knowledge of the Past V
SelfBuffSlot1=item

SelfBuffName2=Grlax's Belt
SelfBuffText2=Expanding Mind II
SelfBuffSlot2=item

SelfBuffName3=Slagstone
SelfBuffText3=Prismatic Ward III
SelfBuffSlot3=item


SelfBuffName4=Merciless Visage of Discord
SelfBuffText4=Form of Endurance VII
SelfBuffSlot4=item

[GroupBuffs]
Value=6
GroupBuffGroup1=Talisman of Unity Rk. II
GroupBuffGroupDisplayName1=Talisman of Unity Rk. II
GroupBuffSingle1=Talisman of Unity Rk. II
GroupBuffSingleDisplayName1=Talisman of Unity Rk. II
GroupBuffAlias1=Shielding
GroupBuffTargets1=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER|SHM|CLR|DRU|WIZ|MAG|ENC|NEC
GroupBuffSlot1=gem6
GroupBuffCombat1=false
GroupBuffGroupAnnounce1=Unity inc on group
GroupBuffSingleAnnounce1=Unity inc on %t
GroupBuffAuto1=TRUE
GroupBuffGroupMin1=1

GroupBuffGroup2=Talisman of Celerity
GroupBuffGroupDisplayName2=Talisman of Celerity
GroupBuffSingle2=Talisman of Celerity
GroupBuffSingleDisplayName2=Talisman of Celerity
GroupBuffAlias2=Haste
GroupBuffTargets2=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER|SHM|CLR|DRU|WIZ|MAG|ENC|NEC
GroupBuffSlot2=gem7
GroupBuffCombat2=false
GroupBuffGroupAnnounce2=Haste inc 
GroupBuffSingleAnnounce2=Haste inc on %t
GroupBuffAuto2=TRUE
GroupBuffGroupMin2=1

GroupBuffGroup3=Champion
GroupBuffGroupDisplayName3=Champion
GroupBuffSingle3=Champion
GroupBuffSingleDisplayName3=Champion
GroupBuffAlias3=Champion
GroupBuffTargets3=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER|SHM|CLR|DRU|WIZ|MAG|ENC|NEC
GroupBuffSlot3=gem8
GroupBuffCombat3=false
GroupBuffGroupAnnounce3=Champion inc 
GroupBuffSingleAnnounce3=Champion inc %t
GroupBuffAuto3=TRUE
GroupBuffGroupMin3=1

GroupBuffGroup4=Null
GroupBuffGroupDisplayName4=Null
GroupBuffSingle4=Wild Growth Rk. II
GroupBuffSingleDisplayName4=Wild Growth Rk. II
GroupBuffAlias4=hp
GroupBuffTargets4=MT
GroupBuffSlot4=gem10
GroupBuffCombat4=False
GroupBuffGroupAnnounce4=WG inc 
GroupBuffSingleAnnounce4=WG inc on %t
GroupBuffAuto4=TRUE
GroupBuffGroupMin4=1

GroupBuffGroup5=Talisman of the Lynx Rk. II
GroupBuffGroupDisplayName5=Talisman of the Lynx Rk. II
GroupBuffSingle5=Null
GroupBuffSingleDisplayName5=Null
GroupBuffAlias5=Proc
GroupBuffTargets5=MT
GroupBuffSlot5=Null
GroupBuffCombat5=TRUE
GroupBuffGroupAnnounce5=Lynx inc on group
GroupBuffSingleAnnounce5=Lynx inc on %t
GroupBuffAuto5=TRUE
GroupBuffGroupMin5=1

GroupBuffGroup6=Blessed Spiritstaff of the Heyokah
GroupBuffGroupDisplayName6=Prophet's Gift of the Ruchu
GroupBuffSingle6=Null
GroupBuffSingleDisplayName6=Null
GroupBuffAlias6=ep2.0
GroupBuffTargets6=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER
GroupBuffSlot6=item
GroupBuffCombat6=TRUE
GroupBuffGroupAnnounce6=Ep2.0 inc 
GroupBuffSingleAnnounce6=Ep2.0 inc on %t
GroupBuffAuto6=TRUE
GroupBuffGroupMin6=1

[SafePCs]
Value=0
PCName1=

[LeaveLoot]
LootNoDrop=true
LeaveUnknown=true
Value=0
LootItem1=pearl
LootAlert1=f:\kungfu.mp3
[WantedLoot]
Value=2
LootItem1=pearl
LootAlert1=f:\kungfu.mp3
LootItem2=spell
[DestroyLoot]
DestroyUnknown=false
Value=0
LootItem1=

[IgnoreMobs]
Value=0
MobName1=

[Debuffs]
DebuffAdds=false
Value=0
DebuffSpell1=Healing Counterbias
DebuffMinMana1=1
DebuffMinHPs1=10
DebuffMaxHPs1=99
DebuffMaxMobs1=100
DebuffMinMobs1=1
DebuffSpellSlot1=gem4
DebuffRecastDly1=400s
DebuffAnnounce1=HC SLOW on %t

[Heals]
OutOfCombatHeal=Halcyon Whisper Rk. II
OutOfCombatSlot=gem1
OutOfCombatHP=80
Value=2

HealName1=Dannal's Mending Rk. II
HealSlot1=gem2
HealMinGroup1=1
HealMinHP1=31
HealMaxHP1=80
HealClasses1=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER|SHM|CLR|DRU|WIZ|MAG|ENC|NEC
HealAnnounce1=Dannal's Mending on %t

HealName2=Antecedent's Intervention Rk. II
HealSlot2=gem3
HealMinGroup2=1
HealMinHP2=1
HealMaxHP2=30
HealClasses2=WAR|SHD|PAL|RNG|MNK|ROG|BRD|BST|BER|SHM|CLR|DRU|WIZ|MAG|ENC|NEC
HealAnnounce2=Emergency Group heal inc, Save your life!

[Alerts]
AlertDeathAudioFile=null
AlertEvac=null
Value=0
AlertMobName1=null
AlertAudioFile1=null

I've test it some,seems works smooth...Just one problem i need to solve:

It will cast Turgur's Swarm over and over,But I already write
Code:
/if ( ${Target.PctHPs}<=98 && ${Me.AltAbilityReady[Turgur's Swarm]} && ${Target.Type.Equal[NPC]} && ${Target.Buff[Turgur's Swarm].ID}!= 13144) {

/gsay AA slow on %t!
/delay 1s
/aa act Turgur's Swarm

in Sub Slow,Why it will keep cast that? The /if condition ${Target.Buff[Turgur's Swarm].ID}!= 13144 didnt work??


And it also cast WG and Epic2.0 out of combat which i have set the "GroupBuffCombatX=TRUE" ,so need fix that too...other function basically works well.

Any comments would be thankful;)
 
Last edited:
Try changing:
Code:
${Target.Buff[Turgur's Swarm].ID}!= 13144

To this:
Code:
!${Target.Buff[Turgur's Swarm].ID}