The routine class handles coroutines. A coroutine is a function that can hand control back to the game in the middle of its own flow and be resumed later, so a sequence that waits on the game can be written top to bottom instead of as a handler per step. The functions that wait can only be used from within a routine, and pass control back to the game until the routine resumes.

Static members#

These elements are static to the class itself and can be accessed like so:

local r = ss.routine(function() ss.wait(3) end)

Static functions#

FunctionReturn ValuesDescription
ss.routine( function f, vararg args ) routine routine Creates a new routine and runs it at once, up to its first wait. Additional arguments are passed to the function f.
ss.routine( string name, function f, vararg args ) routine routine Creates a new routine with a name, which is shown in the log when the routine errors, and runs it at once.
ss.wait(seconds seconds) nil Exits the current routine, resuming it on the first frame tick after the given number of seconds.
ss.wait_frames(integer frames) nil Exits the current routine, resuming it on the first frame tick after the given number of frames.
ss.wait_until(function f) nil Exits the current routine, resuming it on the first frame tick on which f() returns true. An error in f ends the routine.
ss.wait_event(string name) table ev Exits the current routine, resuming it when the given event fires, after the event's handlers have run. Returns the event's payload.
ss.wait_signal(string name) any values Exits the current routine, resuming it when ss.signal is called with the given name. Returns the arguments ss.signal was given.
ss.signal( string name, vararg args ) integer woken Signals all routines that are waiting for the given name via ss.wait_signal, passing them the arguments. Returns the number of routines woken. Usable from a handler, a timer or another routine.
ss.routines.count integer count The number of the mod's routines that are live.
ss.routines.all() table of routine routines Returns a table of references to all of the mod's live routines.
ss.routines.stop_all() nil Stops all of the mod's live routines.

A wait outside a routine results in an error. The waits are driven from the frame tick, in every app state, so a routine keeps waiting and resuming through the menus and after the race it was started in has ended.

Instance members#

Instance members must be accessed through a reference to a specific routine object.

local r = ss.routine(function() ss.wait(10) end)
ss.log(r.waiting)
r:stop()
WARNING: Attempting to call instance members statically will result in an error!

Instance Methods#

What is a method?

FunctionReturn ValuesDescription
stop() nil Abandons the routine where it waits, preventing it from resuming.

Instance Fields#

TypeFieldRead-only?Description
boolean running Yes Returns true while the routine has not finished, errored or been stopped.
boolean done Yes Returns true once the routine's function has returned.
string error Yes The error that ended the routine, with its traceback. nil if no error ended it.
string waiting Yes What the routine is waiting on: time, frames, until, event or signal. nil while the routine is not waiting.
string name Yes The name the routine was started with. nil if none was given.

Errors and the race#

An error inside a routine ends it and is reported like a handler's error, with the traceback; the other routines keep running. A routine lives in its mod's state, not in the race: it is not stopped when a race ends, and a routine that resumes from a long wait may find the cars gone. Check ss.race.state or ss.vehicle.valid after a wait that could have outlasted the race, or start the routine from a race_start handler and stop it from a race_end handler.

Example#

local run

ss.on("race_start", function()
	run = ss.routine("brake test", function()
		ss.wait(5)
		local ai = ss.vehicles[1]
		if not ai then return end
		ai.input = { throttle = 0, brake = 1 }     -- an AI car brakes to a stop
		ss.wait_until(function() return not ai.valid or ai.speed < 1 end)
		if ai.valid then ai.input = nil end         -- and drives off again
	end)
end)

ss.on("race_end", function()
	if run then run:stop(); run = nil end
end)