Skip to content

Your first plugin

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

Your first plugin

This tutorial builds a small plugin: a toast at the start of every wave, a chat command, and a setting the player can change from the Mods menu. It takes about ten minutes and needs ProLeak installed and the game running.

Contents

1. Make the plugin folder

A plugin is a folder in ProLeak/plugins/ inside the game folder. The folder name is the plugin id. Make ProLeak/plugins/my.wave-toast/ and put a plugin.yml in it:

id: my.wave-toast
name: Wave toast
version: 0.1.0
author: me
description: Says what each wave is and how your value compares.
proleak: ">=0.1"

Every key is described in Plugin basics. Then a main.py beside it:

from proleak import on, ui, world


@on("wave.started")
def announce(ev):
    you = world.player()
    if you is None:
        return
    wave = ev.info
    ui.toast(f"{wave.name}: recommended value {wave.recommended_value}, yours {you.value}",
             header=f"Wave {ev.wave}")
  • @on("wave.started") calls announce each time a new wave number shows. Handling events explains handlers, and Events lists every event.
  • ev.info is the wave's data record (data.WaveInfo): its name, unit, count and recommended value.
  • world.player() is you: a Player with your gold, value, fighters and more. It is None outside a game.

2. Load it

Start the game. ProLeak finds plugin folders as the game starts, so a folder made while the game runs needs a restart. Open Mods: the page lists Wave toast as loaded. Play a game and a toast shows at each wave.

After a change to main.py, press Reload on the plugin in the Mods page.

Tip

Reload on save

With dev: true in ProLeak/config/proleak.yml, ProLeak reloads a plugin each time a file in its folder changes. Save main.py and the new code runs at once.

When something goes wrong the plugin shows another state with the reason, and its traceback goes to the Logs tab of the Mods page and to ProLeak/logs/my.wave-toast.log. See Troubleshooting.

3. Add a chat command

Commands stay on your client: teammates never see them. Add to main.py:

from proleak import chat


@chat.command("value")
def value(cmd):
    you = world.player()
    if you is None:
        cmd.reply("not in a game")
        return
    cmd.reply(f"value {you.value}, {len(you.fighters())} fighters", color="#33ff33")

Type !value in the game chat. The reply shows in your chat only.

4. Add a setting

A setting gets a form in the Mods menu without any UI code. Make the toast optional:

from proleak import settings

show_toast = settings.add("show_toast", True, label="Toast each wave")


@on("wave.started")
def announce(ev):
    if not show_toast.value:
        return
    ...

The plugin now has a Settings button in the Mods menu. The value is saved in ProLeak/config/my.wave-toast.yml and survives restarts. Plugin settings covers numbers, choices, colors and keys.

A bigger example

This plugin keeps a log of the waves you leak, toasts each leak, and lists them on !leaks:

from proleak import chat, on, ui

_leaks = {}             # wave -> percent leaked


@on("game.started")
def reset(ev):
    _leaks.clear()


@on("player.leaked")
def record(ev):
    if not ev.player.is_local or ev.percent == 0:
        return
    _leaks[ev.wave] = ev.percent
    ui.toast(f"You leaked {ev.percent:.0f}% of wave {ev.wave}")


@chat.command("leaks")
def leaks(cmd):
    if not _leaks:
        cmd.reply("no leaks yet")
        return
    cmd.reply(", ".join(f"wave {w}: {p:.0f}%" for w, p in sorted(_leaks.items())))
  • player.leaked fires for every player once a wave's leaks are known; ev.player.is_local keeps yours.
  • game.started empties the log, so each game starts with a new one.
  • Module-level state such as _leaks lasts until the plugin reloads.

Where to go next

To Read
Understand the folder, plugin.yml and when your code runs Plugin basics
React to more of the game Handling events
Show menus, pages and popups User interface
Read players, units and game data Players, units and game data
Share the plugin Publishing plugins

Previous: Local games | Next: Plugin basics

Clone this wiki locally