Updated The Basics of Scripting (markdown)

tustin2121 2023-03-04 16:41:44 -05:00
parent 8751b9fe4f
commit f6f0ae8d6b
1 changed files with 360 additions and 5 deletions

@ -15,6 +15,14 @@ Table of Contents:
- [Player Gender Check](#Player-Gender-Check)
- [Hide/Show Map Objects](#HideShow-Map-Objects)
- [Give, Take, & Check for Items](#give-take--check-for-items)
- [Giving Pokémon](#giving-pok%C3%A9mon)
- [Movement](#Movement)
- [Random](#Random)
- [Pokémarts](#pok%C3%A9marts)
- [Weather](#Weather)
- [Door Commands](#Door-Commands)
- [Display Pokémon Sprite](#display-pok%C3%A9mon-sprite)
- [Screen Fading Effects](#Screen-Fading-Effects)
# Labelling
@ -106,7 +114,7 @@ Script_SimpleYesNoScript::
lock
faceplayer
msgbox Text_SimpleYesNoScriptQuestion, MSGBOX_YESNO
compare VAR_RESULT, 0
compare VAR_RESULT, NO
goto_if_eq Script_PlayerAnsweredNo
msgbox Text_PlayerAnsweredYes, MSGBOX_DEFAULT
release
@ -129,7 +137,7 @@ Text_PlayerAnsweredNo:
```
A few more notes about MSGBOX_YESNO:
- The `compare VAR_RESULT` line checks the result of the player's answer - 0 for "No", 1 for "Yes". More about vars later!
- The `compare VAR_RESULT` line checks the result of the player's answer - 0 for "No", 1 for "Yes" (or you can use the constants `NO` and `YES`, or `FALSE` and `TRUE` respectively). More about vars later!
- The `goto_if_eq` line means the script will go to a new label if the result is equal to what we specified above, in this case, 0. If it's *not* equal to that, the script will continue as normal.
@ -354,7 +362,7 @@ This command checks if the player has enough room in their bag for the amount of
```gas
checkitemspace ITEM_POKE_BALL, 5
compare VAR_RESULT, 0
compare VAR_RESULT, FALSE
goto_if_eq Script_NotEnoughSpaceInBag
```
@ -367,7 +375,7 @@ All you need is the above line, super simple. It even automatically generates a
```gas
giveitem ITEM_POKE_BALL, 5
compare VAR_RESULT, 0
compare VAR_RESULT, FALSE
goto_if_eq Script_BagIsFull
```
@ -392,7 +400,7 @@ Script_ItemDemonstration::
faceplayer
msgbox Text_ItemGiveaway, MSGBOX_DEFAULT
checkitem ITEM_POTION
compare VAR_RESULT, 1
compare VAR_RESULT, TRUE
goto_if_ge Script_HasPotionsAlready
msgbox Text_GivingPotion, MSGBOX_DEFAULT
giveitem ITEM_POTION
@ -487,6 +495,353 @@ Text_PlayerHasFullParty:
With the `getpartysize` command, we've checked if the player already has a full party, and if they do, the script will jump to the label `Script_PlayerHasFullParty` and the Pokémon won't be given. In the case that the player's party is not full, it'll give a level 5 Dratini holding a Dragon Fang. If you know what you're doing, you'll notice that this script will keep giving infinite Dratini if the player's party isn't full due to the fact that a flag isn't set. I figured that if people have read the flags section, they should be able to figure out how to rectify that on their own ;)
To give an Pokémon Egg instead of a Pokémon:
```gas
giveegg [Pokémon]
```
Example:
```gas
Script_GiveEggDemo::
lock
faceplayer
msgbox Text_EggQuestion, MSGBOX_YESNO
compare VAR_RESULT, 0
goto_if_eq Script_PlayerAnsweredNo
getpartysize
compare VAR_RESULT, 6
goto_if_eq Script_PlayerHasFullParty
giveegg SPECIES_LARVITAR
playfanfare MUS_FANFA4
msgbox Text_ReceivedEgg, MSGBOX_DEFAULT
waitfanfare
release
end
Script_PlayerHasFullParty::
msgbox Text_PlayerHasFullParty, MSGBOX_DEFAULT
release
end
Script_PlayerAnsweredNo::
msgbox Text_PlayerAnsweredNo, MSGBOX_DEFAULT
release
end
Text_EggQuestion:
.string "Will you take this Egg?$"
Text_PlayerAnsweredNo:
.string "Oh, that's too bad.$"
Text_ReceivedEgg:
.string "{PLAYER} received the Egg!$"
Text_PlayerHasFullParty:
.string "Your party is full.\n"
.string "There's no room for this Egg.$"
```
This script asks the player whether or not they would like to accept the Egg. After that, if the player responds with "YES", it'll check if they have space in their party before giving it to them.
# Give & Check For PC Items
Adding an item to the player's PC is just as easy with a single line:
```gas
addpcitem [Item], [Quantity=1]
```
Useful in cases where a player's bag might be full, but you want them to receive an item anyway. The items list is in `include\constants\items.h`. In order to check if a player has a particular item in their PC, we'd do:
```gas
checkpcitem [Item], [Quantity=1]
compare VAR_RESULT, TRUE
goto_if_[Condition] [Script Label]
```
A more fleshed-out demonstration:
```gas
checkpcitem ITEM_POTION, 1
compare VAR_RESULT, TRUE
goto_if_ge Script_HasPotionInPC
```
Should the player have one or more Potions in their PC's item storage, the script will go to the label `Script_HasPotionInPC`.
# Movements
To make the player / NPCs move in a script, we use the `applymovement` command:
```gas
applymovement [Local ID], [Movements Label]
waitmovement [Local ID=0]
```
The `applymovement` command starts an object moving along a path specified by a movement script with the given label. The `waitmovement` line ensures that the movements are finished before the script continues. `waitmovement` can take an object's id as a parameter, which will make it wait for that specific object to finish its movement, or it can take 0 (the default if it isn't supplied) to wait for the last object that `applymovement` was used on.
Let's say we wanted the player to move three steps upwards along with the NPC they're talking to:
```gas
Script_MovementsDemonstration::
lock
faceplayer
msgbox Text_MovementsDemonstration, MSGBOX_DEFAULT
applymovement 1, Movement_Example
applymovement OBJ_EVENT_ID_PLAYER, Movement_Example
waitmovement
release
end
Text_MovementsDemonstration:
.string "Hey!\n"
.string "Let's walk three steps up.$"
Movement_Example:
walk_up
walk_up
walk_up
step_end
```
`OBJ_EVENT_ID_PLAYER` is used as the player's local ID. I've used 1 for my NPC's ID just for example purposes.
Note: If you find that your NPC isn't following your movement, make sure you have a `waitmovement` call before `release`; `release` cancels any movement, and if the script doesn't wait, the movement won't get a chance to happen before the script finishes!
Note: If an object has a movement script still running on it, a second `applymovement` on it will not take. Make sure you `waitmovement` before applying another movement to the same object!
A list of movement types can currently be seen in `asm\macros\movement.inc`. Don't forget to add `step_end` to indicate that your movements are finished!
# Random
The `random` command can be used to generate a random number within the range you set, and then have the script go to various labels depending on the number. Let's say we wanted a range of 5:
```gas
random 5
switch VAR_RESULT
case 0, [Script Label 1]
case 1, [Script Label 2]
case 2, [Script Label 3]
case 3, [Script Label 4]
case 4, [Script Label 5]
```
The `switch`/`case` commands are a more concise way to do a series of `compare`/`goto_if_eq` statements.
Let's look at an example - a NPC who has three different things to say:
```gas
Script_RandomDemonstration::
lock
faceplayer
random 3
switch VAR_RESULT
case 0, Script_RandomOption1
case 1, Script_RandomOption2
case 2, Script_RandomOption3
end
Script_RandomOption1::
msgbox Text_RandomOption1, MSGBOX_DEFAULT
release
end
Script_RandomOption2::
msgbox Text_RandomOption2, MSGBOX_DEFAULT
release
end
Script_RandomOption3::
msgbox Text_RandomOption3, MSGBOX_DEFAULT
release
end
Text_RandomOption1:
.string "Option 1.$"
Text_RandomOption2:
.string "Option 2.$"
Text_RandomOption3:
.string "Option 3.$"
```
There are a whole bunch of things you could use this for! I like using it for my generic city/town population NPCs to make them a little bit more interesting, but you can use it for a lot more than that.
# Pokémarts
Creating your own shops is straightforward enough with the pokemart command.
```gas
pokemart [Mart Label]
```
All you have to do is choose what you'd like your shop to sell! The list of items can be seen in “include\constants\items.h”. Once you've decided on the items you want your mart to stock, just follow the example below. Let's say we wanted to make a herb shop, we'd have:
```gas
.align 2
Pokemart_HerbShop:
.2byte ITEM_ENERGY_POWDER
.2byte ITEM_ENERGY_ROOT
.2byte ITEM_HEAL_POWDER
.2byte ITEM_REVIVAL_HERB
.2byte ITEM_NONE
```
Make sure you remember to add `.2byte ITEM_NONE` indicate the end of the list of goods. (Note: Vanilla marts have `release` and `end` at the bottom of the item list, but this is not necessary.) A full length example:
```gas
Script_PokemartExample::
lock
faceplayer
message Text_HerbShopGreeting
waitmessage
pokemart Pokemart_HerbShop
msgbox Text_HerbShopEnd, MSGBOX_DEFAULT
release
end
.align 2
Pokemart_HerbShop:
.2byte ITEM_ENERGY_POWDER
.2byte ITEM_ENERGY_ROOT
.2byte ITEM_HEAL_POWDER
.2byte ITEM_REVIVAL_HERB
.2byte ITEM_NONE
Text_HerbShopGreeting:
.string "Welcome to our Herb Shop.\n"
.string "How can I help you?$"
Text_HerbShopEnd:
.string "Please come again!$"
```
# Weather
To manipulate weather in the overworld, use the following commands:
```gas
setweather [Weather Type]
doweather
```
We use `setweather` to choose the weather we'd like and `doweather` to activate it. For instance, here's the kind of script we'd need to start a storm:
<image align="right" src="https://user-images.githubusercontent.com/794812/222929218-33150b8a-f477-4f54-9551-2fadf9063720.gif">
```gas
Script_ExampleWeatherScript::
lock
faceplayer
msgbox Text_ExampleWeatherScriptPreRain, MSGBOX_DEFAULT
setweather WEATHER_RAIN_HEAVY
doweather
msgbox Text_ExampleWeatherScriptPostRain, MSGBOX_DEFAULT
release
end
Text_ExampleWeatherScriptPreRain:
.string "What a lovely day!$"
Text_ExampleWeatherScriptPostRain:
.string "Aww, I spoke too soon.$"
```
You can also use `resetweather` (no argument) instead of `setweather` to reset the weather to whatever is the default on the current map.
Note: `setweather` is a separate command from `doweather`, because `doweather` should not be used in transition scripts (more on that later); just using `setweather` is enough in the map loading scripts, and the normal map loading process with do the weather for you.
The weather list can be found in `include\constants\weather.h`.
# Door Commands
If you need a script that involves having the player or NPCs enter/exit a building, you'll need to know how to manipulate the door animations.
<img align="right" src="https://user-images.githubusercontent.com/794812/222929472-7ee9c388-bc6f-4704-bc5d-377fd667f345.gif">
```gas
opendoor [X], [Y]
waitdooranim
```
The first line, `opendoor`, is where we specify that we want the door to use its opening animation and its location on the map. This line should always be followed by `waitdooranim`, which waits for the door's animation to complete. The X/Y coordinates refer to the position of your door tile in your map. You'll need to make sure this is a proper door tile (that is, is an `MB_ANIMATED_DOOR` tile with the appropriate animation when interacted with normally).
To close the door again:
```gas
closedoor [X], [Y]
waitdooranim
```
There are two additional commands:
```gas
setdooropen [X], [Y]
setdoorclosed [X], [Y]
```
These do what you might expect, sets the door at the given coordinates to be open or closed without the animation.
# Display Pokémon Sprite
You might not use it too often throughout your hack, but showing a Pokémon's sprite can add a little something extra to scripts where the Pokémon is being discussed.
```gas
showmonpic [Pokémon], [X], [Y]
```
So you need to specify the sprite you want to display and the X/Y coordinates of the screen where you want the box containing the sprite to be drawn. The Pokémon species list is in `include\constants\species.h` if you need it. And to hide the box again:
```gas
hidemonpic
```
A full script example:
```gas
Script_DisplaySpriteDemo::
lock
faceplayer
showmonpic SPECIES_DRATINI, 10, 3
msgbox Text_DisplaySpriteDemo, MSGBOX_DEFAULT
hidemonpic
release
end
Text_DisplaySpriteDemo:
.string "Have you seen this Pokémon?$"
```
Coordinates of `10, 3` will display the box containing the specified sprite in the middle of the screen.
# Screen Fading Effects
It's easy to give the overworld a "fading out" effect - useful for cutscenes and such - by using the fadescreen command which looks like this:
```gas
fadescreen [Fade Type]
```
Fade types include `FADE_FROM_BLACK`, `FADE_TO_BLACK`, `FADE_FROM_WHITE`, and `FADE_TO_WHITE`. Here's an example:
<img align="right" src="https://user-images.githubusercontent.com/794812/222929736-a4137a9c-ac9c-4059-94f5-9b58598ae9c6.gif">
```gas
Script_FadescreenExample::
msgbox Text_FadescreenExample, MSGBOX_DEFAULT
fadescreen FADE_TO_BLACK
fadescreen FADE_FROM_BLACK
end
Text_FadescreenExample:
.string "Screen fading to black.$"
```
It's also possible to create a white version of the same effect:
<img align="right" src="https://user-images.githubusercontent.com/794812/222929799-f2266daf-9b1f-4200-9eef-a8be041bca6d.gif">
```gas
Script_FadescreenExample::
msgbox Text_FadescreenExample, MSGBOX_DEFAULT
fadescreen FADE_TO_WHITE
fadescreen FADE_FROM_WHITE
end
Text_FadescreenExample:
.string "Screen fading to white.$"
```