POKéGEAR in the start menu runs the clock, Town Map and phone cards with the original joypad rules. Calls to Elm and Mom run their callee scripts, with the out-of-area and out-of-hours cases and HangUp's corrected timing. Mom saves a quarter of trainer prizes once asked, talking to her at home opens BankOfMom (GET, SAVE, CHANGE and the DST checks) with its digit amount box, and MomTriesToBuySomething buys items and dolls with her savings. Saves gain Mom's money, her next item and its trigger balance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3456aa4e11
commit
209778cabe
29 files changed
+2726
-47
No files matched your search
+93
-1
@@ -33,6 +33,7 @@ These paths refer to the pinned [PRET source](https://github.com/pret/pokecrysta
|
||||
| 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, MOVE PKMN W/O MAIL, stats), item storage, the empty mail box and Oak's rating. Menu strings and texts come from the ROM; lists are native. Printing is 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, including Rare Candy, stones and vitamins. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu (checked by the world), Softboiled and Milk Drink, SEL and the Select button (`SelectMenu`). MAIL and the other field items give a notice. |
|
||||
| `game/scripts/pokegear.ts` | `engine/pokegear/pokegear.asm`, `engine/phone/phone.asm`, `engine/phone/scripts/mom.asm`, `elm.asm`, `engine/rtc/print_hours_mins.asm` | `PokeGear` with each card's joypad handling: the clock (`Pokegear_UpdateClock`, `PrintHoursMins`), the map card's landmark cursor (`TownMap_InitCursorAndPlayerIconPositions`, `TownMap_GetKantoLandmarkLimits`), the phone list (`PokegearPhone_UpdateDisplayList`, `GetCallerClassAndName`, `PokegearPhoneContactSubmenu`, `CheckCanDeletePhoneNumber`) and calls (`MakePhoneCallFromPokegear`, `CheckPhoneContactTimeOfDay`, `GetMapPhoneService`, `HangUp`). Callee scripts run in the event interpreter on the start menu's draft. Screens are native; the radio's stations are not ported. |
|
||||
| `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. |
|
||||
@@ -88,7 +89,7 @@ Native production is `dist/`; the optional reference output is `dist-reference/`
|
||||
|
||||
## Save schema
|
||||
|
||||
Native saves are version 3. Version 2 added scene values by owning map, phone contacts, the weekday offset and DST flag, and positions of objects that scripts moved on the current map. Version 3 adds the player ID, party, bag, Pokédex seen/caught sets and money. Early version-3 backups without money receive the original starting balance; explicitly invalid balances are rejected. Restores recompute each Pokémon's stats from its DVs and reject any mismatch, and check every item against its ROM pocket. Older saves migrate with new-game defaults; a missing player ID is drawn as a new game draws it. Objects are restored from the save on continue, and only the TILES callback runs, as in `MapSetupScript_Continue`.
|
||||
Native saves are version 3. Version 2 added scene values by owning map, phone contacts, the weekday offset and DST flag, and positions of objects that scripts moved on the current map. Version 3 adds the player ID, party, bag, Pokédex seen/caught sets and money, and later Mom's savings (`momsMoney`, migrated by absence to 0). Early version-3 backups without money receive the original starting balance; explicitly invalid balances are rejected. Restores recompute each Pokémon's stats from its DVs and reject any mismatch, and check every item against its ROM pocket. Older saves migrate with new-game defaults; a missing player ID is drawn as a new game draws it. Objects are restored from the save on continue, and only the TILES callback runs, as in `MapSetupScript_Continue`.
|
||||
|
||||
## Scripted trainer battle foundation
|
||||
|
||||
@@ -437,3 +438,94 @@ left its slot; `tests/pc.test.ts` moves Pokémon party to box, box to party,
|
||||
within the party and within a full box, and refuses the last Pokémon and a
|
||||
full destination. Browser tests register the Bicycle and ride it with
|
||||
Select from the keyboard and the on-screen button.
|
||||
|
||||
### The Pokégear, phone calls and Mom's savings
|
||||
|
||||
`PokeGear` runs from the start menu as a generator (`Pokegear`) that yields
|
||||
each card as a `pokegear` effect and is answered with the button pressed, so
|
||||
the original's joypad rules (`PokegearClock_Joypad`,
|
||||
`PokegearMap_ContinueMap`, `PokegearPhone_Joypad`, `PokegearRadio_Joypad`
|
||||
and the contact submenu's loop) stay in the rules layer. The world routes A,
|
||||
B, the directions, Start and Select to it and refreshes the clock card from
|
||||
the game clock every tick, as `Pokegear_UpdateClock` runs every frame.
|
||||
Texts, menu strings, caller names and the AM/PM strings come from the ROM
|
||||
(`POKEGEAR` profile table, verified by `check:reference`). The map header's
|
||||
palette byte's high nybble is decoded as `GetMapPhoneService`.
|
||||
|
||||
A call runs the callee script from `PhoneContacts` (or
|
||||
`PhoneOutOfAreaScript`/`PhoneScript_JustTalkToThem`) in the event
|
||||
interpreter with the world's script host, on the start menu's draft; its
|
||||
state is adopted when it ends. The callee's last text waits for A or B, as
|
||||
`PokegearPhone_FinishPhoneCall` does, then `HangUp` shows "Click!" (20
|
||||
frames) and the boops (120 frames). The two "……" rings last 12 ticks each,
|
||||
an estimate from `Sfx_Call`'s notes; no sound is played.
|
||||
|
||||
Interpreter additions: `random` (`Script_random`'s rejection of draws past
|
||||
the largest multiple), `givemoney`, `takemoney` (unchanged when short, like
|
||||
`TakeMoney`), `checkmoney` (`HAVE_MORE`/`HAVE_AMOUNT`/`HAVE_LESS`) and
|
||||
`getmoney` on `YOUR_MONEY` or `MOMS_MONEY`, `getcurlandmarkname` and
|
||||
`getlandmarkname` (`GetLandmarkName`; `<BSP>` prints as a space). The money
|
||||
and landmark macros put the account or landmark before the string buffer.
|
||||
|
||||
`WinTrainerBattle.give_money` now splits the reward: the reward is added
|
||||
four times, to Mom for as many quarters as `wMomSavingMoney`'s mask says
|
||||
(SOME|HALF counts as four) unless `.CheckMaxedOutMomMoney` finds her
|
||||
account full, and to the wallet otherwise; the text is `SentSomeToMomText`,
|
||||
`SentHalfToMomText` or `SentAllToMomText`. Only `ENGINE_MOM_SAVING_MONEY`
|
||||
(the SOME bit) is reachable: nothing in the ROM sets the HALF and ALL bits.
|
||||
After a trainer battle, `Script_reloadmapafterbattle` calls
|
||||
`MomTriesToBuySomething` (see Mom's bank below).
|
||||
|
||||
Tests: `tests/pokegear.test.ts` (local ROM) covers the cards and their
|
||||
switching, the live clock, the map cursor's wrapping, phone scrolling over
|
||||
ten slots, the contact submenu, Elm's call, "Just go talk to that person!",
|
||||
Mom's lecture and balance call with commits after the menu closes, no
|
||||
service and the save migration. `tests/trainer-battle.test.ts` and
|
||||
`tests/trainer-world.test.ts` cover Mom's quarter, her full account and the
|
||||
purchase refusal. A browser test drives the cards and a call to Elm from the
|
||||
keyboard and the on-screen D-pad.
|
||||
|
||||
### Mom's bank and her purchases
|
||||
|
||||
`BankOfMom` (`scripts/mom.ts`) follows the ROM's jumptable: the yes/no
|
||||
questions and the GET/SAVE/CHANGE/CANCEL menu (strings from
|
||||
`BankOfMom_MenuHeader`) are ordinary effects, and the deposit/withdraw box is
|
||||
a `mombank` effect answered with the button pressed, like the Pokégear's
|
||||
cards, so `Mom_WithdrawDepositMenuJoypad`'s rules stay in the rules layer.
|
||||
`DigitQuantities` is read from the ROM. Texts, strings and the routine come
|
||||
from the `MOM` profile table, verified by `check:reference`. Refusal texts
|
||||
end in `prompt` and the routine returns to the same jumptable entry, which
|
||||
prints its question again and resets the amount; natively the refusal is a
|
||||
page before the next box. The last text is left for the script's
|
||||
`waitbutton`.
|
||||
|
||||
`DSTChecks` reads `hHours` from the game clock. `SetClockForward` and
|
||||
`SetClockBack` move `wStartHour` with a carry into `wStartDay`; the native
|
||||
clock keeps `minuteOffset` within ±720 minutes, so `shiftClockHour` wraps it
|
||||
and moves `weekdayOffset` the other way, which keeps the weekday and the
|
||||
daily reset day unchanged.
|
||||
|
||||
`MomTriesToBuySomething` runs at `Script_reloadmapafterbattle` after a
|
||||
trainer battle. `CheckBalance_MomItem2` compares her savings with the next
|
||||
MomItems_2 trigger; failing that, `.check_have_2300` adds ¥2300 to
|
||||
`wMomItemTriggerBalance` while it is below her savings, and only an exact
|
||||
match buys a `RandomRange(5)` MomItems_1 entry (and steps once more). The
|
||||
trigger balance keeps those increments even when nothing is bought, as in
|
||||
the original. `Mom_GiveItemOrDoll` puts an item in the PC (a full PC cancels
|
||||
the purchase after the steps) or sets the doll's decoration event. The ROM's
|
||||
`.Script` memscript runs `.ASMFunction` (the cost and `wWhichMomItem`) and
|
||||
then `Script_ReceivePhoneCall` with `Mom_GetScriptPointer`'s item or doll
|
||||
script. Natively `.ASMFunction`'s changes are made when the call is queued
|
||||
and the queued script is `Script_ReceivePhoneCall` itself with that caller
|
||||
script; the call starts at the next `PlayerEvents`, so nothing can observe
|
||||
the difference. `wMapReentryScriptQueueFlag`'s early return is the world's
|
||||
rule that keeps an already queued script.
|
||||
|
||||
Tests: `tests/mom.test.ts` (local ROM; the clock shift runs without it)
|
||||
covers the first visit, declining, deposits and withdrawals with each
|
||||
refusal, the digit cursor and step limits, B and zero-amount cancels,
|
||||
CHANGE, the Daylight Saving Time branches and the near-midnight refusal.
|
||||
`tests/trainer-world.test.ts` covers a MomItems_2 purchase and its call, an
|
||||
exact ¥2300 step, a step without a purchase, a doll, a full PC and the save
|
||||
migration. A browser test deposits through the keyboard and the on-screen
|
||||
buttons and checks the backup.
|
||||
Reference in new issue
Block a user