Skip to content

Reference Events

bryanthaboi edited this page Jul 19, 2026 · 1 revision

Event reference

Every event the engine emits, with its payload fields and emit site. Read from the Runtime.emit call sites in src/ — the site column is where to look when you need the exact surrounding behavior. Subscribe with mod.events:on(name, fn); see Concepts: Events and Hooks for dispatch and error-isolation rules.

Payloads are shared between listeners. Treat fields as read-only unless the event is listed as mutable.

Lifecycle and mods

Event Payload Emit site
mods.loaded { loader, data } src/mods/Loader.lua (end of load)
game.ready { game } src/core/Game.lua; re-emitted on dev hot reload (src/dev/HotReload.lua)
mod.options_changed { mod, key, value } src/mods/ManagerState.lua
assets.transformed { modId, count } src/mods/AssetTransform.lua

game.ready's payload is the sanctioned way to reach the live Game object: read ev.game. Content registries are frozen by the time mods.loaded fires — registering from a listener raises.

Save

Event Payload Emit site
save.created { save } src/core/Game.lua (fresh skeleton: boot without a save, New Game)
save.writing { save, meta } src/core/Game.lua (before the file write)
save.loading { raw } src/core/Game.lua (parsed, before migrations/validation)
save.loaded { save, meta, modsDiff } src/core/Game.lua (after validation)

modsDiff is { added, removed, changed } between the save's recorded mod set and the active one (Save Model).

Battle

Event Payload Emit site
battle.started { battle, kind, trainerId, species, level } src/battle/BattleState.lua
battle.ended { battle, result } src/battle/BattleState.lua (result: "caught", "run", "skipped", ...)
battle.turn_started { battle, turn, playerAction, enemyAction } src/battle/BattleState.lua; also src/link/LinkBattle.lua
battle.turn_ended { battle, turn } src/battle/BattleState.lua
battle.move_used { battle, user, target, move, isCalled } src/battle/BattleState.lua (isCalled: Metronome / Mirror Move re-entry)
battle.damage_dealt { battle, user, target, move, damage, crit, typeMult } src/battle/EffectRegistry.lua (typeMult base 10: 10 = neutral, 20 = super)
battle.battler_switched { battle, side, battler, previous } src/battle/BattleState.lua (both sides, all switch paths)
battle.fainted { battle, battler } src/battle/BattleState.lua
battle.exp_gained { battle, mon, gained, levels } src/battle/BattleState.lua
battle.ball_thrown { battle, ball, caught, shakes } src/battle/BattleState.lua (Safari and bag throws)
battle.status_inflicted { battle, target, status, source } src/battle/StatusRegistry.lua

Pokemon

Event Payload Emit site
pokemon.before_give { ctx, species, level, nickname? }mutable src/script/Commands.lua (give_pokemon)
pokemon.caught { battle, mon, species, isNew, ball, destination, game } src/battle/BattleState.lua
pokemon.level_up { mon, level, prevLevel, learnable } src/battle/Experience.lua
pokemon.move_learned { mon, moveId } src/battle/BattleState.lua
pokemon.evolved { mon, fromSpecies, toSpecies, via } src/pokemon/Evolution.lua
pokemon.received { mon, from = "link", peerName } src/link/Protocol.lua, src/link/LinkBattle.lua

pokemon.before_give is the grandfathered mutable event: every story gift, fossil, and scripted give_pokemon passes through it, and listeners may rewrite species, level, and nickname before the mon is built. ctx is the running script context (ctx.save, ctx.overworld).

World

Event Payload Emit site
map.entered { mapId, map, fromMapId, via } src/world/OverworldController.lua (via: "boot", "warp", "connection", "reload", ...)
map.exited { mapId, toMapId } src/world/OverworldController.lua
map.reloaded { mapId, reason } src/world/OverworldController.lua, src/world/WorldAPI.lua
player.warped { fromMap, toMap, x, y, warp } src/world/OverworldController.lua
world.stepped { mapId, x, y, tile } src/world/OverworldController.lua (hot path — keep listeners cheap)
world.interacted { mapId, x, y, kind, target } src/world/OverworldController.lua
world.npc_spawned { mapId, npcId, runtime } src/world/OverworldController.lua
world.trainer_engaged { npc, trainerClass, partyIndex } src/world/OverworldController.lua
world.boulder_moved { mapId, npcId, x, y } src/world/OverworldController.lua
world.blacked_out { save, healTarget } src/world/OverworldController.lua
world.block_replaced { mapId, bx, by, block } src/world/OverworldController.lua
world.object_toggled { mapId, objName, visible } src/world/WorldAPI.lua
flag.changed { name, value } src/script/Flags.lua (set and clear)

Scripts and screens

Event Payload Emit site
script.started { ctx } src/script/ScriptRunner.lua
script.ended { ctx, completed } src/script/ScriptRunner.lua (completed = false on abort)
screen.pushed { state } src/core/StateStack.lua
screen.popped { state } src/core/StateStack.lua

Audio

Event Payload Emit site
music.started { song, previous, chip, reason } src/core/Music.lua
music.stopped { song } src/core/Music.lua
sound.played { kind, name, species } src/core/Sound.lua (kind: "sfx" or "cry")

Link

Event Payload Emit site
link.connected { role, remote = { name, mode, mods, fingerprint } } src/link/LinkState.lua
link.ended { reason } src/link/LinkState.lua
link.desync { turn, component, localHash, remoteHash } src/link/LinkBattle.lua
trade.completed { sent, received, evolveTo } src/link/Protocol.lua

Mod-emitted events

A mod may emit only under its own prefix, so no mod can forge an engine event:

mod.events:emit("mod.my_mod_id.season_changed", { season = "winter" })

Anyone (any mod) can subscribe to mod.<id>.* names with the ordinary mod.events:on.

Clone this wiki locally