mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
Document fix for game freezing while switching mon (#869)
Fixes #868 Co-authored-by: Rangi <35663410+Rangi42@users.noreply.github.com>
This commit is contained in:
parent
0ffdb65210
commit
597701f168
@ -35,9 +35,10 @@ Fixes in the [multi-player battle engine](#multi-player-battle-engine) category
|
|||||||
- [Beat Up may trigger King's Rock even if it failed](#beat-up-may-trigger-kings-rock-even-if-it-failed)
|
- [Beat Up may trigger King's Rock even if it failed](#beat-up-may-trigger-kings-rock-even-if-it-failed)
|
||||||
- [Present damage is incorrect in link battles](#present-damage-is-incorrect-in-link-battles)
|
- [Present damage is incorrect in link battles](#present-damage-is-incorrect-in-link-battles)
|
||||||
- [Dragon Scale, not Dragon Fang, boosts Dragon-type moves](#dragon-scale-not-dragon-fang-boosts-dragon-type-moves)
|
- [Dragon Scale, not Dragon Fang, boosts Dragon-type moves](#dragon-scale-not-dragon-fang-boosts-dragon-type-moves)
|
||||||
|
- [Switching out or switching against a Pokémon with max HP below 4 freezes the game](#switching-out-or-switching-against-a-pokémon-with-max-HP-below-4-freezes-the-game)
|
||||||
|
- [Moves that do damage and increase your stats do not increase stats after a KO](#moves-that-do-damage-and-increase-your-stats-do-not-increase-stats-after-a-ko)
|
||||||
- [HP bar animation is slow for high HP](#hp-bar-animation-is-slow-for-high-hp)
|
- [HP bar animation is slow for high HP](#hp-bar-animation-is-slow-for-high-hp)
|
||||||
- [HP bar animation off-by-one error for low HP](#hp-bar-animation-off-by-one-error-for-low-hp)
|
- [HP bar animation off-by-one error for low HP](#hp-bar-animation-off-by-one-error-for-low-hp)
|
||||||
- [Moves that do damage and increase your stats do not increase stats after a KO](#moves-that-do-damage-and-increase-your-stats-do-not-increase-stats-after-a-ko)
|
|
||||||
- [Single-player battle engine](#single-player-battle-engine)
|
- [Single-player battle engine](#single-player-battle-engine)
|
||||||
- [A Transformed Pokémon can use Sketch and learn otherwise unobtainable moves](#a-transformed-pokémon-can-use-sketch-and-learn-otherwise-unobtainable-moves)
|
- [A Transformed Pokémon can use Sketch and learn otherwise unobtainable moves](#a-transformed-pokémon-can-use-sketch-and-learn-otherwise-unobtainable-moves)
|
||||||
- [Catching a Transformed Pokémon always catches a Ditto](#catching-a-transformed-pokémon-always-catches-a-ditto)
|
- [Catching a Transformed Pokémon always catches a Ditto](#catching-a-transformed-pokémon-always-catches-a-ditto)
|
||||||
@ -714,6 +715,143 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Switching out or switching against a Pokémon with max HP below 4 freezes the game
|
||||||
|
|
||||||
|
This happens because switching involves calculating a percentage of maximum enemy HP. Directly calculating *HP* × 100 / *max HP* would require a two-byte denominator, so instead the game calculates *HP* × 25 / (*max HP* / 4), since even a maximum HP of 999 divided by 4 is 249, which fits in one byte. However, if the maximum HP is below 4 this will divide by 0, which enters an infinite loop in `_Divide`.
|
||||||
|
|
||||||
|
**Fix:** First, edit `SendOutMonText` in [engine/battle/core.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm):
|
||||||
|
|
||||||
|
```diff
|
||||||
|
; compute enemy health remaining as a percentage
|
||||||
|
xor a
|
||||||
|
ldh [hMultiplicand + 0], a
|
||||||
|
ld hl, wEnemyMonHP
|
||||||
|
ld a, [hli]
|
||||||
|
ld [wEnemyHPAtTimeOfPlayerSwitch], a
|
||||||
|
ldh [hMultiplicand + 1], a
|
||||||
|
ld a, [hl]
|
||||||
|
ld [wEnemyHPAtTimeOfPlayerSwitch + 1], a
|
||||||
|
ldh [hMultiplicand + 2], a
|
||||||
|
- ld a, 25
|
||||||
|
- ldh [hMultiplier], a
|
||||||
|
- call Multiply
|
||||||
|
ld hl, wEnemyMonMaxHP
|
||||||
|
ld a, [hli]
|
||||||
|
ld b, [hl]
|
||||||
|
- srl a
|
||||||
|
- rr b
|
||||||
|
- srl a
|
||||||
|
- rr b
|
||||||
|
+ ld c, 100
|
||||||
|
+ and a
|
||||||
|
+ jr z, .shift_done
|
||||||
|
+.shift
|
||||||
|
+ rra
|
||||||
|
+ rr b
|
||||||
|
+ srl c
|
||||||
|
+ and a
|
||||||
|
+ jr nz, .shift
|
||||||
|
+.shift_done
|
||||||
|
+ ld a, c
|
||||||
|
+ ldh [hMultiplier], a
|
||||||
|
+ call Multiply
|
||||||
|
ld a, b
|
||||||
|
ld b, 4
|
||||||
|
ldh [hDivisor], a
|
||||||
|
call Divide
|
||||||
|
```
|
||||||
|
|
||||||
|
Then edit `WithdrawMonText` in the same file:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
; compute enemy health lost as a percentage
|
||||||
|
ld hl, wEnemyMonHP + 1
|
||||||
|
ld de, wEnemyHPAtTimeOfPlayerSwitch + 1
|
||||||
|
ld b, [hl]
|
||||||
|
dec hl
|
||||||
|
ld a, [de]
|
||||||
|
sub b
|
||||||
|
ldh [hMultiplicand + 2], a
|
||||||
|
dec de
|
||||||
|
ld b, [hl]
|
||||||
|
ld a, [de]
|
||||||
|
sbc b
|
||||||
|
ldh [hMultiplicand + 1], a
|
||||||
|
- ld a, 25
|
||||||
|
- ldh [hMultiplier], a
|
||||||
|
- call Multiply
|
||||||
|
ld hl, wEnemyMonMaxHP
|
||||||
|
ld a, [hli]
|
||||||
|
ld b, [hl]
|
||||||
|
- srl a
|
||||||
|
- rr b
|
||||||
|
- srl a
|
||||||
|
- rr b
|
||||||
|
+ ld c, 100
|
||||||
|
+ and a
|
||||||
|
+ jr z, .shift_done
|
||||||
|
+.shift
|
||||||
|
+ rra
|
||||||
|
+ rr b
|
||||||
|
+ srl c
|
||||||
|
+ and a
|
||||||
|
+ jr nz, .shift
|
||||||
|
+.shift_done
|
||||||
|
+ ld a, c
|
||||||
|
+ ldh [hMultiplier], a
|
||||||
|
+ call Multiply
|
||||||
|
ld a, b
|
||||||
|
ld b, 4
|
||||||
|
ldh [hDivisor], a
|
||||||
|
call Divide
|
||||||
|
```
|
||||||
|
|
||||||
|
This changes both calculations to *HP* × (100 / *N*) / (*max HP* / *N*) for the smallest necessary *N*, which will be at least 1, so it avoids dividing by zero and is also more accurate.
|
||||||
|
|
||||||
|
|
||||||
|
### Moves that do damage and increase your stats do not increase stats after a KO
|
||||||
|
|
||||||
|
`BattleCommand_CheckFaint` "ends the move effect if the opponent faints", and these moves attempt to raise the user's stats *after* `checkfaint`. Note that fixing this can lead to stats being increased at the end of battle, but will not have any negative effects.
|
||||||
|
|
||||||
|
**Fix:** Edit [data/moves/effects.asm](https://github.com/pret/pokecrystal/blob/master/data/moves/effects.asm):
|
||||||
|
|
||||||
|
```diff
|
||||||
|
DefenseUpHit:
|
||||||
|
...
|
||||||
|
criticaltext
|
||||||
|
supereffectivetext
|
||||||
|
+ defenseup
|
||||||
|
+ statupmessage
|
||||||
|
checkfaint
|
||||||
|
buildopponentrage
|
||||||
|
- defenseup
|
||||||
|
- statupmessage
|
||||||
|
endmove
|
||||||
|
|
||||||
|
AttackUpHit:
|
||||||
|
...
|
||||||
|
criticaltext
|
||||||
|
supereffectivetext
|
||||||
|
+ attackup
|
||||||
|
+ statupmessage
|
||||||
|
checkfaint
|
||||||
|
buildopponentrage
|
||||||
|
- attackup
|
||||||
|
- statupmessage
|
||||||
|
endmove
|
||||||
|
|
||||||
|
AllUpHit:
|
||||||
|
...
|
||||||
|
criticaltext
|
||||||
|
supereffectivetext
|
||||||
|
+ allstatsup
|
||||||
|
checkfaint
|
||||||
|
buildopponentrage
|
||||||
|
- allstatsup
|
||||||
|
endmove
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### HP bar animation is slow for high HP
|
### HP bar animation is slow for high HP
|
||||||
|
|
||||||
*Fixing this cosmetic bug will* not *break link battle compatibility.*
|
*Fixing this cosmetic bug will* not *break link battle compatibility.*
|
||||||
@ -770,48 +908,6 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
|
|||||||
jr .loop
|
jr .loop
|
||||||
```
|
```
|
||||||
|
|
||||||
### Moves that do damage and increase your stats do not increase stats after a KO
|
|
||||||
|
|
||||||
`BattleCommand_CheckFaint` "ends the move effect if the opponent faints", and these moves attempt to raise the user's stats *after* `checkfaint`. Note that fixing this can lead to stats being increased at the end of battle, but will not have any negative effects.
|
|
||||||
|
|
||||||
**Fix:** Edit [data/moves/effects.asm](https://github.com/pret/pokecrystal/blob/master/data/moves/effects.asm):
|
|
||||||
|
|
||||||
```diff
|
|
||||||
DefenseUpHit:
|
|
||||||
...
|
|
||||||
criticaltext
|
|
||||||
supereffectivetext
|
|
||||||
+ defenseup
|
|
||||||
+ statupmessage
|
|
||||||
checkfaint
|
|
||||||
buildopponentrage
|
|
||||||
- defenseup
|
|
||||||
- statupmessage
|
|
||||||
endmove
|
|
||||||
|
|
||||||
AttackUpHit:
|
|
||||||
...
|
|
||||||
criticaltext
|
|
||||||
supereffectivetext
|
|
||||||
+ attackup
|
|
||||||
+ statupmessage
|
|
||||||
checkfaint
|
|
||||||
buildopponentrage
|
|
||||||
- attackup
|
|
||||||
- statupmessage
|
|
||||||
endmove
|
|
||||||
|
|
||||||
AllUpHit:
|
|
||||||
...
|
|
||||||
criticaltext
|
|
||||||
supereffectivetext
|
|
||||||
+ allstatsup
|
|
||||||
checkfaint
|
|
||||||
buildopponentrage
|
|
||||||
- allstatsup
|
|
||||||
endmove
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Single-player battle engine
|
## Single-player battle engine
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user