Entity Properties
Needs the internal running and needs_internal = true in script_info.
p:get_property("m_FieldName" [, rate_ms]) -> integer | number | boolean | vec3 | string | raw_struct | raw_array | nil
row:get("m_FieldName" [, rate_ms]) -> integer | number | boolean | vec3 | string | raw_struct | raw_array | nilReads one game field by name from a player's entity or from a row returned by entities.by_class. The value comes back with the type the game declares for it.
| Declared type | Lua value |
|---|---|
int8 to int64, uint8 to uint64, GameTick_t, CUtlStringToken, Color | integer |
float32, float64, GameTime_t | number |
bool | boolean |
Vector, VectorWS, QAngle, Vector2D, Vector4D, Quaternion | vec3, the first three components |
CHandle<...>, CEntityHandle, CBaseHandle | integer, the raw handle. Its entity index is handle & 0x7FFF |
Enums come back as integers. CUtlString and CUtlSymbolLarge come back as strings, a CUtlVector as a raw_array, and an embedded class or pointer as a raw_struct, the same as Schema Fields.
Fields known to work: m_iHealth, m_iMaxHealth, m_iTeamNum, m_flSimulationTime, m_bTakesDamage, m_vecAbsVelocity, m_hOwnerEntity, m_nLevel, m_lifeState, m_flCreateTime.
p:get_property("m_iMaxHealth") and p:get_max_health() read different fields and can return different values.
Returns nil when
- the internal is not running, or the flag is missing
- it is the first call for that (entity, field). The first call registers it, and a later call gets the value
- the class has no such field (logged once)
- the entity is stale (logged once)
- the type is unsupported (logged once)
- 128 pairs are already registered across all scripts
Limits
- 128 (entity, field) pairs across all scripts.
- Values refresh within 250 ms by default, so poll every few ticks rather than every tick. Pass
rate_ms(25 to 2000) as the last argument to refresh one field faster. See Refresh rates. - A pair nobody asked for in 10 seconds is dropped.
- Field names up to 63 characters.
- Keep calling
entities.by_classevery tick. A class nobody asked for in 2 seconds is dropped, and then you get no rows.
To read any field the game declares, including strings, lists and nested objects, and to write scalar fields back, see Schema Fields.
Cheaper external reads that need no flag: p:get_level(), row.health, row.max_health, row.team, and p:get_ability_points(slot) for an ability's upgrade tier on any player.
Example
How long each nearby enemy trooper has been alive. my_team, max_m and COL are set earlier in the script:
local rows = entities.by_class("npc_trooper")
if rows then
for _, e in ipairs(rows) do
if e.team ~= my_team and e.distance_m <= max_m then
draw.text3d(e.position, string.format("%d/%d %.0fm", e.health, e.max_health, e.distance_m), COL)
local ct = e:get("m_flCreateTime")
if ct then
-- game.server_time() is "now" on the same clock as m_flCreateTime
draw.text3d(vec3(e.x, e.y, e.z + 24), string.format("age %.0fs", game.server_time() - ct), COL)
end
end
end
endThe player form:
local me = local_player()
local vel = me and me:get_property("m_vecAbsVelocity") -- vec3, nil on the first call
if vel then draw.text(40, 300, string.format("%.0f u/s", vel:length()), 0xFFFFFFFF) end