summaryrefslogtreecommitdiff
path: root/Add-a-new-Unown-puzzle-chamber.md
blob: 642de693927393e0eb980c6f50537c1cdc282f10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
This tutorial is for how to add a new Unown puzzle chamber, including a new sliding panel puzzle, a word on the back wall, and a trigger condition for the back wall to open. As an example, we'll add a chamber for Relicanth.


## Contents

1. [Create a new puzzle](#1-create-a-new-puzzle)
2. [Create a new word wall](#2-create-a-new-word-wall)
3. [Create a condition to open the wall](#3-create-a-condition-to-open-the-wall)


## 1. Create a new puzzle

Create **gfx/unown_puzzle/relicanth.png**:

![gfx/unown_puzzle/relicanth.png](screenshots/gfx-unown_puzzle-relicanth.png)

(This image was drawn by [Neslug](https://www.deviantart.com/neslug/art/GSC-Hoenn-Puzzle-Panels-192327829).)

Then edit [constants/script_constants.asm](../blob/master/constants/script_constants.asm):

```diff
 ; UnownPuzzle setval arguments
 ; LoadUnownPuzzlePiecesGFX.LZPointers indexes (see engine/games/unown_puzzle.asm)
 	const_def
 	const UNOWNPUZZLE_KABUTO     ; 0
 	const UNOWNPUZZLE_OMANYTE    ; 1
 	const UNOWNPUZZLE_AERODACTYL ; 2
 	const UNOWNPUZZLE_HO_OH      ; 3
+	const UNOWNPUZZLE_RELICANTH
 NUM_UNOWN_PUZZLES EQU const_value
```

And edit [engine/games/unown_puzzle.asm](../blob/master/engine/games/unown_puzzle.asm):

```diff
 LoadUnownPuzzlePiecesGFX:
 	...

 .LZPointers:
 ; entries correspond to UNOWNPUZZLE_* constants
 	dw KabutoPuzzleLZ
 	dw OmanytePuzzleLZ
 	dw AerodactylPuzzleLZ
 	dw HoOhPuzzleLZ
+	dw RelicanthPuzzleLZ

 UnownPuzzleCursorGFX:
 INCBIN "gfx/unown_puzzle/cursor.2bpp"

 UnownPuzzleStartCancelLZ:
 INCBIN "gfx/unown_puzzle/start_cancel.2bpp.lz"

 HoOhPuzzleLZ:
 INCBIN "gfx/unown_puzzle/hooh.2bpp.lz"

 AerodactylPuzzleLZ:
 INCBIN "gfx/unown_puzzle/aerodactyl.2bpp.lz"

 KabutoPuzzleLZ:
 INCBIN "gfx/unown_puzzle/kabuto.2bpp.lz"

 OmanytePuzzleLZ:
 INCBIN "gfx/unown_puzzle/omanyte.2bpp.lz"
+
+RelicanthPuzzleLZ:
+INCBIN "gfx/unown_puzzle/relicanth.2bpp.lz"
```

Now you can create a map with a script like this:

```
RuinsOfAlphRelicanthChamberPuzzle:
	refreshscreen
	setval UNOWNPUZZLE_RELICANTH
	special UnownPuzzle
	closetext
	iftrue .PuzzleComplete
	end

.PuzzleComplete
	...
```

And it will work the way you expect.

![Screenshot](screenshots/relicanth-puzzle.png)


## 2. Create a new word wall

Edit [constants/script_constants.asm](../blob/master/constants/script_constants.asm) again:

```diff
 ; DisplayUnownWords setval arguments
 ; UnownWalls and MenuHeaders_UnownWalls indexes (see data/events/unown_walls.asm)
 	const_def
 	const UNOWNWORDS_ESCAPE ; 0
 	const UNOWNWORDS_LIGHT  ; 1
 	const UNOWNWORDS_WATER  ; 2
 	const UNOWNWORDS_HO_OH  ; 3
+	const UNOWNWORDS_WHIRL
```

Then edit [data/events/unown_walls.asm](../blob/master/data/events/unown_walls.asm):

```diff
 UnownWalls:
 ; UNOWNWORDS_ESCAPE
 	; db      $08, $44, $04, $00, $2e, $08, -1
 	unownwall "E", "S", "C", "A", "P", "E"
 ; UNOWNWORDS_LIGHT
 	; db      $26, $20, $0c, $0e, $46, -1
 	unownwall "L", "I", "G", "H", "T"
 ; UNOWNWORDS_WATER
 	; db      $4c, $00, $46, $08, $42, -1
 	unownwall "W", "A", "T", "E", "R"
 ; UNOWNWORDS_HO_OH
 	; db      $0e, $2c, $64, $2c, $0e, -1
 	unownwall "H", "O", "-", "O", "H"
+; UNOWNWORDS_WHIRL
+	unownwall "W", "H", "I", "R", "L"
 
 MenuHeaders_UnownWalls:
 ; UNOWNWORDS_ESCAPE
 	db MENU_BACKUP_TILES ; flags
 	menu_coords 3, 4, 16, 9
 ; UNOWNWORDS_LIGHT
 	db MENU_BACKUP_TILES ; flags
 	menu_coords 4, 4, 15, 9
 ; UNOWNWORDS_WATER
 	db MENU_BACKUP_TILES ; flags
 	menu_coords 4, 4, 15, 9
 ; UNOWNWORDS_HO_OH
 	db MENU_BACKUP_TILES ; flags
 	menu_coords 4, 4, 15, 9
+; UNOWNWORDS_WHIRL
+	db MENU_BACKUP_TILES ; flags
+	menu_coords 4, 4, 15, 9
```

The `unownwall` macro turns capital letters and hyphens into their corresponding Unown letters. The `menu_coords` macro is used here to define the textbox surrounding the word when it appears; note that the word "ESCAPE" has a wider box to fit its six letters.

Now you can create a map with a script like this:

```
RuinsOfAlphRelicanthChamberWallPatternLeft:
	opentext
	writetext RuinsOfAlphRelicanthChamberWallPatternLeftText
	setval UNOWNWORDS_WHIRL
	special DisplayUnownWords
	closetext
	end
```

And it will work the way you expect.

![Screenshot](screenshots/relicanth-word.png)


## 3. Create a condition to open the wall

The wall-opening routines are defined in [engine/events/unown_walls.asm](../blob/master/engine/events/unown_walls.asm). Each wall has a routine that sets the corresponding `WALL_OPENED` event if certain conditions are met:

- `HoOhChamber`: Called when you enter the chamber. Checks if Ho-Oh is the first Pokémon in the party.
- `OmanyteChamber`: Called when you enter the chamber. Checks if a Water Stone is in the Pack or held by a Pokémon in the party.
- `SpecialAerodactylChamber`: Called when you use Flash. Checks if you are in the Aerodactyl chamber.
- `SpecialKabutoChamber`: Called when you use an Escape Rope. Checks if you are in the Kabuto chamber.

`HoOhChamber` and `OmanyteChamber` are called by `scene_script`s in their respective chamber scripts in [maps/\*.asm](../tree/master/maps/); `SpecialAerodactylChamber` `SpecialKabutoChamber` are called by the `OWFlash` and `EscapeRopeFunction` routines in [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm), respectively.

The word "WHIRL" implies that you should use Whirlpool. So, edit [engine/events/unown_walls.asm](../blob/master/engine/events/unown_walls.asm) to define a new `SpecialRelicanthChamber` routine that checks if you are in the Relicanth chamber map, and sets `EVENT_WALL_OPENED_IN_RELICANTH_CHAMBER` if so. Then edit [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm) so that `WhirlpoolFunction` calls `SpecialRelicanthChamber` the way that `EscapeRopeFunction` calls `SpecialKabutoChamber`. (You will, of course, also need to edit [constants/event_flags.asm](../blob/master/event_flags.asm) to define `EVENT_WALL_OPENED_IN_RELICANTH_CHAMBER`, not to mention creating the Relicanth chamber map in the first place.) I won't go into the details of how to do this, since you probably don't want exactly this condition, and the existing four routines are sufficient to show the general pattern.

Anyway, once that's done, you can use Whirlpool in the Relicanth chamber to open the wall.