-
Notifications
You must be signed in to change notification settings - Fork 806
Make the field move Headbutt work with Kanto trees
You may have noticed that the field move Headbutt works on trees that are only found in Johto.
In this tutorial, you will learn how to make it work with all Kanto trees.
- Make Headbutt trigger on Kanto trees
- Design a custom shake animation
- Populate the trees with Pokémon species
This part is the easy one. But before we start, we need to make a point about terminology.
A metatile or block is a logical unit defined in Pokémon Crystal's engine that is used as a building brick to create a map. It is composed of 4 by 4 tiles from the graphical tileset, and of 2 by 2 collision types. The blocks that make up a map are stored in a .blk file.
A tile is an 8 by 8 pixels graphical unit. The Game Boy can only display graphics by pulling tiles from its VRAM (Video RAM).
Note that in pokecrystal, the term "tileset" refers to both the actual graphical tileset that defines tiles' graphics, and also the "metatiles set" or "blockset" that is a metatile or block collection.
The term "tile" is also often misused to describe a 16x16 pixels (or 2x2 tiles) cell on the overworld's grid.
Try not to get confused, and always double check.
Now let's get back to the actual work!
When pressing A while facing a tree, we want the game to recognize this tree as compatible with Headbutt.
To do so, all we have to do is to change the concerned Kanto's metatiles collision type.
The collisions of Kanto's metatiles are stored in data/tilesets/kanto_collision.asm
You can directly edit this file, or use a more user-friendly approach by using a tool like Polished Map.
Open Polished Map, then open a map that uses the Kanto tileset, like CeruleanCity.blk
For better viewing, click on the Palettes dropdown menu then select Day.
On the left panel, right-click on a metatile that contains trees. As an example, we will do the tile with the hexadecimal code $32 (or 50 in decimal).
This will open a pop-up window in which you can edit the collisions on the right panel.
Change the collisions associated to the trees from WALL
to HEADBUTT_TREE
Repeat this action for all metatiles. The list of the concerned metatiles is the following:
15, 50, 51, 52, 53, 54, 66, 76, 96, 108, 109, 110, 111
or in hexadecimal:
0F, 32, 33, 34, 35, 36, 42, 4C, 60, 6C, 6D, 6E, 6F
- Pay attention to the metatile $42 (66 decimal) whose the bottom left collision should remain as
WALL
in order to preserve the ledge.
Once you're done, don't forget to save! Saving will update data/tilesets/kanto_collision.asm
Then build the project, and test it.
Reaching Kanto may take a long time. Please use cheatcodes, WRAM editing, edit the
warp_event
of a door to transport you to a Kanto location, and/or any other method that can speed up your test process.
You can now headbutt trees in Kanto!
However, the animation is using Johto's tree and no Pokémon ever falls from the tree.
Let's work on those issues.
For a custom animation to work we first need to:
- design it,
- include it into the project,
- edit the code to load it at the right moment and under the right conditions.
I'll save you some time with the design, and share my version that you can use:
Save it under gfx/overworld/headbutt_tree_kanto.png To reference this image in the project, open engine/events/field_moves.asm and add the following:
HeadbuttTreeGFX:
INCBIN "gfx/overworld/headbutt_tree.2bpp"
+
+HeadbuttTreeKantoGFX:
+INCBIN "gfx/overworld/headbutt_tree_kanto.2bpp"
HideHeadbuttTree:
Now is the time to edit the code to load this shake animation in place of the Johto tree when in Kanto.
The animation is split in 2 parts:
- the 4 background tiles of the selected tree are replaced by 4 identical grass tiles.
- now that the tree has been replaced by grass, the tree from the animation is loaded over it as a sprite whose frames will be animated.
The grass used in Kanto is different that the one used it Johto.
The tile uses a different design, and the tile is located at a different place within the tileset.
Edit HideHeadbuttTree:
in engine/events/field_moves.asm
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
+ ld a, [wMapTileset]
+ cp TILESET_KANTO
+ ld a, $2c ; grass block
+ jr z, .replacement_tile_determined
+
ld a, $05 ; grass block
+.replacement_tile_determined
ld [hli], a
ld [hld], a
ld bc, SCREEN_WIDTH
The code is pretty self-explanatory: when the loaded tileset is the one from Kanto, we will use the tile at the location $2c in the tileset as the grass tile. Note that the comment misuses the term "block" here, as it actually refers to a tile.
In Polished Map, by pressing the puzzle piece icon, or using the shortcut CTRL+T, you check what the tile $2c corresponds to in Kanto's tileset.
Now we will load the tree animation.
In the same file, edit ShakeHeadbuttTree:
ShakeHeadbuttTree:
farcall ClearSpriteAnims
- ld de, CutGrassGFX
- ld hl, vTiles0 tile FIELDMOVE_GRASS
- lb bc, BANK(CutGrassGFX), 4
- call Request2bpp
- ld de, HeadbuttTreeGFX
+ ld de, HeadbuttTreeKantoGFX ; tree frames
+
+ ld a, [wMapTileset]
+ cp TILESET_KANTO
+ jr z, .tree_frames_determined
+
+ ld de, HeadbuttTreeGFX ; tree frames
+.tree_frames_determined
ld hl, vTiles0 tile FIELDMOVE_TREE
The CutGrassGFX
is the little leaf image that is used for the Razor Leaf battle attack animation, or during the overworld Fly animation.
It is unused during the overworld Headbutt animation, so we removed it.
The rest of the code is very similar to the previous bit we wrote.
Now that the animation is working fine, let's add some Pokémon into those trees.
Each map can have its own treemon set.
A treemon set determines the list of the Pokémon that can be encountered with Headbutt.
You can create a new one by adding a TREEMON_SET_*
constant in constants/pokemon_data_constants.asm, and adding a list in data/wild/treemons.asm
If you add new Pokémons to lists, you can make them sleep at certain times of day by adding them into the proper arrays in data/wild/treemons_asleep.asm
For the purpose of the tutorial, we will use the existing TREEMON_SET_KANTO
.
The array that associates a treemon set to each route is located in data/wild/treemon_maps.asm. Edit this file.
treemon_map ILEX_FOREST, TREEMON_SET_FOREST
+ treemon_map CERULEAN_CITY, TREEMON_SET_KANTO
db -1
We have now reached our goal by adding some wild Pokémon into the trees of Cerulean City.
This concludes this tutorial.