Elysium scripting Editor API index
Build

Players & entities

Finding players, weapons and projectiles, and reading everything about them - position, health, bones, ammo, the planted bomb, any field of the game's schema.

Everything in the world that is not the map is an entity: the players, the weapons they carry, the grenades in flight, the planted bomb. A script reaches them through entity objects - small handles with methods like health(), origin() and weapon().

for _, player in ipairs( ents.players( { enemies = true, alive = true } ) ) do
	print( player:name( ), player:health( ), player:origin( ) )
end

#Entity objects

Kinds. A player is really two entities. The controller is the player as a participant - name, Steam id, ping, money, team. The pawn is the body in the world - position, health, weapons, movement. Weapons and projectiles are entities of their own. ent:kind() says which one you hold: "controller", "pawn", "weapon", "projectile" or "other".

Methods reach through. You do not have to care which of the two you have. A method that belongs to the body - origin(), health(), weapon() - works on the controller too, because it finds the pawn for you; a method that belongs to the controller - name(), money() - works on the pawn. The lists below say what each method reads.

Handles, not pointers. An entity object remembers which entity it was made for. When that entity is gone - a player disconnected, a grenade exploded - its methods answer nil, 0 or false instead of reading whatever else moved into the same slot, and ent:valid() is false. A script can therefore keep an entity in a variable for a while without fearing it goes stale; it only has to cope with the empty answers.

Equality. a == b is true when both are the same entity.

Where you get them. From ents.* below; from game events (ev:player( "attacker" )); from the esp event, which hands you the player it is drawing; and from other entities (ent:weapon(), ent:owner()).

#Finding entities

#ents.local_player() → entity | nil

The local player's controller, or nil before you are in a game. Its body methods work too, so ents.local_player():health() is fine.

#ents.local_pawn() → entity | nil

The local player's pawn.

#ents.viewed() → entity | nil

Whose camera you are looking through: the local player's controller, or, while you are dead and spectating, the player you are watching.

#ents.players( [options] ) → list

The players' controllers, as a list. With no options that is everybody, the local player included. options filters:

FieldKeeps
enemies = trueonly players on the other team than you (in modes without teams: everybody else)
teammates = trueonly players on your team
alive = trueonly players who are alive
dead = trueonly players who are dead
include_local = falseleaves the local player out
local targets = ents.players( { enemies = true, alive = true } )

#ents.weapons( [options] ) → list

Weapons lying in the world. With { dropped = true } only those nobody carries.

#ents.projectiles() → list

Grenades in flight, smokes and fires.

#ents.by_class( name ) → list

Every entity of one class, found by walking the entity list - for example ents.by_class( "C_PlantedC4" ). The list is capped at 1024 entries. Class names are the game's own; ent:class() tells you the name of one you have.

#ents.get( index ) → entity | nil

The entity in a slot of the entity list, 0 to 16383.

#ents.from_handle( handle ) → entity | nil

The entity a handle - as ent:handle() returns it, or a handle field stored in the game - points to.

#ents.bomb() → entity | nil

The planted bomb, or nil. ent:bomb() reads its timers.

#ents.rules() → table | nil

The game rules, as { freeze_period, team_intro, round_start_time, phase }: whether the round is in its freeze period, whether the team intro is playing, the game time the round started, and the game phase as a number. nil outside a game.

#Identity and type

#ent:valid() → boolean

Whether the entity still exists.

#ent:index() → integer | nil

The entity's index in the entity list; -1 if it cannot be worked out, nil if the entity is gone.

#ent:handle() → integer

The entity's handle, for ents.from_handle. 0 when it is gone.

#ent:class() → string

The game's class name for it: "C_CSPlayerPawn", "CCSPlayerController", "C_AK47", "C_PlantedC4". An empty string when the entity is gone.

#ent:kind() → string

"controller", "pawn", "weapon", "projectile", "other", or "none" when the entity is gone.

#ent:is( class ) → boolean

Whether the entity's class is exactly class.

#ent:address() → integertrusted

Where the entity lives in memory. For mem and nothing else.

#Position and motion

#ent:origin() → vec3 | nil

The entity's position in the world. For a player it is the point between the feet.

#ent:angles() → vec3 | nil

How the body is rotated in the world - not where the player looks, see eye_angles.

#ent:eye_angles() → vec3 | nil

Where a player is looking: pitch, yaw, roll in degrees.

#ent:eye() → vec3 | nil

Where the player's eyes are: the origin plus the view offset. The point a trace to or from a player should start at.

#ent:velocity() → vec3 | nil

#ent:speed() → number

The speed in units per second, vertical movement included.

#ent:speed2d() → number

The horizontal speed - the one that matters for bunny hopping and for accuracy.

#ent:on_ground() → boolean

#ent:ducking() → boolean

#ent:duck_amount() → number

How far the player is crouched: 0 standing, 1 fully crouched.

#ent:move_type() → integer

The movement type - walking, flying, noclip, on a ladder. See ents.move_type.

#ent:flags() → integer

The entity's flag bits. ents.flags names them.

#ent:ground_entity() → entity | nil

What the player is standing on.

#ent:stamina() → number

#ent:velocity_modifier() → number

1 for normal speed; below 1 while the player is slowed, for instance after being hit.

#Players

#ent:team() → integer

The team number: 1 spectators, 2 terrorists, 3 counter-terrorists, 0 none yet.

#ent:health() → integer

#ent:armor() → integer

#ent:alive() → boolean

#ent:enemy() → boolean

Whether the entity is on the other team than the local player. In modes without teams everyone else counts as an enemy. false for an entity that is gone.

#ent:name() → string | nil

A player's name; a weapon's name ("ak47"); for anything else the class name.

#ent:steam_id() → integer

The 64-bit Steam id; 0 for bots.

#ent:ping() → integer

#ent:money() → integer

#ent:tick_base() → integer

The player's tick base - the tick their movement has been simulated up to.

#ent:pawn() → entity | nil

The body of a player, given either entity.

#ent:controller() → entity | nil

The controller of a player, given either entity.

#ent:owner() → entity | nil

The entity that holds or threw this one: the player carrying a weapon, the one who threw a grenade.

#ent:simulation_time() → number

#ent:scoped() → boolean

#ent:defusing() → boolean

#ent:walking() → boolean

Whether the game's walking flag is set - slow, quiet steps.

#ent:flashed() → number

The game's flash value: above 0 while the player is blinded.

#ent:shots_fired() → integer

#ent:has_helmet() → boolean

#ent:has_defuser() → boolean

#ent:spotted() → boolean

The game's own "spotted" flag for the player.

#ent:has_bomb() → boolean

Whether the player is carrying the bomb.

#ent:observer_target() → entity | nil

Who a spectating player is watching.

#ent:aim_punch() → vec3 | nil

The recoil punch of the local player, as the engine applies it to the view. nil for anybody else.

#Body, bones and hitboxes

#ent:bone( id ) → vec3 | nil

The world position of a bone. id is 0 to 26; ents.bone has the names - ents.bone.head, ents.bone.pelvis.

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

#ent:skeleton() → table | nil

All the bones at once: a table from bone id to position, { [0] = vec3, [1] = vec3, ... [26] = vec3 }. The keys are bone ids, so the table starts at 0.

#ent:hitboxes() → list | nil

The player's hitboxes: a list of { index, bone, group, mins, maxs, radius } - the hitbox's number, the bone it follows, its hitgroup (see ents.hitgroup), its corners relative to the bone, and its radius for capsule-shaped ones.

#ent:box() → table | nil

The rectangle the player covers on screen: { x, y, x2, y2, w, h } in pixels - top left corner, bottom right corner, size. nil when the player cannot be projected.

#ent:visible( [from] ) → boolean

Whether the player's head can be seen from the camera - or from the point from, if given. A line is traced to the head, skipping the local player's own body.

#Weapons

These methods take either a weapon or a player: given a player they answer for the weapon in their hands.

#ent:weapon() → entity | nil

The player's active weapon. Given a weapon, the weapon itself.

#ent:weapons() → list

Every weapon the player carries.

#ent:weapon_id() → integer

The weapon's item definition index. ents.weapon_id has the names.

#ent:weapon_type() → integer

Pistol, rifle, sniper, grenade - see ents.weapon_type.

#ent:weapon_name() → string

The weapon's name without the weapon_ prefix: "ak47", "awp", "knife", "c4". This is also what render.icon takes.

#ent:ammo() → integer

Rounds in the magazine.

#ent:max_ammo() → integer

The magazine size.

#ent:reserve_ammo() → integer

Rounds in reserve.

#ent:damage() → integer

The weapon's base damage per bullet.

#ent:range() → number

#ent:range_modifier() → number

The fraction of damage that remains after each 500 units - 1 means no falloff.

#ent:penetration() → number

#ent:armor_ratio() → number

#ent:headshot_multiplier() → number

#ent:cycle_time() → number

Seconds between two shots.

#ent:bullets() → integer

How many bullets one shot fires - 1 for rifles, more for shotguns.

#ent:max_speed() → number

How fast the weapon lets its owner run, for the mode - scoped or not - it is in right now.

#ent:inaccuracy() → number

The engine's current inaccuracy for the weapon - the value a shot's spread is scaled by. Asking does not disturb the weapon's own state.

#ent:spread() → number

The weapon's base spread.

#ent:is_gun() → boolean

Pistols, SMGs, rifles, shotguns, snipers and machine guns.

#ent:is_grenade() → boolean

#ent:is_knife() → boolean

#ent:reloading() → boolean

#ent:recoil_index() → number

#ent:accuracy_penalty() → number

#ent:last_shot_time() → number

The game time of the weapon's last shot.

#ent:next_primary_tick() → integer

The tick the primary attack is next allowed on.

#ent:next_secondary_tick() → integer

#ent:next_attack() → number

The game time at which the player may attack again - for a player, not a weapon. Compare it with game.curtime().

local me     = ents.local_pawn( )
local weapon = me and me:weapon( )

if weapon and weapon:is_gun( ) then
	print( weapon:weapon_name( ), weapon:ammo( ) .. "/" .. weapon:max_ammo( ) )
end

#The planted bomb

#ent:bomb() → table | nil

For the planted bomb entity - see ents.bomb() - its state as a table; nil for any other entity.

FieldMeaning
blow_timeThe game time it explodes.
timer_lengthHow long the bomb timer runs in total.
defuse_timeThe game time a defuse in progress finishes.
next_beepThe game time of the next beep.
defusingWhether someone is defusing it.
defusedWhether it has been defused.
explodedWhether it has exploded.
siteThe bombsite, as a number.
local bomb = ents.bomb( )
local state = bomb and bomb:bomb( )

if state and not state.defused and not state.exploded then
	local seconds_left = state.blow_time - game.curtime( )
end

#Reading any field

The game describes every field of every entity class in a schema, and a script can read - and, carefully, write - any of them by name. These are the escape hatch for what the methods above do not cover.

#ent:prop( class, field, type [, byte_offset] ) → value | nil, message

Reads a field.

  • class - the class that declares the field, as the game names it: "C_BaseEntity".
  • field - the field: "m_iHealth".
  • type - how to read it. See the table below.
  • byte_offset - added to the address, to index into arrays and embedded structures.

Answers nil for an entity that is gone or memory that cannot be read, and nil plus a message when the game has no such field or the type is unknown.

local health = ents.local_pawn( ):prop( "C_BaseEntity", "m_iHealth", "i32" )
typeRead as
"bool"one byte, as a boolean
"i8", "u8", "i16", "u16", "i32" (or "int"), "u32", "i64", "u64"an integer of that size
"f32" ("float"), "f64" ("double")a number
"vec2", "vec3" ("angles")a vector
"color"four bytes as a colour
"handle" ("entity")an entity handle, as the entity it refers to
"ptr"a pointer, as an integer
"string"a pointer to text, read as a string

#ent:set_prop( class, field, type, value [, byte_offset] ) → boolean

Writes a field; true if it was written. Writing works for bool, the integer and float types, vec3, color and ptr. A write goes straight into the game's memory - the client's copy, which the server does not see - so it is for visual and client-side changes.

#ent:prop_entity( class, field ) → entity | nil

A handle field, resolved to the entity it points to.

#ents.offset( class, field ) → integer | nil

Where a field sits inside its class, in bytes; nil when the game has no such field. Offsets are looked up once and remembered.

#Constants

Tables of names to numbers. Use the names - the numbers are the game's and can change.

ents.boneents.hitgroup
pelvis1generic0
spine_12head1
spine_23chest2
spine_34stomach3
spine_423left_arm4
neck6right_arm5
head7left_leg6
left_clavicle, left_shoulder, left_elbow, left_hand8, 9, 10, 11right_leg7
right_clavicle, right_shoulder, right_elbow, right_hand12, 13, 14, 15neck8
left_hip, left_knee, left_foot17, 18, 19gear10
right_hip, right_knee, right_foot20, 21, 22
ents.weapon_typeents.flagsents.move_type
knife0on_ground1none0
pistol1ducking2walk2
smg2water_jump8fly3
rifle3on_train16fly_gravity4
shotgun4frozen64vphysics5
sniper5fake_client512noclip7
lmg6in_water1024observer8
c47ladder9
taser8
grenade9
equipment10
healthshot11

The flags are bits: test one with bits.has( value, mask ).

#ents.weapon_id

Item definition indices by name:

GroupNames and numbers
Pistolsdeagle 1, elite 2, fiveseven 3, glock 4, p2000 32, p250 36, tec9 30, usp_s 61, cz75 63, revolver 64
Riflesak47 7, aug 8, famas 10, galil 13, m4a4 16, m4a1_s 60, sg553 39
Snipersawp 9, g3sg1 11, scar20 38, ssg08 40
SMGsmac10 17, mp5sd 23, mp7 33, mp9 34, p90 19, bizon 26, ump45 24
Machine guns and shotgunsm249 14, negev 28, xm1014 25, mag7 27, sawedoff 29, nova 35
Grenades and gearflashbang 43, he_grenade 44, smoke 45, molotov 46, decoy 47, incendiary 48, c4 49, healthshot 57, zeus 31
Knivesknife_ct 41, knife_t 42, bayonet 500, karambit 507
local weapon = ents.local_pawn( ):weapon( )

if weapon and weapon:weapon_id( ) == ents.weapon_id.awp then
	-- sniping
end
Elysium scripting guide · built 2026-10-03