Port evolution, Rare Candy, evolution stones and vitamins
Checks / web (push) Canceled after 0s

Pokémon that levelled up evolve after a won battle, following
EvolveAfterBattle's checks over the ROM's evolution bytes, with the
evolution screen that B can stop and move learning outside battle. The pack
uses Rare Candy, stones (with ABLE/NOT ABLE labels) and vitamins, and its
pocket tabs now sit in their own row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sébastien QUEROLandClaude Opus 5.5 committed 2026-09-30 16:21:59 +02:00
1 parent 1af2beacdc
commit 45275ba83b
19 files changed
+1032 -39

No files matched your search

+54 -1
View File
@@ -32,7 +32,8 @@ These paths refer to the pinned [PRET source](https://github.com/pret/pokecrysta
| Movement interpreter | `macros/scripts/movement.asm`, `engine/overworld/movement.asm`, `engine/overworld/map_objects.asm` | Turns, steps, slides, jumps (two tiles with the original arc), sleeps, facing locks, visibility and emotes. `follow` takes one tile toward the leader's previous square. All movement opcodes decode, including teleport, fishing, skyfall, shake and flicker poses; Controlled reference scenes check spin, teleport, skyfall, fishing and flicker direction, visibility and lift. |
| Specials | `data/events/special_pointers.asm`, `engine/rtc/timeset.asm`, `engine/overworld/decorations.asm` | Selected by routine address from the ROM table: `SetDayOfWeek`, initial DST flags, `RestartMapMusic` (no audio yet), room decoration toggles, `PokemonCenterPC` and `PlayersHousePC` (Bill's, the player's and Oak's PCs), the Town Map, `HealParty`, `HealMachineAnim` (presentation only), `CheckPokerus` and the `StubbedTrainerRankings_Healings` stub. |
| `game/scripts/pc.ts` | `engine/events/pokecenter_pc.asm`, `engine/pokemon/bills_pc_top.asm`, `engine/pokemon/bills_pc.asm`, `engine/events/prof_oaks_pc.asm`, `engine/events/std_collision.asm` | The Pokémon Center and house PCs: Bill's PC (deposit, withdraw, release, change and name boxes), item storage, the empty mail box and Oak's rating. Menu strings and texts come from the ROM; lists are native. Moving Pokémon, the stats screen and printing are not ported. |
| `game/scripts/start-menu.ts` | `engine/menus/start_menu.asm`, `engine/pokemon/mon_menu.asm`, `mon_submenu.asm`, `party_menu.asm`, `switchpartymons.asm`, `engine/items/pack.asm`, `engine/items/item_effects.asm` | The start menu, the party menu with the Pokémon submenu (STATS, SWITCH, MOVE, ITEM) and the pack (USE, GIVE, TOSS) with the field item effects listed below. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu, MAIL, SEL and the other field items give a notice. |
| `game/scripts/start-menu.ts` | `engine/menus/start_menu.asm`, `engine/pokemon/mon_menu.asm`, `mon_submenu.asm`, `party_menu.asm`, `switchpartymons.asm`, `engine/items/pack.asm`, `engine/items/item_effects.asm` | The start menu, the party menu with the Pokémon submenu (STATS, SWITCH, MOVE, ITEM) and the pack (USE, GIVE, TOSS) with the field item effects listed below, including Rare Candy, stones and vitamins. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu, MAIL, SEL and the other field items give a notice. |
| `game/scripts/evolution.ts` | `engine/pokemon/evolve.asm`, `engine/pokemon/learn.asm`, `engine/movie/evolution_animation.asm`, `engine/pokemon/party_menu.asm` | `EvolveAfterBattle`/`EvolvePokemon` over the raw evolution bytes, the evolution texts and a timed, B-stoppable picture sequence, `UpdateSpeciesNameIfNotNicknamed`, `CalcMonStats` and the HP rise, `LearnLevelMoves`, `LearnMove`/`ForgetMove` outside battle and `PlacePartyMonEvoStoneCompatibility`. |
| `game/rom/pokemon.ts` | `data/pokemon/base_stats`, `evos_attacks.asm`, `data/moves/moves.asm`, `data/items/attributes.asm`, `engine/gfx/load_pics.asm` | Species, move and item names, base data, evolution lists, learnsets, move PP, item pockets, growth-rate exp and front pictures (`FixPicBank`, `PadFrontpic`). Starter pictures match rebuilt bytes; all 251 evolution lists match the pinned source. |
| `game/party` | `engine/pokemon/move_mon.asm`, `engine/pokemon/caught_data.asm`, `engine/items/items.asm` | `GeneratePartyMonStats` for script gifts: DVs, `FillMoves`, PP, exp, `CalcMonStatC`, happiness and caught data. `PutItemInPocket`, key items and `TossItem`. `SendMonIntoBox`, `SendGetMonIntoFromBox` (deposit and withdraw), `RestorePPOfDepositedPokemon` and `CalcLevel` for the PC's boxes and item storage. TMs and HMs are refused. |
| Text interpreter | `macros/scripts/text.asm`, `constants/charmap.asm`, `home/text.asm` | Literal/far text, RAM names and string buffers from native state, numbers of dots, and sound or pause cues (consumed). `text_asm` and other RAM reads are refused. |
@@ -332,3 +333,55 @@ tossing, the Bicycle outdoors and indoors, unported effects and saving
while the menu is open. A Chromium/WebKit test opens the menu with Start,
switches Pokémon, changes pockets and tosses a Potion. These are not
emulator comparisons.
## Evolution
The battle's experience routine sets a party member's bit in
`wEvolvableFlags` when it levels up. `ExitBattle` runs `EvolveAfterBattle`
only when `wBattleResult & $0f` is a win; the world then presents it before
the script receives the battle result, on the same draft, so the evolution
commits with the battle. `CleanUpBattleRAM`'s cursor reset follows.
`EvolveAfterBattle` reads `EvosAttacksPointers` and walks each Pokémon's
entries with the original's pointer steps (`.dont_evolve_1/2/3`): trades are
skipped without Link, a forced evolution (a stone) skips every non-item
entry by two bytes, items need `wCurItem` and `wForceEvolution`, levels and
happiness (`HAPPINESS_TO_EVOLVE`, `TR_*` against `wTimeOfDay`) and Tyrogue's
`EVOLVE_STAT` check the copied Pokémon, and an Everstone blocks all but
items. The first match evolves; a stopped evolution goes on to the next
Pokémon. `UpdateSpeciesNameIfNotNicknamed` compares the nickname with the
old species' name (`wBaseDexNo`, which the animation restores).
`CalcMonStats` uses the stat experience; HP rises by the maximum HP's
increase. `LearnLevelMoves` then offers moves at exactly the current level,
and `SetSeenAndCaughtMon` records the species.
`EvolutionAnimation` is presented as a picture schedule in overworld ticks:
40 ticks on the old picture, then seven rounds of a B-checking wait (7 … 1
ticks) and that many flashes (two ticks each way). The waits and flashes
are approximations of the original frame timing; B is accepted only during
the waits and never when `wForceEvolution` is set. No music, cry, palette
or `AnimateFrontpic` is presented.
`LearnMove` outside battle: the first empty slot, otherwise `ForgetMove`
(yes/no, then a move list; `IsHMMove` refuses HM moves), `Text_1_2_and_Poof`
with its `text_asm` continuation, or "Stop learning" (NO asks again) and
"did not learn".
PACK items: `RareCandyEffect` (`CalcExpAtLevel` for the new level, the HP
rise that also revives a fainted Pokémon, `LevelUpHappinessMod` against the
caught landmark, `PARTYMENUTEXT_LEVEL_UP`, a `PrintTempMonStats` page,
`LearnLevelMoves` and an unforced `EvolvePokemon`), `EvoStoneEffect`
(`PARTYMENUACTION_EVO_STONE`'s ABLE/NOT ABLE labels copy ten bytes and step
three at a time, as the original does; bytes past the copy read as the end
here, where the original reads stale RAM) and `VitaminEffect`
(`StatExpItemPointerOffsets`, the high byte limit of 100, `StatStrings`,
`ItemStatRoseText` and `HAPPINESS_USEDITEM`).
Tests: `tests/start-menu.test.ts` covers the Rare Candy level-up, stat page,
HM refusal, forgetting and declining a move, the revived fainted Pokémon,
evolution with and without B, a stone (ABLE labels, no effect on another
species or with an Everstone, B ignored, a kept nickname) and a vitamin up
to its limit. `tests/battle-world.test.ts` wins a wild battle whose level-up
evolves Cyndaquil, and checks that a non-participant that could evolve does
not. A Chromium/WebKit test evolves through a Rare Candy. No emulator
comparison of these routines yet.