game
A read-only copy of the match for this frame: all players, the local player, and the projection of a world point onto the screen.
game hands you a copy of public game state. We make the copy once for each frame, from the engine's own entity list. Every call builds fresh tables, so you can change what you got and nothing else will see the change.
Slots
A player is identified by a slot, a whole number from 1 to 64. The same number is used everywhere:
indexingame.players()- the argument of
entity.get(slot)and the result ofent:index() - the fields
userid,attackerandassisterof game events - the first argument of
resolver.set_yaw(slot, degrees)
In an event, slot 0 means nobody, or the world.
Outside a match, game.in_game() is false, game.players() returns an empty table and game.local_player() returns nil.
Positions are in game units. The origin of a player is at the feet.
Functions
game.in_game
game.in_game() -> boolean
Returns true while the client has a local player in a match, false otherwise.
Errors none.
events.on_paint(function()
if not game.in_game() then return end
draw.text(20, 20, "in a match", 255, 255, 255)
end)
game.local_player
game.local_player() -> table or nil
game["local"]() -> table or nil
Returns a table with the fields below, or nil when you are not in a match or the local player has no body yet.
| field | type | meaning |
|---|---|---|
alive | boolean | true if the local player is alive |
health | integer | 0 to 100000 |
armor | integer | 0 to 100000 |
team | integer | the team number the game uses; players with the same number are teammates |
x, y, z | number | position of the origin |
vx, vy, vz | number | velocity in units per second |
Notes game["local"] is the same function. The word local is a Lua keyword, so game.local() is a syntax error and the bracket form is the way to write it. game.local_player is the name for plain dot syntax. This table has no index, name or angles. Use entity.local_player() when you need them.
events.on_paint(function()
local me = game.local_player()
if not me or not me.alive then return end
draw.text(20, 300, string.format("health %d armor %d", me.health, me.armor), 255, 255, 255)
end)
game.players
game.players() -> array of player tables
Returns an array with one table for every player the engine lists, at most 64, in order of slot. The local player is in the list. Dead players are in the list too.
| field | type | meaning |
|---|---|---|
index | integer | the slot, 1 to 64 |
name | string | at most 32 bytes. Control characters are removed and invalid UTF-8 bytes become ?. |
team | integer | the team number the game uses |
alive | boolean | |
health | integer | 0 to 100000 |
x, y, z | number | position of the origin, at the feet |
yaw | number | the eye yaw the game sends to every client, in degrees, wrapped to -180 to 180 |
pitch | number | the eye pitch in degrees, -180 to 180. Positive looks down. |
vx, vy, vz | number | velocity in units per second, each limited to -32768 to 32768 |
on_ground | boolean | the on-ground flag of the player |
ducking | boolean | the ducking flag of the player |
sim_time | number | the simulation time of the player in seconds. It is 0 when the engine gives no usable value. |
Notes For a player that is not alive, the last eight fields (yaw to sim_time) are 0 or false. The position of a dead player has no meaning you should rely on. To find the local player in the list, compare index with entity.local_player():index().
Cost 100 instructions plus 180 for every player. Call it once for each frame and keep the result.
events.on_paint(function()
local y = 320
for _, p in ipairs(game.players()) do
if p.alive then
draw.text(20, y, string.format("%d %s %d", p.index, p.name, p.health), 220, 220, 220, 255, "small")
y = y + 13
end
end
end)
game.to_screen
game.to_screen(x, y, z) -> sx, sy or nil
| argument | type | meaning |
|---|---|---|
x, y, z | number | a point in the world |
Returns the pixel position of the point on the screen, in the same coordinates draw uses and screen.size() measures. The values are limited to -16384 to 16384. Returns a single nil when the point is behind the camera, when there is no camera, or when a coordinate is outside -1e6 to 1e6.
Errors a type error if an argument is not a number. NaN and infinity raise finite number expected.
Notes The result is for the current frame. A point that is on the screen can still be outside the visible area, so check it against screen.size() if you need to.
events.on_paint(function()
for _, p in ipairs(game.players()) do
if p.alive then
local sx, sy = game.to_screen(p.x, p.y, p.z + 72)
if sx then draw.circle_filled(sx, sy, 3, 255, 80, 80) end
end
end
end)