#
automation
Allows control over the automation in lua.
Quick reference: Build events with event_type.*, add them with add_event() or set_routine(), then start_routine(). Use automation.listener for path_found, start_walking, stuck, path_finished.
#
Routines and automation
The automation exposes a routine system: ordered lists of events (move, wait, input, Lua, etc.).
Typical flow: build a routine (e.g. Goto + Wait + RunCommand), optionally hook automation.listener to react to path_found / start_walking / stuck / path_finished, then call start_routine() to run the routine.
secret.automation.clear_routine()
secret.automation.add_event({ type = secret.automation.event_type.Goto, pos = { x = 1000, y = 2000, z = 100 }, goto_run = true, goto_destination_radius = 100 })
secret.automation.add_event({ type = secret.automation.event_type.Wait, wait_ms = 500 })
secret.automation.add_event({ type = secret.automation.event_type.RunCommand, command = "say arrived" })
secret.automation.start_routine()
Automation lifecycle is exposed via automation.listener, which uses the same API as the
add(name, identity, callback) to register and remove(name, identity) to unregister. Use a string of your choice as identity (e.g. a script name) so you can remove the callback later.
secret.automation.listener.add("path_found", "my_hook", function()
local waypoints = secret.automation.get_waypoints()
print("Path has " .. #waypoints .. " waypoints")
end)
secret.automation.listener.add("path_finished", "my_hook", function()
print("Reached destination")
secret.automation.listener.remove("path_finished", "my_hook")
end)
secret.automation.clear_routine()
secret.automation.add_event({ type = secret.automation.event_type.Wait, wait_ms = 1000 })
secret.automation.add_event({ type = secret.automation.event_type.RunCommand, command = "say Done" })
secret.automation.start_routine()
#
Event table shape
Each event in a routine is a table with optional fields. Common fields:
Conditional / goto / node fields:
cmd_overrides — Optional table that overrides player commands while the event runs:
#
Routine API
#
Building routines
automation.get_routine(): table
- Current routine as 1-based array of event tables.
local events = secret.automation.get_routine()
for i, ev in ipairs(events) do
print("Event " .. i .. " type=" .. tostring(ev.type) .. " wait_ms=" .. tostring(ev.wait_ms))
end
automation.set_routine(events: table)
- Replace the entire routine with the given array of event tables.
secret.automation.set_routine({
{ type = secret.automation.event_type.Wait, wait_ms = 1000 },
{ type = secret.automation.event_type.Goto, pos = { x = 100, y = 200, z = 300 }, hold_ms = 500, goto_destination_radius = 80 }
})
automation.add_event(event: table)
- Append one event to the end of the routine.
secret.automation.add_event({
type = secret.automation.event_type.RunCommand,
command = "say Hello"
})
automation.insert_event(index: number, event: table)
- Insert an event at 1-based index (shifts others). Index 1 = start.
secret.automation.insert_event(1, { type = secret.automation.event_type.Wait, wait_ms = 500 })
automation.remove_event(index: number)
- Remove event at 1-based index. No-op if index < 1.
secret.automation.remove_event(2)
automation.clear_routine()
- Clear all events.
secret.automation.clear_routine()
#
Playback
automation.start_routine()
- Start the current routine.
secret.automation.start_routine()
automation.stop_routine()
- Stop the running routine.
if secret.automation.is_routine_running() then
secret.automation.stop_routine()
end
automation.is_routine_running(): boolean
- True if a routine is running.
secret.automation.is_routine_running()
#
Link-to-next
automation.get_link_to_next(): table
- 1-based array of booleans: per-step link-to-next (flow between steps).
local links = secret.automation.get_link_to_next()
for i, linked in ipairs(links) do
print("Step " .. i .. " linked to next: " .. tostring(linked))
end
automation.set_link_to_next(links: table)
- Set link-to-next flags: table of booleans, one per step.
secret.automation.set_link_to_next({ true, true, false })
#
Runtime state (during routine playback)
automation.get_waypoints(): table
- Current routine waypoints: 1-based array of
{ x, y, z }.
local waypoints = secret.automation.get_waypoints()
for i, wp in ipairs(waypoints) do
print("Waypoint " .. i .. ": " .. wp.x .. ", " .. wp.y .. ", " .. wp.z)
end
automation.get_current_step_index(): number
- 1-based index of the step currently executing (0 when not running).
local step = secret.automation.get_current_step_index()
print("Current step: " .. step)
automation.jump_to_step(step_index: number)
- Jump to a step index in the routine (1-based). Use to skip or re-run steps during playback.
automation.signal(name: string)
- Fire a signal by name. Use with the
WaitForLuaSignalevent type: when the routine hits that event it waits untilautomation.signal(name)is called with the same name (empty string is valid).
secret.automation.signal("my_signal")
automation.get_crosshair_trace_end(): table
- World position where crosshair trace hits:
{ x, y, z }.
local hit = secret.automation.get_crosshair_trace_end()
print(hit.x, hit.y, hit.z)
automation.get_current_position(): table
- Current player position:
{ x, y, z }.
local pos = secret.automation.get_current_position()
print(pos.x, pos.y, pos.z)
automation.get_current_view_angles(): table
- Current view angles:
{ p, y }.
local ang = secret.automation.get_current_view_angles()
print("Pitch: " .. ang.p .. " Yaw: " .. ang.y)
automation.save_routine(name: string): boolean
- Saves the current routine to a file by name.
secret.automation.save_routine("my_routine")
automation.load_routine(name: string): boolean
- Loads a routine from a saved file by name.
if secret.automation.load_routine("my_routine") then
secret.automation.start_routine()
end
automation.run_routine(name: string): boolean
- Load and start a routine by name.
secret.automation.run_routine("my_routine")
automation.list_routines(): table
- 1-based array of saved routine names.
local names = secret.automation.list_routines()
for i, name in ipairs(names) do
print(i .. ": " .. name)
end
automation.list_lua_files(): table
- 1-based array of Lua file names for ExecuteLua /
lua_file.
local files = secret.automation.list_lua_files()
for i, name in ipairs(files) do
print(i .. ": " .. name)
end
automation.export_routine(): string
- Serialize current routine to a string.
local data = secret.automation.export_routine()
automation.import_routine(str: string): boolean
- Import a routine from a string (from
export_routine).
local exported = secret.automation.export_routine()
if secret.automation.import_routine(exported) then
secret.automation.start_routine()
end
#
Event types and buttons
Table of event type IDs for the type field:
secret.automation.add_event({ type = secret.automation.event_type.Wait, wait_ms = 1000 })
secret.automation.add_event({ type = secret.automation.event_type.RunCommand, command = "say hi" })
secret.automation.add_event({ type = secret.automation.event_type.PressKey, button_mask = secret.automation.buttons.IN_ATTACK, hold_ms = 100 })
Button mask constants for PressKey, WhenButtonHeld, and button_mask:
secret.automation.add_event({
type = secret.automation.event_type.PressKey,
button_mask = secret.automation.buttons.IN_ATTACK,
hold_ms = 200
})
Reason IDs passed to the stuck event callback. Exposed on automation (e.g. secret.automation.STUCK_COLLISION_BLOCKED):
secret.automation.listener.add("stuck", "my_script", function(reason_id)
if reason_id == secret.automation.STUCK_NO_PROGRESS then
secret.automation.stop_routine()
end
end)
#
Events
Automation fires signals during routine playback. automation.listener uses the
listener.add(name, identity, callback) and unregister with listener.remove(name, identity). The identity is a string you choose (e.g. script name) so you can remove the callback later.
path_found()
- Fired when a path to the current destination has been computed. Use
get_waypoints()to read the path.
secret.automation.listener.add("path_found", "my_script", function()
local waypoints = secret.automation.get_waypoints()
for i, wp in ipairs(waypoints) do
print(string.format("wp %d: %.0f %.0f %.0f", i, wp.x, wp.y, wp.z))
end
end)
start_walking()
- Fired when movement along the path begins (after path_found). Use
get_current_step_index()to track progress.
secret.automation.listener.add("start_walking", "my_script", function()
local step = secret.automation.get_current_step_index()
local pos = secret.automation.get_current_position()
print("Walking from " .. pos.x .. " " .. pos.y .. " " .. pos.z .. " (step " .. step .. ")")
end)
stuck(reason_id: number)
- Fired when the automation detects it can’t proceed (obstruction, no progress, etc.). The callback receives reason_id; use
automation.STUCK_COLLISION_BLOCKED(1) andautomation.STUCK_NO_PROGRESS(2) to branch. The engine may recalc the path; you can stop or adjust the routine here.
secret.automation.listener.add("stuck", "my_script", function(reason_id)
local step = secret.automation.get_current_step_index()
local pos = secret.automation.get_current_position()
if reason_id == secret.automation.STUCK_COLLISION_BLOCKED then
print("Stuck: collision blocked at step " .. step)
elseif reason_id == secret.automation.STUCK_NO_PROGRESS then
print("Stuck: no progress at step " .. step)
end
-- secret.automation.stop_routine()
end)
path_finished()
- Fired when the current destination is reached. Useful to chain routines or run cleanup.
secret.automation.listener.add("path_finished", "my_script", function()
print("Destination reached")
secret.automation.listener.remove("path_finished", "my_script")
end)
To run different logic per routine, store state and branch inside the callback:
local routine_name = "patrol_a"
secret.automation.listener.add("path_finished", "router", function()
if routine_name == "patrol_a" then
routine_name = "patrol_b"
secret.automation.run_routine("patrol_b")
else
secret.automation.listener.remove("path_finished", "router")
end
end)
secret.automation.run_routine("patrol_a")