Port weather, copying moves, held items and obedience (#28)
Checks / web (push) Canceled after 0s
Checks / web (push) Canceled after 0s
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.
This commit is contained in:
1 parent
8f5b464efc
commit
32d736ecae
13 files changed
+1509
-75
No files matched your search
@@ -51,6 +51,7 @@ type Case = {
|
||||
beatUpHit: number;
|
||||
playerIsSwitching: number;
|
||||
enemyIsSwitching: number;
|
||||
weather?: number;
|
||||
/** A battle script and the index of the command after the one run. */
|
||||
script: number[];
|
||||
scriptIndex: number;
|
||||
@@ -142,6 +143,7 @@ async function compare(page: Page, routines: string[], cases: Case[]) {
|
||||
enemyGoesFirst: at("wEnemyGoesFirst"),
|
||||
animParam: at("wBattleAnimParam"),
|
||||
battleMode: at("wBattleMode"),
|
||||
weather: at("wBattleWeather"),
|
||||
partyCount: at("wPartyCount"),
|
||||
otPartyCount: at("wOTPartyCount"),
|
||||
beatUpHit: at("wBeatUpHitAtLeastOnce"),
|
||||
@@ -257,6 +259,7 @@ async function compare(page: Page, routines: string[], cases: Case[]) {
|
||||
beatUpHit: input.beatUpHit,
|
||||
playerIsSwitching: input.playerIsSwitching,
|
||||
enemyIsSwitching: input.enemyIsSwitching,
|
||||
weather: input.weather ?? 0,
|
||||
script: [...input.script],
|
||||
scriptIndex: input.scriptIndex,
|
||||
});
|
||||
@@ -269,6 +272,7 @@ async function compare(page: Page, routines: string[], cases: Case[]) {
|
||||
write(addresses.enemyGoesFirst, input.enemyGoesFirst);
|
||||
write(addresses.animParam, input.animParam);
|
||||
write(addresses.battleMode, input.battleMode);
|
||||
write(addresses.weather, input.weather ?? 0);
|
||||
write(addresses.partyCount, input.partyCount);
|
||||
write(addresses.otPartyCount, input.otPartyCount);
|
||||
write(addresses.beatUpHit, input.beatUpHit);
|
||||
@@ -621,3 +625,24 @@ test("CheckHit matches Fly, Dig and Lock-On", async ({ page }) => {
|
||||
}
|
||||
await compare(page, ["BattleCommand_CheckHit"], cases);
|
||||
});
|
||||
|
||||
test("Stab matches weather, STAB and type effectiveness", async ({ page }) => {
|
||||
const { make, next } = generator(0x57ab);
|
||||
// Normal, Fighting, Flying, Ground, Ghost, Fire, Water, Grass, Electric, Psychic, Dark.
|
||||
const types = [0, 1, 2, 4, 8, 20, 21, 22, 23, 24, 27];
|
||||
const cases: Case[] = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const input = make({
|
||||
curDamage: [0, 1, 2, 3, 40, 997, 0x7fff, 0xaaaa, 0xffff][next(9)],
|
||||
typeModifier: next(4) ? C.EFFECTIVE : 0,
|
||||
});
|
||||
const user = input.sides[input.turn],
|
||||
target = input.sides[input.turn ^ 1];
|
||||
user.move = { ...user.move, type: types[next(types.length)], effect: next(4) ? 0 : C.EFFECT_SOLARBEAM };
|
||||
user.types = [types[next(types.length)], types[next(types.length)]];
|
||||
target.types = [types[next(types.length)], types[next(types.length)]];
|
||||
if (next(4) === 0) target.sub[0] = 1 << C.SUBSTATUS_IDENTIFIED;
|
||||
cases.push({ ...input, weather: next(4) } as Case);
|
||||
}
|
||||
await compare(page, ["BattleCommand_Stab"], cases);
|
||||
});
|
||||
Reference in new issue
Block a user