Port field moves from the menu, SEL with Select, and moving Pokémon in Bill's PC
Checks / web (push) Canceled after 0s
Checks / web (push) Canceled after 0s
Field moves chosen in the party menu run their original checks and the ROM's from-menu scripts (Cut, Surf, Strength, Flash, Whirlpool, Waterfall, Sweet Scent), and Softboiled and Milk Drink share HP. SEL registers a key item that Select then uses, replacing the Key Items shortcut, and Bill's PC moves Pokémon between the party and every box. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
45275ba83b
commit
3456aa4e11
25 files changed
+1129
-186
No files matched your search
@@ -33,6 +33,7 @@ const BICYCLE = 7,
|
||||
LEFTOVERS = 0x92,
|
||||
FLOWER_MAIL = 0x9e,
|
||||
BERRY = 0xad;
|
||||
const SOFTBOILED = 0x87;
|
||||
const CUT = 0x0f,
|
||||
GUST = 0x10,
|
||||
SAND_ATTACK = 0x1c,
|
||||
@@ -197,8 +198,11 @@ describe.skipIf(!existsSync(romPath))("the start menu", () => {
|
||||
pick(world, "CANCEL");
|
||||
pick(world, "PIDGEY");
|
||||
expect(menuItems(world)).toEqual(["CUT", "STATS", "SWITCH", "MOVE", "ITEM", "CANCEL"]);
|
||||
pick(world, "CUT");
|
||||
expect(world.notice).toBe("Using CUT from the menu is not ported yet.");
|
||||
// CutFunction's CheckBadge, then the party menu again.
|
||||
expect(pick(world, "CUT")).toEqual([
|
||||
"Sorry! A new BADGE is required.",
|
||||
"Choose a POKéMON.",
|
||||
]);
|
||||
// STATS shows the stats screen, and B returns to the party.
|
||||
pick(world, "PIDGEY");
|
||||
world.choose(menuItems(world).indexOf("STATS"));
|
||||
@@ -209,6 +213,56 @@ describe.skipIf(!existsSync(romPath))("the start menu", () => {
|
||||
close(world);
|
||||
});
|
||||
|
||||
it("shares HP with Softboiled, which needs more than a fifth of it", () => {
|
||||
const world = fixture();
|
||||
const data = world.assets.pokemon;
|
||||
const chansey = generatePartyMon(data, {
|
||||
species: 113,
|
||||
level: 20,
|
||||
item: 0,
|
||||
otId: world.playerId,
|
||||
ot: "CHRIS",
|
||||
dvs: 0x9abc,
|
||||
caughtData: 0,
|
||||
});
|
||||
chansey.moves = [SOFTBOILED, 0, 0, 0];
|
||||
world.state.party.push(chansey);
|
||||
world.state.party[0].hp = 3;
|
||||
const fifth = Math.floor(chansey.stats[0] / 5);
|
||||
open(world);
|
||||
pick(world, "POKéMON");
|
||||
pick(world, "CHANSEY");
|
||||
expect(pick(world, "SOFTBOILED")).toEqual(["Use on which POKéMON?"]);
|
||||
// Not on itself, and not on a Pokémon at full HP.
|
||||
expect(pick(world, "CHANSEY")).toEqual([
|
||||
"That can't be used on this POKéMON.",
|
||||
"Use on which POKéMON?",
|
||||
]);
|
||||
expect(pick(world, "PIDGEY")[0]).toBe("That can't be used on this POKéMON.");
|
||||
expect(pick(world, "CYNDAQUIL")).toEqual([
|
||||
`CYNDAQUIL recovered ${Math.min(fifth, world.liveState.party[0].stats[0] - 3)}HP!`,
|
||||
"Choose a POKéMON.",
|
||||
]);
|
||||
// The cursor returns to the user.
|
||||
const party = world.dialogue?.choice;
|
||||
expect(party?.kind === "menu" && party.selected).toBe(2);
|
||||
close(world);
|
||||
expect(world.state.party[2].hp).toBe(chansey.stats[0] - fifth);
|
||||
expect(world.state.party[0].hp).toBe(
|
||||
Math.min(world.state.party[0].stats[0], 3 + fifth),
|
||||
);
|
||||
|
||||
world.state.party[2].hp = fifth;
|
||||
open(world);
|
||||
pick(world, "POKéMON");
|
||||
pick(world, "CHANSEY");
|
||||
expect(pick(world, "SOFTBOILED")).toEqual([
|
||||
"Not enough HP!",
|
||||
"Choose a POKéMON.",
|
||||
]);
|
||||
close(world);
|
||||
});
|
||||
|
||||
it("switches two Pokémon, and B cancels the move", () => {
|
||||
const world = fixture();
|
||||
open(world);
|
||||
@@ -525,6 +579,49 @@ describe.skipIf(!existsSync(romPath))("the start menu", () => {
|
||||
expect(indoors.state.playerState).toBe(0);
|
||||
});
|
||||
|
||||
it("registers the Bicycle with SEL, and Select rides it without a message", () => {
|
||||
const world = fixture();
|
||||
// Nothing registered yet.
|
||||
expect(world.useSelect()).toBe(true);
|
||||
expect(until(world)).toEqual([
|
||||
"An item in your PACK may be",
|
||||
"registered for use on SELECT Button.",
|
||||
]);
|
||||
close(world);
|
||||
open(world);
|
||||
pick(world, "PACK");
|
||||
pickItem(world, BICYCLE);
|
||||
expect(pick(world, "SEL")).toEqual(["Registered the BICYCLE."]);
|
||||
close(world);
|
||||
expect(world.state.registeredItem).toEqual({ which: 0x81, item: BICYCLE });
|
||||
// The registration is saved.
|
||||
world.restore(world.save());
|
||||
expect(world.state.registeredItem).toEqual({ which: 0x81, item: BICYCLE });
|
||||
expect(world.useSelect()).toBe(true);
|
||||
expect(settle(world)).toEqual([]);
|
||||
expect(world.diagnostic).toBe("");
|
||||
expect(world.state.playerState).toBe(1);
|
||||
expect(world.useSelect()).toBe(true);
|
||||
expect(settle(world)).toEqual([]);
|
||||
expect(world.state.playerState).toBe(0);
|
||||
|
||||
const indoors = fixture(PLAYERS_HOUSE, 7, 4);
|
||||
indoors.state.registeredItem = { which: 0x81, item: BICYCLE };
|
||||
indoors.useSelect();
|
||||
expect(until(indoors)).toEqual(["OAK: CHRIS! This isn't the time to use that!"]);
|
||||
close(indoors);
|
||||
expect(indoors.state.playerState).toBe(0);
|
||||
});
|
||||
|
||||
it("forgets a registered item that left its slot", () => {
|
||||
const world = fixture();
|
||||
world.state.registeredItem = { which: 0x02, item: POTION };
|
||||
world.useSelect();
|
||||
expect(until(world)[0]).toBe("An item in your PACK may be");
|
||||
close(world);
|
||||
expect(world.state.registeredItem).toEqual({ which: 0, item: 0 });
|
||||
});
|
||||
|
||||
it("offers no USE without a field menu, and a notice for unported effects", () => {
|
||||
const world = fixture();
|
||||
world.state.bag.items.push(
|
||||
|
||||
Reference in new issue
Block a user