Skip to content

Tutorial 05 New Move

bryanthaboi edited this page Sep 9, 2026 · 2 revisions

Tutorial 05 — New move

Make: Give Abra a new attack that can lower its target's Defense after hitting.

Before you start: Intermediate. Complete Tutorial 02. Read the short callback explanation in Modding Basics. You need a practice Abra below level 10.

Game: Red, local single-player. Use a practice save for experiments. If file creation is new to you, start with Tutorial 00; unfamiliar words are in the Glossary.

1. Set up the files

Create a new tutorial_05 folder in your mod location. Disable earlier tutorial mods for this exercise. The starting state is this empty folder; the finished state is all the files below.

This is a mod folder, not the engine root. Do not replace the engine's own main.lua. Preserve filenames and avoid an extra .txt extension.

Finished folder layout:

mods/tutorial_05/
  main.lua
  manifest.json

Each link opens a complete file you can save at the matching path. The JSON and Lua are also printed in full below; do not append them to another lesson's entry function.

File in this mod Complete example
main.lua Download main.lua
manifest.json Download manifest.json

2. Describe the mod

Complete file — replace tutorial_05/manifest.json:

{
  "id": "tutorial_05",
  "name": "Tutorial 05",
  "version": "1.0.0",
  "entry": "main.lua",
  "api": 2,
  "games": [
    "red"
  ]
}

id is the stable internal name, name is the label in MODS, and entry tells the loader which Lua file to open. games limits these examples to Red. Keep commas between JSON fields and no comma after the last field.

3. Write the change

Complete file — replace tutorial_05/main.lua:

return function(mod)
  mod.content.move_effects:register("TUTORIAL_BEAM_EFFECT", {
    kind = "secondary",
    run = function(ctx)
      if ctx.rng(0, 255) < 85 then
        ctx.changeStage(ctx.target, "defense", -1)
      end
    end,
  })
  mod.content.moves:register("TUTORIAL_BEAM", {
    id = "TUTORIAL_BEAM", name = "TUTORIAL BEAM", type = "PSYCHIC_TYPE",
    category = "special", power = 80, accuracy = 90, pp = 10,
    effect = "TUTORIAL_BEAM_EFFECT",
  })
  mod.content.pokemon:patch("ABRA", {
    learnset = { __append = { { level = 10, move = "TUTORIAL_BEAM" } } },
  })
end

Understand what you wrote

The moves record names the attack, sets its battle values, and points to an effect ID. The effect is registered separately in move_effects; its run function is a callback, which the engine calls when that part of the attack happens.

kind = "secondary" runs the effect after the attack's main damage step. The callback receives ctx, the current battle information and helper functions. ctx.target is the defending battler, and ctx.changeStage changes one of its temporary battle stat stages.

ctx.rng(0, 255) < 85 chooses 85 of 256 possible results, approximately a one-in-three chance. Use the engine's supplied random function so the effect follows the battle's random sequence. Not every successful hit will lower Defense.

The species patch adds the move to Abra's level-10 learnset. It does not instantly teach every existing Abra: a Pokémon must level through that point. An Abra already above level 10 needs a fresh setup or a separate teaching mechanism.

PSYCHIC_TYPE is the engine's exact Psychic type ID. The display name PSYCHIC is not a substitute in this field. This example uses existing battle audio; registering a new move does not require inventing a sound ID.

4. Load and check it

Save every file, restart the app, enable the mod for Red in the launcher's MODS panel, and launch. Resolve any load error before checking gameplay. Troubleshooting shows where errors appear. With default desktop bindings, A is Z/Enter/Space, B is X/Backspace, and Start is Escape/keypad Enter; use your configured controls if different.

Optional source-checkout validation

If you have Python 3, LuaJIT, and the engine source with Red imported, open a terminal in the engine root containing tools/. For a mod installed in that checkout's mods directory, run:

python3 tools/modkit.py validate tutorial_05 --base imported

If you saved it elsewhere, replace the mod ID with the quoted full path to its folder. A validation error identifies a file or content rule to fix; a pass means you can continue to the in-game checks. It does not prove rendering, sound, or the entire playthrough works. Packaged-app users can use MODS errors and the checkpoints without setting up these command-line tools.

Checkpoint

  1. Obtain an Abra below level 10, or use the Save Editor to create a level-9 Abra on a practice save with the mod enabled.
  2. Raise it from level 9 to 10 in game. If training Abra with Teleport is awkward, put it first, switch to another party member during a wild battle, and win so Abra receives experience. A Rare Candy on the practice save is another way to cross the level boundary.
  3. Confirm Abra learns TUTORIAL BEAM. Enter another wild battle and select it. It should deal damage as a special Psychic-type attack.
  4. Try it across several surviving targets to observe the Defense reduction. A miss, a defeated target, or a hit without the secondary effect is not a syntax failure.
  5. For exact loaded values, use the developer console to inspect data.moves.TUTORIAL_BEAM.power (80) and .pp (10).

Common pitfalls

What you see What to check
My Abra does not have the move Restart after enabling, then level a below-10 Abra through level 10. Existing higher-level party members are not automatically retaught.
Defense does not drop each hit The effect has an approximately one-in-three chance and requires an appropriate surviving target.

For syntax, missing-file, and restart problems, use Troubleshooting. Compare the whole finished file before changing several things at once.

Undo and continue

Keep the practice save and its matching mod files together. Saves can contain this example's custom content or progress. To compare with vanilla Red, disable the mod, restart, and open a separate unmodified practice slot. Do not overwrite the only copy of a modded save while its content is disabled. Save recovery explains backups.

Events and Hooks explains callbacks more broadly. Tutorial 10 uses a move effect to apply a new status condition.

Return to the tutorial index to choose the next lesson.

Clone this wiki locally