Skip to content

Adjust Weakness and Resistance Modifiers

Sha0den edited this page Jan 18, 2025 · 4 revisions

This tutorial will demonstrate how to make all Weakness values "+20" instead of "x2" and all Resistance values "-20" instead of "-30". Neither Weakness nor Resistance has been constant throughout the course of the Pokémon Trading Card Game, and for a significant portion of the game, Resistance was reduced from "-30" to "-20". If you are designing a game based around a different era of the TCG, or if you simply wish to have the game be less subject to completely one-sided matches, you may wish to adjust the modifiers for Weakness and/or Resistance. Fortunately, this isn't a difficult change to make.

Contents

  1. Editing the Main Damage Calculation Functions
  2. Updating the AI Logic

1. Editing the Main Damage Calculation Functions

Weakness and Resistance is actually applied during one of two functions, both of which can be found in src/home/duel.asm. (Except in poketcg_v2, where ApplyDamageModifiers_DamageToTarget was moved to src/engine/duel/core.asm.) Weakness is calculated in the original game by shifting all of the bits in the damage value to the left. Since each bit is one power of 2 higher than the previous one, this is an easy way to double the damage value. For example, converting 30 to binary gives you %00011110, converting 60 gives you %00111100, and converting 120 gives you %01111000. Resistance is a little easier to understand, as it simply adds "-30" to the amount of damage being done; in algebra, this is equivalent to subtracting 30. In all of the functions that we will be updating, we'll change the -30 in the Resistance sections to -20, and the Weakness instructions will be replaced with a copy of the original Resistance instructions (substituting -30 with 20).

Let's start off by applying the aforementioned changes to ApplyDamageModifiers_DamageToTarget.

ApplyDamageModifiers_DamageToTarget::
 	...
 	and b
 	jr z, .not_weak
-	sla e
-	rl d
+	ld hl, 20
+	add hl, de
+	ld e, l
+	ld d, h
 	ld hl, wDamageEffectiveness
 	set WEAKNESS, [hl]
 .not_weak
 	call SwapTurn
 	call GetArenaCardResistance
 	call SwapTurn
 	and b
 	jr z, .check_pluspower_and_defender ; jump if not resistant
-	ld hl, -30
+	ld hl, -20
 	add hl, de
 	ld e, l
 	ld d, h
 	...

Then, scroll down, and apply those changes to ApplyDamageModifiers_DamageToSelf.

 ApplyDamageModifiers_DamageToSelf::
 	...
 	and b
 	jr z, .not_weak
-	sla e
-	rl d
+	ld hl, 20
+	add hl, de
+	ld e, l
+	ld d, h
 	ld hl, wDamageEffectiveness
 	set WEAKNESS, [hl]
 .not_weak
 	call GetArenaCardResistance
 	and b
 	jr z, .not_resistant
-	ld hl, -30
+	ld hl, -20
 	add hl, de
 	ld e, l
 	ld d, h
 	...


2. Updating the AI Logic

The game will run with just the first step completed, but the AI still assumes that Weakness is x2 and Resistance is -30. We should fix that if we want the computer opponents to make sensible decisions.

Begin by opening src/engine/duel/ai/damage_calculation.asm, and apply the changes from Step 1 to CalculateDamage_VersusDefendingPokemon.

 CalculateDamage_VersusDefendingPokemon:
 	...
 	jr z, .not_weak
 	; double de
-	sla e
-	rl d
+	ld hl, 20
+	add hl, de
+	ld e, l
+	ld d, h

 .not_weak
 ; handle resistance
 	call SwapTurn
 	call GetArenaCardResistance
 	call SwapTurn
 	and b
 	jr z, .not_resistant
-	ld hl, -30
+	ld hl, -20
 	add hl, de
 	ld e, l
 	ld d, h
 	...

Then, scroll down to CalculateDamage_FromDefendingPokemon and repeat.

 CalculateDamage_FromDefendingPokemon:
 	...
 	jr z, .not_weak
 	; double de
-	sla e
-	rl d
+	ld hl, 20
+	add hl, de
+	ld e, l
+	ld d, h

 .not_weak
 ; handle resistance
 	...
 	and b
 	jr z, .not_resistant
-	ld hl, -30
+	ld hl, -20
 	add hl, de
 	ld e, l
 	ld d, h
 	...

While there isn't a dedicated AI function for estimating recoil damage being done to the Attacking Pokémon, there is still a small calculation that is made during AIDecide_Defender2 (AIDecide_Defender_Phase14 in poketcg_v2), so open src/engine/duel/ai/trainer_cards.asm and scroll down to the relevant function. The actual code is a little different because it's handling all of the math with 8-bit registers (rather than 16-bit register pairs), but it works more or less the same way as the previous functions.

 AIDecide_Defender2:
 	...
 	and b
 	pop de
 	jr z, .check_resist
-	sla d
+	ld a, d
+	add 20
+	ld d, a

 ; subtract 30 from recoil damage if card resists its own color.
 ; if this yields a negative number, return no carry.
 .check_resist
 	push de
 	call GetArenaCardColor
 	call TranslateColorToWR
 	ld b, a
 	call GetArenaCardResistance
 	and b
 	pop de
 	jr z, .subtract
 	ld a, d
-	sub 30
+	sub 20
 	jr c, .no_carry
 	ld d, a
 	...

That completes all of the changes that will need to be made to the game's engine, but you might also want to search the game's text files (found in src/text) for "Weakness" and/or "Resistance" and update any references to the old modifiers.