Skip to main content

Entity

Fields and description

We group everything from player to pet, projectile to pickup item under the class Entity. This type acts as a proxy between the native entity list and the scripting framework and the values are essentially handles.

The entity class has the following members.

-- Handle details
--
bool Entity.isValid -- False if dangling handle
bool Entity.isStale -- True if it has stale data (See #Events.)
any? Entity.extension -- Additional game specific information if relevant

-- Basic entity information
--
EntityType Entity.type -- Type enum
EntitySubType Entity.subtype -- Subtype enum
EntityTeam Entity.team -- Team enum
string Entity.name -- Class name (e.g. Hero/champion/item name)

float Entity.health -- Health points
float Entity.armor -- Armor units
float Entity.shield -- Shield units
float Entity.barrier -- Barrier units
float Entity.maxHealth -- Max health points
float Entity.maxArmor -- Max armor units if armor equipped, or 0 if N/A.
float Entity.maxShield -- Max shield units if shield equipped, or 0 if N/A.
float Entity.maxBarrier -- Max barrier units if barrier equipped, or 0 if N/A.

vec4 Entity.healthTuple -- Health as tuple of 'vec4(Health, Armor, Shield, Barrier)'
vec4 Entity.maxHealthTuple -- Max health as tuple of 'vec4(MaxHealth, MaxArmor, MaxShield, MaxBarrier)'

float Entity.effectiveHealth -- Effective health including any protection
float Entity.effectiveMaxHealth -- Effective max health including any protection
float Entity.effectiveHealthPercent -- Effective health percentage from 0 to 1 calculated from effectiveHealth/effectiveMaxHealth.

float Entity.healthRegen -- Regeration rate of health points units/ms
float Entity.manaRegen -- Regeration rate of mana/stamina in units/ms

float Entity.mana -- Mana/stamina units
float Entity.maxMana -- Maximum mana/stamina units

vec3 Entity.position -- Position
vec3 Entity.direction -- Direction
vec4 Entity.rotQuaternion -- Rotation as quaternion
vec3 Entity.rotEuler -- Rotation as Euler
matrix Entity.rotMatrix -- Rotation as matrix
vec3 Entity.velocity -- Velocity in cm/ms

vec3 Entity.bboxMin -- Bounding box min
vec3 Entity.bboxMax -- Bounding box max
vec3 Entity:bboxAt(vec3 p) -- Gets a point within the bounding box given the [0-1] points addresing min and max.

bool Entity.isMe -- Shorthand for comparison with Me.Entity
bool Entity.isDead -- Whether the entity is dead or not

-- Extended entity state, if game does not support these flags,
-- they will default to false.
--
bool Entity.isAI -- If AI controlled entity
bool Entity.isDown -- If in down state
bool Entity.isBlind -- If blinded
bool Entity.isJumping -- If jumping
bool Entity.isDashing -- If dashing
bool Entity.isRooted -- If rooted (cannot move)
bool Entity.isStunned -- If stunned (cannot move, cast spells, or fire)
bool Entity.isSilenced -- If stunned (cannot cast spells)
bool Entity.isOccluded -- If behind a surface
bool Entity.isCrouching -- If crouching
bool Entity.isInvisible -- If invisible (due to an in-game mechanic)
bool Entity.isSprinting -- If sprinting
bool Entity.isInvulnerable -- If invulnerable
bool Entity.isInAir -- If entity is in air
bool Entity.isFlying -- If entity is flying
bool Entity.isNoclip -- If entity does not collide
uint Entity.flags -- All states as EntityFlag

-- Internal timers.
--
float Entity.renderTime -- Duration that this entity has been visible for, 0 if N/A & occluded.
float Entity.occlusionTime -- Duration that this entity has been occluded for, 0 if N/A & visible.
float Entity.updateTime -- Timestamp of last entity update.
float Entity.tickTime -- Timestamp of last entity tick.
float Entity.spawnTime -- Spawn time

-- Bitset of extended state flags supported by the engine.
--
uint Engine.SUPPORTED_EFLAGS

-- Optional entity information, returns nil if entity does not have them
-- or if the game does not support it.
--
Entity? Entity:getPet(int n) -- If player, gets the Nth pet spawned by it.
Entity? Entity:getPassenger(int n) -- If vehicle, gets the passenger entity at the Nth seat.
vec3? Entity:getBone(int n) -- Gets Nth bone's position.
vec3? Entity:getBone(CommonBone id) -- Gets bone position given a common bone identifier.
string? Entity:getBoneName(int n) -- Names Nth bone of the entity.
Color? Entity:getGlowColor() -- Gets the glow color.
bool Entity:setGlowColor(Color c) -- Sets the glow color, returns false on failure.

Iterable<{int, Entity}> Entity.passengers
Iterable<{int, Entity}> Entity.pets
Iterable<{int, vec3}> Entity.allBones
Iterable<{int, string}> Entity.boneNames
Iterable<{CommonBone, vec3}> Entity.bones

string? Entity.pickupAmmoKind -- If PICKUP_AMMO, the kind of ammunition, if not nil but "" all.
int? Entity.pickupAmmoCount -- If PICKUP_AMMO, the number of bullets, if negative fills the weapon.
vec4? Entity.pickupHealth -- If PICKUP_HEALTH, the change in health it provides.

int? Entity.modelId -- Model identifier as integer.
string? Entity.modelName -- Model identifier as string.
int? Entity.squadId -- Squad identifier the entity belongs to.
Entity? Entity.owner -- If projectile or pet, owner entity.
Entity? Entity.vehicle -- If player, vehicle it's in.
string? Entity.playerName -- Player name.
uint? Entity.spectatorCount -- Number of spectators this player has.

-- Prints a message below the entity box for debugging.
--
void Entity:dprint(string message)

-- Constant descriptor table associated, will be expanded on in the next section.
-- Player = CharacterInfo
-- Projectile = ProjectileInfo
-- Pickup of subtype PICKUP_ITEM = ItemInfo
--
ItemInfo|CharacterInfo|ProjectileInfo Entity.info

-- Lua table that can be used to store arbitrary info.
-- [!Deprecated!] Preferred way is using components with the latest API.
--
table Entity.data
info

Entity objects supports comparison and string conversion as metamethods.

Example/index.ts
for (const entity of Entity.Query({ team: Team.ENEMY })) {
print(entity != Me.Entity); // Prints "true"
}

UI scaling

Instead of manually calculating the screen position for the entity and using a fixed pixel-based size we recommend using the ui information provided by the entity structure. By centralizing this calculation we avoid repeated calculations and achieve to scale all UI components by both distance and the screen resolution of the user.

-- UI information
--
bool Entity.isOnScreen -- If the entity is on screen
float Entity.uiScale -- Recommended UI scale in pixels, < 0 if not on screen
vec2? Entity.uiBboxMin -- Min bounding box on screen, nil if not on screen
vec2? Entity.uiBboxMax -- Max bounding box on screen, nil if not on screen
float Entity.uiDepthMin -- Min depth on screen, < 0 if not on screen
float Entity.uiDepthMax -- Max depth on screen, < 0 if not on screen
vec3? Entity:uiBboxAt(vec3 p) -- Gets a point within the UI bounding box given the [0-1] points addresing min and max, nil if not on screen.

The UI scale here is calculated by a set of parameters called UIParams which you can customize per entity and per entity type, although the Core and the Engine usually take care of it for you.

UIParams        Entity.uiParams           -- UI parameters deciding the scaling on screen

vec2 UIParams.bounds -- Vector containing the [min,max] values for the clamping of a distance value.
float UIParams.relScale -- Relative scale applied based on the screen height in pixels.
float UIParams.absScale -- Absolute scale applied as pixels.
float UIParams.leakyness -- Leakyness of the scaling calculation, e.g. the minimum value for (x-min)/(max-min).
float UIParams.exponent -- Exponent applied to the result of the scaling.
UIParams UIParams.clone -- Clones the UI parameters

float UIParams:calcFromPos(vec3 p) -- Calculates UIScale based on the given position.
float UIParams:calcFromDist(float x) -- Calculates UIScale based on the given distance.
float UIParams:calcFromDistSq(float x) -- Calculates UIScale based on the given distance squared.

-- Configuration for the global UI Parameter settings.
--
UIParams Entity.GetUIParams(EntityType ty)
void Entity.SetUIParams(EntityType ty, UIParams params)

Components

SR Entity model allows you to define your own components that can be attached to any instance of Entity. For the sake of simplicity, Systems (as in the ECS model) are also encapsulated by this single class by exposing certain member functions.

To create a new component, all you need to do is define a class that can be constructed using a single parameter, the parent Entity, and declare any of the following functions to have them be registered automatically. Note that you do not have to implement all of them and the engine is able to optimize the entity loop better if you only define what you need.

class IComponent {
constructor(e: Entity) {}

// Invoked at Event.OnTick.
tick?(e: Entity): void;

// Invoked at Event.OnRender.
draw?(e: Entity): void;

// Invoked upon destruction of the component or the entity.
detach?(e: Entity): void;
}

After the implementation of the component is ready, you can use the following methods to attach, detach, and lookup component instances:

-- Fetches the existing instance of [T], creates a new instance if none found.
--
T Entity:getComponent<T>(Ctor<T> ctor)

-- Fetches the existing instance of [T], returns null if none found.
--
T? Entity:findComponent<T>(Ctor<T> ctor)

-- Removes the existing instance of [T], returns false if none found.
--
bool Entity:removeComponent<T>(Ctor<T> ctor)

Inventory

Entities of type PLAYER and PICKUP additionally have inventory information containing any abilities, items and attachments. The following members of the Entity can be used to get an Item instance.

-- Inventory functions available for player and pickup types.
--
Item? Entity:getInventory(int n) -- Gets the item at the Nth slot.
Item? Entity:getAttachment(Item item, int n) -- Gets the Nth attachment of an item in this inventory.

Iterable<{int, Item}> Entity.items
Iterable<{int, Item}> Entity.abilities

-- Inventory functions exclusive to player types.
--
Item? Entity:getAbility(int n) -- Gets the Nth ability of the character.
Item? Entity.currentWeapon -- Gets the current weapon held by the player.

Item instances have the following fields and can be used to inject user behaviour as well if the source inventory was local player's.

-- Item name as assigned by the game engine.
string Item.name

-- Constant information associated with this item, will be expanded on in the next section.
ItemInfo Item.info

-- Cooldown timer of the actions associated with this item, relative time in milliseconds from the time of query.
float Item.cooldownTimer

-- Casting/Charging percentage.
float Item.castingPercent

-- Ammunition in the item.
uint Item.ammo
-- Number of instances stacked in this slot.
uint Item.count
-- Weardown of the item.
float Item.weardown

-- Active zeroing distance in engine units.
float Item.zeroingDistance
-- Active firing mode.
FiringMode Item.firingMode

-- State flags.
bool Item.zoomed -- Set if zoomed in.
bool Item.shooting -- Set if being fired.
bool Item.casting -- Set if being cast/charged.
bool Item.interactable -- Set if we can interact with this item (set*/switchTo).
bool Item.active -- Set if item is active and can be used (cancel/charge/cast*) if ready without switching to it.

-- Casts an item, returns false on failure.
-- Tip: Relavant mode information can be found in info.
--
bool Item:cast(int? actionIdx) -- No target information, ex: rifle being shot.
bool Item:castAt(vec3 target, int? actionIdx) -- Directional targetting, ex: using a dash ability.
bool Item:castOn(Entity ent, int? actionIdx) -- Entity targetting, ex: healing a teammate by selecting them.

-- Changes item states, returns false on failure.
--
bool Item:charge() -- Starts charging the item.
bool Item:cancel() -- Cancels charging or the animation of the item.
bool Item:switchTo() -- Switches to the item as the primary.
bool Item:setZoom(bool zoomed) -- Changes zoom state.
bool Item:setMode(FiringMode mode) -- Changes firing mode.
bool Item:setZeroing(float dist) -- Changes zeroing distance in engine units.

Events

Entity objects support multiple object-local events in the type of basic events, which, unlike the real Event type, only support subscription via call syntax and no priority system.

-- Entity events emitted on health changes.
void Entity:onDamage(function<vec4 prev, vec4 new> cb)
void Entity:onHeal(function<vec4 prev, vec4 new> cb)
void Entity:onDeath(function<> cb)
void Entity:onRespawn(function<> cb)

-- Miscellaneous entity events.
void Entity:onTeamChange(function<> cb)
void Entity:onDespawn(function<> cb)
void Entity:onVisibilityChange(function<bool isVisible> cb)
void Entity:onInventoryUpdate(function<> cb)

In case that the engine exposes custom events, you may also use the Entity:on function to subscribe to an event by name, the function returns false if the entity does not expose this event.

The event name is case-insensitive and also maps to builtin events, e.g. e:onDespawn(f) is semantically equal to e:on("Despawn", f).

-- Registers a callback to an entity event specified by the name.
bool Entity:on(string name, function cb)

There are also global events to keep track of creation and deletion of entities.

-- Emitted when an entity spawns with a reference to it.
Event<Entity> Event.OnSpawn

-- Emitted before an entity despawns with a reference to it.
Event<Entity> Event.OnDespawn
caution

One important caveat to note is that the mentioned events (as well as component callbacks) trigger during what we call an entity list update phase of the engine which means accessing any other entity might return you stale data and doing object manager queries will error.

Queries

In order to maximize performance, instead of doing manual enumeration, scripts make queries to the entity list. These queries are further optimized by precompiling them into EntityQuery.

table EntityFilter {
EntityType? | EntityType[]? type -- Entity type, if left nil, defaults to Entity.PLAYER
EntitySubType? | EntitySubType[] subtype -- Entity subtype, if left nil, allows any.
EntityTeam? | EntityTeam[]? team -- Entity team, if left nil, allows any team.

float? distance -- Maximum distance from 'distanceFrom'.
float? distanceMin -- Minimum distance from 'distanceFrom'.
vec3? distanceFrom -- Origin for distance limiting, if left nil, defaults to camera origin.

float? maxHealth -- Maximum effective health: `effectiveHealth < x`
float? maxHealthPerc -- Maximum effective health percentage: `effectiveHealthPercent < x`.
float? minHealth -- Minimum effective health: `effectiveHealth > x`
float? minHealthPerc -- Minimum effective health percentage: `effectiveHealthPercent > x`.
float? minHealthMissing -- Minimum effective health missing: `(effectiveMaxHealth - effectiveHealth) > x`.

bool? ai -- Entity flags, if left nil, allows any state.
bool? dead --
bool? down --
bool? blind --
bool? jumping --
bool? dashing --
bool? stunned --
bool? silenced --
bool? rooted --
bool? occluded --
bool? crouching --
bool? invisible --
bool? sprinting --
bool? invulnerable --
bool? inair --
bool? flying --
bool? noclip --

bool? onScreen -- If given, compared against isOnScreen.
bool? notMe -- If set, skips local player.
Ctor? component -- If set, filters to entities with the given component.
}
-- Compiles an entity filter into a query.
--
EntityQuery Entity.Filter(EntityFilter|EntityType desc)

-- Queries the entity list.
--
Iterable<Entity> EntityQuery:query()
Iterable<Entity> Entity.Query(EntityFilter|EntityType|EntityQuery|nil query)

-- Queries the entity list in one step, returns a table of entities.
--
Entity[] EntityQuery:collect()
Entity[] Entity.Collect(EntityFilter|EntityType|EntityQuery|nil query)

-- Counts the number of entities matching the filter.
--
uint EntityQuery:count()
uint Entity.Count(EntityFilter|EntityType|EntityQuery|nil query)

-- Finds the first entity matching filter.
--
Entity? EntityQuery:find()
Entity? Entity.Find(EntityFilter|EntityType|EntityQuery|nil query)

-- Tests the entity against the the filter.
--
bool EntityQuery:test(Entity e)
bool Entity.Test(EntityFilter|EntityType|EntityQuery|nil query, Entity e)

Both Entity.Query/EntityQuery.query and Entity.Collect/EntityQuery.collect can be used to get a list of entities, but the Query version returns a stateless iterator whereas Collect returns a Lua table of all the results collected. Naturally this changes the enumeration syntax.

Example/index.lua
local enemyQuery = Entity.Filter{
type = Entity.PLAYER,
team = Team.ENEMY
}

local function getEnemyPlayerNames()
local enemyNames = {}
for entity in enemyQuery:query() do
local name = entity.playerName
if name then
enemyNames[#enemyNames + 1] = name
end
end
return enemyNames
end
Example/index.ts
const enemyFilter = Entity.Filter({
type: Entity.PLAYER,
team: Team.ENEMY
});
function getEnemyPlayerNames() {
const enemyNames: string[] = [];
for (const entity of enemyFilter.query()) {
const name = entity.playerName;
if (name) enemyNames.push(name);
}
return enemyNames;
}

The main reason why we have two different syntaxes for the same goal is due to the internals of Lua. In the example above, Query has to call out from the Lua VM for each entity whereas Collect does not. This makes Collect faster for iterations of more than a thousand objects. Although do note that generally speaking, you should not iterate a thousand objects in the first place and utilize the OnSpawn and OnDespawn events.

Another key difference is that the result of Query is valid for a single frame whereas with Collect you can store the result without any invalidation issues.

TL;DR: Use Query unless you run into an issue where Collect helps, which will not be all that often with good structure.

Appendix

Here's a list of enumerations previously mentioned but not declared to keep the snippets short.

-- Entity team.
--
EntityTeam Team.NEUTRAL
EntityTeam Team.ALLY
EntityTeam Team.ENEMY

-- Entity types and subtypes.
--
EntityType Entity.PLAYER
EntityType Entity.PET

EntityType Entity.MISC
EntitySubType Entity.MISC_DRONE
EntitySubType Entity.MISC_TRAP
EntitySubType Entity.MISC_CAMERA
EntitySubType Entity.MISC_SPAWNPOINT

EntityType Entity.PROJECTILE

EntityType Entity.PICKUP
EntitySubType Entity.PICKUP_ITEM
EntitySubType Entity.PICKUP_CONTAINER
EntitySubType Entity.PICKUP_HEALTH -- Includes barrier, shield, armor.
EntitySubType Entity.PICKUP_AMMO

EntityType Entity.VEHICLE
EntitySubType Entity.VEHICLE_CAR
EntitySubType Entity.VEHICLE_PLANE
EntitySubType Entity.VEHICLE_BOAT

EntityType Entity.OBJECTIVE
EntitySubType Entity.OBJECTIVE_FLAG
EntitySubType Entity.OBJECTIVE_BOMB
EntitySubType Entity.OBJECTIVE_HOSTAGE

EntitySubType Entity.GENERIC

-- Entity flags.
--
uint Entity.AI
uint Entity.DEAD
uint Entity.DOWN
uint Entity.BLIND
uint Entity.JUMPING
uint Entity.DASHING
uint Entity.STUNNED
uint Entity.SILENCED
uint Entity.ROOTED
uint Entity.OCCLUDED
uint Entity.CROUCHING
uint Entity.INVISIBLE
uint Entity.SPRINTING
uint Entity.INVULNERABLE
uint Entity.INAIR
uint Entity.FLYING
uint Entity.NOCLIP

-- Common bone names.
--
CommonBone Bone.HEAD
CommonBone Bone.NECK
CommonBone Bone.SPINE
CommonBone Bone.PELVIS

CommonBone Bone.R_UPPERARM
CommonBone Bone.R_FOREARM
CommonBone Bone.R_HAND
CommonBone Bone.R_THIGH
CommonBone Bone.R_CALF
CommonBone Bone.R_FOOT

CommonBone Bone.L_UPPERARM
CommonBone Bone.L_FOREARM
CommonBone Bone.L_HAND
CommonBone Bone.L_THIGH
CommonBone Bone.L_CALF
CommonBone Bone.L_FOOT

-- Firing modes.
--
FiringMode FiringMode.SEMI_AUTO
FiringMode FiringMode.FULL_AUTO
FiringMode FiringMode.BURST
string FiringMode.ToString(FiringMode value)
-- Deprecated aliases, will be removed in a future version.
--
Entity[] Entity.QueryCollect(EntityFilter|EntityType|EntityQuery|nil query)
bool Entity.QueryTest(EntityFilter|EntityType|EntityQuery|nil query, Entity e)