** You will need to understand Part 1 of this tutorial before you can decompress the files used in any other parts**
Trainer Offsets: colosseum trainer data.json
Shadow Pokémon Original Offsets: shadow trainer data.json
For each trainer there are 6 Pokémon entries but not all of the slots have to be used. After 6 slots of Pokémon, there is one unused entry then the first slot of the next trainer is right after that. This means that you can start at the first trainer and to get to the next trainer all you need to do is jump 7 slots. This also means that you can easily give any trainer up to 6 Pokémon without having to repoint or expand the data. (Of course the more Pokémon you add the larger the compressed file size will become).
Each Pokémon has a byte which you can set to make it a Shadow Pokémon. That byte is effectively the flag that gets set when you catch that Pokémon and just by setting the flag the game will consider it to be a Shadow Pokémon and your partner will react to it (even if she hasn't actually joined you yet). I don't actually change this because setting this flag to an unused flag just means every time you fight that trainer they will have the Shadow Pokémon no matter how many times you catch it. If you use a flag that is used by the game then you will affect the trainers who's teams rely on that flag. So if I set the flag to the same flag that Evice's Tyranitar uses, then when I reach Evice he won't use the team with Shadow Tyranitar, he'll just use the replacement one.
Also each team that has a Shadow Pokémon has an exact copy of the Shadow Pokémon. So if you want to change one of its moves you will have to change that move on every team that it appears on which can sometimes be up to 4 teams. I made a program that takes the changes to one and applies it to all of the other iterations automatically. In the source code there is a .json file containing all the default occurrences of each Shadow Pokémon.
The source code also contains a .json file with details for each trainer in the game. Since I don't know where the trainer data is saved I had to fill it in manually. I recorder the name, trainer class, in-game location and file offset for each of the trainers.
The first trainer in Colosseum (Folly at the Phenac city entrance) is in the common_rel at offset 658820 (0xA0D84). Each Pokémon is 80 (0x50) bytes long and so each team is 480 bytes long and to go from the start of one team to the start of the next team you jump 560 bytes (because there is an empty Pokémon inbetween). The actual first Pokémon entry is at offset 0x9FE28 but the first few are a bit dodgy, maybe used when they were testing the game. Folly's Pokémon start at the 0x31 (49th) Pokémon entry.
N.B. The trainers don't change their teams based on the Shadow Pokémon you've caught but based on the flag set when it was caught. So when you catch a trainer's Shadow Pokémon, the next time you fight them the game loads up a different team so you will find trainers who have two different teams, one for if you've caught their Shadow Pokémon and one for if you haven't even if the "caught" team is just the same team without the Shadow Pokémon.
When I was still trying to figure the game out, the trainers were the first thing I researched and the first thing I discovered. This meant that at the time I was documenting it and writing my programs I didn't have everything fully figured out yet. I noticed that each Pokémon has the value (0x0004) in it at a certain point and so I used this to search for Pokémon before I realized they were all next to each other and the distances between them were just unused Pokémon. All of the offsets in this section are relative to this 0x0004 value which is actually 12 bytes into the Pokémon's data. If you want you can subtract 12 bytes from each of the start offsets I use in the trainer data json files and then add 12 bytes to each of the offsets in the Pokemon.swift object from the source code (the same offsets in the table below.) I just stuck with it because it would be tedious to update all my code (I'll do it eventually).
The Pokémon's ability can be either 0 or 1, each representing one of the two abilities set in the stats for that Pokémon. You can't give it any ability. For values of other variables like genders, items and natures check out the enumerations in the source code on GitHub.
For the values of the Pokémon's ability, nature, gender, EVs and IVs you can set the value to 0xFF (255) and the game will automatically replace those values with randomly generated values. All the Shadow Pokémon had 0xFF for those values by default.
The "FF Offsets" detailed below are the bytes which are set to 0xFF for any Pokémon that isn't in use. I'm not sure if it's required by the game but my program will fill them in automatically for me when I delete a Pokémon from a trainer while setting all the other necessary values to 0. However if you do something as simple as putting an invalid species for the Pokémon like Pokémon number 0 or Pokémon number 252 (which is one of the empty slots in gen III) then the game will play as usual but the team will be loaded without that Pokémon.
However, if you set proper stats for the Pokémon in slot 252 including choosing one of the models and names already available in the game files then the Pokémon will be playable. You could use this for something like making a duplicate of a Pokémon except it has different abilities and that way you could in essence have a Pokémon with up to 4 different abilities because you could use the two species interchangeably. You could also make something like Meowstic/Gallade/Frosslass where you make a copy of a Pokémon except one of them is all male and the other is all female. You could then give them different level up moves or different evolutions depending on which one it is. In the future, if we crack the model formats we could probably use those slots to add new Pokémon without having to replace old ones.
Just to clarify, the offsets for each variable are relative to the "four offset" at 0x12 from the actual start of the Pokémon so the first variable is documented as being at an offset of -12 from the 0x0004 but is really at an offset of 0x00 from the Pokémon start. I will also add the "true offset" which is relative to the actual start of the Pokémon but if you are comparing with my source code on git hub then use the four offset.
Trainer Pokémon data table
Variable | Size (bytes) | Offset from 0x0004 | True Offset | |
---|---|---|---|---|
Ability | 1 | 0x0C | 0x00 | |
Gender | 1 | 0x0B | 0x01 | |
Nature | 1 | 0x0A | 0x02 | |
Shadow ID | 1 | 0x09 | 0x03 | |
Level | 1 | 0x08 | 0x04 | |
Pokémon Species | 2 | 0x02 | 0x0A | |
"Four offset" | 2 | 0x00 | 0x0C | (almost always 0x0004) |
Held Item | 2 | 0x06 | 0x12 | |
HP IV | 1 | 0x10 | 0x1C | |
Attack IV | 1 | 0x11 | 0x1D | |
Defense IV | 1 | 0x12 | 0x1E | |
Sp. Attack IV | 1 | 0x13 | 0x1F | |
Sp. Defense IV | 1 | 0x14 | 0x20 | |
Speed IV | 1 | 0x15 | 0x21 | |
HP EV | 1 | 0x17 | 0x23 | |
Attack EV | 1 | 0x19 | 0x25 | |
Defense EV | 1 | 0x1B | 0x27 | |
Sp. Attack EV | 1 | 0x1D | 0x29 | |
Sp. Defense EV | 1 | 0x1F | 0x2B | |
Speed EV | 1 | 0x21 | 0x2D | |
Move 1 | 2 | 0x2A | 0x36 | |
Move 2 | 2 | 0x32 | 0x3E | |
Move 3 | 2 | 0x3A | 0x46 | |
Move 4 | 2 | 0x42 | 0x4E | |
ID String of Name | 2 | 0x0A | 0x16 | (The Pokémon's nickname will be the string this points to. This is why with the current AR codes when you change a Pokémon's species it's name doesn't change. For the most part setting this value to 1000 + the Pokémon's national dex number, i.e. Bulbasaur is 1001 (0x3E9) and Treeko is 1252 (0x4E4), gives you the right string but I think it stops following the trend somewhere half way through the gen III Pokémon. I haven't tested it but it may be possible to give a trainer's Pokémon a nickname by setting this to the id of a string you've changed.) |
Typically a trainer will send their Pokémon out in the order they are specified in the data. However, sometimes, and for reasons I don't know yet, a Pokémon will be sent out in a different order to that specified. Usually they are Shadow Pokémon. Most are simply added to the team last but some are added first and still get sent out last every time. Some are added first and come out first as expected. Sometimes a trainer will randomly mix up their Pokémon order in different battles (like after a soft reset). More research is required.
Editing the trainer teams is really fun and creating lots of interesting teams will likely be the main goal in many hacks. However, the more you change, the more likely you are to be increasing the compression size as you start to make lots of unique Pokémon, while the original has a lot of repetition since it didn't feature that many, especially not from gen I. The battle mode trainers are made to be more competitive, but the story mode trainers never have any IVs or EVs on them (hence they're almost all so pathetically weak) although they sometimes have beneficial natures. They almost never have held items either. Almost no trainers have 6 Pokémon and they don't all know 4 moves. This means that the process of making the teams more fun, varied or competitive will almost definitely result in a much larger compressed file size.
By far the best way to decrease the compressed file size is to put 0x00s over all the Pokémon in battle mode if you don't mind not having it in your hack. This will give you enough space to go wild. By doing this my common_rel is 7 KB smaller than the original even though I've changed and added so many Pokémon as well as editing a lot of moves and stats. You can choose to just remove moves, items, evs and/or ivs or even 1 or 2 Pokémon from battle mode teams rather than removing all of their Pokémon completely in order to have a more competitive story for a less competitive battle mode. You can also rely on remove data from other parts of the file like the moves, stats and text since there are all of them in the same file. Finally, you could delete some Pokémon from some of the less important story mode characters. There are Zigzagoon and Hoothoot that were going to get OHKO'd anyway so might as well save the space.
I'm sure we'll soon find out how to safely increase file sizes and then we won't have to make these trade-offs but I think it's worth it for now.
While writing this documentation I have just finally found where the trainer data is stored in Colosseum! It is in the common_rel file with the first trainer being at offset 0x92F04. The order of the trainer data seems to differ from the order of the trainer teams though. Each entry is 52 (0x34) bytes long. The id of the trainer's name string refers to text in the common_rel string table. There are 3 optional string ids at the end of each trainer's data. The first being what they say before the fight (usually only used in colosseums since the you don't see those battles are initiated automatically), the second is what they say if they win (usually only for colosseums and mount battle because anywhere else you just "black out")and they third is what they say if they lose. These strings are found in the string tables in fight_common.fsys's "fight" and "tool_fight" files. Each trainer also has an index for their in-battle model and their trainer class. I will compile a list of these indexes eventually. The index of the trainer's first Pokémon also gets 2 bytes. The Pokémon at index 1 starts at offset 0x9FE28 (a value of 0x31 means the 49th Pokémon entry including the empty rows between trainer teams). Each trainer can also have up to 8 items like potions and x-attacks.
Trainer data table
Variable | Size (bytes) | Offsets |
---|---|---|
Index of Trainer Class Name | 1 | 0x03 |
Index of Trainer's First Pokémon | 2 | 0x04 |
Name String ID | 2 | 0x0A |
Index of Trainer Model | 1 | 0x13 |
Item 1 | 2 | 0x14 |
Item 2 | 2 | 0x16 |
Item 3 | 2 | 0x18 |
Item 4 | 2 | 0x1A |
Item 5 | 2 | 0x1C |
Item 6 | 2 | 0x1E |
Item 7 | 2 | 0x20 |
Item 8 | 2 | 0x22 |
Post Battle String ID | 2 | 0x26 |
Win String ID | 2 | 0x2A |
Lose String ID | 2 | 0x2E |
Part 8:
Edited by evandixon
Update table formatting
Recommended Comments
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now