Remove the gym badges boosts - pret/pokecrystal GitHub Wiki
In Pokémon generations I to III, after obtaining gym badges, the player is given an invisible and unfair advantage against in-game trainers and wild Pokémon battles. Removing those boosts is an easy way to make the game more difficult without overhauling all trainer teams. This tutorial explains how to remove the gym badge boosts from the game.
Contents
1. Remove mentions about badge boosts
You should edit or remove mentions about badges boost at your convenience. There are 5 gym leaders talking about the badges boost:
- Falkner (maps/VioletGym.asm, in
FalknerZephyrBadgeText:
), - Whitney (maps/GoldenrodGym.asm, in
WhitneyPlainBadgeText:
), - Jasmine (maps/OlivineGym.asm, in
Jasmine_BadgeSpeech:
), - Pryce (maps/MahoganyGym.asm, in
PryceText_GlacierBadgeSpeech:
). - Lt.Surge (maps/VermilionGym.asm, in
LtSurgeThunderBadgeText:
).
We will remove Whitney's dialog about badge boost as an example.
Edit maps/GoldenrodGym.asm:
WhitneyPlainBadgeText:
text "PLAINBADGE lets"
line "your #MON use"
para "STRENGTH outside"
line "of battle."
- para "It also boosts"
- line "your #MON's"
- cont "SPEED."
para "Oh, you can have"
line "this too!"
done
Then there are other mentions like:
- Supernerd Tom (maps/Route8.asm, in
SupernerdTomAfterBattleText:
).
If you are working with pokegold, there is also one trainer talking about badge boosts on Route 14. This text had been changed in Pokémon Crystal, so no need to worry about it.
- Pokéfan Trevor (maps/Route14.asm, in
PokefanmTrevorAfterBattleText:
).
Credits to @SatoMew for finding the in-game mention of Pokéfan Trevor.
2. Remove the stat boost effect
The badge boosts in gen II are divided into two groups, and we will remove them both:
- stat boost
- type boost
Let's start with the stat boost by removing the calls to BadgeStatBoosts.
Edit engine/battle/effect_commands.asm:
CalcPlayerStats:
ld hl, wPlayerAtkLevel
ld de, wPlayerStats
ld bc, wBattleMonAttack
ld a, NUM_BATTLE_STATS
call CalcBattleStats
- ld hl, BadgeStatBoosts
- call CallBattleCore
call BattleCommand_SwitchTurn
Edit engine/battle/core.asm:
InitBattleMon:
ld a, MON_SPECIES
call GetPartyParamLocation
...
ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK
call CopyBytes
call ApplyStatusEffectOnPlayerStats
- call BadgeStatBoosts
ret
...
GiveExperiencePoints:
...
.transformed
xor a ; FALSE
ld [wApplyStatLevelMultipliersToEnemy], a
call ApplyStatLevelMultiplierOnAllStats
callfar ApplyStatusEffectOnPlayerStats
- callfar BadgeStatBoosts
callfar UpdatePlayerHUD
In the same file, remove the entire BadgeStatBoosts and BadgeBoost functions (the latter is only called within the former).
INCLUDE "data/battle/stat_multipliers_2.asm"
-BadgeStatBoosts:
-; Raise the stats of the battle mon in wBattleMon
-; depending on which badges have been obtained.
-
-; Every other badge boosts a stat, starting from the first.
-; GlacierBadge also boosts Special Defense, although the relevant code is buggy (see below).
-
-; ZephyrBadge: Attack
-; PlainBadge: Speed
-; MineralBadge: Defense
-; GlacierBadge: Special Attack and Special Defense
-
-; The boosted stats are in order, except PlainBadge and MineralBadge's boosts are swapped.
-
- ld a, [wLinkMode]
- and a
- ret nz
-
- ld a, [wInBattleTowerBattle]
- and a
- ret nz
-
- ld a, [wJohtoBadges]
-
-; Swap badges 3 (PlainBadge) and 5 (MineralBadge).
- ld d, a
- and (1 << PLAINBADGE)
- add a
- add a
- ld b, a
- ld a, d
- and (1 << MINERALBADGE)
- rrca
- rrca
- ld c, a
- ld a, d
- and ((1 << ZEPHYRBADGE) | (1 << HIVEBADGE) | (1 << FOGBADGE) | (1 << STORMBADGE) | (1 << GLACIERBADGE) | (1 << RISINGBADGE))
- or b
- or c
- ld b, a
-
- ld hl, wBattleMonAttack
- ld c, 4
-.CheckBadge:
-; BUG: Glacier Badge may not boost Special Defense depending on the value of Special Attack (see docs/bugs_and_glitches.md)
- ld a, b
- srl b
- call c, BoostStat
- inc hl
- inc hl
-; Check every other badge.
- srl b
- dec c
- jr nz, .CheckBadge
- srl a
- call c, BoostStat
- ret
-
-BoostStat:
-; Raise stat at hl by 1/8.
-
- ld a, [hli]
- ld d, a
- ld e, [hl]
- srl d
- rr e
- srl d
- rr e
- srl d
- rr e
- ld a, [hl]
- add e
- ld [hld], a
- ld a, [hl]
- adc d
- ld [hli], a
-
-; Cap at 999.
- ld a, [hld]
- sub LOW(MAX_STAT_VALUE)
- ld a, [hl]
- sbc HIGH(MAX_STAT_VALUE)
- ret c
- ld a, HIGH(MAX_STAT_VALUE)
- ld [hli], a
- ld a, LOW(MAX_STAT_VALUE)
- ld [hld], a
- ret
_LoadBattleFontsHPBar:
3. Remove the type boost effect
Remove the only call to DoBadgeTypeBoosts
in engine/battle/effect_commands.asm:
BattleCommand_Stab:
; STAB = Same Type Attack Bonus
ld a, BATTLE_VARS_MOVE_ANIM
...
push hl
push de
push bc
farcall DoWeatherModifiers
pop bc
pop de
pop hl
- push de
- push bc
- farcall DoBadgeTypeBoosts
- pop bc
- pop de
Then remove the function DoBadgeTypeBoosts
in engine/battle/misc.asm:
INCLUDE "data/battle/weather_modifiers.asm"
-DoBadgeTypeBoosts:
- ld a, [wLinkMode]
- and a
- ret nz
-
- ld a, [wInBattleTowerBattle]
- and a
- ret nz
-
- ldh a, [hBattleTurn]
- and a
- ret nz
-
- push de
- push bc
-
- ld hl, BadgeTypeBoosts
-
- ld a, [wKantoBadges]
- ld b, a
- ld a, [wJohtoBadges]
- ld c, a
-
-.CheckBadge:
- ld a, [hl]
- cp -1
- jr z, .done
-
- srl b
- rr c
- jr nc, .NextBadge
-
- ld a, [wCurType]
- cp [hl]
- jr z, .ApplyBoost
-
-.NextBadge:
- inc hl
- jr .CheckBadge
-
-.ApplyBoost:
- ld a, [wCurDamage]
- ld h, a
- ld d, a
- ld a, [wCurDamage + 1]
- ld l, a
- ld e, a
-
- srl d
- rr e
- srl d
- rr e
- srl d
- rr e
-
- ld a, e
- or d
- jr nz, .done_min
- ld e, 1
-
-.done_min
- add hl, de
- jr nc, .Update
-
- ld hl, $ffff
-
-.Update:
- ld a, h
- ld [wCurDamage], a
- ld a, l
- ld [wCurDamage + 1], a
-
-.done
- pop bc
- pop de
- ret
-
-INCLUDE "data/types/badge_type_boosts.asm"
You can also remove the file data/types/badge_type_boosts.asm, as it is now unreferenced.
The strength of your Pokémon is now on par with the ones controlled by the AI! Well, almost. The AI controlled Pokémon still can miss Status moves, have low DVs on average, no stat experience, no held items (apart from 3 trainer Pokémon), etc.
If you want to make the single-player adventure more fair/balanced/difficult, here are some tutorials you may want to look into: