From 18b48fb878e95f0f1ff8530a53bfac079287a2d5 Mon Sep 17 00:00:00 2001 From: MathyFurret <4866817+MathyFurret@users.noreply.github.com> Date: Sun, 15 Dec 2024 12:09:35 -0600 Subject: [PATCH 1/5] Gen 4: Fix Assist/Copycat/Metronome under Gravity/Heal Block --- data/mods/gen4/moves.ts | 59 ++++++++++++++++++++++++++++++++++++++++ data/moves.ts | 6 ++-- test/TESTS.md | 2 +- test/sim/moves/assist.js | 42 ++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 test/sim/moves/assist.js diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index e38589fcf941..6e389ca65ae4 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -47,6 +47,32 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { }, }, }, + assist: { + inherit: true, + onHit(target) { + const moves = []; + for (const pokemon of target.side.pokemon) { + if (pokemon === target) continue; + for (const moveSlot of pokemon.moveSlots) { + const moveid = moveSlot.id; + const move = this.dex.moves.get(moveid); + if (move.flags['noassist'] || move.isZ || move.isMax || + (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || + (target.volatiles['healblock'] && move.flags['heal']) + ) { + continue; + } + moves.push(moveid); + } + } + let randomMove = ''; + if (moves.length) randomMove = this.sample(moves); + if (!randomMove) { + return false; + } + this.actions.useMove(randomMove, target); + }, + }, beatup: { inherit: true, basePower: 10, @@ -198,6 +224,22 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { this.add('-start', target, 'typechange', type); }, }, + copycat: { + inherit: true, + onHit(pokemon) { + let move: Move | ActiveMove | null = this.lastMove; + if (!move) return; + + if (move.isMax && move.baseMove) move = this.dex.moves.get(move.baseMove); + if (move.flags['failcopycat'] || move.isZ || move.isMax || + (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || + (pokemon.volatiles['healblock'] && move.flags['heal']) + ) { + return false; + } + this.actions.useMove(move.id, pokemon); + }, + }, cottonspore: { inherit: true, accuracy: 85, @@ -1007,6 +1049,23 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { metronome: { inherit: true, flags: {noassist: 1, failcopycat: 1, nosleeptalk: 1, failmimic: 1}, + onHit(pokemon) { + const moves = this.dex.moves.all().filter(move => ( + (![2, 4].includes(this.gen) || !pokemon.moves.includes(move.id)) && + (!move.isNonstandard || move.isNonstandard === 'Unobtainable') && + move.flags['metronome'] && + !(this.field.pseudoWeather['gravity'] && move.flags['gravity']) && + !(pokemon.volatiles['healblock'] && move.flags['heal']) + )); + let randomMove = ''; + if (moves.length) { + moves.sort((a, b) => a.num - b.num); + randomMove = this.sample(moves).id; + } + if (!randomMove) return false; + pokemon.side.lastSelectedMove = this.toID(randomMove); + this.actions.useMove(randomMove, pokemon); + }, }, mimic: { inherit: true, diff --git a/data/moves.ts b/data/moves.ts index ea281aa1e6b9..1b399f609aaa 100644 --- a/data/moves.ts +++ b/data/moves.ts @@ -12187,9 +12187,8 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { pp: 10, priority: 0, flags: {failencore: 1, nosleeptalk: 1, noassist: 1, failcopycat: 1, failmimic: 1, failinstruct: 1}, - onHit(target, source, effect) { + onHit(pokemon) { const moves = this.dex.moves.all().filter(move => ( - (![2, 4].includes(this.gen) || !source.moves.includes(move.id)) && (!move.isNonstandard || move.isNonstandard === 'Unobtainable') && move.flags['metronome'] )); @@ -12199,8 +12198,7 @@ export const Moves: import('../sim/dex-moves').MoveDataTable = { randomMove = this.sample(moves).id; } if (!randomMove) return false; - source.side.lastSelectedMove = this.toID(randomMove); - this.actions.useMove(randomMove, target); + this.actions.useMove(randomMove, pokemon); }, callsMove: true, secondary: null, diff --git a/test/TESTS.md b/test/TESTS.md index 6c2f32d6bb29..58a89e48bf92 100644 --- a/test/TESTS.md +++ b/test/TESTS.md @@ -20,7 +20,7 @@ Check the test/ directory to see if a file already exists for the effect that yo it(`test should start here`, function () { }); - } + }); To create the battle, use common.createBattle and pass in two arrays of teams. You can add additional flags as well: - gameType: 'doubles', 'triples', 'multi', 'freeforall', etc (tests default to singles) diff --git a/test/sim/moves/assist.js b/test/sim/moves/assist.js new file mode 100644 index 000000000000..42c63fb5dd8f --- /dev/null +++ b/test/sim/moves/assist.js @@ -0,0 +1,42 @@ +'use strict'; + +const assert = require('./../../assert'); +const common = require('./../../common'); + +let battle; + +describe(`[Gen 4] Assist`, function () { + afterEach(function () { + battle.destroy(); + }); + + it(`should never call moves that would fail under Gravity`, function () { + battle = common.gen(4).createBattle([[ + {species: 'furret', moves: ['assist']}, + {species: 'smeargle', moves: ['bounce', 'fly', 'highjumpkick', 'splash']}, + {species: 'smeargle', moves: ['bounce', 'fly', 'highjumpkick', 'splash']}, + {species: 'smeargle', moves: ['bounce', 'fly', 'highjumpkick', 'splash']}, + {species: 'smeargle', moves: ['doubleteam', 'fly', 'highjumpkick', 'splash']}, + {species: 'smeargle', moves: ['bounce', 'fly', 'highjumpkick', 'splash']}, + ], [ + {species: 'deoxys', moves: ['gravity']}, + ]]); + for (let i = 0; i < 5; i++) battle.makeChoices(); + assert.statStage(battle.p1.active[0], 'evasion', 5); + }); + + it(`should never call moves that would fail under Heal Block`, function () { + battle = common.gen(4).createBattle([[ + {species: 'furret', moves: ['assist']}, + {species: 'smeargle', moves: ['recover', 'rest', 'roost', 'wish']}, + {species: 'smeargle', moves: ['recover', 'rest', 'doubleteam', 'wish']}, + {species: 'smeargle', moves: ['recover', 'rest', 'roost', 'wish']}, + {species: 'smeargle', moves: ['recover', 'rest', 'roost', 'wish']}, + {species: 'smeargle', moves: ['recover', 'rest', 'roost', 'wish']}, + ], [ + {species: 'latios', moves: ['healblock']}, + ]]); + for (let i = 0; i < 5; i++) battle.makeChoices(); + assert.statStage(battle.p1.active[0], 'evasion', 5); + }); +}); From 2dc769aef878aa10d8fd0d25fb17e5cfc7a739bd Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:19:53 -0700 Subject: [PATCH 2/5] Update data/mods/gen4/moves.ts --- data/mods/gen4/moves.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index 6e389ca65ae4..1aa5884ca0bf 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -56,7 +56,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { for (const moveSlot of pokemon.moveSlots) { const moveid = moveSlot.id; const move = this.dex.moves.get(moveid); - if (move.flags['noassist'] || move.isZ || move.isMax || + if ( + move.flags['noassist'] || move.isZ || move.isMax || (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || (target.volatiles['healblock'] && move.flags['heal']) ) { From 0c52fef9f0382afb0cbdd96a35635ca0a8249b0a Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:20:21 -0700 Subject: [PATCH 3/5] Update data/mods/gen4/moves.ts --- data/mods/gen4/moves.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index 1aa5884ca0bf..e3b7ca365f30 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -232,7 +232,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { if (!move) return; if (move.isMax && move.baseMove) move = this.dex.moves.get(move.baseMove); - if (move.flags['failcopycat'] || move.isZ || move.isMax || + if ( + move.flags['failcopycat'] || move.isZ || move.isMax || (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || (pokemon.volatiles['healblock'] && move.flags['heal']) ) { From 1b3a3c8bd58e412e4bdda89b8bf94798f4b4e617 Mon Sep 17 00:00:00 2001 From: MathyFurret <4866817+MathyFurret@users.noreply.github.com> Date: Tue, 17 Dec 2024 00:14:33 -0600 Subject: [PATCH 4/5] Remove unnecessary checks --- data/mods/gen4/moves.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index e3b7ca365f30..b28133fce2a4 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -57,7 +57,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { const moveid = moveSlot.id; const move = this.dex.moves.get(moveid); if ( - move.flags['noassist'] || move.isZ || move.isMax || + move.flags['noassist'] || (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || (target.volatiles['healblock'] && move.flags['heal']) ) { @@ -231,9 +231,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { let move: Move | ActiveMove | null = this.lastMove; if (!move) return; - if (move.isMax && move.baseMove) move = this.dex.moves.get(move.baseMove); if ( - move.flags['failcopycat'] || move.isZ || move.isMax || + move.flags['failcopycat'] || (this.field.pseudoWeather['gravity'] && move.flags['gravity']) || (pokemon.volatiles['healblock'] && move.flags['heal']) ) { From f8fa4138f2eddfa9c58d2636c7fdaa253400d0c6 Mon Sep 17 00:00:00 2001 From: MathyFurret <4866817+MathyFurret@users.noreply.github.com> Date: Tue, 17 Dec 2024 00:18:11 -0600 Subject: [PATCH 5/5] prefer const --- data/mods/gen4/moves.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index b28133fce2a4..821b6ea66463 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -228,7 +228,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { copycat: { inherit: true, onHit(pokemon) { - let move: Move | ActiveMove | null = this.lastMove; + const move: Move | ActiveMove | null = this.lastMove; if (!move) return; if (