Lua
Modules, require and walking
Lua · Updated 09 November 2026
What each botwithus module gives you, loading your own files, actions and the two walking styles.
The modules
| Module | What it gives you |
|---|---|
botwithus |
the umbrella: run, stopping, npcs, players, objects, Game, Tile, Actions, Events, Input, clients, Variables |
botwithus.game |
the Game your script gets as ctx.game: :self(), :npcs(), :players(), :objects(), interface checks, :clocks(), walking, :queue_actions(), :poll_events(), breaks, varp and varbit reads |
botwithus.config |
settings fields: int_field, string_field, bool_field, choice_field, item_id_field |
botwithus.entities |
fluent queries: :of_type(), :within(), :where(), :nearest(), :all() |
botwithus.tile |
Tile, with 8-directional distance |
botwithus.actions |
action ids and builders: walk_to(x, y), component_click(...), dialogue_option(...) |
botwithus.events |
decodes the events from Game:poll_events(), such as action_executed and action_refused |
botwithus.variables |
the varp state names: SET, DEFAULT, NO_SUCH_VARP, UNAVAILABLE |
botwithus.input |
the game's input dialog: Input.dialog(game) with :enter_amount(...), :enter_text(...) and more |
Loading your own files
The script's own folder is put first on package.path. So a script can require the files next to it: require("helpers") finds helpers.lua or helpers/init.lua beside your script.
Lua separates package.path entries with ;, so this does not work from a folder whose name contains ;.
Finding things
local tree = bot.objects(ctx.game):of_type(TREE):nearest(me.tile)
bot.npcs(game), bot.players(game) and bot.objects(game) start a query. :of_type(id) and :where(fn) filter it, and :nearest(tile) or :all() finish it.
Acting
ctx.game:do_action(a) queues one action and returns true, or false and the error:
ctx.game:do_action({ id = 3, p1 = tree.id, p2 = tree.tile.x, p3 = tree.tile.y })
ctx.game:queue_actions(list) sends several actions in one go. The game queues all of them or none, and the call raises if they were refused. :try_queue_actions(list) reports the same outcome without raising.
An action the game queued can still be dropped later if its target never becomes clickable. ctx.game:poll_events() then returns an action_refused event for it.
Walking: two styles
ctx.game:walk_to(x, y)queues one walk hop and returns straight away. You write the loop: step,ctx:sleep_ticks, repeat.ctx.game:walk(x, y, plane, radius)does a full walk. It plans the route, walks it, re-plans as needed and carries out its transitions (doors, stairs, teleports, dialogue) until it arrives. It blocks for the whole route and returnsarrived, err.ctx.game:walk_cancel()stops it.
local bot = require("botwithus")
local Tile = bot.Tile
local BANK = Tile.new(3165, 3486, 0)
local RADIUS = 3
function script.on_loop(ctx)
local me = ctx.game:self()
if me.tile.plane == BANK.plane and me.tile:distance(BANK) <= RADIUS then
return -1
end
local arrived, err = ctx.game:walk(BANK.x, BANK.y, BANK.plane, RADIUS)
if not arrived then
io.write(("banker: walk did not arrive (%s); stopping\n"):format(tostring(err)))
return -1
end
return 0
end
ctx.game:walk_ex(...) is the same blocking walk and returns a result table instead: status, the step or transition a failed walk failed on, re-plans used, elapsed time and the walker's events.
Breaks and varps
ctx.game:schedule_break(300)holds the action queue for 300 seconds.ctx.game:interrupt_break()ends it early.ctx.game:read_varp(id)and:read_varbit(id)return a table with astatebeside thevalue. Decide on the state, not the value alone.ctx.game:local_health()returnscurrent, maxlife points, ornilwhile unknown.
Next: Logs and running.