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 out of the game's own files at runtime. Nothing ships with TSUKI and nothing is downloaded.
These loaders return the same kind of handle as draw.load_image, and you draw them with the same draw.image. There is one image system, one budget and one lifetime.
| Function | Returns | Description |
|---|---|---|
draw.ability_icon(hero_name, slot) | integer or nil | Icon for one of a 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 |
draw.load_image is unchanged and still limited to a bare file name under C:\TSUKI\Deadlock\scripts\images\. The three functions here do not widen that; they read the game's own files, which are read only.
Ability icons
The one you usually want. Pass a hero name and a slot:
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. 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"The name is resolved through the game's own item table, so a rename or a new item follows automatically 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 the game's own data files use, and normalises 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" |
If you are converting a source path by hand, the rule is: drop the wrapper and file://{images}/, put panorama/images/ in front, and turn the trailing .psd into _psd.vtex_c. The same applies to .svg.
Some art is stored as vector rather than a texture. Those are rasterized once for each size you ask for. px sets the longer side, from 16 to 512, and defaults to 128. 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 refusal always returns nil rather than drawing 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 raw on a bright background it is invisible. Put something dark behind it and tint deliberately:
local PLATE = draw.color(12, 14, 18, 200)
draw.rect_filled(x, y, 40, 40, PLATE, 3) -- plate first, the art is transparent
draw.image(h, x, y, 40, 40, draw.color(120, 220, 160)) -- arg 6 tints
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.
nil means not yet, not no
The first call for a path usually returns nil while the art loads. Ask again next tick and keep the handle once it lands:
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 in total, shared with draw.load_image |
| Largest side | 4096 px |
| Decode | Once per path, then cached on disk between runs |
| When unused | Nothing is opened until a script asks |
Images do not draw in Enhanced mode
In Enhanced rendering mode, draw.image draws nothing. This applies to every image, not just game art, and a script cannot work around it. If your script needs images, either target Standard mode or fall back to draw.text and draw.rect. TSUKI's own ability ESP is not affected; it takes a different path.