Regional forms - pret/pokecrystal GitHub Wiki

This tutorial, adapted from Pokémon Fool's Gold, will show you how to add rudimentary regional variants. The trick is that, internally, the regional forms are entirely different species-- however, we pull a couple of tricks to make it seem like it's just the same mon. However, it's not a perfect solution-- if there's a more "proper" way of adding forms, please add it :)

As an example, we'll use Hisuian Typhlosion.

Contents

  1. Adding a new species
  2. Changing the way dex numbers work
  3. Regional evolutions

1. Adding a new species

Follow this tutorial, adding the species constant TYPHLOSION_H. Make all of the data according to Hisuian Typhlosion: giving it new sprites, making it Fire/Ghost type, etc. We'll handle its evolution data later... for now, just make it an isolated single-stage mon. I recommend putting the constant at the end of the list, where Munchlax is in the tutorial. On that same note, I highly recommend implementing this one, too, so that it lands after regular Typhlosion in the Old dex order. Similarly, in the New dex order and alphabetical sorting, put Hisuian Typhlosion after regular Typhlosion.

2. Changing the way dex numbers work

For the "illusion" of forms to work, regular Typhlosion and Hisuian Typhlosion need to have the same dex number-- otherwise, the jig will be up!

Currently, dex numbers are simply generated based on the pokemon_constants.asm order. However, if we instead make dex numbers work like names-- that is, assigning each species a string to use as a "number"-- we can include two species with the same number.

Edit main.asm:

 SECTION "bank24", ROMX

 INCLUDE "engine/phone/phone.asm"
 INCLUDE "engine/rtc/timeset.asm"
 INCLUDE "engine/pokegear/pokegear.asm"
 INCLUDE "engine/events/fish.asm"
 INCLUDE "engine/games/slot_machine.asm"
+INCLUDE "data/pokemon/dex_numbers.asm"

Create data/pokemon/dex_numbers.asm:

+PokemonNumbers::
+	db "001@@"
+	db "002@@"
+	db "003@@"
+	...
+	db "249@@"
+	db "250@@"
+	db "251@@"
+	db "157@@"
+	db "???@@"
+	db "???@@"
+	db "???@@"
+	db "???@@"

There are three things of note here: One, the last number is 157, corresponding to Hisuian Typhlosion; two, there are a few extra spots at the end to account for the rest of the spaces (data/pokemon/names.asm does something similar); and three, there are two padding @'s instead of just one; this is in case you want to add an extra symbol to mark a regional form, like 157h, as is done in Fool's Gold.

Edit home/names.asm:

 GetPokemonName::
	...
	pop hl
	pop af
	rst Bankswitch
	ret

+GetPokemonNumber::
+	ldh a, [hROMBank]
+	push af
+	push hl
+	ld a, BANK(PokemonNumbers)
+	rst Bankswitch
+
+	ld a, [wNamedObjectIndexBuffer]
+	dec a
+	ld d, 0
+	ld e, a
+	ld h, 0
+	ld l, a
+	add hl, hl ; hl = hl * 4
+	add hl, hl ; hl = hl * 4
+	add hl, de ; hl = (hl*4) + de
+	ld de, PokemonNumbers
+	add hl, de
+
+	ld de, wStringBuffer1
+	push de
+	ld bc, 4
+	call CopyBytes
+	ld hl, wStringBuffer1 + 4
+	ld [hl], "@"
+	pop de
+
+	pop hl
+	pop af
+	rst Bankswitch
+	ret

Now, we need to actually use the new dex number system in the relevant places: the Old Pokédex mode list, the Pokédex entry, the stats screen, and the Hall of Fame.

Edit engine/pokedex/pokedex.asm:

Pokedex_PrintNumberIfOldMode:
	ld a, [wCurDexMode]
	cp DEXMODE_OLD
	jr z, .printnum
	ret

.printnum
	push hl
	ld de, -SCREEN_WIDTH
	add hl, de
	ld de, wTempSpecies
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
+	push hl
+	call GetPokemonNumber
+	pop hl
+	call PlaceString
	pop hl
	ret

Edit engine/pokedex/pokedex_2.asm:

DisplayDexEntry:
	...
; Print dex number
	hlcoord 2, 8
	ld a, $5c ; No
	ld [hli], a
	ld a, $5d ; .
	ld [hli], a
	ld de, wTempSpecies
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
+	call GetPokemonNumber
+	hlcoord 4, 8
+	call PlaceString

Edit engine/pokemon/stats_screen.asm:

StatsScreen_InitUpperHalf:
	...
	ld [hl], "№"
	inc hl
	ld [hl], "."
	inc hl
	hlcoord 10, 0
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	ld de, wDeciramBuffer
-	call PrintNum
+	call GetPokemonNumber
+	call PlaceString
	hlcoord 14, 0

Edit engine/events/halloffame.asm:

DisplayHOFMon:
	...
	ld a, "№"
	ld [hli], a
	ld [hl], "<DOT>"
	hlcoord 3, 13
-	ld de, wDeciramBuffer
-	lb bc, PRINTNUM_LEADINGZEROS | 1, 3
-	call PrintNum
+	call GetPokemonNumber
+	call PlaceString

3. Regional evolutions

Now, Hisuian Typhlosion is in the game, and both it and its regular counterpart correctly display as #157, but there's no way to get it by evolution! For some Pokémon, this may be desirable, such as standalone lines, but for others, there should be a way to evolve into the regional form. Since Hisui does not exist in Crystal, what we can do is make Quilava evolve into regular Typhlosion in Johto, and Hisuian Typhlosion in Kanto.

Edit constants/pokemon_data_constants.asm:

; evolution types (used in data/pokemon/evos_attacks.asm)
	const_def 1
	const EVOLVE_LEVEL
	const EVOLVE_ITEM
	const EVOLVE_TRADE
	const EVOLVE_HAPPINESS
	const EVOLVE_STAT
+	const EVOLVE_LEVEL_REGION

Edit engine/pokemon/evolve.asm:

(Note that you will probably have to change some jr's to jp.)

 EvolveAfterBattle_MasterLoop:
	...
	ld a, b
	cp EVOLVE_LEVEL
	jp z, .level

	cp EVOLVE_HAPPINESS
	jr z, .happiness
+
+	cp EVOLVE_LEVEL_REGION
+	jp z, .level_region
	...
 .item
	ld a, [hli]
	ld b, a
	ld a, [wCurItem]
	cp b
	jp nz, .dont_evolve_3

	ld a, [wForceEvolution]
	and a
	jp z, .dont_evolve_3
	ld a, [wLinkMode]
	and a
	jp nz, .dont_evolve_3
	jr .proceed

+.level_region
+	ld a, [hli]
+	ld b, a
+	ld a, [wTempMonLevel]
+	cp b
+	jp c, .dont_evolve_2
+	call IsMonHoldingEverstone
+	jp z, .dont_evolve_2
+	
+	push hl
+	farcall RegionCheck ; returns 1 in e if in Kanto; returns 0 in e if in Johto
+	ld a, e
+	and a
+	pop hl
+
+	jr nz, .kanto
+
+	inc hl
+
+.kanto
+	jr .proceed

Now, all that's left is to actually use the new evolution method!

Edit data/pokemon/evos_attacks.asm:

QuilavaEvosAttacks:
-	db EVOLVE_LEVEL, 36, TYPHLOSION
+	db EVOLVE_LEVEL_REGION, 36, TYPHLOSION_H, TYPHLOSION
	db 0 ; no more evolutions
	db 1, TACKLE
	db 1, LEER
	db 1, SMOKESCREEN
	db 6, SMOKESCREEN
	db 12, EMBER
	db 21, QUICK_ATTACK
	db 31, FLAME_WHEEL
	db 42, SWIFT
	db 54, FLAMETHROWER
	db 0 ; no more level-up moves

And that's all there is to it! Quilava will now evolve into Hisuian Typhlosion in Kanto, and regular Typhlosion in Johto.

One important thing to know is that RegionCheck doesn't count all of "Kanto" as Kanto for evolution purposes-- notably, any area between New Bark Town and the Pokémon League will count as Johto. This is the same function that is used for battle music, so you can tell which areas are which based on that.

⚠️ **GitHub.com Fallback** ⚠️