Game Icons
Scripts can draw the game's own art: ability icons, item and upgrade art, status icons, hero portraits and minimap markers. The art is read from the game's own files.
These loaders return the same kind of handle as draw.load_image, and you draw them with the same draw.image. They use the same handle budget and lifetime as draw.load_image.
| Function | Returns | Description |
|---|---|---|
draw.ability_icon(hero_name, slot) | integer or nil | Icon for one of your own hero's four abilities. slot is 1 to 4 |
draw.item_icon(name, [px]) | integer or nil | Icon for an item or upgrade by name |
draw.load_game_image(path, [px]) | integer or nil | Any image in the game's interface art, by path |
These three read the game's own files and never change them. draw.load_image only takes a bare file name under C:\TSUKI\Deadlock\scripts\images\.
Ability icons
Pass a hero's name and a slot. It only returns an icon while the menu draws ability art: the Ultimate ESP in Icon mode, or Ability Cooldowns with Use Game Icons on. Your own hero works with either. Another hero's icons also need Ability Cooldowns on, and only appear for abilities that player has learned. For a reliable icon of another hero, load the art by path with draw.load_game_image.
function on_tick()
local me = local_player()
local hero = me and me:hero_name()
if not hero then return end
for slot = 1, 4 do
local h = draw.ability_icon(hero, slot)
if h then
draw.image(h, 40 + (slot - 1) * 70, 300, 64, 64)
end
end
endhero_name is a method, not a field, so you have to call it.
Item icons
Pass the item or upgrade name, with or without the upgrade_ prefix:
local h = draw.item_icon("counterspell") -- same as "upgrade_counterspell"Names are looked up in the game's own item table, so renamed and new items work without a TSUKI update. nil means the name is unknown.
Loading by path
draw.load_game_image takes a path into the game's interface art. It accepts either the compiled path or the source path used in the game's data files, and normalises it for you:
| Form | Example |
|---|---|
| Compiled path | panorama/images/hud/abilities/astro/holliday_crackshot_psd.vtex_c |
| Source path | file://{images}/hud/abilities/bebop/bebop_hook.psd |
| Source path, wrapped | panorama:"file://{images}/hud/abilities/haze/haze_sleep_dagger.psd" |
To convert a source path by hand, drop the wrapper and file://{images}/, put panorama/images/ in front, and turn the trailing .psd into _psd.vtex_c. A trailing .svg becomes .vsvg_c instead, so file://{images}/hud/modifiers/icon_parry.svg is panorama/images/hud/modifiers/icon_parry.vsvg_c.
px only matters for vector art (.vsvg_c). It sets the longer side, from 16 to 512, default 128. Textures ignore it. Minimap markers live under materials/minimap/ and load the same way.
Useful starting points:
| Path | What it holds |
|---|---|
panorama/images/hud/abilities/<hero>/ | Ability art, one folder per hero |
panorama/images/hud/modifiers/ | Status and buff icons |
panorama/images/heroes/ | Hero portrait art |
panorama/images/minimap/ | Minimap markers |
materials/minimap/ | Camp and crate markers |
What it refuses
A refused call always returns nil and never draws something wrong.
| Input | Result |
|---|---|
A path containing .. | nil, logged once |
| A path outside the interface art | nil. This is not a general file reader |
| A path that does not exist | nil |
| Art in a format that cannot be decoded | nil, never garbage pixels |
Drawing them well
Most of this art is white and meant to be tinted. Drawn as is on a bright background, it is invisible. Put something dark behind it and pick a tint:
local PLATE = draw.color(12, 14, 18, 200)
draw.rect_filled(x, y, 40, 40, PLATE, 3) -- plate first, because the art is transparent
draw.image(h, x, y, 40, 40, draw.color(120, 220, 160)) -- argument 6 is the tint
draw.rect(x, y, 40, 40, draw.color(80, 220, 120, 230), 1.6, 3)Sizes vary by file. Ability icons are mostly square, but others are not. Call draw.image_size(h) if you need the real aspect ratio.
Do not shrink them far. These are large source images. A 20 px box throws away most of the detail. Draw at 28 px or more where you can.
Waiting for art to load
The first call for a path usually returns nil while the art loads. Ask again on the next tick and keep the handle once you get one:
local icon
function on_tick()
icon = icon or draw.item_icon("counterspell")
if icon then draw.image(icon, 40, 40, 32, 32) end
endLimits
| Handles | 64 loaded at once, shared with draw.load_image. Scripts that load the same game image share one handle and one slot. draw.unload_image gives one back, and the slot is freed once no script holds it. A script's images are given back when it resets or reloads |
| Largest side | 4096 px |
Images draw in every rendering mode (Standard, Enhanced and Internal). In Enhanced and Internal mode a newly loaded image can take a fraction of a second longer to appear.