Cookbook: species and moves
These recipes add or extend creature and move records. New content also needs a way for the player to obtain or use it.
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.
Record shapes: Concepts: Data Model and Reference: Registries. Worked paths: Tutorial 03, Tutorial 05.
R11 - Add a new move (existing effect)
Basic Lua. Before you paste: A Red Rattata below level 15 that can gain a level. This defines the move and adds one learnset entry. Existing level-15-or-higher Pokemon do not replay an earlier level-up.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.moves:register("MODSTRIKE", {
id = "MODSTRIKE", name = "MODSTRIKE",
type = "NORMAL", category = "physical",
power = 70, accuracy = 100, pp = 15,
effect = "NO_ADDITIONAL_EFFECT",
})
mod.content.pokemon:patch("RATTATA", {
learnset = { __append = { { level = 15, move = "MODSTRIKE" } } },
})
Checkpoint: Rattata learns MODSTRIKE at 15 and it deals plain damage.
Browse effect ids with mod.content.move_effects:each().
Gen 2 / Gen 3: with "api": 3 the same record registers on every game
(Gen 3 allocates a free move slot) and effect maps to the native effect; an
effect with no verified mapping is refused.
R12 - Add a custom move effect
Callbacks. Before you paste: Register a move that uses MODDRAIN_EFFECT; this effect alone is not a learnable move. The one-in-three check is random, so test several uses.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.move_effects:register("MODDRAIN_EFFECT", {
kind = "secondary",
run = function(ctx)
if ctx.rng(0, 255) < 85 then
ctx.changeStage(ctx.target, "speed", -1)
end
end,
})
Checkpoint: a move with effect = "MODDRAIN_EFFECT" drops speed about a
third of the time. The ctx facade (say, anim, damage, inflict,
changeStage, rng) is the supported surface
(src/battle/EffectRegistry.lua).
Gen 3: this record runs unchanged from an api 2 or api 3 mod (gen3MoveEffects).
secondary and full run after a hit that dealt damage, primary runs for a
power-0 move, ctx has the same members over Gen 3 battlers, and
changeStage reads special as Special Attack. The Gen 1 damage-pipeline
fields (hitCount, chooseDamage, onMiss, afterDamage, gate,
perform, ...) are not read. Gold routes to gen2MoveEffects.
R13 - Add a new species
Basic Lua + assets. Before you paste: Supply original assets/front.png and assets/back.png, with the dimensions described in Art Pipeline. To encounter the new species, also follow Tutorial03's encounter step.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.pokemon:register("MODMON", {
id = "MODMON", name = "MODMON", dex = 152, types = { "NORMAL" },
baseStats = { hp = 60, attack = 70, defense = 55, speed = 90, special = 65 },
catchRate = 120, baseExp = 100, growthRate = "MEDIUM_FAST",
level1Moves = { "TACKLE" }, learnset = {}, evolutions = {},
spriteFront = mod.assets:path("assets/front.png"),
spriteBack = mod.assets:path("assets/back.png"),
frontSize = 5,
})
Checkpoint: modkit validate passes; the mon battles and the dex counts
152. Full field list and the catchable checkpoint:
Tutorial 03.
Gen 2 / Gen 3: an api 3 mod registers the same record on every game;
Gen 3 allocates a free species slot. Gen 3 battle pictures are 64x64
(smaller art is recentred).
R14 - Give a species a party icon
Basic Lua + assets. Before you paste: MODMON must already exist (R13). Put its original icon at assets/icon.png; open the party menu with MODMON in your party.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.icons:register("MODMON", {
image = mod.assets:path("assets/icon.png"),
})
Checkpoint: the party menu shows the icon. The registry is keyed by species id, so a species past dex 151 gets an icon without touching any list.
Gen 2 / Gen 3: Gen 3 takes this record and replaces the party icon (a
string value borrows another species' icon). Gold's icons have a Gen 2
shape; an api 3 mod writes that shape as a pass-through record there.
R15 - Give a species a cry
Basic Lua + audio. Before you paste: For the first alternative, MODMON and assets/cry.wav must exist. The second alternative retunes PIKACHU instead; choose the one you intend to change.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.cries:register("MODMON", { file = mod.assets:path("assets/cry.wav") })
-- or derive from a vanilla cry:
mod.content.cries:patch("PIKACHU", { pitch = 200 })
Checkpoint: the cry plays on send-out and in the dex. Def shapes: a
file, a { base, pitch, length } derivation, or a chip program.
Gen 3: cries rows keyed by species play file and chip defs through
the Gen 3 audio engine. There is no vanilla cry row to patch, so the
PIKACHU derivation does not apply.
R16 - Add a growth curve
Functions. Before you paste: Assign growthRate = "MODCUBIC" to a registered species before testing. The formula here is a simple cubic example, not a recreation of a later game's similarly named curve.
Complete walkthrough / required concept.
Insert in main.lua inside the entry function (unless a filename is shown).
mod.content.growth_rates:register("MODCUBIC", {
expForLevel = function(level) return level * level * level end,
})
Checkpoint: a species with growthRate = "MODCUBIC" levels on your
curve. The curve must strictly increase; validation calls it at levels
1 and 2 and rejects a flat one.
Gen 2 / Gen 3: the curve applies on both. Gen 3 seeds its six native
curves (MEDIUM_FAST, ERRATIC, FLUCTUATING, MEDIUM_SLOW, FAST,
SLOW), so registering one of those ids fails as already registered; pick
a new id, or override a native one to replace it.
R17 - Add an evolution method
Advanced outline. Before you paste: You must define MODMON, MODMON2, and how friendship is maintained before this outline can produce an evolution. It does not implement a friendship system by itself.
Complete walkthrough / required concept.
Outline / alternative: read the requirements above; this is not a complete mod.
mod.content.evolution_methods:register("FRIENDSHIP", {
check = function(game, mon, evo, trigger)
return trigger.kind == "levelup" and (mon.friendship or 0) >= 220
end,
})
mod.content.pokemon:patch("MODMON", {
evolutions = { { method = "FRIENDSHIP", species = "MODMON2" } },
})
Checkpoint: the evolution fires when check returns true (vanilla
methods: LEVEL, ITEM, TRADE; src/pokemon/Evolution.lua). The
evolution.check hook wraps every check if you need to intercept
globally.
Gen 2 / Gen 3: both games already evolve on friendship natively. Gen 3
seeds its EVO_* methods (EVO_FRIENDSHIP, EVO_LEVEL, ...) as records, a
custom id is called as check(game, mon, evo, trigger) with trigger.kind
"levelup", "trade" or "item", and mon is the native party record.
On Gold an api 3 record is called this same way; an api 2 record gets
Gold's own check(entry, mon, ctx).
Start here
Playing
Tutorials
- Choose a tutorial
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Creative guides
Concepts
Recipes and reference
Author and developer tools
Home · Start Playing · Glossary · Troubleshooting · Repository · Community
Game data is imported locally from a supported ROM supplied by the player. Shared mods contain original work or transform recipes, never extracted game content. Check each guide's target game before using its examples.