Port the fishing rods and wild Magikarp

The Old, Good and Super Rods run FishFunction facing water: the map's fish
group and Fish pick no fish, no bite, or a Pokémon from FishGroups and the
time of day's TimeFishGroups. The player casts and jiggles with the
fishing frames drawn from LoadFishingGFX's tiles, shows "!" on a bite, and
the hooked Pokémon attacks as BATTLETYPE_FISH. Facing pieces now use
signed offsets, which the rod above and left of the player needs.

Wild Magikarp no longer stop a battle: LoadEnemyMon redraws their DVs
through CalcMagikarpLength and its filters, as the original does. The
length routine matches the original in the reference emulator.

Part of #27

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sébastien QUEROLandClaude Opus 5.5 committed 2026-10-03 00:49:35 +02:00
1 parent 4cb4676c7d
commit 397dcef44c
20 files changed
+681 -47

No files matched your search

+28 -1
View File
@@ -19,7 +19,8 @@ async function start(
| "pokegear"
| "mom"
| "fly"
| "headbutt" = false,
| "headbutt"
| "fishing" = false,
) {
await page.route("**/src/game/runtime.ts", async (route) => {
const response = await route.fetch(),
@@ -507,6 +508,32 @@ test("Headbutt shakes a tree and a sleeping Hoothoot falls out", async ({
await expect(screen).toHaveAttribute("data-map", "24:3");
});
test("the Old Rod hooks a Magikarp from New Bark Town's shore", async ({
page,
}) => {
await start(page, "fishing");
const text = page.locator("#dialogue-text"),
choices = page.locator("#dialogue-choice"),
pack = page.locator("#mart");
await page.keyboard.press("Enter");
await choices.getByRole("option", { name: /^PACK/ }).click();
await page.keyboard.press("ArrowRight");
await page.keyboard.press("ArrowRight");
await pack.getByRole("button", { name: "OLD ROD", exact: true }).click();
await choices.getByRole("option", { name: "USE", exact: true }).click();
// The cast, 40 frames, four bites with "!", 40 more frames.
await page.clock.runFor(5_000);
await expect(text).toHaveText(/Oh!\s+A bite!/);
await page.keyboard.press("KeyX");
await page.clock.runFor(5_000);
await expect(page.locator("#battle")).toBeVisible();
await expect(page.locator("#battle-text")).toHaveText(
/The hooked\s+MAGIKARP\s+attacked!/,
);
await expect(page.locator("#battle-foe-name")).toHaveText("MAGIKARP");
await expect(page.locator("#game-notice")).toHaveText("");
});
test("Mom keeps the player's money with the digit box", async ({ page }) => {
await start(page, "mom");
const text = page.locator("#dialogue-text"),