game

Attach a mod to one or more games. Every registered game becomes a cartridge in the row along the bottom of the overlay; only the selected game's mods run, and everything else lies dormant. Clicking the selected cartridge pops it back out (no game selected, no mod running). Hovering a cartridge fans out the mods registered for it, and picking one opens that mod's settings.

functiongame.register(def) → GameMod

Register this mod against a game (or several) and get back the object you hang your callbacks and settings on. Pass a handle string, one definition table, or an array of them — an array means the same mod serves several games (e.g. FireRed and LeafGreen).

Field of a definitionTypeNotes
handlestringStable id for the game, e.g. "pkmn_firered". Two mods using the same handle share one cartridge. "base" is reserved — see below.
namestring?Shown under the cartridge. Defaults to the handle.
imagestring?Path to cartridge art, relative to the app folder (e.g. "addons/"..MOD_NAME.."/cart.png"). When it's missing or unloadable, the engine falls back to the site's own icon for that game (curated games carry one, fetched and cached automatically while any installed mod registers the game), and only then to the name as text.
local g = game.register({
    { handle="pkmn_firered",   name="Pokemon FireRed",   image="addons/"..MOD_NAME.."/fr.png" },
    { handle="pkmn_leafgreen", name="Pokemon LeafGreen", image="addons/"..MOD_NAME.."/lg.png" },
})
game.BASE ("base") is the mod that isn't about a game. Register it and you get no cartridge — there would be nothing to select, since it never stops — and your Think/OnFrame run whatever is or isn't selected. OnActivate fires once, on the first frame the mod exists (so a mod downloaded mid-session starts like one that was there at boot), and OnDeactivate only when the mod is unloaded. Screenshot keys, a clock, a chat overlay: things it would be absurd to switch off by picking a different cartridge. The site lists it as a game too ("Anything not game related. Always active."), so a mod that declares it is filed under it there.
local g = game.register(game.BASE, { name = "Screenshot keys" })
function g:Think() ... end      -- runs always
fieldGameMod.Thinkfunction(self)

Overridable: called once per frame, but only while one of your games is selected (or always, if you registered game.BASE). Dormant mods cost nothing.

Runs at the start of the frame, before the capture card is read — so the newest pixels it can see are the ones OnFrame was handed last frame. That is deliberate: Think sits outside the window the engine has to finish before the display's deadline, so a slow Think costs you nothing but a frame of its own freshness, instead of delaying the video for everyone. Read pixels in OnFrame, decide things in Think.

fieldGameMod.OnFramefunction(self, frame)

Overridable: called with each captured Frame while your game is selected — the gated version of OnFrameReceived. Use it to read or alter pixels only when your game is actually on.

fieldGameMod.OnActivate / OnDeactivatefunction(self)

Overridable: your game was just selected / deselected. Switching between two games that both belong to your mod does not fire these — you stay active.

fieldGameMod.LateUnreliableThinkfunction(self)

Overridable: for work too heavy to finish inside one frame. Offered every frame, but a call that hasn't returned yet keeps running instead of a new one starting — see Threading for what that costs you and how to yield.

methodg:addSetting(key, label, kind, options?, default?) → GameMod

Declare a setting. You only say what it's called, how it should be shown, and what kind of input it is — the engine owns everything else: it stores the value, remembers it between runs, validates it, and builds the settings menu. There is nothing to draw and nothing to save.

ParamTypeNotes
keystringHow you read it back with g:get(key).
labelstringShown in the settings menu.
kindstring"bool" (yes/no), "choice" (pick one), "multi" (pick any number), or "text".
optionsstring[]?The choices, for "choice" and "multi". For a choice, a value outside the list is rejected; for a multi, unknown names are dropped and the rest kept.
defaultany?Used until the user changes it. Defaults to true for bool, the first option for choice, nothing chosen for multi, empty for text.
g:addSetting("show_stats", "Show Pokemon stats", "bool", nil, true)
g:addSetting("route_info", "Show route information", "choice",
             { "on", "off", "overlay only" }, "on")
g:addSetting("badges", "Gym badges you hold", "multi",
             { "Boulder", "Cascade", "Thunder", "Rainbow" })

if g:get("show_stats") then ... end
for _, badge in ipairs(g:get("badges")) do ... end

Reach for "multi" when the answers are not exclusive. A count is not a set: "four gym badges" does not say which four, and in FireRed only four of the eight boost anything at all — so a number can be right about the total and wrong about every effect it is used for.

methodg:get(key) → boolean | string | string[] | nil

Current value of one of your settings — a boolean for "bool", an array for "multi", otherwise a string. nil if you never declared that key.

A "multi" always comes back as an array, in the order the options were declared rather than the order they were ticked — so two equal answers compare equal without sorting first. Nothing chosen is an empty array, never nil. Pass an array back to g:set.

methodg:set(key, value) → nil

Change a setting yourself. Saved immediately; invalid values for a choice are ignored.

functiongame.active() → string | nil

Handle of the selected game, or nil if none is. Takes no parameters.

functiongame.isActive(handle) → boolean

Whether that particular game is the selected one — handy when your mod serves several and needs to tell them apart.

functiongame.select(handle) → nil

Select a game as if its cartridge had been clicked. Fires the relevant OnDeactivate/OnActivate. The choice is remembered and restored next launch. Pass nil to deselect — no game selected is a normal state (clicking the selected cartridge does the same).

functiongame.list() → table[]

Every registered game in registration order, as { handle, name, image }. Takes no parameters.

functiongame.gamesOfMod(modName) → string[]

The handles of the games a given mod registered, e.g. game.gamesOfMod("pkmn_stats"){"pkmn_firered", "pkmn_leafgreen"}. Used by the engine's upload form to fill itself in from the mod rather than asking you to retype what the mod already declared — handles rather than display names, because the site matches on internal names that look like handles.

ParamTypeNotes
modNamestringAn addon folder name — the same value as MOD_NAME.
functiongame.modsFor(handle) → table[]

The other direction from gamesOfMod: every mod registered against one game, as the objects those mods passed to game.register. This is what the overlay's per-game mod list is built from. The objects are the mods' own, so treat them as read-only unless one is yours.

ParamTypeNotes
handlestringA game handle, e.g. "pkmn_firered".
functiongame.modName(obj) → string | nil

Which addon a registered object belongs to — the folder name, the same value that mod sees as MOD_NAME. Useful for labelling something you got out of modsFor. nil for anything that was not registered.

ParamTypeNotes
objtableAn object from game.modsFor.
functiongame.modSettings(obj) → table[]

The settings a mod declared with addSetting, with their current values — this is what the overlay builds a mod's settings panel out of, and it is why a mod does not have to draw one. Empty for a mod that declared none.

ParamTypeNotes
objtableAn object from game.modsFor.
functiongame.setModSetting(obj, key, value) → nil

Change one of those settings, as if the user had. The value is stored and persisted by the engine and the owning mod reads it back through its own get — so this is the supported way for a settings UI to write, and not a way to reach into another mod's state generally.

ParamTypeNotes
objtableAn object from game.modsFor.
keystringThe setting's key, as declared.
valueanyThe new value, matching the setting's declared type.
One page of the MCCP modding reference. Every section is its own document; search covers all of them.