Skip to content

API Game modes

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

Game modes

Import from proleak import modes

Game modes: your own rules on ProLeak's local server.

Classes

Class
Bot A bot to seat on a lane with Lane.bot; bots makes them.
bots The bots a mode seats on its lanes.
Lane One lane, set during setup: who holds it.
Lanes The lanes of a game, by slot: game.lanes[1] is the Lane of slot 1.
Player A player by slot.
Unit A server unit by id.
System One system of the server, such as game.economy.
Commands The chat commands of the mode's server (game.commands): the game's - commands.
Gate A side's corridor gate (the 2v2 map has one each side).
Game The server-side game of the running mode.
ServerEvent A server event: its units are server units, its players Player, and ev.game the game.

Functions

Returns Function
Callable[[Setup], Setup] mode(name: str, *, title: str, subtitle: str, image: str | None = None, tooltip: str | None = None, hue: float | None = None, info: str | None = None, info_popup: str | None = None, map: str = 'legiontd2', players: int | None = None) Registers a game mode of this plugin; decorates its setup(game).
Callable[[ServerHandler], ServerHandler] on(event: str, pre: bool = False, priority: int = 0) Subscribes a server-scope handler, called while this plugin's mode runs.
None play(name: str) Starts a local game with this plugin's mode name; raises ModeError with the reason.
list[dict] list_modes() Every mode: the default game first, then each plugin's, as dicts (id, owner, name, title, map, players).
Game game() The running mode's game (server scope only).

Values

Type Value
type Setup A mode's setup(game), run once on the server before the first client connects.
type ServerHandler A server-scope handler: it gets one ServerEvent.

Detailed description

A mode runs in two places. Its client-scope code is the rest of your plugin (proleak.on, ui, ...). Its server scope is the code this module calls: the setup given to mode, the handlers given to on, and the policies and timers they set. Only server-scope code of the mode the server runs reaches the server; anything else raises NotAllowedHere.

Server scope must be deterministic: use game.random and the server clock (game.tick, game.after, game.every), never random or time, so a game replays the same.

Function documentation

mode

mode(name: str, *, title: str, subtitle: str, image: str | None = None, tooltip: str | None = None, hue: float | None = None, info: str | None = None, info_popup: str | None = None, map: str = 'legiontd2', players: int | None = None) -> Callable[[Setup], Setup]

Registers a game mode of this plugin; decorates its setup(game).

setup runs on the server once, before the first client connects: it sets the lanes, switches systems off and replaces policies. The mode gets a card on the game's Solo & Co-op screen, after the game's own cards:

  • title and subtitle, its name and the line under it;
  • image, a PNG or JPG in the plugin's folder, at most 2 MB (ProLeak's helmet when none is given);
  • tooltip, shown over the card while the pointer is on it;
  • hue, the colour of the glow round the card under the pointer, in degrees on the colour wheel (0 red, 120 green, 240 blue; purple, 275, when none is given);
  • info and info_popup: a link under the card, as the game's Ranked FAQ, that opens info_popup in a popup. A blank line starts a paragraph, and a paragraph whose lines all start with -  is a list. Each needs the other.

play(name) starts the mode from code. players is the players a side the mode is made for.

on

on(event: str, pre: bool = False, priority: int = 0) -> Callable[[ServerHandler], ServerHandler]

Subscribes a server-scope handler, called while this plugin's mode runs.

ev is a server event: its units are server units (Unit), its players Player, and ev.game is the game. pre=True handlers may change editable fields or cancel.

play

play(name: str) -> None

Starts a local game with this plugin's mode name; raises ModeError with the reason.

list_modes

list_modes() -> list[dict]

Every mode: the default game first, then each plugin's, as dicts (id, owner, name, title, map, players).

game

game() -> Game

The running mode's game (server scope only).

Value documentation

Setup

Setup = Callable[[Game], None]

A mode's setup(game), run once on the server before the first client connects.

ServerHandler

ServerHandler = Callable[[ServerEvent], None]

A server-scope handler: it gets one ServerEvent.

Bot class

A bot to seat on a lane with Lane.bot; bots makes them.

bots class

The bots a mode seats on its lanes.

Returns Method
Bot basic(king_heal: float = 0.0) ProLeak's basic bot: it picks a legion, builds for the next wave, buys workers, sends with Auto Income (Auto Power once a teammate sends) and heals its king with King Regen after a wave took more than king_heal (a share, 0 to 1) of its life.

Method documentation

basic

basic(king_heal: float = 0.0) -> Bot

ProLeak's basic bot: it picks a legion, builds for the next wave, buys workers, sends with Auto Income (Auto Power once a teammate sends) and heals its king with King Regen after a wave took more than king_heal (a share, 0 to 1) of its life.

Lane class

One lane, set during setup: who holds it.

Type Property
str kind read-only Who holds it: "human", "bot", "idle" or "closed".
Returns Method
None human() The player takes it.
None bot(ai: Bot) A bot takes it, such as bots.basic().
None idle() The lane plays: its waves come, nobody builds.
None closed() The lane is shut: its waves never come.

Property documentation

kind

kind: str [read-only]

Who holds it: "human", "bot", "idle" or "closed".

Method documentation

human

human() -> None

The player takes it.

bot

bot(ai: Bot) -> None

A bot takes it, such as bots.basic().

idle

idle() -> None

The lane plays: its waves come, nobody builds.

closed

closed() -> None

The lane is shut: its waves never come.

Lanes class

The lanes of a game, by slot: game.lanes[1] is the Lane of slot 1.

Player class

A player by slot. Setting a resource shows it at once.

Type Property
int slot read-only Its slot, 1 to 8.
int gold Gold in hand.
int mythium Mythium in hand.
int income Gold it earns each wave.
int workers Workers it has.
int value read-only The value of its fighters.

Property documentation

slot

slot: int [read-only]

Its slot, 1 to 8.

gold

gold: int

Gold in hand.

mythium

mythium: int

Mythium in hand.

income

income: int

Gold it earns each wave.

workers

workers: int

Workers it has.

value

value: int [read-only]

The value of its fighters.

Unit class

A server unit by id.

Type Property
int id read-only Its id.
str type read-only Its unit type id, such as crab_unit_id.
int owner read-only Its owner's slot.
int lane read-only The slot of the lane it is in; 0 for none.
float x read-only Map x position.
float z read-only Map z position.
bool alive read-only True while it is alive.
float life read-only Its life now; setting it shows the change at once.
bool controlled read-only True: the mode drives it, it follows only the mode's orders.
Returns Method
None order_move(x: float, z: float) Walk to map point (x, z).
None order_attack(target: Unit) Attack target, even one this unit ignores (the order lifts the ignore).
None ignore(target: Unit) Never take target as a target, and drop it at once if attacking it.
None unignore(target: Unit) Let the unit take target as a target again.
None kill() It dies at once; nobody earns its bounty.

Property documentation

id

id: int [read-only]

Its id.

type

type: str [read-only]

Its unit type id, such as crab_unit_id.

owner

owner: int [read-only]

Its owner's slot.

lane

lane: int [read-only]

The slot of the lane it is in; 0 for none.

x

x: float [read-only]

Map x position.

z

z: float [read-only]

Map z position.

alive

alive: bool [read-only]

True while it is alive.

life

life: float [read-only]

Its life now; setting it shows the change at once.

controlled

controlled: bool [read-only]

True: the mode drives it, it follows only the mode's orders.

Method documentation

order_move

order_move(x: float, z: float) -> None

Walk to map point (x, z).

order_attack

order_attack(target: Unit) -> None

Attack target, even one this unit ignores (the order lifts the ignore).

ignore

ignore(target: Unit) -> None

Never take target as a target, and drop it at once if attacking it.

The unit picks another target or walks on. A later unit given target's id is not ignored.

unignore

unignore(target: Unit) -> None

Let the unit take target as a target again.

kill

kill() -> None

It dies at once; nobody earns its bounty.

System class

One system of the server, such as game.economy.

Type Property
bool enabled read-only Whether the system runs; assign False to switch it off.

Detailed description

enabled switches the whole system on or off. Each policy the system has is an attribute: assign a function to replace the game's rule, or None to bring it back. The Game properties list each system's policies, and the Policies section of the Game modes guide gives each policy's arguments and answer.

Property documentation

enabled

enabled: bool [read-only]

Whether the system runs; assign False to switch it off.

Commands class

The chat commands of the mode's server (game.commands): the game's - commands.

Type Property
str cheats read-only "off" (the default): never.
list[str] names read-only Every command the server answers, without its -.
Returns Method
None allow(fn: Callable[[Player], bool | None] | None) Decides who may cheat and type -debug: fn is given each Player and returns True or False (None: allowed).
bool enabled(name: str) Whether the command name (without its -) answers.
None enable(name: str) Switches the command name back on.
None disable(name: str) Switches the command name off: typed, it does nothing, as an unknown command.

Detailed description

The cheats (-gold, -wave, -maphack, ...) work only while the game's debug mode is on, and cheats decides when that is. The Chat commands section of the Game modes guide lists every command.

Property documentation

cheats

cheats: str [read-only]

"off" (the default): never. "debug": once a player types -debug, as in an official custom game. "on": from the start.

names

names: list[str] [read-only]

Every command the server answers, without its -.

Method documentation

allow

allow(fn: Callable[[Player], bool | None] | None) -> None

Decides who may cheat and type -debug: fn is given each Player and returns True or False (None: allowed). Without it (or after allow(None)), every player may.

enabled

enabled(name: str) -> bool

Whether the command name (without its -) answers.

enable

enable(name: str) -> None

Switches the command name back on.

disable

disable(name: str) -> None

Switches the command name off: typed, it does nothing, as an unknown command.

Gate class

A side's corridor gate (the 2v2 map has one each side).

Type Property
bool is_open read-only True while units walk through it.
float | None life read-only None, or the life of a closed gate the waiting wave must break: it opens when the life is gone.
Returns Method
None open() Opens it now: the units it held go on.
None close() Closes it: the next units to reach it wait.

Property documentation

is_open

is_open: bool [read-only]

True while units walk through it.

life

life: float | None [read-only]

None, or the life of a closed gate the waiting wave must break: it opens when the life is gone.

Method documentation

open

open() -> None

Opens it now: the units it held go on.

close

close() -> None

Closes it: the next units to reach it wait.

Game class

The server-side game of the running mode.

Type Property
System economy read-only Income, kill bounty and mythium.
System building read-only Building fighters.
System waves read-only The waves: what comes, and the build time before it.
System movement read-only How units walk their lane.
System combat read-only Damage and target choice.
System mercenaries read-only Hiring and sending mercenaries.
System spells read-only The legion spells offered at wave 11.
System notices read-only The messages and sounds that tell players what happens.
System bots read-only The bots on the lanes.
System gates read-only The corridor gates of the 2v2 map.
Commands commands read-only The chat commands: when the cheats work, who may use them, which commands answer.
Lanes lanes read-only The lanes by slot, 1 to 8: game.lanes[1].
list[Player] players read-only The players in the game.
int wave read-only The wave being played or built for.
int tick read-only The server clock, in milliseconds.
Returns Method
list[Unit] units(owner: int | None = None, lane: int | None = None, type: str | None = None) The units alive; given owner (a slot), lane (a slot) or type, only those that match.
Gate gate(side: str) The "west" or "east" corridor gate.
Unit unit(id: int) The unit with this id.
int random(n: int) A number from 0 to n - 1 from the game's own seeded stream.
float random_float() A number from 0 up to 1 from the game's own seeded stream.
int after(ms: int, fn: Callable[[], None]) Runs fn() once, ms from now on the server clock; returns the timer.
int every(ms: int, fn: Callable[[], None]) Runs fn() every ms until cancelled or the game ends; returns the timer.
None cancel(timer: int) Stops a timer from after or every.
Unit spawn(type: str, owner: int, x: float, z: float) A new unit of type for the owner slot at (x, z); it stands until ordered.

Property documentation

economy

economy: System [read-only]

Income, kill bounty and mythium. Policies: income, bounty, mythium_rate.

building

building: System [read-only]

Building fighters. Policies: can_build, cost.

waves

waves: System [read-only]

The waves: what comes, and the build time before it. Policies: units, build_seconds, next_wave.

movement

movement: System [read-only]

How units walk their lane. Policies: route.

combat

combat: System [read-only]

Damage and target choice. Policies: damage, target.

mercenaries

mercenaries: System [read-only]

Hiring and sending mercenaries. Policies: stock, delivery.

spells

spells: System [read-only]

The legion spells offered at wave 11. Policies: offer.

notices

notices: System [read-only]

The messages and sounds that tell players what happens. It has no policies.

bots

bots: System [read-only]

The bots on the lanes. It has no policies.

gates

gates: System [read-only]

The corridor gates of the 2v2 map. Policies: holds, opens.

commands

commands: Commands [read-only]

The chat commands: when the cheats work, who may use them, which commands answer.

lanes

lanes: Lanes [read-only]

The lanes by slot, 1 to 8: game.lanes[1]. Set who holds each one in setup.

players

players: list[Player] [read-only]

The players in the game.

wave

wave: int [read-only]

The wave being played or built for.

tick

tick: int [read-only]

The server clock, in milliseconds.

Method documentation

units

units(owner: int | None = None, lane: int | None = None, type: str | None = None) -> list[Unit]

The units alive; given owner (a slot), lane (a slot) or type, only those that match.

gate

gate(side: str) -> Gate

The "west" or "east" corridor gate.

unit

unit(id: int) -> Unit

The unit with this id.

random

random(n: int) -> int

A number from 0 to n - 1 from the game's own seeded stream.

random_float

random_float() -> float

A number from 0 up to 1 from the game's own seeded stream.

after

after(ms: int, fn: Callable[[], None]) -> int

Runs fn() once, ms from now on the server clock; returns the timer.

every

every(ms: int, fn: Callable[[], None]) -> int

Runs fn() every ms until cancelled or the game ends; returns the timer.

cancel

cancel(timer: int) -> None

Stops a timer from after or every.

spawn

spawn(type: str, owner: int, x: float, z: float) -> Unit

A new unit of type for the owner slot at (x, z); it stands until ordered.

ServerEvent class

A server event: its units are server units, its players Player, and ev.game the game.

Inherits Event.

Type Property
Game game read-only The game of the running mode.

Property documentation

game

game: Game [read-only]

The game of the running mode.


Previous: Game data | Next: Game state

Clone this wiki locally