|
Generation 3 (Traditional) Traditionally, Generation 3 is hacked using tools, hex editors and patches. This is for you if you do that. |
![]() |
|
Thread Tools | Display Modes |
![]() |
#1 |
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]()
this is eventually gonna be a contents page promise x
Last edited by Alice; 2nd March 2018 at 10:34 PM. |
![]() |
![]() |
|
Sponsored Links |
![]() |
#2 |
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Part #1: The Basics ----------------------------------------------------------------------------------------------------------------------------------------------------- Pointers & Script Layout XSE uses dynamic offsets - meaning it automatically searches for free space from a given beginning offset. For the sake of this tutorial, we'll use #dynamic 0x800000, although it can technically be any free offset. 0x800000 and upwards is generally the safest, as from that point onwards there is a lot of free space to use. ![]() Thus, below should be the first line of your script. This means that every script you compile from now on will automatically compile to the first free offset it finds after 0x800000. ![]() Now, onto the second line of your script. A pointer is just a label for a section of your script, prefixed with @. It can be any mixture of letters or numbers as long as it doesn't contain any spaces or special characters. For example, we can have @MyScript1 but not @My Script 1. We'll call our first pointer @main for the sake of the tutorial, so now we've got this: ![]() The #org part notes that this is the start of a new script section labelled pointer @main. There are lots of different ways of "closing" the script which I will cover later in the tutorial, but for now I'll just show you the most basic way of finishing it: end. That's it. You can put whatever you want between your pointer and your "finishing statement", like this: ![]() Above is your basic layout. This tells the game to compile the script labelled @main to free space anywhere above 0x800000. |
![]() |
![]() |
![]() |
|
![]() |
#3 |
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() How To Compile Your Script To insert your script into your hack, or compile it, is nice and simple. First you want to open your ROM in AdvanceMap 1.92, and decide where you want your script to be run from:
In this example, we're going to assign a script to a NPC. Assemble your script, then hit this button: ![]() You should end up with a screen like this: ![]() All you have to do is copy that offset beside @start, or your beginning pointer, and paste it in the person event's "Script Offset" Box, shown here: ![]() For level scripts that are not triggered in the overworld, but from entering the map, you want to put your script here, outlined in red: ![]() Last edited by Avara; 1st March 2018 at 10:07 PM. |
![]() |
![]() |
![]() |
|
![]() |
#4 | ||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Simple Text Scripts Let's start with a basic NPC - we want to make someone face us and say hi, or in scripting terms, display a string of text. We do this with a msgbox. The msgbox command is set up like this: There are various msgbox types which we'll go through one at a time. Here's the most common, 0x6: ![]()
Spoiler:
So, we have quite a few new additions here. lock prevents the player from moving. Alternatively, lockall stops all NPCs on the map from moving. Should come directly after your #org @main but before your msgbox. faceplayer is fairly self explanitory too; it just makes the NPC face the PC before talking. release lets the player move again. If you used lockall instead, you'll have to use releaseall. After release or releaseall, finish with end. #org @greeting is a pointer to our text string, "= Hi!". I'll go into more detail on text info later, but the "=" basically tells XSE it's the start of a string, or line of text. That script will make someone face you and say "Hi!". Alternatively, there is a shorter way of scripting NPCs: msgbox 0x2. ![]()
Spoiler:
Using the above version, msgbox 0x2, means you don't need the lock, faceplayer or release commands, whereas msgbox 0x6 does. Both scripts do exactly the same thing. msgbox 0x3 is used in the original games for signposts; it displays the sign textbox when used on an actual signpost tile. Like 0x2, you don't need the lock, faceplayer or release commands. Quote:
Quote:
Last edited by Avara; 1st March 2018 at 10:07 PM. |
||
![]() |
![]() |
![]() |
|
![]() |
#5 | |||||||||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Additional Text Info As I mentioned before, the "=" before your desired script's text lets the program know you want the text that follows it to be displayed. Of course, there's a limit to how long the text can be - to ensure you're never wrong, use the Text Adjuster. ![]() The \n allows the text to go to a new line when it gets too long. After the initial use of \n, \l is used for each new line after that. As an example: Quote:
[player] will show up as the player's name in-game. Similarly, [rival] displays the rival's name. That text string, first with \n and then \l to break up the lines, will look like this: ----------------------------------------------------------------------------------------------------------------------------------------------------- We can display more than just the player or rival's name similarly, using buffer commands. These let you show the name of a Pokémon, item, attack or number.Now that we've got that handy list of hex IDs, we can move onto our first set of commands that use them. Let's start with the easiest; bufferfirstpokemon, set up like this: The [buffer number] part is where you choose the buffer number to assign the first Pokémon in your party's name to - for [buffer1] set this to 0x0, for [buffer2] set this to 0x1, etc. The [buffer1] part is what you'll be using in your text to display the PC's first Pokémon's name like so: Quote:
Like before, you need to assign the Pokémon's name to a buffer number. Using that list of hex IDs from earlier, you can then choose a Pokémon's name to display. Let's pick Venusaur for example, or the Pokémon ID number 3. Here's an example combining bufferfirstpokemon and bufferpokemon, assigning them to buffer numbers 1 and 2 respectively. Quote:
The bufferitem and bufferattack commands are almost identical to bufferpokemon, set up like this: All you have to do is choose your buffer number as before, and an item ID. For the sake of the tutorial, let's use item ID #1 - a Master Ball in both FR and EM. Quote:
Quote:
Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- The buffernumber command isn't as straightforward. It actually shows the numerical value of a variable. We'll go into more detail on variables later, but let's use 0x8000 and its value is 100 for example purposes. Quote:
Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- ![]() Adding color to your text is a nice way of differentiating characters and making item or place names stand out. Quote:
Spoiler:
Emerald Colors:
Spoiler:
Last edited by Avara; 1st March 2018 at 10:08 PM. |
|||||||||
![]() |
![]() |
![]() |
|
![]() |
#6 | ||||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Conditional Text Scripts Let's start the next section with something nice and simple, shall we? Throwback to our msgbox command. This time we'll be looking at msgbox 0x5, or in other words, making a script where the player can answer "Yes" or "No". ![]()
Spoiler:
The goto command is exactly as it sounds; it literally tells the script to go to another pointer. compare 0x800D, or compare LASTRESULT gets the result of the player's choice - in msgbox 0x5's case, 0x0 for 0 "No" or 0x1 for 1 "Yes". Notice that when the player chooses "Yes", it doesn't go straight to the msgbox command which displays the text. This needs to be contained in its own script section, hence why I named the pointer "@YesOrg" for convenience. If you accidentally send your "Yes" pointer to the pointer for the text string(@yes) instead of the script section it's contained in (@YesOrg), bugs will follow. If the LASTRESULT, or 0x800D is not 0x1 for "Yes" it will not goto @YesOrg, it just continues the script, meaning it displays the text string for @no and closes. goto works just as well - the example below will give you the exact same results as the script above. ![]()
Spoiler:
----------------------------------------------------------------------------------------------------------------------------------------------------- Let's go back to our basic NPC scripts for a moment. Every city needs filler NPCs, and they can get boring if they just say the same thing over and over again. In comes our next handy command, random. All it does is generate a random number within the range you set and then goes to the appropriate pointer, like this: Quote:
![]()
Spoiler:
----------------------------------------------------------------------------------------------------------------------------------------------------- Now we've covered random, we can move onto multichoice. For those of you who don't know what a multichoice box is, here's an example. ![]() The layout for the multichoice command is as follows: Quote:
The 0x1 at the end means the player can't press B to exit the multichoice box. If it's 0x0 it can be cancelled with B - 0x1 is just my personal preference as it forces the player to pick a choice. Here's an example script from the above screenshot of a FireRed ROM, with "Yes", "No" and "Info" as options:
Spoiler:
The copyvar command here copies the result stored in LASTRESULT to var number 8000 so it can be compared to the result of the player's choice. More on vars later. Depending on the player's choice, you can make the script goto a different @pointer. ----------------------------------------------------------------------------------------------------------------------------------------------------- Another minor conditional script example is one based on whether the player chose the male or female character - for this we could use the checkgender command: Quote:
Quote:
|
||||
![]() |
![]() |
![]() |
|
![]() |
#7 | |||||||||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Flags & Variables Think of a flag as an on or off switch - it can be either 1 "ON" or 0 "OFF". Think of a variable as a better version of a flag - it can't just be 0x0 or 0x1 "on or off"- but holds any value between 0x0 and 0xFF, hence the name "variable". Both are crucial for creating your gameplay events, but we'll focus on flags for now: Quote:
Quote:
![]() Here is a list of "special" flags for each game - these have different in-game functions when set, or "ON": FireRed:
Spoiler:
Emerald:
Spoiler:
----------------------------------------------------------------------------------------------------------------------------------------------------- karatekid552 and DavidJCobb did an excellent job of referencing every flag and variable in the FireRed ROM and what they do. If you hack FR, this documentation will be invaluable to you. Emerald hackers will find this information on flags/vars useful.----------------------------------------------------------------------------------------------------------------------------------------------------- Let's move on to variables. Quote:
Quote:
Quote:
Quote:
Now that we know how to add to, subtract from and set a variable, how do we check it? Quote:
Quote:
Quote:
|
|||||||||
![]() |
![]() |
![]() |
|
![]() |
#8 | |||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Part #2: The Core ----------------------------------------------------------------------------------------------------------------------------------------------------- Give, Take & Check For Items Before you think about the multitude of free items you can give your players, you should always make sure they can actually take the item first! Quote:
Not using this command prior to giving items can cause the player to "lose" them if they've got no space in their bag to take it. Now, onto actually giving the items! There are two ways of doing it: Nice and simple, and this way you even get a little message box automatically generated to notify the player that they've received the item. There is another way of giving the player an item "silently", meaning no pop-up notification. This version is useful for if you want to add your own custom string, for example: Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- Checking for items is easy with the checkitem command, set up like this: Let's see an example and check if the player has one Master Ball. I used if 0x4 instead of 0x1 because this time, we're checking not that we have exactly one Master Ball - we're checking that we have more than one before we go to our pointer @Has. Quote:
Remember that if you're using the header file "#include stditems.rbh" you can substitute the item ID for its name beside the #define in any of these cases, e.g. if you want to take the player's Master Ball you could have: ----------------------------------------------------------------------------------------------------------------------------------------------------- Adding an item to the player's PC is just as easy with a single line: Useful in cases where a player's bag might be full, but you want them to receive an item anyway. |
|||
![]() |
![]() |
![]() |
#9 | |||||||||||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Giving Pokémon & Eggs Wondering how to give your player a Pokémon? In order to do this, we'll need to make use of two commands called givepokemon and countpokemon. Here's an example of how to use both, incorporating some things we've learned already:
Spoiler:
This script is for a NPC who gives the player a Bulbasaur - if they answer "Yes" to the question and have room for it in their party. It only happens once, afterwards the NPC says something generic. Let's break it all down: Quote:
Quote:
Quote:
compare 0x800D 0x6 compares the result of countpokemon to 6, and if it is 6, the script goes to the pointer @Full. Quote:
Quote:
Quote:
Quote:
We've used msgbox 0x4 here, followed by waitfanfare then closeonkeypress, which prevents the message from being closed until the jingle has finished playing, similarly to how the pop-up message for finding items on the ground is. Quote:
Quote:
return takes us back to our original script when the nicknaming screen is exited. *If you're hacking Emerald, 0x2723DD for nicknaming instead of 0x81A74EB. Those are just pointers to already existing in-game scripts containing specials, which we'll cover much later! Quote:
Quote:
|
|||||||||||
![]() |
![]() |
![]() |
#10 | ||||||||
Beginner
Join Date: Nov 2013
Posts: 33
![]() |
![]() Sounds, Fanfares & Music Since we're hacking a Pokémon game, let's start with the cry command: Quote:
Quote:
Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- It's kind of hard to describe what a fanfare is - in not so many words it's a short tune, for example, the healing jingle in Pokémon Centers. To use one in your script, use these lines: Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- For sounds, the layout is almost identical to fanfares: Quote:
----------------------------------------------------------------------------------------------------------------------------------------------------- If you'd like to play music through your script, this is also nice and simple: Quote:
Quote:
Quote:
|
||||||||
![]() |
![]() |
![]() |
Tags |
scripting, tutorial, xse, [Document], [Tutorial] |
Thread Tools | |
Display Modes | |
|
|