Skip to content

Cookbook World And Scripting

bryanthaboi edited this page Jul 19, 2026 · 1 revision

Cookbook — world and scripting

Command vocabulary: Reference: Script Commands; worked paths: Tutorials 06–08.

R20 — Add a script command

mod.commands:register("mod_reward", function(ctx, amount)
  ctx.save.money = math.min(999999, (ctx.save.money or 0) + (amount or 100))
end)

Checkpoint: { "mod_reward", 500 } works in any script row. The handler is fn(ctx, ...)ctx.save, ctx.overworld, ctx.game are the surface; return a label string to jump. The script.command hook sees every dispatched row if you need to intercept instead.

R21 — Add a text token

mod.content.tokens:register("CLOCK", function(game, arg)
  return tostring(math.floor((game.save.playSeconds or 0) / 3600))
end)

Checkpoint: {CLOCK} in any text renders the value. Grammar is {NAME} or {NAME:arg}, handler fn(game, arg) -> string | nil (src/script/Tokens.lua); nil drops the token, a thrown error is logged and drops it.

R22 — Add a talk script to an NPC

mod.content.map_scripts:register("PALLET_TOWN", {
  talk = {
    TEXT_PALLETTOWN_GIRL = {
      { "face_player" },
      { "show_text", "My line is\nmodded now!" },
    },
  },
})

Checkpoint: the Pallet Town girl says your line; every other TEXT constant on the map is untouched. Per TEXT constant the highest-precedence contribution wins; false suppresses lower ones.

R23 — Spawn a new NPC on a map

mod.events:on("map.entered", function(ev)
  if ev.mapId == "PALLET_TOWN" then
    mod.world:spawnNpc("PALLET_TOWN", {
      index = 95, x = 10, y = 9, sprite = "SPRITE_FISHER",
      movement = "WALK", range = "ANY_DIR", text = "TEXT_PALLETTOWN_GIRL",
    })
  end
end)

Checkpoint: the NPC appears and wanders on every visit. Runtime objects are not serialized — re-spawn on map.entered. For a permanent NPC, patch the map record's objects with __append instead (Tutorial 06).

R24 — Add an onStep trigger

mod.content.map_scripts:register("PALLET_TOWN", {
  onStep = function(game, ow, x, y)
    if x == 10 and y == 10 then
      mod.log:info("stepped on the spot")
      -- return true to consume the step
    end
  end,
})

Checkpoint: stepping on (10,10) logs; the map's own onStep still runs. Contributions chain first-truthy-return-consumes (src/script/MapScripts.lua).

R25 — Add a new map + connection

local W, H = 6, 5
local blocks = {}
for i = 1, W * H do blocks[i] = 10 end
mod.content.maps:register("MODROUTE", {
  id = "MODROUTE", label = "ModRoute", index = 1000,
  tileset = "OVERWORLD", width = W, height = H, blocks = blocks,
  borderBlock = 10,
  connections = { west = { map = "PALLET_TOWN", offset = 0 } },
})
mod.content.maps:patch("PALLET_TOWN", {
  connections = { east = { map = "MODROUTE", offset = 0 } },
})

Checkpoint: walking off Pallet Town's east edge enters MODROUTE and back. Both directions are needed; blocks must count width * height. Full treatment: Tutorial 07.

Clone this wiki locally