Object MethodTouch and ActionsComing soonv1.0.51

Navigation.run(options, onCheckpoint?)

Follows a map/route saved in this macro using live measurements and returns a table describing how the run ended. Choose Live heading tracking (controlMode = "heading_feedback") or Strict mode with its measured local calibration. The closed-loop control and the input ownership belong to this call: do not send Touch or swipe input while it runs. Optional callbacks run point and observation groups.

Documented for app version 1.0.51 (not on Google Play yet)Updated:

Detailed Explanation

This section explains when to use the API, how to call it, and which structures it works best with in production flow.

How To Call It

Navigation is a global table: call its functions with a dot (Navigation.<method>(...)), not a colon. Requires Macro Handler 1.0.51 or later.

When To Use It

Use it to walk a character along a route saved in this macro in joystick-driven games. The map, marker, route, calibration and groups are prepared on the Navigation card; do not invent ids or calibration numbers, and verify the setup with the route preview and Observe without moving. heading_feedback learns the movement relationship during travel from a taught heading tip; strict requires local calibration. full_map is the default; mini_map requires a separately taught area and marker. Movement does not start when the position, the map or a fresh frame is missing.

Parameters and Return

options: profileId, routeId, routeType (one_way, loop, ping_pong), repeatCount, controlMode, timeoutMs, mapSource and optional observationGroup={groupId, groupName, intervalMs}. Use IDs saved in this macro. repeatCount is zero for unlimited loop/back-and-forth or positive for a total count; one ping-pong repetition includes outward and return legs, while one-way is one passage. Dynamic profileSelection or routeSelection uses traversal and repeat settings from the selected saved route. onCheckpoint(event) must accept validateOnly preflight calls without actions and return true only when the group completes successfully. event carries group identity and kind; observation events also carry measurement values. Missing callbacks, errors or returns other than true cancel the journey.

Options and Limits

The option table is checked strictly: an unknown key, a wrong type (text where a number belongs) or an invalid value returns state = "ERROR" with lastFailure = "invalid_navigation_options" without moving; the table may hold at most 40 keys and 16 KiB. Keys: profileId and routeId (ids of the saved setup), or profileSelection and routeSelection (a saved name or id from a Dialog or variable); routeType = "one_way" (default), "loop" or "ping_pong"; controlMode = "strict" (default) or "heading_feedback"; resumePolicy = "restart" (default) or "after_verified_agent" (not with heading_feedback); timeoutMs (default 120000); repeatCount (default 0: loop and ping_pong run until timeoutMs; a positive value is the total number of cycles, and one_way accepts only 0 or 1); mapSource = "full_map" (default) or "mini_map"; observationGroup = { groupId, groupName, intervalMs (default 1000) } for a group that scans while moving; autoCalibrate (default true); outputPrefix (default "navigation"); and the controller and headingFeedback sub-tables. Result fields: state (ARRIVED, LOOP_COMPLETED, STUCK, OFF_ROUTE, PLAYER_LOST, MAP_LOST, CALIBRATION_REQUIRED, CALIBRATION_INVALID, GESTURE_FAILED, STOPPED, ERROR and others), lastFailure, progress (0-1), playerX/playerY with playerKnown, heading with headingKnown, crossTrackError, routeIndex, speed, joystickX/joystickY, confidence, delay, mapScore, markerScore, stuck and resumePending.

Best Combined With

Evaluate the result by state: ARRIVED or LOOP_COMPLETED is success; on OFF_ROUTE, PLAYER_LOST, MAP_LOST or GESTURE_FAILED do not move blindly. Check position and heading with playerKnown and headingKnown and never read an unknown value as zero. Point callbacks run after joystick release and the route continues after the group. For observation callbacks, navigation continues steering: scan only in that group, and before a screen action check that Navigation.stop() returns true. An explicit stop ends the journey with STOPPED; travelling again requires a separate Navigation call. Match groups by stable groupId; names are display labels. Navigation.run needs Android 8.0 (API 26) in every control mode; on older versions it returns GESTURE_FAILED (continued_gesture_requires_api26) without moving.

Example Usage

The snippet below is a starter pattern that can be applied directly in runtime flow.

-- profileId and routeId come from the Navigation card of this macro
local result = Navigation.run({ profileId = profileId, routeId = routeId, routeType = "one_way", timeoutMs = 120000 })
if result.state == "ARRIVED" then
  print("arrived")
else
  print("stopped: " .. result.state .. " " .. result.lastFailure)
end

Copyable Progressive Examples

From foundation to combined usage, each level is provided as a separate code block so you can copy the level you need and adapt it directly.

Foundation

Shows the shortest direct way to call the API.

Foundation
-- profileId and routeId come from the Navigation card of this macro
local result = Navigation.run({ profileId = profileId, routeId = routeId, routeType = "one_way", timeoutMs = 120000 })
if result.state == "ARRIVED" then
  print("arrived")
else
  print("stopped: " .. result.state .. " " .. result.lastFailure)
end

Simple

Wraps the base call with minimal flow control.

Simple
local stepOk = true
-- profileId and routeId come from the Navigation card of this macro
local result = Navigation.run({ profileId = profileId, routeId = routeId, routeType = "one_way", timeoutMs = 120000 })
if result.state == "ARRIVED" then
  print("arrived")
else
  print("stopped: " .. result.state .. " " .. result.lastFailure)
end
if stepOk then
  wait(200)
end

Practical Flow

A practical pattern for real macros with pcall, logging, and guards.

Practical Flow
local ok, err = pcall(function()
  -- profileId and routeId come from the Navigation card of this macro
  local result = Navigation.run({ profileId = profileId, routeId = routeId, routeType = "one_way", timeoutMs = 120000 })
  if result.state == "ARRIVED" then
    print("arrived")
  else
    print("stopped: " .. result.state .. " " .. result.lastFailure)
  end
end)

if not ok then
  print("API step failed: Navigation.run: " .. tostring(err))
  requestStop()
end

Detailed

This level packages the API into a reusable helper with error reporting.

Detailed
-- Use real macro-scoped IDs; preflight never performs actions
local function run_run_step()
  -- profileId and routeId come from the Navigation card of this macro
  local result = Navigation.run({ profileId = profileId, routeId = routeId, routeType = "one_way", timeoutMs = 120000 })
  if result.state == "ARRIVED" then
    print("arrived")
  else
    print("stopped: " .. result.state .. " " .. result.lastFailure)
  end
end

local ok, err = pcall(run_run_step)
if not ok then
  toast("Step failed")
  print(err)
end

Combined

Combines the API with related structures to form a more realistic workflow.

Combined
-- Replace IDs with the saved setup and observation group from this macro.
local monitorId = "saved-group-id"
local result = Navigation.run({
  profileId = "saved-profile-uuid", routeId = "saved-route-uuid",
  controlMode = "heading_feedback", timeoutMs = 120000,
  observationGroup = { groupId = monitorId, groupName = "Watch target", intervalMs = 1000 }
}, function(event)
  if event.groupId ~= monitorId then error("Unknown group") end
  if event.validateOnly then return true end
  if event.kind ~= "observation" then error("Unexpected callback") end
  Snap.screenRefresh()
  local target = Region():find(Asset.image("target"))
  if target then
    if Navigation.stop() ~= true then error("NAVIGATION_RELEASE_UNCONFIRMED") end
    click(target)
  end
  return true
end)
print(result.state, result.lastFailure)