New Field Moves Via the Party Menu & How to Add a Reskinned Clone of Rock Smash - haven1433/HexManiacAdvance GitHub Wiki
[Fire Red] How to add new Field Moves and make them work from the Party Menu, and How to add a reskinned clone of Rock Smash
Credits: 玉虫エリカ (Tamamushi Erika) and Defa for helping me understand how to modify the ASM
CREDIT IS REQUIRED! I spent nearly 2 and a half hours writing this tutorial (as you can see by the timestamps in this tutorial). (Ignore the fact the timestamps are all over the place; I wrote this tutorial out of order. It's been a long week.) Theoretically speaking, this tutorial should work for HUBOL, but I am willing to bet that the offsets for these tables are not the same as they are in vanilla. If someone can find the offsets for these tables in HUBOL, or prove they are the same as they are in vanilla, I will update this tutorial with this newfound info and tell you how to do it in HUBOL as well, but for now, go into this, assuming it's vanilla only.
Defa gave me ASM code earlier that can add a field move that reads the Behaviour Byte of the tile in front of you instead of the NPC Sprite in front of you, which, I think, is really nifty for things like Secret Power or Whirlpool. I will likely be posting that here tomorrow, but for now, I don't want to think about tutorials.
I also know how to change which field moves are locked to which badge, I.E. make Strength locked to badge 7 instead of badge 4, or add a new badge lock; (FRLG normally only has 7 badge HMs despite there being 8 badges.) If someone asks me to, I can make a tutorial on this, too, but I'm not doing that until later.
Something I forgot to write in the tutorial but wish I did, so I'll put it here: The cursor callback table is the table of pointers that tells the game which ASM code to go to when performing a field move from the party menu, which is why we put the Rock Smash clone ASM pointer there. If you have your own ASM (for example, the behaviour byte code I mentioned above that I will share tomorrow), you would put that ASM's pointer at the end of the table.
First, we want to go to 45A788, and CUT AND PASTE these bytes somewhere to free space. Write down and remember the offset we pasted it to. From this point on, I'm going to refer to this later as the "cursor callback table."
(figure 1)
Next, we want to go to 45A76E. This is the field move table. Notice the numbers 94, 0F, 13, 46, 39, F9, 7F, 64, 5B, D0, 87, and E6. These are the index numbers (in hex) of the field moves in order: Flash, Cut, Fly, Strength, Surf, Rock Smash, Waterfall, Teleport, Dig, Milk Drink, Soft-Boiled, and Sweet Scent. At the very end, there is an 0C byte. This 0C tells us that this is where the table ends. We want to add our new move. For this example, I'm going to use Brick Break and teach you how to make a Rock Smash clone.
(figure 2)
The index number for Brick Break is 280, which, when translated to hex, is 0x118. In little endian, we're going to add 18 01 to the table by deleting 0C 00, adding 18 01, and then adding 0C 00 to the end of the table like this:
(figure 3)
Now, go to 45A618. There is a table highlighted here that contains all of the options that can be shown on the party menu when you select a Pokémon. CUT AND PASTE this somewhere to free space.
(figure 4)
Now that we've repointed this table somewhere else, in the table viewer, click the bottom entry on the table, and click [Add 1 New].
(figure 5)
A new copy of Sweet Scent has appeared at the end of the name table; double-click the link, and it will take you to the move names table.
(figure 6)
Find the move you want to add as a field move, and copy its address.
(figure 7)
Go back to the table we were just looking at, and paste the address we just copied to the newest entry on the table.
(figure 8)
Now, go to 45A37C. There is a table located here for the field moves' descriptions. CUT AND PASTE this somewhere to free space.
(figure 9)
I don't know why all of the pointers aren't showing up as pointers: HMA moment, but that's not important. At the end of this table, we're going to add an offset for Raw text data that contains the description of your new field move. At 9300F9, I have text that says, "Break a brick." so I'm going to put <9300F9> at the end of this table here.
(figure 10)
Now that we've added Brick Break to the list of Field moves, we need to give it an effect and add that effect to the cursor callback table. For this tutorial, we're going to make a reskinned clone of Rock Smash. The ASM for Rock Smash is located at 0C99D9. We're going to want to COPY (NOT CUT) this chunk here and paste it somewhere that there's free space on an offset that ends in 0, 4, 8, or C. For example, 80242C or 912108 are valid offsets to paste to, but 80242E or 912107 are NOT.
(figure 11)
Inside our new code, you'll see a string of bytes called 11 9A 0C 08. Change this to the offset (in little endian) of the byte circled in yellow, relative to where you pasted it. In my example, this yellow byte is located at 903ED1, so I'm replacing 11 9A 0C 08 with D1 3E 90 08.
(figure 12)
The code now looks like this for me:
(figure 13)
Because of how ASM works, we have to get our hands a little bit dirty. Highlight the entire code, and click on [Code] at the far left of the screen and make sure the Code Type is set to "Thumb." Due to how ASM works, the bl instructions in our code changed in a way we do not want due to the fact that we pasted the code somewhere else, so we're going to modify them back to what we want them to be. There are 3 bl instructions in this code, which I have circled in red. We want to change the offset of the top one to 0C97A8, the middle one to 11FB0C, and the bottom one to 069AE4.
(figure 14)
Our new code grew in size, which means it worked. Now, I've circled a couple of bytes. First, look at the red circle. This 0x60 right here is the number associated with the NPC sprite (in hex). The Rock Smash rock's overworld sprite index number is 96, which translates to 0x60 in hex.
(figure 15)
In my hack, I have a brick sprite at overworld sprite index number 179, which translates to 0xB3 in hex, so I am going to change the red circled byte from 0x60 to 0xB3, so that Brick Break's code checks if there's a brick in front of the player instead of a cracked rock.
(figure 16)
Now that the red byte has been changed to the correct overworld sprite index, we're going to look at the orange circle now. This is the pointer to the script that will play when we execute our new field move. For this example, I'm just going to make Brick Break perform a text box that says "test." This test script is located at 903F70, so we'll replace the pointer with <903F70>.
(figure 17)
Now that all of this is done, we're going to take note of the offset located at the yellow byte. In my example, this byte is at 903E99. This offset is important in the next step.
(figure 18)
Remember the cursor callback table? Go back to the offest that you repointed this table to. At the very end of this table, write down a pointer to the offset of the yellow circled byte, followed by 0D 00 00 00. In my case, I'm writing <903E99> 0D 00 00 00:
(figure 19)
And we're done! We have successfully caused the game to execute a script when using a newly-added field move from the party menu when facing a specific NPC Overworld sprite.
(figures 20 & 21)