The console namespace is a mod's way into the developer console, the ~ console of the Source engine recreated in the hook. A mod can run command lines, print to the console, read and set cvars, and add cvars and commands of its own that then behave like the built-in ones: help, find and cvarlist list them, Tab completes them, and archive cvars are saved to cfg\config.cfg with everything else.

Static members#

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

ss.console.exec("fps_max 144")

Static functions#

FunctionReturn ValuesDescription
ss.console.exec(string line) nil Runs a command line as if it had been typed into the console: commands and cvars, several separated by ;, aliases and exec included. Errors such as an unknown command print in the console, not in the script.
ss.console.print(vararg values) nil Prints a line to the console. Each value is converted with tostring and the values are separated by tabs, as the standard print does.
ss.console.warning(vararg values) nil Prints a line to the console in the warning colour, otherwise as ss.console.print.
ss.console.get(string name) string value Returns the value of a cvar as a string, or nil when there is no cvar of that name.
ss.console.set( string name, any value ) boolean found Sets a cvar from a string, number or boolean and returns whether a cvar of that name exists. The value is clamped to the cvar's range. The sv_cheats gate belongs to the command line, so a cheat cvar can be set this way; ss.console.exec respects it.
ss.console.find(string name) table cvar Returns a cvar object for an existing cvar, the hook's own included, or nil when there is none.
ss.console.cvar( string name, string default, string help, [table opts] ) table cvar Creates a cvar owned by the mod and returns its cvar object. The keys of opts are listed under Cvar options. A name the hook already owns is an error; a name the mod registered before is replaced, which is what a reload needs.
ss.console.register( string name, string help, function fn, [table flags] ) boolean Adds a command owned by the mod. fn runs with one table, described under Commands, every time the command is run. The flags are those of Cvar options. A name the hook already owns is an error; a name the mod registered before is replaced.
ss.console.open() boolean open Opens the console and returns whether it is open. Nothing happens while con_enable is 0.
ss.console.close() nil Closes the console.
ss.console.toggle() boolean open Opens the console when it is closed and closes it when it is open, as the ~ key does, and returns whether it is open afterwards.
ss.console.is_open() boolean open Whether the console is open.
ss.console.clear() nil Clears the console's output, as the clear command does.
ss.console.text([integer lines]) string text Returns the console's output as one string with a newline after every line: the last lines lines, or all of it when lines is left out or 0.

Commands#

A command is a name and a function. When the command is run, from the console, from a bind, from a cfg file or through ss.console.exec, the function receives one table with the arguments the console tokenised: quoted strings are one argument, and ; ends the command.

The argument table
TypeFieldDescription
string [1], [2], ... The arguments after the command's name, in order.
integer n How many arguments there are.
string name The name the command was run by.
string raw Everything after the name as it was typed, quotes included.
ss.console.register("magnet_strength", "Sets the magnet's pull, 0 to 10.", function(args)
	if args.n < 1 then
		ss.console.print("magnet_strength <0..10>")
		return
	end
	STRENGTH = math.min(10, math.max(0, tonumber(args[1]) or 0))
	ss.console.print("magnet strength is now", STRENGTH)
end)

The function runs on the game's main thread, so a slow one stalls the game for that long. An error inside it is printed in the console in the warning colour with a traceback, and the command stays registered. A command the mod does not want to be seen in find or Tab completion takes the hidden flag.

Note

A command only knows its own arguments; Tab completion fills in the command's name, not what it takes. Printing a usage line when args.n is 0 is the convention the built-in commands follow.

Cvar objects#

ss.console.cvar and ss.console.find return a live object: reading a field reads the cvar as it is now, and assigning value, number, int or bool sets it, clamped to the cvar's range, with its on_change run. Setting a value the cvar clamps prints the clamped value, as Source does. The sv_cheats gate is the command line's, not the cvar's, so it does not apply here.

TypeFieldRead-only?Description
string value No The value as a string. Assigning a string, number or boolean sets the cvar.
number number No The value as a number, 0 when it is not one.
integer int No The value as an integer.
boolean bool No Whether the value is not 0.
string name Yes The cvar's name.
string default No The default value, what help shows as def.. Writable for the mod's own cvars.
string help No The help text. Writable for the mod's own cvars.
number min Yes The lower bound, or nil when the cvar has none.
number max Yes The upper bound, or nil when the cvar has none.
integer flags Yes The cvar's flags as the number the engine keeps.
local speed = ss.console.cvar("magnet_speed", "10", "How fast the magnet pulls.", { min = 0, max = 100 })
speed.number = 250            -- clamps to 100 and prints the clamp, as the console would
ss.console.print(speed.value) -- "100.000000"

local fps = ss.console.find("fps_max")
if fps and fps.int == 0 then ss.console.print("uncapped") end

Cvar options#

The keys of the opts table of ss.console.cvar. Every key is optional.

TypeFieldDescription
number min The lowest value the cvar accepts; a lower one is clamped.
number max The highest value the cvar accepts; a higher one is clamped.
table flags The cvar's flags, as a table of names: archive (saved to cfg\config.cfg and restored at start-up), cheat (needs sv_cheats 1 to change), hidden (left out of find and completion), notify, replicated, developmentonly, never_as_string, protected, sponly, unregistered. A number of the engine's FCVAR_ bits is accepted too.
function on_change Runs after the value changes, with the new value and the old one as strings. An error in it is printed in the console with a traceback.

The same names, as a table or a number, are the fourth argument of ss.console.register.

From the console#

Two built-in commands run Lua the other way round. lua <code> runs the code in a script state of the console's own, with the whole ss API, and prints the results of an expression tab separated; print goes to the console there, not to the log. lua_mod <mod> <code> runs the code inside a mod's state, so a mod's globals can be read and changed while it runs; ss_mods lists the states by name. Both take the code as the rest of the line, quoted or not.

] lua return 1 + 1, ss.vehicle and ss.vehicle.speed_kmh
2	0
] lua_mod Magnet STRENGTH = 3
] magnet_strength
magnet_strength <0..10>

A mod's commands and cvars are gone with its state, so ss_mods is also where to look when a command of a mod is unknown: the mod has not loaded, or its script failed before the registration ran.

Example#

Scripts\main.lua
-- A cvar that turns the mod's overlay on and off, saved between runs, and a
-- command that reports where the player is.
local show = ss.console.cvar("hud_overlay", "1", "Show the mod's overlay.", {
	min = 0, max = 1, flags = { "archive" },
	on_change = function(new, old)
		ss.console.print("overlay", new == "1" and "on" or "off")
	end,
})

ss.console.register("whereami", "Prints the player's position.", function(args)
	local me = ss.vehicle
	if not me then
		ss.console.warning("not in a race")
		return
	end
	ss.console.print(string.format("%.1f %.1f %.1f", me.position.x, me.position.y, me.position.z))
end)

ss.on("draw", function(ev)
	if show.bool and ss.vehicle then
		ss.draw.text(string.format("%.0f km/h", ss.vehicle.speed_kmh), 20, 20, { size = 28 })
	end
end)