Skip to content

Game assets

Alexandre 'kidev' Poumaroux edited this page Oct 21, 2026 · 7 revisions

Game assets

proleak.assets works with the game's assets as this player hears and sees them: it plays sounds and effects anywhere, places the game's models or a plugin's own anywhere, puts a plugin's sounds and models in place of the game's, moves and hides the map's decorations, shows a model in place of the whole map, and sets the lighting. The changes reach this player only.

from proleak import assets

assets.register("Sounds/Effects/GoldCoins", "Particles/VFX/Environment/FallingSnow.pkfx",
                "Models/Characters/Mech/APS", "Sounds/Music/Menu")
theme = assets.load_sound("music/theme.ogg")
assets.replace("Sounds/Music/Menu", theme)                 # the main menu's music
assets.play_sound("Sounds/Effects/GoldCoins", at=(40, 60))  # a game sound at a map point
assets.play_effect("Particles/VFX/Environment/FallingSnow.pkfx", 40, 60, seconds=10)
assets.place("Models/Characters/Mech/APS", 42, 61, turn=90)  # a game model on the map
assets.set_lighting("night", lock=True)

Contents

Cosmetics

What players buy is a cosmetic: skins and monument cards (the Skins/ models), the effects and sounds a skin brings (its own attack, missile, aura and buff effects with their sounds), and the monuments' pedestals. ProLeak reads the list from the game's own store data. A call that names a cosmetic works on a local ProLeak server only and raises NotAllowedHere elsewhere. Everything else works in every game, official ones included.

How long a change lasts

Every change a plugin makes is held by that plugin: another plugin naming the same path, doodad or effect gets ValueError with the first plugin's name. changed() lists what the plugin holds.

A change made during a game (a replaced sound or model, a changed doodad, a placed model, a played or swapped effect, the map, the lighting) goes back to the game's own as the player leaves that game, so each game starts from the game's own assets, whichever plugin's mode it plays. A change made outside a game, in the menu, stays until the plugin undoes it. When the plugin unloads, everything it changed goes back to the game's own.

Registering the game's assets

A plugin registers every sound, model and effect of the game it uses with register(*paths) while it loads (in its module or on_load). Once the game has started, ProLeak loads each one in the background, as the game loads its own on first use, so the plugin's first call with it costs nothing. A call naming a path the plugin did not register raises ValueError, and so does register after the plugin has loaded.

A game mode lists the assets only it uses in assets= of modes.mode: they load as the mode's server starts, and the plugin may use them while its mode plays.

The map's doodads and the plugin's own sounds and bundle models need no registering.

Loading a plugin's assets

Call Loads Kept
load_sound(file) a WAV or OGG file of the plugin's folder, at most 32 MB a Sound; sound.path is where the game finds it
load_bundle(file) a Unity asset bundle of the plugin's folder, at most 256 MB a Bundle; bundle.names() lists its assets and scenes, and bundle.model(name) gives the path of one

Both work while the plugin loads (in its module or on_load) and load in the background: state is loading, ready, or failed: and the reason. A sound or model given a place while it loads takes it once ready. A bundle must be built with the game's Unity version (2022.3.76f1).

Playing

play_sound(sound) plays a Sound or a game sound path everywhere; at=(x, z) plays it at a map point and unit= from a unit. play_effect(path, x, z) plays a game effect at a map point, on the ground or at height y; play_effect(path, unit=unit) plays it on a unit, following it and ending with it. It lasts seconds (0 keeps it until effect.stop() or the end of the game), at scale.

loaded() lists the sound and model paths the game has loaded since it started: play the game, then read the list to find a path.

Replacing

replace(path, source) puts source in place of the game's sound or model at path, from the next time the game loads it. source is a Sound, a bundle model, or another game path:

assets.replace("Sounds/Units/APS_Attack", assets.load_sound("pew.wav"))
assets.replace("Models/Characters/Mech/APS", bundle.model("assets/robot.prefab"))
assets.replace_ui_sound("Click", assets.load_sound("click.wav"))

A unit's model comes from its row's prefabpath (such as Models/Characters/Mech/APS); a model put in its place shows for every unit of that type and should carry the bones and animations the game drives. restore(path) and restore_ui_sound(name) give the game its own back.

The game's music tracks are these paths:

Path Plays
Sounds/Music/Login while the game starts
Sounds/Music/Menu in the main menu
Sounds/Music/LoadingScreen on the loading screen
Sounds/Music/01 to Sounds/Music/08 in a game, one after the other
Sounds/Music/Campaign/<mission> on a campaign mission's screen
Sounds/Music/CardTraderBackground at the card trader
Sounds/Music/MonumentBackground on the profile's monument tab

add_music(sound) plays a sound after the game's eight tracks in each game, and remove_music(sound) takes it out. play_music(sound) plays a sound as the music now, until the game changes its music; stop_music() stops it.

The map

The map's decorations are its doodads: trees, rocks, buildings, lights, the water's effects. doodads() lists those of the map loaded now, each with its path under the map's doodads (siblings of one name are told apart by #2, #3), its place (x, z, height y), turn, scale, visible, the effect it shows and its children: a group such as DoodadsV1/_ROCKS holds the doodads under it (hiding it hides them all), a single model holds none. doodads(near=(x, z), radius=r) lists only those within r of a map point. The Legion TD 2 map has some 2500, and listing them all costs a good part of a handler's time budget: list the area needed, keep a full list rather than asking again, and use doodad(path) for one whose path is known.

pine = assets.doodad("Trees/Pine_03")
pine.hide()                     # or show()
pine.move(42, 61)               # on the ground; move(42, 61, y=3) at a height
pine.turn_to(90)
pine.resize(1.5)                # against its own size, at most 10
pine.show_effect("Particles/VFX/Environment/FallingSnow.pkfx")
pine.reset()                    # as the game made it

assets.place("Trees/Pine_03", 40, 60)                               # a copy of a doodad
assets.place("Models/Doodads/CrystalCoast/Lightshafts_Day", 90, 80)  # a game model
assets.place(bundle.model("assets/statue.prefab"), 70, 50, scale=2)  # a plugin's model

place returns a Doodad that moves, turns, resizes and hides like the map's; reset() removes it. The game loads and makes models, and starts effects, over the next frames (a few milliseconds of each), so these calls return at once and their result shows a frame or more later.

replace_map(model) shows a model of the game or of a bundle, or a bundle's scene (a name ending .unity, loaded beside the game's scene), in place of the map's ground and decorations, on every map load; restore_map() brings the map back. The lanes, the grid and where units walk stay the game's: the model only changes what the map looks like.

Effects

The game's effects are paths such as Particles/VFX/Effects/GoldCoins.pkfx. swap_effect(path, to) shows to wherever the game starts path from then on, and restore_effect(path) gives the game its own back.

Lighting

set_lighting sets any of:

Argument Sets
theme the game's day, night or fade lighting
lock=True the theme stays whatever theme the game asks for (the game turns day and night with its phases)
color the main light's colour, (red, green, blue) from 0 to 1
intensity the main light's intensity, 0 to 10
ambient the ambient light's colour, (red, green, blue) from 0 to 1

What is left out stays the game's. reset_lighting() gives the game its own lighting back.


Previous: Chat, camera, input and more | Next: Game modes

Clone this wiki locally