Elysium scripting Editor API index
Build

Traces & damage

Ask the map questions - what is in the way, can this point see that one, what does a bullet do to a wall.

The world module answers questions about geometry. It does not list entities - that is ents - it tells you what a line, a box or a bullet would run into between two points.

on( "frame", function( canvas )
	local me = ents.local_pawn( )
	if not me then return end

	local from   = me:eye( )
	local result = world.trace( from, from + me:eye_angles( ):forward( ) * 4096 )

	if result.hit then
		print( string.format( "something %.0f units ahead", result.fraction * 4096 ) )
	end
end )

#Rays, boxes and balls

#world.trace( from, to [, options] ) → result

Sends a ray from from to to and reports what it hits first. from and to are vec3 points in the world.

options is an optional table:

FieldMeaningDefault
skipAn entity the ray passes through - or false to skip nothing.the local player's pawn
maskWhat the ray collides with, as the engine's bit mask.world.mask.visible
layerThe collision layer the trace is made on, 0 to 255.4
mins, maxsTwo vec3s: sweeps a box with those corners along the ray instead of a thin line. Both are needed.none
radiusSweeps a ball of that radius along the ray. Wins over mins and maxs.none

The result is a table:

FieldMeaning
fractionHow far along the ray it got before hitting something: 0 right at from, 1 all the way to to.
hittrue when something was hit - that is, when fraction is below 1.
start_solidtrue when the ray started inside something solid.
posWhere the ray ended: the hit point, or to when it hit nothing.
normalThe direction the surface it hit faces.
entityThe entity it hit, or nil for the map itself.
contentsThe engine's contents bits of what it hit.
-- is there a ceiling above my head?
local me   = ents.local_pawn( )
local head = me:eye( )
local up   = world.trace( head, head + vec3( 0, 0, 72 ) )

if up.hit then
	print( "room for", math.floor( up.fraction * 72 ), "units" )
end

#world.visible( from, to [, target [, skip]] ) → boolean

Whether the ray from from to to arrives unobstructed. target is an entity: if the ray is stopped by it, the end point still counts as visible - what you want when to is a point inside a player, such as the head. skip is the entity the ray passes through, the local player's pawn by default.

local head = player:bone( ents.bone.head )

if world.visible( me:eye( ), head, player ) then
	-- a clear line from my eyes to their head
end

ent:visible() is this call for the common case.

#world.mask

Two ready-made collision masks to pass as mask:

world.mask.visibleWhat visibility checks collide with. The default of world.trace.
world.mask.bulletWhat bullets collide with.

Masks are the engine's own bit sets; these are the two the cheat itself traces with. Anything else you pass is handed to the engine as it is.

#Bullets and walls

A bullet that meets a wall is not simply stopped: it loses damage, it may come out on the other side with some left, and what it does depends on the material. The cheat uses the engine's own routine to work this out, and world.bullet gives a script the same answer.

#world.bullet( from, direction [, options] ) → table | nil

Runs the engine's bullet simulation from from along direction with the data of a weapon, and reports what the walls do to the bullet.

  • from - a vec3, where the bullet starts. For the muzzle use me:eye().
  • direction - a vec3 pointing the way the bullet flies. It does not have to be normalised. To go from view angles, use angles:forward().
  • options.weapon - a weapon entity whose damage, penetration and range are used. By default the weapon the local player holds.

The result:

FieldMeaning
damageThe damage left after the last surface the bullet got through, before the hitgroup multiplier. world.damage applies that.
penetratedtrue if the bullet went through at least one surface.
surfacesHow many surfaces it went through.
contactsA list, in order, of everything it met: { distance, damage, penetrated } - how far from from the contact is, the damage the bullet had there, and whether it got through.

nil when the simulation cannot run: the weapon cannot penetrate (a knife, a grenade), the weapon's data is not available, or the engine's routines were not found.

on( "frame", function( canvas )
	local me = ents.local_pawn( )
	if not me or not me:weapon( ) then return end

	local eye = me:eye( )
	local hit = world.bullet( eye, me:eye_angles( ):forward( ) )

	if hit then
		local width, height = canvas:screen( )

		canvas:text( width / 2 + 12, height / 2, string.format( "%d dmg after %d wall(s)", math.floor( hit.damage + 0.5 ), hit.surfaces ),
			color( 255, 255, 255 ), { shadow = true } )
	end
end )

#world.damage( hitgroup [, options] ) → number

What the local player's current weapon does to a player at full strength - no walls, no distance - for a hitgroup, after armour and the server's damage scales. hitgroup is a number from ents.hitgroup.

options:

FieldMeaningDefault
armorThe target's armour.0
helmetWhether the target wears a helmet.false
teamThe target's team: 2 terrorists, 3 counter-terrorists. The damage scales differ by team.2

Combine the two calls for an expected damage: the bullet's remaining damage is the weapon's damage after the walls, and world.damage is the weapon's damage at full strength, so their ratio is the share that survives.

local full   = world.damage( ents.hitgroup.head, { armor = 100, helmet = true, team = 3 } )
local behind = world.bullet( eye, direction )

if behind then
	local share = behind.damage / weapon:damage( )
	print( string.format( "a headshot through that wall would do about %d", full * share ) )
end
Elysium scripting guide · built 2026-10-03