summaryrefslogtreecommitdiff
path: root/Adding-items-that-act-like-HMs.md
blob: 4b8f3505b277d40dc6c2d02126386ee792d9e4d9 (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
174
175
176
177
178
179
180
181
182
This tutorial will cover how to add items that act like HM Field moves, using CUT as an example.

## Contents

1. [Adding the item](#1-adding-the-item)
2. [Fixing the success message](#2-fixing-the-success-message)
3. [Fixing Oak's message](#3-fixing-oaks-message)
4. [Including other HMs](#4-including-other-hms)

## 1. Adding the item

Follow the guide on [adding new items](#Add-a-new-item) to create the item that will act like an HM. I changed ITEM_19 into CHAINSAW with the following:

[constants/item_constants.asm](../blob/master/constants/item_constants.asm):
```Diff
	const WATER_STONE  ; 18
-	const ITEM_19      ; 19
+	const CHAINSAW     ; 19
	const HP_UP        ; 1a
```

[data/items/names.asm](../blob/master/data/items/names.asm):
```Diff
	db "WATER STONE@"
-	db "TERU-SAMA@"
+	db "CHAINSAW@"
	db "HP UP@"
```

[data/items/descriptions.asm](../blob/master/data/items/descriptions.asm):

```diff
 	dw WaterStoneDesc
-	dw TeruSama2Desc
+	dw ChainsawDesc
	dw HPUpDesc

 	...

-TeruSama2Desc:
-	db   "?@"
+ChainsawDesc:
+	db   "Cuts down pesky"
+	next "plants.@"
```

[data/items/attributes.asm](../blob/master/data/items/attributes.asm):
```Diff
-; ITEM_19
-	item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
+; CHAINSAW
+	item_attribute 0, HELD_NONE, 0, CANT_TOSS, KEY_ITEM, ITEMMENU_CLOSE, ITEMMENU_NOUSE
```

[data/items/catch_rate_items.asm](../blob/master/data/items/catch_rate_items.asm):
```Diff
TimeCapsule_CatchRateItems:
-	db ITEM_19, LEFTOVERS
```

***

In this example, Chainsaw will act like the HM Cut, so we'll use `CutFunction` in [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm). A list of HM Functions is at the end of this tutorial. Since these functions are in a different bank from the item effect functions, we just need to write a small function that can farcall our HM Function. [ engine/items/item_effects.asm](../blob/master/engine/items/item_effects.asm ):

```Diff
	dw EvoStoneEffect      ; WATER_STONE
-	dw NoEffect            ; ITEM_19
+	dw ChainsawEffect      ; CHAINSAW

	...

+ChainsawEffect:
+	farcall CutFunction
+	ret
```

## 2. Fixing the success message
The above works, but it has a few flaws. Firstly, a message will pop up saying a Pokémon used the relevant HM Effect. There are several ways to change this, but the easiest is to edit the text that's displayed when your HM's effect script is run. The HM Effect scripts will be listed at the end.

First, skip loading the Pokémon's name. At best this finds the first Pokémon that has cut, at worse it fails and the text is incorrect. [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm):

```Diff
Script_Cut:
-	callasm GetPartyNick
	writetext Text_UsedCut
```

Then, we can change the text to be a bit more neutral. `Text_UsedCut` points to `UnknownText_0x1c05dd` in [data/text/common_2.asm](../blob/master/data/text/common_2.asm):

```Diff
UnknownText_0x1c05dd::
-	text_ram wStringBuffer2
-	text " used"
-	line "CUT!"
+	text "You cut some"
+	line "plants!"
	prompt
```

## 3. Fixing Oak's message

As it stands, if you use your item and it fails, you'll be told the HM's error message AND be yelled at by Oak. To avoid this, we can introduce a new temporary var that can be used to skip Oak's message for HM-like-items.

First off, we need to create a new label in wram. There's a nice chunk of free space in wram bank 0 right after `wDaysSince`. [wram.asm](../blob/master/wram.asm):


```Diff
wDaysSince:: db

+wUsingHMItem:: db

SECTION "WRAM 1", WRAMX
```

Next, we'll change our item effect so that it sets `wUsingHMItem` to 1, signifying that it's okay to skip Oak's Message. [engine/items/item_effects.asm](../blob/master/engine/items/item_effects.asm)

```Diff
ChainsawEffect:
+	ld a, 1
+	ld [wUsingHMItem], a
	farcall CutFunction
	ret
```

Finally, we'll skip Oak's message if `wUsingHMItem` is set. Oak's message is handled in [engine/items/pack.asm](../blob/master/engine/items/pack.asm):

```Diff
	ld a, [wItemEffectSucceeded]
	and a
-	jr z, .Oak
+
+	; grab and reset wUsingHMItem without changing flag
+	ld hl, wUsingHMItem
+	ld a, [hl]
+	ld [hl], 0
+
+	jr z, .tryOak
	ld a, PACKSTATE_QUITRUNSCRIPT
	ld [wJumptableIndex], a
	ret

+.tryOak
+	or a
+	jr z, .Oak
+	ret

TossMenu:
	ld hl, Text_ThrowAwayHowMany
```

The above loads `wUsingHMItem`'s value and resets it to 0 so Oak's message won't be skipped for normal items. If Oak's message would normally plays, it will do one quick check of `wUsingHMItem`'s old value, and go right to returning if it wasn't zero.

## 4. Including other HMs

Including the other HM effects is as simple as repeating the above with different effect functions and new items. Our code to handle Oak's message based on `wUsingHMItem` doesn't need to be changed to allow other HMs, however every HM must include code to it to 1 (or any other nonzero value).

The following are lists of HM Functions as of time of writing. These may not all work as well as Cut, and may change naming conventions over time.

### HM Function List

All of these are in [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm).
* `CutFunction`
* `FlyFunction`
* `SurfFunction`
* `StrengthFunction`
* `OWFlash`
* `WhirlpoolFunction`
* `WaterfallFunction`

Additionally, functions like `TeleportFunction` can be used as well.

### HM Effect Scripts

All of these are in [engine/events/overworld.asm](../blob/master/engine/events/overworld.asm).

* `Script_Cut`
* Fly does not show a message
* `UsedSurfScript`
* `Script_UsedStrength`
* Flash does not show the Pokémon's name
* `Script_UsedWhirlpool`
* `Script_UsedWaterfall`