summaryrefslogtreecommitdiff
path: root/engine/pokemon/experience.asm
diff options
context:
space:
mode:
Diffstat (limited to 'engine/pokemon/experience.asm')
-rwxr-xr-xengine/pokemon/experience.asm149
1 files changed, 149 insertions, 0 deletions
diff --git a/engine/pokemon/experience.asm b/engine/pokemon/experience.asm
new file mode 100755
index 00000000..3ee4b2a8
--- /dev/null
+++ b/engine/pokemon/experience.asm
@@ -0,0 +1,149 @@
+; calculates the level a mon should be based on its current exp
+CalcLevelFromExperience::
+ ld a, [wLoadedMonSpecies]
+ ld [wd0b5], a
+ call GetMonHeader
+ ld d, $1 ; init level to 1
+.loop
+ inc d ; increment level
+ call CalcExperience
+ push hl
+ ld hl, wLoadedMonExp + 2 ; current exp
+; compare exp needed for level d with current exp
+ ld a, [hExperience + 2]
+ ld c, a
+ ld a, [hld]
+ sub c
+ ld a, [hExperience + 1]
+ ld c, a
+ ld a, [hld]
+ sbc c
+ ld a, [hExperience]
+ ld c, a
+ ld a, [hl]
+ sbc c
+ pop hl
+ jr nc, .loop ; if exp needed for level d is not greater than exp, try the next level
+ dec d ; since the exp was too high on the last loop iteration, go back to the previous value and return
+ ret
+
+; calculates the amount of experience needed for level d
+CalcExperience::
+ ld a, [wMonHGrowthRate]
+ add a
+ add a
+ ld c, a
+ ld b, 0
+ ld hl, GrowthRateTable
+ add hl, bc
+ call CalcDSquared
+ ld a, d
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld a, [hl]
+ and $f0
+ swap a
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld a, [hli]
+ and $f
+ ld [H_DIVISOR], a
+ ld b, $4
+ call Divide
+ ld a, [H_QUOTIENT + 1]
+ push af
+ ld a, [H_QUOTIENT + 2]
+ push af
+ ld a, [H_QUOTIENT + 3]
+ push af
+ call CalcDSquared
+ ld a, [hl]
+ and $7f
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld a, [H_PRODUCT + 1]
+ push af
+ ld a, [H_PRODUCT + 2]
+ push af
+ ld a, [H_PRODUCT + 3]
+ push af
+ ld a, [hli]
+ push af
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld [H_MULTIPLICAND + 1], a
+ ld a, d
+ ld [H_MULTIPLICAND + 2], a
+ ld a, [hli]
+ ld [H_MULTIPLIER], a
+ call Multiply
+ ld b, [hl]
+ ld a, [H_PRODUCT + 3]
+ sub b
+ ld [H_PRODUCT + 3], a
+ ld b, $0
+ ld a, [H_PRODUCT + 2]
+ sbc b
+ ld [H_PRODUCT + 2], a
+ ld a, [H_PRODUCT + 1]
+ sbc b
+ ld [H_PRODUCT + 1], a
+; The difference of the linear term and the constant term consists of 3 bytes
+; starting at H_PRODUCT + 1. Below, hExperience (an alias of that address) will
+; be used instead for the further work of adding or subtracting the squared
+; term and adding the cubed term.
+ pop af
+ and $80
+ jr nz, .subtractSquaredTerm ; check sign
+ pop bc
+ ld a, [hExperience + 2]
+ add b
+ ld [hExperience + 2], a
+ pop bc
+ ld a, [hExperience + 1]
+ adc b
+ ld [hExperience + 1], a
+ pop bc
+ ld a, [hExperience]
+ adc b
+ ld [hExperience], a
+ jr .addCubedTerm
+.subtractSquaredTerm
+ pop bc
+ ld a, [hExperience + 2]
+ sub b
+ ld [hExperience + 2], a
+ pop bc
+ ld a, [hExperience + 1]
+ sbc b
+ ld [hExperience + 1], a
+ pop bc
+ ld a, [hExperience]
+ sbc b
+ ld [hExperience], a
+.addCubedTerm
+ pop bc
+ ld a, [hExperience + 2]
+ add b
+ ld [hExperience + 2], a
+ pop bc
+ ld a, [hExperience + 1]
+ adc b
+ ld [hExperience + 1], a
+ pop bc
+ ld a, [hExperience]
+ adc b
+ ld [hExperience], a
+ ret
+
+; calculates d*d
+CalcDSquared:
+ xor a
+ ld [H_MULTIPLICAND], a
+ ld [H_MULTIPLICAND + 1], a
+ ld a, d
+ ld [H_MULTIPLICAND + 2], a
+ ld [H_MULTIPLIER], a
+ jp Multiply
+
+INCLUDE "data/growth_rates.asm"