• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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.

[Other] [Pokeemerald] Can You Randomize Type-Effectiveness For New Game?

247
Posts
6
Years
    • Seen yesterday
    I've been trying to find a way where, when the player starts up a new game in Pokemon Emerald, the type-effectiveness table is randomized. Fire might be super-effective against Dragon, Dark might not affect Grass, etc. I know that the effectiveness table is in src/battle_util.c, but the issue I have is that the table is a constant array. This, obviously, makes it impossible for the values within said array to be changed at any point within the code without just changing the values directly within the array before compiling the ROM. However, I want the game to randomize the type-effectiveness table when the player clicks "New Game", so that isn't a solution for me. I've tried removing the "const" keyword, as well as placing it at different points within src/battle_util.c, but whenever I compile, I get this error:
    Code:
    `.data' referenced in section `.text' of src/battle_util.o: defined in discarded
     section `.data' of src/battle_util.o
    `.data' referenced in section `.text' of src/battle_util.o: defined in discarded
     section `.data' of src/battle_util.o
    I know this error comes up when you remove the "const" keyword from rom const data, but I have to somehow remove that keyword so that I can have the code edit those values. Is there anyway to go about this?
     
    451
    Posts
    6
    Years
    • Seen May 11, 2024
    You get that error because removing the const moves the table from the .rodata section to the .data section, which is discarded by the linker. To fix this, put the table in the ewram section like this:
    Code:
    EWRAM_DATA u8 gTypeEffectiveness[336]
     
    247
    Posts
    6
    Years
    • Seen yesterday
    You get that error because removing the const moves the table from the .rodata section to the .data section, which is discarded by the linker. To fix this, put the table in the ewram section like this:
    Code:
    EWRAM_DATA u8 gTypeEffectiveness[336]

    The error has changed. If I keep the static keyword, remove const, and add EWRAM_DATA, this is the error:
    Code:
    `ewram_data' referenced in section `.text' of src/battle_util.o: defined in disc
    arded section `ewram_data' of src/battle_util.o
    `ewram_data' referenced in section `.text' of src/battle_util.o: defined in disc
    arded section `ewram_data' of src/battle_util.o
    If I remove the static and the const keywords, and then add EWRAM_DATA, this is the error:
    Code:
    `sTypeEffectivenessTable' referenced in section `.text' of src/battle_util.o: de
    fined in discarded section `ewram_data' of src/battle_util.o
    `sTypeEffectivenessTable' referenced in section `.text' of src/battle_util.o: de
    fined in discarded section `ewram_data' of src/battle_util.o
     
    451
    Posts
    6
    Years
    • Seen May 11, 2024
    The error has changed. If I keep the static keyword, remove const, and add EWRAM_DATA, this is the error:
    Code:
    `ewram_data' referenced in section `.text' of src/battle_util.o: defined in disc
    arded section `ewram_data' of src/battle_util.o
    `ewram_data' referenced in section `.text' of src/battle_util.o: defined in disc
    arded section `ewram_data' of src/battle_util.o
    If I remove the static and the const keywords, and then add EWRAM_DATA, this is the error:
    Code:
    `sTypeEffectivenessTable' referenced in section `.text' of src/battle_util.o: de
    fined in discarded section `ewram_data' of src/battle_util.o
    `sTypeEffectivenessTable' referenced in section `.text' of src/battle_util.o: de
    fined in discarded section `ewram_data' of src/battle_util.o

    Oh I didn't notice that you are using pokeemerald-expansion.
    You'll need to include "src/battle_util.o" in sym_ewram.txt so that the ewram_data section for that file isn't discarded.
     
    247
    Posts
    6
    Years
    • Seen yesterday
    Oh I didn't notice that you are using pokeemerald-expansion.
    You'll need to include "src/battle_util.o" in sym_ewram.txt so that the ewram_data section for that file isn't discarded.

    It compiled! Thank you! Just for my own education, could this potentially limit some critical section of the ROM's memory, thus causing problems, or is there plenty of room within EWRAM_DATA? And could you explain or direct me to a link that can explain the difference between bss, common, and ewram data?
     
    853
    Posts
    3
    Years
    • Seen Nov 9, 2023
    It compiled! Thank you! Just for my own education, could this potentially limit some critical section of the ROM's memory, thus causing problems, or is there plenty of room within EWRAM_DATA? And could you explain or direct me to a link that can explain the difference between bss, common, and ewram data?

    https://github.com/Touched/asm-tutorial/blob/master/doc.md

    that should help a bit, not sure if it covers everything; and there should be plenty of ewram I think.

    since emerald usually has more ewram and than firered, and setting the type effectiveness up that way is pretty much how it is in firered.

    that's about all I can help with, don't know enough to be even close to confident about how to randomize that.
     
    451
    Posts
    6
    Years
    • Seen May 11, 2024
    could this potentially limit some critical section of the ROM's memory, thus causing problems, or is there plenty of room within EWRAM_DATA?
    Looking at the symbol map, it seems that there's around 12 kilobytes of free space at the end of ewram (and around 1 kilobyte at the end of iwram).
    So yes, you can run out of ram if you create large arrays or a ton of variables but instead of breaking the rom you will just run into some compilation errors.
    Here's what I got when I tried to make a 16000 byte array in ewram:
    Code:
    ld_script.ld:24 cannot move location counter backwards (from 02040f35 to 02040000)

    could you explain or direct me to a link that can explain the difference between bss, common, and ewram data?
    From what I can tell uninitialized static variables are placed in .bss, uninitialized global variables are placed in COMMON, initialized variables are placed in .data and initialized variables defined with EWRAM_DATA are placed in ewram_data.
    I don't really know what the differences between these sections are aside from ewram_data being placed in ewram while .bss and COMMON are placed in iwram.
    You can probably get a better answer to this in the pret discord.
     
    247
    Posts
    6
    Years
    • Seen yesterday
    https://github.com/Touched/asm-tutorial/blob/master/doc.md

    that should help a bit, not sure if it covers everything; and there should be plenty of ewram I think.

    I appreciate the link!

    Looking at the symbol map, it seems that there's around 12 kilobytes of free space at the end of ewram (and around 1 kilobyte at the end of iwram).
    So yes, you can run out of ram if you create large arrays or a ton of variables but instead of breaking the rom you will just run into some compilation errors.......

    From what I can tell uninitialized static variables are placed in .bss, uninitialized global variables are placed in COMMON, initialized variables are placed in .data and initialized variables defined with EWRAM_DATA are placed in ewram_data..

    Thanks, that helps a lot!

    I've been able to write up a separate program that creates a given number of unique random type matchup tables. Each table is based upon the official type matchup table in the sense that no type has too many immunities, nor too many or too few resistances, weaknesses, or neutral matchups, looking at it from both an offensive and defensive perspective. I then take all of these tables and stick them into a static const array within src/battle_util.c. When the player starts up a new game, a method is run that randomly selects one of these tables from the array, and sets that as the table to be used in battles. Based on my tests, you could have up to 11,345 unique tables in the array without having any issues with the game! Of course, this number can change depending on how much stuff you have in your decompilation project. There's also the fact that no one would ever need an array that massive for this purpose. 1,000 tables sounds ridiculous enough.

    If I can figure out how to make this program a bit more user-friendly and set it up as a normal-ish application, I'll probably post it on this forum.
     
    853
    Posts
    3
    Years
    • Seen Nov 9, 2023
    I appreciate the link!



    Thanks, that helps a lot!

    I've been able to write up a separate program that creates a given number of unique random type matchup tables. Each table is based upon the official type matchup table in the sense that no type has too many immunities, nor too many or too few resistances, weaknesses, or neutral matchups, looking at it from both an offensive and defensive perspective. I then take all of these tables and stick them into a static const array within src/battle_util.c. When the player starts up a new game, a method is run that randomly selects one of these tables from the array, and sets that as the table to be used in battles. Based on my tests, you could have up to 11,345 unique tables in the array without having any issues with the game! Of course, this number can change depending on how much stuff you have in your decompilation project. There's also the fact that no one would ever need an array that massive for this purpose. 1,000 tables sounds ridiculous enough.

    If I can figure out how to make this program a bit more user-friendly and set it up as a normal-ish application, I'll probably post it on this forum.

    Well you may be able to create a function in the code that can do that, as well.
    I'm mostly spitballin since I still think mad noob with this stuff, but I believe if you set up an array that also functions as an index, one for types & one for effectiveness multipliers.

    Like an enum.

    then use a loop that goes through the index, picking a number for atk type then defense type, then pull the effectiveness from its array/index.

    I think that should work for randomizing, from there you'd need to get your conditions setup.

    Set it so each atk type can only have so many of each effectiveness (setting as a range is best).

    Then do the same for defense type.

    And have the code be able to count how many meet the conditions.


    I had the idea because I need something similar for a thing I'm working on with Field_Moves.

    I was able to change what's added to the list, but I can't figure out how to make it count how many things are added to said list by/in said function.


    That aside you've got something that actually works at least, so usability aside that's all that really matters.
     
    247
    Posts
    6
    Years
    • Seen yesterday
    Well you may be able to create a function in the code that can do that, as well.
    I initially tried putting the code directly into the ROM, but it wouldn't work. It seems that there was a bit too much going on at one moment for the ROM to handle, so the game would freeze whenever I called this function. And I know it's not my code that's messing up, as I've tested it outside of the ROM through a normal C compiler. Obviously, it would be great if I could get it to work within the ROM rather than needing an external tool, but since it's working perfectly as is, I have no desire to try to finagle my way through jamming this into the ROM.
    ....if you set up an array that also functions as an index, one for types & one for effectiveness multipliers.

    Like an enum.

    then use a loop that goes through the index, picking a number for atk type then defense type, then pull the effectiveness from its array/index.

    I think that should work for randomizing, from there you'd need to get your conditions setup.

    Set it so each atk type can only have so many of each effectiveness (setting as a range is best).

    Then do the same for defense type.

    And have the code be able to count how many meet the conditions.
    This process doesn't quite work with how the effectiveness table is laid out within the ROM. The table is a two-dimensional array, with each row representing one type and what multiplier is applied when it attacks each type, and each column represents one type and what multiplier is applied when it is attacked by each type. Each row and column needs to be handled individually (this is where the maximum/minimum values are needed), and yet handled together as well, since one row impacts every column, and vice versa. Just walking through one type by itself and setting the modifier for every offensive and defensive before moving on to the next type won't work out, as you'll start over-writing stuff and not accounting for the other type's layouts.

    I was able to change what's added to the list, but I can't figure out how to make it count how many things are added to said list by/in said function.
    How I've accomplished this in my program is that, before I start adding things to a row or column, I set four u8 variables to 0, each variable representing immune, resistant, neutral, and effective modifier count. Then, every time I add one of these modifiers to the row or column, I increment the related variable by 1. With this process, I always have an accurate view of what has been set in the array. Maybe that process can help with your issue.
     
    853
    Posts
    3
    Years
    • Seen Nov 9, 2023
    I initially tried putting the code directly into the ROM, but it wouldn't work. It seems that there was a bit too much going on at one moment for the ROM to handle, so the game would freeze whenever I called this function. And I know it's not my code that's messing up, as I've tested it outside of the ROM through a normal C compiler. Obviously, it would be great if I could get it to work within the ROM rather than needing an external tool, but since it's working perfectly as is, I have no desire to try to finagle my way through jamming this into the ROM.


    How I've accomplished this in my program is that, before I start adding things to a row or column, I set four u8 variables to 0, each variable representing immune, resistant, neutral, and effective modifier count. Then, every time I add one of these modifiers to the row or column, I increment the related variable by 1. With this process, I always have an accurate view of what has been set in the array. Maybe that process can help with your issue.

    Good to know I'll keep that freezing thing in mind for my changes.

    and I'll see if that other change will work for me, adding another field to my function, and setting its value equal to the value that's looping
    sounds like it may work for establishing a pseudo counter, from there I think I just need to setup the break condition in the right place and it should work out.

    I think, anyway thanks for the tip. :)
    If it works, or at least I get the code approved I may share it with you if you're interested, its for setting up no learn overworld HM use.

    I'm doing a lot right now(meaning I'm not close to a stable build) so it may be a while before I could actually do a live test,
    so for the most part I'm just writing code and having it proof read over on the discord, before I consider it done and move to the next thing.
     
    Back
    Top