> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pret/pokeemerald/llms.txt
> Use this file to discover all available pages before exploring further.

# Scripting

> Write and modify event scripts in pokeemerald.

pokeemerald's script engine drives all in-game events — NPC dialogue, item pickups, flag checks, and more. Scripts are written in GBA scripting assembly and executed by the interpreter in `src/script.c` and `src/scrcmd.c`.

## Script files

| Path                        | Purpose                                                             |
| --------------------------- | ------------------------------------------------------------------- |
| `data/event_scripts.s`      | Top-level event script file; `#include`s all map and global scripts |
| `data/scripts/`             | Per-map script files                                                |
| `data/script_cmd_table.inc` | Maps opcode IDs to handler functions in `src/scrcmd.c`              |
| `data/specials.inc`         | Table of special functions callable via the `special` command       |

<Note>
  Scripts in `data/event_scripts.s` use pokeemerald's custom preproc macro format. [poryscript](https://github.com/huderlem/poryscript) is recommended for writing new scripts — it compiles a higher-level language to the binary script format and has a VS Code extension.
</Note>

## Script command table

`data/script_cmd_table.inc` assigns each opcode a constant name and a C handler. For example:

```asm theme={null}
script_cmd_table_entry SCR_OP_END        ScrCmd_end        @ 0x02
script_cmd_table_entry SCR_OP_SETFLAG    ScrCmd_setflag    @ 0x29
script_cmd_table_entry SCR_OP_SPECIAL    ScrCmd_special    @ 0x25
script_cmd_table_entry SCR_OP_CALLNATIVE ScrCmd_callnative @ 0x23
```

The full table is in `data/script_cmd_table.inc`. Handler implementations live in `src/scrcmd.c`.

## Specials table

`data/specials.inc` defines `gSpecials`, the table of C functions that scripts can invoke via the `special` command. Each entry is assigned an index automatically using `def_special`. A selection of real entries:

```asm theme={null}
gSpecials::
    def_special HealPlayerParty
    def_special SetCableClubWarp
    def_special ShowPokemonStorageSystemPC
    def_special GetTrainerFlag
    def_special DoTrainerApproach
    def_special PlayTrainerEncounterMusic
    def_special ObjectEventInteractionPlantBerryTree
    def_special ObjectEventInteractionPickBerryTree
    def_special Bag_ChooseBerry
    def_special ChooseHalfPartyForBattle
```

Call a special by name from a script:

```asm theme={null}
special HealPlayerParty
```

## Basic script syntax

Scripts are label-terminated lists of commands in ARM assembly syntax:

```asm theme={null}
Route101_EventScript_ProfBirch:
    lock
    faceplayer
    msgbox Route101_Text_ProfBirchHelp, MSGBOX_NPC
    release
    end
```

<Tip>
  Always pair `lock` with `release` and `end` every script path. Forgetting `release` will freeze the player's movement.
</Tip>

## Common script commands

<AccordionGroup>
  <Accordion title="Control flow">
    | Command                  | Description                  |
    | ------------------------ | ---------------------------- |
    | `end`                    | Terminate the current script |
    | `return`                 | Return from a `call`         |
    | `call <label>`           | Call a sub-script            |
    | `goto <label>`           | Jump to a label              |
    | `goto_if <cond> <label>` | Conditional jump             |
    | `callnative <func>`      | Call a C function directly   |
  </Accordion>

  <Accordion title="Player and NPC interaction">
    | Command                 | Description                  |
    | ----------------------- | ---------------------------- |
    | `lock`                  | Freeze the player            |
    | `release`               | Unfreeze the player          |
    | `faceplayer`            | Make the NPC face the player |
    | `msgbox <text>, <type>` | Show a message box           |
  </Accordion>

  <Accordion title="Items and Pokémon">
    | Command                                  | Description                      |
    | ---------------------------------------- | -------------------------------- |
    | `giveitem <item>`                        | Give the player an item          |
    | `givepokemon <species>, <level>, <item>` | Give the player a Pokémon        |
    | `special <name>`                         | Call a function from `gSpecials` |
  </Accordion>

  <Accordion title="Flags and variables">
    | Command                 | Description                              |
    | ----------------------- | ---------------------------------------- |
    | `setflag <flag>`        | Set a flag to TRUE                       |
    | `clearflag <flag>`      | Set a flag to FALSE                      |
    | `checkflag <flag>`      | Set the compare result to the flag value |
    | `setvar <var>, <value>` | Assign a value to a variable             |
    | `addvar <var>, <value>` | Add to a variable                        |
    | `copyvar <dest>, <src>` | Copy a variable                          |
  </Accordion>
</AccordionGroup>

## MSGBOX types

| Constant           | Behaviour                                       |
| ------------------ | ----------------------------------------------- |
| `MSGBOX_NPC`       | Standard NPC dialogue with A-to-advance         |
| `MSGBOX_SIGN`      | Sign-style box; closes on B or A                |
| `MSGBOX_DEFAULT`   | Box opens but does not auto-handle input        |
| `MSGBOX_YESNO`     | Appends a Yes/No prompt; result in `VAR_RESULT` |
| `MSGBOX_AUTOCLOSE` | Closes automatically after the text scrolls     |

## Map scripts

Map scripts run automatically at specific lifecycle points. Attach them in the map's `.inc` file using:

```asm theme={null}
map_script MAPSCRIPT_ON_LOAD,       MapName_OnLoad
map_script MAPSCRIPT_ON_TRANSITION, MapName_OnTransition
map_script MAPSCRIPT_ON_RESUME,     MapName_OnResume
```

| Hook                           | When it fires                                              |
| ------------------------------ | ---------------------------------------------------------- |
| `MAPSCRIPT_ON_LOAD`            | First time the map loads into RAM                          |
| `MAPSCRIPT_ON_TRANSITION`      | During the map transition (before fade-in)                 |
| `MAPSCRIPT_ON_RESUME`          | Every time the player returns to the overworld on this map |
| `MAPSCRIPT_ON_DIVE`            | When the player uses Dive on this map                      |
| `MAPSCRIPT_ON_RETURN_TO_FIELD` | After a battle or menu closes on this map                  |

## Using poryscript

[poryscript](https://github.com/huderlem/poryscript) compiles a higher-level scripting language to the binary format expected by pokeemerald. It removes boilerplate and makes branching logic readable.

<Steps>
  <Step title="Install poryscript">
    Download the latest release binary from the [poryscript releases page](https://github.com/huderlem/poryscript/releases) and place it in your `PATH`, or in the repository root.
  </Step>

  <Step title="Write a .pory file">
    ```asm theme={null}
    script Route101_EventScript_ProfBirch {
        lock
        faceplayer
        msgbox(Route101_Text_ProfBirchHelp, MSGBOX_NPC)
        release
    }
    ```
  </Step>

  <Step title="Compile to script binary">
    ```bash theme={null}
    poryscript -i input.pory -o output.inc
    ```

    Then `#include` the output file from `data/event_scripts.s`.
  </Step>

  <Step title="Install the VS Code extension">
    Search for **poryscript** in the VS Code Extensions panel, or install `karathan.poryscript` directly. It provides syntax highlighting and snippets.
  </Step>
</Steps>
