Files
Crystal/tests/battle-fixture.ts
T
Sébastien QUEROL 32d736ecae
Checks / web (push) Canceled after 0s
Port weather, copying moves, held items and obedience (#28)
Complete the weather, Substitute, Transform, called-move and forced-switch effects. Add held-item behavior, Exp. Share awards and badge-based traded Pokemon obedience, and persist trainer berry consumption.

Validated with 576 passing unit tests and 149 browser tests, native/reference builds, reference/vendor/release checks and 320 Metal Powder emulator comparisons per browser. Smart AI and special balls/battle types remain on #28.
2026-10-03 15:03:19 +02:00

50 lines
2.0 KiB
TypeScript

import { CrystalAssets } from "../src/game/rom/assets";
import { generatePartyMon } from "../src/game/party/pokemon";
import { GameWorld } from "../src/game/world/world";
export type BattleScenario = "win" | "loss" | "unsupported" | "catch" | "switch" | "potion";
/** Test-only encounters on an existing floor: production maps stay gated.
* Everything after selection runs through the ROM's real wild-battle script. */
export function battleFixtureWorld(assets: CrystalAssets, scenario: BattleScenario = "win") {
assets.grassCollisions = () => [assets.collision(assets.map("24:7"), 3, 2)];
assets.grassWildMons = (id) => id === "24:7" ? {
rates: [256, 256, 256],
slots: [0, 1, 2].map(() => Array.from({ length: 7 }, () => ({ species: 16, level: 3 }))),
} : undefined;
let seed = 1;
const world = new GameWorld(assets, () => new Date("2026-09-22T12:00:00"), () => {
seed = (seed * 1103515245 + 12345) >>> 0;
return (seed >>> 16) & 255;
});
const mon = generatePartyMon(assets.pokemon, {
species: 155, level: 5, item: 0, otId: world.playerId,
ot: "CHRIS", dvs: 0x823b, caughtData: 0,
});
mon.exp = 178; // One battle away from level 6 and Smokescreen.
if (scenario === "loss") mon.hp = 1;
if (scenario === "unsupported") {
// Psywave at level 1 loops forever in the original, so it stays refused.
mon.level = 1;
mon.moves = [149, 0, 0, 0];
mon.pp = [10, 0, 0, 0];
}
world.state.party.push(mon);
if (scenario === "switch")
world.state.party.push(generatePartyMon(assets.pokemon, {
species: 158, level: 5, item: 0, otId: world.playerId,
ot: "CHRIS", dvs: 0x823b, caughtData: 0,
}));
if (scenario === "catch") world.state.bag.balls = [{ item: 5, quantity: 10 }]; // POKé BALL
if (scenario === "potion") {
mon.hp = 3;
world.state.bag.items = [{ item: 18, quantity: 1 }]; // POTION
}
world.state.pokedex.seen.add(155);
world.state.pokedex.caught.add(155);
world.state.money = 3001;
return world;
}
export const ENCOUNTER_WALK = ["up", "right", "right", "right", "right"] as const;