diff --git a/The-Basics-of-Scripting.md b/The-Basics-of-Scripting.md index 1856d2e..4a3ae07 100644 --- a/The-Basics-of-Scripting.md +++ b/The-Basics-of-Scripting.md @@ -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: + + + +```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. + + + +```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: + + + +```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: + + + +```gas +Script_FadescreenExample:: + msgbox Text_FadescreenExample, MSGBOX_DEFAULT + fadescreen FADE_TO_WHITE + fadescreen FADE_FROM_WHITE + end + +Text_FadescreenExample: + .string "Screen fading to white.$" +```