Control Flow
Every block opens with a keyword and closes with a matching
end…. There are no braces and no parentheses, which also means
you cannot group conditions, so complex logic is expressed by nesting.
if / elseif / else
Runs a block when an expression is true. Close it with endif.
if hp < 30
potion 'heal'
elseif hp < 60
hotkey 'Bandage self'
else
overhead 'healthy'
endif
Combine conditions with and / or, and negate with
not:
if hp < 50 and mana >= 11
cast 'greater heal'
endif
if not dead
// main loop
endif There are no parentheses. and and or are
evaluated left to right, so you cannot write (a or b) and c. When
you need that, nest two ifs. The outer one acts as the
and.
while
Repeats a block for as long as the expression stays true. Close it with
endwhile.
while mana < maxmana
skill 'meditation'
wait 11000
endwhile for
Repeats a block a fixed number of times. Close it with endfor.
The current pass is available as index, counting from 0.
for 5
say 'shout {{index}}'
wait 1000
endfor foreach
Walks a list, putting each entry into a variable of your choosing. Also
closed with endfor.
createlist 'ore'
pushlist 'ore' 0x19B9
pushlist 'ore' 0x19BA
foreach id in ore
@dclicktype id backpack
wait 500
endfor
removelist 'ore'
Combined with findtypelist, this is how you act on everything
that matches, rather than on one random item:
createlist 'loot'
findtypelist 'loot' 0x0EED ground 0 any 3 // gold within 3 tiles
foreach item in loot
dclick item
wait 600
endfor
removelist 'loot' break & continue
break leaves the loop entirely; continue jumps back
to the loop's condition and starts the next pass.
while 1 = 1
if weight > maxweight
break // pack is full, stop looting
endif
if not findtype 0x0EED ground
continue // nothing here, look again
endif
dclicktype 0x0EED ground
endwhile stop, replay & loop
stop ends the script immediately. loop jumps back to
the very first line. That is the usual way to make a watcher script keep watching.
replay is an older spelling of the same thing.
if dead
overhead 'I am dead, stopping'
stop
endif
// ... work ...
wait 250
loop Waiting properly
Most scripts fail for one of two reasons: they do not wait for the server, or they do not wait at all.
-
After anything that opens a target cursor, use
waitfortarget, never a fixedwait. The server's latency is not your business. -
Same for gumps (
waitforgump), menus (waitformenu) and prompts (waitforprompt). -
In a
loop, alwayswaitat least a little, even when there is nothing to do.
cast 'greater heal'
waitfortarget // right: waits exactly as long as needed
target 'self'
cast 'greater heal'
wait 2000 // wrong: too slow when fast, too fast when lagging
target 'self'