-
Notifications
You must be signed in to change notification settings - Fork 991
Add a new growth rate
In this guide we'll be adding the "Fluctuating" growth rate into the game, but you can use the steps below to add in any growth rate you like, including completely custom ones.
A "simple" growth rate that follows the same format of the original four growth rates behaves as a cubic function: (where n is level,
Here,
Because the fluctuating group contains level^4 arguments, and is also a piecewise function - that is, the equation changes depending on the level - the technique I chose to use consists of a lookup table of the exp values for each level. It's absolutely possible to do this by calculating it on the fly, but that will not be covered in this guide.
Navigate to data/pokemon and create a new file named Fluctuating.asm.
Open the file and paste the following
+FlucEXP:
+ table_width 3, FlucEXP
+ for n, 1, MAX_LEVEL + 2
+ if n < 15
+ DEF x = (n + 1) / 3 + 24
+ elif n < 36
+ DEF x = n + 14
+ else
+ DEF x = n / 2 + 32
+ endc
+ def x = x * n**3 / 50
+ db x >> 16, HIGH(x), LOW(x)
+ endr
+ assert_table_length MAX_LEVEL + 1
+
This is a very clever bit of code contributed by Sylvie that generates a table of the experience amounts for each level.
Note that this includes values for up to level 101. without this, a bug will occur after hitting level 100.
It's also possible to hard code the amounts like this:
+FlucEXP:
+ table_width 3, FlucEXP
+ db $00, $00, $00 ;Level 1
+ db $00, $00, $04 ;Level 2
+ db $00, $00, $0D ;Level 3
+ db $00, $00, $20 ;Level 4
+ db $00, $00, $41 ;Level 5
+ db $00, $00, $70 ;Level 6
...
+ assert_table_length MAX_LEVEL
+
If you go down this route, you will need one line for each level. The experience amount are expressed in byte size blocks, three for each level. eg/ for Level 4, the experience required is 32. in 3 byte Hex this would be expressed as 000020, hence the values are 00, 00 and 20. A table like this can be generated with some Excel wizardry and copied into the file. The only real advantage of this method is the ability to put any value you like against each level. If you want to create the Fluctuating or Erratic growth rates, or something else formulaic, the method involving formulas above is recommended.
Navigate to main.asm and add your new file to the bottom of Bank 1E:
...
INCLUDE "engine/overworld/elevator.asm"
INCLUDE "engine/items/tm_prices.asm"
+ INCLUDE "data/pokemon/Fluctuating.asm"
If the compiler complains about the bank being full, you can also start a new Bank below 1E and put it there like this:
...
INCLUDE "engine/overworld/elevator.asm"
INCLUDE "engine/items/tm_prices.asm"
+
+ SECTION "bank1F", ROMX
+ INCLUDE "data/pokemon/Fluctuating.asm"
Open constants/pokemon_data_constants.asm and add a new line as below:
...
const_def
const GROWTH_MEDIUM_FAST
const GROWTH_SLIGHTLY_FAST
const GROWTH_SLIGHTLY_SLOW
const GROWTH_MEDIUM_SLOW
const GROWTH_FAST
const GROWTH_SLOW
+ const GROWTH_FLUCTUATING
DEF NUM_GROWTH_RATES EQU const_value
...
Alternatively, skip this step and just reuse "GROWTH_SLIGHTLY_FAST" or "GROWTH_SLIGHTLY_SLOW" which exist but are not used. In that case, skip the next part to and go straight to section 5.
Add in a new line here, the numbers DO NOT MATTER as they will be ignored by the code. Alternatively, you can skip this step if you are reusing "Slightly Fast" or "Slightly Slow".
...
growth_rate 4, 5, 0, 0, 0 ; Fast
growth_rate 5, 4, 0, 0, 0 ; Slow
+ growth_rate 5, 4, 0, 0, 0 ; Fluctuating
assert_table_length NUM_GROWTH_RATES
Now that we have a table in the ROM, the script that calculates experience needs to read from it for your new growth rate.
Open engine/pokemon/experience.asm
First we will add an exception so that the normal calculation method is skipped and the table lookup is used:
...
; calculates the amount of experience needed for level d
CalcExperience::
ld a, [wMonHGrowthRate]
+ cp GROWTH_FLUCTUATING
+ jp z, .fluctuating
add a
add a
ld c, a
...
If you are reusing another growth rate, just replace GROWTH_FLUCTUATING with the appropriate constant.
Finally, the actual looking up:
...
.addCubedTerm
pop bc
ldh a, [hExperience + 2]
add b
ldh [hExperience + 2], a
pop bc
ldh a, [hExperience + 1]
adc b
ldh [hExperience + 1], a
pop bc
ldh a, [hExperience]
adc b
ldh [hExperience], a
ret
+.fluctuating
+ ld b, 0
+ ld a, d ; d contains level
+ dec a ; a now contains level minus 1
+ ld c, a ; c now contains level minus 1
+ ld hl, FlucEXP ; table of exp values loaded into hl
+ add hl, bc ; done three times because its 3 bytes per level
+ add hl, bc ; there is probably a more slick way of doing this
+ add hl, bc ; but if its not broke...
+ ld a, BANK(FlucEXP);its the same bank
+ push de
+ ld de, wUnusedD153;ram destination for far copy its a 1 byte unused buffer with two empty bytes after it, perfect size for what this needs
+ ld bc, $3;number of bytes to copy
+ call FarCopyData
+ ld hl, wUnusedD153
+ ld a, [hli]
+ ldh [hExperience], a
+ ld a, [hli]
+ ldh [hExperience + 1], a
+ ld a, [hl]
+ ldh [hExperience + 2], a
+ pop de
+ ret
; calculates d*d
CalcDSquared:
xor a
...
And with that, it should work. Don't forget to change the Growth rate in the Pokemon Base Stats file to use it on a Pokemon.
Read below to create a "simple" growth rate as mentioned in the introduction.
Here we'll create a basic polynomial growth rate named: "Too Fast".
Open constants/pokemon_data_constants.asm and add a new line as below:
...
const_def
const GROWTH_MEDIUM_FAST
const GROWTH_SLIGHTLY_FAST
const GROWTH_SLIGHTLY_SLOW
const GROWTH_MEDIUM_SLOW
const GROWTH_FAST
const GROWTH_SLOW
+ const GROWTH_TOO_FAST
DEF NUM_GROWTH_RATES EQU const_value
...
Open data/growth_rates.asm and add a new line as below:
...
growth_rate 4, 5, 0, 0, 0 ; Fast
growth_rate 5, 4, 0, 0, 0 ; Slow
+ growth_rate 1, 4, 0, 0, 0 ; Too Fast
assert_table_length NUM_GROWTH_RATES
Note the numbers here are each a part of the equation where growth_rate a, b, c, d, e
go into:
This example growth rate maxes out at only 250,000 EXP.
You can also plot the function in desmos to get idea for the values you would like to use.