All pastes #947611 Raw Edit

Unnamed

public text v1 · immutable
·published 2008-03-18 16:35 UTC
rendered paste body
;----- *** GLOBAL ***
#define OB_IDLE 0
#define OB_ASSIST_IDLE 2000
#define OB_PARTY_IDLE 3000


;----- *** MAIN ***
#define OB_DEAD 1001
#define OB_TOON 1002
#define OB_NPC 1003
#define OB_ITEM 1004
#define OB_LOOT 1005
#define OB_QUEST 1006
#define OB_BG 1007
#define OB_ROAM 1008

#define MAIN_STATE_START 1001
#define MAIN_STATE_END 1008

;----- *** ASSIST MODE ***
; no NPC or QUEST or ITEM, replace ROAM with ASSIST
#define OB_DEAD_ASSIST 2001
#define OB_TOON_ASSIST 2002
#define OB_LOOT_ASSIST 2003
#define OB_ASSIST 2004

#define ASSIST_STATE_START 2001
#define ASSIST_STATE_END 2004

;----- *** PARTY MODE ***
#define OB_DEAD_PARTY 3001
#define OB_TOON_PARTY 3002
#define OB_NPC_PARTY 3003
#define OB_ITEM_PARTY 3004
#define OB_LOOT_PARTY 3005
#define OB_QUEST_PARTY 3006
#define OB_ROAM_PARTY 3007

#define OB_PARTY_REST 3100
#define OB_FOLLOW_LEADER 3102
#define OB_PARTYHEAL 3103
#define OB_PARTYBUFF 3104
#define OB_PARTYREZ 3105
#define OB_PARTYCURE 3106
#define OB_CROWDCONTROL 3107

#define PARTY_STATE_START 3001
#define PARTY_STATE_END 3007

;----- DEAD
#define OB_RELEASE 101
#define OB_DEADMOVE 102
#define OB_USE_SPIRITHEALER 103
#define OB_SPIRITHEALER 104
#define OB_SAFE_RES 105
#define OB_REVIVE_CORPSE 106
#define OB_DEAD_WAIT 107
#define OB_DEAD_FUCKED 108
#define OB_DEAD_MOREGOSSIP 109
#define OB_CLASS_DEAD 110

;----- TOON
#define OB_COMBAT_BUFF 201
#define OB_COMBAT 202
#define OB_COMBAT_IDLE 203
#define OB_BUFF 204
#define OB_REST 205
#define OB_MOVETO_PULL 206
#define OB_PULL_BUFF 207
#define OB_PULL 208
#define OB_PULL_WAIT 209
#define OB_CASTING 210
#define OB_CASTING_WAIT 211
#define OB_ACT_HUMAN 212
#define OB_COMBAT_CLASS_IDLE 213
#define OB_FLEE 214
#define OB_FLEE_WAIT 215
#define OB_TOON_WAIT 216

;----- NPC Sub State Name
#define OB_USE_NPC 301
#define OB_MOREGOSSIP 302
#define OB_TAKE_FLIGHT 303
#define OB_REPAIR 304
#define OB_SELL 305
#define OB_TRAINER 306
#define OB_AUCTION 307
#define OB_NPC_WAIT 308
#define OB_NPC_MOVE 309
#define OB_LOGOUT 310
#define OB_START_HEARTH 311
#define OB_HEARTHING 312
#define OB_RESTOCK 313
#define OB_MULE 314
#define OB_NPC_GETTING_READY 315
#define OB_HEARTH_GETTING_READY 316
#define OB_LEARN_FLIGHT 317

;----- TRADESKILL (in NPC and takes place b4 SELL)
#define OB_TRADESKILL_MAKE 320
#define OB_TRADESKILL_BUY 321
#define OB_TRADESKILL_MOVE 322
#define OB_TRADESKILL_WAIT 323

;----- LOOT
#define OB_USE_LOOT 401
#define OB_SKIN_CORPSE 402
#define OB_LOOT_CORPSE 403
#define OB_LOOT_HERB 404
#define OB_LOOT_ORE 405
#define OB_LOOTALL 406
#define OB_CLOSE_LOOT 407
#define OB_LOOT_WAIT 408
#define OB_LOOT_MOVE 409
#define OB_LOOT_GETTING_READY 410
#define OB_OPENING 411
#define OB_FISHING 412


;----- ITEM
#define OB_EQUIP_BAG 501
#define OB_EQUIP_GEAR 502
#define OB_EQUIP_WAIT 503
#define OB_ITEM_DESTROY 504
#define OB_ITEM_OPEN 505
#define OB_ITEM_MOTE 506

;----- QUEST
#define OB_QUEST_REWARD 510
#define OB_QUEST_NEEDGOSSIP 511
#define OB_QUEST_GOSSIP 512
#define OB_QUEST_CLOSEGOSSIP 513
#define OB_QUEST_NEEDNPC 514
#define OB_ITEM_BEGINSQUEST 515
#define OB_QUEST_NEEDOBJECT 516
#define OB_QUEST_HARVEST 517
#define OB_QUEST_WAIT 518

;----- ROAM
#define OB_MOUNT 601
#define OB_DISMOUNT 602
#define OB_LEVELUP 603
#define OB_NEED_PULL 604
#define OB_NEED_VENDOR 605
#define OB_NEED_TRAINER 606
#define OB_NEED_MAILBOX 607
#define OB_NEED_BANK 608
#define OB_NEED_AH 609
#define OB_NEED_FP 530
#define OB_MOVETO_MOB 610
#define OB_ROAMING 611
#define OB_ROAM_TO_NODE 612
#define OB_ROAM_COMPLETE 613
#define OB_ROAM_EXPLORE 614
#define OB_ROAM_EVENT 615

;----- BG
#define OB_BGWAITINGQ 701
#define OB_BGWAITSTART 702
#define OB_BGPREBUFF 703
#define OB_INBG 704
#define OB_BGNEEDQUEUE 705
#define OB_LEAVEBG 706
#define OB_BG_GAURDING 707
#define OB_BG_STUCK 708
#define OB_BG_CLASSGUARD 709



#define OB_FISHING_EXTENSION Autofish
#define OB_FISHING_POLE Fishing Pole


objectdef oState inherits oBase
{
	variable int CurrentState = OB_IDLE
	variable int CurrentSubState = OB_IDLE

	variable string MovingToLoc = "FALSE"
	variable int JustRes = ${LavishScript.RunningTime}
	variable int FindSpot = ${LavishScript.RunningTime}

	variable int LagTime = 10000

	; logout settings
	variable bool LogoutOnTimer = FALSE
	variable int LogOutIn = 0
	variable int LogOutInMS = 0
	variable bool LogOutOnLevel = FALSE
	variable int LogOutLevel = 0
	variable int LastLogoutChange = 0

	; ends hotspot iteration by iterating to next valid location
	variable int Location_Failed_Count = 0
	variable int Location_Failed_Timer = 0

	;Mail
	variable int MailClickable = ${LavishScript.RunningTime}

	variable int DEADState_Wait_Until = 0
	variable int DEADState_Release_Wait_Until_Timeout = 10
	variable int DEADState_Interact_Wait_Until_Timeout = 4

	variable int ITEMState_Equip_Wait_Until = 0
	variable int ITEMState_Equip_Wait_Until_Timeout = 2

	variable int TOONState_Pull_Wait_Until = 0
	variable int TOONState_Pull_Wait_Until_Timeout = 4
	variable int TOONState_Casting_Wait_Until = 0
	variable int TOONState_Casting_Until_Timeout = 2

	variable int TOONState_General_Wait_Until = 0
	variable int TOONState_General_Until_Timeout = 5

	variable int LOOTState_Loot_Wait_Until = 0
	variable int LOOTState_Loot_Wait_Until_Timeout = 1
	variable int LOOTState_Loot_Wait_After_Until_Timeout = 2

	variable int LOOTState_Skip_Scans = 0
	variable int LOOTState_Skip_Scans_Timeout = 10

	variable int TOONState_Flee_Wait_Until = 0
	variable int TOONState_Last_Flee_Time = 0

	variable int LOOTState_Loot_Fishing_Until = 0
	variable int LOOTState_Loot_Fishing_Timeout = 30
	variable string MainHandBeforeFishing = NULL
	variable string OffHandBeforeFishing = NULL


	variable int NPCState_NPC_Wait_Until = 0
	variable int NPCState_Hearthstone_Wait_Until_Timeout = 10
	variable int NPCState_Use_Wait_Until_Timeout = 10
	variable int NPCState_Interact_Wait_Until_Timeout = 2

	variable int QUESTstate_Wait_Until = 0
	variable int QUESTstate_Wait_Until_Timeout = 4
	variable int QUESTstate_Harvest_Wait_Until_Timeout = 10
	
	variable int WaitForLoot = ${LavishScript.RunningTime}


	method Initialize()
	{

	}

	method ShutDown()
	{

	}

	member StateName(int StateNumber)
	{
		switch ${StateNumber}
		{
			;----- GLOBAL State Name
			case OB_IDLE
			return "IDLE"
			case OB_ASSIST_IDLE
			return "ASSIST IDLE"

			;----- MAIN State Name
			case OB_DEAD
			return "DEAD"
			case OB_TOON
			return "TOON"
			case OB_NPC
			return "NPC"
			case OB_BG
			return "BG"
			case OB_ITEM
			return "ITEM"
			case OB_LOOT
			return "LOOT"
			case OB_QUEST
			return "QUEST"
			case OB_ROAM
			return "ROAM"
			case OB_DEAD_WAIT
			return "DEAD WAITING"
			case OB_DEAD_MOREGOSSIP
			return "MOREGOSSIP"

			;----- ASSIST State Name
			case OB_DEAD_ASSIST
			return "DEAD"
			case OB_TOON_ASSIST
			return "TOON"
			case OB_LOOT_ASSIST
			return "LOOT_ASSIST"
			case OB_ASSIST
			return "ASSIST"

			;----- PARTY State Name
			case OB_DEAD_PARTY
			return "DEAD_PARTY"
			case OB_TOON_PARTY
			return "TOON_PARTY"
			case OB_NPC_PARTY
			return "NPC_PARTY"
			case OB_ITEM_PARTY
			return "ITEM_PARTY"
			case OB_LOOT_PARTY
			return "LOOT_PARTY"
			case OB_QUEST_PARTY
			return "QUEST_PARTY"
			case OB_ROAM_PARTY
			return "ROAM_PARTY"
			case OB_PARTYHEAL
			return "HEALING GROUP"
			case OB_PARTYBUFF
			return "BUFFING GROUP"
			case OB_PARTY_REST
			return "PARTY REST"
			case  OB_FOLLOW_LEADER
			return "FOLLOW_LEADER"
			case OB_PARTYREZ
			return "RESSURECT"
			case OB_PARTYCURE
			return "THE CURE"
			case OB_CROWDCONTROL
			return "CROWD CONTROL"
			case OB_PARTY_IDLE
			return "IDLE"

			;----- DEAD Sub State Name
			case OB_RELEASE
			return "RELEASE"
			case OB_DEADMOVE
			return "MOVING"
			case OB_SPIRITHEALER
			return "SPIRIT HEALER"
			case OB_SAFE_RES
			return "SAFE RES"
			case OB_REVIVE_CORPSE
			return "REVIVE CORPSE"
			case OB_DEAD_FUCKED
			return "MISSING PATH WE ARE FUCKED"
			case OB_CLASS_DEAD
			return "ROUTINE OVERRIDE"

			;----- ROAM Sub State Name
			case OB_LEVELUP
			return "LEVEL UP"
			case OB_NEED_VENDOR
			return "VENDOR"
			case OB_NEED_TRAINER
			return "TRAINER"
			case OB_NEED_MAILBOX
			return "MAILBOX"
			case OB_NEED_BANK
			return "BANK"
			case OB_NEED_AH
			return "AH"
			case OB_NEED_FP
			return "FLIGHT PATH"
			case OB_MOUNT
			return "MOUNT"
			case OB_DISMOUNT
			return "DISMOUNT"
			case OB_MOVETO_MOB
			return "MOVETO_MOB"
			case OB_ROAMING
			return "ROAMING"
			case OB_NEED_INNKEEPER
			return "INNKEEPER"
			case OB_MULE
			return "MAIL MULE"
			case OB_NPC_GETTING_READY
			return "GETTING READY"
			case OB_ROAM_TO_NODE
			return "ROAM TO NODE"
			case OB_ROAM_COMPLETE
			return "ROAM COMPLETE"
			case OB_ROAM_EXPLORE
			return "ROAM EXPLORE"
			case OB_ROAM_EVENT
			return "ROAM EVENT"

			;----- TOON Sub State Name
			case OB_COMBAT_BUFF
			return "COMBAT BUFF"
			case OB_COMBAT
			return "COMBAT"
			case OB_COMBAT_IDLE
			return "COMBAT_IDLE"
			case OB_COMBAT_CLASS_IDLE
			return "CLASS_IDLE"
			case OB_BUFF
			return "BUFF"
			case OB_REST
			return "REST"
			case OB_MOVETO_PULL
			return "MOVETO_PULL"
			case OB_PULL_BUFF
			return "PULL BUFF"
			case OB_PULL
			return "PULL"
			case OB_PULL_WAIT
			return "PULL WAIT"
			case OB_CASTING
			return "CASTING"
			case OB_CASTING_WAIT
			return "CASTING WAIT"
			case OB_ACT_HUMAN
			return "ACT HUMAN"
			case OB_FLEE
			return "RUN LIKE A GIRL"
			case OB_FLEE_WAIT
			return "POST FLEE WAIT"
			case OB_TOON_WAIT
			return "GENERAL WAIT"

			;----- LOOT Sub State Name
			case OB_SKIN_CORPSE
			return "SKINNING"
			case OB_LOOT_CORPSE
			return "LOOTING"
			case OB_LOOT_HERB
			return "HERBING"
			case OB_LOOT_ORE
			return "MINING"
			case OB_USE_LOOT
			return "USE"
			case OB_LOOTALL
			return "LOOT ALL"
			case OB_CLOSE_LOOT
			return "CLOSING LOOT"
			case OB_LOOT_WAIT
			return "WAIT FOR LOOT"
			case OB_LOOT_MOVE
			return "MOVE TO LOOT"
			case OB_LOOT_GETTING_READY
			return "GETTING READY"
			case OB_OPENING
			return "OPENING"
			case OB_FISHING
			return "FISHING"

			;----- NPC Sub State Name
			case OB_MOREGOSSIP
			return "TALK TO NPC"
			case OB_TAKE_FLIGHT
			return "FLIGHT MASTER"
			case OB_LEARN_FLIGHT
			return "LEARN FLIGHT"
			case OB_REPAIR
			return "REPAIR"
			case OB_SELL
			return "SELL"
			case OB_TRAINER
			return "TRAINER"
			case OB_AUCTION
			return "AUCTION"
			case OB_NPC_WAIT
			return "NPC WAIT"
			case OB_NPC_MOVE
			return "NPC MOVE"
			case OB_START_HEARTH
			return "Invoke Hearthstone"
			case OB_HEARTHING
			return "Hearthing"
			case OB_RESTOCK
			return "RESTOCK FOOD"
			case OB_HEARTH_GETTING_READY
			return "HEARTH GETTING READY"

			;----- TRADESKILL
			case OB_TRADESKILL_MAKE
			return "TRADESKILL_MAKE"
			case OB_TRADESKILL_BUY
			return "TRADESKILL_BUY"
			case OB_TRADESKILL_MOVE
			return "TRADESKILL_MOVE"
			case OB_TRADESKILL_WAIT
			return "TRADESKILL_WAIT"

			;----- ITEM Sub State Name
			case OB_EQUIP_BAG
			return "Equip Bag"
			case OB_EQUIP_GEAR
			return "Equip Gear"
			case OB_EQUIP_WAIT
			return "Equip Wait"
			case OB_ITEM_DESTROY
			return "Destroying"
			case OB_ITEM_OPEN
			return "Opening"
			case OB_ITEM_MOTE
			return "Stacking Motes"

			;----- QUEST Sub State Name
			case OB_QUEST_NEEDOBJECT
			return "QUEST_OBJECT"
			case OB_QUEST_HARVEST
			return "QUEST_HARVEST"
			case OB_QUEST_NEEDGOSSIP
			return "NEED_QUEST"
			case OB_QUEST_GOSSIP
			return "QUEST_GOSSIP"
			case OB_QUEST_CLOSEGOSSIP
			return "CLOSE_QUESTS"
			case OB_QUEST_NEEDNPC
			return "MOVETO_QUESTGIVER"
			case OB_ITEM_BEGINSQUEST
			return "ITEM_STARTQUEST"
			case OB_QUEST_REWARD
			return "QUEST_REWARD"
			case OB_QUEST_WAIT
			return "QUEST_WAIT"

			;----- BG State
			case OB_BGWAITINGQ
			return "BG Queued"
			case OB_BGWAITSTART
			return "Wait BG Start"
			case OB_BGPREBUFF
			return "BG Buff Prep"
			case OB_INBG
			return "In BG"
			case OB_BGNEEDQUEUE
			return "BG:Need Queue"
			case OB_LEAVEBG
			return "Leave BG"
			case OB_BG_GAURDING
			return "GAURDING"
			case OB_BG_STUCK
			return "BG STUCK"
		}
		return "UNKNOWN:" ${StateNumber}
	}

	/* we branch which states get tested based on Mode */
	/* assist and party have there own set of states that can hook the others as needed */
	method Pulse()
	{
		variable int TempState
		variable int i

		if !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked} && !${UIElement[chkPartyMode@Overview@Pages@openbot].Checked}
		{
			for (i:Set[MAIN_STATE_START];${i}<= MAIN_STATE_END;i:Inc)
			{
				TempState:Set[${This.${This.StateName[${i}]}State}]
				if ${TempState} != OB_IDLE
				{
					This.CurrentState:Set[${i}]
					This.CurrentSubState:Set[${TempState}]
					;This:Debug[${This.StateName[${This.CurrentState}]} ${This.StateName[${This.CurrentSubState}]}]
					This:${This.StateName[${This.CurrentState}]}Pulse
					return
				}
			}
		}
		elseif ${UIElement[chkAssistMode@Overview@Pages@openbot].Checked}
		{
			if ${State.ManualOverride}
			{
				This.CurrentState:Set[OB_ASSIST]
				This.CurrentSubState:Set[OB_ASSIST_IDLE]
				This:Output[User Control Detected.]
				This:${This.StateName[${This.CurrentState}]}Pulse
				return
			}
			for (i:Set[ASSIST_STATE_START];${i}<= ASSIST_STATE_END;i:Inc)
			{
				TempState:Set[${This.${This.StateName[${i}]}State}]
				if ${TempState} != OB_IDLE
				{
					This.CurrentState:Set[${i}]
					This.CurrentSubState:Set[${TempState}]
					;This:Debug[${This.StateName[${This.CurrentState}]} ${This.StateName[${This.CurrentSubState}]}]
					This:${This.StateName[${This.CurrentState}]}Pulse
					return
				}
			}
		}
		else
		{
			for (i:Set[PARTY_STATE_START];${i}<= PARTY_STATE_END;i:Inc)
			{
				TempState:Set[${This.${This.StateName[${i}]}State}]
				if ${TempState} != OB_IDLE
				{
					This.CurrentState:Set[${i}]
					This.CurrentSubState:Set[${TempState}]
					;This:Debug[${This.StateName[${This.CurrentState}]} ${This.StateName[${This.CurrentSubState}]}]
					This:${This.StateName[${This.CurrentState}]}Pulse
					return
				}
			}
		}
	}

	;----------
	;----- DEAD Sub State
	;----------

	member DEADState()
	{
		/* wait for death lag */
		if ${LavishScript.RunningTime} <= ${DEADState_Wait_Until}
		{
			return OB_DEAD_WAIT
		}

		/* when we are dead, but not yet a ghost -- allow for routine hooking here */
		if ${Me.Dead}
		{
			if ${Class.NeedDead}
			{
				return OB_CLASS_DEAD
			}
			This.DEADState_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.DEADState_Release_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_RELEASE
		}

		/* ok -- we died and releaseed -- now what? (No BG Spirit Healer Nearby) */
		if ${Me.Ghost} && !${BG.InBG}
		{
			if ${Math.Calc[${LavishScript.RunningTime} - ${This.JustRes}]} >= ${LagTime}
			{
				/* check corpse before Spirit Healer */
				if ${POI.Type.Equal[CORPSE]}
				{
					if ${Navigator.SafeToRes}
					{
						return OB_REVIVE_CORPSE
					}
					else
					{
						if ${Math.Distance[${Me.Location},${Me.Corpse}]} < 40
						{
							return OB_SAFE_RES
						}
						else
						{
							return OB_DEADMOVE
						}
					}
				}
				elseif !${POI.NeedSpiritHealer}
				{
					/* only set corpse if we dont need Spirit Healer */
					/* and only need Spirit Healer based on corpse counter */
					if ${POI.Set[${Me.Corpse.X}:${Me.Corpse.Y}:${Me.Corpse.Z}:-1:"Corpse of ${Me.Name}":CORPSE:${Me.FactionGroup.Upper}:${Me.Level}]}
					{
						return OB_DEADMOVE
					}
				}

				if ${POI.Type.Equal[SPIRITHEALER]} && !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked}
				{
					if ${POI.InUseRange}
					{
						if ${WoWScript[StaticPopup1:IsVisible()]}
						{
							This.DEADState_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.DEADState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_SPIRITHEALER
						}
						else
						{
							if ${WoWScript[GetGossipOptions()](exists)}
							{
								return OB_DEAD_MOREGOSSIP
							}
							else
							{
								This.DEADState_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.DEADState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_USE_SPIRITHEALER
							}
						}
					}
					else
					{
						return OB_DEADMOVE
					}
				}
				else
				{
					if ${POI.SetNearestPOI[SPIRITHEALER]} && !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked}
					{
						return OB_DEADMOVE
					}
					elseif ${POI.Set[${Me.Corpse.X}:${Me.Corpse.Y}:${Me.Corpse.Z}:-1:"Corpse of ${Me.Name}":CORPSE:${Me.FactionGroup.Upper}:${Me.Level}]}
					{
						return OB_DEADMOVE
					}
					else
					{
						This:Output[No way to Corpse and to Spirithealer. Not enough Mapping data.]
						return OB_DEAD_FUCKED
					}
				}
			}
			else
			{
				return OB_DEAD_WAIT
			}
		}
		if ${Me.Ghost} && ${BG.InBG}
		{
			Toon:Stop
			return OB_DEAD_WAIT
		}
		return OB_IDLE
	}

	method DEADPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_CLASS_DEAD
			Class:DeadPulse
			break

			case OB_RELEASE
			if ${UIElement[chkDeathSoundOn@Config@Pages@openbot].Checked}
			{
				This:PlaySound["Inform"]
			}
			Navigator:ClearPath
			move -stop
			This.JustRes:Set[${LavishScript.RunningTime}]
			WoWScript RepopMe()
			if ${LavishScript.RunningTime} <= ${Math.Calc[${POI.LastRetrieveCorpseTime} + ${POI.CorpseCampTimeout}]} && !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked} && !${BG.BGMode}
			{
				POI.CorpseCampCount:Inc
				This:Output[Corpse Camp Counter ${POI.CorpseCampCount} of ${Config.GetSlider[sldCorpseCamped]}]
				if ${POI.CorpseCampCount} >= ${Config.GetSlider[sldCorpseCamped]} && !${BG.InBG}
				{
					This:Output[Corpse Camped -> Try Spritithealer]
					This:Output[Trying luck at next Grind Spot]
					Grind:NextHotspot
					POI.NeedSpiritHealer:Set[TRUE]
					POI.CorpseCampCount:Set[0]
				}
			}
			else
			{
				POI.CorpseCampCount:Set[0]
			}
			Grind.RepopCount:Inc
			break

			case OB_DEAD_MOREGOSSIP
			WoWScript SelectGossipOption(1)
			break

			case OB_SPIRITHEALER
			WoWScript "AcceptXPLoss()"
			break

			case OB_USE_SPIRITHEALER
			Navigator:ClearPath
			move -stop
			POI:Use
			break

			case OB_DEADMOVE
			MovingToLoc:Set["TRUE"]
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_SAFE_RES
			Navigator:ClearPath
			FindSpot:Set[${LavishScript.RunningTime}]
			MovingToLoc:Set["TRUE"]
			Navigator:MoveToLoc[${Navigator.FindSafeSpot}]
			break

			case OB_REVIVE_CORPSE
			Navigator:ClearPath
			Navigator.ForceRes:Set[FALSE]
			Navigator.ResSpot:Set[0]
			WoWScript RetrieveCorpse()
			MovingToLoc:Set["TRUE"]
			MovingToLoc:Set["FALSE"]
			POI.LastRetrieveCorpseTime:Set[${LavishScript.RunningTime}]
			break
		}
	}

	;----------
	;----- TOON Sub State
	;----------
	member TOONState()
	{

		if ${LavishScript.RunningTime} <= ${This.TOONState_General_Wait_Until}
		{
			return OB_TOON_WAIT
		}

		if ${Me.Flying}
		{
			This.TOONState_General_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.TOONState_General_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_TOON_WAIT
		}

		if ${Flee.NeedToRun}
		{
			return OB_FLEE
		}

		if ${Me.InCombat} && !${Mount.IsMounted}
		{
			/* first lets deal with our POI and Target */
			if ${Toon.ValidTarget[${Target.GUID}]} && ${Target.PctHPs} > 0
			{
				if ${POI.GUID.NotEqual[${Target.GUID}]}
				{
					if !${POI.Set[${Target.X}:${Target.Y}:${Target.Z}:${Target.GUID}:${Target.Name}:MOB:FACTION_NEUTRAL:${Target.Level},TRUE]}
					{
						This:Debug[Error: Can not set POI to Target]
					}
				}
			}
			elseif ${Me.InCombat} && ${Toon.ValidTarget[${Targeting.TargetCollection.Get[1]}]} && ${Object[${Targeting.TargetCollection.Get[1]}].PctHPs} > 0
			{
				Toon:NeedTarget
				if !${POI.Set[${Object[${Targeting.TargetCollection.Get[1]}].X}:${Object[${Targeting.TargetCollection.Get[1]}].Y}:${Object[${Targeting.TargetCollection.Get[1]}].Z}:${Object[${Targeting.TargetCollection.Get[1]}].GUID}:${Object[${Targeting.TargetCollection.Get[1]}].Name}:MOB:FACTION_NEUTRAL:${Object[${Targeting.TargetCollection.Get[1]}].Level},TRUE]}
				{
					This:Debug[Error: Can not set POI to AGGRO Target]
					Toon:NeedTarget
				}
			}

			/* darkfriend add this */
			if ${BG.BGMode}
			{
				if (${Target(exists)} && ${Target.Type.Equal["Player"]}) || (${Target.Distance} < ${Toon.PullRange} && ${Target.LineOfSight} && (!${Mount.IsMounted} || !${Movement.Speed} && ${Mount.IsMounted}))
				{
					if ${Class.NeedCombatBuff}
					{
						return OB_COMBAT_BUFF
					}
					else
					{
						return OB_COMBAT
					}
				}
				elseif !${Target(exists)} && !${Mount.IsMounted}
				{
					/* we have no target, so lets idle */
					if ${Class.NeedCombatIdle}
					{
						return OB_COMBAT_CLASS_IDLE
					}
				}
			}
			else
			{
				if ${Target(exists)}
				{
					if ${Class.NeedCombatBuff}
					{
						return OB_COMBAT_BUFF
					}
					else
					{
						return OB_COMBAT
					}
				}
				else
				{
					/* we have no target, so lets idle */
					if ${Class.NeedCombatIdle}
					{
						return OB_COMBAT_CLASS_IDLE
					}
					return OB_COMBAT_IDLE
				}
			}
		}

		if ${Class.NeedRest}
		{
			return OB_REST
		}

		if ${Class.NeedBuff} &&  (0 < ${Toon.SafeSpotRange}) && ${WoWScript[GetBattlefieldInstanceExpiration()]} == 0
		{
			if !${Mount.IsMounted} && 0 < ${Toon.SafeSpotRange}
			{
				return OB_BUFF
			}
		}

		if ${Toon.PullableTarget} && (!${Mount.IsMounted} || ${BG.BGMode})
		{
			if ${POI.Set[${Object[${Targeting.TargetCollection.Get[1]}].X}:${Object[${Targeting.TargetCollection.Get[1]}].Y}:${Object[${Targeting.TargetCollection.Get[1]}].Z}:${Object[${Targeting.TargetCollection.Get[1]}].GUID}:${Object[${Targeting.TargetCollection.Get[1]}].Name}:MOB:FACTION_NEUTRAL:${Object[${Targeting.TargetCollection.Get[1]}].Level},FALSE]}
			{
				if ${Object[${Targeting.TargetCollection.Get[1]}].Distance} > ${Toon.PullRange} && !${Me.Casting}
				{
					return OB_MOVETO_PULL
				}
				else
				{
					if ${Class.NeedPullBuff}
					{
						return OB_PULL_BUFF
					}
					else
					{
						return OB_PULL
					}
				}
			}
			else
			{
				This:Output["Error: Can not set POI to PULL Target"]
			}
		}

		/* catch all casting check - takes place after combat and pull so it wont interfere with combat casting */
		/* we have waits already defined for skinning and such in LOOT */
		if ${Toon.Casting}
		{
			return OB_CASTING
		}

		if ${LavishScript.RunningTime} <= ${This.TOONState_Casting_Wait_Until}
		{
			return OB_CASTING_WAIT
		}

		if ${Human.NeedAction} && ${Human.ActionDelay} < ${LavishScript.RunningTime} && !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked}
		{
			return OB_ACT_HUMAN
		}

		if ${LavishScript.RunningTime} <= ${This.TOONState_Flee_Wait_Until} || ${Math.Calc[${LavishScript.RunningTime}-${This.TOONState_Last_Flee_Time}]} < 1500
		{
			return OB_FLEE_WAIT
		}
		return OB_IDLE
	}

	method TOONPulse()
	{
		if ${Script[OB_FISHING_EXTENSION](exists)}
		{
			This:EndFishing
		}

		switch ${This.CurrentSubState}
		{
			case OB_TOON_WAIT
			/* do nothing, just wait and see */
			break
			case OB_FLEE
			if ${Class.HookFlee}
			{
				Class:FleePulse
			}
			Flee:MoveToFlee
			This.TOONState_Last_Flee_Time:Set[${LavishScript.RunningTime}]
			break

			case OB_FLEE_WAIT
			if ${Math.Calc[${LavishScript.RunningTime}-${This.TOONState_Last_Flee_Time}]} < 1500
			{
				Flee:MoveToFlee
				This.TOONState_Flee_Wait_Until:Set[${This.InMilliseconds[${Math.Rand[450]}]}]
				This:Output["Should be safe, but getting a bit farther away."]
				return
			}
			if ${Movement.Speed}
			{
				Navigator:MoveToLoc[${Me.X},${Me.Y},${Me.Z}]
				move -stop
			}
			This:Output["Waiting a moment after FLEE."]
			break

			case OB_COMBAT_BUFF
			Mount:Dismount
			Class:CombatBuffPulse
			break

			case OB_COMBAT
			Mount:Dismount
			Navigator:ClearPath
			Class:AttackPulse
			break

			case OB_COMBAT_IDLE
			move -stop
			This:Output["Idle in combat."]
			break

			case OB_COMBAT_CLASS_IDLE
			Class:CombatIdle
			break

			case OB_BUFF
			Mount:Dismount
			Navigator:ClearPath
			Class:BuffPulse
			break

			case OB_REST
			Mount:Dismount
			Navigator:ClearPath
			Class:RestPulse
			break

			case OB_MOVETO_PULL
			Mount:Dismount
			Toon:NeedTarget
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_PULL_BUFF
			Mount:Dismount
			Navigator:ClearPath
			Class:PullBuffPulse
			break

			case OB_PULL
			Navigator:ClearPath
			Toon:NeedTarget
			Class:PullPulse
			break

			case OB_CASTING
			This.TOONState_Casting_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.TOONState_Casting_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			if ${Toon.spellCastTime}
			{
				move -stop
			}
			break

			case OB_CASTING_WAIT
			move -stop
			break

			case OB_ACT_HUMAN
			Human:Pulse
			break
		}
	}


	;----------
	;----- LOOT Sub State
	;----------
	member LOOTState()
	{
		variable guidlist list
		variable int Index
		variable bool Found = FALSE
		variable int bltimer

		if ${BG.BGLootMode} && ${BG.BGMode} && ${BG.InBG}
		{
			return OB_IDLE
		}

		if ${Script[OB_FISHING_EXTENSION](exists)} && ${LavishScript.RunningTime} <= ${This.LOOTState_Loot_Fishing_Until} && (${Item[-inventory,"OB_FISHING_POLE"](exists)} || ${Me.Equip[16].Name.Equal["OB_FISHING_POLE"]})
		{
			This:StartFishing
			return OB_FISHING
		}
		else
		{
			This:EndFishing
		}

		if ${Me(unit).Casting.Name.Token[1," "].Equal[Skinning]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_SKIN_CORPSE
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Herbalism]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_LOOT_HERB
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Mining]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_LOOT_ORE
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Opening]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_OPENING
		}

		if ${LavishScript.RunningTime} <= ${This.LOOTState_Loot_Wait_Until}
		{
			return OB_LOOT_WAIT
		}

		if ${LootWindow(exists)}
		{
			if ${LootWindow.Count} > 0 && (${Inventory.FreeSlots} > 0)
			{
				This.LOOTState_Skip_Scans:Set[0]
				return OB_LOOTALL
			}
			else
			{
				This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_After_Until_Timeout} * ${Bot.GlobalCooldown})]}]
				This.LOOTState_Skip_Scans:Set[0]
				return OB_CLOSE_LOOT
			}
		}

		
			if (${Inventory.FreeSlots} > 0) && ${UIElement[chkLoot@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-units,-dead,-lootable,-nearest]
				Index:Set[0]
				if ${list.Count} > 0
				{
					while ${list.GUID[${Index:Inc}](exists)} && !${Found}
					{
						if ${Unit[${list.GUID[${Index}]}].Lootable}
						{
							if ${POI.Set[${Unit[${list.GUID[${Index}]}].X}:${Unit[${list.GUID[${Index}]}].Y}:${Unit[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Unit[${list.GUID[${Index}]}].Name}:LOOT:FACTION_NEUTRAL:${Unit[${list.GUID[${Index}]}].Level}]}
							{
								Found:Set[TRUE]
							}
						}
						if ${Unit[${list.GUID[${Index}]}].Skinnable}
						{
							if ${Toon.CanSkinMob[${list.GUID[${Index}]}]}
							{
								if ${POI.Set[${Unit[${list.GUID[${Index}]}].X}:${Unit[${list.GUID[${Index}]}].Y}:${Unit[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Unit[${list.GUID[${Index}]}].Name}:SKILL_SKINNING:FACTION_NEUTRAL:${Unit[${list.GUID[${Index}]}].Level}]}
								{
									Found:Set[TRUE]
								}
							}
						}
					}
				}
			}
			
			if ${LavishScript.RunningTime} >= ${LOOTState_Skip_Scans} || ${UIElement[chkAssistMode@Overview@Pages@openbot].Checked}
		{
			This.LOOTState_Skip_Scans:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Skip_Scans_Timeout} * ${Bot.GlobalCooldown})]}]


			if !${Found} && ${Toon.HasSkill[SKILL_HERBALISM]} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkGather@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects,-herb,-usable,-unlocked,-nearest]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${Toon.SkillLevel[Herbalism]} >= ${OBDB.GetLevel[${Object[${list.GUID[${Index}]}].Name}]}
					{
						if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:SKILL_HERBALISM:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
						{
							Found:Set[TRUE]
						}
					}
					else
					{
						This:Output[do Not want ${Object[${list.GUID[${Index}]}].Name} level to high.]
					}
				}
			}
			if !${Found} && ${Toon.HasSkill[SKILL_MINING]} && ${Item[-inventory,"Mining Pick"](exists)} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkGather@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects,-mine,-usable,-unlocked,-nearest]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${Toon.SkillLevel[Mining]} >= ${OBDB.GetLevel[${Object[${list.GUID[${Index}]}].Name}]}
					{
						if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:SKILL_MINING:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
						{
							Found:Set[TRUE]
						}
					}
					else
					{
						This:Output[do Not want ${Object[${list.GUID[${Index}]}].Name} level to high.]
					}
				}
			}
			/* quest objects */
			if !${Found} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkHarvestQuests@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects, -nearest, -chest, -unlocked, -usable]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:QUESTOBJECT:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
					{
						Found:Set[TRUE]
					}
				}
			}
		}


		if ${POI.Type.Equal[LOOT]} || ${POI.Type.Equal[Skinning]}
		{
			/*
			if ${Toon.DetectAdds[${POI.GUID}]}
			{
				This:Output[Detected too many adds next to ${POI.Name}. Blacklisting it with GUID for 1 Hour.]
				GlobalBlacklist:Insert[${POI.GUID},3600000]
				POI:Clear
				This.LOOTState_Skip_Scans:Set[0]
				return OB_LOOT_WAIT
			}
			else
			{
				*/
				if ${POI.IsBlacklisted} || !${Object[${POI.GUID}](exists)}
				{
					POI:Clear
					This.LOOTState_Skip_Scans:Set[0]
					return OB_LOOT_WAIT
				}
				else
				{
					if ${POI.InUseRange}
					{
						if (${POI.Type.Equal[LOOT]} && !${Unit[${POI.GUID}].CanLoot})
						{
							POI:Clear
							This.LOOTState_Skip_Scans:Set[0]
							return OB_LOOT_WAIT
						}
						if ${Movement.Speed} || ${Toon.Sitting}
						{
							return OB_LOOT_GETTING_READY
						}
						else
						{
							if ${WaitForLoot} <= ${LavishScript.RunningTime}
							{
							return OB_USE_LOOT
							}
						}
					}
					else
					{
						return OB_LOOT_MOVE
					}
				}
			/*	
			}
			*/
		}
		return OB_IDLE
	}

	method LOOTPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_LOOT_MOVE
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_LOOT_GETTING_READY
			Toon:Standup
			if ${Movement.Speed}
			{
				Navigator:ClearPath
				move -stop
			}
			break

			case OB_USE_LOOT
			POI:Use
			break

			case OB_SKIN_CORPSE
			This:Output["OOOO a skinable corpse, gimmie!!"]
			POI.LastUse:Set[${LavishScript.RunningTime}]
			break

			case OB_LOOT_HERB
			This:Output["OOOO a Herb, gimmie!!"]
			POI.LastUse:Set[${LavishScript.RunningTime}]
			break

			case OB_LOOT_ORE
			This:Output["OOOO an ore deposit, gimmie!!!"]
			POI.LastUse:Set[${LavishScript.RunningTime}]
			break

			case OB_OPENING
			This:Output["OOOO something to open, gimmie!!!"]
			POI.LastUse:Set[${LavishScript.RunningTime}]
			break


			case OB_LOOTALL
			Mount:Dismount
			Navigator:ClearPath
			move -stop
			Toon:Standup
			WaitForLoot:Set[${Math.Calc[${LavishScript.RunningTime} + 800]}]
			POI:LootAll
			Grind.LootCount:Inc
			break

			case OB_CLOSE_LOOT
			WaitForLoot:Set[${Math.Calc[${LavishScript.RunningTime} + 800]}]
			WoWScript CloseLoot()
			POI:Clear
			break
		}
	}

	;----------
	;----- NPC Sub State
	;----------
	member NPCState()
	{
		if ${Me(unit).Casting.Name.Token[1," "].Equal["Hearthstone"]}
		{
			This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Hearthstone_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_HEARTHING
		}

		if ${LavishScript.RunningTime} <= ${NPCState_NPC_Wait_Until}
		{
			return OB_NPC_WAIT
		}

		if ${POI.NeedLogout} || (${UIElement[chkLogOutOnLevel@Logout@Pages@OpenBot].Checked} && ${UIElement[sldLogOutLevel@Logout@Pages@OpenBot].Value(exists)} && ${Me.Level} >= ${UIElement[sldLogOutLevel@Logout@Pages@OpenBot].Value}) || (${UIElement[chkLogoutOnTimer@Logout@Pages@OpenBot].Checked} && ${UIElement[sldLogOutIn@Logout@Pages@OpenBot].Value(exists)} && ${Bot.LogOutIn} <= ${LavishScript.RunningTime}
		{
			if ${Item[Hearthstone](exists)} && ${Me.Action[Hearthstone].Usable}
			{
				if ${Movement.Speed} || ${Toon.Sitting}
				{
					return OB_HEARTH_GETTING_READY
				}
				else
				{
					This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Hearthstone_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
					return OB_START_HEARTH
				}
			}

			if ${POI.Type.Equal[INNKEEPER]} && !${POI.IsBlacklisted}
			{
				if ${POI.InUseRange}
				{
					return OB_LOGOUT
				}
				else
				{
					return OB_NPC_MOVE
				}
			}
			else
			{
				if ${POI.SetNearestPOI[INNKEEPER]}
				{
					return OB_NPC_MOVE
				}
				else
				{
					This:Output[Not enough mapping data to get to an Innkeeper, logging out here!]
					return OB_LOGOUT
				}
			}
		}

		if ${POI.Type.Equal[FLIGHTMASTER]} && !${POI.IsBlacklisted}
		{
			if ${POI.InUseRange}
			{
				if ${WoWScript[TaxiFrame:IsVisible()]}
				{
					This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
					return OB_TAKE_FLIGHT
				}
				else
				{
					if ${WoWScript[GetGossipOptions()](exists)}
					{
						This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
						return OB_MOREGOSSIP
					}
					if ${Movement.Speed} || ${Toon.Sitting}
					{
						return OB_NPC_GETTING_READY
					}
					else
					{
						This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
						return OB_USE_NPC
					}
				}
			}
			else
			{
				return OB_NPC_MOVE
			}
		}
		else
		{
			if ${FlightPlan.TakeFlightMaster}
			{
				if ${FlightPlan.SetFlightPOI}
				{
					return OB_NPC_MOVE
				}
				else
				{
					FlightPlan.NeedFlight:Set[FALSE]
				}
			}
		}

		if ${FlightPlan.LearnFlightMaster}
		{
			if !${Config.GetCheckbox[chkLearnFM]}
			{
				FlightPlan.LearnFlightMaster:Set[FALSE]
				FlightPlan.LearnFM:Set["0:0:0:0:0:0:0:0"]
			}
			elseif ${POI.Type.Equal[FLIGHTMASTER]} && !${POI.IsBlacklisted}
			{
				if ${POI.InUseRange}
				{
					if ${WoWScript[TaxiFrame:IsVisible()]}
					{
						return OB_LEARN_FLIGHT
					}
					else
					{
						if ${WoWScript[GetGossipOptions()](exists)}
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_MOREGOSSIP
						}
						if ${Movement.Speed} || ${Toon.Sitting}
						{
							return OB_NPC_GETTING_READY
						}
						else
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_USE_NPC
						}
					}
				}
				return OB_NPC_MOVE
			}
			elseif ${POI.Set[${FlightPlan.LearnFM}]}
			{
				return OB_LEARN_FLIGHT
			}
		}

		if ${POI.NeedRepair}
		{
			if ${POI.Type.Equal[REPAIR]} && !${POI.IsBlacklisted}
			{
				if ${POI.InUseRange}
				{
					if ${WoWScript[MerchantFrame:IsVisible()]}
					{
						This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
						return OB_REPAIR
					}
					else
					{
						if ${WoWScript[GetGossipOptions()](exists)}
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_MOREGOSSIP
						}
						else
						{
							if ${Movement.Speed} || ${Toon.Sitting}
							{
								return OB_NPC_GETTING_READY
							}
							else
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_USE_NPC
							}
						}
					}
				}
				else
				{
					return OB_NPC_MOVE
				}
			}
			else
			{
				if ${POI.SetNearestPOI[REPAIR]}
				{
					return OB_NPC_MOVE
				}
				else
				{
					This:Output[Not enough mapping data to REPAIR POI !]
					;no return here try other NPC
				}
			}
		}

		if !${BG.BGMode}
		{
			if ${POI.NeedTradeSkill}
			{
				/* Tradeskills.NeedTradeSkill should determine when tradeskills should start and stop */
				if ${Tradeskills.NeedTradeSkill}
				{
					if ${Tradeskills.NeedMake}
					{
						return OB_TRADESKILL_MAKE
					}
					elseif ${Tradeskills.NeedBuy}
					{
						return OB_TRADESKILL_BUY
					}
					elseif ${Tradeskills.NeedTradePOI}
					{
						/* set POI here */
						return OB_TRADESKILL_MOVE
					}
					elseif ${Tradeskills.NeedWait}
					{
						return OB_TRADESKILL_WAIT
					}
				}
				POI.NeedTradeSkill:Set[FALSE]
			}

			if ${POI.NeedSell}
			{
				if ${POI.Type.Equal[SELL]} && !${POI.IsBlacklisted}
				{
					if ${WoWScript[MerchantFrame:IsVisible()]}
					{
						This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
						return OB_SELL
					}
					else
					{
						if ${POI.InUseRange}
						{
							if ${WoWScript[GetGossipOptions()](exists)}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_MOREGOSSIP
							}
							else
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_USE_NPC
							}
						}
						else
						{
							return OB_NPC_MOVE
						}
					}
				}
				else
				{
					if ${POI.SetNearestPOI[SELL]}
					{
						return OB_NPC_MOVE
					}
					else
					{
						This:Output[Not enough mapping data to SELL POI !]
						;no return here try other NPC
					}
				}
			}

			if ${POI.NeedRestock}
			{
				if ${Inventory.FreeSlots} > 0
				{
					if (${POI.Name.Equal[${Inventory.FoodMerch}]} || ${POI.Name.Equal[${Inventory.DrinkMerch}]} || ${POI.Name.Equal[${Inventory.AmmoMerch}]}) &&  !${POI.IsBlacklisted}
					{
						if ${POI.InUseRange}
						{
							if ${WoWScript[MerchantFrame:IsVisible()]}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_RESTOCK
							}
							else
							{
								if ${WoWScript[GetGossipOptions()](exists)}
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_MOREGOSSIP
								}
								else
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_USE_NPC
								}
							}
						}
						else
						{
							return OB_NPC_MOVE
						}
					}
					else
					{
						if ${Inventory.NeedRestock[1].Equal[Food]} && ${Inventory.FoodMerch.NotEqual[""]} && ${POI.SetPOINamed[${Inventory.FoodMerch}]}
						{
							return OB_NPC_MOVE
						}
						if ${Inventory.NeedRestock[1].Equal[Water]} && ${Inventory.DrinkMerch.NotEqual[""]} && ${POI.SetPOINamed[${Inventory.DrinkMerch}]}
						{
							return OB_NPC_MOVE
						}
						if (${Inventory.NeedRestock[1].Equal[Ammo]} || ${Inventory.NeedRestock[1].Equal[Arrow]}) && ${Inventory.AmmoMerch.NotEqual[""]} && ${POI.SetPOINamed[${Inventory.AmmoMerch}]}
						{
							return OB_NPC_MOVE
						}
						This:Output[Not enough mapping data to RESTOCK POI !]
						;no return here try other NPC
					}
				}
				else
				{
					POI.NeedRestock:Set[FALSE]
				}
			}

			if ${POI.NeedMailbox}
			{
				if ${POI.Type.Equal[MAILBOX]} && !${POI.IsBlacklisted}
				{
					if ${POI.InUseRange}
					{
						if ${WoWScript[MailFrame:IsVisible()]}
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_MULE
						}
						else
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_USE_NPC
						}
					}
					else
					{
						return OB_NPC_MOVE
					}
				}
				else
				{
					if ${POI.SetNearestPOI[MAILBOX]}
					{
						return OB_NPC_MOVE
					}
					else
					{
						This:Output[Not enough mapping data to MAILBOX POI !]
						;no return here try other NPC
						POI.NeedMailbox:Set[FALSE]
					}
				}
			}

			if ${POI.NeedClassTrainer}
			{
				if ${POI.Type.Equal[${Me.Class}_TRAINER]} && !${POI.IsBlacklisted}
				{
					if ${POI.InUseRange}
					{
						if ${This.VisibleFrame[ClassTrainerFrame]}
						{
							This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_TRAINER
						}
						else
						{
							if ${WoWScript[GetGossipOptions()](exists)}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_MOREGOSSIP
							}
							else
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_USE_NPC
							}
						}
					}
					else
					{
						if !${WoWScript["GetContainerItemCooldown(${Item[Hearthstone].Bag.Number}, ${Item[Hearthstone].Slot})", 2]}
					{
					Move -stop
					Item[Hearthstone]:Use
					Bot.ForcedStateWait:Set[${This.InTenths[120]}]
					}
					return OB_NPC_MOVE
					}
				}
				else
				{
					if ${POI.SetNearestPOI[${Me.Class}_TRAINER]}
					{
						return OB_NPC_MOVE
					}
					else
					{
						This:Output[Not enough mapping data to CLASSTRAINER, aborting trainer run !]
						;no return here try other NPC
						POI.NeedClassTrainer:Set[FALSE]
					}
				}
			}


			;THIS IS A SOURCE OF ROAM LAG - ATTEMPTED REWRITE
			if !${POI.IgnoreSkinningTrainer} && ${Toon.HasSkill[SKILL_SKINNING]}
			{
				if (${Toon.SkillLevel[SKILL_SKINNING]}==${Toon.SkillMaxLevel[SKILL_SKINNING]}) && (${Toon.SkillLevel[SKILL_SKINNING]}<${Bot.SkillLvlCap})
				{
					if ${POI.Type.Equal["Skinning_TRAINER"]} && !${POI.IsBlacklisted}
					{
						if ${POI.InUseRange}
						{
							if ${This.VisibleFrame[ClassTrainerFrame]}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_TRAINER
							}
							else
							{
								if ${WoWScript[GetGossipOptions()](exists)}
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_MOREGOSSIP
								}
								else
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_USE_NPC
								}
							}
						}
						else
						{
							return OB_NPC_MOVE
						}
					}
					else
					{
						if !${POI.Type.Equal["FLIGHTMASTER"]}
						{
							if ${POI.SetNearestPOI["Skinning_TRAINER",${Math.Calc[1 + ${Toon.SkillLevel[SKILL_SKINNING]}]}]}
							{
								return OB_NPC_MOVE
							}
							else
							{
								This:Output[Not enough mapping data to Skinning Trainer that can train me, aborting trainer run !]
								POI.IgnoreSkinningTrainer:Set[TRUE]
								;no return here try other NPC
							}
						}
					}
				}
			}

			if !${POI.IgnoreHerbalismTrainer} && ${Toon.HasSkill[SKILL_HERBALISM]}
			{
				if (${Toon.SkillLevel[SKILL_HERBALISM]}==${Toon.SkillMaxLevel[SKILL_HERBALISM]}) && (${Toon.SkillLevel[SKILL_HERBALISM]}<${Bot.SkillLvlCap})
				{
					if ${POI.Type.Equal["Herbalism_TRAINER"]} && !${POI.IsBlacklisted}
					{
						if ${POI.InUseRange}
						{
							if ${This.VisibleFrame[ClassTrainerFrame]}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_TRAINER
							}
							else
							{
								if ${WoWScript[GetGossipOptions()](exists)}
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_MOREGOSSIP
								}
								else
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_USE_NPC
								}
							}
						}
						else
						{
							return OB_NPC_MOVE
						}
					}
					else
					{
						if !${POI.Type.Equal["FLIGHTMASTER"]}
						{
							if ${POI.SetNearestPOI["Herbalism_TRAINER",${Math.Calc[1 + ${Toon.SkillLevel[SKILL_HERBALISM]}]}]}
							{
								return OB_NPC_MOVE
							}
							else
							{
								This:Output[Not enough mapping data to Herbalism Trainer that can train me, aborting trainer run !]
								POI.IgnoreHerbalismTrainer:Set[TRUE]
								;no return here try other NPC
							}
						}
					}
				}
			}

			if !${POI.IgnoreMiningTrainer} && ${Toon.HasSkill[SKILL_MINING]}
			{
				if (${Toon.SkillLevel[SKILL_MINING]}==${Toon.SkillMaxLevel[SKILL_MINING]}) && (${Toon.SkillLevel[SKILL_MINING]}<${Bot.SkillLvlCap})
				{
					if ${POI.Type.Equal["Mining_TRAINER"]} && !${POI.IsBlacklisted}
					{
						if ${POI.InUseRange}
						{
							if ${This.VisibleFrame[ClassTrainerFrame]}
							{
								This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
								return OB_TRAINER
							}
							else
							{
								if ${WoWScript[GetGossipOptions()](exists)}
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_MOREGOSSIP
								}
								else
								{
									This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
									return OB_USE_NPC
								}
							}
						}
						else
						{
							return OB_NPC_MOVE
						}
					}
					else
					{
						if !${POI.Type.Equal["FLIGHTMASTER"]}
						{
							if ${POI.SetNearestPOI["Mining_TRAINER",${Math.Calc[1 + ${Toon.SkillLevel[SKILL_MINING]}]}]}
							{
								return OB_NPC_MOVE
							}
							else
							{
								This:Output[Not enough mapping data to Mining Trainer that can train me, aborting trainer run !]
								POI.IgnoreMiningTrainer:Set[TRUE]
								;no return here try other NPC
							}
						}
					}
				}
			}
		}
		return OB_IDLE
	}

	method NPCPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_NPC_GETTING_READY
			Toon:Standup
			if ${Movement.Speed}
			{
				Navigator:ClearPath
				move -stop
			}
			break

			case OB_RESTOCK
			variable iterator iter
			Inventory.RestockList:GetIterator[iter]
			iter:First

			This:Debug["RESTOCK?: ${Inventory.NeedRestock}"]
			if !${Inventory.NeedRestock} || !${POI.Name.Equal[${Inventory.${Inventory.NeedRestock[1]}Merch}]}
			{
				WoWScript CloseMerchant()
				This:Output["Done Restocking here."]
				POI:Clear
				POI.NeedRestock:Set[FALSE]
				break
			}
			while ${iter.IsValid}
			{
				This:Debug["MAX: ${iter.Value.Max} STACK: ${Inventory.StackCount[${iter.Key}]} DIS: ${iter.Value.Disabled}"]
				if ${iter.Value.Max} > ${Inventory.StackCount[${iter.Key}]} && !${iter.Value.Disabled}
				{
					if ${Inventory.BuyItem[${iter.Key}]}
					{
						This:Debug["Buying ${iter.Key}"]
						This.NPCState_NPC_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.NPCState_Interact_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
						break
					}
					elseif ${LNavGroup[${iter.Value.myType}].Contains[${POI.Name}]}
					{
						iter.Value.Disable:Set[TRUE]
					}
				}
				iter:Next
			}
			break


			case OB_HEARTH_GETTING_READY
			Toon:Standup
			if ${Movement.Speed}
			{
				Navigator:ClearPath
				move -stop
			}
			break

			case OB_START_HEARTH
			Item[Hearthstone]:Use
			break

			case OB_NPC_MOVE
			Human.StopOnFollow_Override:Set[${This.InSeconds[300]}]
			if ${Mount.NeedMount}
			{
				Grind.CurrentGrind.CurrentHotspot:Set[1]
				Mount:Mount
				return
			}
			if ${POI.Distance} <= ${Mount.DismountDistance} && ${Mount.IsMounted}
			{
				Mount:Dismount
			}
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_TAKE_FLIGHT
			This:Output["Taking Flightpath to ${FlightPlan.FlightNode[${FlightPlan.DestinationFM}]}"]
			if ${WoWScript[TaxiFrame:IsVisible()]}
			{
				if ${FlightPlan.NeedRefresh}
				{
					FlightPlan:Refresh
					FlightPlan.NeedRefresh:Set[FALSE]
					return
				}
				if ${FlightPlan.NeedFlight}
				{
					if ${FlightPlan.GetNodeSlot[${FlightPlan.DestinationFM}]} > 0
					{
						WoWScript TakeTaxiNode(${FlightPlan.GetNodeSlot[${FlightPlan.DestinationFM}]})
						FlightPlan.NeedFlight:Set[FALSE]
						FlightPlan.DestinationFM:Set[NULL]
						FlightPlan.LastFlight:Set[${LavishScript.RunningTime}]
						return
					}
				}
			}
			break

			case OB_LEARN_FLIGHT
			if ${WoWScript[TaxiFrame:IsVisible()]}
			{
				if ${FlightPlan.NeedRefresh}
				{
					FlightPlan:Refresh
					FlightPlan.NeedRefresh:Set[FALSE]
					FlightPlan.LearnFlightMaster:Set[FALSE]
					FlightPlan.LearnFM:Set["0:0:0:0:0:0:0:0"]
					return
				}
			}
			break

			case OB_USE_NPC
			Mount:Dismount
			Toon:Standup
			Navigator:ClearPath
			move -stop
			POI:Use
			break

			case OB_LOGOUT
			if ${UIElement[chkErrorSoundOn@Config@Pages@openbot].Checked}
			{
				This:PlaySound["Stop"]
			}
			This:Debug["OB_LOGOUT, Have a good day"]
			Navigator:ClearPath
			move -stop
			WoWScript Logout()
			endscript openbot
			break

			case OB_MOREGOSSIP
			;TODO: use event GOSSIP_SHOW and title1, gossip1 = GetGossipOptions()
			;see http://www.wowwiki.com/API_GetGossipOptions
			variable int gcheck=1
			variable int copt=0
			while ${WoWScript[GetGossipOptions(),${gcheck}](exists)}
			{
				;This:Output[${WoWScript[GetGossipOptions(),${gcheck}]}]
				if ${WoWScript[GetGossipOptions(),${gcheck}].NotEqual["binder"]} && ${WoWScript[GetGossipOptions(),${gcheck}].NotEqual["gossip"]}
				{
					copt:Inc
				}
				if ${WoWScript[GetGossipOptions(),${gcheck}].Find["browse your goods"]}!=NULL || ${WoWScript[GetGossipOptions(),${gcheck}].Find["have for sale"]}!=NULL
				{
					This:Output["Selecting: ${gcheck} ${WoWScript[GetGossipOptions(),${gcheck}]}"]
					WoWScript SelectGossipOption(${copt})
					break
				}
				gcheck:Inc
			}
			WoWScript SelectGossipOption(1)
			break

			case OB_REPAIR
			WoWScript RepairAllItems()
			POI.NeedRepair:Set[FALSE]
			if ${Object[${Inventory.GetSlot[Sell]}](exists)}
			{
				POI.NeedSell:Set[TRUE]
			}
			break

			case OB_SELL
			if ${Object[${Inventory.GetSlot[Sell]}](exists)}
			{
				Object[${Inventory.GetSlot[Sell]}]:Use
			}
			else
			{
				WoWScript CloseMerchant()
				This:Output["Done Selling."]
				POI.NeedSell:Set[FALSE]
				if ${Object[${Inventory.GetSlot[Mule]}](exists)} && ${Me.Coinage} >= 30
				{
					POI.NeedMailbox:Set[TRUE]
				}
			}
			break

			case OB_TRAINER
			WoWScript SetTrainerServiceTypeFilter("available",1)
			WoWScript SetTrainerServiceTypeFilter("unavailable",0)
			WoWScript SetTrainerServiceTypeFilter("used",0)

			if ${WoWScript[GetNumTrainerServices()]}>0
			{
				if ${WoWScript[GetTrainerServiceCost(${WoWScript[GetTrainerSelectionIndex()]})]} <= ${Me.Coinage}
				{
					WoWScript BuyTrainerService(${WoWScript[GetTrainerSelectionIndex()]})
				}
				else
				{
					if ${POI.Type.Equal[${Me.Class}_TRAINER]}
					{
						POI.NeedClassTrainer:Set[FALSE]
						This:Output[Not enough money for ${Me.Class} Trainer, skipping Training !]
					}
					if ${POI.Type.Equal["Skinning_TRAINER"]}
					{
						POI.IgnoreSkinningTrainer:Set[TRUE]
						This:Output[Not enough money for Skinning Trainer, skipping Training !]
					}
					if ${POI.Type.Equal["Herbalism_TRAINER"]}
					{
						POI.IgnoreHerbalismTrainer:Set[TRUE]
						This:Output[Not enough money for Herbalism Trainer, skipping Training !]
					}
					if ${POI.Type.Equal["Mining_TRAINER"]}
					{
						POI.IgnoreMiningTrainer:Set[TRUE]
						This:Output[Not enough money for Mining Trainer, skipping Training !]
					}
				}
			}
			else
			{
				if ${POI.Type.Equal[${Me.Class}_TRAINER]}
				{
					POI.NeedClassTrainer:Set[FALSE]
				}
			}
			break

			case OB_MULE
			/*
			MultiMail posted in #openbot Author cubed
			 */
			if ${Object[${Inventory.GetSlot[Mule,"-notsoulbound"]}](exists)} && ${Me.Coinage} >= 30
			{
				variable index:string ItemIndex
				variable int i = 1
				variable guidlist itemList
				itemList:Search[-items,-inventory,-notsoulbound]
				for(i:Set[1];${i} <= ${itemList.Count};i:Inc)
				{
					if ${Inventory.isItem[Mule,${itemList.Object[${i}].Name}]}
					{
						ItemIndex:Insert[${itemList.GUID[${i}]}]
					}
				}

				variable int inThisMail = 0
				while ${ItemIndex.Get[1](exists)}
				{
					for(i:Set[1];${i} <= 12;i:Inc)
					{
						Item[${ItemIndex.Get[1]}]:PickUp
						WoWScript ClickSendMailItemButton(${i})
						if ${ItemIndex.Get[1](exists)}
						{
							inThisMail:Inc
						}
						ItemIndex:Remove[1]
						ItemIndex:Collapse
					}

					if ${Me.Coinage} >= ${Math.Calc[${inThisMail} * 30]}
					{
						WoWScript SendMail(\"${UIElement[tenMuleChar@Config@InvPages@Inventory@Pages@OpenBot].Text}\"\, \"Multiple Items\"\, \"\")
						inThisMail:Set[0]
					}
					else
					{
						This:Output["Error: Not enough money to automule the desired items!"]
						POI.NeedMailbox:Set[FALSE]
						return
					}
				}
			}
			else
			{
				POI.NeedMailbox:Set[FALSE]
			}
			break

			case OB_TRADESKILL_MAKE
			Tradeskills:MakeTradeSkill
			break

			case OB_TRADESKILL_BUY
			Tradeskills:BuyTradeSkill
			break

			case OB_TRADESKILL_MOVE
			Tradeskills:NeedTradePOI
			break

			case OB_TRADESKILL_WAIT
			This:Debug[Waiting in Tradeskill]
			break
		}
	}

	;----------
	;----- ITEM Sub State
	;----------
	member ITEMState()
	{
		if ${Inventory.NeedStackMotes}
		{
			return OB_ITEM_MOTE
		}
		if ${Inventory.NeedDestroy}
		{
			return OB_ITEM_DESTROY
		}
		if ${Inventory.NeedOpen}
		{
			This:Echo["We Need to open something"]
			return OB_ITEM_OPEN
		}
		if ${LavishScript.RunningTime} <= ${This.ITEMState_Equip_Wait_Until}
		{
			return OB_EQUIP_WAIT
		}
		if ${Autoequip.DismissBindPopUp}
		{
			This.ITEMState_Equip_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.ITEMState_Equip_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_EQUIP_WAIT
		}
		if ${Autoequip.NeedEQ} && !${Me.Equip[16].Name.Equal["OB_FISHING_POLE"]}
		{
			if ${Autoequip.EquipGear}
			{
				This.ITEMState_Equip_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.ITEMState_Equip_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
				return OB_EQUIP_WAIT
			}
			elseif ${Autoequip.EquipBag}
			{
				This.ITEMState_Equip_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.ITEMState_Equip_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
				return OB_EQUIP_WAIT
			}
			else
			{
				Autoequip.NeedEQ:Set[FALSE]
			}
		}
		return OB_IDLE
	}

	method ITEMPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_ITEM_DESTROY
			Inventory:Destroy
			break
			case OB_ITEM_OPEN
			This:Echo["we are trying to open"]
			Inventory:Open
			break
			case OB_ITEM_MOTE
			Inventory:StackMotes
			break
			case OB_EQUIP_WAIT
			break
		}
	}


	;----------
	;----- QUEST Sub State
	;----
	member QUESTState()
	{
		/* wait between brief wait between quest states */
		if ${LavishScript.RunningTime} <= ${This.QUESTstate_Wait_Until}
		{
			return OB_QUEST_WAIT
		}
		/* if not waiting, do */
		if ${Questgiver.ChooseReward}
		{
			This.QUESTstate_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.QUESTstate_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_QUEST_REWARD
		}
		/* need questgiver */
		if ${Questgiver.SetQuestGiverPOI}
		{
			Questgiver:ClearMerchantFrames
			if ${POI.InUseRange}
			{
				if !${Questgiver.GossipVisible}
				{
					This.QUESTstate_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.QUESTstate_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
					return OB_QUEST_NEEDGOSSIP
				}
				if ${Questgiver.NeedGossip}
				{
					This.QUESTstate_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.QUESTstate_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
					return OB_QUEST_GOSSIP
				}
				return OB_QUEST_CLOSEGOSSIP
			}
			else
			{
				return OB_QUEST_NEEDNPC
			}
		}
		/* an item begins a quest */
		if ${Questgiver.ItemStartQuest}
		{
			This.QUESTstate_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.QUESTstate_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_ITEM_BEGINSQUEST
		}
		return OB_IDLE
	}


	method QUESTPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_QUEST_WAIT
			break
			case OB_QUEST_REWARD
			Questgiver:GetReward
			break

			case OB_QUEST_NEEDOBJECT
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break
			case OB_QUEST_HARVEST
			POI:Use
			break
			case OB_QUEST_NEEDGOSSIP
			Target ${POI.GUID}
			POI:Use
			break
			case OB_QUEST_GOSSIP
			Questgiver:GossipPulse
			break
			case OB_QUEST_CLOSEGOSSIP
			if ${WoWScript[QuestFrame:IsVisible()]}
			{
				WoWScript "QuestFrame:Hide()"
			}
			break
			case OB_QUEST_NEEDNPC
			Target ${POI.GUID}
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break
			case OB_ITEM_BEGINSQUEST
			Questgiver:BeginItemQuest
			break
		}
	}


	;----------
	;----- ROAM Sub State
	;----------
	member ROAMState()
	{
		if !${Me.Dead} && !${Me.Ghost} && ${Mount.NeedMount}
		{
			return OB_MOUNT
		}

		if !${Me.Dead} && !${Me.Ghost} && ${POI.Distance} <= ${Mount.DismountDistance} && ${Mount.IsMounted}
		{
			return OB_DISMOUNT
		}

		if ${Me.Level} != ${Toon.Level}
		{
			return OB_LEVELUP
		}
		if ${UIElement[chkEnableQuest@Quest@HumanPages@Human@Pages@openbot].Checked}
		{
			if ${Quest.Complete}
			{
				return OB_ROAM_COMPLETE
			}

			if ${Quest.HasEvent}
			{
				return OB_ROAM_EVENT
			}
		}

		/* conditionals for moving to mob should be defined in Toon.MoveToMob */
		if ${Toon.MoveToMob} && !${Mount.IsMounted}
		{
			if ${POI.Type.Equal[MOB]} && ${POI.GUID.Equal[${Targeting.TargetCollection.Get[1]}]}
			{
				return OB_MOVETO_MOB
			}
			elseif ${POI.Set[${Object[${Targeting.TargetCollection.Get[1]}].X}:${Object[${Targeting.TargetCollection.Get[1]}].Y}:${Object[${Targeting.TargetCollection.Get[1]}].Z}:${Object[${Targeting.TargetCollection.Get[1]}].GUID}:${Object[${Targeting.TargetCollection.Get[1]}].Name}:MOB:FACTION_NEUTRAL:${Object[${Targeting.TargetCollection.Get[1]}].Level},FALSE]}
			{
				return OB_MOVETO_MOB
			}
		}

		;REWRITTEN TO REDUCE ROAM LAG
		variable bool canMine = FALSE
		variable bool canHerb = FALSE
		if ${Toon.HasSkill[Herbalism]} || ${Toon.HasSkill[Mining]}
		{
			if ${Toon.HasSkill[Herbalism]} && ${UIElement[chkRoamHerb@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				canHerb:Set[TRUE]
			}

			if ${Item[-inventory,"Mining Pick"](exists)} && ${Toon.HasSkill[Mining]} && ${UIElement[chkRoamMine@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				canMine:Set[TRUE]
			}
			if ${canHerb} && ${canMine}
			{
				if ${POI.SetNearestPOI[MINING,1,${Toon.SkillLevel[Mining]}]}
				{
					;If there is a Herb Node Nearer or same Distance then we prefer to roam there
					if ${POI.SetNearestPOI[HERBALISM,1,${Toon.SkillLevel[Herbalism]},${POI.Distance}]}
					{
						return OB_ROAM_TO_NODE
					}
					return OB_ROAM_TO_NODE
				}
				else
				{
					if ${POI.SetNearestPOI[HERBALISM,1,${Toon.SkillLevel[Herbalism]}]}
					{
						return OB_ROAM_TO_NODE
					}
				}
			}
			elseif ${canMine}
			{
				if ${POI.SetNearestPOI[MINING,1,${Toon.SkillLevel[Mining]}]}
				{
					return OB_ROAM_TO_NODE
				}
			}
			elseif ${canHerb}
			{
				if ${POI.SetNearestPOI[HERBALISM,1,${Toon.SkillLevel[Herbalism]}]}
				{
					return OB_ROAM_TO_NODE
				}
			}
		}
		if ${UIElement[chkEnableQuest@Quest@HumanPages@Human@Pages@openbot].Checked}
		{
			if ${Quest.ChangeLocation}
			{
				This:Debug[Changing Location for Questing]
			}

			if ${Quest.Explore}
			{
				return OB_ROAM_EXPLORE
			}
		}

		if ${Grind.ChangeLocation}
		{
			This:Debug[Changing Location]
		}

		/* only attempt to set a hotspot poi if poi is not current hotspot*/
		if ${POI.Name.NotEqual[${Grind.HotSpotName}]} || (${POI.X} != ${Grind.X} || ${POI.Y} != ${Grind.Y} || ${POI.Z} != ${Grind.Z})
		{
			This:Debug["Setting POI to ${Grind.HotSpotName}"]
			if !${POI.Set[${Grind.X}:${Grind.Y}:${Grind.Z}:${Grind.HotSpotName}:${Grind.HotSpotName}:HOTSPOT:FACTION_NEUTRAL:0]}
			{
				if ${Config.GetCheckbox[chkTakeFMToGrind]}
				{
					if ${FlightPlan.FlyToPoint[${Grind.X},${Grind.Y},${Grind.Z}]}
					{
						if ${FlightPlan.SetFlightPOI}
						{
							return OB_ROAMING
						}
					}
				}
				/* if we loop 25 times within 2 minutes, location is bad */
				if ${This.Location_Failed_Count:Inc} > 25 && ${This.Location_Failed_Timer} > ${LavishScript.RunningTime}
				{
					if ${UIElement[chkErrorSoundOn@Config@Pages@openbot].Checked}
					{
						This:PlaySound["Stop"]
					}
					This:Output["ERROR: LOCATION FAILED. NO CONNECTIONS TO ANY HOTSPOT. FORCING LOCATION CHANGE"]
					Grind:LoadBestLocationSet[TRUE]
					This.Location_Failed_Count:Set[0]
					This.Location_Failed_Timer:Set[0]
					return OB_IDLE
				}
				if ${This.Location_Failed_Timer} < ${LavishScript.RunningTime}
				{
					This.Location_Failed_Timer:Set[${This.Location_Failed_Timer}+120000]
				}
				/* first try iterating through hotspots */
				This:Output["Error: Not enough mapping data to ${Grind.HotSpotName}. Iterating to Next Hotspot"]
				Grind:NextHotspot
				return OB_IDLE
			}
		}

		if ${POI.Type.Equal[HOTSPOT]} && ${POI.Name.Token[1,"@"].Upper.Equal[FISHING]}
		{
			if ${Script[OB_FISHING_EXTENSION](exists)} &&  (${Item[-inventory,"OB_FISHING_POLE"](exists)} || ${Me.Equip[16].Name.Equal["OB_FISHING_POLE"]})
			{
				if ${POI.Distance} <= ${Navigator.GetPercision}
				{
					This:Output[Reached Fishing Hotspot start OB_FISHING_EXTENSION now.]
					This.LOOTState_Loot_Fishing_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Fishing_Timeout} * ${Bot.GlobalCooldown})]}]
				}
			}
			else
			{
				This:Output[Need OB_FISHING_EXTENSION loaded and OB_FISHING_POLE in Inventory to Fish ! Skipping Fishing Hotspot.]
				This:NextHotspot
			}
		}

		/* dont check POI distance for iterating Grind unless POI is Hotspot */
		if ${POI.Type.Equal[HOTSPOT]} && ${POI.Distance} <= ${Math.Calc[${Navigator.GetPercision}+${POI.RandomDistanceModifier}]} && ${POI.Name.Token[1,"@"].Upper.NotEqual[FISHING]}
		{
			This:Output[Reached Current Hotspot. Random switch distance was: ${POI.Distance}]
			This:NextHotspot
		}
		if ${POI.Type.Equal[HOTSPOT]}
		{
		return OB_ROAMING
		}
	}

	method ROAMPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_MOUNT
			Mount:Mount
			break

			case OB_DISMOUNT
			Mount:Dismount
			break

			case OB_LEVELUP
			This:Output[Gratz we Leveled up! New Level is ${Me.Level}.]
			This:Output[Checking Profile and doing Trainer run.]
			Toon.Level:Set[${Me.Level}]
			Targeting:MinMaxLvLs
			Grind:LoadBestLocationSet[FALSE]
			if ${Math.Calc[${Me.Level}%4]} == 0
			{
				POI.NeedClassTrainer:Set[TRUE]
			}
			break

			case OB_MOVETO_MOB
			Mount:Dismount
			Toon:NeedTarget
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_ROAMING
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break
		}
	}

	method NextHotspot()
	{
		if ${Grind.RandomizeHotSpots}
		{
			Grind:RandomHotSpot
			This:Output[Next Random HotSpot is ${Grind.HotSpotName}.]
		}
		else
		{
			Grind:NextHotspot
			This:Output[Next HotSpot is ${Grind.HotSpotName}.]
		}
		POI.RandomDistanceModifier:Set[${Math.Rand[10]}]
		This:Output[Next Distance Modifier is: ${POI.RandomDistanceModifier}]
	}

	method EndFishing()
	{
		if !${Script[OB_FISHING_EXTENSION].Paused}
		{
			Script[OB_FISHING_EXTENSION]:Pause
		}
		if ${Me.Equip[16].Name.Equal["OB_FISHING_POLE"]}
		{
			if ${Item[-inventory,"${MainHandBeforeFishing}"](exists)}
			{
				Item[-inventory,"${MainHandBeforeFishing}"]:Use
				MainHandBeforeFishing:Set[NULL]
			}
			if ${Item[-inventory,"${OffHandBeforeFishing}"](exists)}
			{
				Item[-inventory,"${OffHandBeforeFishing}"]:Use
				MainHandBeforeFishing:Set[NULL]
			}
		}
	}

	method StartFishing()
	{
		Navigator:FaceHeading[${Grind.Hd}]
		if !${Me.Equip[16].Name.Equal["OB_FISHING_POLE"]}
		{
			MainHandBeforeFishing:Set[${Me.Equip[16].Name}]
			OffHandBeforeFishing:Set[${Me.Equip[17].Name}]
			Item[-inventory,"OB_FISHING_POLE"]:Use
		}
		if ${Script[OB_FISHING_EXTENSION].Paused}
		{
			Script[OB_FISHING_EXTENSION]:Resume
		}
	}

	; ------ ASSIST MODE
	member ASSISTState()
	{
		if ${State.NeedAssist[${Target.GUID}]}
		{
			if ${State.HaveAssistPath[${Target.GUID}]}
			{
				if ${Target.Distance} < ${Toon.PullRange}
				{
					if ${Class.NeedPullBuff}
					{
						return OB_PULL_BUFF
					}
					else
					{
						return OB_PULL
					}
				}
				else
				{
					return OB_MOVETO_MOB
				}
			}
			else
			{
				This:Output[Need Path to Mob.]
			}
		}
		return OB_ASSIST_IDLE
	}

	method ASSISTPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_PULL
			Class:PullPulse
			break

			case OB_PULL_BUFF
			Class:PullBuffPulse
			break

			case OB_ASSIST_IDLE
			POI.myobjectstring:Set["0:0:0:0:0:0:0:0:0"]
			Navigator:ClearPath
			break

			case OB_MOVETO_MOB
			Navigator:MoveToMob[${Target.GUID}]
			break
		}
	}

	member NeedAssist(string MobGUID)
	{
		variable objectref TargetMob
		TargetMob:Set[${MobGUID}]

		if ${Mount.IsMounted}
		{
			return FALSE
		}

		if !${TargetMob(exists)} || ${TargetMob.Name.Equal[NULL]}
		{
			return FALSE
		}

		if (${MobGUID.Equal[${Me.GUID}]} || ${TargetMob.Dead})
		{
			return FALSE
		}
		if !${TargetMob.Attackable}
		{
			return FALSE
		}
		return TRUE
	}

	member HaveAssistPath(string GUID)
	{
		variable float mobDistance
		variable objectref theMob = ${GUID}
		variable int moveDirectly = ${Toon.PullRange}

		mobDistance:Set[${Math.Distance[${Me.X},${Me.Y},${Me.Z},${theMob.X},${theMob.Y},${theMob.Z}]}]
		if ${moveDirectly} < 40
		{
			moveDirectly:Set[40]
		}
		if ${mobDistance} < ${moveDirectly} && !${Me.IsPathObstructed[${theMob.X},${theMob.Y},${Math.Calc[${theMob.Z}+0.6]}]}
		{
			return TRUE
		}
		elseif ${Navigator.AvailablePath[${theMob.X},${theMob.Y},${theMob.Z}]}
		{
			return TRUE
		}
		return FALSE
	}

	member LOOT_ASSISTState()
	{
		if (${State.NeedAssist[${Target.GUID}]} && ${State.HaveAssistPath[${Target.GUID}]}) || ${Mount.IsMounted}
		{
			return OB_IDLE
		}
		return ${This.LOOTState}
	}

	method LOOT_ASSISTPulse()
	{
		This:LOOTPulse
	}

	member ManualOverride()
	{
		if ${WoWScript[IsMouseButtonDown("LeftButton")]} && ${WoWScript[IsMouseButtonDown("RightButton")]}
		{
			return TRUE
		}
		return FALSE
	}


	; ------ PARTY MODE
	; This is where we hook our party stuff to the normal OB states or rewrite the state for Party Mode if needed

	/* when we are dead -- no mechanics change -- it's all about getting back to our body baybe */
	member DEAD_PARTYState()
	{
		return ${This.DEADState}
	}
	method DEAD_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
		}
		This:DEADPulse
	}

	/* major changes to how this operates -- most party decisions regarding combat are made in this state */
	/* the basic principle is that flags are set based on group member weights in Party:Update */
	/* in combat -- these updates occur every state pulse -- out of combat, the occur in periodic CPU saving pulses */
	variable int LastPartySwitch = 0
	member TOON_PARTYState()
	{
		variable objectref theMob
		variable bool IsLead = ${Party.IsPartyLeader}
		variable bool IsAlone = ${Party.Alone}
		variable bool FightBack = FALSE

		Autoequip:NeedOrGreed
		if ${LavishScript.RunningTime} <= ${This.TOONState_General_Wait_Until}
		{
			return OB_TOON_WAIT
		}

		if ${Flee.NeedToRun} && ${IsAlone}
		{
			return OB_FLEE
		}

		if ${Me.InCombat} || (!${Party.KillTarget.Equal[NULL]} && ${Object[${Party.KillTarget}].Target(exists)})
		{
			Party:Update
			if !${IsAlone}
			{
				FightBack:Set[TRUE]
			}
			elseif !${Mount.IsMounted}
			{
				FightBack:Set[TRUE]
			}
			if (${Party.NeedHeal} || ${Party.NeedCure}) && ${Me.PctHPs} > 35
			{
				/* we need to make sure I stay alive first */
				FightBack:Set[FALSE]
			}
			if ${Party.NeedCrowdControl}
			{
				FightBack:Set[FALSE]
			}
		}

		if ${FightBack}
		{
			if !${Party.KillTarget.Equal[NULL]} && ${Object[${Party.KillTarget}].PctHPs} > 0 && (!${Toon.ValidTarget[${Target.GUID}]} || ${Math.Calc[${LavishScript.RunningTime}-${This.LastPartySwitch}]} > 5000)
			{
				if ${POI.GUID.NotEqual[${Object[${Party.KillTarget}].GUID}]}
				{
					Target ${Party.KillTarget}
					This.LastPartySwitch:Set[${LavishScript.RunningTime}]

					if !${POI.Set[${Object[${Party.KillTarget}].X}:${Object[${Party.KillTarget}].Y}:${Object[${Party.KillTarget}].Z}:${Object[${Party.KillTarget}].GUID}:${Object[${Party.KillTarget}].Name}:MOB:FACTION_NEUTRAL:${Object[${Party.KillTarget}].Level},TRUE]}
					{
						This:Debug[Error: Can not set POI to Target]
					}
				}
			}
			elseif ${Toon.ValidTarget[${Target.GUID}]} && ${Target.PctHPs} > 0
			{
				if ${POI.GUID.NotEqual[${Target.GUID}]}
				{
					if !${POI.Set[${Target.X}:${Target.Y}:${Target.Z}:${Target.GUID}:${Target.Name}:MOB:FACTION_NEUTRAL:${Target.Level},TRUE]}
					{
						This:Debug[Error: Can not set POI to Target]
					}
				}
			}
			elseif ${Me.InCombat} && ${Toon.ValidTarget[${Targeting.TargetCollection.Get[1]}]} && ${Object[${Targeting.TargetCollection.Get[1]}].PctHPs} > 0
			{
				Toon:NeedTarget
				if !${POI.Set[${Object[${Targeting.TargetCollection.Get[1]}].X}:${Object[${Targeting.TargetCollection.Get[1]}].Y}:${Object[${Targeting.TargetCollection.Get[1]}].Z}:${Object[${Targeting.TargetCollection.Get[1]}].GUID}:${Object[${Targeting.TargetCollection.Get[1]}].Name}:MOB:FACTION_NEUTRAL:${Object[${Targeting.TargetCollection.Get[1]}].Level},TRUE]}
				{
					This:Debug[Error: Can not set POI to AGGRO Target]
					Toon:NeedTarget
				}
			}

			/* then if we have a target, lets do combat */
			if ${Target(exists)}
			{
				if ${Class.NeedCombatBuff}
				{
					return OB_COMBAT_BUFF
				}
				else
				{
					return OB_COMBAT
				}
			}
			else
			{
				/* we have no target, so lets idle */
				if ${Class.NeedCombatIdle}
				{
					return OB_COMBAT_CLASS_IDLE
				}
				return OB_COMBAT_IDLE
			}
		}

		if ${Party.NeedHeal}
		{
			return OB_PARTYHEAL
		}

		if ${Party.NeedCrowdControl}
		{
			return OB_CROWDCONTROL
		}

		if ${Party.NeedCure}
		{
			return OB_PARTYCURE
		}

		if ${Class.NeedRest}
		{
			return OB_REST
		}

		if ${Party.NeedRez}
		{
			return OB_PARTYREZ
		}

		if ${Class.NeedBuff}
		{
			if !${Mount.IsMounted} && 0 < ${Toon.SafeSpotRange}
			{
				return OB_BUFF
			}
		}

		if ${Party.NeedBuff} && !${Mount.IsMounted}
		{
			return OB_PARTYBUFF
		}

		if ${IsAlone} && !${Mount.IsMounted}
		{
			if ${This.PullMobExists[1]} && ${Toon.SafeSpotRange} < 0
			{
				theMob:Set[${Targeting.TargetCollection.Get[1]}]
			}
		}
		elseif !${Party.KillTarget.Equal[NULL]}
		{
			theMob:Set[${Party.KillTarget}]
		}
		elseif ${IsLead} && !${Mount.IsMounted}
		{
			if ${Toon.PullableTarget}
			{
				theMob:Set[${Targeting.TargetCollection.Get[1]}]
			}
		}

		if ${theMob.GUID(exists)}
		{
			if ${POI.Set[${theMob.X}:${theMob.Y}:${theMob.Z}:${theMob.GUID}:${theMob.Name}:MOB:FACTION_NEUTRAL:${theMob.Level},FALSE]}
			{
				if ${theMob.Distance} > ${Toon.PullRange} && !${Me.Casting}
				{
					return OB_MOVETO_PULL
				}
				else
				{
					if ${Class.NeedPullBuff}
					{
						return OB_PULL_BUFF
					}
					else
					{
						return OB_PULL
					}
				}
			}
			else
			{
				This:Output["Error: Can not set POI to PULL Target"]
			}
		}
		if ${Toon.Casting}
		{
			return OB_CASTING
		}
		if ${LavishScript.RunningTime} <= ${This.TOONState_Casting_Wait_Until}
		{
			return OB_CASTING_WAIT
		}
		if ${LavishScript.RunningTime} <= ${This.TOONState_Flee_Wait_Until} || ${Math.Calc[${LavishScript.RunningTime}-${This.TOONState_Last_Flee_Time}]} < 1500
		{
			return OB_FLEE_WAIT
		}
		return OB_IDLE
	}

	/* just hooking the ones that are different */
	method TOON_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_PARTYHEAL
			Mount:Dismount
			Target ${Group.Member[${Party.HealUnit}].GUID}
			if !${Party.InRange[${Party.HealUnit},25]}
			{
				This:Output[HealUnit -- Moving within 25 yards.]
				Party:NavToUnit[${Party.HealUnit}]
				break
			}
			This:Output[Party Heal - ${Group.Member[${Party.HealUnit}].Name}]
			Toon:Stop
			Class:PartyHealPulse
			break
			case OB_PARTYCURE
			Mount:Dismount
			Target ${Group.Member[${Party.CureUnit}].GUID}
			if !${Party.InRange[${Party.CureUnit},25]}
			{
				This:Output[CureUnit -- Moving within 25 yards.]
				Party:NavToUnit[${Party.CureUnit}]
				break
			}
			This:Output[Party Cure - ${Group.Member[${Party.CureUnit}].Name}]
			Toon:Stop
			Class:PartyCurePulse
			break
			case OB_PARTYREZ
			Mount:Dismount
			Target ${Group.Member[${Party.RezUnit}].GUID}
			if !${Party.InRange[${Party.RezUnit},25]}
			{
				This:Output[RezUnit -- Moving within 25 yards.]
				Party:NavToUnit[${Party.RezUnit}]
				break
			}
			This:Output[Party Rez - ${Group.Member[${Party.RezUnit}].Name}]
			Toon:Stop
			Class:PartyRezPulse
			break
			case OB_PARTYBUFF
			Mount:Dismount
			Target ${Group.Member[${Party.BuffUnit}].GUID}
			if !${Party.InRange[${Party.BuffUnit},25]}
			{
				This:Output[BuffUnit -- Moving within 25 yards.]
				Party:NavToUnit[${Party.BuffUnit}]
				break
			}
			This:Output[Party Buff - ${Group.Member[${Party.BuffUnit}].Name}]
			Toon:Stop
			Class:PartyBuffPulse
			break
			case OB_CROWDCONTROL
			Mount:Dismount
			Target ${Party.CrowdControl}
			if ${Math.Distance[${Me.Location},${Object[${Party.CrowdControl}].Location}]} > 25
			{
				This:Output[Crowd Control -- Moving within 25 yards.]
				Navigator:MoveToMob[${Party.CrowdControl}]
				break
			}
			This:Output[Crowd Control  - ${Object[${Party.CrowdControl}].Name}]
			Toon:Stop
			Class:CrowdControlPulse
			break
			case OB_MOVETO_PULL
			Mount:Dismount
			Party:NeedTarget
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break
			case OB_PULL
			Navigator:ClearPath
			Party:NeedTarget
			Class:PullPulse
			break
		}
		This:TOONPulse
	}

	/* mechanics of NPC remain unchanged -- decision to visit NPC is toon specific rather than party specific */
	/* this means the party member will go repair and then come back to group in ROAM */
	member NPC_PARTYState()
	{
		return ${This.NPCState}
	}
	method NPC_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
		}
		This:NPCPulse
	}

	/* mechanics of autoequip and such remain unchanged */
	member ITEM_PARTYState()
	{
		return ${This.ITEMState}
	}
	member method ITEM_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
		}
		This:ITEMPulse
	}

	/* the same old loot stuff with a couple of extra checks against my party members POI */
	/* includes a broadcast using Uplink of POI when you are preparing to loot to ensure POI is current */
	/* uses Party.IgnoreLoot -- the intent is to prevent two party members from going after the same loot */
	member LOOT_PARTYState()
	{
		variable guidlist list
		variable int Index
		variable bool Found = FALSE
		variable int bltimer

		Autoequip:NeedOrGreed

		if ${Me(unit).Casting.Name.Token[1," "].Equal[Skinning]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_SKIN_CORPSE
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Herbalism]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_LOOT_HERB
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Mining]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_LOOT_ORE
		}
		if ${Me(unit).Casting.Name.Token[1," "].Equal[Opening]}
		{
			This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
			return OB_OPENING
		}

		if ${LavishScript.RunningTime} <= ${This.LOOTState_Loot_Wait_Until}
		{
			return OB_LOOT_WAIT
		}

		if ${LootWindow(exists)}
		{
			if ${LootWindow.Count} > 0 && (${Inventory.FreeSlots} > 0)
			{
				This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_After_Until_Timeout} * ${Bot.GlobalCooldown})]}]
				This.LOOTState_Skip_Scans:Set[0]
				return OB_LOOTALL
			}
			else
			{
				This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_After_Until_Timeout} * ${Bot.GlobalCooldown})]}]
				This.LOOTState_Skip_Scans:Set[0]
				return OB_CLOSE_LOOT
			}
		}

		if ${LavishScript.RunningTime} >= ${LOOTState_Skip_Scans}
		{
			This.LOOTState_Skip_Scans:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Skip_Scans_Timeout} * ${Bot.GlobalCooldown})]}]
			 if (${Inventory.FreeSlots} > 0) && ${UIElement[chkLoot@Config@InvPages@Inventory@Pages@openbot].Checked}
         		{
            			list:Clear
            			list:Search[-units,-dead,-nearest]
            			Index:Set[0]
				if ${list.Count} > 0
				{
					while ${list.GUID[${Index:Inc}](exists)} && !${Found}
					{
						if ${Unit[${list.GUID[${Index}]}].Lootable}
						{
							if ${POI.Set[${Unit[${list.GUID[${Index}]}].X}:${Unit[${list.GUID[${Index}]}].Y}:${Unit[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Unit[${list.GUID[${Index}]}].Name}:LOOT:FACTION_NEUTRAL:${Unit[${list.GUID[${Index}]}].Level}]}
							{
								Found:Set[TRUE]
							}
						}
						if ${Unit[${list.GUID[${Index}]}].Skinnable}
						{
							if ${Toon.CanSkinMob[${list.GUID[${Index}]}]}
							{
								if ${POI.Set[${Unit[${list.GUID[${Index}]}].X}:${Unit[${list.GUID[${Index}]}].Y}:${Unit[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Unit[${list.GUID[${Index}]}].Name}:SKILL_SKINNING:FACTION_NEUTRAL:${Unit[${list.GUID[${Index}]}].Level}]}
								{
									Found:Set[TRUE]
								}
							}
						}
					}
				}
			}
			if !${Found} && ${Toon.HasSkill[SKILL_HERBALISM]} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkGather@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects,-herb,-usable,-unlocked,-nearest]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${Toon.SkillLevel[Herbalism]} >= ${OBDB.GetLevel[${Object[${list.GUID[${Index}]}].Name}]}
					{
						if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:SKILL_HERBALISM:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
						{
							Found:Set[TRUE]
						}
					}
					else
					{
						This:Output[do Not want ${Object[${list.GUID[${Index}]}].Name} level to high.]
					}
				}
			}
			if !${Found} && ${Toon.HasSkill[SKILL_MINING]} && ${Item[-inventory,"Mining Pick"](exists)} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkGather@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects,-mine,-usable,-unlocked,-nearest]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${Toon.SkillLevel[Mining]} >= ${OBDB.GetLevel[${Object[${list.GUID[${Index}]}].Name}]}
					{
						if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:SKILL_MINING:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
						{
							Found:Set[TRUE]
						}
					}
					else
					{
						This:Output[do Not want ${Object[${list.GUID[${Index}]}].Name} level to high.]
					}
				}
			}
			/* quest objects */
			if !${Found} && (${Inventory.FreeSlots} > 0) && ${UIElement[chkHarvestQuests@Config@InvPages@Inventory@Pages@openbot].Checked}
			{
				list:Clear
				list:Search[-gameobjects, -nearest, -chest, -unlocked, -usable]
				Index:Set[0]
				while ${list.GUID[${Index:Inc}](exists)} && !${Found}
				{
					if ${POI.Set[${Object[${list.GUID[${Index}]}].X}:${Object[${list.GUID[${Index}]}].Y}:${Object[${list.GUID[${Index}]}].Z}:${list.GUID[${Index}]}:${Object[${list.GUID[${Index}]}].Name}:QUESTOBJECT:FACTION_NEUTRAL:${Object[${list.GUID[${Index}]}].Level}]}
					{
						Found:Set[TRUE]
					}
				}
			}
		}

		if ${POI.Type.Equal[LOOT]} || ${POI.Type.Equal[Skinning]}
		{
			/*
			if ${Party.IgnoreLoot[${POI.GUID}]}
			{
				This:Output["Party Looted: Skipping ${POI.Type} for ${POI.Name}"]
				POI:Clear
				WoWScript ClearTarget()
				This.LOOTState_Skip_Scans:Set[0]
				return OB_LOOT_WAIT
			}
			else
			{
			*/
				if ${POI.IsBlacklisted} || !${Object[${POI.GUID}](exists)}
				{
					POI:Clear
					This.LOOTState_Skip_Scans:Set[0]
					return OB_LOOT_WAIT
				}
				else
				{
					if ${POI.InUseRange}
					{
						if (${POI.Type.Equal[LOOT]} && !${Unit[${POI.GUID}].CanLoot})
						{
							POI:Clear
							This.LOOTState_Skip_Scans:Set[0]
							return OB_LOOT_WAIT
						}
						if ${Movement.Speed} || ${Toon.Sitting}
						{
							return OB_LOOT_GETTING_READY
						}
						else
						{
							Party.Uplink:Broadcast[POI,${POI.Type}]
							This.LOOTState_Loot_Wait_Until:Set[${Math.Calc[${LavishScript.RunningTime}+(${This.LOOTState_Loot_Wait_Until_Timeout} * ${Bot.GlobalCooldown})]}]
							return OB_USE_LOOT
						}
					}
					else
					{
						Party.Uplink:Broadcast[POI,${POI.Type}]
						return OB_LOOT_MOVE
					}
				}
			/*
			}
			*/
		}
		return OB_IDLE
	}

	/* the mechanics of looting dont change -- so just hook existing */
	method LOOT_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
		}
		This:LOOTPulse
	}

	/* quest mechanics don't change */
	member QUEST_PARTYState()
	{
		return ${This.QUESTState}
	}
	method QUEST_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
		}
		This:QUESTPulse
	}

	/* if you are the party leader -- roam is pretty much like normal */
	/* if you are not the party leader, your POI is the party leader or his destination in ROAM */
	/* combat, rez and buff decisions are all handled in Toon at a higher priority over Looting, etc. */
	member ROAM_PARTYState()
	{
		if !${Me.Dead} && !${Me.Ghost} && ${Mount.NeedMount}
		{
			return OB_MOUNT
		}

		if !${Me.Dead} && !${Me.Ghost} && ${POI.Distance} <= ${Mount.DismountDistance} && ${Mount.IsMounted}
		{
			return OB_DISMOUNT
		}

		if ${Me.Level} != ${Toon.Level}
		{
			return OB_LEVELUP
		}

		if ${Party.NeedRest}
		{
			return OB_PARTY_IDLE
		}

		/* anyone who is not the leader needs to follow around -- all combat decisions are now made in TOON */
		if  !${WoWScript[IsPartyLeader()]}
		{
			if ${POI.Type.Equal[GROUP]} && !${Party.InRange[${WoWScript[GetPartyLeaderIndex()]},50]}
			{
				return OB_FOLLOW_LEADER
			}
			if ${Party.InRange[${WoWScript[GetPartyLeaderIndex()]},50]}
			{
				return OB_FOLLOW_LEADER
			}
			if ${Party.SetPOI_ToUnit[${WoWScript[GetPartyLeaderIndex()]}]}
			{
				return OB_FOLLOW_LEADER
			}
			if ${Party.SetPOI_ToDestination[${WoWScript[GetPartyLeaderIndex()]}]}
			{
				return OB_FOLLOW_LEADER
			}
			return OB_PARTY_IDLE
		}
		return ${This.ROAMState}
	}

	method ROAM_PARTYPulse()
	{
		switch ${This.CurrentSubState}
		{
			case OB_FOLLOW_LEADER
			{
				if ${Mount.NeedMount}
				{
					Grind.CurrentGrind.CurrentHotspot:Set[1]
					Mount:Mount
					return
				}
				if ${POI.Distance} <= ${Mount.DismountDistance} && ${Mount.IsMounted}
				{
					Mount:Dismount
				}
				if ${POI.Distance} < ${Navigator.GetPercision}
				{
					POI.myobjectstring:Set["0:0:0:0:0:0:0:0:0"]
					POI.Current:Set[${This.myobjectstring.Token[4,:]}]
					Navigator:ClearPath
					Toon:Stop
					return
				}
				if ${Party.InRange[${WoWScript[GetPartyLeaderIndex()]},12]}
				{
					Toon:Stop
					return
				}
				if ${Party.InRange[${WoWScript[GetPartyLeaderIndex()]},50]}
				{
					Party:NavToUnit[${WoWScript[GetPartyLeaderIndex()]}]
					return
				}
				if !${Navigator.IsMovingToCurrentPOI}
				{
					Navigator:MoveToCurrentPOI
					return
				}
			}
			case OB_PARTY_IDLE
			{
				if !${Party.NeedRest}
				{
					This:Output["Cant find a connection to Leader or Destination"]
				}
				else
				{
					This:Output["Waiting on resting party member."]
				}
				return
			}
		}
		This:ROAMPulse
	}


	; ------ BG MODE

	member BGState()
	{
		if ${BG.BGMode}
		{
			if ${BG.isINBG}
			{
				if ${BG.ShouldLeaveBG} || ${BG.BGOver}
				{
					return OB_LEAVEBG
				}

				if ${BG.GatesCheck}
				{
					; In Battleground and gates are open
					; Time to Fight
					if ${BG.NeedBGPulse}
					{
						return OB_INBG
					}
					else
					{
						; Most of the Time we want to use the roam Pulse
						return ${This.BG_ROAMState}
					}
				}

				; Were in a BG But Gates are not Open
				; O well Check for Prep Buffing and stuff
				if ${Class.HookBGPrebuff}
				{
					if ${Class.NeedBGPrebuff}
					{
						return OB_BGPREBUFF
					}
				}

				; Standard Wait for Start
				return OB_BGWAITSTART
			}

			if ${BG.NeedQue}
			{
				; Need to Queue
				return OB_BGNEEDQUEUE
			}

			; We arent in a BG and were are not queued. Must be waiting
			return OB_BGWAITINGQ
		}
		else
		{
			return OB_IDLE
		}
	}
	member BG_ROAMState()
	{
		variable bool	tmpGaurding		= ${BG.Gaurding}
		BG.Gaurding:Set[FALSE]

		if !${Me.Dead} && !${Me.Ghost} && ${Mount.NeedMount}
		{
			return OB_MOUNT
		}

		if !${Me.Dead} && !${Me.Ghost} && ${POI.Distance} <= ${Mount.DismountDistance} && ${Mount.IsMounted}
		{
			Mount:Dismount
		}
		/* conditionals for moving to mob should be defined in Toon.MoveToMob */
		if ${Toon.MoveToMob}
		{
			if ${POI.Type.Equal[MOB]} && ${POI.GUID.Equal[${Targeting.TargetCollection.Get[1]}]}
			{
				return OB_MOVETO_MOB
			}
			elseif ${POI.Set[${Object[${Targeting.TargetCollection.Get[1]}].X}:${Object[${Targeting.TargetCollection.Get[1]}].Y}:${Object[${Targeting.TargetCollection.Get[1]}].Z}:${Object[${Targeting.TargetCollection.Get[1]}].GUID}:${Object[${Targeting.TargetCollection.Get[1]}].Name}:MOB:FACTION_NEUTRAL:${Object[${Targeting.TargetCollection.Get[1]}].Level},FALSE]}
			{
				return OB_MOVETO_MOB
			}
		}

		/* only attempt to set a hotspot poi if poi is not current hotspot*/
		if ${POI.Name.NotEqual[${Grind.HotSpotName}]} || (${POI.X} != ${Grind.X} || ${POI.Y} != ${Grind.Y} || ${POI.Z} != ${Grind.Z})
		{
			This:Debug["Setting POI to ${Grind.HotSpotName}"]
			if !${POI.Set[${Grind.X}:${Grind.Y}:${Grind.Z}:${Grind.HotSpotName}:${Grind.HotSpotName}:HOTSPOT:FACTION_NEUTRAL:0]}
			{
				/* if we loop 25 times within 2 minutes, location is bad */
				if ${This.Location_Failed_Count:Inc} > 25 && ${This.Location_Failed_Timer} > ${LavishScript.RunningTime}
				{
					if ${UIElement[chkErrorSoundOn@Config@Pages@openbot].Checked}
					{
						This:PlaySound["Stop"]
					}
					This:Output["ERROR: LOCATION FAILED. NO CONNECTIONS TO ANY HOTSPOT. GAURDING"]
					This.Location_Failed_Count:Set[0]
					This.Location_Failed_Timer:Set[0]
					; Go back to being idle for now until we get a workaround
					;return OB_BG_STUCK
					return OB_IDLE
				}
				if ${This.Location_Failed_Timer} < ${LavishScript.RunningTime}
				{
					This.Location_Failed_Timer:Set[${This.Location_Failed_Timer}+120000]
				}
				/* first try iterating through hotspots */
				This:Output["Error: Not enough mapping data to ${Grind.HotSpotName}. FOOL. MAP MORE"]
				BG:MissingMapData

				return OB_ROAMING
			}
		}

		/* dont check POI distance for iterating Grind unless POI is Hotspot */
		if ${POI.Type.Equal[HOTSPOT]} && ${POI.Distance} <= ${Math.Calc[${Navigator.GetPercision}+${POI.RandomDistanceModifier}]} && ${POI.Name.Token[1,"@"].Upper.NotEqual[FISHING]}
		{
			BG.Guarding:Set[TRUE]
			; Set Gaurd here
			if ${tmpGaurding}
			{
				This:Output[Reached Current Hotspot. Gaurding]
			}
			if ${Class.HookBGGuard}
			{
				if ${Class.NeedBGGuard}
				{
					return OB_BG_CLASSGUARD
				}
			}
			return OB_BG_GAURDING
		}
		return OB_ROAMING
	}
	method BGPulse()
	{
		; Update our Very Powerfull Gui <-- HA!
		BG:UpdateGUI

		; Check if were leader. Dont want to be
		BG:ChkBGLeader

		; Check if we can join a higher priority BG while in another
		BG:CanJoinNextBG

		switch ${This.CurrentSubState}
		{
			case OB_LEAVEBG
			BG:LeaveBG
			break

			case OB_INBG
			BG:InBGPulse
			break

			case OB_BGNEEDQUEUE
			if !${Navigator.IsMovingToCurrentPOI}
			{
				BG:JoinBG
			}
			break

			case OB_BGPREBUFF
			Class:BGPrebuffPulse
			break

			case OB_BGWAITINGQ
			BG:QueueWait
			break

			case OB_BGWAITSTART
			BG:IdleTime
			break

			case OB_MOUNT
			Mount:Mount
			break

			case OB_MOVETO_MOB
			Mount:Dismount
			Toon:NeedTarget
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_ROAMING
			if !${Navigator.IsMovingToCurrentPOI}
			{
				Navigator:MoveToCurrentPOI
			}
			break

			case OB_BG_GAURDING
			BG:BGGaurd
			break

			case OB_BG_STUCK

			break

			case OB_BG_CLASSGUARD
			Class:BGGuardPulse
			break
		}
		return
	}
}