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.
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:
Navigation is a global table: call its functions with a dot (Navigation.<method>(...)), not a colon. Requires Macro Handler 1.0.51 or later.
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.
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.
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.
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.
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)
endFrom 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.
-- 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)
endlocal 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)
endlocal 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-- 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-- 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)