Elysium scripting Editor API index
Start

Your first script

From an empty file to a script with a menu, a saved setting and a reaction to the game - in about ten minutes.

You need nothing but a text editor. Every step below is something you can see working in the game before you move on to the next.

  1. Make the file. Open C:\elysium\scripts - the folder is created the first time the cheat starts, and the open folder button in the Scripts tab opens it for you. Create a file called hello.lua. The name is the script's name everywhere: in the list, in its saved settings, in its own folder.
  2. Put something in it.

    hello.lua
    print( "hello from lua" )
    
    on( "frame", function( canvas )
    	canvas:text( 20, 20, "hello", color( 255, 255, 255 ) )
    end )
  3. Load it. Open the menu and go to the Scripts tab. Scripts are read when the cheat starts; a file added later shows up after rescan. Click the row of hello to select it - the right half of the tab shows its controls, and the panel under the list shows its output: hello from lua. The word hello is now drawn in the top left corner of your screen.
  4. Change it, reload it. Edit the text in the file, save, and press reload with hello selected. The state of the script is thrown away and the file is read again. That loop - save, reload, look - is the whole workflow.

#What those lines did

print( ... ) wrote to the output panel in the Scripts tab (and the console). The game has no console of its own that a script could write to, so this panel is where a script talks to you.

on( "frame", handler ) told the cheat: call this function every time a frame is drawn. frame is one of a dozen events. The handler receives a canvas - the thing you draw with. It is only valid while the handler runs; do not keep it.

canvas:text( x, y, text, color ) draws a line of text. color( 255, 255, 255 ) makes a white colour; the fourth number, alpha, is optional.

Controls live in groups, and groups show up in the right half of the Scripts tab. Replace the file's content with this:

hello.lua
local group = ui.group( "hello" )

local enabled = group:toggle( "enabled", true )
local size    = group:slider( "text size", 10, 40, 18, { step = 1 } )
local tint    = group:color( "colour", color( 168, 85, 247 ) )

-- A font is built once per size and then reused.
local fonts = { }

local function font_for( px )
	if fonts[ px ] == nil then
		fonts[ px ] = render.font( "Segoe UI", px ) or false
	end

	return fonts[ px ]
end

on( "frame", function( canvas )
	if not enabled:get( ) then
		return
	end

	local options = { font = font_for( size:get( ) ) or nil, shadow = true }

	canvas:text( 20, 20, "hello from lua", tint:get( ), options )
end )

Reload. The right half now has a toggle, a slider and a colour picker. Move them - the text follows at once. Reload the script again, or restart the game: the controls come back with the values you left. They are written to C:\elysium\scripts\.data\hello.values.json a moment after you change something, keyed by the group's title and the control's label.

Three ideas are in that file:

#React to the game

The game announces things - a player was hurt, a round started, a bomb was planted - and a script can listen to any of them by putting game: in front of the event's name. Add this to the end of the file:

on( "game:player_hurt", function( ev )
	local victim = ev:player( "userid" )

	if victim then
		ui.notify( victim:name( ) .. " took " .. ev:int( "dmg_health" ) .. " damage" )
	end
end )

The ev object reads the event's fields by name: ev:int( "dmg_health" ) is a number, ev:player( "userid" ) is the player the field points to, as an entity. ui.notify puts a toast in the corner of the screen. Hurt someone in a game and watch it appear.

#When something goes wrong

Break the script on purpose: change canvas:text in the first handler to canvas:txt, save and reload. The script's row turns red and says error, and the output panel shows what happened and where:

[hello] error in frame: hello.lua:12: attempt to call a nil value (method 'txt')
stack traceback:
	hello.lua:12: in function <hello.lua:10>

A script that raises an error is stopped - all of it, not only the handler - and stays stopped until you reload it. This is deliberate: a handler that fails once per frame would fill the output with thousands of copies of the same error. Fix the typo, press reload, and it runs again.

The other thing that stops a script is time. A handler that takes longer than about 30 ms is interrupted with script ran past its time budget. The game waits while a script runs, so a handler that needs more than a millisecond or two every frame is worth looking at. How scripts run has the details.

#Where to go from here

Elysium scripting guide · built 2026-10-03