• 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!
  • 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.

[Script✓] Manipulating a Pokémon's OT ID does not work

  • 119
    Posts
    15
    Years
    This problem is solved. See bottom of the post for the solution.

    I'm trying to write a script in which the player receives a Pokémon that is not theirs originally. I don't want a trading cutscene or anything, just a givepokemon sequence. One important element of this is changing the OT ID of the Pokémon to a random number.

    I have tried to approach this the same way in which I changed the OT name and the Pokémon's nickname, namely by using "copybyte" or "writebytetooffset". I am using Leon's & UltimaSoul's ROM base wich has disabled checksum reads. For good measure, I followed all of the steps below to completely disable Pokémon data encryption and allow for easy data manipulation without the risk of Bad Eggs. (I know the OT ID is not part of the encrypted data, but still.) This went fine and didn't hurt the game in any way.

    Spoiler:
    Next, I double-checked where in the RAM the OT ID of the party Pokémon are stored. With help of Bulbapedia, some other pages and a hex calculator I have identified the following addresses as the locations of the visible (non-secret) OT ID's of the party Pokémon. Presumably because of the disabled encryption, the ID numbers are simply stored in "plaintext", i.e. not in reversed order or anything. I have checked this multiple times with the memory viewer of the emulator I am using. Each time, the two bytes stored at this location (in hex) corresponds to the visible OT ID (in dec). For example, in one run with a full party, each of these addresses would contain the bytes "A2 07" which translates to "41479" in decimal. This was exactly the OT ID for all Pokémon.
    Code:
    Party slot nr.		visible OT ID	
    		in memory		
    -------------------------------------------------------------------------------------------------
    1	0x0202428A .. 8B	
    2	0x020242EE .. EF	
    3	0x02024352 .. 53 
    4	0x020243B6 .. B7	
    5	0x0202441A .. 1B
    6	0x0202447E .. 7F

    As mentioned, in other scripts I have succesfully manipulated the nickname and OT name of party Pokémon by using buffers and "copybyte" commands to copy string bytes to the right offsets. I hoped the same could be done with the OT ID of party Pokémon. So I wrote a script which followed three steps:

    1. Give the player a Pokémon using givepokemon.
    2. Generate a random number between 0x0 and 0xEE and store in 0x8001. Repeat for 0x8002.
    3. Depending on the party slot, copy the randomly generated number to the location of the OT ID.

    The locations of the 0x8001 and 0x8002 variables (each two bytes long) are as follows (source):
    Code:
    0x020370BA .. BB       Script variable 0x8001
    0x020370BC .. BD       Script variable 0x8002

    This resulted in the following script:

    Spoiler:
    Here is the problem:

    The script is not game breaking, the Pokémon is received and everything is in order. Except that the OT ID remains unchanged from the Player's Trainer ID. Also when looking in the memory at the abovementioned locations in which the OT ID's are stored, they remain the same and identical for each Pokémon received.

    To check whether it had to do with the "copybyte" command, I also included a "writebytetooffset" branch in the script above (@otid2) to write a pre-determined OT ID into the memory. But this has no effect either.

    For some reason unbeknownst to me, these commands are able to manipulate Pokémon nicknames, but not OT ID's. It's not just that the script is faulty, but the actual process of writing bytes to memory does not take place. Can someone explain to me where I went wrong?

    Thanks a lot for any help!

    PS: I am aware that this level of game data manipulation might be better suited for ASM, but I kind of hope I can solve it using XSE and common sense.

    EDIT: I have found the solution to this problem, as described below:

    What I got wrong was how addresses/offsets and memory locations work. I don't know the correct technical terminology, but using simple language, I assumed that the order of all bytes in the RAM memory was from left-to-right. While in reality each block of four bytes goes from right-to-left. I had seen this explained before but I somehow didn't think of it before. It is best illustrated as follows:

    Code:
    address		..B0	 ..B4	  ..B8	   ..BC
    020370B0 | 	00000000 00000000 00540000 0000004C
    what i thought:			  B8B9BABB BCBDBEBF
    in reality:			  BBBAB9B8 BFBDBDBC
    Because of this, I had simply gotten the locations of both the relevant bytes in the 0x8001 and 0x8002 bytes wrong, but most importantly the correct destinations of these bytes. The old script above was actually still changing the OT ID in a way, but the secret (invisible) OT ID, not the visible one. I hope this makes some sense, but it is hard to properly explain it.

    In any case, the corrected script is as follows - which works as a charm:

    Spoiler:

    Hope this helps anyone in need of changing the OT ID's of party Pokémon. Remember to disable checksum reading as the above script will otherwise result in a Bad Egg. Also, once you have done that, trading from your hack with games that do not have checksum disabled is not (always) possible.
     
    Last edited:
    Back
    Top