From ded5540890bb75856a3836ead4db431971315a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Mon, 5 Jan 2026 01:43:32 +0000 Subject: [PATCH 1/6] Refactor Mirror Move flags --- data/mods/gen1/moves.ts | 2 +- data/mods/gen1/scripts.ts | 7 +++++++ data/mods/gen2/moves.ts | 5 ++--- data/mods/gen2/scripts.ts | 10 ++++++++++ data/mods/gen3/moves.ts | 15 --------------- data/mods/gen3/scripts.ts | 8 ++++++++ data/mods/gen4/moves.ts | 8 +++----- data/mods/gen4/scripts.ts | 13 ++++++++++++- 8 files changed, 43 insertions(+), 25 deletions(-) diff --git a/data/mods/gen1/moves.ts b/data/mods/gen1/moves.ts index ba21a2506c..9af0722d30 100644 --- a/data/mods/gen1/moves.ts +++ b/data/mods/gen1/moves.ts @@ -485,7 +485,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { inherit: true, onHit(pokemon) { const foe = pokemon.side.foe.active[0]; - if (!foe?.lastMove || foe.lastMove.id === 'mirrormove') { + if (!foe?.lastMove || !foe.lastMove.flags['mirror']) { // only Mirror Move isn't mirrorable return false; } pokemon.side.lastSelectedMove = foe.lastMove.id; diff --git a/data/mods/gen1/scripts.ts b/data/mods/gen1/scripts.ts index f95763976e..6a1d7b89db 100644 --- a/data/mods/gen1/scripts.ts +++ b/data/mods/gen1/scripts.ts @@ -21,6 +21,13 @@ export const Scripts: ModdedBattleScriptsData = { poke.gender = 'N'; poke.eggGroups = null; } + for (const i in this.data.Moves) { + if (i === 'mirrormove') { + delete this.modData('Moves', i).flags.mirror; + } else { + this.modData('Moves', i).flags.mirror = 1; + } + } }, // BattlePokemon scripts. pokemon: { diff --git a/data/mods/gen2/moves.ts b/data/mods/gen2/moves.ts index 1aadb96470..ff7797aea2 100644 --- a/data/mods/gen2/moves.ts +++ b/data/mods/gen2/moves.ts @@ -436,13 +436,12 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { inherit: true, flags: { metronome: 1, failencore: 1, nosketch: 1 }, onHit(pokemon) { - const noMirror = ['metronome', 'mimic', 'mirrormove', 'sketch', 'sleeptalk', 'transform']; const target = pokemon.side.foe.active[0]; - const lastMove = target?.lastMove && target?.lastMove.id; + const lastMove = target?.lastMove; if (!lastMove || (!pokemon.activeTurns && !target.moveThisTurn)) { return false; } - if (noMirror.includes(lastMove) || pokemon.moves.includes(lastMove)) { + if (!lastMove.flags['mirror'] || pokemon.moves.includes(lastMove.id)) { return false; } this.actions.useMove(lastMove, pokemon); diff --git a/data/mods/gen2/scripts.ts b/data/mods/gen2/scripts.ts index d564f84d97..390588de76 100644 --- a/data/mods/gen2/scripts.ts +++ b/data/mods/gen2/scripts.ts @@ -5,6 +5,16 @@ export const Scripts: ModdedBattleScriptsData = { inherit: 'gen3', gen: 2, + init() { + const noMirror = ['metronome', 'mimic', 'mirrormove', 'sketch', 'sleeptalk', 'transform']; + for (const i in this.data.Moves) { + if (noMirror.includes(i)) { + delete this.modData('Moves', i).flags.mirror; + } else { + this.modData('Moves', i).flags.mirror = 1; + } + } + }, pokemon: { inherit: true, getStat(statName, unboosted, unmodified, fastReturn) { diff --git a/data/mods/gen3/moves.ts b/data/mods/gen3/moves.ts index 9764e11df8..76ea241009 100644 --- a/data/mods/gen3/moves.ts +++ b/data/mods/gen3/moves.ts @@ -528,21 +528,6 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { mirrormove: { inherit: true, flags: { metronome: 1, failencore: 1, nosleeptalk: 1, noassist: 1 }, - onTryHit() { }, - onHit(pokemon) { - const noMirror = [ - 'assist', 'curse', 'doomdesire', 'focuspunch', 'futuresight', 'magiccoat', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'psychup', 'roleplay', 'sketch', 'sleeptalk', 'spikes', 'spitup', 'taunt', 'teeterdance', 'transform', - ]; - const lastAttackedBy = pokemon.getLastAttackedBy(); - if (!lastAttackedBy?.source.lastMove || !lastAttackedBy.move) { - return false; - } - if (noMirror.includes(lastAttackedBy.move) || !lastAttackedBy.source.hasMove(lastAttackedBy.move)) { - return false; - } - this.actions.useMove(lastAttackedBy.move, pokemon); - }, - target: "self", }, naturepower: { inherit: true, diff --git a/data/mods/gen3/scripts.ts b/data/mods/gen3/scripts.ts index fd0d8b31a8..4cdb2907de 100644 --- a/data/mods/gen3/scripts.ts +++ b/data/mods/gen3/scripts.ts @@ -3,6 +3,9 @@ export const Scripts: ModdedBattleScriptsData = { gen: 3, init() { const specialTypes = ['Fire', 'Water', 'Grass', 'Ice', 'Electric', 'Dark', 'Psychic', 'Dragon']; + const noMirror = [ + 'assist', 'curse', 'doomdesire', 'focuspunch', 'futuresight', 'magiccoat', 'metronome', 'mimic', 'mirrormove', 'naturepower', 'psychup', 'roleplay', 'sketch', 'sleeptalk', 'spikes', 'spitup', 'taunt', 'teeterdance', 'transform', + ]; let newCategory = ''; for (const i in this.data.Moves) { if (!this.data.Moves[i]) console.log(i); @@ -11,6 +14,11 @@ export const Scripts: ModdedBattleScriptsData = { if (newCategory !== this.data.Moves[i].category) { this.modData('Moves', i).category = newCategory; } + if (noMirror.includes(i)) { + delete this.modData('Moves', i).flags.mirror; + } else { + this.modData('Moves', i).flags.mirror = 1; + } } }, pokemon: { diff --git a/data/mods/gen4/moves.ts b/data/mods/gen4/moves.ts index d6ad9cf3c5..ca42b1f3cf 100644 --- a/data/mods/gen4/moves.ts +++ b/data/mods/gen4/moves.ts @@ -1148,13 +1148,11 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { if (!lastAttackedBy?.source.lastMove || !lastAttackedBy.move) { return false; } - const noMirror = [ - 'acupressure', 'aromatherapy', 'assist', 'chatter', 'copycat', 'counter', 'curse', 'doomdesire', 'feint', 'focuspunch', 'futuresight', 'gravity', 'hail', 'haze', 'healbell', 'helpinghand', 'lightscreen', 'luckychant', 'magiccoat', 'mefirst', 'metronome', 'mimic', 'mirrorcoat', 'mirrormove', 'mist', 'mudsport', 'naturepower', 'perishsong', 'psychup', 'raindance', 'reflect', 'roleplay', 'safeguard', 'sandstorm', 'sketch', 'sleeptalk', 'snatch', 'spikes', 'spitup', 'stealthrock', 'struggle', 'sunnyday', 'tailwind', 'toxicspikes', 'transform', 'watersport', - ]; - if (noMirror.includes(lastAttackedBy.move) || !lastAttackedBy.source.hasMove(lastAttackedBy.move)) { + const move = this.dex.moves.get(lastAttackedBy.move); + if (!move.flags['mirror'] || !lastAttackedBy.source.hasMove(move.id)) { return false; } - this.actions.useMove(lastAttackedBy.move, pokemon); + this.actions.useMove(move, pokemon); }, target: "self", }, diff --git a/data/mods/gen4/scripts.ts b/data/mods/gen4/scripts.ts index 67f54d423d..21b6bceadb 100644 --- a/data/mods/gen4/scripts.ts +++ b/data/mods/gen4/scripts.ts @@ -1,7 +1,18 @@ export const Scripts: ModdedBattleScriptsData = { inherit: 'gen5', gen: 4, - + init() { + const noMirror = [ + 'acupressure', 'aromatherapy', 'assist', 'chatter', 'copycat', 'counter', 'curse', 'doomdesire', 'feint', 'focuspunch', 'futuresight', 'gravity', 'hail', 'haze', 'healbell', 'helpinghand', 'lightscreen', 'luckychant', 'magiccoat', 'mefirst', 'metronome', 'mimic', 'mirrorcoat', 'mirrormove', 'mist', 'mudsport', 'naturepower', 'perishsong', 'psychup', 'raindance', 'reflect', 'roleplay', 'safeguard', 'sandstorm', 'sketch', 'sleeptalk', 'snatch', 'spikes', 'spitup', 'stealthrock', 'struggle', 'sunnyday', 'tailwind', 'toxicspikes', 'transform', 'watersport', + ]; + for (const i in this.data.Moves) { + if (noMirror.includes(i)) { + delete this.modData('Moves', i).flags.mirror; + } else { + this.modData('Moves', i).flags.mirror = 1; + } + } + }, actions: { inherit: true, runSwitch(pokemon) { From 437c2bbfa3bfc6e1dd2f50f7d25a1829fbbf3c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Mon, 5 Jan 2026 01:58:28 +0000 Subject: [PATCH 2/6] Fix lint --- data/mods/gen1/moves.ts | 5 ++--- data/mods/gen2/moves.ts | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/data/mods/gen1/moves.ts b/data/mods/gen1/moves.ts index 9af0722d30..0af022eaa5 100644 --- a/data/mods/gen1/moves.ts +++ b/data/mods/gen1/moves.ts @@ -485,9 +485,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { inherit: true, onHit(pokemon) { const foe = pokemon.side.foe.active[0]; - if (!foe?.lastMove || !foe.lastMove.flags['mirror']) { // only Mirror Move isn't mirrorable - return false; - } + // only Mirror Move isn't mirrorable + if (!foe?.lastMove?.flags['mirror']) return false; pokemon.side.lastSelectedMove = foe.lastMove.id; this.actions.useMove(foe.lastMove.id, pokemon); }, diff --git a/data/mods/gen2/moves.ts b/data/mods/gen2/moves.ts index ff7797aea2..b599458349 100644 --- a/data/mods/gen2/moves.ts +++ b/data/mods/gen2/moves.ts @@ -438,10 +438,10 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { onHit(pokemon) { const target = pokemon.side.foe.active[0]; const lastMove = target?.lastMove; - if (!lastMove || (!pokemon.activeTurns && !target.moveThisTurn)) { + if (!pokemon.activeTurns && !target.moveThisTurn) { return false; } - if (!lastMove.flags['mirror'] || pokemon.moves.includes(lastMove.id)) { + if (!lastMove?.flags['mirror'] || pokemon.moves.includes(lastMove.id)) { return false; } this.actions.useMove(lastMove, pokemon); From 7cf0d7135f4fa7f0aa56a597fc731b20985c9f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Mon, 5 Jan 2026 04:32:35 +0000 Subject: [PATCH 3/6] Simplify condition --- data/mods/gen2/moves.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/data/mods/gen2/moves.ts b/data/mods/gen2/moves.ts index b599458349..e9fd75a407 100644 --- a/data/mods/gen2/moves.ts +++ b/data/mods/gen2/moves.ts @@ -438,10 +438,8 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { onHit(pokemon) { const target = pokemon.side.foe.active[0]; const lastMove = target?.lastMove; - if (!pokemon.activeTurns && !target.moveThisTurn) { - return false; - } - if (!lastMove?.flags['mirror'] || pokemon.moves.includes(lastMove.id)) { + if (!lastMove?.flags['mirror'] || pokemon.moves.includes(lastMove.id) || + (!pokemon.activeTurns && !target.moveThisTurn)) { return false; } this.actions.useMove(lastMove, pokemon); From 9acdaad6d849819a14691717b344715b5fc7f3f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Tue, 6 Jan 2026 19:13:32 +0000 Subject: [PATCH 4/6] Also abilities --- sim/dex-species.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sim/dex-species.ts b/sim/dex-species.ts index 14f3c5f33a..4a6db05ec1 100644 --- a/sim/dex-species.ts +++ b/sim/dex-species.ts @@ -594,11 +594,12 @@ export class DexSpecies { species.canHatch = species.canHatch || (!['Ditto', 'Undiscovered'].includes(species.eggGroups[0]) && !species.prevo && species.name !== 'Manaphy'); if (this.dex.gen === 1) species.bst -= species.baseStats.spd; - if (this.dex.gen < 5) { + if (this.dex.gen <= 2) species.abilities = { 0: 'No Ability' }; + else if (this.dex.gen < 5) { species.abilities = this.dex.deepClone(species.abilities); delete species.abilities['H']; + if (this.dex.gen === 3 && this.dex.abilities.get(species.abilities['1']).gen === 4) delete species.abilities['1']; } - if (this.dex.gen === 3 && this.dex.abilities.get(species.abilities['1']).gen === 4) delete species.abilities['1']; if (this.dex.parentMod) { // if this species is exactly identical to parentMod's species, reuse parentMod's copy From 4dd2d71d1bec9f923dfc39f121df5711cbad6789 Mon Sep 17 00:00:00 2001 From: andrebastosdias Date: Sat, 21 Mar 2026 17:38:22 +0000 Subject: [PATCH 5/6] Don't modify object inplace --- data/mods/gen1/scripts.ts | 7 +++++-- data/mods/gen2/scripts.ts | 7 +++++-- data/mods/gen3/scripts.ts | 15 +++++++++------ data/mods/gen4/scripts.ts | 7 +++++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/data/mods/gen1/scripts.ts b/data/mods/gen1/scripts.ts index 45d19f0f94..64d73f329d 100644 --- a/data/mods/gen1/scripts.ts +++ b/data/mods/gen1/scripts.ts @@ -22,10 +22,13 @@ export const Scripts: ModdedBattleScriptsData = { poke.eggGroups = null; } for (const i in this.data.Moves) { + const move = this.data.Moves[i]; if (i === 'mirrormove') { - delete this.modData('Moves', i).flags.mirror; + const flags = { ...move.flags }; + delete flags['mirror']; + this.modData('Moves', i).flags = flags; } else { - this.modData('Moves', i).flags.mirror = 1; + this.modData('Moves', i).flags = { mirror: 1, ...move.flags }; } } }, diff --git a/data/mods/gen2/scripts.ts b/data/mods/gen2/scripts.ts index 390588de76..b6a4702f6a 100644 --- a/data/mods/gen2/scripts.ts +++ b/data/mods/gen2/scripts.ts @@ -8,10 +8,13 @@ export const Scripts: ModdedBattleScriptsData = { init() { const noMirror = ['metronome', 'mimic', 'mirrormove', 'sketch', 'sleeptalk', 'transform']; for (const i in this.data.Moves) { + const move = this.data.Moves[i]; if (noMirror.includes(i)) { - delete this.modData('Moves', i).flags.mirror; + const flags = { ...move.flags }; + delete flags['mirror']; + this.modData('Moves', i).flags = flags; } else { - this.modData('Moves', i).flags.mirror = 1; + this.modData('Moves', i).flags = { mirror: 1, ...move.flags }; } } }, diff --git a/data/mods/gen3/scripts.ts b/data/mods/gen3/scripts.ts index 4cdb2907de..257218af6c 100644 --- a/data/mods/gen3/scripts.ts +++ b/data/mods/gen3/scripts.ts @@ -8,16 +8,19 @@ export const Scripts: ModdedBattleScriptsData = { ]; let newCategory = ''; for (const i in this.data.Moves) { - if (!this.data.Moves[i]) console.log(i); - if (this.data.Moves[i].category === 'Status') continue; - newCategory = specialTypes.includes(this.data.Moves[i].type) ? 'Special' : 'Physical'; - if (newCategory !== this.data.Moves[i].category) { + const move = this.data.Moves[i]; + if (!move) console.log(i); + if (move.category === 'Status') continue; + newCategory = specialTypes.includes(move.type) ? 'Special' : 'Physical'; + if (newCategory !== move.category) { this.modData('Moves', i).category = newCategory; } if (noMirror.includes(i)) { - delete this.modData('Moves', i).flags.mirror; + const flags = { ...move.flags }; + delete flags['mirror']; + this.modData('Moves', i).flags = flags; } else { - this.modData('Moves', i).flags.mirror = 1; + this.modData('Moves', i).flags = { mirror: 1, ...move.flags }; } } }, diff --git a/data/mods/gen4/scripts.ts b/data/mods/gen4/scripts.ts index 406f46b634..83be9d76e7 100644 --- a/data/mods/gen4/scripts.ts +++ b/data/mods/gen4/scripts.ts @@ -6,10 +6,13 @@ export const Scripts: ModdedBattleScriptsData = { 'acupressure', 'aromatherapy', 'assist', 'chatter', 'copycat', 'counter', 'curse', 'doomdesire', 'feint', 'focuspunch', 'futuresight', 'gravity', 'hail', 'haze', 'healbell', 'helpinghand', 'lightscreen', 'luckychant', 'magiccoat', 'mefirst', 'metronome', 'mimic', 'mirrorcoat', 'mirrormove', 'mist', 'mudsport', 'naturepower', 'perishsong', 'psychup', 'raindance', 'reflect', 'roleplay', 'safeguard', 'sandstorm', 'sketch', 'sleeptalk', 'snatch', 'spikes', 'spitup', 'stealthrock', 'struggle', 'sunnyday', 'tailwind', 'toxicspikes', 'transform', 'watersport', ]; for (const i in this.data.Moves) { + const move = this.data.Moves[i]; if (noMirror.includes(i)) { - delete this.modData('Moves', i).flags.mirror; + const flags = { ...move.flags }; + delete flags['mirror']; + this.modData('Moves', i).flags = flags; } else { - this.modData('Moves', i).flags.mirror = 1; + this.modData('Moves', i).flags = { mirror: 1, ...move.flags }; } } }, From 50b123eed3dd3e702d1c5f6e53f6b2325547d992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:56:26 +0100 Subject: [PATCH 6/6] Fix merge --- data/mods/gen4/scripts.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/data/mods/gen4/scripts.ts b/data/mods/gen4/scripts.ts index 97a2669135..5da2aaf093 100644 --- a/data/mods/gen4/scripts.ts +++ b/data/mods/gen4/scripts.ts @@ -15,6 +15,7 @@ export const Scripts: ModdedBattleScriptsData = { this.modData('Moves', i).flags = { mirror: 1, ...move.flags }; } } + }, pokemon: { inherit: true, getActionSpeed() {