Skip to content

Overworld Scripting ‐ Specials

ShinyTillDawn edited this page Jan 10, 2024 · 10 revisions

Click to return to the main scripting page

Introduction

This tutorial is centered around using specials, which are other events that ROM hackers can use in their scripts alongside regular scripting commands (like playsong and trainerbattle). All specials can be called with the special and special2 script commands, and each special has its own numeric ID and name.

The names of specials are preferred when displaying scripts instead of their numeric IDs. For instance, users of Hex Maniac Advance (HMA) would see special HealPlayerParty in their scripts instead of special 0.

This tutorial will cover common specials, how to find other specials beyond the scope of this GitHub page, and how to incorporate them into overworld scripts.

Common Specials

To get started with understanding and using specials, this section will list some common, easy-to-incorporate, and/or useful specials that are either abundant in the handheld Generation III Pokémon games or something ROM hackers are most likely to implement in a new script.

HealPlayerParty

This special has a numeric ID of 0x0. When calling this via a special command, all of the main character's Pokémon are fully restored as if they were healed at a Pokémon Centre.

SpawnCameraObject

This special has a numeric ID of 0x116 in Pokémon Emerald and 0x113 everywhere else. When calling this via a special command, it lets future applymovement and move.camera commands move the camera instead of an NPC. (The camera has an ID of 127.) In Pokémon Ruby and Sapphire, the special is named SpawnCameraDummy.

RemoveCameraObject

This special has a numeric ID of 0x117 in Pokémon Emerald and 0x114 everywhere else. When calling this via a special command, it no longer allows script commands to move the camera. In Pokémon Ruby and Sapphire, the special is named RemoveCameraDummy.

StartRematchBattle

This special has a numeric ID of 0x3E in Pokémon Emerald and 0x3B everywhere else. It is called BattleSetup_StartRematchBattle in the Hoenn games. This is particularly useful for starting a trainer battle with custom background music. The way to do that is outlined below:

special StartRematchBattle
playsong [song name] playOnce
trainerbattle 01 [trainer name] 0 <introText> <defeatText> <continueScript>

Fill in a valid song name (or number) and a trainer name (or ID), as well as a pointer to text for when the trainer is defeated. Note that due to the way this special works, the introText and continueScript pointers don't actually work, but it is a good practice to still put valid addresses. In addition, using this setup for NPCs that need to walk up to you prior to battling will cause the game to crash at runtime, so this setup would be most ideal for boss battles with more elaborate scripts.

DrawWholeMapView

This special has a numeric ID of 0x91 in Pokémon Emerald and 0x8E everywhere else. When calling this via a special command, the map refreshes in-game (in a sense) so that edits to the map (mainly via setmaptile commands) will properly register in-game.

ShakeScreen

This special has a numeric ID of 0x138 in Pokémon Emerald and 0x136 everywhere else. In Pokémon Ruby, Sapphire, and Emerald, the name is actually ShakeCamera. Depending on the values of a few temporary variables, calling it via a special command will cause the screen to shake as if an earthquake was occurring. ROM hackers can configure the shakes' intensity and direction by using a few setvar commands beforehand.

EnableNationalPokedex

This special has a numeric ID of 0x1F3 in Pokémon Emerald and 0x16F in Pokémon FireRed and LeafGreen. The other handheld games do not have this special. When calling this via a special command, the player will have the National Dex from now on. In Pokémon FireRed and LeafGreen, another special, IsNationalPokedexEnabled (0x193) is used to determine whether or not to allow trading with the Hoenn games/evolve certain Generation I Pokémon. Most ROM hackers elect to enable the National Dex right away.

Using Specials

To incorporate specials into scripts, one just needs to put special [name] or special2 [name] on its own line of code. Substitute [name] with the name of the desired special. (Make sure it's a special that exists in the edited game.) As for where to put the command in the script, it depends on what special is being used. Perhaps it needs to be placed after a message box, or it may need to be placed before a trainerbattle command. It may take a few tries to get the right placement, but that's OK. Making backups is recommended.

Some specials require a waitstate command so that future commands don't run right away. Check the documentation to see if the special in question mandates it. Usually, waitstate would occur right after the special/special2 command.

The difference between the 2 commands is that special2 requires specifying a variable to store the return value of the special's operation. Some specials hard-code which variable to store information in, so those would not need a special2 command, but using one anyway would not hurt. The other command (special) only requires a special's name.

Sample Code

msgbox.default <E4A820>
{
OK! Who wants to learn Comet Punch?
}
  setvar var5 30
  special ChooseMonForMoveTutor
  waitstate
  lock
  faceplayer
  if.no.goto <E4A770>
  msgbox.autoclose <E4A870>
{
Have fun!
}
  release
  end

This code snippet comes from the TM/Move Tutor Editing tutorial. After agreeing to teach a Pokémon Comet Punch, this code will run. It shows a message box that asks the player to select a Pokémon, and then a special is called to open the party menu and teach the selected Pokémon whichever move tutor ID is stored in var5. Afterwards, the code branches off into another section if the move was not taught after all. From there, either one message box shows or another.

This command requires waitstate and lock because this special allows other commands to run and other NPCs on the map to move.

Finding Other Specials

You can find every available special — with examples from the game — here.

Clone this wiki locally