mirror of https://github.com/pret/pokecrystal.git
Document more bugs and glitches
Add a toc.py script to auto-generate tables of contents in Markdown files
This commit is contained in:
parent
76ea57688e
commit
feef75c5df
|
@ -14,6 +14,7 @@
|
|||
- ["Smart" AI encourages Mean Look if its own Pokémon is badly poisoned](#smart-ai-encourages-mean-look-if-its-own-pokémon-is-badly-poisoned)
|
||||
- [A Disabled, PP Up–enhanced move may not trigger automatic Struggling](#a-disabled-pp-upenhanced-move-may-not-trigger-automatic-struggling)
|
||||
- [Counter and Mirror Coat still work if the opponent uses an item](#counter-and-mirror-coat-still-work-if-the-opponent-uses-an-item)
|
||||
- [A Pokémon that fainted from Pursuit will have its old status condition when revived](#a-pokémon-that-fainted-from-pursuit-will-have-its-old-status-condition-when-revived)
|
||||
- [Present damage is incorrect in link battles](#present-damage-is-incorrect-in-link-battles)
|
||||
- [BRN/PSN/PAR do not affect catch rate](#brnpsnpar-do-not-affect-catch-rate)
|
||||
- [Moon Ball does not boost catch rate](#moon-ball-does-not-boost-catch-rate)
|
||||
|
@ -25,10 +26,15 @@
|
|||
- [Magikarp in Lake of Rage are shorter, not longer](#magikarp-in-lake-of-rage-are-shorter-not-longer)
|
||||
- [Battle transitions fail to account for the enemy's level](#battle-transitions-fail-to-account-for-the-enemys-level)
|
||||
- [No bump noise if standing on tile `$3E`](#no-bump-noise-if-standing-on-tile-3e)
|
||||
- [`LoadMetatiles` wrap around past 128 blocks](#loadmetatiles-wrap-around-past-128-blocks)
|
||||
- [Playing Entei's Pokédex cry can distort Raikou's and Suicune's](#playing-enteis-pokédex-cry-can-distort-raikous-and-suicunes)
|
||||
- [Lock-On and Mind Reader don't always bypass Fly and Dig](#lock-on-and-mind-reader-dont-always-bypass-fly-and-dig)
|
||||
- [`LoadMetatiles` wraps around past 128 blocks](#loadmetatiles-wraps-around-past-128-blocks)
|
||||
- [Surfing directly across a map connection does not load the new map](#surfing-directly-across-a-map-connection-does-not-load-the-new-map)
|
||||
- [`CheckOwnMon` only checks the first five letters of OT names](#checkownmon-only-checks-the-first-five-letters-of-ot-names)
|
||||
- [Catching a Transformed Pokémon always catches a Ditto](#catching-a-transformed-pokémon-always-catches-a-ditto)
|
||||
- [Using a Park Ball in normal battles has a corrupt animation](#using-a-park-ball-in-normal-battles-has-a-corrupt-animation)
|
||||
- [`HELD_CATCH_CHANCE` has no effect](#held_catch_chance-has-no-effect)
|
||||
- [Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly](#only-the-first-three-evosattacks-evolution-entries-can-have-stone-compatibility-reported-correctly)
|
||||
- [`ScriptCall` can overflow `wScriptStack` and crash](#scriptcall-can-overflow-wscriptstack-and-crash)
|
||||
- [`LoadSpriteGFX` does not limit the capacity of `UsedSprites`](#loadspritegfx-does-not-limit-the-capacity-of-usedsprites)
|
||||
- [`ChooseWildEncounter` doesn't really validate the wild Pokémon species](#choosewildencounter-doesnt-really-validate-the-wild-pokémon-species)
|
||||
|
@ -371,6 +377,13 @@ This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.
|
|||
*To do:* Identify specific code causing this bug and fix it.
|
||||
|
||||
|
||||
## A Pokémon that fainted from Pursuit will have its old status condition when revived
|
||||
|
||||
([Video](https://www.youtube.com/watch?v=tiRvw-Nb2ME))
|
||||
|
||||
*To do:* Identify specific code causing this bug and fix it.
|
||||
|
||||
|
||||
## Present damage is incorrect in link battles
|
||||
|
||||
([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw))
|
||||
|
@ -720,7 +733,43 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](
|
|||
```
|
||||
|
||||
|
||||
## `LoadMetatiles` wrap around past 128 blocks
|
||||
## Playing Entei's Pokédex cry can distort Raikou's and Suicune's
|
||||
|
||||
([Video](https://www.youtube.com/watch?v=z305e4sIO24))
|
||||
|
||||
The exact cause is unknown, but a workaround exists for `DexEntryScreen_MenuActionJumptable.Cry` in [engine/pokedex.asm](engine/pokedex.asm):
|
||||
|
||||
```asm
|
||||
.Cry: ; 40340
|
||||
call Pokedex_GetSelectedMon
|
||||
ld a, [wd265]
|
||||
call GetCryIndex
|
||||
ld e, c
|
||||
ld d, b
|
||||
call PlayCryHeader
|
||||
ret
|
||||
```
|
||||
|
||||
**Workaround:**
|
||||
|
||||
```asm
|
||||
.Cry: ; 40340
|
||||
ld a, [CurPartySpecies]
|
||||
call PlayCry
|
||||
ret
|
||||
```
|
||||
|
||||
|
||||
## Lock-On and Mind Reader don't always bypass Fly and Dig
|
||||
|
||||
This bug affects Attract, Curse, Foresight, Mean Look, Mimic, Nightmare, Spider Web, Transform, and stat-lowering effects of moves like String Shot or Bubble during the semi-invulnerable turn of Fly or Dig.
|
||||
|
||||
*To do:* Identify specific code causing this bug and fix it.
|
||||
|
||||
|
||||
## `LoadMetatiles` wraps around past 128 blocks
|
||||
|
||||
This bug prevents you from using blocksets with more than 128 blocks.
|
||||
|
||||
[home/map.asm](home/map.asm):
|
||||
|
||||
|
@ -793,6 +842,40 @@ endr
|
|||
**Fix:** Change `rept NAME_LENGTH_JAPANESE +- 2` to `rept PLAYER_NAME_LENGTH +- 2`.
|
||||
|
||||
|
||||
## Catching a Transformed Pokémon always catches a Ditto
|
||||
|
||||
This bug can affect Mew or Pokémon other than Ditto that used Transform via Mirror Move or Sketch.
|
||||
|
||||
*To do:* Identify specific code causing this bug and fix it.
|
||||
|
||||
|
||||
## Using a Park Ball in normal battles has a corrupt animation
|
||||
|
||||
([Video](https://www.youtube.com/watch?v=v1ErZdLCIyU))
|
||||
|
||||
This is a bug with `ParkBall` in [items/item_effects.asm](items/item_effects.asm):
|
||||
|
||||
```asm
|
||||
.room_in_party
|
||||
xor a
|
||||
ld [wWildMon], a
|
||||
ld a, [CurItem]
|
||||
cp PARK_BALL
|
||||
call nz, ReturnToBattle_UseBall
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
|
||||
```asm
|
||||
.room_in_party
|
||||
xor a
|
||||
ld [wWildMon], a
|
||||
ld a, [BattleType]
|
||||
cp BATTLETYPE_CONTEST
|
||||
call nz, ReturnToBattle_UseBall
|
||||
```
|
||||
|
||||
|
||||
## `HELD_CATCH_CHANCE` has no effect
|
||||
|
||||
This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
|
||||
|
@ -817,6 +900,29 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm
|
|||
**Fix:** Uncomment `ld b, a`.
|
||||
|
||||
|
||||
## Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly
|
||||
|
||||
This is a bug with `PlacePartyMonEvoStoneCompatibility.DetermineCompatibility` in [engine/party_menu.asm](engine/party_menu.asm):
|
||||
|
||||
```asm
|
||||
.DetermineCompatibility: ; 50268
|
||||
ld de, StringBuffer1
|
||||
ld a, BANK(EvosAttacksPointers)
|
||||
ld bc, 2
|
||||
call FarCopyBytes
|
||||
ld hl, StringBuffer1
|
||||
ld a, [hli]
|
||||
ld h, [hl]
|
||||
ld l, a
|
||||
ld de, StringBuffer1
|
||||
ld a, BANK(EvosAttacks)
|
||||
ld bc, $a
|
||||
call FarCopyBytes
|
||||
```
|
||||
|
||||
**Fix:** Change `ld bc, $a` to `ld bc, $10` to support up to five Stone entries.
|
||||
|
||||
|
||||
## `ScriptCall` can overflow `wScriptStack` and crash
|
||||
|
||||
[engine/scripting.asm](engine/scripting.asm):
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Usage: python3 toc.py [-n] files.md...
|
||||
Replace a "## TOC" heading in a Markdown file with a table of contents,
|
||||
generated from the other headings in the file. Supports multiple files.
|
||||
Use "-n" for numbered list items.
|
||||
Headings must start with "##" signs to be detected.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from collections import namedtuple
|
||||
|
||||
toc_name = 'Contents'
|
||||
valid_toc_headings = {'## TOC', '##TOC'}
|
||||
|
||||
TocItem = namedtuple('TocItem', ['name', 'anchor', 'level'])
|
||||
punctuation_regexp = re.compile(r'[^\w\- ]+')
|
||||
|
||||
def name_to_anchor(name):
|
||||
# GitHub's algorithm for generating anchors from headings
|
||||
# https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/toc_filter.rb
|
||||
anchor = name.strip().lower() # lowercase
|
||||
anchor = re.sub(punctuation_regexp, '', anchor) # remove punctuation
|
||||
anchor = anchor.replace(' ', '-') # replace spaces with dash
|
||||
return anchor
|
||||
|
||||
def get_toc_index(lines):
|
||||
toc_index = None
|
||||
for i, line in enumerate(lines):
|
||||
if line.rstrip() in valid_toc_headings:
|
||||
toc_index = i
|
||||
break
|
||||
return toc_index
|
||||
|
||||
def get_toc_items(lines, toc_index):
|
||||
for i, line in enumerate(lines):
|
||||
if i <= toc_index:
|
||||
continue
|
||||
if line.startswith('##'):
|
||||
name = line.lstrip('#')
|
||||
level = len(line) - len(name) - len('##')
|
||||
name = name.strip()
|
||||
anchor = name_to_anchor(name)
|
||||
yield TocItem(name, anchor, level)
|
||||
|
||||
def toc_string(toc_items, numeric):
|
||||
lines = ['## %s' % toc_name, '']
|
||||
for name, anchor, level in toc_items:
|
||||
padding = ' ' * level
|
||||
line = '%s- [%s](#%s)' % (padding, name, anchor)
|
||||
lines.append(line)
|
||||
return '\n'.join(lines) + '\n'
|
||||
|
||||
def add_toc(filename, numeric):
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
toc_index = get_toc_index(lines)
|
||||
if toc_index is None:
|
||||
return None # no TOC heading
|
||||
toc_items = list(get_toc_items(lines, toc_index))
|
||||
if not toc_items:
|
||||
return False # no content headings
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
for i, line in enumerate(lines):
|
||||
if i == toc_index:
|
||||
f.write(toc_string(toc_items, numeric))
|
||||
else:
|
||||
f.write(line)
|
||||
return True # OK
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print('*** ERROR: Not enough arguments')
|
||||
print(__doc__)
|
||||
exit(1)
|
||||
del sys.argv[0]
|
||||
numeric = False
|
||||
if sys.argv[0] == '-n':
|
||||
numeric = True
|
||||
del sys.argv[0]
|
||||
if not sys.argv:
|
||||
print('*** ERROR: No filenames specified')
|
||||
exit(1)
|
||||
for filename in sys.argv:
|
||||
print(filename)
|
||||
result = add_toc(filename, numeric)
|
||||
if result is None:
|
||||
print('*** WARNING: No "## TOC" heading found')
|
||||
elif result is False:
|
||||
print('*** WARNING: No content headings found')
|
||||
else:
|
||||
print('OK')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue