Add a new growth rate - pret/pokered GitHub Wiki

1. Introduction

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.

To create a "simple" growth rate that follows the same format of the original four growth rates (where n is level, (a/b) * n^3 + c * n^2 + d * n - e), jump to the end of this guide.

2. Creating the Data File

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 + 1
+        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
+	

This is a very clever bit of code contributed by Sylvie that generates a table of the experience amounts for each level.

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.

3.Include your new file in the ROM

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"

4. Creating the new Growth Rate

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.

Open data/growth_rates.asm

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

5. Reading from the Table

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.

6. Simple Growth Rate

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: (a/b) * n^3 + c * n^2 + d * n - e and n is level.

This example growth rate maxes out at only 250,000 EXP.