#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.
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( ) )
endKinds. 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()).
ents.local_player() → entity | nilThe 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 | nilThe local player's pawn.
ents.viewed() → entity | nilWhose 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] ) → listThe players' controllers, as a list. With no options that is everybody, the local player included. options filters:
| Field | Keeps |
|---|---|
enemies = true | only players on the other team than you (in modes without teams: everybody else) |
teammates = true | only players on your team |
alive = true | only players who are alive |
dead = true | only players who are dead |
include_local = false | leaves the local player out |
local targets = ents.players( { enemies = true, alive = true } )ents.weapons( [options] ) → listWeapons lying in the world. With { dropped = true } only those nobody carries.
ents.projectiles() → listGrenades in flight, smokes and fires.
ents.by_class( name ) → listEvery 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 | nilThe entity in a slot of the entity list, 0 to 16383.
ents.from_handle( handle ) → entity | nilThe entity a handle - as ent:handle() returns it, or a handle field stored in the game - points to.
ents.bomb() → entity | nilThe planted bomb, or nil. ent:bomb() reads its timers.
ents.rules() → table | nilThe 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.
ent:valid() → booleanWhether the entity still exists.
ent:index() → integer | nilThe entity's index in the entity list; -1 if it cannot be worked out, nil if the entity is gone.
ent:handle() → integerThe entity's handle, for ents.from_handle. 0 when it is gone.
ent:class() → stringThe 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 ) → booleanWhether the entity's class is exactly class.
ent:address() → integertrustedWhere the entity lives in memory. For mem and nothing else.
ent:origin() → vec3 | nilThe entity's position in the world. For a player it is the point between the feet.
ent:angles() → vec3 | nilHow the body is rotated in the world - not where the player looks, see eye_angles.
ent:eye_angles() → vec3 | nilWhere a player is looking: pitch, yaw, roll in degrees.
ent:eye() → vec3 | nilWhere 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 | nilent:speed() → numberThe speed in units per second, vertical movement included.
ent:speed2d() → numberThe horizontal speed - the one that matters for bunny hopping and for accuracy.
ent:on_ground() → booleanent:ducking() → booleanent:duck_amount() → numberHow far the player is crouched: 0 standing, 1 fully crouched.
ent:move_type() → integerThe movement type - walking, flying, noclip, on a ladder. See ents.move_type.
ent:flags() → integerThe entity's flag bits. ents.flags names them.
ent:ground_entity() → entity | nilWhat the player is standing on.
ent:stamina() → numberent:velocity_modifier() → number1 for normal speed; below 1 while the player is slowed, for instance after being hit.
ent:team() → integerThe team number: 1 spectators, 2 terrorists, 3 counter-terrorists, 0 none yet.
ent:health() → integerent:armor() → integerent:alive() → booleanent:enemy() → booleanWhether 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 | nilA player's name; a weapon's name ("ak47"); for anything else the class name.
ent:steam_id() → integerThe 64-bit Steam id; 0 for bots.
ent:ping() → integerent:money() → integerent:tick_base() → integerThe player's tick base - the tick their movement has been simulated up to.
ent:pawn() → entity | nilThe body of a player, given either entity.
ent:controller() → entity | nilThe controller of a player, given either entity.
ent:owner() → entity | nilThe entity that holds or threw this one: the player carrying a weapon, the one who threw a grenade.
ent:simulation_time() → numberent:scoped() → booleanent:defusing() → booleanent:walking() → booleanWhether the game's walking flag is set - slow, quiet steps.
ent:flashed() → numberThe game's flash value: above 0 while the player is blinded.
ent:shots_fired() → integerent:has_helmet() → booleanent:has_defuser() → booleanent:spotted() → booleanThe game's own "spotted" flag for the player.
ent:has_bomb() → booleanWhether the player is carrying the bomb.
ent:observer_target() → entity | nilWho a spectating player is watching.
ent:aim_punch() → vec3 | nilThe recoil punch of the local player, as the engine applies it to the view. nil for anybody else.
ent:bone( id ) → vec3 | nilThe 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 | nilAll 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 | nilThe 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 | nilThe 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] ) → booleanWhether 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.
These methods take either a weapon or a player: given a player they answer for the weapon in their hands.
ent:weapon() → entity | nilThe player's active weapon. Given a weapon, the weapon itself.
ent:weapons() → listEvery weapon the player carries.
ent:weapon_id() → integerThe weapon's item definition index. ents.weapon_id has the names.
ent:weapon_type() → integerPistol, rifle, sniper, grenade - see ents.weapon_type.
ent:weapon_name() → stringThe weapon's name without the weapon_ prefix: "ak47", "awp", "knife", "c4". This is also what render.icon takes.
ent:ammo() → integerRounds in the magazine.
ent:max_ammo() → integerThe magazine size.
ent:reserve_ammo() → integerRounds in reserve.
ent:damage() → integerThe weapon's base damage per bullet.
ent:range() → numberent:range_modifier() → numberThe fraction of damage that remains after each 500 units - 1 means no falloff.
ent:penetration() → numberent:armor_ratio() → numberent:headshot_multiplier() → numberent:cycle_time() → numberSeconds between two shots.
ent:bullets() → integerHow many bullets one shot fires - 1 for rifles, more for shotguns.
ent:max_speed() → numberHow fast the weapon lets its owner run, for the mode - scoped or not - it is in right now.
ent:inaccuracy() → numberThe 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() → numberThe weapon's base spread.
ent:is_gun() → booleanPistols, SMGs, rifles, shotguns, snipers and machine guns.
ent:is_grenade() → booleanent:is_knife() → booleanent:reloading() → booleanent:recoil_index() → numberent:accuracy_penalty() → numberent:last_shot_time() → numberThe game time of the weapon's last shot.
ent:next_primary_tick() → integerThe tick the primary attack is next allowed on.
ent:next_secondary_tick() → integerent:next_attack() → numberThe 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( ) )
endent:bomb() → table | nilFor the planted bomb entity - see ents.bomb() - its state as a table; nil for any other entity.
| Field | Meaning |
|---|---|
blow_time | The game time it explodes. |
timer_length | How long the bomb timer runs in total. |
defuse_time | The game time a defuse in progress finishes. |
next_beep | The game time of the next beep. |
defusing | Whether someone is defusing it. |
defused | Whether it has been defused. |
exploded | Whether it has exploded. |
site | The 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( )
endThe 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, messageReads 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" )type | Read 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] ) → booleanWrites 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 | nilA handle field, resolved to the entity it points to.
ents.offset( class, field ) → integer | nilWhere a field sits inside its class, in bytes; nil when the game has no such field. Offsets are looked up once and remembered.
Tables of names to numbers. Use the names - the numbers are the game's and can change.
ents.bone | ents.hitgroup | ||
|---|---|---|---|
pelvis | 1 | generic | 0 |
spine_1 | 2 | head | 1 |
spine_2 | 3 | chest | 2 |
spine_3 | 4 | stomach | 3 |
spine_4 | 23 | left_arm | 4 |
neck | 6 | right_arm | 5 |
head | 7 | left_leg | 6 |
left_clavicle, left_shoulder, left_elbow, left_hand | 8, 9, 10, 11 | right_leg | 7 |
right_clavicle, right_shoulder, right_elbow, right_hand | 12, 13, 14, 15 | neck | 8 |
left_hip, left_knee, left_foot | 17, 18, 19 | gear | 10 |
right_hip, right_knee, right_foot | 20, 21, 22 |
ents.weapon_type | ents.flags | ents.move_type | |||
|---|---|---|---|---|---|
knife | 0 | on_ground | 1 | none | 0 |
pistol | 1 | ducking | 2 | walk | 2 |
smg | 2 | water_jump | 8 | fly | 3 |
rifle | 3 | on_train | 16 | fly_gravity | 4 |
shotgun | 4 | frozen | 64 | vphysics | 5 |
sniper | 5 | fake_client | 512 | noclip | 7 |
lmg | 6 | in_water | 1024 | observer | 8 |
c4 | 7 | ladder | 9 | ||
taser | 8 | ||||
grenade | 9 | ||||
equipment | 10 | ||||
healthshot | 11 |
The flags are bits: test one with bits.has( value, mask ).
ents.weapon_idItem definition indices by name:
| Group | Names and numbers |
|---|---|
| Pistols | deagle 1, elite 2, fiveseven 3, glock 4, p2000 32, p250 36, tec9 30, usp_s 61, cz75 63, revolver 64 |
| Rifles | ak47 7, aug 8, famas 10, galil 13, m4a4 16, m4a1_s 60, sg553 39 |
| Snipers | awp 9, g3sg1 11, scar20 38, ssg08 40 |
| SMGs | mac10 17, mp5sd 23, mp7 33, mp9 34, p90 19, bizon 26, ump45 24 |
| Machine guns and shotguns | m249 14, negev 28, xm1014 25, mag7 27, sawedoff 29, nova 35 |
| Grenades and gear | flashbang 43, he_grenade 44, smoke 45, molotov 46, decoy 47, incendiary 48, c4 49, healthshot 57, zeus 31 |
| Knives | knife_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