Elysium scripting Editor API index
Build

Game, console & sound

The map and the clock, the console, chat and sound, convars, particles, and the game's own interface.

The game module is the script's window onto the game as a whole - which map is loaded, what time it is, what the console can be told to do - as opposed to entities, which are things in the game.

on( "game:round_start", function( ev )
	game.chat( "round started on " .. ( game.map( ) or "?" ) )
end )

#Where and when

#game.in_game() → boolean

Whether there is a local player - you are in a map, not on the main menu.

#game.map() → string | nil

The short name of the loaded map, such as "de_mirage"; nil outside a map.

#game.curtime() → number

The game's clock, in seconds: the time the game logic itself runs on. It is what times such as weapon:next_attack() and bomb.blow_time are measured against, so use it - not render.time() - to compare with them.

#game.tick() → integer

The client's tick counter.

#game.server_tick() → integer

The newest server tick the client has heard of.

#game.realtime() → number

Seconds on a clock that only moves forward, whatever the game does. The same clock as render.time().

#game.frametime() → number

Seconds the last frame took.

#game.fps() → number

#game.time_to_ticks( seconds ) → integer

#game.ticks_to_time( ticks ) → number

Conversions between seconds and ticks, at the game's 64 ticks per second.

#game.tick_interval → number

The length of a tick in seconds: 0.015625.

#game.tickrate → integer

64.

#game.screen() → width, height

The size of the game's picture in pixels.

#game.angles() → vec3

The view angles the game is using right now.

#game.set_angles( angles )game thread

Turns the player's view. Pitch is kept within ±89 and the roll is zeroed. If you call it from a thread other than the game's, the change is queued and applied at the next frame stage. For changing what a command carries, see cmd:set_angles.

#game.stage

A table naming the frame stages the cheat itself reacts to, for the stage event: game.stage.net_commit (6), game.stage.pre_render (7) and game.stage.render_start (12).

#Console, chat and sound

#game.command( text )game thread

Runs a console command, as if you had typed it: game.command( "echo hello" ). It goes through the game's own command system, so it is subject to the same rules as typing it - and a command that sends something to the server, say for instance, does exactly that. Called from outside the game's thread, it is queued and runs at the next frame stage.

#game.chat( text )game thread

Prints a line in your local chat window. Nothing is sent to the server or to other players.

#game.sound( path [, volume] )game thread

Plays one of the game's sounds by its path - "sounds/ui/coin_pickup_01", "sounds/ui/killcard_1" and "sounds/training/timer_bell" are three that exist. volume is a percentage, 100 by default. The call is made through the same engine routine as the playvol console command. A path the game does not know plays nothing.

#game.play_file( path ) → boolean

Plays a .wav file from the script's folder through the system mixer - independent of the game's own sound. true if the file exists and was started, false otherwise. Only WAV files; the sound plays asynchronously.

#game.js( code )game thread

Runs JavaScript in the game's own user-interface (Panorama) context - the HUD panel's script environment, the one the scoreboard is built with. Nothing happens if the interface is not ready. Queued like the other engine calls.

#Convars

Convars are the game's console variables: sv_cheats, cl_showfps, viewmodel_fov.

#game.cvar( name ) → convar | nil

Finds a convar by name; nil if the game has none. Lookups are remembered, so asking again is cheap.

local fps = game.cvar( "cl_showfps" )

if fps then
	print( fps:name( ), fps:int( ) )
end

#cv:name() → string, cv:description() → string

#cv:flags() → integer

The convar's flag bits, as the game defines them.

#cv:type() → integer

The engine's numeric type id of the convar.

#cv:get() → value

The value in the convar's own type: a boolean, an integer, a number or a string; nil for a type the runtime does not know. It relies on type(); if it answers nil where you expected a value, use the typed readers below, which do not.

#cv:bool(), cv:int(), cv:float(), cv:string()

Read the value as that type, whatever the convar's own type is.

#cv:set( value ) → boolean

Writes the value in the convar's own type. The engine is not told the value changed: change callbacks do not run, and a convar the server controls stays what the server says. true if the write went through. For a type it cannot write it raises an error pointing at the typed setters below.

#cv:set_bool( b ), cv:set_int( n ), cv:set_float( x ) → boolean

Write the value as that type.

-- widen the viewmodel for as long as the script runs
local fov = game.cvar( "viewmodel_fov" )
local before = fov and fov:float( )

if fov then fov:set_float( 80 ) end

on( "unload", function( )
	if fov and before then fov:set_float( before ) end
end )

#Particles

#game.particle( path [, options] ) → particle | nilgame thread

Creates a particle effect from a .vpcf resource of the game - "particles/embedded/snow.vpcf", for instance - and positions it. nil if the effect could not be created.

options is an optional table: origin - a vec3 for the effect's first control point (index 0) - and points - a table { [index] = vec3 } that places further control points. What a control point means depends on the effect.

local snow

on( "move", function( cmd )
	if not snow then
		snow = game.particle( "particles/embedded/snow.vpcf", { origin = view.origin( ) } )
	end
end )

This has to run on the game thread: call it from move, stage or a game: handler. From anywhere else it raises an error. Particles a script has created are destroyed when it unloads.

#p:point( index, position ) → boolean

Moves one of the effect's control points.

#p:destroy()

Removes the effect. Game thread only; does nothing from elsewhere.

#p:alive() → boolean

Whether the effect exists - false after destroy().

Elysium scripting guide · built 2026-10-03