Question OLD macro for botting

Fridgecritter

Premium Member
Joined
May 14, 2011
Messages
49
Reaction score
6
Points
8
This is an old macro (about 6 years old I think) used only on emulators where warping is allowed, that lets you warp to a target, attack it, do a couple of keypresses (keypress 6 is summon bots and bot attack), loots the corpse based on a wildcard, so you can just put "ornate" as one of the wildcards and it will loot everything with the word ornate in it. There's also a timer in it that waits so many seconds if a kill is taking too long, and moves on to the next mob, and there's avoid mobs (notvalid) as well as named.

I was wondering if anyone would be able to take a look at it and clean it up. It gets stuck every now and then and tries to loot a corpse that isn't there. I get the message "You must first target a corpse to loot" over and over spammed and it won't move on. When I catch it, I can just start the macro over again and it does fine for a bunch more kills.

I'm hoping to learn in the process, so the changes you make if you could say why you did it so I can compare, I would be eternally grateful. I want to learn more not just have it done for me.

Code:
sub main
	/declare longKill timer
	/declare lootTimeOut timer
	/declare curZone string
	/declare notValid string
|	/declare named string
	/declare altCurrency string
	/declare lootItems string
	/declare lootWildcard1 string
	/declare lootWildcard2 string
	/declare lootWildcard3 string
	/declare lootWildcard4 string
	/declare lootWildcard5 string
	/declare lootWildcard6 string
	/declare lootWildcard7 string
	/declare lootWildcard8 string
	/declare lootWildcard9 string
	/declare lootWildcard10 string
	/declare lootWildcard11 string
	/declare lootWildcard12 string
	/declare lootWildcard13 string
	/declare lootName string
	/declare lootCount int
	/declare minLootValue int
	/declare npcID int
	/declare i int
	/declare ii int

	/declare noloot int
	
	/varset minLootValue 150

	/varset altCurrency /Ebon Crystal/Dream Mote/

	/varset lootItems /Diamond/Blue Diamond/Jacinth/Fire Opal/

	/varset lootWildcard1 ornate
	/varset lootWildcard2 item2
	/varset lootWildcard3 item3
	/varset lootWildcard4 item4
	/varset lootWildcard5 item5
	/varset lootWildcard6 item6
	/varset lootWildcard7 item7
	/varset lootWildcard8 item8
	/varset lootWildcard9 item9
	/varset lootWildcard10 item10
	/varset lootWildcard11 item11
	/varset lootWildcard12 item12
	/varset lootWildcard13 item13
	
	/varset notValid /NPCname1/NPCname2/

|	/varset named /NPCname1/NPCname2/

	/varset curZone ${Zone}

	/call doHideCorpses

	:WaitForRespawns

	/if (${SpawnCount[npc]}>0) {
		:NextSpawn

		/if (!${String[${Zone}].Equal[${curZone}]}) /return

		/for i 1 to ${SpawnCount}
			/vardata npcID NearestSpawn[${i}].ID

			/if ((${npcID}!=${Me.ID}) && (${Spawn[${npcID}].Type.Equal[NPC]})) {
				/if ((${notValid.Find[/${Spawn[${npcID}].CleanName}/]}==NULL) && (${Spawn[${npcID}].CleanName.Length}>0)) {
					/target id ${npcID}

					/if (!${longKill}) {
						/call warpTarget 0
					} else {
						/call warpTarget 1
					}

					:Retarget

					/target clear
					/delay 5
					/target id ${npcID}
					/delay 1s ${Target.Distance}<10
					/stick 7 moveback
					/delay 3
					/keypress 6
					/keypress 6
					/delay 3
					/attack on

					/varset longKill 60s

					:WaitForDead

					/face fast nolook

					/doevents

					/if (${String[${Me.Class}].Equal[Rogue]}) {
						/if (${Me.AbilityReady[Backstab]}) /doability Backstab
						/if (${String[${Me.Song[Thief's Eyes]}].Equal[NULL]}) /doability "Thief's Eyes"
					}
					
					/if (${String[${Me.Class}].Equal[Druid]}) {
						/casting "Galatine"
						/delay 4
					}
					
					/if (${String[${Me.Class}].Equal[Warrior]}) {
						/if (${Window[CombatAbilityWnd].Open}) {
							/if (${Window[CombatAbilityWnd].Child[CAW_CombatEffectLabel].Text.Equal[No Effect]}) /casting "Blade of Hatred"
						}
					}

|					/if ((${Target.Type.Equal[CORPSE]}) || (!${longKill})) /target clear
					/if (!${longKill}) /goto :Retarget
					/if (${Target.Distance}>50) /call warpTarget 0

|					/if (${Target.ID}==${npcID}) /goto :WaitForDead

					:NearbyCorpseFound

/if (!${noloot}) {
					/if (${Spawn[${npcID}].Type.Equal[CORPSE]}) {
						/if (!${Me.FreeInventory}) {
							/beep
						} else {
							/target id ${npcID}
							/call warpTarget 0
							/delay 2s ${Target.Distance}<10

							/if (${Target.Distance}<10) {
								/varset lootTimeOut 5s
								
								/delay 2
								/loot

								:WaitForLootWndOpen
								/delay 5
								/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) :NextSpawn
								/delay 1s ${Window[LootWnd].Open}
								/loot
								/if (!${Window[LootWnd].Open}) /goto :WaitForLootWndOpen

								/vardata lootCount Corpse.Items

								/if (${lootCount}) {
									/for ii 1 to ${lootCount}
										/if (!${Me.FreeInventory}) /goto :DoneLooting

										/if (${Corpse.Item[${ii}].ID}) {
											/varset lootName ${Corpse.Item[${ii}].Name}

											/if (${altCurrency.Find[/${lootName}/]}) {
												/call lootItem ${ii}
												/call reclaimCurrency ${lootName}
											} else {
												/if ((${Corpse.Item[${ii}].Name.Find[${lootWildcard1}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard2}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard3}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard4}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard5}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard6}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard7}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard8}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard9}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard10}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard11}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard12}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard13}]} || ... || ${lootItems.Find[/${lootName}/]} || ${Corpse.Item[${ii}].Value}>${Math.Calc[${minLootValue}*1000]}) && (!${Corpse.Item[${ii}].Lore} || !${FindItem[${Corpse.Item[${ii}].Name}].ID})) {
													/call lootItem ${ii}
												}
											}
											
											/if (${lootName.Find[EPIC]}) {
												/call lootItem ${ii}
											}
										}
									/next ii
								}

								:DoneLooting

								/notify LootWnd DoneButton leftmouseup

								:WaitForLootWndClose
								/delay 5
								/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) :NextSpawn
								/if (${Window[LootWnd].Open}) /goto :WaitForLootWndClose

								/if (${NearestSpawn[corpse].LineOfSight}) {
									/vardata npcID NearestSpawn[corpse].ID
									/goto :NearbyCorpseFound
								}
							}
						}
					} else {
						/if (!${String[${Spawn[${npcID}].ID}].Equal[NULL]}) /goto :WaitForDead
					}
}
						/if (!${String[${Spawn[${npcID}].ID}].Equal[NULL]}) /goto :WaitForDead
					/goto :NextSpawn
				}
			}
		/next i
	}

	/delay 5s

	/goto :WaitForRespawns
/return


sub doHideCorpses
	/hidec all
	/hidec looted
	/delay 5
/return

sub warpTarget(boolWithDistance)
	/if (${boolWithDistance}) {
		/warp loc ${Math.Calc[${Target.Y}-2]} ${Math.Calc[${Target.X}-2]} ${Target.Z}
	} else {
		/warp target
	}
/return

sub reclaimCurrency(strCurrencyName)
	/declare itemIndex int local
	/declare itemTotal int local

	/if (${Window[IW_AltCurrPage].Open}) {
		/varset itemIndex ${Window[IW_AltCurrPage].Child[IW_AltCurr_PointList].List[=${strCurrencyName},2]}

		/if (${itemIndex}) {
			/notify IW_AltCurrPage IW_AltCurr_PointList listselect ${itemIndex}
			/notify IW_AltCurrPage IW_AltCurr_ReclaimButton leftmouseup
			/delay 5
		}
	}
/return

sub lootItem(intLootSlot)
	/shift /itemnotify loot${intLootSlot} rightmouseup

	:WaitLootItem
	/delay 5
	/if (${Corpse.Item[${intLootSlot}].ID}) /goto :WaitLootItem
/return


sub Event_Backstab(strText, strMobName, strDamage)	
	/declare formattedDamage string local
	
	|/if (${Group.Members}==NULL) /return
	
	/if (!${strDamage}==NULL) {
		/if (${strDamage}>500000) {
			|/popup ${strDamage}
			/if (${strDamage}<1000000) {
				/varset formattedDamage ${String[${strDamage}].Left[3]},${String[${strDamage}].Right[3]}
			} else {
				/varset formattedDamage ${String[${strDamage}].Left[4]},${String[${strDamage}].Right[3]}
				/varset formattedDamage ${String[${formattedDamage}].Left[1]},${String[${formattedDamage}].Right[7]}
			}
			/guildsay Backstab (${strMobName}) for ${formattedDamage} points of damage.
		}
	}
/return
 
I would line out the loot process and go with /advloot. So much easier and you can load up on empty bags and have it loot all or set up special items to keep.
 
oh I see you don't have advance loot on those servers.
 
I was wondering if anyone would be able to take a look at it and clean it up. It gets stuck every now and then and tries to loot a corpse that isn't there. I get the message "You must first target a corpse to loot" over and over spammed and it won't move on.


There's some issues with a /goto command I'm thinking, though I can't be sure. I feel like that's the issue. You have

Code:
/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) :NextSpawn

in two spots in the looting process. :NextSpawn is a tag, /goto :NextSpawn is saying to go to the tag. I'm not entirely sure exactly how these work when there are multiple copies of the same tag present in a single sub, but I would think it would backtrack from your current location in the sub in reverse to find the tag in the sub.....though It may start from the top of the sub and do it that way.

The issue here is that the if statement isn't entirely valid. It should be doing a /goto :NextSpawn instead of just :NextSpawn. You will find at the end it has

Code:
/if (!${String[${Spawn[${npcID}].ID}].Equal[NULL]}) /goto :WaitForDead
					/goto :NextSpawn

which is called EVERY TIME it gets to that portion of the sub assuming t's finding an NPC to kill. The reason the macro corrects when you rerun the macro is because that mob is removed from the list of valid spawns to kill...because it's a corpse and because a call to hide corpses is done at the start of the macro.

I think the main issue is the :NextSpawn tag being used in multiple places. There should never be more than one tag and any number of /goto commands for that tag, but never the other way around as it can confuse the macro parser.

Code:
/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) /goto :NextSpawn

would be likely what you need to replace that with, adding the command /goto to the front of those two :NextSpawn tags which would make it only have a single tag, with multiple goto's.

That should be your fix.

Code:
:WaitForLootWndOpen
									/delay 5
									/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) /goto :NextSpawn
									/delay 1s ${Window[LootWnd].Open}
									/loot
									/if (!${Window[LootWnd].Open}) /goto :WaitForLootWndOpen

Specifically for this section would be my guess (I've corrected it in this chunk) The reason is because it's waiting for the loot window to open, but it never does, so it just constantly spams the /loot command.
One could add a check for you to have a target in the first place, and secondly that the target is a corpse.

But for the primitive way this macro is handling everything else I expect just fixing the /goto statements should be sufficient enough.

You said you wanted to learn, so I explained some crap. But here's the macro back....fixed the formatting a bit and cleaned up a lil bit of the stuff that my ocd hates. Hope this sorts your issue and it runs another 6 years.


Code:
Sub main
	/declare longKill timer
	/declare lootTimeOut timer
	/declare curZone string
	/declare notValid string
|	/declare named string
	/declare altCurrency string
	/declare lootItems string
	/declare lootWildcard1 string
	/declare lootWildcard2 string
	/declare lootWildcard3 string
	/declare lootWildcard4 string
	/declare lootWildcard5 string
	/declare lootWildcard6 string
	/declare lootWildcard7 string
	/declare lootWildcard8 string
	/declare lootWildcard9 string
	/declare lootWildcard10 string
	/declare lootWildcard11 string
	/declare lootWildcard12 string
	/declare lootWildcard13 string
	/declare lootName string
	/declare lootCount int
	/declare minLootValue int
	/declare npcID int
	/declare i int
	/declare ii int

	/declare noloot int
	
	/varset minLootValue 150

	/varset altCurrency /Ebon Crystal/Dream Mote/

	/varset lootItems /Diamond/Blue Diamond/Jacinth/Fire Opal/

	/varset lootWildcard1 ornate
	/varset lootWildcard2 item2
	/varset lootWildcard3 item3
	/varset lootWildcard4 item4
	/varset lootWildcard5 item5
	/varset lootWildcard6 item6
	/varset lootWildcard7 item7
	/varset lootWildcard8 item8
	/varset lootWildcard9 item9
	/varset lootWildcard10 item10
	/varset lootWildcard11 item11
	/varset lootWildcard12 item12
	/varset lootWildcard13 item13
	
	/varset notValid /NPCname1/NPCname2/

|	/varset named /NPCname1/NPCname2/

	/varset curZone ${Zone}

	/call doHideCorpses

	:WaitForRespawns

	/if (${SpawnCount[npc]}>0) {
		:NextSpawn
		/if (!${String[${Zone}].Equal[${curZone}]}) /return
		/for i 1 to ${SpawnCount}
			/vardata npcID NearestSpawn[${i},NPC].ID
			/if ((${npcID}!=${Me.ID}) && (${Spawn[${npcID}].Type.Equal[NPC]})) {
				/if ((${notValid.Find[/${Spawn[${npcID}].CleanName}/]}==NULL) && (${Spawn[${npcID}].CleanName.Length}>0)) {
					/target id ${npcID}
					/if (!${longKill}) {
						/call warpTarget 0
					} else {
						/call warpTarget 1
					}
					:Retarget
					/squelch /target clear
					/delay 5
					/target id ${npcID}
					/delay 1s ${Target.Distance}<10
					/stick 7 moveback
					/delay 3
					/keypress 6
					/keypress 6
					/delay 3
					/attack on
					/varset longKill 60s
					:WaitForDead
					/face fast nolook
					/doevents
					/if (${String[${Me.Class}].Equal[Rogue]}) {
						/if (${Me.AbilityReady[Backstab]}) /doability Backstab
						/if (${String[${Me.Song[Thief's Eyes]}].Equal[NULL]}) /doability "Thief's Eyes"
					}
					/if (${String[${Me.Class}].Equal[Druid]}) {
						/casting "Galatine"
						/delay 4
					}
					/if (${String[${Me.Class}].Equal[Warrior]}) {
						/if (${Window[CombatAbilityWnd].Open}) {
							/if (${Window[CombatAbilityWnd].Child[CAW_CombatEffectLabel].Text.Equal[No Effect]}) /casting "Blade of Hatred"
						}
					}
					|/if ((${Target.Type.Equal[CORPSE]}) || (!${longKill})) /target clear
					/if (!${longKill}) /goto :Retarget
					/if (${Target.Distance}>50) /call warpTarget 0
					|/if (${Target.ID}==${npcID}) /goto :WaitForDead
					:NearbyCorpseFound
					/if (!${noloot}) {
						/if (${Spawn[${npcID}].Type.Equal[CORPSE]}) {
							/if (!${Me.FreeInventory}) {
								/beep
							} else {
								/target id ${npcID}
								/call warpTarget 0
								/delay 2s ${Target.Distance}<10
								/if (${Target.Distance}<10) {
									/varset lootTimeOut 5s
									/delay 2
									/loot
									:WaitForLootWndOpen
									/delay 5
									/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) /goto :NextSpawn
									/delay 1s ${Window[LootWnd].Open}
									/loot
									/if (!${Window[LootWnd].Open}) /goto :WaitForLootWndOpen
									/vardata lootCount Corpse.Items
									/if (${lootCount}) {
										/for ii 1 to ${lootCount}
											/if (!${Me.FreeInventory}) /goto :DoneLooting
											/if (${Corpse.Item[${ii}].ID}) {
												/varset lootName ${Corpse.Item[${ii}].Name}
												/if (${altCurrency.Find[/${lootName}/]}) {
													/call lootItem ${ii}
													/call reclaimCurrency ${lootName}
												} else {
													/if ((${Corpse.Item[${ii}].Name.Find[${lootWildcard1}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard2}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard3}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard4}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard5}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard6}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard7}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard8}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard9}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard10}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard11}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard12}]} || ${Corpse.Item[${ii}].Name.Find[${lootWildcard13}]} || ... || ${lootItems.Find[/${lootName}/]} || ${Corpse.Item[${ii}].Value}>${Math.Calc[${minLootValue}*1000]}) && (!${Corpse.Item[${ii}].Lore} || !${FindItem[${Corpse.Item[${ii}].Name}].ID})) {
														/call lootItem ${ii}
													}
												}
												/if (${lootName.Find[EPIC]}) {
													/call lootItem ${ii}
												}
											}
										/next ii
									}
									:DoneLooting
									/notify LootWnd DoneButton leftmouseup
									:WaitForLootWndClose
									/delay 5
									/if ((!${NearestSpawn[corpse].LineOfSight}) || (!${lootTimeOut})) /goto :NextSpawn
									/if (${Window[LootWnd].Open}) /goto :WaitForLootWndClose
									/if (${NearestSpawn[corpse].LineOfSight}) {
										/vardata npcID NearestSpawn[corpse].ID
										/goto :NearbyCorpseFound
									}
								}
							}
						} else {
							/if (!${String[${Spawn[${npcID}].ID}].Equal[NULL]}) /goto :WaitForDead
						}
					}
					/if (!${String[${Spawn[${npcID}].ID}].Equal[NULL]}) /goto :WaitForDead
					/goto :NextSpawn
				}
			}
		/next i
	}
	/delay 5s
	/goto :WaitForRespawns
/return


Sub doHideCorpses
	/hidec all
	/hidec looted
	/delay 5
/return

Sub warpTarget(boolWithDistance)
	/if (${boolWithDistance}) {
		/warp loc ${Math.Calc[${Target.Y}-2]} ${Math.Calc[${Target.X}-2]} ${Target.Z}
	} else {
		/warp target
	}
/return

Sub reclaimCurrency(strCurrencyName)
	/declare itemIndex int local
	/declare itemTotal int local
	/if (${Window[IW_AltCurrPage].Open}) {
		/varset itemIndex ${Window[IW_AltCurrPage].Child[IW_AltCurr_PointList].List[=${strCurrencyName},2]}
		/if (${itemIndex}) {
			/notify IW_AltCurrPage IW_AltCurr_PointList listselect ${itemIndex}
			/notify IW_AltCurrPage IW_AltCurr_ReclaimButton leftmouseup
			/delay 5
		}
	}
/return

Sub lootItem(intLootSlot)
	/shift /itemnotify loot${intLootSlot} rightmouseup
	:WaitLootItem
	/delay 5
	/if (${Corpse.Item[${intLootSlot}].ID}) /goto :WaitLootItem
/return


Sub Event_Backstab(strText, strMobName, strDamage)	
	/declare formattedDamage string local
	|/if (${Group.Members}==NULL) /return
	/if (!${strDamage}==NULL) {
		/if (${strDamage}>500000) {
			|/popup ${strDamage}
			/if (${strDamage}<1000000) {
				/varset formattedDamage ${String[${strDamage}].Left[3]},${String[${strDamage}].Right[3]}
			} else {
				/varset formattedDamage ${String[${strDamage}].Left[4]},${String[${strDamage}].Right[3]}
				/varset formattedDamage ${String[${formattedDamage}].Left[1]},${String[${formattedDamage}].Right[7]}
			}
			/guildsay Backstab (${strMobName}) for ${formattedDamage} points of damage.
		}
	}
/return