-
Notifications
You must be signed in to change notification settings - Fork 817
Improve the trainer rematch system
This tutorial aims to improve the rematch system by removing the fight count check that the trainer rematch system performs before selecting a rematchable trainer's party and by making trainers automatically offer their phone number after first battling them. First, I think it useful to provide a brief primer on the rematch system, what exactly we will change, and why the changes may be desirable.
Before a rematch, the Pokemon Crystal rematch system performs two checks: it initially looks in memory for a count that is based on which of the rematchable trainer's parties you have last defeated, then it checks whether you have reached a certain point in the game. Upon first defeating a rematchable trainer, a count of 1 will be stored in memory, followed by a count of 2 once you defeat the first rematch party, etc. However, the first rematch party will not load unless you have also reached a certain point in the game, determined by either a location (flypoint check) or an event being cleared (event flag check).
In this tutorial, we will use Schoolboy Alan on Route 36 as an example. In order to rematch him a second time, you must have defeated him in the first rematch battle (storing a count of 2) in addition to having reached Blackthorn. Say that you never received a rematch call from him by the time you have reached Blackthorn (a common scenario), so you never defeated him in a rematch. This means that, since you cannot load the required count (2), it does not matter whether you have reached Blackthorn or not; you must fight Alan's first rematch party, which will likely be thoroughly underleveled relative to your party.
We will resolve this by removing the fight count check entirely, thus checking only for the player's game progress in determining the rematch party that will be loaded. This will allow for rematch trainers to be much closer to the player's level even if they have not been defeated in a rematch before.
Additionally, it is mildly annoying to have to talk to trainers after battling them for the first time in order to obtain their numbers. If you do not know which trainers offer their phone numbers, then you either have to talk to every trainer after battle or look up a guide, so it is quite convenient to have the rematch trainers load the "phone number offer" text immediately after battle. Despite the impression perhaps left by my lengthy preamble, these changes are actually very simple to make.
The code to be changed is in the map file where the trainer is located - Route 36 for our example - so open and edit maps/Route36.asm:
.ChooseRematch:
scall .Rematch
winlosstext SchoolboyAlan1BeatenText, 0
- readmem wAlanFightCount
- ifequal 4, .Fight4
- ifequal 3, .Fight3
- ifequal 2, .Fight2
- ifequal 1, .Fight1
- ifequal 0, .LoadFight0
-.Fight4:
checkevent EVENT_RESTORED_POWER_TO_KANTO
iftrue .LoadFight4
-.Fight3:
checkevent EVENT_BEAT_ELITE_FOUR
iftrue .LoadFight3
-.Fight2:
checkflag ENGINE_FLYPOINT_BLACKTHORN
iftrue .LoadFight2
-.Fight1:
checkflag ENGINE_FLYPOINT_OLIVINE
iftrue .LoadFight1
-.LoadFight0:
loadtrainer SCHOOLBOY, ALAN1
startbattle
reloadmapafterbattle
- loadmem wAlanFightCount, 1
clearflag ENGINE_ALAN_READY_FOR_REMATCH
end
This script no longer checks for the count using readmem
, thus the corresponding functions are no longer necessary; the code will simply perform the event/flag checks in order. You will need to edit the equivalent code in each map file for every trainer that you want to have ignore the fight count check.
Also, we removed the loadmem wAlanFightCount
line since we don't need to increase the counter anymore. Make sure to also delete the counter increase below each .LoadFight
in the other map files.
We will accomplish this by removing every instance of endifjustbattled
(simply ends the script after battle, which we don't want) in every rematch script. This forces rematch trainers to automatically offer their phone number after battle rather than requiring the player to speak to trainers after battle to obtain it. Simply do the following:
TrainerSchoolboyAlan1:
trainer SCHOOLBOY, ALAN1, EVENT_BEAT_SCHOOLBOY_ALAN, SchoolboyAlan1SeenText, SchoolboyAlan1BeatenText, 0, .Script
.Script:
loadvar VAR_CALLERID, PHONE_SCHOOLBOY_ALAN
- endifjustbattled
opentext
Again, you will need remove this code from every rematch trainer script. And that's it!
Optionally, you can remove the counter variables in wram.asm, as these map files were the only places where they were being used. Removing those variables can free up to 28 bytes. Be sure to replace them with something else, or padding with a ds
, or you will end up shifting all variables stored after, therefore rendering your save file corrupted.
...
wMobileBattleRoomSceneID:: db
- ds 49
-
-; fight counts
-wJackFightCount:: db
-wBeverlyFightCount:: db ; unreferenced
-wHueyFightCount:: db
-wGavenFightCount:: db
-wBethFightCount:: db
-wJoseFightCount:: db
-wReenaFightCount:: db
-wJoeyFightCount:: db
-wWadeFightCount:: db
-wRalphFightCount:: db
-wLizFightCount:: db
-wAnthonyFightCount:: db
-wToddFightCount:: db
-wGinaFightCount:: db
-wIrwinFightCount:: db ; unreferenced
-wArnieFightCount:: db
-wAlanFightCount:: db
-wDanaFightCount:: db
-wChadFightCount:: db
-wDerekFightCount:: db ; unreferenced
-wTullyFightCount:: db
-wBrentFightCount:: db
-wTiffanyFightCount:: db
-wVanceFightCount:: db
-wWiltonFightCount:: db
-wKenjiFightCount:: db ; unreferenced
-wParryFightCount:: db
-wErinFightCount:: db
-
- ds 100
+ ds 177
wEventFlags:: flag_array NUM_EVENTS
...
The events that are checked in order to determine which party to load can be easily modified by swapping a checkflag
______ or checkevent
______ with any other listed in either flypoints.asm or event_flags.asm. This is especially useful if you wish to add rematch parties or simply have rematch parties updated more frequently, progression-wise.
Also, when modifying rematch parties, keep in mind that not all of them correspond to the map file code as neatly as they do for Schoolboy Alan, where ALAN1
is loaded for the initial fight, ALAN2
for the first rematch, ALAN3
for the second rematch, etc. For example, some will load "TRAINERNAME3
" for the initial fight, so you must make sure that you enter the initial party data (in trainers/parties.asm) in the field for the given trainer's third party. However, TRAINERNAME3
will generally correspond to the third field for a given trainer starting from the top of the parties file. The exact trainer that is loaded is indicated below each .Loadfight
(directly below the code we edited). For example: loadtrainer SCHOOLBOY, ALAN2
.
Finally, for a list of rematchable trainers to help you find and change all of their codes, see the third header (Phone) on this page: https://www.serebii.net/crystal/pokegear.shtml