Skip to content

Make the field move Headbutt work with Kanto trees

Damien Doury edited this page Jun 19, 2023 · 3 revisions

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.

Contents

  1. Make Headbutt trigger on Kanto trees
  2. Design a custom shake animation
  3. Populate the trees with Pokémon species

1. Make Headbutt trigger on Kanto trees

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.

palettes

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).

blockset

This will open a pop-up window in which you can edit the collisions on the right panel.

collisions_before

Change the collisions associated to the trees from WALL to HEADBUTT_TREE

collisions_after

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.

2. Design a custom shake animation

For a custom animation to work we first need to:

  1. design it,
  2. include it into the project,
  3. 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:

headbutt_tree_kanto

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:

  1. the 4 background tiles of the selected tree are replaced by 4 identical grass tiles.
  2. 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.

grass_tile

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.

3. Populate the trees with Pokémon species

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.

result

This concludes this tutorial.

Clone this wiki locally