Powerup ESP ​
Color-coded ESP labels for every pickup entity in range: powerups from bridge spawn points (survival, casting, movement, gun), permanent stat modifiers from breakable props (hp, wp, cd, spirit, firerate, ammo), gold boxes, and health pickups. Each category gets its own color so a glance tells you what's available without reading the label.
What this shows ​
- One unified loop for all four pickup types.
powerup,pickup_modifier,pickup_gold, andpickup_healthget read in one pass viaget_world_entities(type). The inner logic doesn't care which type it's looking at. Thepickup_namefield disambiguates. - The
activefilter is doing real work. Each powerup spawn point has four entities stacked at the same position (one per buff variant). Without theactivefilter the script would draw four overlapping labels at every powerup location. pickup_namedrives the label and color. A smallget_label_and_colorhelper substring-matches the pickup name to a human-readable label and a category color. Adding a new pickup type is one line in that function. No other changes.- Distance label. A faint distance readout below each pickup label so you can quickly tell what's nearby versus far away without parsing world geometry.
Script ​
-- powerup_esp.lua
-- Shows active powerup and pickup entities with their type labels.
local colors = {
survival = draw.color(90, 210, 170),
casting = draw.color(180, 100, 255),
movement = draw.color(100, 200, 255),
gun = draw.color(255, 160, 50),
hp = draw.color(50, 255, 50),
wp = draw.color(200, 200, 255),
cd = draw.color(255, 255, 100),
spirit = draw.color(200, 100, 255),
firerate = draw.color(255, 100, 100),
ammo = draw.color(255, 180, 50),
gold = draw.color(255, 215, 0),
health = draw.color(50, 255, 100),
fallback = draw.color(200, 200, 200),
dist = draw.color(160, 160, 160),
}
local function get_label_and_color(name)
if not name or name == "" then return "PICKUP", colors.fallback end
name = name:lower()
if name:find("survival") then return "SURVIVAL", colors.survival end
if name:find("casting") then return "CASTING", colors.casting end
if name:find("movement") then return "MOVEMENT", colors.movement end
if name:find("gun") then return "GUN", colors.gun end
if name:find("firerate") then return "FIRE RATE", colors.firerate end
if name:find("ammo") then return "AMMO", colors.ammo end
if name:find("spirit") then return "SPIRIT", colors.spirit end
if name:find("wp_") then return "WEAPON", colors.wp end
if name:find("hp_") then return "HEALTH+", colors.hp end
if name:find("cd_") then return "COOLDOWN", colors.cd end
if name:find("gold") then return "GOLD", colors.gold end
if name:find("health") then return "HEALTH", colors.health end
return name:gsub("_pickup.*", ""):upper(), colors.fallback
end
function on_tick()
local types = {"powerup", "pickup_modifier", "pickup_gold", "pickup_health"}
for _, t in ipairs(types) do
local ents = get_world_entities(t)
for _, e in ipairs(ents) do
if e.active and e.distance < 200 then
local sp = draw.world_to_screen(vec3(e.x, e.y, e.z))
if sp then
local label, color = get_label_and_color(e.pickup_name)
draw.text(sp.x, sp.y, label, color)
draw.text(sp.x, sp.y + 14, string.format("%.0fm", e.distance), colors.dist)
end
end
end
end
endNotes ​
The 200 m distance gate keeps the screen clean, pickups across the map don't get labeled. Lower it if you only want immediate surroundings, or remove the check entirely for full-map awareness during pre-fight planning.
get_label_and_color falls back to a generic "PICKUP" label for anything it doesn't recognize. If new pickup classes are added in a future patch, the script keeps working, those pickups just render with the fallback label until a matching case is added. The fallback also strips _pickup.* from the unrecognized name and uppercases it, which usually produces something readable.
To change colors or add categories, edit the colors table at the top and append a new if name:find(...) branch in get_label_and_color. The render loop never needs to change.