Entities ​
The game world is populated with entities, anything that exists in 3D space and can be observed, interacted with, or collided with. Troopers, jungle camps, the midboss, crates, powerup buffs, gravestones, skeletons, and many projectiles (Doorman's luggage cart, Paige's knight charge, and so on) are all entities. Players have their own dedicated accessor, everything else lives in the entity list.
You can also approach detection through particles, modifiers, or other systems, but checking the entity list is usually the first thing to try when designing a script, especially anything ESP or detection-related.
Discovery: Show All Entities ESP ​
The cheat ships with a dev tool that overlays every entity it currently sees with its class name, health, and distance. Enable it from Scripts → Dev Tools → Show All Entities ESP.

In the screenshot above, Graves' Gravestone ultimate shows up as citadel_gravestone_blocker, and the skeletons it spawns are npc_necro_skele. The breakable props next to the gravestone are citadel_breakableprop. Toggle the ESP on to discover the exact class name for whatever entity you're trying to script around, then filter get_world_entities() by that class name.
Include All Entity Types ​
Right below the ESP toggle is Include All Entity Types (off by default). The scanner normally parses only the curated useful entities, everything in the type table below plus known projectiles, gravestones, breakables, and similar gameplay objects. Flip this toggle on to also parse exotic engine entities like env_sky, zipline nodes, func_brush, trigger volumes, and so on. They'll then appear in get_world_entities() alongside the rest.
Leave it off unless a script genuinely needs one of those classes. Scanning the full entity list every frame has measurable overhead, which is why the curated parse is the default.
get_world_entities([filter]) ​
Returns a table of all world entities currently tracked. Optionally filter by a curated type name.
Arguments:
filter(string, optional). If provided, only returns entities matching this type name.
Returns: Table of entity tables, each with these fields:
| Field | Type | Description |
|---|---|---|
type | string | Curated entity type (see list below). May be empty for entities outside the curated set. |
class_name | string | Internal RTTI class name (e.g. npc_neutral_sinners_sacrifice, citadel_gravestone_blocker) |
x, y, z | number | World position |
health | integer | Current HP (if applicable) |
max_health | integer | Maximum HP (if applicable) |
team | integer | Team number. 0=none, 1=spectator, 2=amber, 3=sapphire, 4=neutral (jungle, props) |
distance | number | Distance from the local player, in meters |
currency_value | integer | Soul value (for dropped souls) |
pickup_name | string or nil | Pickup identifier, only present on powerup, pickup_modifier, pickup_gold, and pickup_health types. See Pickup entities. |
active | boolean | For pickup entities, whether this variant is currently spawned and collectible. Multiple pickup entities can stack at the same position, only one is active at a time. |
Curated types ​
| Type | Description |
|---|---|
trooper | Lane creeps |
trooper_boss | Lane guardian creeps |
camp | Jungle camp neutrals and bugs |
sinner | Sinner sacrifice camps |
tower | Guardians, walkers, shrines |
midboss | Mid boss |
soul_orb | Denial/last-hit soul orbs |
soul_urn | Soul urn pickups |
dropped_souls | Dropped souls from kills |
powerup | Map powerups (casting, movement, survival, gun) |
pickup_gold | Small gold boxes |
pickup_health | Health pickups |
pickup_modifier | Stat modifier pickups (hp, wp, cd, spirit, firerate) |
guided_owl | Grey Talon guided arrow projectile |
doorman_cart | Doorman luggage cart projectile |
entity | Unclassified entities (props, spawners, items on ground) |
For anything outside the curated list, gravestones, breakable props, ability-specific projectiles, skeletons, etc., call get_world_entities() with no argument to get everything, then filter on class_name yourself.
When the local player position isn't valid yet (spectating, pre-spawn, between rounds) get_world_entities() returns an empty table. If you got an entity back, distance is always a valid number. No nil check needed.
Pickup entities ​
Entities of type powerup, pickup_modifier, pickup_gold, and pickup_health carry the extra pickup_name and active fields. Each powerup spawn location has four entities stacked at the same position, one per buff variant, and only one is active at a time. Always filter by active to avoid rendering duplicate labels at the same world point.
Powerup variants (type "powerup", temporary buffs from bridge spawn points):
pickup_name | Buff |
|---|---|
survival_powerup_pickup | Survival |
casting_powerup_pickup | Casting |
movement_powerup_pickup | Movement |
gun_powerup_pickup | Gun |
Modifier variants (type "pickup_modifier", permanent stat bonuses from breakable props):
pickup_name | Stat |
|---|---|
hp_permanent_pickup_label | Max health |
wp_permanent_pickup_label | Weapon damage |
cd_permanent_pickup_label | Cooldown reduction |
spirit_permanent_pickup_label | Spirit power |
firerate_permanent_pickup_label | Fire rate |
ammo_permanent_pickup_label | Ammo |
Names ending in _lv2 are upgraded versions of the same stat.
Basic powerup ESP example, labels the four powerup variants by name:
function on_tick()
for _, p in ipairs(get_world_entities("powerup")) do
if p.active and p.distance < 200 then
local sp = draw.world_to_screen(vec3(p.x, p.y, p.z))
if sp then
local label = "POWERUP"
if p.pickup_name then
if p.pickup_name:find("survival") then label = "SURVIVAL"
elseif p.pickup_name:find("casting") then label = "CASTING"
elseif p.pickup_name:find("movement") then label = "MOVEMENT"
elseif p.pickup_name:find("gun") then label = "GUN"
end
end
draw.text(sp.x, sp.y, label, draw.color(255, 0, 255))
end
end
end
endFor a fuller version that handles all four pickup types (powerups, modifiers, gold, health) with color-coded categories, see Powerup ESP.
Examples ​
-- Total count
local all = get_world_entities()
print("Total entities: " .. #all)-- All sinners with distance
for _, s in ipairs(get_world_entities("sinner")) do
print("Sinner at " .. s.x .. ", " .. s.y .. " - " .. s.distance .. "m away")
end-- Mark nearby powerups on screen
for _, p in ipairs(get_world_entities("powerup")) do
if p.distance < 30 then
local sp = draw.world_to_screen(vec3(p.x, p.y, p.z))
if sp then
draw.text(sp.x, sp.y, "POWERUP", draw.color(255, 255, 0, 255))
end
end
end-- Show camp HP bars
for _, c in ipairs(get_world_entities("camp")) do
if c.health > 0 and c.distance < 100 then
local sp = draw.world_to_screen(vec3(c.x, c.y, c.z))
if sp then
draw.text(sp.x, sp.y, c.health .. "/" .. c.max_health, draw.color(120, 120, 255, 255))
end
end
end-- Gravestone marker (entity outside the curated list, filter on class_name)
for _, e in ipairs(get_world_entities()) do
if e.class_name == "citadel_gravestone_blocker" then
draw.box3d(vec3(e.x, e.y, e.z), 50, 50, 80, draw.color(0, 255, 0, 255), 2)
end
end-- Discover unknown entity classes
local seen = {}
function on_tick()
for _, e in ipairs(get_world_entities()) do
if not seen[e.class_name] then
seen[e.class_name] = true
print("class:", e.class_name)
end
end
endentity.set_rate(type, tier) ​
Controls how frequently entity positions are updated. By default, entities update at sensible speeds. Use this to promote entities to faster updates when your script needs precise, real-time tracking.
Arguments:
type(string). Entity type name (e.g."sinner","powerup") or internal class name (e.g."npc_neutral_sinners_sacrifice","citadel_punchablepowerup").tier(string). One of:"fast". Updated every frame (~16ms). Use for time-critical features like custom parry or precision aiming."medium". Updated every 200ms. Good for ESP or general tracking."slow". Updated every ~1 second. For entities you just need to know exist."default". Revert to the system's default rate for this type.
Returns: nothing.
Notes:
- You can only promote entities to faster speeds, not demote below their default. For example, sinners default to
"medium", setting them to"slow"has no effect. - Overrides persist until you call
set_ratewith"default"or the script is unloaded. - Multiple scripts can set different rates for the same type. The fastest rate wins.
Examples:
-- Make powerup positions update every frame for precision tracking
entity.set_rate("powerup", "fast")
-- Revert to default
entity.set_rate("powerup", "default")
-- For a custom auto-parry against a specific projectile, promote it to per-frame
entity.set_rate("citadel_punchablepowerup", "fast")entity.get_rate(type) ​
Returns the current Lua rate override for an entity type.
Arguments:
type(string). Entity type name or class name.
Returns: string: "fast", "medium", "slow", or "default" (no override set).
print(entity.get_rate("sinner")) -- "default"
entity.set_rate("sinner", "fast")
print(entity.get_rate("sinner")) -- "fast"
entity.set_rate("sinner", "default")
print(entity.get_rate("sinner")) -- "default"Default update rates ​
Entities update at different speeds depending on their importance. You don't need to call set_rate unless you need faster updates than the defaults.
| Type | Default Rate | Notes |
|---|---|---|
trooper | Per-frame when trooper ESP/aimbot is on, otherwise slow | High count (~100+) |
soul_orb | Per-frame when soul aimbot/triggerbot is on, otherwise slow | High count |
guided_owl | Per-frame | Always fast when present |
sinner | 200 ms | Always on |
tower | 200 ms | Always on |
midboss | 200 ms | Always on |
camp | 200 ms | Always on |
powerup | 200 ms | Always on |
pickup_gold | 200 ms | Always on |
pickup_health | 200 ms | Always on |
pickup_modifier | 200 ms | Always on |
dropped_souls | 200 ms | Always on |
soul_urn | 200 ms | Always on |
doorman_cart | 200 ms | Always on |
entity | ~1 second | Static entities (props, items) |
Position freshness in get_world_entities() depends on the rate, per-frame entities have positions ~16 ms old, 200 ms entities up to ~200 ms old, slow entities up to ~1 s old. For static entities like props and items, the position never changes so staleness doesn't matter.