Port the remaining battle items, the stats screen and hBattleTurn at the menu

- Run every non-ball item effect usable in battle from the ROM's
  ItemEffects: Full Restore, revives, bitter medicine, Bitter Berry, Ethers
  and Elixers, X items, X Accuracy, Guard Spec, Dire Hit and Poké Doll.
- Read happiness changes from HappinessChanges, including the larger
  level-up gain where a Pokémon was caught.
- Model hBattleTurn at the battle menu, including the trainer AI's writes,
  and drop the status-heal refusal.
- Port the stats screen for battles and Bill's PC.
- Compare the send-out and withdraw texts, RestoreHealth, RestorePP,
  ChangeHappiness and CalcPlayerStats with the original routines.

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 11:24:55 +02:00
1 parent cfd083c16d
commit b13e09ec20
22 files changed
+1547 -171

No files matched your search

+40
View File
@@ -226,6 +226,46 @@ describe.skipIf(!existsSync(romPath))("the Pokémon Center PC", () => {
expect(world.save()).toEqual(saved);
});
it("opens the stats screen from Bill's PC for party and boxed Pokémon", () => {
const world = fixture();
const data = world.assets.pokemon;
const pidgey = world.state.party[1];
pidgey.hp = 1;
pidgey.status = 0x08;
open(world);
pick(world, "BILL's PC");
pick(world, /^DEPOSIT/);
pick(world, "PIDGEY");
const stats = () => {
const choice = world.dialogue?.choice;
if (choice?.kind !== "menu") throw new Error("Expected a menu");
world.choose(choice.items.indexOf("STATS"));
for (let tick = 0; tick < 10 && !world.statsScreen; tick++) world.tick();
const shown = world.statsScreen;
world.advanceDialogue();
until(world);
return shown;
};
// A party Pokémon shows its own HP and status.
expect(stats()).toMatchObject({ species: PIDGEY, hp: 1, status: 0x08 });
expect(world.statsScreen).toBeUndefined();
expect(menuItems(world)).toEqual(["DEPOSIT", "STATS", "RELEASE", "CANCEL"]);
pick(world, "DEPOSIT");
pick(world, "CANCEL");
pick(world, /^WITHDRAW/);
pick(world, "PIDGEY");
// CalcTempmonStats: a boxed Pokémon shows computed stats, full HP and
// no status.
const boxed = stats()!;
expect(boxed.status).toBe(0);
expect(boxed.hp).toBe(boxed.stats[0]);
expect(boxed.stats).toEqual(
calcStats(data, PIDGEY, pidgey.dvs, 4, pidgey.statExp),
);
expect(menuItems(world)).toEqual(["WITHDRAW", "STATS", "RELEASE", "CANCEL"]);
expect(world.notice, world.diagnostic).toBe("");
});
it("refuses to withdraw into a full party or deposit into a full box", () => {
const world = fixture();
const party = world.state.party;