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.
Recently I got into ROM hacking and I just have questions about hacking Pokemon FireRed. My first question is about the EV system. I was wondering if there was a way to disable the cap on how much you can feed vitamins (Protein, Iron, etc) to a Pokemon. I was wondering if there was a way to disable this mechanic or simply to change the amount each vitamin gives to a stat such as 50 EVs instead of 10 EVs. My second question is I wanted to know if there is a method/item that would reset EVs or even change the natures in the game. Last thing I'd like to ask is does anybody know how to implement the color indicator for a nature (i.e. Timid nature is +Speed/-Attack so in the newer games they indicate the +Speed stat in red and the -Attack stat in blue)? Help/suggestions or an alternative to any of my questions would be great as I'm still learning about hacking ROMs (so far I can only seem to write basic scripts in XSE and somewhat Hex edit). Thanks!
The color coded natures feature is by Spherical Ice. The details are in this post
As for the other question, while I don't know how to remove the EV cap, there is another way to get the vitamins to bypass 100 EVs. It's probably not the best way, but it works.
I was also able to make a function 'EV reset item.' Again there is probably a more efficient way, but I'll just show you what I did so far.
This is Darthatron's code to call a script from an item. To use this, just put the offset of the XSE script where the Xs are. (Normally I would compile the script first and then insert this.)
To get the item to use this, go the usage page in LSA's Complete Item Editor (this is the tool I use and it makes this process easier) and check the box next to "Add Use of Select Script" at the bottom left. Put the offset (+1) of where you inserted the routine above.
As for the script, I used the JPAN Hacked engine tool to add a few specials. I added special 0x6, 0x7, 0xF, and 0x3E.
Simplified explanations for what these specials do and how to use them here.
Vitamin Script
Whole Script
Spoiler:
#dyn 0x160000
#org @Start
special 0x9F
waitspecial
storepartypokemon 0x0 0x8004
compare 0x8004 0x6
if >= jump @Exit
special 0x6
setvar 0x8005 0x0
special2 0x8006 0x7
setvar 0x8005 0x1
special2 0x8007 0x7
setvar 0x8005 0x2
special2 0x8008 0x7
setvar 0x8005 0x3
special2 0x8009 0x7
setvar 0x8005 0x4
special2 0x800A 0x7
setvar 0x8005 0x5
special2 0x800B 0x7
writebytetooffset 0x6 0x203F4D8
writebytetooffset 0x80 0x203F4D9
writebytetooffset 0x7 0x203F4DA
writebytetooffset 0x80 0x203F4DB
special 0x3E
writebytetooffset 0x6 0x203F4D8
writebytetooffset 0x80 0x203F4D9
writebytetooffset 0x8 0x203F4DA
writebytetooffset 0x80 0x203F4DB
special 0x3E
writebytetooffset 0x6 0x203F4D8
writebytetooffset 0x80 0x203F4D9
writebytetooffset 0x9 0x203F4DA
writebytetooffset 0x80 0x203F4DB
special 0x3E
writebytetooffset 0x6 0x203F4D8
writebytetooffset 0x80 0x203F4D9
writebytetooffset 0xA 0x203F4DA
writebytetooffset 0x80 0x203F4DB
special 0x3E
writebytetooffset 0x6 0x203F4D8
writebytetooffset 0x80 0x203F4D9
writebytetooffset 0xB 0x203F4DA
writebytetooffset 0x80 0x203F4DB
special 0x3E
compare 0x8006 0x1FE
if >= jump @MaxEV ' Larger Than or Equal To
setvar 0x8005 0x0
special2 0x8006 0x7
compare 0x8006 0xFA
if >= jump @MaxEV ' Larger Than or Equal To
setvar 0x8006 0x1
special 0xF
special 0x6
removeitem 0x38 1
message @Boost ' \v\h02's\nHP was rai...
callstd MSG_SIGN ' Signpost-style message
release
end
#org @Exit
release
end
#org @MaxEV
special 0x6
message @Max ' It won't have any ef...
callstd MSG_SIGN ' Signpost-style message
release
end
#org @Boost
= \v\h02's\nHP was raised!
#org @Max
= It won't have any effect!
Explanation:
Spoiler:
(This was written in PKSV so XSE commands might be slightly different). I'll just explain what is basically does.
special 0x9F
waitspecial
storepartypokemon 0x0 0x8004
compare 0x8004 0x6
if >= jump @Exit
This opens the Pokemon menu and lets you select a Pokemon. If you hit cancel it goes to a script called Exit (which I just made release and end the script).
Then I went through each stat (determined by 0x8005) and stored them each into different temporary variables. Special 0x6 is the special that let's you use any of the Read/Edit specials so it is important. It "opens" the Pokemon's data for you to manipulate.
This is the 'add two variables together' special. Basically the idea here was to add all the EVs together. The snippet above adds 0x8007 to 0x8006. I went down and added all the other variables to 0x8006.
compare 0x8006 0x1FE
if >= jump @MaxEV ' Larger Than or Equal To
setvar 0x8005 0xSTAT TO CHANGE
special2 0x8006 0x7
compare 0x8006 0xFC FC = 252 in hex
if >= jump @MaxEV ' Larger Than or Equal To
setvar 0x8006 0x1
special 0xF
special 0x6
......
I then compared 0x8006 (which now has the Pokemon's total EVs) to 510, which is the maximum amount of total EVs a Pokemon can have. If they are maxed out it goes to a script that displays the 'It won't work' message.
Then it checks the EV that the item will raise and if it's 252 (the max amount for one EV) it will go to that same script as before.
Then it increases the EV by 1 (the setvar 0x8006 0x1, followed by special 0xF). This was for the Wings from Gen V (which bypass the 100 EV check).
Then it does special 0x6 again. This is important, because if you use special 0x6 to "open" a Pokemon, you have to use it again to "close" it. Not closing what you open leads to bad stuff.
Reset Script
Whole Script
Spoiler:
#dyn 0x740000
#org @start
special 0x9F
waitspecial
storepartypokemon 0x0 0x8004
compare 0x8004 0x6
if >= jump @None
special 0x6
setvar 0x8005 0x5
special2 0x8006 0x7
compare 0x8006 0x0
if true jump @Zero
compare 0x8006 0xFC
if true jump @Max
compare 0x8006 0xFA
if >= jump @Minus250
compare 0x8006 0xF0
if >= jump @Minus240
compare 0x8006 0xE6
if >= jump @Minus230
compare 0x8006 0xDC
if >= jump @Minus220
compare 0x8006 0xD2
if >= jump @Minus210
compare 0x8006 0xC8
if >= jump @Minus200
compare 0x8006 0xBE
if >= jump @Minus190
compare 0x8006 0xB4
if >= jump @Minus180
compare 0x8006 0xAA
if >= jump @Minus170
compare 0x8006 0xA0
if >= jump @Minus160
compare 0x8006 0x96
if >= jump @Minus150
compare 0x8006 0x8C
if >= jump @Minus140
compare 0x8006 0x82
if >= jump @Minus130
compare 0x8006 0x78
if >= jump @Minus120
compare 0x8006 0x6E
if >= jump @Minus110
compare 0x8006 0x64
if >= jump @Minus100
compare 0x8006 0x5A
if >= jump @Minus90
compare 0x8006 0x50
if >= jump @Minus80
compare 0x8006 0x46
if >= jump @Minus70
compare 0x8006 0x3C
if >= jump @Minus60
compare 0x8006 0x32
if >= jump @Minus50
compare 0x8006 0x28
if >= jump @Minus40
compare 0x8006 0x1E
if >= jump @Minus30
compare 0x8006 0x14
if >= jump @Minus20
compare 0x8006 0xA
if >= jump @Less10
jump @Minus10
#org @Minus250
setvar 0x8006 0x1FA
special 0xF
jump @Minus10
#org @Minus240
setvar 0x8006 0x1F0
special 0xF
jump @Minus10
#org @Minus230
setvar 0x8006 0x1E6
special 0xF
jump @Minus10
#org @Minus220
setvar 0x8006 0x1DC
special 0xF
jump @Minus10
#org @Minus210
setvar 0x8006 0x1D2
special 0xF
jump @Minus10
#org @Minus200
setvar 0x8006 0x1C8
special 0xF
jump @Minus10
#org @Minus190
setvar 0x8006 0x1BE
special 0xF
jump @Minus10
#org @Minus180
setvar 0x8006 0x1B4
special 0xF
jump @Minus10
#org @Minus170
setvar 0x8006 0x1AA
special 0xF
jump @Minus10
#org @Minus160
setvar 0x8006 0x1A0
special 0xF
jump @Minus10
#org @Minus150
setvar 0x8006 0x196
special 0xF
jump @Minus10
#org @Minus140
setvar 0x8006 0x18C
special 0xF
jump @Minus10
#org @Minus130
setvar 0x8006 0x182
special 0xF
jump @Minus10
#org @Minus120
setvar 0x8006 0x178
special 0xF
jump @Minus10
#org @Minus110
setvar 0x8006 0x16E
special 0xF
jump @Minus10
#org @Minus100
setvar 0x8006 0x164
special 0xF
jump @Minus10
#org @Minus90
setvar 0x8006 0x15A
special 0xF
jump @Minus10
#org @Minus80
setvar 0x8006 0x150
special 0xF
jump @Minus10
#org @Minus70
setvar 0x8006 0x146
special 0xF
jump @Minus10
#org @Minus60
setvar 0x8006 0x13C
special 0xF
jump @Minus10
#org @Minus50
setvar 0x8006 0x132
special 0xF
jump @Minus10
#org @Minus40
setvar 0x8006 0x128
special 0xF
jump @Minus10
#org @Minus30
setvar 0x8006 0x11E
special 0xF
jump @Minus10
#org @Minus20
setvar 0x8006 0x114
special 0xF
jump @Minus10
#org @Less10
setvar 0x8006 0x10A
special 0xF
jump @Minus10
#org @Minus10
special2 0x8006 0x7
compare 0x8006 0xA
if true jump @10
compare 0x8006 0x9
if true jump @9
compare 0x8006 0x8
if true jump @8
compare 0x8006 0x7
if true jump @7
compare 0x8006 0x6
if true jump @6
compare 0x8006 0x5
if true jump @5
compare 0x8006 0x4
if true jump @4
compare 0x8006 0x3
if true jump @3
compare 0x8006 0x2
if true jump @2
compare 0x8006 0x1
if true jump @1
compare 0x8006 0x0
if true jump @Done
jump @Done
#org @10
setvar 0x8006 0x10A
special 0xF
jump @Done
#org @9
setvar 0x8006 0x109
special 0xF
jump @Done
#org @8
setvar 0x8006 0x108
special 0xF
jump @Done
#org @7
setvar 0x8006 0x107
special 0xF
jump @Done
#org @6
setvar 0x8006 0x106
special 0xF
jump @Done
#org @5
setvar 0x8006 0x105
special 0xF
jump @Done
#org @4
setvar 0x8006 0x104
special 0xF
jump @Done
#org @3
setvar 0x8006 0x103
special 0xF
jump @Done
#org @2
setvar 0x8006 0x102
special 0xF
jump @Done
#org @1
setvar 0x8006 0x101
special 0xF
jump @Done
#org @Zero
special 0x6
message @Nothing
callstd MSG_SIGN
release
end
#org @Max
setvar 0x8006 0xFC
special 0xF
jump @Done
#org @None
release
end
#org @Done
removeitem GREPABERRY 1
special 0x6
message @Reset
callstd MSG_SIGN
release
end
#org @Reset
= \v\h02's Special Defense EVs\nhave been reset back to zero!
#org @Nothing
= \v\h02 has no EVs in Special\nDefense! It will have no effect!
Explanation:
Spoiler:
I started with the same open party menu thing as before, so I'll skip it here.
special 0x6
setvar 0x8005 0xSTAT
special2 0x8006 0x7
compare 0x8006 0x0
if true jump @Zero
compare 0x8006 0xFC
if true jump @Max
compare 0x8006 0xFA
if >= jump @Minus250
compare 0x8006 0xF0
if >= jump @Minus240
......
This checks the EV of the stat in question. First I checked if it was equal to 252. If true it went to a script that subtracted 252 from the EV.
Then I checked if if was greater than or equal to 250. If true it jumped to a script that subtracted 250 from the EV and then jumped to another check.
And so on and so forth down the line subtracting by ten for each check. It goes from greatest to least for a reason. It won't work if you do the checks in a different order.
#org @Minus250
setvar 0x8006 0x1FA
special 0xF
jump @Minus10
All the minus scripts subtract the amount of EVs from the stat that it says in the '#org @' section.
This script is like the check at the very beginning in that it checks the amount of EVs in the stat. The difference here is that you only get here if you have 10 or less EVs.
#org @Zero
special 0x6
message @Nothing
callstd MSG_SIGN
release
end
#org @Max
setvar 0x8006 0xFC
special 0xF
jump @Done
The first one is what happens if you have zero EVs already. If just says 'There aren't any EVs'. The second one is what happens if you had 252 EVs at the beginning. It just subtracts 252 EVs.
The reason you can't just subtract 252 EVs from the start no matter what is that it won't work if you do that. The game won't stop at zero, so if you had 100 EVs and you subtracted 252 it wouldn't just set the EV to 0, it would set it to something different.
That's why the script is so long and annoying, because you have to make sure you have the exact amount of EVs.
There is 100000% almost certainly a better way to do either of these, I scripted these a while ago and I can probably find a more efficient way to do it now.
These will work though. I've used them plenty of times and they work fine. The point of my sharing it is to show you one way you could go about solving the problem you posed.
Silly question but for the "vitamin script" I would have to place it in a different offset from the ASM routine you posted first and the same applies for the "reset script" too right?
They have to be in two separate places in the ROM at once in order to work, so yes they would have two different offsets. You replace the XXs with the script offset. When put the offset to the ASM in the item editor make sure to add one to the offset. I forgot if I already mentioned that but it's important information in case you didn't know it already.