Skip to content

Make new battle text to distinguish status move misses and fails

Idain edited this page Aug 17, 2022 · 9 revisions

In Generation 2, it is hard to know whether a status move missed or didn't affect the opponent due to the ambiguity of the move failure text. With this tutorial, we can fix this.

Contents

  1. Use a separate prompt for move misses because of attack fail or Protect
  2. (Optional) Add text if the target for status conditions has a status already

1. Use a separate prompt for move misses because of attack fail or Protect

In data/text/battle.asm there's a text for when the opponent evades a move, but it's only used by Leech Seed in case it fails:

 EvadedText:
	text "<TARGET>"
	line "evaded the attack!"
	prompt

We can use it for our purpose. Let's edit engine/battle/effect_commands.asm:

 ...
 
 BattleCommand_Poison:
 ; poison
 
 ...
 .dont_sample_failure
+	ld hl, ProtectingItselfText
 	call CheckSubstituteOpp
 	jr nz, .failed
+
+	ld hl, EvadedText
 	ld a, [wAttackMissed]
 	and a
 	jr nz, .failed
 ...

 PrintDidntAffect2:
	call AnimateFailedMove
-	ld hl, DidntAffect1Text ; 'it didn't affect'
-	ld de, DidntAffect2Text ; 'it didn't affect'
+	ld hl, EvadedText ; 'evaded the attack'
+	ld de, ProtectingItselfText ; 'protecting itself'
	jp FailText_CheckOpponentProtect

You might have noticed we're also using ProtectingItselfText. This is for moves being blocked by either Protect or Detect.

2. (Optional) Add text if the target for status conditions has a status already

In generation 2 there are no moves that only apply the Burn or Freeze status, but in case your project has new moves which fulfill this function, this step is for you.

Let's edit data/text/battle.asm again and add text in case the Pokémon is already burned or frozen:

...

 AlreadyAsleepText:
 	text "<TARGET>'s"
 	line "already asleep!"
 	prompt
 
+AlreadyBurnedText:
+	text "<TARGET>'s"
+	line "already burned!"
+	prompt
+
+AlreadyFrozenText:
+	text "<TARGET>'s"
+	line "already frozen!"
+	prompt

Next, edit engine/battle/effect_commands.asm to use our new created status texts:

 ...
 
 UpdateMoveData:
 	ld a, BATTLE_VARS_MOVE_ANIM
 	call GetBattleVarAddr
 	ld d, h
 	ld e, l
 
 	ld a, BATTLE_VARS_MOVE
 	call GetBattleVar
 	ld [wCurSpecies], a
 	ld [wNamedObjectIndex], a
 
	dec a
	call GetMoveData
	call GetMoveName
	jp CopyName1

+CheckForStatusIfAlreadyHasAny:
+	ld a, BATTLE_VARS_STATUS_OPP
+	call GetBattleVarAddr
+	ld d, h
+	ld e, l
+	and SLP_MASK
+	ld hl, AlreadyAsleepText
+	ret nz
+	
+	ld a, [de]
+	bit FRZ, a
+	ld hl, AlreadyFrozenText
+	ret nz
+	
+	bit PAR, a
+	ld hl, AlreadyParalyzedText
+	ret nz
+	
+	bit PSN, a
+	ld hl, AlreadyPoisonedText
+	ret nz
+	
+	bit BRN, a
+	ld hl, AlreadyBurnedText
+	ret


 BattleCommand_SleepTarget:

 ...

 .not_protected_by_item
-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVarAddr
-	ld d, h
-	ld e, l
-	ld a, [de]
-	and SLP_MASK
-	ld hl, AlreadyAsleepText
+	call CheckForStatusIfAlreadyHasAny
	jr nz, .fail

	ld a, [wAttackMissed]
	and a
	jp nz, PrintDidntAffect2

	ld hl, DidntAffect1Text
	call .CheckAIRandomFail
	jr c, .fail

-	ld a, [de]
-	and a
-	jr nz, .fail
 BattleCommand_Poison:

 	...

 	call CheckIfTargetIsPoisonType
 	jp z, .failed
 
-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVar
-	ld b, a
-	ld hl, AlreadyPoisonedText
-	and 1 << PSN
+	call CheckForStatusIfAlreadyHasAny
	jp nz, .failed
 BattleCommand_Paralyze:
 ; paralyze
 
-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVar
-	bit PAR, a
+	call CheckForStatusIfAlreadyHasAny
 	jr nz, .paralyzed

 	...

 .dont_sample_failure
-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVarAddr
-	and a
-	jr nz, .failed

  	...

 .paralyzed
+	push hl
	call AnimateFailedMove
-	ld hl, AlreadyParalyzedText
+	pop hl
	jp StdBattleTextbox

CheckForStatusIfAlreadyHasAny is a new function made to check whether the Pokémon has some status already applied and print the appropriate "Already [STATUS] text". Then we replaced every instance where it used to do an individual status check with our function.

That's it! Now we can know if the status move either missed or doesn't affect the opponent (either due to being statused already or status immunity)!

Status move fail display

Clone this wiki locally