Overworld Scripting ‐ A Complete Example - haven1433/HexManiacAdvance GitHub Wiki

Video Version

Click to return to the main scripting page

Introduction

In this tutorial, we'll be making a not-too-simple, but not-too-complex script, from the ground up. By the end of it, we'll have used flags, specials, sections, autos, and message boxes, as well as learned a few debugging techniques.

Outline

The goal is to make a character that asks to see a pokemon, and then gives you an item if you show it to them. An outline for the script would look like this:

Ask to see a Rattata? Yes/No
No -> ok, nevermind
Pick a pokemon from the team.
Not a Ratata? -> ok, nevermind
Thanks for showing me a Rattata!
Give Rare Candy
Explain what Rare Candies do.

And then if you talk to the character again, they'll just tell you what Rare Candies do.

Scripting

Since you're talking to a character, there's a few things we'll want in almost every script. Here's some boilerplate code:

section0:
  lock        # prevent normal NPC movement during the script
  faceplayer  # turn towards the player
  # your stuff goes here
  release     # allow normal NPC movement now that the script is over
  end         # end the script

section0 is called a "section header", and you can call it just about whatever you want, as long as you don't have spaces and end with :.

The bits you care about go in the middle. Let's add a bit of code for asking the user if they have a pokemon:

section0:
  lock
  faceplayer

  msgbox.yesno <auto>          # ask the player a yes/no question
{
Have you caught a RATTATA yet?
}
  if.no.goto <notyet>          # jump to another section if the player said no

  release
  end

notyet:
  msgbox.default <auto>        # show a message
{
If you catch one, let me know!
}
  release
  end

We ask the player a yes-or-no question, and then we jump to another section if the user says no.

We'll worry about how the "show a pokemon" part works a little later: right now, let's just pretend that the player is telling the truth, and go ahead and give them the item.

section0:
  lock
  faceplayer
  msgbox.yesno <auto>
{
Have you caught a RATTATA yet?
}
  if.no.goto <notyet>

  msgbox.item <auto> "RARE CANDY" 1 mus_level_up  # give item/jingle/message
{
Oh, cool! Take this RARE CANDY for
showing that to me.
}
  msgbox.default <auto>                           # show a message
{
You can use a RARE CANDY to make
your pokemon stronger!
}

  release
  end

notyet:
  msgbox.default <auto>
{
If you catch one, let me know!
}
  release
  end

Now we have a pretty good 'first draft' of our script. Let's start adding some details.

Documentation and Specials

There are hundreds of commands available for event scripting, but there are still some special-case things that are used only rarely that don't get their own command. Instead, all of these 'special case' things are put together into one command, the special command. It comes in 2 forms: special and special2. They both do the same thing, except that you use special2 when you want the special to set the value of a variable. See Specials for more information.

There's also documentation available within the application:

documentation.scripting.overworld.reference expample

Within here, you can find a list of every available scripting command / special, which links to a detailed reference document with examples of using each command and special. Using this reference, we can discover 2 specials that help with our specific task: ChoosePartyMon and GetPartyMonSpecies. Lets add those to our script to check if the player has a Rattata (species 19) in their team:

  special ChoosePartyMon                    # show party menu, store chosen party index in var4
  waitstate                                 # included because the documentation says to
  if.compare.goto var4 = 7 <notyet>         # branch if the player chose 'cancel'
  special2 varResult GetPartyMonSpecies     # get the species
  if.compare.goto varResult != 19 <notyet>  # branch if the player didn't choose Rattata

Flags

We've written most of our script, but if we test it, we'll notice that the player can get unlimited rare candies by talking to the NPC. We want the NPC to remember if it's already given an item to the player, so let's use a Flag to track this bit of information. Our general goal is something like:

top:
  if the flag is set, jump to bottom
  do the script
  set the flag
bottom:
  basic text explaining what rare candies do

Here's what that looks like in an actual script:

section0:
  lock
  faceplayer
  if.flag.set.goto 0x0021 <finish>  # you can name the 'finish' section whatever you want
  ...                               # stuff we've already written goes here
  setflag 0x0021                    # set the flag once we've given the item
finish:
  msgbox.default <auto>
{
You can use a RARE CANDY to make
your pokemon stronger!
}
  release
  end

Debugging

Always test your scripts! There may be some detail you messed up or didn't understand correctly. For example, when we test this script, we'll notice that after special ChoosePartyMon, the NPC starts walking around again. We can correct this by adding lock/faceplayer again after that special.

Other common things to watch for:

  • When you edit a script, any existing save file (or save state) may not load it correctly at first. Always leave and re-enter the map that contains the script to make sure that everything gets loaded correctly.
  • NPCs are only visible if their assigned Flag is clear.
  • Script events will only activate if their variable matches the trigger.
  • Script events will always activate if their variable matches the trigger. So make sure the script either moves the character or changes the value in their assigned variable.

Wrap Up

Here's the full script that we've written, all together:

section0:
  lock
  faceplayer
  if.flag.set.goto 0x0021 <finish>
  msgbox.yesno <auto>
{
Have you caught a RATTATA yet?
}
  if.no.goto <notyet>
  msgbox.default <auto>
{
Great! Please show it to me.
}
  special ChoosePartyMon
  waitstate
  lock
  faceplayer
  if.compare.goto var4 = 7 <notyet>
  special2 varResult GetPartyMonSpecies
  if.compare.goto varResult != 19 <notyet>
  msgbox.item <auto> "RARE CANDY" 1 mus_level_up
{
Oh, cool! Take this RARE CANDY for
showing that to me.
}
  setflag 0x0021

finish:
  msgbox.default <auto>
{
You can use a RARE CANDY to make
your pokemon stronger!
}
  release
  end

notyet:
  msgbox.default <auto>
{
If you catch one, let me know!
}
  release
  end
⚠️ **GitHub.com Fallback** ⚠️