Print text when you lose a trainer battle - pret/pokecrystal GitHub Wiki

Enemy trainers all have set text that gets printed when you win a battle with them. They also have space to set text for when you lose, but that only works for battles you can lose, and the only such battle is the first one with your rival in Cherrygrove City:

Screenshot

It turns out that all the other rival battles have unused loss text (documented on The Cutting Room Floor); and the battle with Red is also set to use the same "…" text whether you win or lose. Other trainers don't bother to set loss text, and just use 0 as a placeholder. For example, in maps/Route30.asm:

TrainerYoungsterJoey:
	trainer YOUNGSTER, JOEY1, EVENT_BEAT_YOUNGSTER_JOEY, YoungsterJoey1SeenText, YoungsterJoey1BeatenText, 0, .Script

And in maps/VioletGym.asm:

VioletGymFalknerScript:
	...
	winlosstext FalknerWinLossText, 0
	loadtrainer FALKNER, FALKNER1
	startbattle
	reloadmapafterbattle

Anyway, it's quite simple to enable this feature. Edit engine/battle/core.asm:

 LostBattle:
 	ld a, 1
 	ld [wBattleEnded], a
 
 	ld a, [wInBattleTowerBattle]
 	bit 0, a
 	jr nz, .battle_tower
 
-	ld a, [wBattleType]
-	cp BATTLETYPE_CANLOSE
-	jr nz, .not_canlose
+	ld a, [wBattleMode]
+	dec a ; wild?
+	jr z, .no_loss_text
+
+	ld hl, wLossTextPointer
+	ld a, [hli]
+	ld h, [hl]
+	or h
+	jr z, .no_loss_text
 
 ; Remove the enemy from the screen.
 	hlcoord 0, 0
 	lb bc, 8, 21
 	call ClearBox
 	call BattleWinSlideInEnemyTrainerFrontpic
 
 	ld c, 40
 	call DelayFrames
 
 	ld a, [wDebugFlags]
 	bit DEBUG_BATTLE_F, a
 	jr nz, .skip_win_loss_text
 	call PrintWinLossText
 .skip_win_loss_text
 	ret
 
 .battle_tower
 ; Remove the enemy from the screen.
 	hlcoord 0, 0
 	lb bc, 8, 21
 	call ClearBox
 	call BattleWinSlideInEnemyTrainerFrontpic
 
 	ld c, 40
 	call DelayFrames
 
 	call EmptyBattleTextbox
 	ld c, BATTLETOWERTEXT_WIN_TEXT
 	farcall BattleTowerText
 	call WaitPressAorB_BlinkCursor
 	call ClearTilemap
 	call ClearBGPalettes
 	ret
 
-.not_canlose
+.no_loss_text
 	ld a, [wLinkMode]
 	and a
 	jr nz, .LostLinkBattle

Now if you lose a trainer battle and [wLossTextPointer] is nonzero, the text will be printed, regardless of what the battle type is.

There's one more thing to do. Edit maps/Route24.asm:

 Route24RocketScript:
 	faceplayer
 	playmusic MUSIC_ROCKET_ENCOUNTER
 	opentext
 	writetext Route24RocketSeenText
 	waitbutton
 	closetext
-	winlosstext Route24RocketBeatenText, -1
+	winlosstext Route24RocketBeatenText, 0
 	loadtrainer GRUNTM, GRUNTM_31
 	startbattle
 	dontrestartmapmusic
 	reloadmapafterbattle
 	...

If you lost against this Rocket Grunt, it would try printing text at [-1], which might glitch or crash the game. We just had to set it to the usual 0 for no loss text.

Now we're done!

Screenshot

You can optionally edit home/trainers.asm:

 PrintWinLossText::
-	ld a, [wBattleType]
-	cp BATTLETYPE_CANLOSE
-	jr .canlose ; ??????????
-
-; unused
-	ld hl, wWinTextPointer
-	jr .ok
-
-.canlose
 	ld a, [wBattleResult]
 	ld hl, wWinTextPointer
 	and $f ; WIN?
 	jr z, .ok
 	ld hl, wLossTextPointer
 
 .ok
 	ld a, [hli]
 	ld h, [hl]
 	ld l, a
 	call GetMapScriptsBank
 	call FarPrintText
 	call WaitBGMap
 	call WaitPressAorB_BlinkCursor
 	ret

That removes some vestigial code which looks like Game Freak planned to check for BATTLETYPE_CANLOSE here instead of in LostBattle. (This would have worked if jr .canlose had been jr z, .canlose.) Removing this code doesn't affect gameplay, but it does save ROM space, which is especially useful in the home bank.