Show move names for TMs and HMs when receiving or buying - pret/pokecrystal GitHub Wiki

In Gen 2, acquiring a TM or HM would just say "PLAYER received TM##." when you're given one, or "PLAYER found TM##!" when you take an item ball or hidden item. Gen 3 made these messages more helpful by showing the name of the move that the TM/HM teaches. This tutorial will implement that little quality of life feature.

Contents

  1. Define a routine to append move names after TM/HM item names
  2. Use the new routine in all cases where you acquire an item
  3. Update the hard-coded TM13 and TM24 messages
  4. Define a new routine to show move names when buying TMs

1. Define a routine to append move names after TM/HM item names

Edit engine/overworld/scripting.asm:

+AppendTMHMMoveName::
+; a = item ID
+	ld a, [wNamedObjectIndex]
+	cp TM01
+	ret c
+; save item name buffer
+	push de
+; a = TM/HM number
+	ld c, a
+	farcall GetTMHMNumber
+	ld a, c
+; a = move ID
+	ld [wTempTMHM], a
+	predef GetTMHMMove
+	ld a, [wTempTMHM]
+; wStringBuffer1 = move name
+	ld [wNamedObjectIndex], a
+	call GetMoveName
+; hl = item name buffer
+	pop hl
+; append wStringBuffer1 to item name buffer
+	ld [hl], " "
+	inc hl
+	ld de, wStringBuffer1
+	jp CopyName2

This routine assumes that you've loaded the item ID in [wNamedObjectIndex], and the end of the item name buffer in de. Then it converts the item ID to the corresponding TM/HM number, then converts that to the corresponding move ID, gets the name of the move, and appends that to the item name buffer (which is why we started with the end of the buffer).

(The move name is written to wStringBuffer1, so you can't also use that for the TM/HM name. You'd end up with issues like TM01 being called "DYNADYNAMICPUNCH".)

2. Use the new routine in all cases where you acquire an item

Edit engine/overworld/scripting.asm again:

 Script_verbosegiveitem:
 ; script command 0x9e
 ; parameters: item, quantity

 	call Script_giveitem
 	call CurItemName
 	ld de, wStringBuffer1
 	ld a, STRING_BUFFER_4
 	call CopyConvertedText
+	ld de, wStringBuffer4 + STRLEN("TM##")
+	call AppendTMHMMoveName
 	ld b, BANK(GiveItemScript)
 	ld de, GiveItemScript
 	jp ScriptCall
 Script_verbosegiveitemvar:
 ; script command 0x9f
 ; parameters: item, var

 	call GetScriptByte
 	cp ITEM_FROM_MEM
 	jr nz, .ok
 	ld a, [wScriptVar]
 .ok
 	ld [wCurItem], a
 	call GetScriptByte
 	call GetVarAction
 	ld a, [de]
 	ld [wItemQuantityChange], a
 	ld hl, wNumItems
 	call ReceiveItem
 	ld a, TRUE
 	jr c, .ok2
 	xor a
 .ok2
 	ld [wScriptVar], a
 	call CurItemName
 	ld de, wStringBuffer1
 	ld a, STRING_BUFFER_4
 	call CopyConvertedText
+	ld de, wStringBuffer4 + STRLEN("TM##")
+	call AppendTMHMMoveName
 	ld b, BANK(GiveItemScript)
 	ld de, GiveItemScript
 	jp ScriptCall

Edit engine/events/misc_scripts.asm:

 FindItemInBallScript::
 	callasm .TryReceiveItem
 	...

 .TryReceiveItem:
 	xor a
 	ld [wScriptVar], a
 	ld a, [wItemBallItemID]
 	ld [wNamedObjectIndex], a
 	call GetItemName
 	ld hl, wStringBuffer3
 	call CopyName2
+	ld de, wStringBuffer3 + STRLEN("TM##")
+	farcall AppendTMHMMoveName
 	ld a, [wItemBallItemID]
 	ld [wCurItem], a
 	ld a, [wItemBallQuantity]
 	ld [wItemQuantityChange], a
 	ld hl, wNumItems
 	call ReceiveItem
 	ret nc
 	ld a, $1
 	ld [wScriptVar], a
 	ret

Edit engine/events/hidden_item.asm:

 HiddenItemScript::
 	opentext
 	readmem wHiddenItemID
 	getitemname STRING_BUFFER_3, USE_SCRIPT_VAR
+	callasm .append_tmhm_move_name
 	writetext .found_text
 	giveitem ITEM_FROM_MEM
 	iffalse .bag_full
 	callasm SetMemEvent
 	specialsound
 	itemnotify
 	sjump .finish

 .bag_full
 	buttonsound
 	writetext .no_room_text
 	waitbutton

 .finish
 	closetext
 	end
+
+.append_tmhm_move_name
+	ld de, wStringBuffer3 + STRLEN("TM##")
+	farcall AppendTMHMMoveName
+	ret

3. Update the hard-coded TM13 and TM24 messages

Edit maps/Route39Farmhouse.asm:

Text_ReceivedTM13:
	text "<PLAYER> received"
-	line "TM13."
+	line "TM13 SNORE."
	done

Edit maps/BlackthornGym1F.asm:

 BlackthornGymText_ReceivedTM24:
 	text "<PLAYER> received"
-	line "TM24."
+	line "TM24 DRAGONBREATH."
 	done

And edit maps/DragonsDenB1F.asm:

 Text_ReceivedTM24:
 	text "<PLAYER> received"
-	line "TM24."
+	line "TM24 DRAGONBREATH."
 	done

Now we'll see the move name along with the TM/HM number when it's first acquired.

Screenshot

4. Define a new routine to show move names when buying TMs

Edit engine/menus/menu_2.asm:

	call PlaceString
	ret

+PlaceMartMenuItemName:
+	push de
+	ld a, [wMenuSelection]
+	ld [wNamedObjectIndex], a
+	call GetItemName
+	cp TM01
+	jr c, .place_string
+	ld hl, wStringBuffer1
+	ld de, wStringBuffer4
+	ld bc, STRING_BUFFER_LENGTH
+	call CopyBytes
+	ld de, wStringBuffer4 + STRLEN("TM##")
+	callfar AppendTMHMMoveName
+	ld de, wStringBuffer4
+.place_string:
+	pop hl
+	call PlaceString
+	ret
+
PlaceMenuItemQuantity:
	push de
	ld a, [wMenuSelection]

This routine applies the same exact logic as PlaceMenuItemName for non-TM/HM items. For TMs/HMs, however, it calls the previously defined AppendTMHMMoveName method to fetch the move name and add it to the TM## name the mart usually shows. Now that we have this method, we need to reference it when defining Mart menus.

Edit engine/items/mart.asm:

	db 4, 8 ; rows, columns
	db SCROLLINGMENU_ITEMS_NORMAL ; item format
	dbw 0, wCurMartCount
-	dba PlaceMenuItemName
+	dba PlaceMartMenuItemName
	dba .PrintBCDPrices
	dba UpdateItemDescription

In case you're wondering why we didn't just edit the existing PlaceMenuItemName function, it's because that function is used in the PC to draw item names, and the PC doesn't have enough room to write out move names in the same manner we've done here.

Now your Marts should show the names of moves!

image

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