starlit

entity

Handles for players, the methods that read them, and the properties that ent:get can return.

entity gives you a handle for a player and methods to read it. A handle is a small object, not a table. Everything it can tell you comes from the game state of the current frame.

Handles

A handle is good for the frame it was made in. In a later frame it is stale: ent:valid() is false, the flag methods return false, and the data methods return nil. This is on purpose. A slot can be taken over by another player between two frames, and an old handle must never show the new player's data.

Keep the slot between frames and ask for a new handle each frame:

local watched = nil -- a slot, not a handle

events.on_paint(function()
  local ent = watched and entity.get(watched)
  if ent and ent:is_alive() then
    draw.text(20, 400, ent:name() .. ": " .. ent:get("health"), 255, 255, 255)
  end
end)

Three more rules:

  • Methods are called with a colon: ent:origin().
  • A handle is read-only. Assigning a field raises handle is read-only.
  • A method called on something that is not an entity handle of your script, a control handle for example, raises invalid handle.

Functions

entity.get

entity.get(slot) -> handle or nil
argumenttypemeaning
slotnumberan exact whole number from 1 to 64

Returns a handle if a player with that slot is in this frame's snapshot, otherwise nil. A value that is not a valid slot, such as 0, 65, 2.5, "2" or NaN, gives nil and no error.

Errors calling it with no argument raises number expected.

events.on_paint(function()
  local ent = entity.get(2)
  if ent then draw.text(20, 20, ent:name(), 255, 255, 255) end
end)

entity.local_player

entity.local_player() -> handle or nil

Returns the handle of the local player, or nil when you are not in a match.

events.on_paint(function()
  local me = entity.local_player()
  if me then draw.text(20, 20, "my slot is " .. me:index(), 255, 255, 255) end
end)

entity.players

entity.players([enemies_only [, include_dead]]) -> array of handles
argumenttypedefaultmeaning
enemies_onlybooleanfalseonly players the ragebot would treat as enemies
include_deadbooleanfalsealso players that are not alive

Returns an array of at most 64 handles, in order of slot. Without arguments you get every living player, the local player included.

An enemy is a player on another team than the local player. When the server runs with mp_teammates_are_enemies every player but you is an enemy. The local player is never an enemy.

Errors an argument that is neither nil nor a boolean raises a type error.

Cost 100 instructions plus 60 for every player.

events.on_paint(function()
  local y = 20
  for _, ent in ipairs(entity.players(true)) do
    draw.text(20, y, ent:name(), 255, 255, 255, 255, "small")
    y = y + 13
  end
end)

Handle methods

All methods cost 20 instructions, except where noted.

ent:index

ent:index() -> integer

Returns the slot of the player. This works on a stale handle too, because a slot is only a number.

local function slot_of(ent) return ent:index() end

ent:valid

ent:valid() -> boolean

Returns true while the handle is from this frame and the player is still in the snapshot.

local function usable(ent) return ent:valid() and ent:is_alive() end

ent:is_alive

ent:is_alive() -> boolean

Returns true if the player is alive. false for a dead player and for a stale handle.

local function count_alive()
  local n = 0
  for _, ent in ipairs(entity.players(false, true)) do
    if ent:is_alive() then n = n + 1 end
  end
  return n
end

ent:is_enemy

ent:is_enemy() -> boolean

Returns true if the player is an enemy, by the rule given under entity.players. The local player is never an enemy. false for a stale handle.

local function is_foe(ent) return ent:is_enemy() and ent:is_alive() end

ent:is_local

ent:is_local() -> boolean

Returns true if the handle is the local player.

local function is_me(ent) return ent:is_local() end

ent:name

ent:name() -> string or nil

Returns the player's name, at most 32 bytes, cleaned as described for game.players(). nil for a stale handle.

local function label(ent) return ent:name() or "?" end

ent:origin

ent:origin() -> x, y, z or nil

Returns the position of the origin, at the feet, in game units. A single nil for a stale handle.

local function feet(ent)
  local x, y, z = ent:origin()
  if not x then return nil end
  return vec3(x, y, z)
end

ent:velocity

ent:velocity() -> vx, vy, vz or nil

Returns velocity in units per second, each component limited to -32768 to 32768. A dead player has zeros. A single nil for a stale handle.

local function planar_speed(ent)
  local vx, vy = ent:velocity()
  if not vx then return 0 end
  return math.sqrt(vx * vx + vy * vy)
end

ent:eye_angles

ent:eye_angles() -> pitch, yaw or nil

Returns the eye angles in degrees, wrapped to -180 to 180. Positive pitch looks down. A dead player has zeros. A single nil for a stale handle.

local function facing(ent)
  local _, yaw = ent:eye_angles()
  return yaw
end

ent:eye_position

ent:eye_position() -> x, y, z or nil

Returns the position of the eyes: the origin, raised by the view height the engine reports. nil for a stale handle, for a dead player, when the engine value is not available, and when the script has used its 512 engine reads for this frame.

Cost 60 instructions, and one of the 512 engine reads.

local function head_point(ent)
  local x, y, z = ent:eye_position()
  if not x then return nil end
  return game.to_screen(x, y, z)
end

ent:get

ent:get(name) -> number, boolean or nil
argumenttypemeaning
namestringone of the property names in the table below

Returns the value of the property, or nil when the name is not on the list, when the property needs a living player and the player is dead, when it is local-only and the player is somebody else, when the engine value is not available, when the handle is stale, or when the 512 engine reads of this frame are used up. A name that is not on the list is never repeated in a message.

Errors a name that is not a string raises string expected.

Cost 40 instructions, and 60 more for a property that is read from the engine.

local function hp(ent) return ent:get("health") or 0 end

Properties of ent:get

The values come from the frame snapshot, or from a guarded read of the engine. The ranges are what we clamp to.

nametyperangefornotes
healthinteger0 to 100000any player
teaminteger0 to 255any player
alivebooleanany player
speednumber0 to 65536any playerspeed on the ground plane, from the x and y velocity. 0 for a dead player.
on_groundbooleanany playerfalse for a dead player
duckingbooleanany playerfalse for a dead player
sim_timenumber0 and upany playersimulation time in seconds. 0 for a dead player.
armorinteger0 to 1000living players
moneyinteger0 to 65535any player
pinginteger0 to 5000any player
helmetbooleanliving players
defuserbooleanliving players
scopedbooleanliving players
defusingbooleanliving players
shots_firedinteger0 to 1000local player, alivenil for every other player
weaponinteger0 to 65535living playersthe game's item definition number of the active weapon, 0 for none
clipinteger-1 to 1000living playersrounds in the magazine of the active weapon. -1 usually means the weapon has no magazine.
reloadingbooleanliving players

The first seven properties come from the frame snapshot and cost nothing extra. The rest are read from the engine when you ask, and each read counts against the 512 engine reads a script may make in one frame.

previous: game · next: events