Making Pokemon Emerald my own one tweak at a time - Scarlet's March of gaming
In the month of March I had such lofty ideals, as I often do. I said to myself “I really want to beat Skyrim”, and I really did want to. I got the game downloaded, and as I sat through Brynjolf's iconic monologue in the ever-romantic horse-drawn carriage ride, a further intrusive thought emerged. I don’t know where it came from, and I don’t know why it appeared as I watched a man try to escape captivity and shortly thereafter get shot by an Imperial arrow. I wanted to make a Pokemon Emerald ROM hack. In that moment I closed the game and jumped onto Google, so instead of my usual jaunt of talking about old games and discovering a few new gems for my collection, I wanted to instead take some time to talk about my first real dive into the world of Pokemon ROM hacking in this glorious era of decompiled games.
As a bit of a precursor I will mention that you don’t need programming experience to poke around and make some simple changes, though it surely doesn’t hurt. Available over at the pokeemerald GitHub repo you can find the vast majority of the game’s underlying workings transcribed to some pretty damn readable C code. I won’t pretend to understand the process of decompiling a game and getting it to this state, but the folks behind this project have made it entirely trivial for anybody to follow a simple list of instructions and build the game for themselves. With such power, how could I not want to poke around a little and fine-tune this already-great game to my liking?
Now while I am technically a professional programmer, my domain is largely the more intuitive language of C++, and beyond that I’m used to working in considerably smaller files than these 3000+ line behemoths. Even so, you might be surprised at just how easily you can add in a new feature or two by just hitting your head against the wall and searching for words. My first hack of sorts had four major objectives to get me going: implementing a level cap, an experience multiplier, adding in new natures, and for a bit of fun, making it so the Focus Band’s effect is always active.
If you managed to follow the instructions on the setup page, what you’ll be looking at is a built “pokeemerald.gba” ROM, and a whole bunch of files you don’t know what to do with. To make the project a bit easier to navigate, you’ll want to pick an IDE to load it into, with one of the more accessible (and free!) being Visual Studio Code. This is basically a lightweight code editor with a bunch of plugins you can use that’s able to load the full breadth of the project for you. This lets you move quickly between files, but perhaps more importantly for surface level edits like what we have planned here, lets you search for keywords through the entire project. This is really important if you operate the way I do.
Adding More RNG!
We’re basically all setup now, so let’s actually get started on making some edits; making the Focus Band always active seems like a good first task. If you’ve managed to sleep on this item, it’s one of very few viable items for competitive battling in Gen 3, and is held by a colossal 80 Pokemon in the Battle Tower (and 24 in Trainer Hill if you remember that’s a thing that exists in Emerald). Its purpose? To provide you with a 10% chance to survive any hit. A reusable 10% chance I might add. It throws in that bit of extra spice that Pokemon battling really needed on top of the variable damage formula and random critical hit chance. So where do we start? With the decompilation being labelled so well, searching for “FOCUS_BAND” across the project seems like a good place. You can do this in VS Code by clicking on the Search button on the left bar, or pressing Ctrl+Shift+F. And would you look at that, 150 results in 22 files!
This usage is split between a few different variables, and the way it works is actually pretty simple to follow. “ITEM_FOCUS_BAND” is the value that’s used to say the item is being held, and if it is being held, the hold effect is set to “HOLD_EFFECT_FOCUS_BAND”. Following that, the hold effect of the currently held item is checked against all known values in the “battle_script_commands.c” file to see which effect should happen. For the Focus Band in particular, it rolls a random number between 0 and 99, and if the value is less than 10, the effect triggers. We want this 10% check to remain intact, but we can kill the check for actually holding the Focus Band.
And that’s basically it. There are five places where “HOLD_EFFECT_FOCUS_BAND” is checked for, so we just remove those and the game thinks we’re always holding the Focus Band. We’ve not messed with much more here, so other hold items should continue to work fine alongside this effect. If you wanted to be the most thorough, you can also edit the message that pops up when that 10% chance triggers, and this is again just a simple search for the relevant text. In “battle_message.c” you’ll find the appropriate message "{B_DEF_NAME_WITH_PREFIX} hung on\nusing its {B_LAST_ITEM}!". The {B_LAST_ITEM} is the key part we need to remove, since having no item will result in the message saying “Pokemon hung on using its ????????????!”, and that’s less than ideal. Changing it to say willpower or friendship is pretty fitting, but with that we’re done. Save your changes, remake the ROM and jump into battle. You should notice that every so often both you and your opponent won’t faint from a lethal hit, along with your custom survival message.
Changing the Natural Order
Moving onto my next goal, adding new natures largely followed a similar pattern. The idea here is that if we want to make a new nature we should probably search for instances of an already-existing nature and copy what they do, and a search for “BASHFUL” gives some good results.
From our search we can conclude that natures are stored as “NATURE_BASHFUL”, and there are nine places we’ll need to edit to put a new one in. A lot of these are pretty minor, like which type of AI the Pokemon will use in Battle Palace, so you don’t really need anything bespoke. Reusing another nature’s values that you feel fit close enough will do fine. The real point of interest for me is the “gNatureStatTable” value in “pokemon.c”. This is actually how the stat-altering effects of the natures are applied, with 0 meaning no change, +1 being a 10% boost, and -1 being a 10% reduction. By adding in your new nature to this table, you can have any assortment of stat boosts and reductions; you aren’t limited to one of each! I decided to have a Lucky and Unlucky nature myself, with these providing a boost and reduction to all stats respectively.
If you wanted to take this a step further, there’s a few other things you could do. By searching for where the “gNatureStatTable” value is used, you can see there’s only a few places where the stats are calculated. There’s nothing stopping you from having other values in this table between -128 and 127, and adding them into any place where these checks are done. I plan to mess with this further to have special natures to debuff particularly strong Pokemon, and the simplest way of doing this would be to have a -2 value that reduces certain stats by 20% as opposed to the standard 10%. You’d then alter the “PickWildMonNature” function to only use those natures with certain species. A bit more involved for sure, but with the code at your fingertips the sky really is the limit if you have the patience to poke around and figure things out.
I did actually edit PickWildMonNature myself to make my new natures appear as a separate 1/100 check
Making Nuzlocke Players Actually Fight Trainers
My last two changes of this post go somewhat hand in hand. In recent times, nuzlocking, the act of beating a Pokemon game with a number of set restrictions, has moved on a little. Gone are the days of forming an attachment with your team and getting through the games by any means necessary. Nowadays “hardcore nuzlockes” are all the rage on YouTube, and a large component of these playthroughs are a level cap that restricts your team’s level to the strongest Pokemon of the next gym leader’s party. These level limits are self-imposed, and these players often use Rare Candies to ensure their whole team is at the limit for the boss fight. We can do better.
The easiest way I could find for implementing a level cap was to just ensure a Pokemon didn’t level up unless we had enough badges. This means any experience gained while at the level cap will still be stored, and then be used after the next badge was obtained. There’s actually only two places edits need to be made here, and the flags we need to check already exist for each gym badge. After a bit of searching, I landed in the “battle_controller_player.c” and “pokemon.c” files, the former handling the act of levelling up in battle, and the latter being something I only really stumbled upon after a bit of play testing.
When you gain experience in battle, your current experience and gained experience are added together to check if you’re beyond a threshold to level up. If you are, that satisfying ping of the experience bar will play, and your stats will be boosted. We’re keeping all of that, but just adding in a check to see which badges we have. If we have Badge 8, our level cap is 58. Badge 7 means a level cap of 46, and so on. We then just tack this onto the check, and we’ll only level up if we’re below the level cap. Nice! The changes to “pokemon.c” are a little less intuitive, but they do make sense. You see a Pokemon in the PC is stored differently to a Pokemon in your party. The game basically trims the fat and leaves the essential data to be able to recalculate what your Pokemon’s data will be when it’s in your party. The level is part of the fat that’s trimmed; it doesn’t need to be stored when it can always be recalculated using the Pokemon’s experience. With that in mind, we throw in the same bit of code for the level cap in the "GetLevelFromMonExp" function, and to my eye we’re set. Pokemon level up fine to the level cap, and then are frozen in time until you’ve beaten the respective gym. After that they’ll gain a slurry of stored experience all at once.
Now that’s out of the way, let’s look at tackling the use of Rare Candies. I get it, grinding is tiresome. So let’s just multiply the gained experience by, say, eight. On top of this, we can make it that you gain no experience for fighting wild Pokemon. I think this is actually pretty balanced, and a bit more of a fun approach when compared to using Rare Candies. This basically means that grinding isn’t a chore, but it also means that you do need to pick and choose some optional trainers to fight between your big challenges. It keeps the game fresh and challenging, and it’s just three lines of code! This one took me more tracking down than I’d care to admit, but it culminated in the below lines in the “battle_script_commands.c” file. It looks so simple, and that’s really because it is! A weird note is that gBattleMoveDamage is used to store the gained experience for some reason, and it needs to be set to 1 for wild Pokemon as opposed to 0 to avoid a softlock if you’ve gained 0 experience but are already over the threshold for levelling up… A conundrum I introduced myself with the previous tweak.
But that’s it for my first ROM hack. I didn’t change much, but I’ve made a version of Pokemon Emerald that really is to my own taste, and it’s only going to grow as I think up more weird things to do. I’m certain that everything I’ve done has been done before, but I had a great time figuring it out for myself (and subsequently trying to explain it here!). If you want a bit more guidance, I can wholeheartedly recommend checking out the Simple Modifications Directory over at PokeCommunity for a stellar catalogue of tweaks with instructions for adding them to your game. Paired with PoryMap to serve as a really in-depth map editor for the decompilation, and the ability to use git to be able to more easily track your changes and make backups, Pokemon ROM hacking has never been so accessible. If you’ve found any of this interesting, I can only recommend giving it a go for yourself. It’s been a great month for me of poking around in my spare time, and slowly coming to terms with the delightful language of C.
See You Next Month!
So that was my March. I did play a few other things, but with this being so interesting to me I wanted to really shine a spotlight on it. I’ll be back next month with some pretty heavy JRPG gaming having recently downloaded Final Fantasy 7 Remake on Steam. Will I actually manage to get through such a game with my limited time and motivation? We’ll find out at the end of April!