3 Cookbook Tweaks
bryanthaboi edited this page 2026-10-20 17:01:40 -04:00

Cookbook: tweaks

These recipes change existing Red content. Start with R02 if this is your first edit.

Setup: a working mod from Getting Started. Examples target Red/local single-player unless a recipe explicitly says otherwise. Use Modding Basics for syntax and Glossary for unfamiliar terms. Save and restart after content edits. A validation pass and an in-game checkpoint are different checks.

Where code goes: insert Lua fragments inside your existing return function(mod) ... end in main.lua. A complete-file label or named other file overrides that default. Do not paste a second entry function inside the first. Read the recipe's requirements before copying its code. For output, use Read log output; for IDs, use Find internal IDs.

Content changes to things that already exist. Mechanism: Concepts: Registries. All code goes in main.lua inside return function(mod) ... end unless noted.

R01 - Recolor a battle sprite

Basic Lua. Before you paste: A working mod manifest; create a separate transforms.lua as shown. This reads the player's imported Mew sprite, so import Red first.

Complete walkthrough / required concept.

Ship a recipe, not pixels: declare "assets_transforms": "transforms.lua" in the manifest and write the transform.

Outline / alternative: read the requirements above; this is not a complete mod.

-- transforms.lua
return function(ctx)
  local front = ctx.readImage("battle/front/mew.png")
  ctx.writeImage(ctx.recolor(front, {
    { 255, 255, 255 }, { 255, 170, 200 }, { 180, 60, 120 }, { 40, 0, 20 },
  }), "battle/front/mew.png")
end

The derived file shadows the cache path everywhere it is drawn. Checkpoint: Mew renders recolored in the dex and in battle. Full walkthrough: Tutorial 01.

Gen 3: transforms read Gen 1/2 cache paths. To recolor a Gen 3 species, register a four-row palettes record under MEWMON (normal pictures) or MEWMON_SHINY (an api 2 or api 3 mod writes it in the native shape); it is applied as a luminance ramp over the cart art (R56).

R02 - Rewrite one dialogue line

First change. Before you paste: A mod with manifest.json and main.lua. This changes one existing town sign; no assets are needed.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.text:override("_PalletTownSignText", "MODDED SIGN.")

Checkpoint: reading the Pallet Town sign shows the new text. Find label names in the merged registry: mod.content.text:each().

Gen 2 / Gen 3: text is keyed by that game's own labels and takes its native shape (Gold's script text is pointers; label-keyed engine prose is rom_text on Gen 2 and Gen 3). The same :each() lists them.

R03 - Buff a move's power

Basic Lua. Before you paste: A mod entry function. This edits existing Tackle; it does not create or teach a move. Inspect data.moves.TACKLE.power in the developer console to verify 50; one random hit is not a reliable comparison.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.moves:patch("TACKLE", { power = 50 })

Checkpoint: Tackle deals more damage; every unnamed field stays vanilla.

Gen 2 / Gen 3: with "api": 3 this exact line patches Tackle on every game (Portable Mods).

R04 - Rebalance a species' stats

Basic Lua. Before you paste: A mod entry function. Inspect data.pokemon.PIDGEY.baseStats.speed after restarting to verify 71. A party Pokemon's calculated stat is a different value.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.pokemon:patch("PIDGEY", { baseStats = { speed = 71 } })

Checkpoint: the baseStats sub-table merges; only speed changes. base_stats is the classic typo; api = 2 rejects it with a suggestion.

Gen 2 / Gen 3: an api 3 mod writes the same baseStats on every game. special sets both later Special stats; specialAttack and specialDefense carry the split.

R05 - Change a wild encounter table

Basic Lua. Before you paste: A Red save that can enter Route 1 grass. An encounter slot chooses what can appear; rate controls how often an encounter is attempted. Repeated encounters are random.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.encounters:patch("ROUTE_1", {
  grass = {
    rate = 30,
    slots = { __prepend = { { species = "EKANS", level = 5 } } },
  },
})

Checkpoint: Route 1 rolls Ekans in its most common slot; rate (of 255) governs how often grass rolls at all. Ten slots weight front-to-back per constants.encounterBuckets.

Gen 2 / Gen 3: an api 3 mod uses this grass shape with that game's map id (FR_ROUTE_1 on FireRed); Gen 3 maps it onto the land table, and on Gold one write applies to every time of day.

R18 - Change a trainer's party

Basic Lua. Before you paste: Use a Red save before defeating Brock. parties contains a list of parties, each of which contains a list of Pokemon. Write every party you intend to retain.

Complete walkthrough / required concept.

Insert in main.lua inside the entry function (unless a filename is shown).

mod.content.trainers:patch("OPP_BROCK", {
  parties = { { { species = "ONIX", level = 14 },
                { species = "GEODUDE", level = 12 } } },
})

Checkpoint: Brock leads Onix 14. parties is an array of parties; arrays replace wholesale, so state the full party list.

Gen 2 / Gen 3: an api 3 mod writes the same parties shape. Trainer ids are per game; Gen 3 keys each trainer by its number as a string ("326"), with one party each.