summaryrefslogtreecommitdiff
path: root/Level-cap.md
diff options
context:
space:
mode:
Diffstat (limited to 'Level-cap.md')
-rw-r--r--Level-cap.md218
1 files changed, 218 insertions, 0 deletions
diff --git a/Level-cap.md b/Level-cap.md
new file mode 100644
index 0000000..fbe21ff
--- /dev/null
+++ b/Level-cap.md
@@ -0,0 +1,218 @@
+This tutorial guides you through changing the max level. You will add a new variable, modify level cap logic, and optionally remove gaining exp. once a pokemon is the max level.
+
+**TODO**:
+Investigate wether one is able to set the level cap by modifying `MAX_LEVEL EQU [0-255]` in `constants/battle_constants.asm`.
+
+## 1. Add Level Cap variable
+First, we want to add a `wLevelCap` variable to `wram.asm` in the root folder.
+In `wram.asm`, go to line 2668, `wBeverlyFightCount:: db ; unused`.
+Since this byte is unused, you can replace it.
+Replace this line with `wLevelCap:: db`.
+This is the value we'll be checking for the level cap
+
+```diff
+; fight counts
+wJackFightCount:: db ; d9f2
+- wBeverlyFightCount:: db ; unused
++ wLevelCap:: db
+wHueyFightCount:: db
+wGavenFightCount:: db
+```
+
+To set the level cap, write this in a script:
+`loadmem wLevelCap, [0-255] ; number from 0 to 255 representing what your level cap should be`
+
+## 2. Replace first level cap check
+
+In `engine/pokemon/experience.asm`, go to line 9: `cp LOW(MAX_LEVEL + 1)`.
+This is what we first need to change.
+Before the `ld a, d` on the line before it, add code to load the new level cap into register `b`.
+
+```diff
+.next_level
+ inc d
++ ld a, [wLevelCap]
++ inc a
++ push bc
++ ld b, a
+ ld a, d
++ cp b
++ pop bc
+ cp LOW(MAX_LEVEL + 1)
+ jr z, .got_level
+ call CalcExpAtLevel
+```
+
+## 3. Replace the rest of the cap checks
+
+There are now five more instances of `MAX_LEVEL` that you'll need to change.
+First, go to the `.no_exp_overflow` label located in `engine/battle/core.asm`.
+Instead of storing the `MAX_LEVEL` value, we load our custom max level.
+
+```diff
+.no_exp_overflow
+ ld a, [wCurPartyMon]
+ ld e, a
+ ld d, 0
+ ld hl, wPartySpecies
+ add hl, de
+ ld a, [hl]
+ ld [wCurSpecies], a
+ call GetBaseData
+ push bc
+- ld d, MAX_LEVEL
++ push af
++ ld a, [wLevelCap]
++ ld d, a
++ pop af
+ callfar CalcExpAtLevel
+```
+
+Next, `ctrl + f` for the next instance of `MAX_LEVEL`, located in the `.not_max_exp` label. You'll notice that the line before this reads `ld a, [hl]` Before this line, load the level cap into register b. Then, after `ld a, [hl]`, add a comparison and restore the `bc` register. Here we use the comparison to control the jump.
+
+```diff
+.not_max_exp
+; Check if the mon leveled up
+ xor a ; PARTYMON
+ ld [wMonType], a
+ predef CopyMonToTempMon
+ callfar CalcLevel
+ pop bc
+ ld hl, MON_LEVEL
+ add hl, bc
++ ld a, [wLevelCap]
++ push bc
++ ld b, a
+ ld a, [hl]
++ cp b
++ pop bc
+- cp MAX_LEVEL
+ jp nc, .next_mon
+```
+
+Third, ctrl + f for the next instance of MAX_LEVEL, located in the `AnimateExpBar` label. You'll notice there's a `ld a, [wBattleMonLevel]` before it. Before this, add
+
+```diff
+AnimateExpBar:
+ push bc
+
+ ld hl, wCurPartyMon
+ ld a, [wCurBattleMon]
+ cp [hl]
+ jp nz, .finish
+
++ ld a, [wLevelCap]
++ push bc
++ ld b, a
+ ld a, [wBattleMonLevel]
++ cp b
++ pop bc
+- cp MAX_LEVEL
+ jp nc, .finish
+```
+
+Fourth, ctrl + f for the next instance of MAX_LEVEL. Replace `ld d, MAX_LEVEL` with loading the custom max level.
+
+```diff
+ ld [hli], a
+ ld [hl], a
+
+.NoOverflow:
++ push af
++ ld a, [wLevelCap]
++ ld d, a
++ pop af
+ callfar CalcExpAtLevel
+ ldh a, [hProduct + 1]
+ ld b, a
+```
+
+Fifth, ctrl + f for the final instance of MAX_LEVEL. You'll notice before it reads `ld a, e`. Before this, lod the level cap into b, then do the comparison on that.
+
+```diff
+ ld a, e
+ ld d, a
+
+.LoopLevels:
++ ld a, [wLevelCap]
++ push bc
++ ld b, a
+ ld a, e
+- cp MAX_LEVEL
++ cp b
++ pop bc
+ jr nc, .FinishExpBar
+ cp d
+ jr z, .FinishExpBar
+ inc a
+```
+
+Now you're done with replacing the max level checks with the level cap checks.
+
+## 4. Optional: Remove exp. gain text at max level
+
+You'll notice that the exp. gain text still displays when you reach the level cap.
+To remove this, go to line 7059 in `engine/battle/core.asm`, which should be about the lines of
+
+```diff
+.stat_exp_awarded
+ inc de
+ inc de
+ dec c
+ jr nz, .stat_exp_loop
++ pop bc
++ ld hl, MON_LEVEL
++ add hl, bc
++ ld a, [wLevelCap]
++ push bc
++ ld b, a
++ ld a, [hl]
++ cp b
++ pop bc
++ jp nc, .next_mon
++ push bc
+ xor a
+ ldh [hMultiplicand + 0], a
+ ldh [hMultiplicand + 1], a
+ ld a, [wEnemyMonBaseExp]
+```
+
+Next, go to
+
+```diff
+.EvenlyDivideExpAmongParticipants:
+; count number of battle participants
+ ld a, [wBattleParticipantsNotFainted]
+ ld b, a
+ ld c, PARTY_LENGTH
+ ld d, 0
+.count_loop
++ push bc
++ push de
++ ld a, [wLevelCap]
++ ld b, a
++ ld a, [wPartyCount]
++ cp c
++ jr c, .no_mon
++ ld a, c
++ dec a
++ ld hl, wPartyMon1Level
++ call GetPartyLocation
++ ld a, [hl]
++.no_mon
++ cp b
++ pop de
++ pop bc
++ jr nz, .gains_exp
++ srl b
++ ld a, d
++ jr .no_exp
++.gains_exp
+ xor a
+ srl b
+ adc d
+ ld d, a
++.no_exp
+ dec c
+ jr nz, .count_loop
+```