Skip to content

Make new battle text to distinguish status move misses and fails

Idain edited this page Sep 14, 2021 · 9 revisions

In Generation 2, it is hard to know if a status move missed or didn't affect the opponent (either due to being statused already or status immunity) due to the ambiguity of the move failure text. With this tutorial, we can fix this.

Contents

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

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

First, edit data/text/battle.asm:

...

AttackMissed2Text:
	text "<USER>'s"
	line "attack missed!"
	prompt

+AvoidStatusText:
+	text "<TARGET>"
+	line "avoided the"
+	cont "attack!"
+	prompt

...

You must not add this separate text for missing status moves. Just remember to use either AttackMissedText or AttackMissed2Text when AvoidStatusText is used in this tutorial. They are identical anyway.

Next, edit engine/battle/effect_commands.asm:

...

BattleCommand_Poison:
; poison

...

.do_poison
-	ld hl, DidntAffect1Text	
+	ld hl, AvoidStatusText

...

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

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

First, edit data/text/battle.asm again:

...

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

NOTE: The frozen and burn status are added to prompt the player that the enemy already has a status so they won't try inflicting another one again.

Next, edit engine/battle/effect_commands.asm:

...

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
+	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
+	call CheckForStatusIfAlreadyHasAny
+	jr nz, .fail

-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVarAddr
-	ld d, h
-	ld e, l
-	ld a, [de]
-	and SLP
-	ld hl, AlreadyAsleepText
-	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

...

.do_poison
-	ld hl, DidntAffect1Text
-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVar
-	and a
-	jr nz, .failed
-

...

BattleCommand_Paralyze:
; paralyze

-	ld a, BATTLE_VARS_STATUS_OPP
-	call GetBattleVar
-	bit PAR, a
-	jr nz, .paralyzed
+	call CheckForStatusIfAlreadyHasAny
+	jr nz, .hasstatus

...

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

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

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