summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gain-experience-from-catching-Pokémon.md101
1 files changed, 101 insertions, 0 deletions
diff --git a/Gain-experience-from-catching-Pokémon.md b/Gain-experience-from-catching-Pokémon.md
new file mode 100644
index 0000000..53bc9d1
--- /dev/null
+++ b/Gain-experience-from-catching-Pokémon.md
@@ -0,0 +1,101 @@
+This tutorial is for how to make it so that your party Pokémon get experience points from capturing wild Pokémon, as in generation VI onwards. As you'll soon see, it's a pretty easy addition.
+
+
+## Contents
+
+1. [Add a new function](#1-add-a-new-function)
+2. [Call the function](#2-call-the-function)
+
+
+## 1. Add a new function
+
+Luckily for us, the UpdateBattleStateAndExperienceAfterEnemyFaint function in the core.asm already does what we want, with a few tweaks. This routine is called when your Pokémon knocks out an opposing Pokémon (either wild or a Trainer's). So we'll make use of it!
+
+Edit [engine/battle/core.asm](../blob/master/engine/battle/core.asm):
+
+```diff
+UpdateBattleStateAndExperienceAfterEnemyFaint:
+ call UpdateBattleMonInParty
+ ...
+ ld [wBattleParticipantsNotFainted], a
+ ret
+
++ApplyExperienceAfterEnemyCaught:
++ call IsAnyMonHoldingExpShare
++ jr z, .skip_exp
++ ld hl, wEnemyMonBaseStats
++ ld b, wEnemyMonEnd - wEnemyMonBaseStats
++.loop
++ srl [hl]
++ inc hl
++ dec b
++ jr nz, .loop
++
++.skip_exp
++ ld hl, wEnemyMonBaseStats
++ ld de, wBackupEnemyMonBaseStats
++ ld bc, wEnemyMonEnd - wEnemyMonBaseStats
++ call CopyBytes
++ xor a
++ ld [wGivingExperienceToExpShareHolders], a
++ call GiveExperiencePoints
++ call IsAnyMonHoldingExpShare
++ ret z
++
++ ld a, [wBattleParticipantsNotFainted]
++ push af
++ ld a, d
++ ld [wBattleParticipantsNotFainted], a
++ ld hl, wBackupEnemyMonBaseStats
++ ld de, wEnemyMonBaseStats
++ ld bc, wEnemyMonEnd - wEnemyMonBaseStats
++ call CopyBytes
++ ld a, $1
++ ld [wGivingExperienceToExpShareHolders], a
++ call GiveExperiencePoints
++ pop af
++ ld [wBattleParticipantsNotFainted], a
++ ret
+
+IsAnyMonHoldingExpShare:
+ ld a, [wPartyCount]
+```
+
+Here we made a new function called ApplyExperienceAfterEnemyCaught. Basically, everything is copied except anything related to Trainers, since you wouldn't capture a Trainer's Pokémon ever (you don't want to be a thief). Moreover, there's no need to update the battle scene or change the music to the victory jingle since the game already does this for us once the wild Pokémon is successfully captured.
+
+
+## 2. Call the function
+
+We have a new function but we need to call it at the appropriate place. This is done in the file that dictates how a ball operates. Since these are (in Vanilla Crystal) in different banks, a farcall needs to be made instead of a regular call. But is that enough? Not really, we need to be a bit more careful with it.
+
+Edit [engine/items/item_effects.asm](../blob/master/engine/items/item_effects.asm):
+
+```diff
+.Transformed:
+ ld a, [wEnemyMonSpecies]
+ ...
+ ld hl, Text_GotchaMonWasCaught
+ call PrintText
+
++ ld a, [wTempSpecies]
++ ld l, a
++ ld a, [wCurPartyLevel]
++ ld h, a
++ push hl
++ farcall ApplyExperienceAfterEnemyCaught
++ pop hl
++ ld a, l
++ ld [wCurPartySpecies], a
++ ld [wTempSpecies], a
++ ld a, h
++ ld [wCurPartyLevel], a
+
+ call ClearSprites
+
+```
+
+Turns out just doing the farcall isn't enough. Indeed, if your Pokémon happens to level up, wCurPartyLevel gets overwritten. Even worse, the species also gets overwritten which would cause you to capture the wrong species! To get the intended result, we need to store the values the game needs to add the proper Pokémon to your collection, and then retrieve them after the experience routine is over with.
+
+And just like that, you're ready to catch 'em all and raise your Pokémon in one fell swoop.
+
+![Screenshot](screenshots/catch_exp.png)