Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.
Great work on the tutorial series, Anthroyd, it is very comprehensive.
I have a question. Is it possible to add another menu option to the START screen? I ask because I want to try to implement a Persona/Shin Megami Tensei style Fusion Mechanic and I don't know if that would be possible given the tools we have.
THANK YOU for this. Your series has convinced me to start work on the hack I've been planning over lunch breaks for ages. Have a bump, keep the content rolling!
Hello Anthroyd, I would like to thank you for the amazing quality of this series. This is what one might call a proper video tutorial series.
UPDATE: I have Figured this out, see the edit. Everything between the two dashed lines below should be ignored if you are new to the scene, it is a wall of confusing nonsense.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Spoiler:
I would like to ask you something about the general use of XSE and AdvMap specifically with regards to map scripts (level scripts).
(Small Background: this is my first attempt at rom hacking ever, and thus I have little to no experience with how roms are supposed to behave when edited like that).
To begin, I will walk you through the steps in which to reproduce my problem.
So here goes:
1) Open PGE and load a fresh Pokemon FireRed v1.0 file.
2) Launch AdvMap through PGE and navigate to the Map in which to do the edit. (In this case Prof. Oak's laboratory).
3) Go to the Header Tab, press CTRL+H and look at the Map script offset (which includes the parts to be edited). (I am not sure if this is how it's supposed to be done)
4) At this point I have tried to do two things in order to complete the edit:
4a) Copy the Map script offset, go to PGE and open XSE, and then paste the Map script offset (168F7E) in the Offset box, toggle the Map Script button on, and finally decompile.
Do some edits to the script (in this case I'm editing the text part of the Srings section), Debug to make sure there are no errors, and then Compile.
Then return to AdvMap, save my work using the menu bar button and then test the result with VBA.
This results in some interesting things. The Script will run correctly, but it seems to have damaged some other part of the rom (possibly overwritten some data or parts of another script),
in this case resulting in Oak's individual person script being damaged. (I tried this multiple times, checking both scripts before and after compiling, and Oak's script seems to change right after the Map Script's compilation).
Is this supposed to happen when recompiling one of the original scripts?
4b) Copy the Map script offset, go to PGE and open XSE, do the pasting and decompiling, then edit the script to allocate it's pointers dynamically
(In my mind, this is to create a new copy of the script somewhere that wouldn't intrude or overwrite any original data [I have no idea if that's how things actually work])
by adding the "#dynamic 0x800000" to the beginning of the script and modifying all pointers to begin with @, removing most "0x"s and "0x8"s, except for variables and such, making it effectively a completely new script.
Then compile it and copy it's offset to the Map script offset field and hit "save changes and reload map" in AdvMap (which automatically updates the Script Offset field in the non-advanced Header view),
then save my work and test the hack. In this case, no other scripts seem to be affected, however, the newly compiled script runs smoothly all the way until it gets to the "END" line.
At this point the game will freeze, while the music still runs normally, my inputs stop working completely, and everything seems to be static.
(I have tried inserting msgbox commands in between the last lines of the main function to see where exactly the game is freezing, and It seems to be freezing right after displaying the msgbox before the END command,
leaving me unable to even close the msgbox. Note: this happens when using No$GBA. When tested in VBA, I am stuck at the last message box before the end command, and after completing the normal text,
it displays messages of giving the player a master ball then an ultra ball, then a great ball (all out of nowhere), then continues to spit out complete gibberish)
Here are both scripts I have attempted, and the original:
'---------
' Strings
'---------
#org 0x18DC94
= [rival]: Gramps!\nI'm fed up with waiting!
#org 0x18DFBC
= OAK: [rival]?\nLet me think[.]\pOh, that's right, I told you to\ncome! Just wait!\pHere, [player].\pThere are three POKéMON here.\pHaha!\pThe POKéMON are held inside\nthese POKé BALLS.\pWhen I was young, I was a serious\nPOKéMON TRAINER.\pBut now, in my old age, I have\nonly these three left.\pYou can have one.\nGo on, choose!
#org 0x18DCB9
= [rival]: Hey! Gramps! No fair!\nWhat about me?
#org 0x18E0EA
= OAK: Be patient, [rival].\nYou can have one, too!
'-----------
' Movements
'-----------
#org 0x1692B0
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1692B7
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1A75E9
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org 0x1692C0
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
'---------
' Strings
'---------
#org 0x18DC94
= [rival]: Gramps!\nI'm fed up with waiting!
#org 0x18DFBC
= OAK: Hmm? [rival]?\nWhy are you here already?\lI said for you to come back\llater...\lAh, whatever! Just wait there.\pLook, [player]! Do you see that ball on\nthe table?\lIt's called a POKé BALL. It holds\la POKéMON inside.\lYou may have it! Go on, take it!
#org 0x18DCB9
= [rival]: Hey! Gramps!\nWhat about me?
#org 0x18E0EA
= OAK: Be patient, [rival],\nI'll give you one later.
'-----------
' Movements
'-----------
#org 0x1692B0
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1692B7
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1A75E9
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org 0x1692C0
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
'---------
' Strings
'---------
#org @18DC94
= [rival]: Gramps!\nI'm fed up with waiting!
#org @18DFBC
= OAK: Hmm? [rival]?\nWhy are you here already?\lI said for you to come back\llater...\lAh, whatever! Just wait there.\pLook, [player]! Do you see that ball on\nthe table?\lIt's called a POKé BALL. It holds\la POKéMON inside.\lYou may have it! Go on, take it!
#org @18DCB9
= [rival]: Hey! Gramps!\nWhat about me?
#org @18E0EA
= OAK: Be patient, [rival],\nI'll give you one later.
'-----------
' Movements
'-----------
#org @1692B0
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @1692B7
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @1A75E9
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org @1692C0
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
So what exactly am I doing wrong?
It would be great if you can elaborate more specifically on the header tab, the difference between the script offsets specified in the normal and advanced views, and most importantly the correct way to modify or replace them.
Thank you for reading this if you did, and good luck with your studies!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Edit:
So as it turns out, I was attempting to modify a level script without understanding the scripts themselves or the User Interface under the Header tab in AdvMap.
I was trying to modify the "Map Script Offset" script in the advanced header view (CTRL+H when in the header tab), when I should have been working with individual level scripts in the normal header view.
For some reason, it was completely unclear to me how to navigate an individual Map's pre-existing scrips even though it turned out to be very simple.
Anyways, to see the level scripts of any given map, look under the Header Tab, in the Map Script box, Under the "Script No:" text. There is a white box with 0 in it and two tiny arrow buttons pointing up and down.
Using these buttons you can see all the map scripts attached to this map starting at script number 0, and going up. In my case, I've opened "PALLET TOWN (4.3)" which is Oak's lab.
Script No:0 is a Type 03 level script, and clicking on the up arrow button twice reveals two additional map scripts of types 04 and 02, script numbers 1 and 2, respectively.
The part which I wanted to edit was the text under the "Strings" section of the type 02 level script. You can see this part by copying the offset under "Script offset 2:", in my case (16923E),
and pasting it in XSE in the "Offset" box and clicking the decompile button (the one to the right of this box). Taking a look under the "Strings" section,
you can see the text that Oak says when you first enter the lab in the intro event where he gives you your first Pokemon.
In order to perform an edit, you must do some heavy editing to the original script before attempting anything new, in order to avoid damaging any original data.
Here is how i did it:
'---------
' Strings
'---------
#org @18DC94
= [rival]: Gramps!\nI'm fed up with waiting!
#org @18DFBC
= OAK: Hmm? [rival]?\nWhy are you here already?\lI said for you to come back\llater...\lAh, whatever! Just wait there.\pLook, [player]! Do you see that ball on\nthe table?\lIt's called a POKé BALL. It holds\la POKéMON inside.\lYou may have it! Go on, take it!
#org @18DCB9
= [rival]: Hey! Gramps!\nWhat about me?
#org @18E0EA
= OAK: Be patient, [rival],\nI'll give you one later.
'-----------
' Movements
'-----------
#org @1692B0
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @1692B7
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @1A75E9
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org @1692C0
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
'---------
' Strings
'---------
#org 0x18DC94
= [rival]: Gramps!\nI'm fed up with waiting!
#org 0x18DFBC
= OAK: [rival]?\nLet me think[.]\pOh, that's right, I told you to\ncome! Just wait!\pHere, [player].\pThere are three POKéMON here.\pHaha!\pThe POKéMON are held inside\nthese POKé BALLS.\pWhen I was young, I was a serious\nPOKéMON TRAINER.\pBut now, in my old age, I have\nonly these three left.\pYou can have one.\nGo on, choose!
#org 0x18DCB9
= [rival]: Hey! Gramps! No fair!\nWhat about me?
#org 0x18E0EA
= OAK: Be patient, [rival].\nYou can have one, too!
'-----------
' Movements
'-----------
#org 0x1692B0
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1692B7
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org 0x1A75E9
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org 0x1692C0
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
As you can see, I replaced all "#org 0x" with "#org @", and parts where functions are called like "applymovement MOVE_PLAYER 0x8" with "applymovement MOVE_PLAYER @".
Just be careful not to replace things like variables and such. In short, If you can't read and understand the script, you shouldn't be doing this yet.
So I basically changed all pointers into dynamic pointers and added "#dynamic 0x800000" to the beginning of the script such that it will compile as a completely new script.
This is done so that when you compile the script, It wouldn't overwrite the original script, which can result in some weird things happening in the game, potentially breaking it.
Now you may change whatever you want to change,
hit the compile button, and copy your new script's offset. Going back to AdvMap, go back to your level script, again, in my case the type 02 level script in Oak's lab,
and you replace the script's old offset with the new one (under "Script offset 2:" for type 02 level scripts) and hit save map scripts, and then save the changes to the rom (CTRL + S). And that should be it.
If I have made any mistakes explaining this, please do inform me.
Note: the rest of this event's scripts are normal Person events and scripts found under the events section of AdvMap.
I'm no Anthroyd (phenomenal video series, by the way!). But I think I can help you out with what's going wrong here. :)
**
First of all, re-editing the script to dynamically allocate its pointers is exactly what you should be doing - so good job. Doing it any other way, as you detail in step 4a, will overwrite other parts of the code; someday I'll write a proper tutorial explaining how and why this happens, but for now, here's a quick illustration.
Imagine each script in the map stored, in a long chain, from beginning to end. So in 4.4, you have Oak's speeches, the Pokédexes, Gary's trash-talking and so on. Each of these scripts is a different length and consequently occupies a different number of bytes - but they're all stored back-to-back, one after the other.
That's the important part - there is no space left between scripts in a vanilla FireRed ROM. (That would be wasteful, after all.) When Game Freak created the ROM, their compiler automatically worked out how many bytes every script needed, and allocated exactly that amount of space to each one. And no more.
Hopefully, it should now be clear why editing Oak's text to a longer string will inevitably corrupt, overwrite and generally mess up other scripts in the ROM. Since there is no additional space for extra text bytes, XSE will dutifully compile your changes over the top of an existing script. If you're lucky, this will only corrupt other person or signpost scripts, which are relatively easily fixed. If you're unlucky, you'll start messing around with map scripts, ASM code and image data, which are much harder to put right.
So... is it impossible to extend dialog, or otherwise modify scripts? Of course not! We simply need to find somewhere else to store our new, modified script - a location currently unused by the ROM. Some free space, in other words. And we then need to tell the game to look there when executing the script, instead reading from the original location.
This is what you've done with your new script. By adding the pre-processing directive #dynamic 0x800000, you're telling the compiler that you want it to start looking for free space, beginning at the offset 0x800000. (This is typically used because it's an easily memorable location, not because it's technically the beginning of the free space in vanilla FireRed. If you'd like to find your own space, crack open a hex editor and start hunting for FF bytes at around 0x71A500. But I digress - and 0x800000 is a perfectly good place to start storing your scripts.)
Time for a quick terminology lesson. There are two kinds of offset you should be familiar with when scripting: dynamic, and static. Dynamic offsets begin with the prefix '@', while static offsets begin with the prefix '0x'. The difference is, essentially, that static offsets point to a pre-determined location in the ROM - for instance, 0x167F7E - while dynamic offsets are placeholder labels. In other words, they don't point anywhere... yet.
That's why static offsets are always numerical. Since existing scripts are stored somewhere specific in the ROM, every script you decompile will be labelled with numbers, instead of text. For example:
#org 0x168F7E #org 0x168FE1 #org 0x168FF0
These numbers (well, offsets, really) are useful because they're the actual locations of each part of the decompiled script. If you open up a hex editor and 'Goto...' the offset 0x16923E, those bytes right there are the hex symbols corresponding to each of your scripting commands.
For example, at 0x16923E:
Code:
69 C7 00 4F 04 00 B0 92 16 08 51 00 00 [...]
...A meaningless string of bytes? Not quite. Armed with a bit of scripting know-how, we can manually translate this!
Code:
0x69 = lockall
0xC7 = textcolor, with parameter 0x0
0x4F = applymovement, with person ID 0004, using movement data at 1692B0
0x51 = waitmovement, with parameter 0x0000
...Well, you get the picture. (If you're wondering where I got the byte values, try F1 for XSE's Command Help.)
That said, when we're trying to read or write a script in XSE-language, static (or numeric) offsets aren't as easy to understand as dynamic offsets.
Why? Because dynamic offsets can be anything you like - text, numbers, or a combination of both. So they can be memorable, and they can help you organise your code. For example:
#org @start #org @text_1 #org @oakSpeaks01
This is one of the reasons it's preferable to use dynamic offsets when coding your scripts.
But the most important reason that you'll (almost) always want to use dynamic offsets in your custom code isn't just that it makes things easier to read. It's because any and all dynamic offsets will be automatically replaced by the compiler when you hit the button in XSE!
This sounds magic, but in fact, all that's happening is that the compiler is doing this:
1) Calculate length of script segment beginning at #org @dynamic_offset_01. 2) Search through the ROM for free space (FF bytes) of exactly that length. 3) Replace @dynamic_offset_01 with 0x(free space offset); for example, 0x800000. 4) Convert XSE commands into hex bytes. 5) Overwrite FF bytes with custom hex bytes. 6) Output list of offsets where custom code was stored, ready to be copied and pasted with AdvanceMap.
You could do this yourself with a copy of FSF, if you had the patience - going through each label, calculating the byte length of each section using the Command Help in XSE, and typing that into FSF manually. But it takes far too long to be practical - and sooner or later, you'd end up making a mistake. XSE's compiler is super-fast, however, and it doesn't screw up.
There's another, incredibly useful feature which only works with dynamic offsets, too. XSE's pre-processing directive #clean will automatically remove the last dynamically-compiled script from the ROM.
In other words, it'll replace everything it just compiled with FF bytes again. So, if you mess something up, you haven't wasted any space. You can just clean your old script off the ROM, and compile the modified one in its place!
tl;dr: static offsets are bad unless you know exactly what you're doing. Dynamic offsets are easier to understand, safer to use and can be erased at will.
**
...And all of that said, none of that is technically your problem here.
XSE is a great tool - but it never officially left beta. As such, there are a few quirks and bugs here and there. (Remarkably few, actually; it's one of the most solid hacking tools you'll ever come across. And paired with DavidJCobb's scripting reference, diego's Mega-Huge tutorial and Spherical Ice's level script documentation, you'll have essentially everything you need to code whatever you like.)
But XSE does *not* decompile level scripts properly every time. Which is what's going wrong here.
Here's the section of your code that's bugging out:
Code:
'---------------
#org @168FF0
#raw word 0x4055
#raw word 0x1
#raw pointer @16923E
#raw word 0x4055
But first, let's step through the code to see what's going on here (and what's going wrong).
...Incidentally, this is the first method I recommend for debugging a misbehaving script. Step through each line of code, commenting what it does as you go.
If you find yourself confused or unsure what a particular line is doing, chances are you've found your problem. (Or at least, you've found something to research, and you have a starting point for your bug hunt.)
So...
Code:
#dynamic 0x800000 // start looking for free space at 0x80000.
'---------------
#org @168F7E // this section of code is a header; it contains pointers to lists, one for each different type of level script
#raw 0x3 // this map contains type 3 level scripts
#raw pointer @168F8E // pointer to our type 3 level script handler
#raw 0x4 // this map contains type 4 level scripts
#raw pointer @168FE1 // pointer to our type 4 level script handler
#raw 0x2 // this map contains type 2 level scripts
#raw pointer @168FF0 // pointer to our type 2 level script handler
#raw 0x0 // end of map level scripts
'---------------
#org @168FE1 // list of type 4 level scripts
#raw word 0x4055 // which variable will the game check?
#raw word 0x1 // if the variable is 0x1, jump to and execute the following pointer
#raw pointer @168FEB // type 4 level script pointer
#raw word 0x0 // end of type 4 scripts
'---------------
#org @168FF0 // list of type 2 level scripts
#raw word 0x4055 // which variable will the game check?
#raw word 0x1 // if the variable is 0x1, jump to and execute the following pointer
#raw pointer @16923E // type 2 level script pointer
#raw word 0x4055 // which variable will the game check?
'---------------
#org @168F8E
[...]
And, you see, we've already found our problem. After checking for a variable, the code appears to stop abruptly - which will break the script execution, as you discovered.
Why does it stop? Because XSE has failed to decompile everything it found at the pointer 0x168FF0. (This isn't your fault and it's a tricky little bug to spot.) But if XSE won't decompile the whole script, what can we do?
Brute-force it, of course! Break out HxD and go to the offset 0x168FF0... and here's what you'll see.
We can translate this fairly easily; the bytes are all raw, which means they correspond directly to the hex codes you'll find in your editor. And they've just been flipped:
Code:
#raw word 0x4055
#raw word 0x1
#raw pointer 0x816923E
#raw word 0x4055
#raw word 0x7
#raw pointer 0x8169002
#raw word 0x0
So now we have our full, decompiled script. (We know to stop at the 00 00 mark because the game terminates its lists of level scripts with two 00 bytes - a raw word of 0x0.)
Here's my version of your code, cleaned up a bit and with handier labels for your dynamic offsets. Compile this, stick it in the Map Script Offset field in Advance-Map, and you should be ready to roll!
Code:
#dynamic 0x800000
#include stdpoke.rbh
#include stditems.rbh
#include stdattacks.rbh
#include stdmove.rbh
'---------------
#org @level_scripts_master_header
#raw 0x3
#raw pointer @list_of_type_3_scripts
#raw 0x4
#raw pointer @list_of_type_4_scripts
#raw 0x2
#raw pointer @list_of_type_2_scripts
#raw 0x0
'---------------
#org @list_of_type_4_scripts
#raw word 0x4055
#raw word 0x1
#raw pointer @type_4_script_01
#raw word 0x0
'---------------
#org @list_of_type_2_scripts
#raw word 0x4055
#raw word 0x1
#raw pointer @type_2_script_01
#raw word 0x4055
#raw word 0x7
#raw pointer 0x8169002 // this is your @type_2_script_02. It's a little long to decompile here, but feel free to plug 169002 into XSE if you want a look!
#raw word 0x0
'---------------
#org @list_of_type_3_scripts
setflag 0x2CF
compare 0x4055 0x1
if 0x1 call @type_3_script_01
compare 0x4055 0x7
if 0x1 call @type_3_script_02
compare 0x4055 0x8
if 0x1 call @type_3_script_03
checkflag 0x247
if 0x1 call @type_3_script_04
end
'---------------
#org @type_4_script_01
spriteface 0xFF 0x2
end
'---------------
#org @type_2_script_01
lockall
textcolor 0x0
applymovement 0x4 @oak_m1
waitmovement 0x0
hidesprite 0x4
movesprite2 0x4 0x6 0x3
spritebehave 0x4 0x8
clearflag 0x2B
applymovement MOVE_PLAYER @player_m1
waitmovement 0x0
applymovement 0x8 @gary_m1
waitmovement 0x0
clearflag 0x4001
playsong2 0x0
fadedefault
msgbox @t1 MSG_KEEPOPEN '"[rival]: Gramps!\nI'm fed up with ..."
closeonkeypress
pause 0x3C
msgbox @t2 MSG_KEEPOPEN '"OAK: Hmm? [rival]?\nWhy are you he..."
closeonkeypress
pause 0x1E
applymovement 0x8 @gary_m2
waitmovement 0x0
msgbox @t3 MSG_KEEPOPEN '"[rival]: Hey! Gramps!\nWhat about ..."
msgbox @t4 MSG_KEEPOPEN '"OAK: Be patient, [rival],\nI'll gi..."
setvar 0x4055 0x2
releaseall
end
'---------------
#org @type_3_script_01
movesprite2 0x4 0x6 0xB
spritebehave 0x4 0x7
playsong2 0x12E
return
'---------------
#org @type_3_script_02
movesprite2 0x4 0x6 0xB
spritebehave 0x4 0x7
return
'---------------
#org @type_3_script_03
setvar 0x4055 0x9
return
'---------------
#org @type_3_script_04
setflag 0x24F
return
'---------
' Strings
'---------
#org @t1
= [rival]: Gramps!\nI'm fed up with waiting!
#org @t2
= OAK: Hmm? [rival]?\nWhy are you here already?\pI said for you to come back\nlater[.]\pAh, whatever! Just wait there.\pLook, [player]! Do you see that ball on\nthe table?\pIt's called a POKé BALL. It holds\na POKéMON inside.\pYou may have it! Go on, take it!
#org @t3
= [rival]: Hey! Gramps!\nWhat about me?
#org @t4
= OAK: Be patient, [rival],\nI'll give you one later.
'-----------
' Movements
'-----------
#org @oak_m1
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @player_m1
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0x11 'Step Up (Normal)
#raw 0xFE 'End of Movements
#org @gary_m1
#raw 0x2E 'Face Up (Delayed)
#raw 0xFE 'End of Movements
#org @gary_m2
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0x26 'Step on the Spot Up (Faster)
#raw 0xFE 'End of Movements
Any questions, please fire away! (I really should write that tutorial sometime...)
Might've been covered in a video and I missed it but, what about editing stuff like game corner prizes? I've found tools that take care of the majority of stuff that I'm working on but nothing on this particular thing. I thought it'd be similar to the mart but it's a bit more complicated.
Replacing Tileset with Modern Tileset is too hard and this guide hasn't helped me at all in making a new hack rom . I would like to shot a positive comment, but I couldn't make an hack rom with this . It's just too hard. Like I can't put new tileset, can't modify the storyline etc. So annoying really. Also I already stucked in "assign double script to the NPC" , what? you can't , there's only 1 offset for NPC and it was not clear how to assign one more script to the NPC. Also when I make a new map, like new Pallet town I can see some pieces of buildings of other routes.. so many problems that made me bothered in making a new hack rom (was super hyped before realized it's so damn hard)
I'm updating this thread to alert that an update video has been completed and released. Thank you all for your support throughout the past two years. I really appreciate it.
I'm having the strangest problem, for some reason, when testing my game, SOME doors just don't work, even if the building and door weren't edited at all. Any idea what's happening? I've been using your tutorials.
EDIT: I fixed the problem, something I did changed the behavior bytes of some door tiles, if anyone knows why this happened, please tell me. I think it was either due to expanding tilesets or because I added a move to gastly's learnset.
I would like to point out something regarding map editing! I haven't seen any content in your tutorials, but I hope other people can help me too! I'm trying to change the hero's avatar/Icon/protagonist head on the town map. In this case it's Fire Red. Using unLZ I was able to find the male and female offsets at number 188 and 189. I have replaced some of the offsets with my own avatars, but I can never get the right colors. It's always messed up. Could anyone out there help me out?